From f3eabc8dde1ae207c554653ee74a65acdf66c088 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Mon, 17 Jul 2023 18:46:40 +0200 Subject: [PATCH 01/80] wip: Add initial trait --- polimec-skeleton/Cargo.lock | 1 + polimec-skeleton/pallets/funding/Cargo.toml | 3 ++- .../pallets/funding/src/functions.rs | 7 +++++ polimec-skeleton/pallets/funding/src/lib.rs | 4 ++- polimec-skeleton/pallets/funding/src/mock.rs | 26 ++++++++++++++++++- 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/polimec-skeleton/Cargo.lock b/polimec-skeleton/Cargo.lock index c4a10060a..2ef33bac9 100644 --- a/polimec-skeleton/Cargo.lock +++ b/polimec-skeleton/Cargo.lock @@ -5904,6 +5904,7 @@ dependencies = [ "pallet-balances", "pallet-credentials", "pallet-insecure-randomness-collective-flip", + "pallet-vesting", "parity-scale-codec", "polimec-traits", "scale-info", diff --git a/polimec-skeleton/pallets/funding/Cargo.toml b/polimec-skeleton/pallets/funding/Cargo.toml index eeb314891..a349de1cb 100644 --- a/polimec-skeleton/pallets/funding/Cargo.toml +++ b/polimec-skeleton/pallets/funding/Cargo.toml @@ -35,7 +35,7 @@ sp-io = { git = "https://github.com/paritytech/substrate", default-features = fa pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } pallet-assets = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } - +pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } pallet-credentials = { path = "../credentials", default-features = false } [features] @@ -53,6 +53,7 @@ std = [ "pallet-balances/std", "pallet-credentials/std", "polimec-traits/std", + "pallet-vesting/std", "frame-benchmarking?/std", ] runtime-benchmarks = [ diff --git a/polimec-skeleton/pallets/funding/src/functions.rs b/polimec-skeleton/pallets/funding/src/functions.rs index 91cc07a1a..f5c317c25 100644 --- a/polimec-skeleton/pallets/funding/src/functions.rs +++ b/polimec-skeleton/pallets/funding/src/functions.rs @@ -2216,4 +2216,11 @@ impl Pallet { })) } } + + pub fn set_vesting_for( + who: T::AccountId, locked: BalanceOf, per_block: BalanceOf, starting_block: T::BlockNumber, + ) -> Result<(), DispatchError> { + let target = who; + T::Vesting::add_vesting_schedule(&target, locked, per_block, starting_block) + } } diff --git a/polimec-skeleton/pallets/funding/src/lib.rs b/polimec-skeleton/pallets/funding/src/lib.rs index eefeafb71..b952deaa9 100644 --- a/polimec-skeleton/pallets/funding/src/lib.rs +++ b/polimec-skeleton/pallets/funding/src/lib.rs @@ -205,7 +205,7 @@ use frame_support::{ pallet_prelude::ValueQuery, traits::{ tokens::{fungible, fungibles, Balance}, - Get, Randomness, + Get, Randomness, VestingSchedule, }, BoundedVec, PalletId, Parameter, }; @@ -315,6 +315,8 @@ pub mod pallet { /// Something that provides the members of Polimec type HandleMembers: PolimecMembers>; + type Vesting: VestingSchedule>; + /// The maximum length of data stored on-chain. #[pallet::constant] type StringLimit: Get; diff --git a/polimec-skeleton/pallets/funding/src/mock.rs b/polimec-skeleton/pallets/funding/src/mock.rs index f6f85516f..3863ef200 100644 --- a/polimec-skeleton/pallets/funding/src/mock.rs +++ b/polimec-skeleton/pallets/funding/src/mock.rs @@ -33,7 +33,7 @@ use sp_arithmetic::Percent; use sp_core::H256; use sp_runtime::{ testing::Header, - traits::{BlakeTwo256, IdentityLookup}, + traits::{BlakeTwo256, IdentityLookup, ConvertInto}, BuildStorage, }; use system::EnsureSigned; @@ -65,6 +65,7 @@ frame_support::construct_runtime!( Balances: pallet_balances, FundingModule: pallet_funding, Credentials: pallet_credentials, + Vesting: pallet_vesting, LocalAssets: pallet_assets::::{Pallet, Call, Storage, Event}, StatemintAssets: pallet_assets::::{Pallet, Call, Storage, Event, Config}, } @@ -201,6 +202,28 @@ impl pallet_credentials::Config for TestRuntime { type MembershipChanged = (); } +use frame_support::traits::WithdrawReasons; + + +parameter_types! { + pub const MinVestedTransfer: Balance = 10 * PLMC; + pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons = + WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); +} + +impl pallet_vesting::Config for TestRuntime { + type BlockNumberToBalance = ConvertInto; + type Currency = Balances; + type MinVestedTransfer = MinVestedTransfer; + type RuntimeEvent = RuntimeEvent; + type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; + type WeightInfo = (); + + // `VestingInfo` encode length is 36bytes. 28 schedules gets encoded as 1009 bytes, which is the + // highest number of schedules that encodes less than 2^10. + const MAX_VESTING_SCHEDULES: u32 = 28; +} + pub const HOURS: BlockNumber = 300u64; // REMARK: In the production configuration we use DAYS instead of HOURS. @@ -250,6 +273,7 @@ impl pallet_funding::Config for TestRuntime { type PalletId = FundingPalletId; type MaxProjectsToUpdatePerBlock = ConstU32<100>; type MaxEvaluationsPerUser = ConstU32<4>; + type Vesting = Vesting; // Low value to simplify the tests type MaxBidsPerUser = ConstU32<4>; type MaxContributionsPerUser = ConstU32<4>; From 69a52f2e4685fa7c5111a9cd7f26dee2b87b802f Mon Sep 17 00:00:00 2001 From: lrazovic <4128940+lrazovic@users.noreply.github.com> Date: Mon, 17 Jul 2023 23:52:01 +0200 Subject: [PATCH 02/80] feat: start to draft the ReleaseSchedule trait --- .../pallets/funding/src/functions.rs | 12 +++--- .../pallets/funding/src/traits.rs | 42 +++++++++++++++++++ 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/polimec-skeleton/pallets/funding/src/functions.rs b/polimec-skeleton/pallets/funding/src/functions.rs index f5c317c25..d63653eed 100644 --- a/polimec-skeleton/pallets/funding/src/functions.rs +++ b/polimec-skeleton/pallets/funding/src/functions.rs @@ -2217,10 +2217,10 @@ impl Pallet { } } - pub fn set_vesting_for( - who: T::AccountId, locked: BalanceOf, per_block: BalanceOf, starting_block: T::BlockNumber, - ) -> Result<(), DispatchError> { - let target = who; - T::Vesting::add_vesting_schedule(&target, locked, per_block, starting_block) - } + // pub fn set_vesting_for( + // who: T::AccountId, locked: BalanceOf, per_block: BalanceOf, starting_block: T::BlockNumber, + // ) -> Result<(), DispatchError> { + // let target = who; + // T::Vesting::add_vesting_schedule(&target, locked, per_block, starting_block) + // } } diff --git a/polimec-skeleton/pallets/funding/src/traits.rs b/polimec-skeleton/pallets/funding/src/traits.rs index 51a845b3b..9f2d81fde 100644 --- a/polimec-skeleton/pallets/funding/src/traits.rs +++ b/polimec-skeleton/pallets/funding/src/traits.rs @@ -1,4 +1,6 @@ use crate::{BalanceOf, Config}; +use frame_support::pallet_prelude::DispatchResult; +use frame_support::traits::tokens::fungible; use frame_support::weights::Weight; use sp_arithmetic::FixedPointNumber; use sp_runtime::DispatchError; @@ -19,3 +21,43 @@ pub trait DoRemainingOperation { fn do_one_operation(&mut self, project_id: T::ProjectIdentifier) -> Result; } + +/// A vesting schedule over a currency. This allows a particular currency to have vesting limits +/// applied to it. +pub trait ReleaseSchedule { + /// The quantity used to denote time; usually just a `BlockNumber`. + type Moment; + + /// The currency that this schedule applies to. + type Currency: fungible::InspectHold + + fungible::MutateHold + + fungible::BalancedHold; + + /// Get the amount that is currently being vested and cannot be transferred out of this account. + /// Returns `None` if the account has no vesting schedule. + fn vesting_balance(who: &AccountId) -> Option<>::Balance>; + + /// Adds a release schedule to a given account. + /// + /// If the account has `MaxVestingSchedules`, an Error is returned and nothing + /// is updated. + /// + /// Is a no-op if the amount to be vested is zero. + /// + /// NOTE: This doesn't alter the free balance of the account. + fn set_release_schedule( + who: &AccountId, locked: >::Balance, + per_block: >::Balance, starting_block: Self::Moment, + ) -> DispatchResult; + + // /// Checks if `add_vesting_schedule` would work against `who`. + // fn can_add_vesting_schedule( + // who: &AccountId, locked: >::Balance, + // per_block: >::Balance, starting_block: Self::Moment, + // ) -> DispatchResult; + + // /// Remove a vesting schedule for a given account. + // /// + // /// NOTE: This doesn't alter the free balance of the account. + // fn remove_vesting_schedule(who: &AccountId, schedule_index: u32) -> DispatchResult; +} From f3fc15e71d0d9a11ce8e0bc24141923144665ed2 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Tue, 18 Jul 2023 15:48:34 +0200 Subject: [PATCH 03/80] wip: start linear-release pallet --- polimec-skeleton/Cargo.lock | 16 + .../pallets/funding/src/traits.rs | 42 - .../pallets/linear-release/Cargo.toml | 41 + .../pallets/linear-release/README.md | 11 + .../pallets/linear-release/src/impls.rs | 327 ++++++ .../pallets/linear-release/src/lib.rs | 378 ++++++ .../pallets/linear-release/src/mock.rs | 135 +++ .../pallets/linear-release/src/tests.rs | 1014 +++++++++++++++++ .../pallets/linear-release/src/traits.rs | 64 ++ .../pallets/linear-release/src/types.rs | 93 ++ polimec-skeleton/rustfmt.toml | 23 +- 11 files changed, 2096 insertions(+), 48 deletions(-) create mode 100644 polimec-skeleton/pallets/linear-release/Cargo.toml create mode 100644 polimec-skeleton/pallets/linear-release/README.md create mode 100644 polimec-skeleton/pallets/linear-release/src/impls.rs create mode 100644 polimec-skeleton/pallets/linear-release/src/lib.rs create mode 100644 polimec-skeleton/pallets/linear-release/src/mock.rs create mode 100644 polimec-skeleton/pallets/linear-release/src/tests.rs create mode 100644 polimec-skeleton/pallets/linear-release/src/traits.rs create mode 100644 polimec-skeleton/pallets/linear-release/src/types.rs diff --git a/polimec-skeleton/Cargo.lock b/polimec-skeleton/Cargo.lock index 2ef33bac9..e57d2bf32 100644 --- a/polimec-skeleton/Cargo.lock +++ b/polimec-skeleton/Cargo.lock @@ -6005,6 +6005,22 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-linear-release" +version = "4.0.0-dev" +dependencies = [ + "frame-support", + "frame-system", + "log", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-membership" version = "4.0.0-dev" diff --git a/polimec-skeleton/pallets/funding/src/traits.rs b/polimec-skeleton/pallets/funding/src/traits.rs index 9f2d81fde..51a845b3b 100644 --- a/polimec-skeleton/pallets/funding/src/traits.rs +++ b/polimec-skeleton/pallets/funding/src/traits.rs @@ -1,6 +1,4 @@ use crate::{BalanceOf, Config}; -use frame_support::pallet_prelude::DispatchResult; -use frame_support::traits::tokens::fungible; use frame_support::weights::Weight; use sp_arithmetic::FixedPointNumber; use sp_runtime::DispatchError; @@ -21,43 +19,3 @@ pub trait DoRemainingOperation { fn do_one_operation(&mut self, project_id: T::ProjectIdentifier) -> Result; } - -/// A vesting schedule over a currency. This allows a particular currency to have vesting limits -/// applied to it. -pub trait ReleaseSchedule { - /// The quantity used to denote time; usually just a `BlockNumber`. - type Moment; - - /// The currency that this schedule applies to. - type Currency: fungible::InspectHold - + fungible::MutateHold - + fungible::BalancedHold; - - /// Get the amount that is currently being vested and cannot be transferred out of this account. - /// Returns `None` if the account has no vesting schedule. - fn vesting_balance(who: &AccountId) -> Option<>::Balance>; - - /// Adds a release schedule to a given account. - /// - /// If the account has `MaxVestingSchedules`, an Error is returned and nothing - /// is updated. - /// - /// Is a no-op if the amount to be vested is zero. - /// - /// NOTE: This doesn't alter the free balance of the account. - fn set_release_schedule( - who: &AccountId, locked: >::Balance, - per_block: >::Balance, starting_block: Self::Moment, - ) -> DispatchResult; - - // /// Checks if `add_vesting_schedule` would work against `who`. - // fn can_add_vesting_schedule( - // who: &AccountId, locked: >::Balance, - // per_block: >::Balance, starting_block: Self::Moment, - // ) -> DispatchResult; - - // /// Remove a vesting schedule for a given account. - // /// - // /// NOTE: This doesn't alter the free balance of the account. - // fn remove_vesting_schedule(who: &AccountId, schedule_index: u32) -> DispatchResult; -} diff --git a/polimec-skeleton/pallets/linear-release/Cargo.toml b/polimec-skeleton/pallets/linear-release/Cargo.toml new file mode 100644 index 000000000..4dae5bf16 --- /dev/null +++ b/polimec-skeleton/pallets/linear-release/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "pallet-linear-release" +version = "4.0.0-dev" +authors = ["Parity Technologies "] +edition = "2021" +license = "MIT-0" +homepage = "https://substrate.io" +repository = "https://github.com/paritytech/substrate/" +description = "FRAME example pallet" +readme = "README.md" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false } +log = { version = "0.4.17", default-features = false } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } + +[dev-dependencies] +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-support/std", + "frame-system/std", + "log/std", + "scale-info/std", + "sp-runtime/std", + "sp-std/std", + "pallet-balances/std" +] +try-runtime = ["frame-support/try-runtime"] diff --git a/polimec-skeleton/pallets/linear-release/README.md b/polimec-skeleton/pallets/linear-release/README.md new file mode 100644 index 000000000..4c9ee8862 --- /dev/null +++ b/polimec-skeleton/pallets/linear-release/README.md @@ -0,0 +1,11 @@ + +# Dev Mode Example Pallet + +A simple example of a FRAME pallet demonstrating +the ease of requirements for a pallet in dev mode. + +Run `cargo doc --package pallet-dev-mode --open` to view this pallet's documentation. + +**Dev mode is not meant to be used in production.** + +License: MIT-0 diff --git a/polimec-skeleton/pallets/linear-release/src/impls.rs b/polimec-skeleton/pallets/linear-release/src/impls.rs new file mode 100644 index 000000000..cf7819a41 --- /dev/null +++ b/polimec-skeleton/pallets/linear-release/src/impls.rs @@ -0,0 +1,327 @@ +use super::*; + +impl Pallet { + // Create a new `VestingInfo`, based off of two other `VestingInfo`s. + // NOTE: We assume both schedules have had funds unlocked up through the current block. + pub fn merge_vesting_info( + now: BlockNumberFor, + schedule1: VestingInfo, BlockNumberFor>, + schedule2: VestingInfo, BlockNumberFor>, + ) -> Option, BlockNumberFor>> { + let schedule1_ending_block = schedule1.ending_block_as_balance::(); + let schedule2_ending_block = schedule2.ending_block_as_balance::(); + let now_as_balance = T::BlockNumberToBalance::convert(now); + + // Check if one or both schedules have ended. + match (schedule1_ending_block <= now_as_balance, schedule2_ending_block <= now_as_balance) { + // If both schedules have ended, we don't merge and exit early. + (true, true) => return None, + // If one schedule has ended, we treat the one that has not ended as the new + // merged schedule. + (true, false) => return Some(schedule2), + (false, true) => return Some(schedule1), + // If neither schedule has ended don't exit early. + _ => {}, + } + + let locked = schedule1 + .locked_at::(now) + .saturating_add(schedule2.locked_at::(now)); + // This shouldn't happen because we know at least one ending block is greater than now, + // thus at least a schedule a some locked balance. + debug_assert!(!locked.is_zero(), "merge_vesting_info validation checks failed to catch a locked of 0"); + + let ending_block = schedule1_ending_block.max(schedule2_ending_block); + let starting_block = now.max(schedule1.starting_block()).max(schedule2.starting_block()); + + let per_block = { + let duration = + ending_block.saturating_sub(T::BlockNumberToBalance::convert(starting_block)).max(One::one()); + (locked / duration).max(One::one()) + }; + + let schedule = VestingInfo::new(locked, per_block, starting_block); + debug_assert!(schedule.is_valid(), "merge_vesting_info schedule validation check failed"); + + Some(schedule) + } + + // Execute a vested transfer from `source` to `target` with the given `schedule`. + pub fn do_vested_transfer( + source: AccountIdOf, + target: AccountIdOf, + schedule: VestingInfo, BlockNumberFor>, + reason: &ReasonOf, + ) -> DispatchResult { + // Validate user inputs. + ensure!(schedule.locked() >= T::MinVestedTransfer::get(), Error::::AmountLow); + if !schedule.is_valid() { + return Err(Error::::InvalidScheduleParams.into()); + }; + + // Check we can add to this account prior to any storage writes. + Self::can_add_release_schedule(&target, schedule.locked(), schedule.per_block(), schedule.starting_block())?; + + T::Currency::transfer( + &source, + &target, + schedule.locked(), + // TODO: Set a proper Preservation + frame_support::traits::tokens::Preservation::Expendable, + )?; + + // We can't let this fail because the currency transfer has already happened. + let res = Self::add_release_schedule( + &target, + schedule.locked(), + schedule.per_block(), + schedule.starting_block(), + reason, + ); + debug_assert!(res.is_ok(), "Failed to add a schedule when we had to succeed."); + + Ok(()) + } + + /// Iterate through the schedules to track the current locked amount and + /// filter out completed and specified schedules. + /// + /// Returns a tuple that consists of: + /// - Vec of vesting schedules, where completed schedules and those specified + /// by filter are removed. (Note the vec is not checked for respecting + /// bounded length.) + /// - The amount locked at the current block number based on the given schedules. + /// + /// NOTE: the amount locked does not include any schedules that are filtered out via `action`. + pub fn report_schedule_updates( + schedules: Vec, BlockNumberFor>>, + action: VestingAction, + ) -> (Vec, BlockNumberFor>>, BalanceOf) { + let now = >::block_number(); + + let mut total_locked_now: BalanceOf = Zero::zero(); + let filtered_schedules = action + .pick_schedules::(schedules) + .filter(|schedule| { + let locked_now = schedule.locked_at::(now); + let keep = !locked_now.is_zero(); + if keep { + total_locked_now = total_locked_now.saturating_add(locked_now); + } + keep + }) + .collect::>(); + + (filtered_schedules, total_locked_now) + } + + /// Write an accounts updated vesting lock to storage. + pub fn write_lock(who: &T::AccountId, total_locked_now: BalanceOf, reason: &ReasonOf) { + if total_locked_now.is_zero() { + let _to_handle = T::Currency::release( + &reason, + who, + total_locked_now, + frame_support::traits::tokens::Precision::BestEffort, + ); + Self::deposit_event(Event::::VestingCompleted { account: who.clone() }); + } else { + let _to_handle = T::Currency::hold(&reason, who, total_locked_now); + Self::deposit_event(Event::::VestingUpdated { account: who.clone(), unvested: total_locked_now }); + }; + } + + /// Write an accounts updated vesting schedules to storage. + pub fn write_vesting( + who: &T::AccountId, + schedules: Vec, BlockNumberFor>>, + ) -> Result<(), DispatchError> { + let schedules: BoundedVec, BlockNumberFor>, MaxVestingSchedulesGet> = + schedules.try_into().map_err(|_| Error::::AtMaxVestingSchedules)?; + + if schedules.len() == 0 { + Vesting::::remove(&who); + } else { + Vesting::::insert(who, schedules) + } + + Ok(()) + } + + /// Unlock any vested funds of `who`. + pub fn do_vest(who: T::AccountId, reason: &ReasonOf) -> DispatchResult { + let schedules = Self::vesting(&who).ok_or(Error::::NotVesting)?; + + let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), VestingAction::Passive)?; + + Self::write_vesting(&who, schedules)?; + Self::write_lock(&who, locked_now, reason); + + Ok(()) + } + + /// Execute a `VestingAction` against the given `schedules`. Returns the updated schedules + /// and locked amount. + pub fn exec_action( + schedules: Vec, BlockNumberFor>>, + action: VestingAction, + ) -> Result<(Vec, BlockNumberFor>>, BalanceOf), DispatchError> { + let (schedules, locked_now) = match action { + VestingAction::Merge { index1: idx1, index2: idx2 } => { + // The schedule index is based off of the schedule ordering prior to filtering out + // any schedules that may be ending at this block. + let schedule1 = *schedules.get(idx1).ok_or(Error::::ScheduleIndexOutOfBounds)?; + let schedule2 = *schedules.get(idx2).ok_or(Error::::ScheduleIndexOutOfBounds)?; + + // The length of `schedules` decreases by 2 here since we filter out 2 schedules. + // Thus we know below that we can push the new merged schedule without error + // (assuming initial state was valid). + let (mut schedules, mut locked_now) = Self::report_schedule_updates(schedules.to_vec(), action); + + let now = >::block_number(); + if let Some(new_schedule) = Self::merge_vesting_info(now, schedule1, schedule2) { + // Merging created a new schedule so we: + // 1) need to add it to the accounts vesting schedule collection, + schedules.push(new_schedule); + // (we use `locked_at` in case this is a schedule that started in the past) + let new_schedule_locked = new_schedule.locked_at::(now); + // and 2) update the locked amount to reflect the schedule we just added. + locked_now = locked_now.saturating_add(new_schedule_locked); + } // In the None case there was no new schedule to account for. + + (schedules, locked_now) + }, + _ => Self::report_schedule_updates(schedules.to_vec(), action), + }; + + debug_assert!( + locked_now > Zero::zero() && schedules.len() > 0 || locked_now == Zero::zero() && schedules.len() == 0 + ); + + Ok((schedules, locked_now)) + } +} + +impl ReleaseSchedule for Pallet +// where +// BalanceOf: MaybeSerializeDeserialize + Debug, +{ + type Currency = T::Currency; + type Moment = BlockNumberFor; + + /// Get the amount that is currently being vested and cannot be transferred out of this account. + fn vesting_balance(who: &T::AccountId) -> Option> { + if let Some(v) = Self::vesting(who) { + let now = >::block_number(); + let total_locked_now = v.iter().fold(Zero::zero(), |total, schedule| { + schedule.locked_at::(now).saturating_add(total) + }); + Some(T::Currency::balance(who).min(total_locked_now)) + } else { + None + } + } + + /// Adds a vesting schedule to a given account. + /// + /// If the account has `MaxVestingSchedules`, an Error is returned and nothing + /// is updated. + /// + /// On success, a linearly reducing amount of funds will be locked. In order to realise any + /// reduction of the lock over time as it diminishes, the account owner must use `vest` or + /// `vest_other`. + /// + /// Is a no-op if the amount to be vested is zero. + /// + /// NOTE: This doesn't alter the free balance of the account. + fn add_release_schedule( + who: &T::AccountId, + locked: BalanceOf, + per_block: BalanceOf, + starting_block: BlockNumberFor, + reason: &ReasonOf, + ) -> DispatchResult { + if locked.is_zero() { + return Ok(()); + } + + let vesting_schedule = VestingInfo::new(locked, per_block, starting_block); + // Check for `per_block` or `locked` of 0. + if !vesting_schedule.is_valid() { + return Err(Error::::InvalidScheduleParams.into()); + }; + + let mut schedules = Self::vesting(who).unwrap_or_default(); + + // NOTE: we must push the new schedule so that `exec_action` + // will give the correct new locked amount. + ensure!(schedules.try_push(vesting_schedule).is_ok(), Error::::AtMaxVestingSchedules); + + let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), VestingAction::Passive)?; + + Self::write_vesting(who, schedules)?; + Self::write_lock(who, locked_now, reason); + Ok(()) + } + + // Ensure we can call `add_vesting_schedule` without error. This should always + // be called prior to `add_vesting_schedule`. + fn can_add_release_schedule( + who: &T::AccountId, + locked: BalanceOf, + per_block: BalanceOf, + starting_block: BlockNumberFor, + ) -> DispatchResult { + // Check for `per_block` or `locked` of 0. + if !VestingInfo::new(locked, per_block, starting_block).is_valid() { + return Err(Error::::InvalidScheduleParams.into()); + } + + ensure!( + (Vesting::::decode_len(who).unwrap_or_default() as u32) < T::MAX_VESTING_SCHEDULES, + Error::::AtMaxVestingSchedules + ); + + Ok(()) + } + + /// Remove a vesting schedule for a given account. + fn remove_vesting_schedule(who: &T::AccountId, schedule_index: u32, reason: &ReasonOf) -> DispatchResult { + let schedules = Self::vesting(who).ok_or(Error::::NotVesting)?; + let remove_action = VestingAction::Remove { index: schedule_index as usize }; + + let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), remove_action)?; + + Self::write_vesting(who, schedules)?; + Self::write_lock(who, locked_now, reason); + Ok(()) + } + + fn set_release_schedule( + who: &T::AccountId, + locked: >::Balance, + per_block: >::Balance, + starting_block: Self::Moment, + ) -> DispatchResult { + if locked.is_zero() { + return Ok(()); + } + + let vesting_schedule = VestingInfo::new(locked, per_block, starting_block); + // Check for `per_block` or `locked` of 0. + if !vesting_schedule.is_valid() { + return Err(Error::::InvalidScheduleParams.into()); + }; + + let mut schedules = Self::vesting(who).unwrap_or_default(); + + // NOTE: we must push the new schedule so that `exec_action` + // will give the correct new locked amount. + ensure!(schedules.try_push(vesting_schedule).is_ok(), Error::::AtMaxVestingSchedules); + + let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), VestingAction::Passive)?; + + Self::write_vesting(who, schedules)?; + Ok(()) + } +} diff --git a/polimec-skeleton/pallets/linear-release/src/lib.rs b/polimec-skeleton/pallets/linear-release/src/lib.rs new file mode 100644 index 000000000..b18c386be --- /dev/null +++ b/polimec-skeleton/pallets/linear-release/src/lib.rs @@ -0,0 +1,378 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! +//! # Dev Mode Example Pallet +//! +//! A simple example of a FRAME pallet demonstrating +//! the ease of requirements for a pallet in dev mode. +//! +//! Run `cargo doc --package pallet-dev-mode --open` to view this pallet's documentation. +//! +//! **Dev mode is not meant to be used in production.** + +// Ensure we're `no_std` when compiling for Wasm. +#![cfg_attr(not(feature = "std"), no_std)] + +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::{ + dispatch::DispatchResult, + ensure, + pallet_prelude::*, + traits::{fungible::*, tokens::Balance, Get, WithdrawReasons}, +}; +use frame_system::{pallet_prelude::*, WeightInfo}; + +use crate::types::LockType; +use scale_info::TypeInfo; +use sp_runtime::{ + traits::{AtLeast32BitUnsigned, Bounded, Convert, One, Saturating, Zero}, + RuntimeDebug, +}; +use sp_std::{marker::PhantomData, prelude::*}; + +// Re-export pallet items so that they can be accessed from the crate namespace. +pub use pallet::*; +use traits::ReleaseSchedule; +use types::VestingInfo; + +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; + +mod impls; +pub mod traits; +mod types; + +pub type BalanceOf = ::Balance; +pub type AccountIdOf = ::AccountId; +pub type ReasonOf = ::Reason; + +/// Actions to take against a user's `Vesting` storage entry. +#[derive(Clone, Copy)] +pub enum VestingAction { + /// Do not actively remove any schedules. + Passive, + /// Remove the schedule specified by the index. + Remove { index: usize }, + /// Remove the two schedules, specified by index, so they can be merged. + Merge { index1: usize, index2: usize }, +} + +impl VestingAction { + /// Whether or not the filter says the schedule index should be removed. + fn should_remove(&self, index: usize) -> bool { + match self { + Self::Passive => false, + Self::Remove { index: index1 } => *index1 == index, + Self::Merge { index1, index2 } => *index1 == index || *index2 == index, + } + } + + /// Pick the schedules that this action dictates should continue vesting undisturbed. + fn pick_schedules( + &self, + schedules: Vec, BlockNumberFor>>, + ) -> impl Iterator, BlockNumberFor>> + '_ { + schedules.into_iter().enumerate().filter_map( + move |(index, schedule)| { + if self.should_remove(index) { + None + } else { + Some(schedule) + } + }, + ) + } +} + +// Wrapper for `T::MAX_VESTING_SCHEDULES` to satisfy `trait Get`. +pub struct MaxVestingSchedulesGet(PhantomData); +impl Get for MaxVestingSchedulesGet { + fn get() -> u32 { + T::MAX_VESTING_SCHEDULES + } +} + +/// Enable `dev_mode` for this pallet. +#[frame_support::pallet(dev_mode)] +pub mod pallet { + use super::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + /// The overarching event type. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + type Balance: Balance + From + MaybeSerializeDeserialize; + + type Reason: Parameter + Member + MaxEncodedLen + Ord + Copy; + + type Currency: InspectHold, Balance = BalanceOf> + + MutateHold, Balance = BalanceOf, Reason = ReasonOf> + + BalancedHold, Balance = BalanceOf> + + Mutate, Balance = BalanceOf>; + + /// Convert the block number into a balance. + type BlockNumberToBalance: Convert, BalanceOf>; + + /// Reasons that determine under which conditions the balance may drop below + /// the unvested amount. + type UnvestedFundsAllowedWithdrawReasons: Get; + + /// The minimum amount transferred to call `vested_transfer`. + #[pallet::constant] + type MinVestedTransfer: Get>; + + const MAX_VESTING_SCHEDULES: u32; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; + } + + #[pallet::extra_constants] + impl Pallet { + #[pallet::constant_name(MaxVestingSchedules)] + fn max_vesting_schedules() -> u32 { + T::MAX_VESTING_SCHEDULES + } + } + + #[pallet::genesis_config] + pub struct GenesisConfig { + pub vesting: Vec<(AccountIdOf, T::BlockNumber, T::BlockNumber, BalanceOf)>, + } + + #[cfg(feature = "std")] + impl Default for GenesisConfig { + fn default() -> Self { + GenesisConfig { vesting: Default::default() } + } + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + use sp_runtime::traits::Saturating; + + // Generate initial vesting configuration + // * who - Account which we are generating vesting configuration for + // * begin - Block when the account will start to vest + // * length - Number of blocks from `begin` until fully vested + // * liquid - Number of units which can be spent before vesting begins + for &(ref who, begin, length, liquid) in self.vesting.iter() { + let balance = T::Currency::balance(who); + assert!(!balance.is_zero(), "Currencies must be init'd before vesting"); + // Total genesis `balance` minus `liquid` equals funds locked for vesting + let locked = balance.saturating_sub(liquid); + let length_as_balance = T::BlockNumberToBalance::convert(length); + let per_block = locked / length_as_balance.max(sp_runtime::traits::One::one()); + let vesting_info = VestingInfo::new(locked, per_block, begin); + if !vesting_info.is_valid() { + panic!("Invalid VestingInfo params at genesis") + }; + + Vesting::::try_append(who, vesting_info).expect("Too many vesting schedules at genesis."); + + // TODO: Use T::Currency::hold to lock the funds, using the T::Reasons + + } + } + } + + #[pallet::hooks] + impl Hooks> for Pallet { + fn integrity_test() { + assert!(T::MAX_VESTING_SCHEDULES > 0, "`MaxVestingSchedules` must ge greater than 0"); + } + } + + // Simple declaration of the `Pallet` type. It is placeholder we use to implement traits and + // method. + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// The amount vested has been updated. This could indicate a change in funds available. + /// The balance given is the amount which is left unvested (and thus locked). + VestingUpdated { account: T::AccountId, unvested: BalanceOf }, + /// An \[account\] has become fully vested. + VestingCompleted { account: T::AccountId }, + } + + /// Error for the vesting pallet. + #[pallet::error] + pub enum Error { + /// The account given is not vesting. + NotVesting, + /// The account already has `MaxVestingSchedules` count of schedules and thus + /// cannot add another one. Consider merging existing schedules in order to add another. + AtMaxVestingSchedules, + /// Amount being transferred is too low to create a vesting schedule. + AmountLow, + /// An index was out of bounds of the vesting schedules. + ScheduleIndexOutOfBounds, + /// Failed to create a new schedule because some parameter was invalid. + InvalidScheduleParams, + } + + /// The MEL requirement for bounded pallets is skipped by `dev_mode`. + /// This means that all storages are marked as unbounded. + /// This is equivalent to specifying `#[pallet::unbounded]` on this type definitions. + /// When the dev_mode is removed, we would need to implement implement `MaxEncodedLen`. + #[pallet::storage] + pub type Dummy = StorageValue<_, Vec>; + + /// Information regarding the vesting of a given account. + #[pallet::storage] + #[pallet::getter(fn vesting)] + pub type Vesting = StorageMap< + _, + Blake2_128Concat, + T::AccountId, + BoundedVec, BlockNumberFor>, MaxVestingSchedulesGet>, + >; + + #[pallet::call] + impl Pallet { + /// Unlock any vested funds of the sender account. + /// + /// The dispatch origin for this call must be _Signed_ and the sender must have funds still + /// locked under this pallet. + /// + /// Emits either `VestingCompleted` or `VestingUpdated`. + /// + /// ## Complexity + /// - `O(1)`. + #[pallet::call_index(0)] + pub fn vest(origin: OriginFor, reason: ReasonOf) -> DispatchResult { + let who = ensure_signed(origin)?; + Self::do_vest(who, &reason) + } + + /// Unlock any vested funds of a `target` account. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// - `target`: The account whose vested funds should be unlocked. Must have funds still + /// locked under this pallet. + /// + /// Emits either `VestingCompleted` or `VestingUpdated`. + /// + /// ## Complexity + /// - `O(1)`. + #[pallet::call_index(1)] + pub fn vest_other(origin: OriginFor, target: AccountIdOf, reason: ReasonOf) -> DispatchResult { + ensure_signed(origin)?; + Self::do_vest(target, &reason) + } + + /// Create a vested transfer. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// - `target`: The account receiving the vested funds. + /// - `schedule`: The vesting schedule attached to the transfer. + /// + /// Emits `VestingCreated`. + /// + /// NOTE: This will unlock all schedules through the current block. + /// + /// ## Complexity + /// - `O(1)`. + #[pallet::call_index(2)] + pub fn vested_transfer( + origin: OriginFor, + target: AccountIdOf, + schedule: VestingInfo, BlockNumberFor>, + reason: ReasonOf + ) -> DispatchResult { + let transactor = ensure_signed(origin)?; + Self::do_vested_transfer(transactor, target, schedule, &reason) + } + + /// Force a vested transfer. + /// + /// The dispatch origin for this call must be _Root_. + /// + /// - `source`: The account whose funds should be transferred. + /// - `target`: The account that should be transferred the vested funds. + /// - `schedule`: The vesting schedule attached to the transfer. + /// + /// Emits `VestingCreated`. + /// + /// NOTE: This will unlock all schedules through the current block. + /// + /// ## Complexity + /// - `O(1)`. + #[pallet::call_index(3)] + pub fn force_vested_transfer( + origin: OriginFor, + source: AccountIdOf, + target: AccountIdOf, + schedule: VestingInfo, BlockNumberFor>, + reason: ReasonOf + ) -> DispatchResult { + ensure_root(origin)?; + Self::do_vested_transfer(source, target, schedule, &reason) + } + + /// Merge two vesting schedules together, creating a new vesting schedule that unlocks over + /// the highest possible start and end blocks. If both schedules have already started the + /// current block will be used as the schedule start; with the caveat that if one schedule + /// is finished by the current block, the other will be treated as the new merged schedule, + /// unmodified. + /// + /// NOTE: If `schedule1_index == schedule2_index` this is a no-op. + /// NOTE: This will unlock all schedules through the current block prior to merging. + /// NOTE: If both schedules have ended by the current block, no new schedule will be created + /// and both will be removed. + /// + /// Merged schedule attributes: + /// - `starting_block`: `MAX(schedule1.starting_block, scheduled2.starting_block, + /// current_block)`. + /// - `ending_block`: `MAX(schedule1.ending_block, schedule2.ending_block)`. + /// - `locked`: `schedule1.locked_at(current_block) + schedule2.locked_at(current_block)`. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// - `schedule1_index`: index of the first schedule to merge. + /// - `schedule2_index`: index of the second schedule to merge. + #[pallet::call_index(4)] + pub fn merge_schedules(origin: OriginFor, schedule1_index: u32, schedule2_index: u32, reason: ReasonOf) -> DispatchResult { + let who = ensure_signed(origin)?; + if schedule1_index == schedule2_index { + return Ok(()) + }; + let schedule1_index = schedule1_index as usize; + let schedule2_index = schedule2_index as usize; + + let schedules = Self::vesting(&who).ok_or(Error::::NotVesting)?; + let merge_action = VestingAction::Merge { index1: schedule1_index, index2: schedule2_index }; + + let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), merge_action)?; + + Self::write_vesting(&who, schedules)?; + Self::write_lock(&who, locked_now, &reason); + + Ok(()) + } + } +} diff --git a/polimec-skeleton/pallets/linear-release/src/mock.rs b/polimec-skeleton/pallets/linear-release/src/mock.rs new file mode 100644 index 000000000..451dca8bb --- /dev/null +++ b/polimec-skeleton/pallets/linear-release/src/mock.rs @@ -0,0 +1,135 @@ +use frame_support::{ + parameter_types, + traits::{ConstU32, ConstU64, WithdrawReasons}, +}; +use sp_core::H256; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, Identity, IdentityLookup}, +}; + +use super::*; +use crate as pallet_vesting; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system, + Balances: pallet_balances, + Vesting: pallet_vesting, + } +); + +impl frame_system::Config for Test { + type AccountData = pallet_balances::AccountData; + type AccountId = u64; + type BaseCallFilter = frame_support::traits::Everything; + type BlockHashCount = ConstU64<250>; + type BlockLength = (); + type BlockNumber = u64; + type BlockWeights = (); + type DbWeight = (); + type Hash = H256; + type Hashing = BlakeTwo256; + type Header = Header; + type Index = u64; + type Lookup = IdentityLookup; + type MaxConsumers = frame_support::traits::ConstU32<16>; + type OnKilledAccount = (); + type OnNewAccount = (); + type OnSetCode = (); + type PalletInfo = PalletInfo; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type SS58Prefix = (); + type SystemWeightInfo = (); + type Version = (); +} + +impl pallet_balances::Config for Test { + type AccountStore = System; + type Balance = u64; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type FreezeIdentifier = LockType; + type HoldIdentifier = LockType; + type MaxFreezes = ConstU32<10>; + type MaxHolds = ConstU32<10>; + type MaxLocks = ConstU32<10>; + type MaxReserves = ConstU32<10>; + type ReserveIdentifier = LockType; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); +} +parameter_types! { + pub const MinVestedTransfer: u64 = 256 * 2; + pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons = + WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); + pub static ExistentialDeposit: u64 = 1; +} +impl Config for Test { + type Balance = u64; + type BlockNumberToBalance = Identity; + type Currency = Balances; + type MinVestedTransfer = MinVestedTransfer; + type RuntimeEvent = RuntimeEvent; + type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; + type WeightInfo = (); + + const MAX_VESTING_SCHEDULES: u32 = 3; +} + +#[derive(Default)] +pub struct ExtBuilder { + existential_deposit: u64, + vesting_genesis_config: Option>, +} + +impl ExtBuilder { + pub fn existential_deposit(mut self, existential_deposit: u64) -> Self { + self.existential_deposit = existential_deposit; + self + } + + + pub fn build(self) -> sp_io::TestExternalities { + EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit); + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { + balances: vec![ + (1, 10 * self.existential_deposit), + (2, 21 * self.existential_deposit), + (3, 30 * self.existential_deposit), + (4, 40 * self.existential_deposit), + (12, 10 * self.existential_deposit), + (13, 9999 * self.existential_deposit), + ], + } + .assimilate_storage(&mut t) + .unwrap(); + + let vesting = if let Some(vesting_config) = self.vesting_genesis_config { + vesting_config + } else { + vec![ + (1, 0, 10, 5 * self.existential_deposit), + (2, 10, 20, self.existential_deposit), + (12, 10, 20, 5 * self.existential_deposit), + ] + }; + + pallet_vesting::GenesisConfig:: { vesting } + .assimilate_storage(&mut t) + .unwrap(); + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext + } +} \ No newline at end of file diff --git a/polimec-skeleton/pallets/linear-release/src/tests.rs b/polimec-skeleton/pallets/linear-release/src/tests.rs new file mode 100644 index 000000000..4d268d3fc --- /dev/null +++ b/polimec-skeleton/pallets/linear-release/src/tests.rs @@ -0,0 +1,1014 @@ +use frame_support::{assert_noop, assert_ok, assert_storage_noop, dispatch::EncodeLike}; +use frame_system::RawOrigin; +use sp_runtime::{ + traits::{BadOrigin, Identity}, + TokenError, +}; + +use super::{Vesting as VestingStorage, *}; +use crate::mock::{Balances, ExtBuilder, System, Test, Vesting}; + +/// A default existential deposit. +const ED: u64 = 256; + +/// Calls vest, and asserts that there is no entry for `account` +/// in the `Vesting` storage item. +fn vest_and_assert_no_vesting(account: u64) +where + u64: EncodeLike<::AccountId>, + T: pallet::Config, +{ + // Its ok for this to fail because the user may already have no schedules. + let _result = Vesting::vest(Some(account).into()); + assert!(!>::contains_key(account)); +} + +#[test] +fn check_vesting_status() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + let user1_free_balance = Balances::free_balance(&1); + let user2_free_balance = Balances::free_balance(&2); + let user12_free_balance = Balances::free_balance(&12); + assert_eq!(user1_free_balance, ED * 5); // Account 1 has free balance + assert_eq!(user2_free_balance, ED * 1); // Account 2 has free balance + assert_eq!(user12_free_balance, ED * 5); // Account 12 has free balance + let user1_vesting_schedule = VestingInfo::new( + ED * 5, + 128, // Vesting over 10 blocks + 0, + ); + let user2_vesting_schedule = VestingInfo::new( + ED * 20, + ED, // Vesting over 19 blocks + 10, + ); + let user12_vesting_schedule = VestingInfo::new( + ED * 5, + 64, // Vesting over 20 blocks + 10, + ); + assert_eq!(Vesting::vesting(&1).unwrap(), vec![user1_vesting_schedule]); // Account 1 has a vesting schedule + assert_eq!(Vesting::vesting(&2).unwrap(), vec![user2_vesting_schedule]); // Account 2 has a vesting schedule + assert_eq!(Vesting::vesting(&12).unwrap(), vec![user12_vesting_schedule]); // Account 12 has a vesting schedule + + // Account 1 has only 128 units vested from their illiquid ED * 5 units at block 1 + assert_eq!(Vesting::vesting_balance(&1), Some(128 * 9)); + // Account 2 has their full balance locked + assert_eq!(Vesting::vesting_balance(&2), Some(user2_free_balance)); + // Account 12 has only their illiquid funds locked + assert_eq!(Vesting::vesting_balance(&12), Some(user12_free_balance)); + + System::set_block_number(10); + assert_eq!(System::block_number(), 10); + + // Account 1 has fully vested by block 10 + assert_eq!(Vesting::vesting_balance(&1), Some(0)); + // Account 2 has started vesting by block 10 + assert_eq!(Vesting::vesting_balance(&2), Some(user2_free_balance)); + // Account 12 has started vesting by block 10 + assert_eq!(Vesting::vesting_balance(&12), Some(user12_free_balance)); + + System::set_block_number(30); + assert_eq!(System::block_number(), 30); + + assert_eq!(Vesting::vesting_balance(&1), Some(0)); // Account 1 is still fully vested, and not negative + assert_eq!(Vesting::vesting_balance(&2), Some(0)); // Account 2 has fully vested by block 30 + assert_eq!(Vesting::vesting_balance(&12), Some(0)); // Account 2 has fully vested by block 30 + + // Once we unlock the funds, they are removed from storage. + vest_and_assert_no_vesting::(1); + vest_and_assert_no_vesting::(2); + vest_and_assert_no_vesting::(12); + }); +} + +#[test] +fn check_vesting_status_for_multi_schedule_account() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + assert_eq!(System::block_number(), 1); + let sched0 = VestingInfo::new( + ED * 20, + ED, // Vesting over 20 blocks + 10, + ); + // Account 2 already has a vesting schedule. + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + + // Account 2's free balance is from sched0. + let free_balance = Balances::free_balance(&2); + assert_eq!(free_balance, ED * (20)); + assert_eq!(Vesting::vesting_balance(&2), Some(free_balance)); + + // Add a 2nd schedule that is already unlocking by block #1. + let sched1 = VestingInfo::new( + ED * 10, + ED, // Vesting over 10 blocks + 0, + ); + assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1)); + // Free balance is equal to the two existing schedules total amount. + let free_balance = Balances::free_balance(&2); + assert_eq!(free_balance, ED * (10 + 20)); + // The most recently added schedule exists. + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); + // sched1 has free funds at block #1, but nothing else. + assert_eq!(Vesting::vesting_balance(&2), Some(free_balance - sched1.per_block())); + + // Add a 3rd schedule. + let sched2 = VestingInfo::new( + ED * 30, + ED, // Vesting over 30 blocks + 5, + ); + assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched2)); + + System::set_block_number(9); + // Free balance is equal to the 3 existing schedules total amount. + let free_balance = Balances::free_balance(&2); + assert_eq!(free_balance, ED * (10 + 20 + 30)); + // sched1 and sched2 are freeing funds at block #9. + assert_eq!(Vesting::vesting_balance(&2), Some(free_balance - sched1.per_block() * 9 - sched2.per_block() * 4)); + + System::set_block_number(20); + // At block #20 sched1 is fully unlocked while sched2 and sched0 are partially unlocked. + assert_eq!( + Vesting::vesting_balance(&2), + Some(free_balance - sched1.locked() - sched2.per_block() * 15 - sched0.per_block() * 10) + ); + + System::set_block_number(30); + // At block #30 sched0 and sched1 are fully unlocked while sched2 is partially unlocked. + assert_eq!( + Vesting::vesting_balance(&2), + Some(free_balance - sched1.locked() - sched2.per_block() * 25 - sched0.locked()) + ); + + // At block #35 sched2 fully unlocks and thus all schedules funds are unlocked. + System::set_block_number(35); + assert_eq!(Vesting::vesting_balance(&2), Some(0)); + // Since we have not called any extrinsics that would unlock funds the schedules + // are still in storage, + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); + // but once we unlock the funds, they are removed from storage. + vest_and_assert_no_vesting::(2); + }); +} + +#[test] +fn unvested_balance_should_not_transfer() { + ExtBuilder::default().existential_deposit(10).build().execute_with(|| { + let user1_free_balance = Balances::free_balance(&1); + assert_eq!(user1_free_balance, 100); // Account 1 has free balance + // Account 1 has only 5 units vested at block 1 (plus 50 unvested) + assert_eq!(Vesting::vesting_balance(&1), Some(45)); + println!("{}", Balances::balance_on_hold(&LockType::Evaluation(0), &1)); + // Account 1 cannot send more than vested amount... + assert_noop!(Balances::transfer_allow_death(Some(1).into(), 2, 56), TokenError::Frozen); + }); +} + +#[test] +fn vested_balance_should_transfer() { + ExtBuilder::default().existential_deposit(10).build().execute_with(|| { + let user1_free_balance = Balances::free_balance(&1); + assert_eq!(user1_free_balance, 100); // Account 1 has free balance + // Account 1 has only 5 units vested at block 1 (plus 50 unvested) + assert_eq!(Vesting::vesting_balance(&1), Some(45)); + assert_ok!(Vesting::vest(Some(1).into())); + assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 55)); + }); +} + +#[test] +fn vested_balance_should_transfer_with_multi_sched() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + let sched0 = VestingInfo::new(5 * ED, 128, 0); + assert_ok!(Vesting::vested_transfer(Some(13).into(), 1, sched0)); + // Total 10*ED locked for all the schedules. + assert_eq!(Vesting::vesting(&1).unwrap(), vec![sched0, sched0]); + + let user1_free_balance = Balances::free_balance(&1); + assert_eq!(user1_free_balance, 3840); // Account 1 has free balance + + // Account 1 has only 256 units unlocking at block 1 (plus 1280 already fee). + assert_eq!(Vesting::vesting_balance(&1), Some(2304)); + assert_ok!(Vesting::vest(Some(1).into())); + assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 1536)); + }); +} + +#[test] +fn non_vested_cannot_vest() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + assert!(!>::contains_key(4)); + assert_noop!(Vesting::vest(Some(4).into()), Error::::NotVesting); + }); +} + +#[test] +fn vested_balance_should_transfer_using_vest_other() { + ExtBuilder::default().existential_deposit(10).build().execute_with(|| { + let user1_free_balance = Balances::free_balance(&1); + assert_eq!(user1_free_balance, 100); // Account 1 has free balance + // Account 1 has only 5 units vested at block 1 (plus 50 unvested) + assert_eq!(Vesting::vesting_balance(&1), Some(45)); + assert_ok!(Vesting::vest_other(Some(2).into(), 1)); + assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 55)); + }); +} + +#[test] +fn vested_balance_should_transfer_using_vest_other_with_multi_sched() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + let sched0 = VestingInfo::new(5 * ED, 128, 0); + assert_ok!(Vesting::vested_transfer(Some(13).into(), 1, sched0)); + // Total of 10*ED of locked for all the schedules. + assert_eq!(Vesting::vesting(&1).unwrap(), vec![sched0, sched0]); + + let user1_free_balance = Balances::free_balance(&1); + assert_eq!(user1_free_balance, 3840); // Account 1 has free balance + + // Account 1 has only 256 units unlocking at block 1 (plus 1280 already free). + assert_eq!(Vesting::vesting_balance(&1), Some(2304)); + assert_ok!(Vesting::vest_other(Some(2).into(), 1)); + assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 1536)); + }); +} + +#[test] +fn non_vested_cannot_vest_other() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + assert!(!>::contains_key(4)); + assert_noop!(Vesting::vest_other(Some(3).into(), 4), Error::::NotVesting); + }); +} + +#[test] +fn extra_balance_should_transfer() { + ExtBuilder::default().existential_deposit(10).build().execute_with(|| { + assert_ok!(Balances::transfer_allow_death(Some(3).into(), 1, 100)); + assert_ok!(Balances::transfer_allow_death(Some(3).into(), 2, 100)); + + let user1_free_balance = Balances::free_balance(&1); + assert_eq!(user1_free_balance, 150); // Account 1 has 100 more free balance than normal + + let user2_free_balance = Balances::free_balance(&2); + assert_eq!(user2_free_balance, 110); // Account 2 has 100 more free balance than normal + + // Account 1 has only 5 units vested at block 1 (plus 150 unvested) + assert_eq!(Vesting::vesting_balance(&1), Some(45)); + assert_ok!(Vesting::vest(Some(1).into())); + let user1_free_balance2 = Balances::free_balance(&1); + assert_eq!(user1_free_balance2, 150); // Account 1 has 100 more free balance than normal + assert_ok!(Balances::transfer_allow_death(Some(1).into(), 3, 155)); // Account 1 can send extra units gained + + // Account 2 has no units vested at block 1, but gained 100 + assert_eq!(Vesting::vesting_balance(&2), Some(200)); + assert_ok!(Vesting::vest(Some(2).into())); + assert_ok!(Balances::transfer_allow_death(Some(2).into(), 3, 100)); // Account 2 can send extra + // units gained + }); +} + +#[test] +fn liquid_funds_should_transfer_with_delayed_vesting() { + ExtBuilder::default().existential_deposit(256).build().execute_with(|| { + let user12_free_balance = Balances::free_balance(&12); + + assert_eq!(user12_free_balance, 2560); // Account 12 has free balance + // Account 12 has liquid funds + assert_eq!(Vesting::vesting_balance(&12), Some(user12_free_balance - 256 * 5)); + + // Account 12 has delayed vesting + let user12_vesting_schedule = VestingInfo::new( + 256 * 5, + 64, // Vesting over 20 blocks + 10, + ); + assert_eq!(Vesting::vesting(&12).unwrap(), vec![user12_vesting_schedule]); + + // Account 12 can still send liquid funds + assert_ok!(Balances::transfer_allow_death(Some(12).into(), 3, 256 * 5)); + }); +} + +#[test] +fn vested_transfer_works() { + ExtBuilder::default().existential_deposit(256).build().execute_with(|| { + let user3_free_balance = Balances::free_balance(&3); + let user4_free_balance = Balances::free_balance(&4); + assert_eq!(user3_free_balance, 256 * 30); + assert_eq!(user4_free_balance, 256 * 40); + // Account 4 should not have any vesting yet. + assert_eq!(Vesting::vesting(&4), None); + // Make the schedule for the new transfer. + let new_vesting_schedule = VestingInfo::new( + 256 * 5, + 64, // Vesting over 20 blocks + 10, + ); + assert_ok!(Vesting::vested_transfer(Some(3).into(), 4, new_vesting_schedule)); + // Now account 4 should have vesting. + assert_eq!(Vesting::vesting(&4).unwrap(), vec![new_vesting_schedule]); + // Ensure the transfer happened correctly. + let user3_free_balance_updated = Balances::free_balance(&3); + assert_eq!(user3_free_balance_updated, 256 * 25); + let user4_free_balance_updated = Balances::free_balance(&4); + assert_eq!(user4_free_balance_updated, 256 * 45); + // Account 4 has 5 * 256 locked. + assert_eq!(Vesting::vesting_balance(&4), Some(256 * 5)); + + System::set_block_number(20); + assert_eq!(System::block_number(), 20); + + // Account 4 has 5 * 64 units vested by block 20. + assert_eq!(Vesting::vesting_balance(&4), Some(10 * 64)); + + System::set_block_number(30); + assert_eq!(System::block_number(), 30); + + // Account 4 has fully vested, + assert_eq!(Vesting::vesting_balance(&4), Some(0)); + // and after unlocking its schedules are removed from storage. + vest_and_assert_no_vesting::(4); + }); +} + +#[test] +fn vested_transfer_correctly_fails() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + let user2_free_balance = Balances::free_balance(&2); + let user4_free_balance = Balances::free_balance(&4); + assert_eq!(user2_free_balance, ED * 20); + assert_eq!(user4_free_balance, ED * 40); + + // Account 2 should already have a vesting schedule. + let user2_vesting_schedule = VestingInfo::new( + ED * 20, + ED, // Vesting over 20 blocks + 10, + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![user2_vesting_schedule]); + + // Fails due to too low transfer amount. + let new_vesting_schedule_too_low = VestingInfo::new(::MinVestedTransfer::get() - 1, 64, 10); + assert_noop!( + Vesting::vested_transfer(Some(3).into(), 4, new_vesting_schedule_too_low), + Error::::AmountLow, + ); + + // `per_block` is 0, which would result in a schedule with infinite duration. + let schedule_per_block_0 = VestingInfo::new(::MinVestedTransfer::get(), 0, 10); + assert_noop!( + Vesting::vested_transfer(Some(13).into(), 4, schedule_per_block_0), + Error::::InvalidScheduleParams, + ); + + // `locked` is 0. + let schedule_locked_0 = VestingInfo::new(0, 1, 10); + assert_noop!(Vesting::vested_transfer(Some(3).into(), 4, schedule_locked_0), Error::::AmountLow,); + + // Free balance has not changed. + assert_eq!(user2_free_balance, Balances::free_balance(&2)); + assert_eq!(user4_free_balance, Balances::free_balance(&4)); + // Account 4 has no schedules. + vest_and_assert_no_vesting::(4); + }); +} + +#[test] +fn vested_transfer_allows_max_schedules() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + let mut user_4_free_balance = Balances::free_balance(&4); + let max_schedules = ::MAX_VESTING_SCHEDULES; + let sched = VestingInfo::new( + ::MinVestedTransfer::get(), + 1, // Vest over 2 * 256 blocks. + 10, + ); + + // Add max amount schedules to user 4. + for _ in 0..max_schedules { + assert_ok!(Vesting::vested_transfer(Some(13).into(), 4, sched)); + } + + // The schedules count towards vesting balance + let transferred_amount = ::MinVestedTransfer::get() * max_schedules as u64; + assert_eq!(Vesting::vesting_balance(&4), Some(transferred_amount)); + // and free balance. + user_4_free_balance += transferred_amount; + assert_eq!(Balances::free_balance(&4), user_4_free_balance); + + // Cannot insert a 4th vesting schedule when `MaxVestingSchedules` === 3, + assert_noop!(Vesting::vested_transfer(Some(3).into(), 4, sched), Error::::AtMaxVestingSchedules,); + // so the free balance does not change. + assert_eq!(Balances::free_balance(&4), user_4_free_balance); + + // Account 4 has fully vested when all the schedules end, + System::set_block_number(::MinVestedTransfer::get() + sched.starting_block()); + assert_eq!(Vesting::vesting_balance(&4), Some(0)); + // and after unlocking its schedules are removed from storage. + vest_and_assert_no_vesting::(4); + }); +} + +#[test] +fn force_vested_transfer_works() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + let user3_free_balance = Balances::free_balance(&3); + let user4_free_balance = Balances::free_balance(&4); + assert_eq!(user3_free_balance, ED * 30); + assert_eq!(user4_free_balance, ED * 40); + // Account 4 should not have any vesting yet. + assert_eq!(Vesting::vesting(&4), None); + // Make the schedule for the new transfer. + let new_vesting_schedule = VestingInfo::new( + ED * 5, + 64, // Vesting over 20 blocks + 10, + ); + + assert_noop!(Vesting::force_vested_transfer(Some(4).into(), 3, 4, new_vesting_schedule), BadOrigin); + assert_ok!(Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, new_vesting_schedule)); + // Now account 4 should have vesting. + assert_eq!(Vesting::vesting(&4).unwrap()[0], new_vesting_schedule); + assert_eq!(Vesting::vesting(&4).unwrap().len(), 1); + // Ensure the transfer happened correctly. + let user3_free_balance_updated = Balances::free_balance(&3); + assert_eq!(user3_free_balance_updated, ED * 25); + let user4_free_balance_updated = Balances::free_balance(&4); + assert_eq!(user4_free_balance_updated, ED * 45); + // Account 4 has 5 * ED locked. + assert_eq!(Vesting::vesting_balance(&4), Some(ED * 5)); + + System::set_block_number(20); + assert_eq!(System::block_number(), 20); + + // Account 4 has 5 * 64 units vested by block 20. + assert_eq!(Vesting::vesting_balance(&4), Some(10 * 64)); + + System::set_block_number(30); + assert_eq!(System::block_number(), 30); + + // Account 4 has fully vested, + assert_eq!(Vesting::vesting_balance(&4), Some(0)); + // and after unlocking its schedules are removed from storage. + vest_and_assert_no_vesting::(4); + }); +} + +#[test] +fn force_vested_transfer_correctly_fails() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + let user2_free_balance = Balances::free_balance(&2); + let user4_free_balance = Balances::free_balance(&4); + assert_eq!(user2_free_balance, ED * 20); + assert_eq!(user4_free_balance, ED * 40); + // Account 2 should already have a vesting schedule. + let user2_vesting_schedule = VestingInfo::new( + ED * 20, + ED, // Vesting over 20 blocks + 10, + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![user2_vesting_schedule]); + + // Too low transfer amount. + let new_vesting_schedule_too_low = VestingInfo::new(::MinVestedTransfer::get() - 1, 64, 10); + assert_noop!( + Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, new_vesting_schedule_too_low), + Error::::AmountLow, + ); + + // `per_block` is 0. + let schedule_per_block_0 = VestingInfo::new(::MinVestedTransfer::get(), 0, 10); + assert_noop!( + Vesting::force_vested_transfer(RawOrigin::Root.into(), 13, 4, schedule_per_block_0), + Error::::InvalidScheduleParams, + ); + + // `locked` is 0. + let schedule_locked_0 = VestingInfo::new(0, 1, 10); + assert_noop!( + Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, schedule_locked_0), + Error::::AmountLow, + ); + + // Verify no currency transfer happened. + assert_eq!(user2_free_balance, Balances::free_balance(&2)); + assert_eq!(user4_free_balance, Balances::free_balance(&4)); + // Account 4 has no schedules. + vest_and_assert_no_vesting::(4); + }); +} + +#[test] +fn force_vested_transfer_allows_max_schedules() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + let mut user_4_free_balance = Balances::free_balance(&4); + let max_schedules = ::MAX_VESTING_SCHEDULES; + let sched = VestingInfo::new( + ::MinVestedTransfer::get(), + 1, // Vest over 2 * 256 blocks. + 10, + ); + + // Add max amount schedules to user 4. + for _ in 0..max_schedules { + assert_ok!(Vesting::force_vested_transfer(RawOrigin::Root.into(), 13, 4, sched)); + } + + // The schedules count towards vesting balance. + let transferred_amount = ::MinVestedTransfer::get() * max_schedules as u64; + assert_eq!(Vesting::vesting_balance(&4), Some(transferred_amount)); + // and free balance. + user_4_free_balance += transferred_amount; + assert_eq!(Balances::free_balance(&4), user_4_free_balance); + + // Cannot insert a 4th vesting schedule when `MaxVestingSchedules` === 3 + assert_noop!( + Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, sched), + Error::::AtMaxVestingSchedules, + ); + // so the free balance does not change. + assert_eq!(Balances::free_balance(&4), user_4_free_balance); + + // Account 4 has fully vested when all the schedules end, + System::set_block_number(::MinVestedTransfer::get() + 10); + assert_eq!(Vesting::vesting_balance(&4), Some(0)); + // and after unlocking its schedules are removed from storage. + vest_and_assert_no_vesting::(4); + }); +} + +#[test] +fn merge_schedules_that_have_not_started() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + // Account 2 should already have a vesting schedule. + let sched0 = VestingInfo::new( + ED * 20, + ED, // Vest over 20 blocks. + 10, + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + assert_eq!(Balances::usable_balance(&2), 0); + + // Add a schedule that is identical to the one that already exists. + assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched0)); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched0]); + assert_eq!(Balances::usable_balance(&2), 0); + assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); + + // Since we merged identical schedules, the new schedule finishes at the same + // time as the original, just with double the amount. + let sched1 = VestingInfo::new( + sched0.locked() * 2, + sched0.per_block() * 2, + 10, // Starts at the block the schedules are merged/ + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched1]); + + assert_eq!(Balances::usable_balance(&2), 0); + }); +} + +#[test] +fn merge_ongoing_schedules() { + // Merging two schedules that have started will vest both before merging. + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + // Account 2 should already have a vesting schedule. + let sched0 = VestingInfo::new( + ED * 20, + ED, // Vest over 20 blocks. + 10, + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + + let sched1 = VestingInfo::new( + ED * 10, + ED, // Vest over 10 blocks. + sched0.starting_block() + 5, // Start at block 15. + ); + assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1)); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); + + // Got to half way through the second schedule where both schedules are actively vesting. + let cur_block = 20; + System::set_block_number(cur_block); + + // Account 2 has no usable balances prior to the merge because they have not unlocked + // with `vest` yet. + assert_eq!(Balances::usable_balance(&2), 0); + + assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); + + // Merging schedules un-vests all pre-existing schedules prior to merging, which is + // reflected in account 2's updated usable balance. + let sched0_vested_now = sched0.per_block() * (cur_block - sched0.starting_block()); + let sched1_vested_now = sched1.per_block() * (cur_block - sched1.starting_block()); + assert_eq!(Balances::usable_balance(&2), sched0_vested_now + sched1_vested_now); + + // The locked amount is the sum of what both schedules have locked at the current block. + let sched2_locked = + sched1.locked_at::(cur_block).saturating_add(sched0.locked_at::(cur_block)); + // End block of the new schedule is the greater of either merged schedule. + let sched2_end = sched1.ending_block_as_balance::().max(sched0.ending_block_as_balance::()); + let sched2_duration = sched2_end - cur_block; + // Based off the new schedules total locked and its duration, we can calculate the + // amount to unlock per block. + let sched2_per_block = sched2_locked / sched2_duration; + + let sched2 = VestingInfo::new(sched2_locked, sched2_per_block, cur_block); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2]); + + // And just to double check, we assert the new merged schedule we be cleaned up as expected. + System::set_block_number(30); + vest_and_assert_no_vesting::(2); + }); +} + +#[test] +fn merging_shifts_other_schedules_index() { + // Schedules being merged are filtered out, schedules to the right of any merged + // schedule shift left and the merged schedule is always last. + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + let sched0 = VestingInfo::new( + ED * 10, + ED, // Vesting over 10 blocks. + 10, + ); + let sched1 = VestingInfo::new( + ED * 11, + ED, // Vesting over 11 blocks. + 11, + ); + let sched2 = VestingInfo::new( + ED * 12, + ED, // Vesting over 12 blocks. + 12, + ); + + // Account 3 starts out with no schedules, + assert_eq!(Vesting::vesting(&3), None); + // and some usable balance. + let usable_balance = Balances::usable_balance(&3); + assert_eq!(usable_balance, 30 * ED); + + let cur_block = 1; + assert_eq!(System::block_number(), cur_block); + + // Transfer the above 3 schedules to account 3. + assert_ok!(Vesting::vested_transfer(Some(4).into(), 3, sched0)); + assert_ok!(Vesting::vested_transfer(Some(4).into(), 3, sched1)); + assert_ok!(Vesting::vested_transfer(Some(4).into(), 3, sched2)); + + // With no schedules vested or merged they are in the order they are created + assert_eq!(Vesting::vesting(&3).unwrap(), vec![sched0, sched1, sched2]); + // and the usable balance has not changed. + assert_eq!(usable_balance, Balances::usable_balance(&3)); + + assert_ok!(Vesting::merge_schedules(Some(3).into(), 0, 2)); + + // Create the merged schedule of sched0 & sched2. + // The merged schedule will have the max possible starting block, + let sched3_start = sched1.starting_block().max(sched2.starting_block()); + // `locked` equal to the sum of the two schedules locked through the current block, + let sched3_locked = sched2.locked_at::(cur_block) + sched0.locked_at::(cur_block); + // and will end at the max possible block. + let sched3_end = sched2.ending_block_as_balance::().max(sched0.ending_block_as_balance::()); + let sched3_duration = sched3_end - sched3_start; + let sched3_per_block = sched3_locked / sched3_duration; + let sched3 = VestingInfo::new(sched3_locked, sched3_per_block, sched3_start); + + // The not touched schedule moves left and the new merged schedule is appended. + assert_eq!(Vesting::vesting(&3).unwrap(), vec![sched1, sched3]); + // The usable balance hasn't changed since none of the schedules have started. + assert_eq!(Balances::usable_balance(&3), usable_balance); + }); +} + +#[test] +fn merge_ongoing_and_yet_to_be_started_schedules() { + // Merge an ongoing schedule that has had `vest` called and a schedule that has not already + // started. + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + // Account 2 should already have a vesting schedule. + let sched0 = VestingInfo::new( + ED * 20, + ED, // Vesting over 20 blocks + 10, + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + + // Fast forward to half way through the life of sched1. + let mut cur_block = (sched0.starting_block() + sched0.ending_block_as_balance::()) / 2; + assert_eq!(cur_block, 20); + System::set_block_number(cur_block); + + // Prior to vesting there is no usable balance. + let mut usable_balance = 0; + assert_eq!(Balances::usable_balance(&2), usable_balance); + // Vest the current schedules (which is just sched0 now). + Vesting::vest(Some(2).into()).unwrap(); + + // After vesting the usable balance increases by the unlocked amount. + let sched0_vested_now = sched0.locked() - sched0.locked_at::(cur_block); + usable_balance += sched0_vested_now; + assert_eq!(Balances::usable_balance(&2), usable_balance); + + // Go forward a block. + cur_block += 1; + System::set_block_number(cur_block); + + // And add a schedule that starts after this block, but before sched0 finishes. + let sched1 = VestingInfo::new( + ED * 10, + 1, // Vesting over 256 * 10 (2560) blocks + cur_block + 1, + ); + assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1)); + + // Merge the schedules before sched1 starts. + assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); + // After merging, the usable balance only changes by the amount sched0 vested since we + // last called `vest` (which is just 1 block). The usable balance is not affected by + // sched1 because it has not started yet. + usable_balance += sched0.per_block(); + assert_eq!(Balances::usable_balance(&2), usable_balance); + + // The resulting schedule will have the later starting block of the two, + let sched2_start = sched1.starting_block(); + // `locked` equal to the sum of the two schedules locked through the current block, + let sched2_locked = sched0.locked_at::(cur_block) + sched1.locked_at::(cur_block); + // and will end at the max possible block. + let sched2_end = sched0.ending_block_as_balance::().max(sched1.ending_block_as_balance::()); + let sched2_duration = sched2_end - sched2_start; + let sched2_per_block = sched2_locked / sched2_duration; + + let sched2 = VestingInfo::new(sched2_locked, sched2_per_block, sched2_start); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2]); + }); +} + +#[test] +fn merge_finished_and_ongoing_schedules() { + // If a schedule finishes by the current block we treat the ongoing schedule, + // without any alterations, as the merged one. + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + // Account 2 should already have a vesting schedule. + let sched0 = VestingInfo::new( + ED * 20, + ED, // Vesting over 20 blocks. + 10, + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + + let sched1 = VestingInfo::new( + ED * 40, + ED, // Vesting over 40 blocks. + 10, + ); + assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1)); + + // Transfer a 3rd schedule, so we can demonstrate how schedule indices change. + // (We are not merging this schedule.) + let sched2 = VestingInfo::new( + ED * 30, + ED, // Vesting over 30 blocks. + 10, + ); + assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched2)); + + // The schedules are in expected order prior to merging. + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); + + // Fast forward to sched0's end block. + let cur_block = sched0.ending_block_as_balance::(); + System::set_block_number(cur_block); + assert_eq!(System::block_number(), 30); + + // Prior to `merge_schedules` and with no vest/vest_other called the user has no usable + // balance. + assert_eq!(Balances::usable_balance(&2), 0); + assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); + + // sched2 is now the first, since sched0 & sched1 get filtered out while "merging". + // sched1 gets treated like the new merged schedule by getting pushed onto back + // of the vesting schedules vec. Note: sched0 finished at the current block. + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2, sched1]); + + // sched0 has finished, so its funds are fully unlocked. + let sched0_unlocked_now = sched0.locked(); + // The remaining schedules are ongoing, so their funds are partially unlocked. + let sched1_unlocked_now = sched1.locked() - sched1.locked_at::(cur_block); + let sched2_unlocked_now = sched2.locked() - sched2.locked_at::(cur_block); + + // Since merging also vests all the schedules, the users usable balance after merging + // includes all pre-existing schedules unlocked through the current block, including + // schedules not merged. + assert_eq!(Balances::usable_balance(&2), sched0_unlocked_now + sched1_unlocked_now + sched2_unlocked_now); + }); +} + +#[test] +fn merge_finishing_schedules_does_not_create_a_new_one() { + // If both schedules finish by the current block we don't create new one + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + // Account 2 should already have a vesting schedule. + let sched0 = VestingInfo::new( + ED * 20, + ED, // 20 block duration. + 10, + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + + // Create sched1 and transfer it to account 2. + let sched1 = VestingInfo::new( + ED * 30, + ED, // 30 block duration. + 10, + ); + assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched1)); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); + + let all_scheds_end = + sched0.ending_block_as_balance::().max(sched1.ending_block_as_balance::()); + + assert_eq!(all_scheds_end, 40); + System::set_block_number(all_scheds_end); + + // Prior to merge_schedules and with no vest/vest_other called the user has no usable + // balance. + assert_eq!(Balances::usable_balance(&2), 0); + + // Merge schedule 0 and 1. + assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); + // The user no longer has any more vesting schedules because they both ended at the + // block they where merged, + assert!(!>::contains_key(&2)); + // and their usable balance has increased by the total amount locked in the merged + // schedules. + assert_eq!(Balances::usable_balance(&2), sched0.locked() + sched1.locked()); + }); +} + +#[test] +fn merge_finished_and_yet_to_be_started_schedules() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + // Account 2 should already have a vesting schedule. + let sched0 = VestingInfo::new( + ED * 20, + ED, // 20 block duration. + 10, // Ends at block 30 + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + + let sched1 = VestingInfo::new( + ED * 30, + ED * 2, // 30 block duration. + 35, + ); + assert_ok!(Vesting::vested_transfer(Some(13).into(), 2, sched1)); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); + + let sched2 = VestingInfo::new( + ED * 40, + ED, // 40 block duration. + 30, + ); + // Add a 3rd schedule to demonstrate how sched1 shifts. + assert_ok!(Vesting::vested_transfer(Some(13).into(), 2, sched2)); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); + + System::set_block_number(30); + + // At block 30, sched0 has finished unlocking while sched1 and sched2 are still fully + // locked, + assert_eq!(Vesting::vesting_balance(&2), Some(sched1.locked() + sched2.locked())); + // but since we have not vested usable balance is still 0. + assert_eq!(Balances::usable_balance(&2), 0); + + // Merge schedule 0 and 1. + assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); + + // sched0 is removed since it finished, and sched1 is removed and then pushed on the back + // because it is treated as the merged schedule + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2, sched1]); + + // The usable balance is updated because merging fully unlocked sched0. + assert_eq!(Balances::usable_balance(&2), sched0.locked()); + }); +} + +#[test] +fn merge_schedules_throws_proper_errors() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + // Account 2 should already have a vesting schedule. + let sched0 = VestingInfo::new( + ED * 20, + ED, // 20 block duration. + 10, + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + + // Account 2 only has 1 vesting schedule. + assert_noop!(Vesting::merge_schedules(Some(2).into(), 0, 1), Error::::ScheduleIndexOutOfBounds); + + // Account 4 has 0 vesting schedules. + assert_eq!(Vesting::vesting(&4), None); + assert_noop!(Vesting::merge_schedules(Some(4).into(), 0, 1), Error::::NotVesting); + + // There are enough schedules to merge but an index is non-existent. + Vesting::vested_transfer(Some(3).into(), 2, sched0).unwrap(); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched0]); + assert_noop!(Vesting::merge_schedules(Some(2).into(), 0, 2), Error::::ScheduleIndexOutOfBounds); + + // It is a storage noop with no errors if the indexes are the same. + assert_storage_noop!(Vesting::merge_schedules(Some(2).into(), 0, 0).unwrap()); + }); +} + +#[test] +fn merge_vesting_handles_per_block_0() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + let sched0 = VestingInfo::new( + ED, 0, // Vesting over 256 blocks. + 1, + ); + assert_eq!(sched0.ending_block_as_balance::(), 257); + let sched1 = VestingInfo::new( + ED * 2, + 0, // Vesting over 512 blocks. + 10, + ); + assert_eq!(sched1.ending_block_as_balance::(), 512u64 + 10); + + let merged = VestingInfo::new(764, 1, 10); + assert_eq!(Vesting::merge_vesting_info(5, sched0, sched1), Some(merged)); + }); +} + +#[test] +fn vesting_info_validate_works() { + let min_transfer = ::MinVestedTransfer::get(); + // Does not check for min transfer. + assert_eq!(VestingInfo::new(min_transfer - 1, 1u64, 10u64).is_valid(), true); + + // `locked` cannot be 0. + assert_eq!(VestingInfo::new(0, 1u64, 10u64).is_valid(), false); + + // `per_block` cannot be 0. + assert_eq!(VestingInfo::new(min_transfer + 1, 0u64, 10u64).is_valid(), false); + + // With valid inputs it does not error. + assert_eq!(VestingInfo::new(min_transfer, 1u64, 10u64).is_valid(), true); +} + +#[test] +fn vesting_info_ending_block_as_balance_works() { + // Treats `per_block` 0 as 1. + let per_block_0 = VestingInfo::new(256u32, 0u32, 10u32); + assert_eq!(per_block_0.ending_block_as_balance::(), 256 + 10); + + // `per_block >= locked` always results in a schedule ending the block after it starts + let per_block_gt_locked = VestingInfo::new(256u32, 256 * 2u32, 10u32); + assert_eq!(per_block_gt_locked.ending_block_as_balance::(), 1 + per_block_gt_locked.starting_block()); + let per_block_eq_locked = VestingInfo::new(256u32, 256u32, 10u32); + assert_eq!( + per_block_gt_locked.ending_block_as_balance::(), + per_block_eq_locked.ending_block_as_balance::() + ); + + // Correctly calcs end if `locked % per_block != 0`. (We need a block to unlock the remainder). + let imperfect_per_block = VestingInfo::new(256u32, 250u32, 10u32); + assert_eq!(imperfect_per_block.ending_block_as_balance::(), imperfect_per_block.starting_block() + 2u32,); + assert_eq!(imperfect_per_block.locked_at::(imperfect_per_block.ending_block_as_balance::()), 0); +} + +#[test] +fn per_block_works() { + let per_block_0 = VestingInfo::new(256u32, 0u32, 10u32); + assert_eq!(per_block_0.per_block(), 1u32); + assert_eq!(per_block_0.raw_per_block(), 0u32); + + let per_block_1 = VestingInfo::new(256u32, 1u32, 10u32); + assert_eq!(per_block_1.per_block(), 1u32); + assert_eq!(per_block_1.raw_per_block(), 1u32); +} + +// When an accounts free balance + schedule.locked is less than ED, the vested transfer will fail. +#[test] +fn vested_transfer_less_than_existential_deposit_fails() { + ExtBuilder::default().existential_deposit(4 * ED).build().execute_with(|| { + // MinVestedTransfer is less the ED. + assert!(::Currency::minimum_balance() > ::MinVestedTransfer::get()); + + let sched = VestingInfo::new(::MinVestedTransfer::get() as u64, 1u64, 10u64); + // The new account balance with the schedule's locked amount would be less than ED. + assert!(Balances::free_balance(&99) + sched.locked() < ::Currency::minimum_balance()); + + // vested_transfer fails. + assert_noop!(Vesting::vested_transfer(Some(3).into(), 99, sched), TokenError::BelowMinimum,); + // force_vested_transfer fails. + assert_noop!(Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 99, sched), TokenError::BelowMinimum,); + }); +} diff --git a/polimec-skeleton/pallets/linear-release/src/traits.rs b/polimec-skeleton/pallets/linear-release/src/traits.rs new file mode 100644 index 000000000..f02277402 --- /dev/null +++ b/polimec-skeleton/pallets/linear-release/src/traits.rs @@ -0,0 +1,64 @@ +// TODO: Add Header + +use frame_support::{pallet_prelude::DispatchResult, traits::tokens::fungible}; + +/// A release schedule over a fungible. This allows a particular fungible to have release limits +/// applied to it. +pub trait ReleaseSchedule { + /// The quantity used to denote time; usually just a `BlockNumber`. + type Moment; + + /// The currency that this schedule applies to. + type Currency: fungible::InspectHold + + fungible::MutateHold + + fungible::BalancedHold; + + + /// Get the amount that is currently being vested and cannot be transferred out of this account. + /// Returns `None` if the account has no vesting schedule. + fn vesting_balance(who: &AccountId) -> Option<>::Balance>; + + /// Adds a release schedule to a given account. + /// + /// If the account has `MaxVestingSchedules`, an Error is returned and nothing + /// is updated. + /// + /// Is a no-op if the amount to be vested is zero. + /// + /// NOTE: This doesn't alter the free balance of the account. + fn add_release_schedule( + who: &AccountId, + locked: >::Balance, + per_block: >::Balance, + starting_block: Self::Moment, + reason: &Reason + ) -> DispatchResult; + + /// Ser a release schedule to a given account, without locking any funds. + /// + /// If the account has `MaxVestingSchedules`, an Error is returned and nothing + /// is updated. + /// + /// Is a no-op if the amount to be vested is zero. + /// + /// NOTE: This doesn't alter the free balance of the account. + fn set_release_schedule( + who: &AccountId, + locked: >::Balance, + per_block: >::Balance, + starting_block: Self::Moment, + ) -> DispatchResult; + + /// Checks if `add_release_schedule` would work against `who`. + fn can_add_release_schedule( + who: &AccountId, + locked: >::Balance, + per_block: >::Balance, + starting_block: Self::Moment, + ) -> DispatchResult; + + /// Remove a release schedule for a given account. + /// + /// NOTE: This doesn't alter the free balance of the account. + fn remove_vesting_schedule(who: &AccountId, schedule_index: u32, reason: &Reason) -> DispatchResult; +} diff --git a/polimec-skeleton/pallets/linear-release/src/types.rs b/polimec-skeleton/pallets/linear-release/src/types.rs new file mode 100644 index 000000000..4ebb79cd4 --- /dev/null +++ b/polimec-skeleton/pallets/linear-release/src/types.rs @@ -0,0 +1,93 @@ +use super::*; + +/// Enum used to identify PLMC holds +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo, Ord, PartialOrd)] +pub enum LockType { + Evaluation(ProjectId), + Participation(ProjectId), +} + +/// Struct to encode the vesting schedule of an individual account. +#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)] +pub struct VestingInfo { + /// Locked amount at genesis. + locked: Balance, + /// Amount that gets unlocked every block after `starting_block`. + per_block: Balance, + /// Starting block for unlocking(vesting). + starting_block: BlockNumber, +} + +impl VestingInfo +where + Balance: AtLeast32BitUnsigned + Copy, + BlockNumber: AtLeast32BitUnsigned + Copy + Bounded, +{ + /// Instantiate a new `VestingInfo`. + pub fn new(locked: Balance, per_block: Balance, starting_block: BlockNumber) -> VestingInfo { + VestingInfo { locked, per_block, starting_block } + } + + /// Validate parameters for `VestingInfo`. Note that this does not check + /// against `MinVestedTransfer`. + pub fn is_valid(&self) -> bool { + !self.locked.is_zero() && !self.raw_per_block().is_zero() + } + + /// Locked amount at schedule creation. + pub fn locked(&self) -> Balance { + self.locked + } + + /// Amount that gets unlocked every block after `starting_block`. Corrects for `per_block` of 0. + /// We don't let `per_block` be less than 1, or else the vesting will never end. + /// This should be used whenever accessing `per_block` unless explicitly checking for 0 values. + pub fn per_block(&self) -> Balance { + self.per_block.max(One::one()) + } + + /// Get the unmodified `per_block`. Generally should not be used, but is useful for + /// validating `per_block`. + pub(crate) fn raw_per_block(&self) -> Balance { + self.per_block + } + + /// Starting block for unlocking(vesting). + pub fn starting_block(&self) -> BlockNumber { + self.starting_block + } + + /// Amount locked at block `n`. + pub fn locked_at>(&self, n: BlockNumber) -> Balance { + // Number of blocks that count toward vesting; + // saturating to 0 when n < starting_block. + let vested_block_count = n.saturating_sub(self.starting_block); + let vested_block_count = BlockNumberToBalance::convert(vested_block_count); + // Return amount that is still locked in vesting. + vested_block_count + .checked_mul(&self.per_block()) // `per_block` accessor guarantees at least 1. + .map(|to_unlock| self.locked.saturating_sub(to_unlock)) + .unwrap_or(Zero::zero()) + } + + /// Block number at which the schedule ends (as type `Balance`). + pub fn ending_block_as_balance>(&self) -> Balance { + let starting_block = BlockNumberToBalance::convert(self.starting_block); + let duration = if self.per_block() >= self.locked { + // If `per_block` is bigger than `locked`, the schedule will end + // the block after starting. + One::one() + } else { + self.locked / self.per_block() + + if (self.locked % self.per_block()).is_zero() { + Zero::zero() + } else { + // `per_block` does not perfectly divide `locked`, so we need an extra block to + // unlock some amount less than `per_block`. + One::one() + } + }; + + starting_block.saturating_add(duration) + } +} diff --git a/polimec-skeleton/rustfmt.toml b/polimec-skeleton/rustfmt.toml index 402b58e25..a7034e8d6 100644 --- a/polimec-skeleton/rustfmt.toml +++ b/polimec-skeleton/rustfmt.toml @@ -1,8 +1,19 @@ -edition = "2021" -fn_params_layout = "Compressed" -use_field_init_shorthand = true +# Basic +hard_tabs = true max_width = 120 -use_small_heuristics = "Default" # This modifies `fn_call_width`, `attr_fn_like_width`, `struct_lit_width`, `struct_variant_width`, `array_width`, `chain_width`, `single_line_if_else_max_width` according to the value of `max_width` -use_try_shorthand = true +use_small_heuristics = "Max" +# Imports +imports_granularity = "Crate" +reorder_imports = true +# Consistency newline_style = "Unix" -hard_tabs = true \ No newline at end of file +# Misc +spaces_around_ranges = false +binop_separator = "Back" +reorder_impl_items = true +match_arm_leading_pipes = "Preserve" +match_arm_blocks = false +match_block_trailing_comma = true +trailing_semicolon = false +use_field_init_shorthand = true +edition = "2021" \ No newline at end of file From 15d326a801026f90e154a3b9c742edb68e006895 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Tue, 18 Jul 2023 15:49:36 +0200 Subject: [PATCH 04/80] Delete Cargo.toml --- polimec-skeleton/pallets/funding/Cargo.toml | 67 --------------------- 1 file changed, 67 deletions(-) delete mode 100644 polimec-skeleton/pallets/funding/Cargo.toml diff --git a/polimec-skeleton/pallets/funding/Cargo.toml b/polimec-skeleton/pallets/funding/Cargo.toml deleted file mode 100644 index a349de1cb..000000000 --- a/polimec-skeleton/pallets/funding/Cargo.toml +++ /dev/null @@ -1,67 +0,0 @@ -[package] -name = 'pallet-funding' -authors = ['Polimec Foundation '] -documentation = "https://wiki.polimec.org/" -edition = "2021" -homepage = "https://www.polimec.org/" -license-file = "LICENSE" -readme = "README.md" -repository = "https://github.com/Polimec/polimec-node" -version = "0.1.0" -rust-version = "1.69.0" - -[dependencies] -parity-scale-codec = { version = "3.0.0", features = [ - "derive", -], default-features = false } -scale-info = { version = "2.5.0", default-features = false, features = [ - "derive", -] } -itertools = { version = "0.11.0", default-features = false } - -# Substrate dependencies -frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.42" } - -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-arithmetic = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -polimec-traits = { path = "../../traits", default-features = false } - -[dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-assets = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-credentials = { path = "../credentials", default-features = false } - -[features] -default = ["std"] -std = [ - "itertools/use_std", - "parity-scale-codec/std", - "scale-info/std", - "sp-std/std", - "sp-runtime/std", - "sp-arithmetic/std", - "frame-support/std", - "frame-system/std", - "pallet-assets/std", - "pallet-balances/std", - "pallet-credentials/std", - "polimec-traits/std", - "pallet-vesting/std", - "frame-benchmarking?/std", -] -runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "pallet-assets/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", -] -try-runtime = ["frame-support/try-runtime"] From 3b10eb1b5b6beb21e9acfb32eef76ffc69c77d70 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Tue, 18 Jul 2023 15:51:41 +0200 Subject: [PATCH 05/80] revert: Delete Cargo.toml --- polimec-skeleton/pallets/funding/Cargo.toml | 67 +++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 polimec-skeleton/pallets/funding/Cargo.toml diff --git a/polimec-skeleton/pallets/funding/Cargo.toml b/polimec-skeleton/pallets/funding/Cargo.toml new file mode 100644 index 000000000..a349de1cb --- /dev/null +++ b/polimec-skeleton/pallets/funding/Cargo.toml @@ -0,0 +1,67 @@ +[package] +name = 'pallet-funding' +authors = ['Polimec Foundation '] +documentation = "https://wiki.polimec.org/" +edition = "2021" +homepage = "https://www.polimec.org/" +license-file = "LICENSE" +readme = "README.md" +repository = "https://github.com/Polimec/polimec-node" +version = "0.1.0" +rust-version = "1.69.0" + +[dependencies] +parity-scale-codec = { version = "3.0.0", features = [ + "derive", +], default-features = false } +scale-info = { version = "2.5.0", default-features = false, features = [ + "derive", +] } +itertools = { version = "0.11.0", default-features = false } + +# Substrate dependencies +frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.42" } + +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-arithmetic = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +polimec-traits = { path = "../../traits", default-features = false } + +[dev-dependencies] +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-assets = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-credentials = { path = "../credentials", default-features = false } + +[features] +default = ["std"] +std = [ + "itertools/use_std", + "parity-scale-codec/std", + "scale-info/std", + "sp-std/std", + "sp-runtime/std", + "sp-arithmetic/std", + "frame-support/std", + "frame-system/std", + "pallet-assets/std", + "pallet-balances/std", + "pallet-credentials/std", + "polimec-traits/std", + "pallet-vesting/std", + "frame-benchmarking?/std", +] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "pallet-assets/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", +] +try-runtime = ["frame-support/try-runtime"] From 9f0250e0298196d7ce80f66c51be499daf6b38d8 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Tue, 18 Jul 2023 15:53:54 +0200 Subject: [PATCH 06/80] revert pallet-funding changes --- polimec-skeleton/Cargo.lock | 1 - polimec-skeleton/pallets/funding/Cargo.toml | 2 -- .../pallets/funding/src/functions.rs | 7 ------ polimec-skeleton/pallets/funding/src/lib.rs | 4 +-- polimec-skeleton/pallets/funding/src/mock.rs | 25 ------------------- 5 files changed, 1 insertion(+), 38 deletions(-) diff --git a/polimec-skeleton/Cargo.lock b/polimec-skeleton/Cargo.lock index e57d2bf32..33866b0da 100644 --- a/polimec-skeleton/Cargo.lock +++ b/polimec-skeleton/Cargo.lock @@ -5904,7 +5904,6 @@ dependencies = [ "pallet-balances", "pallet-credentials", "pallet-insecure-randomness-collective-flip", - "pallet-vesting", "parity-scale-codec", "polimec-traits", "scale-info", diff --git a/polimec-skeleton/pallets/funding/Cargo.toml b/polimec-skeleton/pallets/funding/Cargo.toml index a349de1cb..c496460be 100644 --- a/polimec-skeleton/pallets/funding/Cargo.toml +++ b/polimec-skeleton/pallets/funding/Cargo.toml @@ -35,7 +35,6 @@ sp-io = { git = "https://github.com/paritytech/substrate", default-features = fa pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } pallet-assets = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } pallet-credentials = { path = "../credentials", default-features = false } [features] @@ -53,7 +52,6 @@ std = [ "pallet-balances/std", "pallet-credentials/std", "polimec-traits/std", - "pallet-vesting/std", "frame-benchmarking?/std", ] runtime-benchmarks = [ diff --git a/polimec-skeleton/pallets/funding/src/functions.rs b/polimec-skeleton/pallets/funding/src/functions.rs index d63653eed..91cc07a1a 100644 --- a/polimec-skeleton/pallets/funding/src/functions.rs +++ b/polimec-skeleton/pallets/funding/src/functions.rs @@ -2216,11 +2216,4 @@ impl Pallet { })) } } - - // pub fn set_vesting_for( - // who: T::AccountId, locked: BalanceOf, per_block: BalanceOf, starting_block: T::BlockNumber, - // ) -> Result<(), DispatchError> { - // let target = who; - // T::Vesting::add_vesting_schedule(&target, locked, per_block, starting_block) - // } } diff --git a/polimec-skeleton/pallets/funding/src/lib.rs b/polimec-skeleton/pallets/funding/src/lib.rs index b952deaa9..eefeafb71 100644 --- a/polimec-skeleton/pallets/funding/src/lib.rs +++ b/polimec-skeleton/pallets/funding/src/lib.rs @@ -205,7 +205,7 @@ use frame_support::{ pallet_prelude::ValueQuery, traits::{ tokens::{fungible, fungibles, Balance}, - Get, Randomness, VestingSchedule, + Get, Randomness, }, BoundedVec, PalletId, Parameter, }; @@ -315,8 +315,6 @@ pub mod pallet { /// Something that provides the members of Polimec type HandleMembers: PolimecMembers>; - type Vesting: VestingSchedule>; - /// The maximum length of data stored on-chain. #[pallet::constant] type StringLimit: Get; diff --git a/polimec-skeleton/pallets/funding/src/mock.rs b/polimec-skeleton/pallets/funding/src/mock.rs index 3863ef200..007bba0c8 100644 --- a/polimec-skeleton/pallets/funding/src/mock.rs +++ b/polimec-skeleton/pallets/funding/src/mock.rs @@ -65,7 +65,6 @@ frame_support::construct_runtime!( Balances: pallet_balances, FundingModule: pallet_funding, Credentials: pallet_credentials, - Vesting: pallet_vesting, LocalAssets: pallet_assets::::{Pallet, Call, Storage, Event}, StatemintAssets: pallet_assets::::{Pallet, Call, Storage, Event, Config}, } @@ -201,29 +200,6 @@ impl pallet_credentials::Config for TestRuntime { type MembershipInitialized = (); type MembershipChanged = (); } - -use frame_support::traits::WithdrawReasons; - - -parameter_types! { - pub const MinVestedTransfer: Balance = 10 * PLMC; - pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons = - WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); -} - -impl pallet_vesting::Config for TestRuntime { - type BlockNumberToBalance = ConvertInto; - type Currency = Balances; - type MinVestedTransfer = MinVestedTransfer; - type RuntimeEvent = RuntimeEvent; - type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; - type WeightInfo = (); - - // `VestingInfo` encode length is 36bytes. 28 schedules gets encoded as 1009 bytes, which is the - // highest number of schedules that encodes less than 2^10. - const MAX_VESTING_SCHEDULES: u32 = 28; -} - pub const HOURS: BlockNumber = 300u64; // REMARK: In the production configuration we use DAYS instead of HOURS. @@ -273,7 +249,6 @@ impl pallet_funding::Config for TestRuntime { type PalletId = FundingPalletId; type MaxProjectsToUpdatePerBlock = ConstU32<100>; type MaxEvaluationsPerUser = ConstU32<4>; - type Vesting = Vesting; // Low value to simplify the tests type MaxBidsPerUser = ConstU32<4>; type MaxContributionsPerUser = ConstU32<4>; From 51e67582667d6cd468bb55454704c8065435440b Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Tue, 18 Jul 2023 16:56:14 +0200 Subject: [PATCH 07/80] feat; hardcode the LockType to focus on the main logic --- .../pallets/linear-release/src/impls.rs | 29 ++++++++++--------- .../pallets/linear-release/src/lib.rs | 27 ++++++++--------- .../pallets/linear-release/src/mock.rs | 4 +-- .../pallets/linear-release/src/tests.rs | 2 +- .../pallets/linear-release/src/traits.rs | 5 ++-- 5 files changed, 34 insertions(+), 33 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/impls.rs b/polimec-skeleton/pallets/linear-release/src/impls.rs index cf7819a41..f9185fddf 100644 --- a/polimec-skeleton/pallets/linear-release/src/impls.rs +++ b/polimec-skeleton/pallets/linear-release/src/impls.rs @@ -1,3 +1,5 @@ +use crate::types::LockType; + use super::*; impl Pallet { @@ -51,7 +53,6 @@ impl Pallet { source: AccountIdOf, target: AccountIdOf, schedule: VestingInfo, BlockNumberFor>, - reason: &ReasonOf, ) -> DispatchResult { // Validate user inputs. ensure!(schedule.locked() >= T::MinVestedTransfer::get(), Error::::AmountLow); @@ -76,7 +77,6 @@ impl Pallet { schedule.locked(), schedule.per_block(), schedule.starting_block(), - reason, ); debug_assert!(res.is_ok(), "Failed to add a schedule when we had to succeed."); @@ -116,19 +116,21 @@ impl Pallet { } /// Write an accounts updated vesting lock to storage. - pub fn write_lock(who: &T::AccountId, total_locked_now: BalanceOf, reason: &ReasonOf) { + pub fn write_lock(who: &T::AccountId, total_locked_now: BalanceOf) -> Result<(), DispatchError>{ if total_locked_now.is_zero() { - let _to_handle = T::Currency::release( - &reason, + T::Currency::release( + &LockType::Participation(0u32.into()), who, total_locked_now, frame_support::traits::tokens::Precision::BestEffort, - ); + )?; Self::deposit_event(Event::::VestingCompleted { account: who.clone() }); } else { - let _to_handle = T::Currency::hold(&reason, who, total_locked_now); + T::Currency::hold(&LockType::Participation(0u32.into()), who, total_locked_now)?; Self::deposit_event(Event::::VestingUpdated { account: who.clone(), unvested: total_locked_now }); }; + + Ok(()) } /// Write an accounts updated vesting schedules to storage. @@ -149,13 +151,13 @@ impl Pallet { } /// Unlock any vested funds of `who`. - pub fn do_vest(who: T::AccountId, reason: &ReasonOf) -> DispatchResult { + pub fn do_vest(who: T::AccountId) -> DispatchResult { let schedules = Self::vesting(&who).ok_or(Error::::NotVesting)?; let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), VestingAction::Passive)?; Self::write_vesting(&who, schedules)?; - Self::write_lock(&who, locked_now, reason); + Self::write_lock(&who, locked_now)?; Ok(()) } @@ -202,7 +204,7 @@ impl Pallet { } } -impl ReleaseSchedule for Pallet +impl ReleaseSchedule for Pallet // where // BalanceOf: MaybeSerializeDeserialize + Debug, { @@ -239,7 +241,6 @@ impl ReleaseSchedule for Pallet locked: BalanceOf, per_block: BalanceOf, starting_block: BlockNumberFor, - reason: &ReasonOf, ) -> DispatchResult { if locked.is_zero() { return Ok(()); @@ -260,7 +261,7 @@ impl ReleaseSchedule for Pallet let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), VestingAction::Passive)?; Self::write_vesting(who, schedules)?; - Self::write_lock(who, locked_now, reason); + Self::write_lock(who, locked_now)?; Ok(()) } @@ -286,14 +287,14 @@ impl ReleaseSchedule for Pallet } /// Remove a vesting schedule for a given account. - fn remove_vesting_schedule(who: &T::AccountId, schedule_index: u32, reason: &ReasonOf) -> DispatchResult { + fn remove_vesting_schedule(who: &T::AccountId, schedule_index: u32) -> DispatchResult { let schedules = Self::vesting(who).ok_or(Error::::NotVesting)?; let remove_action = VestingAction::Remove { index: schedule_index as usize }; let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), remove_action)?; Self::write_vesting(who, schedules)?; - Self::write_lock(who, locked_now, reason); + Self::write_lock(who, locked_now)?; Ok(()) } diff --git a/polimec-skeleton/pallets/linear-release/src/lib.rs b/polimec-skeleton/pallets/linear-release/src/lib.rs index b18c386be..d781bc4b3 100644 --- a/polimec-skeleton/pallets/linear-release/src/lib.rs +++ b/polimec-skeleton/pallets/linear-release/src/lib.rs @@ -37,7 +37,7 @@ use frame_support::{ }; use frame_system::{pallet_prelude::*, WeightInfo}; -use crate::types::LockType; +// use crate::types::LockType; use scale_info::TypeInfo; use sp_runtime::{ traits::{AtLeast32BitUnsigned, Bounded, Convert, One, Saturating, Zero}, @@ -112,7 +112,9 @@ impl Get for MaxVestingSchedulesGet { /// Enable `dev_mode` for this pallet. #[frame_support::pallet(dev_mode)] pub mod pallet { - use super::*; + use crate::types::LockType; + +use super::*; #[pallet::config] pub trait Config: frame_system::Config { @@ -121,10 +123,11 @@ pub mod pallet { type Balance: Balance + From + MaybeSerializeDeserialize; + // TODO: Unused at the moment, but will be used in the future instead of hardcoding `LockType`. type Reason: Parameter + Member + MaxEncodedLen + Ord + Copy; type Currency: InspectHold, Balance = BalanceOf> - + MutateHold, Balance = BalanceOf, Reason = ReasonOf> + + MutateHold, Balance = BalanceOf, Reason = LockType>> + BalancedHold, Balance = BalanceOf> + Mutate, Balance = BalanceOf>; @@ -262,9 +265,9 @@ pub mod pallet { /// ## Complexity /// - `O(1)`. #[pallet::call_index(0)] - pub fn vest(origin: OriginFor, reason: ReasonOf) -> DispatchResult { + pub fn vest(origin: OriginFor) -> DispatchResult { let who = ensure_signed(origin)?; - Self::do_vest(who, &reason) + Self::do_vest(who) } /// Unlock any vested funds of a `target` account. @@ -279,9 +282,9 @@ pub mod pallet { /// ## Complexity /// - `O(1)`. #[pallet::call_index(1)] - pub fn vest_other(origin: OriginFor, target: AccountIdOf, reason: ReasonOf) -> DispatchResult { + pub fn vest_other(origin: OriginFor, target: AccountIdOf) -> DispatchResult { ensure_signed(origin)?; - Self::do_vest(target, &reason) + Self::do_vest(target) } /// Create a vested transfer. @@ -302,10 +305,9 @@ pub mod pallet { origin: OriginFor, target: AccountIdOf, schedule: VestingInfo, BlockNumberFor>, - reason: ReasonOf ) -> DispatchResult { let transactor = ensure_signed(origin)?; - Self::do_vested_transfer(transactor, target, schedule, &reason) + Self::do_vested_transfer(transactor, target, schedule) } /// Force a vested transfer. @@ -328,10 +330,9 @@ pub mod pallet { source: AccountIdOf, target: AccountIdOf, schedule: VestingInfo, BlockNumberFor>, - reason: ReasonOf ) -> DispatchResult { ensure_root(origin)?; - Self::do_vested_transfer(source, target, schedule, &reason) + Self::do_vested_transfer(source, target, schedule) } /// Merge two vesting schedules together, creating a new vesting schedule that unlocks over @@ -356,7 +357,7 @@ pub mod pallet { /// - `schedule1_index`: index of the first schedule to merge. /// - `schedule2_index`: index of the second schedule to merge. #[pallet::call_index(4)] - pub fn merge_schedules(origin: OriginFor, schedule1_index: u32, schedule2_index: u32, reason: ReasonOf) -> DispatchResult { + pub fn merge_schedules(origin: OriginFor, schedule1_index: u32, schedule2_index: u32) -> DispatchResult { let who = ensure_signed(origin)?; if schedule1_index == schedule2_index { return Ok(()) @@ -370,7 +371,7 @@ pub mod pallet { let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), merge_action)?; Self::write_vesting(&who, schedules)?; - Self::write_lock(&who, locked_now, &reason); + Self::write_lock(&who, locked_now)?; Ok(()) } diff --git a/polimec-skeleton/pallets/linear-release/src/mock.rs b/polimec-skeleton/pallets/linear-release/src/mock.rs index 451dca8bb..6d765fe14 100644 --- a/polimec-skeleton/pallets/linear-release/src/mock.rs +++ b/polimec-skeleton/pallets/linear-release/src/mock.rs @@ -9,7 +9,7 @@ use sp_runtime::{ }; use super::*; -use crate as pallet_vesting; +use crate::{self as pallet_vesting, types::LockType}; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; @@ -82,7 +82,7 @@ impl Config for Test { type RuntimeEvent = RuntimeEvent; type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; type WeightInfo = (); - + type Reason = LockType; const MAX_VESTING_SCHEDULES: u32 = 3; } diff --git a/polimec-skeleton/pallets/linear-release/src/tests.rs b/polimec-skeleton/pallets/linear-release/src/tests.rs index 4d268d3fc..3a0ff7802 100644 --- a/polimec-skeleton/pallets/linear-release/src/tests.rs +++ b/polimec-skeleton/pallets/linear-release/src/tests.rs @@ -6,7 +6,7 @@ use sp_runtime::{ }; use super::{Vesting as VestingStorage, *}; -use crate::mock::{Balances, ExtBuilder, System, Test, Vesting}; +use crate::{mock::{Balances, ExtBuilder, System, Test, Vesting}, types::LockType}; /// A default existential deposit. const ED: u64 = 256; diff --git a/polimec-skeleton/pallets/linear-release/src/traits.rs b/polimec-skeleton/pallets/linear-release/src/traits.rs index f02277402..b5d8e7a62 100644 --- a/polimec-skeleton/pallets/linear-release/src/traits.rs +++ b/polimec-skeleton/pallets/linear-release/src/traits.rs @@ -4,7 +4,7 @@ use frame_support::{pallet_prelude::DispatchResult, traits::tokens::fungible}; /// A release schedule over a fungible. This allows a particular fungible to have release limits /// applied to it. -pub trait ReleaseSchedule { +pub trait ReleaseSchedule { /// The quantity used to denote time; usually just a `BlockNumber`. type Moment; @@ -31,7 +31,6 @@ pub trait ReleaseSchedule { locked: >::Balance, per_block: >::Balance, starting_block: Self::Moment, - reason: &Reason ) -> DispatchResult; /// Ser a release schedule to a given account, without locking any funds. @@ -60,5 +59,5 @@ pub trait ReleaseSchedule { /// Remove a release schedule for a given account. /// /// NOTE: This doesn't alter the free balance of the account. - fn remove_vesting_schedule(who: &AccountId, schedule_index: u32, reason: &Reason) -> DispatchResult; + fn remove_vesting_schedule(who: &AccountId, schedule_index: u32) -> DispatchResult; } From 17a8e57b43b48c1fb7b077204a2d99f09f98df95 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Tue, 18 Jul 2023 18:30:00 +0200 Subject: [PATCH 08/80] wip: add release schedule --- .../pallets/linear-release/src/impls.rs | 26 ++++---- .../pallets/linear-release/src/lib.rs | 16 ++++- .../pallets/linear-release/src/tests.rs | 63 +++++++++++++++++-- .../pallets/linear-release/src/types.rs | 6 +- 4 files changed, 91 insertions(+), 20 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/impls.rs b/polimec-skeleton/pallets/linear-release/src/impls.rs index f9185fddf..938c4e058 100644 --- a/polimec-skeleton/pallets/linear-release/src/impls.rs +++ b/polimec-skeleton/pallets/linear-release/src/impls.rs @@ -72,13 +72,9 @@ impl Pallet { )?; // We can't let this fail because the currency transfer has already happened. - let res = Self::add_release_schedule( - &target, - schedule.locked(), - schedule.per_block(), - schedule.starting_block(), - ); - debug_assert!(res.is_ok(), "Failed to add a schedule when we had to succeed."); + let res = + Self::add_release_schedule(&target, schedule.locked(), schedule.per_block(), schedule.starting_block()); + debug_assert!(res.is_ok(), "{:#?}", res.err()); Ok(()) } @@ -116,17 +112,22 @@ impl Pallet { } /// Write an accounts updated vesting lock to storage. - pub fn write_lock(who: &T::AccountId, total_locked_now: BalanceOf) -> Result<(), DispatchError>{ + pub fn write_lock(who: &T::AccountId, total_locked_now: BalanceOf) -> Result<(), DispatchError> { if total_locked_now.is_zero() { T::Currency::release( &LockType::Participation(0u32.into()), who, - total_locked_now, + T::Currency::balance_on_hold(&LockType::Participation(0u32.into()), who), frame_support::traits::tokens::Precision::BestEffort, )?; Self::deposit_event(Event::::VestingCompleted { account: who.clone() }); } else { - T::Currency::hold(&LockType::Participation(0u32.into()), who, total_locked_now)?; + T::Currency::release( + &LockType::Participation(0u32.into()), + who, + total_locked_now, + frame_support::traits::tokens::Precision::BestEffort, + )?; Self::deposit_event(Event::::VestingUpdated { account: who.clone(), unvested: total_locked_now }); }; @@ -156,6 +157,9 @@ impl Pallet { let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), VestingAction::Passive)?; + println!("do_vest: schedules: {:?}", schedules); + println!("do_vest: locked_now: {:?}", locked_now); + Self::write_vesting(&who, schedules)?; Self::write_lock(&who, locked_now)?; @@ -320,7 +324,7 @@ impl ReleaseSchedule for Pallet // will give the correct new locked amount. ensure!(schedules.try_push(vesting_schedule).is_ok(), Error::::AtMaxVestingSchedules); - let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), VestingAction::Passive)?; + let (schedules, _) = Self::exec_action(schedules.to_vec(), VestingAction::Passive)?; Self::write_vesting(who, schedules)?; Ok(()) diff --git a/polimec-skeleton/pallets/linear-release/src/lib.rs b/polimec-skeleton/pallets/linear-release/src/lib.rs index d781bc4b3..699900d13 100644 --- a/polimec-skeleton/pallets/linear-release/src/lib.rs +++ b/polimec-skeleton/pallets/linear-release/src/lib.rs @@ -114,7 +114,7 @@ impl Get for MaxVestingSchedulesGet { pub mod pallet { use crate::types::LockType; -use super::*; + use super::*; #[pallet::config] pub trait Config: frame_system::Config { @@ -194,6 +194,9 @@ use super::*; // TODO: Use T::Currency::hold to lock the funds, using the T::Reasons + T::Currency::hold(&LockType::Participation(0u32.into()), who, locked) + .map_err(|err| panic!("{:?}", err)) + .unwrap(); } } } @@ -360,7 +363,7 @@ use super::*; pub fn merge_schedules(origin: OriginFor, schedule1_index: u32, schedule2_index: u32) -> DispatchResult { let who = ensure_signed(origin)?; if schedule1_index == schedule2_index { - return Ok(()) + return Ok(()); }; let schedule1_index = schedule1_index as usize; let schedule2_index = schedule2_index as usize; @@ -375,5 +378,14 @@ use super::*; Ok(()) } + + #[pallet::call_index(5)] + pub fn release_schedule( + origin: OriginFor, + schedule: VestingInfo, BlockNumberFor>, + ) -> DispatchResult { + let transactor = ensure_signed(origin)?; + Self::set_release_schedule(&transactor, schedule.locked(), schedule.per_block(), schedule.starting_block()) + } } } diff --git a/polimec-skeleton/pallets/linear-release/src/tests.rs b/polimec-skeleton/pallets/linear-release/src/tests.rs index 3a0ff7802..ab5e31c25 100644 --- a/polimec-skeleton/pallets/linear-release/src/tests.rs +++ b/polimec-skeleton/pallets/linear-release/src/tests.rs @@ -96,7 +96,7 @@ fn check_vesting_status_for_multi_schedule_account() { // Account 2's free balance is from sched0. let free_balance = Balances::free_balance(&2); - assert_eq!(free_balance, ED * (20)); + assert_eq!(free_balance, ED * (1)); assert_eq!(Vesting::vesting_balance(&2), Some(free_balance)); // Add a 2nd schedule that is already unlocking by block #1. @@ -259,11 +259,11 @@ fn extra_balance_should_transfer() { assert_eq!(Vesting::vesting_balance(&1), Some(45)); assert_ok!(Vesting::vest(Some(1).into())); let user1_free_balance2 = Balances::free_balance(&1); - assert_eq!(user1_free_balance2, 150); // Account 1 has 100 more free balance than normal + assert_eq!(user1_free_balance2, 195); // Account 1 has 100 more free balance than normal assert_ok!(Balances::transfer_allow_death(Some(1).into(), 3, 155)); // Account 1 can send extra units gained // Account 2 has no units vested at block 1, but gained 100 - assert_eq!(Vesting::vesting_balance(&2), Some(200)); + assert_eq!(Vesting::vesting_balance(&2), Some(110)); assert_ok!(Vesting::vest(Some(2).into())); assert_ok!(Balances::transfer_allow_death(Some(2).into(), 3, 100)); // Account 2 can send extra // units gained @@ -462,7 +462,7 @@ fn force_vested_transfer_correctly_fails() { ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { let user2_free_balance = Balances::free_balance(&2); let user4_free_balance = Balances::free_balance(&4); - assert_eq!(user2_free_balance, ED * 20); + assert_eq!(user2_free_balance, ED * 21); assert_eq!(user4_free_balance, ED * 40); // Account 2 should already have a vesting schedule. let user2_vesting_schedule = VestingInfo::new( @@ -1012,3 +1012,58 @@ fn vested_transfer_less_than_existential_deposit_fails() { assert_noop!(Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 99, sched), TokenError::BelowMinimum,); }); } + + +// TODO +#[test] +fn set_release_schedule() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + assert_eq!(System::block_number(), 1); + // Initial Status + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 30 * ED); // 7680 ED + let user_3_reserved_balance = Balances::reserved_balance(&3); + assert_eq!(user_3_reserved_balance, 0); + let user_3_on_hold_balance = Balances::balance_on_hold(&LockType::Participation(0), &3); + assert_eq!(user_3_on_hold_balance, 0); + assert_eq!(Vesting::vesting_balance(&3), None); + + // Hold 15 ED + assert_ok!(Balances::hold(&LockType::Participation(0), &3, 15 * ED)); + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 15 * ED); + let user_3_on_hold_balance = Balances::balance_on_hold(&LockType::Participation(0), &3); + assert_eq!(user_3_on_hold_balance, 15 * ED); + let user_3_reserved_balance = Balances::reserved_balance(&3); + assert_eq!(user_3_reserved_balance, 15 * ED); + assert_eq!(Vesting::vesting_balance(&3), None); + + // Set release schedule to release the locked amount, starting from now, one ED per block. + let user3_vesting_schedule = VestingInfo::new( + user_3_on_hold_balance, + ED, + System::block_number(), + ); + assert_ok!(Vesting::release_schedule(Some(3).into(), user3_vesting_schedule)); + assert_eq!(Vesting::vesting_balance(&3), Some(15 * ED)); + + // 1 ED can be "released" + System::set_block_number(2); + assert_eq!(Vesting::vesting_balance(&3), Some(14 * ED)); + + + // 2 ED can be "released" + System::set_block_number(3); + assert_eq!(Vesting::vesting_balance(&3), Some(13 * ED)); + + // Go to the end of the schedule + System::set_block_number(16); + assert_eq!(System::block_number(), 16); + assert_eq!(Vesting::vesting_balance(&3), Some(0)); + vest_and_assert_no_vesting::(3); + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 30 * ED); + + + }); +} \ No newline at end of file diff --git a/polimec-skeleton/pallets/linear-release/src/types.rs b/polimec-skeleton/pallets/linear-release/src/types.rs index 4ebb79cd4..c39383cf2 100644 --- a/polimec-skeleton/pallets/linear-release/src/types.rs +++ b/polimec-skeleton/pallets/linear-release/src/types.rs @@ -11,11 +11,11 @@ pub enum LockType { #[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)] pub struct VestingInfo { /// Locked amount at genesis. - locked: Balance, + pub locked: Balance, /// Amount that gets unlocked every block after `starting_block`. - per_block: Balance, + pub per_block: Balance, /// Starting block for unlocking(vesting). - starting_block: BlockNumber, + pub starting_block: BlockNumber, } impl VestingInfo From afcd124f9a5f88dfc791712099df7cef7db97309 Mon Sep 17 00:00:00 2001 From: lrazovic <4128940+lrazovic@users.noreply.github.com> Date: Tue, 18 Jul 2023 23:02:45 +0200 Subject: [PATCH 09/80] feat: add linear release to the funding pallet --- polimec-skeleton/Cargo.lock | 1 + polimec-skeleton/pallets/funding/Cargo.toml | 2 + polimec-skeleton/pallets/funding/src/lib.rs | 2 + polimec-skeleton/pallets/funding/src/mock.rs | 21 + .../pallets/funding/src/traits.rs | 2 + .../pallets/linear-release/src/impls.rs | 28 +- .../pallets/linear-release/src/lib.rs | 34 +- .../pallets/linear-release/src/mock.rs | 8 +- .../pallets/linear-release/src/tests.rs | 1988 +++++++++-------- .../pallets/linear-release/src/traits.rs | 5 +- 10 files changed, 1066 insertions(+), 1025 deletions(-) diff --git a/polimec-skeleton/Cargo.lock b/polimec-skeleton/Cargo.lock index 33866b0da..cf0b813f0 100644 --- a/polimec-skeleton/Cargo.lock +++ b/polimec-skeleton/Cargo.lock @@ -5904,6 +5904,7 @@ dependencies = [ "pallet-balances", "pallet-credentials", "pallet-insecure-randomness-collective-flip", + "pallet-linear-release", "parity-scale-codec", "polimec-traits", "scale-info", diff --git a/polimec-skeleton/pallets/funding/Cargo.toml b/polimec-skeleton/pallets/funding/Cargo.toml index c496460be..ee456ee6e 100644 --- a/polimec-skeleton/pallets/funding/Cargo.toml +++ b/polimec-skeleton/pallets/funding/Cargo.toml @@ -28,6 +28,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", default-features = f sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } sp-arithmetic = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } polimec-traits = { path = "../../traits", default-features = false } +pallet-linear-release = { path = "../linear-release", default-features = false } [dev-dependencies] sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } @@ -52,6 +53,7 @@ std = [ "pallet-balances/std", "pallet-credentials/std", "polimec-traits/std", + "pallet-linear-release/std", "frame-benchmarking?/std", ] runtime-benchmarks = [ diff --git a/polimec-skeleton/pallets/funding/src/lib.rs b/polimec-skeleton/pallets/funding/src/lib.rs index eefeafb71..b78b1cd22 100644 --- a/polimec-skeleton/pallets/funding/src/lib.rs +++ b/polimec-skeleton/pallets/funding/src/lib.rs @@ -315,6 +315,8 @@ pub mod pallet { /// Something that provides the members of Polimec type HandleMembers: PolimecMembers>; + type Vesting: traits::ReleaseSchedule, BondTypeOf>; + /// The maximum length of data stored on-chain. #[pallet::constant] type StringLimit: Get; diff --git a/polimec-skeleton/pallets/funding/src/mock.rs b/polimec-skeleton/pallets/funding/src/mock.rs index 007bba0c8..052274a20 100644 --- a/polimec-skeleton/pallets/funding/src/mock.rs +++ b/polimec-skeleton/pallets/funding/src/mock.rs @@ -65,6 +65,7 @@ frame_support::construct_runtime!( Balances: pallet_balances, FundingModule: pallet_funding, Credentials: pallet_credentials, + Vesting: pallet_linear_release, LocalAssets: pallet_assets::::{Pallet, Call, Storage, Event}, StatemintAssets: pallet_assets::::{Pallet, Call, Storage, Event, Config}, } @@ -225,6 +226,25 @@ parameter_types! { pub EarlyEvaluationThreshold: Percent = Percent::from_percent(10); } +use frame_support::traits::WithdrawReasons; + +parameter_types! { + pub const MinVestedTransfer: u64 = 256 * 2; + pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons = + WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); +} +impl pallet_linear_release::Config for TestRuntime { + type Balance = Balance; + type BlockNumberToBalance = ConvertInto; + type Currency = Balances; + type MinVestedTransfer = MinVestedTransfer; + type RuntimeEvent = RuntimeEvent; + type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; + type WeightInfo = (); + type Reason = LockType; + const MAX_VESTING_SCHEDULES: u32 = 3; +} + impl pallet_funding::Config for TestRuntime { type RuntimeEvent = RuntimeEvent; type ProjectIdentifier = Identifier; @@ -258,6 +278,7 @@ impl pallet_funding::Config for TestRuntime { type WeightInfo = (); type FeeBrackets = FeeBrackets; type EarlyEvaluationThreshold = EarlyEvaluationThreshold; + type Vesting = Vesting; } // Build genesis storage according to the mock runtime. diff --git a/polimec-skeleton/pallets/funding/src/traits.rs b/polimec-skeleton/pallets/funding/src/traits.rs index 51a845b3b..c7c98f806 100644 --- a/polimec-skeleton/pallets/funding/src/traits.rs +++ b/polimec-skeleton/pallets/funding/src/traits.rs @@ -19,3 +19,5 @@ pub trait DoRemainingOperation { fn do_one_operation(&mut self, project_id: T::ProjectIdentifier) -> Result; } + +pub use pallet_linear_release::traits::ReleaseSchedule; diff --git a/polimec-skeleton/pallets/linear-release/src/impls.rs b/polimec-skeleton/pallets/linear-release/src/impls.rs index 938c4e058..ee67da94d 100644 --- a/polimec-skeleton/pallets/linear-release/src/impls.rs +++ b/polimec-skeleton/pallets/linear-release/src/impls.rs @@ -53,6 +53,7 @@ impl Pallet { source: AccountIdOf, target: AccountIdOf, schedule: VestingInfo, BlockNumberFor>, + reason: ReasonOf ) -> DispatchResult { // Validate user inputs. ensure!(schedule.locked() >= T::MinVestedTransfer::get(), Error::::AmountLow); @@ -73,7 +74,7 @@ impl Pallet { // We can't let this fail because the currency transfer has already happened. let res = - Self::add_release_schedule(&target, schedule.locked(), schedule.per_block(), schedule.starting_block()); + Self::add_release_schedule(&target, schedule.locked(), schedule.per_block(), schedule.starting_block(), reason); debug_assert!(res.is_ok(), "{:#?}", res.err()); Ok(()) @@ -112,20 +113,22 @@ impl Pallet { } /// Write an accounts updated vesting lock to storage. - pub fn write_lock(who: &T::AccountId, total_locked_now: BalanceOf) -> Result<(), DispatchError> { + pub fn write_lock(who: &T::AccountId, total_locked_now: BalanceOf, reason: ReasonOf) -> Result<(), DispatchError> { if total_locked_now.is_zero() { T::Currency::release( - &LockType::Participation(0u32.into()), + &reason, who, - T::Currency::balance_on_hold(&LockType::Participation(0u32.into()), who), + T::Currency::balance_on_hold(&reason, who), frame_support::traits::tokens::Precision::BestEffort, )?; Self::deposit_event(Event::::VestingCompleted { account: who.clone() }); } else { + let amount = T::Currency::balance_on_hold(&reason, who); + let amount = amount.saturating_sub(total_locked_now); T::Currency::release( - &LockType::Participation(0u32.into()), + &reason, who, - total_locked_now, + amount, frame_support::traits::tokens::Precision::BestEffort, )?; Self::deposit_event(Event::::VestingUpdated { account: who.clone(), unvested: total_locked_now }); @@ -152,7 +155,7 @@ impl Pallet { } /// Unlock any vested funds of `who`. - pub fn do_vest(who: T::AccountId) -> DispatchResult { + pub fn do_vest(who: T::AccountId, reason: ReasonOf) -> DispatchResult { let schedules = Self::vesting(&who).ok_or(Error::::NotVesting)?; let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), VestingAction::Passive)?; @@ -161,7 +164,7 @@ impl Pallet { println!("do_vest: locked_now: {:?}", locked_now); Self::write_vesting(&who, schedules)?; - Self::write_lock(&who, locked_now)?; + Self::write_lock(&who, locked_now, reason)?; Ok(()) } @@ -208,7 +211,7 @@ impl Pallet { } } -impl ReleaseSchedule for Pallet +impl ReleaseSchedule, ReasonOf> for Pallet // where // BalanceOf: MaybeSerializeDeserialize + Debug, { @@ -245,6 +248,7 @@ impl ReleaseSchedule for Pallet locked: BalanceOf, per_block: BalanceOf, starting_block: BlockNumberFor, + reason: ReasonOf, ) -> DispatchResult { if locked.is_zero() { return Ok(()); @@ -265,7 +269,7 @@ impl ReleaseSchedule for Pallet let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), VestingAction::Passive)?; Self::write_vesting(who, schedules)?; - Self::write_lock(who, locked_now)?; + Self::write_lock(who, locked_now, reason)?; Ok(()) } @@ -291,14 +295,14 @@ impl ReleaseSchedule for Pallet } /// Remove a vesting schedule for a given account. - fn remove_vesting_schedule(who: &T::AccountId, schedule_index: u32) -> DispatchResult { + fn remove_vesting_schedule(who: &T::AccountId, schedule_index: u32, reason: ReasonOf,) -> DispatchResult { let schedules = Self::vesting(who).ok_or(Error::::NotVesting)?; let remove_action = VestingAction::Remove { index: schedule_index as usize }; let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), remove_action)?; Self::write_vesting(who, schedules)?; - Self::write_lock(who, locked_now)?; + Self::write_lock(who, locked_now, reason)?; Ok(()) } diff --git a/polimec-skeleton/pallets/linear-release/src/lib.rs b/polimec-skeleton/pallets/linear-release/src/lib.rs index 699900d13..e279a73a9 100644 --- a/polimec-skeleton/pallets/linear-release/src/lib.rs +++ b/polimec-skeleton/pallets/linear-release/src/lib.rs @@ -60,8 +60,8 @@ pub mod traits; mod types; pub type BalanceOf = ::Balance; -pub type AccountIdOf = ::AccountId; pub type ReasonOf = ::Reason; +pub type AccountIdOf = ::AccountId; /// Actions to take against a user's `Vesting` storage entry. #[derive(Clone, Copy)] @@ -112,7 +112,6 @@ impl Get for MaxVestingSchedulesGet { /// Enable `dev_mode` for this pallet. #[frame_support::pallet(dev_mode)] pub mod pallet { - use crate::types::LockType; use super::*; @@ -123,11 +122,11 @@ pub mod pallet { type Balance: Balance + From + MaybeSerializeDeserialize; - // TODO: Unused at the moment, but will be used in the future instead of hardcoding `LockType`. - type Reason: Parameter + Member + MaxEncodedLen + Ord + Copy; + // TODO: Still I dont-like this. I want to be able to use the `LockType` from the pallet_balances, without coupling it. + type Reason: Parameter + Copy; type Currency: InspectHold, Balance = BalanceOf> - + MutateHold, Balance = BalanceOf, Reason = LockType>> + + MutateHold, Balance = BalanceOf, Reason = ReasonOf> + BalancedHold, Balance = BalanceOf> + Mutate, Balance = BalanceOf>; @@ -193,10 +192,11 @@ pub mod pallet { Vesting::::try_append(who, vesting_info).expect("Too many vesting schedules at genesis."); // TODO: Use T::Currency::hold to lock the funds, using the T::Reasons + // FIXME: Re-add it, otherwise the tests will fail - T::Currency::hold(&LockType::Participation(0u32.into()), who, locked) - .map_err(|err| panic!("{:?}", err)) - .unwrap(); + // T::Currency::hold(&LockType::Participation(0u32.into()), who, locked) + // .map_err(|err| panic!("{:?}", err)) + // .unwrap(); } } } @@ -268,9 +268,9 @@ pub mod pallet { /// ## Complexity /// - `O(1)`. #[pallet::call_index(0)] - pub fn vest(origin: OriginFor) -> DispatchResult { + pub fn vest(origin: OriginFor, reason: ReasonOf) -> DispatchResult { let who = ensure_signed(origin)?; - Self::do_vest(who) + Self::do_vest(who, reason) } /// Unlock any vested funds of a `target` account. @@ -285,9 +285,9 @@ pub mod pallet { /// ## Complexity /// - `O(1)`. #[pallet::call_index(1)] - pub fn vest_other(origin: OriginFor, target: AccountIdOf) -> DispatchResult { + pub fn vest_other(origin: OriginFor, target: AccountIdOf, reason: ReasonOf) -> DispatchResult { ensure_signed(origin)?; - Self::do_vest(target) + Self::do_vest(target, reason) } /// Create a vested transfer. @@ -308,9 +308,10 @@ pub mod pallet { origin: OriginFor, target: AccountIdOf, schedule: VestingInfo, BlockNumberFor>, + reason: ReasonOf ) -> DispatchResult { let transactor = ensure_signed(origin)?; - Self::do_vested_transfer(transactor, target, schedule) + Self::do_vested_transfer(transactor, target, schedule, reason) } /// Force a vested transfer. @@ -333,9 +334,10 @@ pub mod pallet { source: AccountIdOf, target: AccountIdOf, schedule: VestingInfo, BlockNumberFor>, + reason: ReasonOf ) -> DispatchResult { ensure_root(origin)?; - Self::do_vested_transfer(source, target, schedule) + Self::do_vested_transfer(source, target, schedule, reason) } /// Merge two vesting schedules together, creating a new vesting schedule that unlocks over @@ -360,7 +362,7 @@ pub mod pallet { /// - `schedule1_index`: index of the first schedule to merge. /// - `schedule2_index`: index of the second schedule to merge. #[pallet::call_index(4)] - pub fn merge_schedules(origin: OriginFor, schedule1_index: u32, schedule2_index: u32) -> DispatchResult { + pub fn merge_schedules(origin: OriginFor, schedule1_index: u32, schedule2_index: u32, reason: ReasonOf) -> DispatchResult { let who = ensure_signed(origin)?; if schedule1_index == schedule2_index { return Ok(()); @@ -374,7 +376,7 @@ pub mod pallet { let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), merge_action)?; Self::write_vesting(&who, schedules)?; - Self::write_lock(&who, locked_now)?; + Self::write_lock(&who, locked_now, reason)?; Ok(()) } diff --git a/polimec-skeleton/pallets/linear-release/src/mock.rs b/polimec-skeleton/pallets/linear-release/src/mock.rs index 6d765fe14..5d6fa6842 100644 --- a/polimec-skeleton/pallets/linear-release/src/mock.rs +++ b/polimec-skeleton/pallets/linear-release/src/mock.rs @@ -58,13 +58,13 @@ impl pallet_balances::Config for Test { type Balance = u64; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; - type FreezeIdentifier = LockType; - type HoldIdentifier = LockType; + type FreezeIdentifier = LockType; + type HoldIdentifier = LockType; type MaxFreezes = ConstU32<10>; type MaxHolds = ConstU32<10>; type MaxLocks = ConstU32<10>; type MaxReserves = ConstU32<10>; - type ReserveIdentifier = LockType; + type ReserveIdentifier = LockType; type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } @@ -78,11 +78,11 @@ impl Config for Test { type Balance = u64; type BlockNumberToBalance = Identity; type Currency = Balances; + type Reason = LockType; // TODO: Use the type from Balances. type MinVestedTransfer = MinVestedTransfer; type RuntimeEvent = RuntimeEvent; type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; type WeightInfo = (); - type Reason = LockType; const MAX_VESTING_SCHEDULES: u32 = 3; } diff --git a/polimec-skeleton/pallets/linear-release/src/tests.rs b/polimec-skeleton/pallets/linear-release/src/tests.rs index ab5e31c25..ea3f66d85 100644 --- a/polimec-skeleton/pallets/linear-release/src/tests.rs +++ b/polimec-skeleton/pallets/linear-release/src/tests.rs @@ -19,999 +19,999 @@ where T: pallet::Config, { // Its ok for this to fail because the user may already have no schedules. - let _result = Vesting::vest(Some(account).into()); + let _result = Vesting::vest(Some(account).into(), LockType::Participation(0)); assert!(!>::contains_key(account)); } -#[test] -fn check_vesting_status() { - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - let user1_free_balance = Balances::free_balance(&1); - let user2_free_balance = Balances::free_balance(&2); - let user12_free_balance = Balances::free_balance(&12); - assert_eq!(user1_free_balance, ED * 5); // Account 1 has free balance - assert_eq!(user2_free_balance, ED * 1); // Account 2 has free balance - assert_eq!(user12_free_balance, ED * 5); // Account 12 has free balance - let user1_vesting_schedule = VestingInfo::new( - ED * 5, - 128, // Vesting over 10 blocks - 0, - ); - let user2_vesting_schedule = VestingInfo::new( - ED * 20, - ED, // Vesting over 19 blocks - 10, - ); - let user12_vesting_schedule = VestingInfo::new( - ED * 5, - 64, // Vesting over 20 blocks - 10, - ); - assert_eq!(Vesting::vesting(&1).unwrap(), vec![user1_vesting_schedule]); // Account 1 has a vesting schedule - assert_eq!(Vesting::vesting(&2).unwrap(), vec![user2_vesting_schedule]); // Account 2 has a vesting schedule - assert_eq!(Vesting::vesting(&12).unwrap(), vec![user12_vesting_schedule]); // Account 12 has a vesting schedule - - // Account 1 has only 128 units vested from their illiquid ED * 5 units at block 1 - assert_eq!(Vesting::vesting_balance(&1), Some(128 * 9)); - // Account 2 has their full balance locked - assert_eq!(Vesting::vesting_balance(&2), Some(user2_free_balance)); - // Account 12 has only their illiquid funds locked - assert_eq!(Vesting::vesting_balance(&12), Some(user12_free_balance)); - - System::set_block_number(10); - assert_eq!(System::block_number(), 10); - - // Account 1 has fully vested by block 10 - assert_eq!(Vesting::vesting_balance(&1), Some(0)); - // Account 2 has started vesting by block 10 - assert_eq!(Vesting::vesting_balance(&2), Some(user2_free_balance)); - // Account 12 has started vesting by block 10 - assert_eq!(Vesting::vesting_balance(&12), Some(user12_free_balance)); - - System::set_block_number(30); - assert_eq!(System::block_number(), 30); - - assert_eq!(Vesting::vesting_balance(&1), Some(0)); // Account 1 is still fully vested, and not negative - assert_eq!(Vesting::vesting_balance(&2), Some(0)); // Account 2 has fully vested by block 30 - assert_eq!(Vesting::vesting_balance(&12), Some(0)); // Account 2 has fully vested by block 30 - - // Once we unlock the funds, they are removed from storage. - vest_and_assert_no_vesting::(1); - vest_and_assert_no_vesting::(2); - vest_and_assert_no_vesting::(12); - }); -} - -#[test] -fn check_vesting_status_for_multi_schedule_account() { - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - assert_eq!(System::block_number(), 1); - let sched0 = VestingInfo::new( - ED * 20, - ED, // Vesting over 20 blocks - 10, - ); - // Account 2 already has a vesting schedule. - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); - - // Account 2's free balance is from sched0. - let free_balance = Balances::free_balance(&2); - assert_eq!(free_balance, ED * (1)); - assert_eq!(Vesting::vesting_balance(&2), Some(free_balance)); - - // Add a 2nd schedule that is already unlocking by block #1. - let sched1 = VestingInfo::new( - ED * 10, - ED, // Vesting over 10 blocks - 0, - ); - assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1)); - // Free balance is equal to the two existing schedules total amount. - let free_balance = Balances::free_balance(&2); - assert_eq!(free_balance, ED * (10 + 20)); - // The most recently added schedule exists. - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); - // sched1 has free funds at block #1, but nothing else. - assert_eq!(Vesting::vesting_balance(&2), Some(free_balance - sched1.per_block())); - - // Add a 3rd schedule. - let sched2 = VestingInfo::new( - ED * 30, - ED, // Vesting over 30 blocks - 5, - ); - assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched2)); - - System::set_block_number(9); - // Free balance is equal to the 3 existing schedules total amount. - let free_balance = Balances::free_balance(&2); - assert_eq!(free_balance, ED * (10 + 20 + 30)); - // sched1 and sched2 are freeing funds at block #9. - assert_eq!(Vesting::vesting_balance(&2), Some(free_balance - sched1.per_block() * 9 - sched2.per_block() * 4)); - - System::set_block_number(20); - // At block #20 sched1 is fully unlocked while sched2 and sched0 are partially unlocked. - assert_eq!( - Vesting::vesting_balance(&2), - Some(free_balance - sched1.locked() - sched2.per_block() * 15 - sched0.per_block() * 10) - ); - - System::set_block_number(30); - // At block #30 sched0 and sched1 are fully unlocked while sched2 is partially unlocked. - assert_eq!( - Vesting::vesting_balance(&2), - Some(free_balance - sched1.locked() - sched2.per_block() * 25 - sched0.locked()) - ); - - // At block #35 sched2 fully unlocks and thus all schedules funds are unlocked. - System::set_block_number(35); - assert_eq!(Vesting::vesting_balance(&2), Some(0)); - // Since we have not called any extrinsics that would unlock funds the schedules - // are still in storage, - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); - // but once we unlock the funds, they are removed from storage. - vest_and_assert_no_vesting::(2); - }); -} - -#[test] -fn unvested_balance_should_not_transfer() { - ExtBuilder::default().existential_deposit(10).build().execute_with(|| { - let user1_free_balance = Balances::free_balance(&1); - assert_eq!(user1_free_balance, 100); // Account 1 has free balance - // Account 1 has only 5 units vested at block 1 (plus 50 unvested) - assert_eq!(Vesting::vesting_balance(&1), Some(45)); - println!("{}", Balances::balance_on_hold(&LockType::Evaluation(0), &1)); - // Account 1 cannot send more than vested amount... - assert_noop!(Balances::transfer_allow_death(Some(1).into(), 2, 56), TokenError::Frozen); - }); -} - -#[test] -fn vested_balance_should_transfer() { - ExtBuilder::default().existential_deposit(10).build().execute_with(|| { - let user1_free_balance = Balances::free_balance(&1); - assert_eq!(user1_free_balance, 100); // Account 1 has free balance - // Account 1 has only 5 units vested at block 1 (plus 50 unvested) - assert_eq!(Vesting::vesting_balance(&1), Some(45)); - assert_ok!(Vesting::vest(Some(1).into())); - assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 55)); - }); -} - -#[test] -fn vested_balance_should_transfer_with_multi_sched() { - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - let sched0 = VestingInfo::new(5 * ED, 128, 0); - assert_ok!(Vesting::vested_transfer(Some(13).into(), 1, sched0)); - // Total 10*ED locked for all the schedules. - assert_eq!(Vesting::vesting(&1).unwrap(), vec![sched0, sched0]); - - let user1_free_balance = Balances::free_balance(&1); - assert_eq!(user1_free_balance, 3840); // Account 1 has free balance - - // Account 1 has only 256 units unlocking at block 1 (plus 1280 already fee). - assert_eq!(Vesting::vesting_balance(&1), Some(2304)); - assert_ok!(Vesting::vest(Some(1).into())); - assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 1536)); - }); -} - -#[test] -fn non_vested_cannot_vest() { - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - assert!(!>::contains_key(4)); - assert_noop!(Vesting::vest(Some(4).into()), Error::::NotVesting); - }); -} - -#[test] -fn vested_balance_should_transfer_using_vest_other() { - ExtBuilder::default().existential_deposit(10).build().execute_with(|| { - let user1_free_balance = Balances::free_balance(&1); - assert_eq!(user1_free_balance, 100); // Account 1 has free balance - // Account 1 has only 5 units vested at block 1 (plus 50 unvested) - assert_eq!(Vesting::vesting_balance(&1), Some(45)); - assert_ok!(Vesting::vest_other(Some(2).into(), 1)); - assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 55)); - }); -} - -#[test] -fn vested_balance_should_transfer_using_vest_other_with_multi_sched() { - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - let sched0 = VestingInfo::new(5 * ED, 128, 0); - assert_ok!(Vesting::vested_transfer(Some(13).into(), 1, sched0)); - // Total of 10*ED of locked for all the schedules. - assert_eq!(Vesting::vesting(&1).unwrap(), vec![sched0, sched0]); - - let user1_free_balance = Balances::free_balance(&1); - assert_eq!(user1_free_balance, 3840); // Account 1 has free balance - - // Account 1 has only 256 units unlocking at block 1 (plus 1280 already free). - assert_eq!(Vesting::vesting_balance(&1), Some(2304)); - assert_ok!(Vesting::vest_other(Some(2).into(), 1)); - assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 1536)); - }); -} - -#[test] -fn non_vested_cannot_vest_other() { - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - assert!(!>::contains_key(4)); - assert_noop!(Vesting::vest_other(Some(3).into(), 4), Error::::NotVesting); - }); -} - -#[test] -fn extra_balance_should_transfer() { - ExtBuilder::default().existential_deposit(10).build().execute_with(|| { - assert_ok!(Balances::transfer_allow_death(Some(3).into(), 1, 100)); - assert_ok!(Balances::transfer_allow_death(Some(3).into(), 2, 100)); - - let user1_free_balance = Balances::free_balance(&1); - assert_eq!(user1_free_balance, 150); // Account 1 has 100 more free balance than normal - - let user2_free_balance = Balances::free_balance(&2); - assert_eq!(user2_free_balance, 110); // Account 2 has 100 more free balance than normal - - // Account 1 has only 5 units vested at block 1 (plus 150 unvested) - assert_eq!(Vesting::vesting_balance(&1), Some(45)); - assert_ok!(Vesting::vest(Some(1).into())); - let user1_free_balance2 = Balances::free_balance(&1); - assert_eq!(user1_free_balance2, 195); // Account 1 has 100 more free balance than normal - assert_ok!(Balances::transfer_allow_death(Some(1).into(), 3, 155)); // Account 1 can send extra units gained - - // Account 2 has no units vested at block 1, but gained 100 - assert_eq!(Vesting::vesting_balance(&2), Some(110)); - assert_ok!(Vesting::vest(Some(2).into())); - assert_ok!(Balances::transfer_allow_death(Some(2).into(), 3, 100)); // Account 2 can send extra - // units gained - }); -} - -#[test] -fn liquid_funds_should_transfer_with_delayed_vesting() { - ExtBuilder::default().existential_deposit(256).build().execute_with(|| { - let user12_free_balance = Balances::free_balance(&12); - - assert_eq!(user12_free_balance, 2560); // Account 12 has free balance - // Account 12 has liquid funds - assert_eq!(Vesting::vesting_balance(&12), Some(user12_free_balance - 256 * 5)); - - // Account 12 has delayed vesting - let user12_vesting_schedule = VestingInfo::new( - 256 * 5, - 64, // Vesting over 20 blocks - 10, - ); - assert_eq!(Vesting::vesting(&12).unwrap(), vec![user12_vesting_schedule]); - - // Account 12 can still send liquid funds - assert_ok!(Balances::transfer_allow_death(Some(12).into(), 3, 256 * 5)); - }); -} - -#[test] -fn vested_transfer_works() { - ExtBuilder::default().existential_deposit(256).build().execute_with(|| { - let user3_free_balance = Balances::free_balance(&3); - let user4_free_balance = Balances::free_balance(&4); - assert_eq!(user3_free_balance, 256 * 30); - assert_eq!(user4_free_balance, 256 * 40); - // Account 4 should not have any vesting yet. - assert_eq!(Vesting::vesting(&4), None); - // Make the schedule for the new transfer. - let new_vesting_schedule = VestingInfo::new( - 256 * 5, - 64, // Vesting over 20 blocks - 10, - ); - assert_ok!(Vesting::vested_transfer(Some(3).into(), 4, new_vesting_schedule)); - // Now account 4 should have vesting. - assert_eq!(Vesting::vesting(&4).unwrap(), vec![new_vesting_schedule]); - // Ensure the transfer happened correctly. - let user3_free_balance_updated = Balances::free_balance(&3); - assert_eq!(user3_free_balance_updated, 256 * 25); - let user4_free_balance_updated = Balances::free_balance(&4); - assert_eq!(user4_free_balance_updated, 256 * 45); - // Account 4 has 5 * 256 locked. - assert_eq!(Vesting::vesting_balance(&4), Some(256 * 5)); - - System::set_block_number(20); - assert_eq!(System::block_number(), 20); - - // Account 4 has 5 * 64 units vested by block 20. - assert_eq!(Vesting::vesting_balance(&4), Some(10 * 64)); - - System::set_block_number(30); - assert_eq!(System::block_number(), 30); - - // Account 4 has fully vested, - assert_eq!(Vesting::vesting_balance(&4), Some(0)); - // and after unlocking its schedules are removed from storage. - vest_and_assert_no_vesting::(4); - }); -} - -#[test] -fn vested_transfer_correctly_fails() { - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - let user2_free_balance = Balances::free_balance(&2); - let user4_free_balance = Balances::free_balance(&4); - assert_eq!(user2_free_balance, ED * 20); - assert_eq!(user4_free_balance, ED * 40); - - // Account 2 should already have a vesting schedule. - let user2_vesting_schedule = VestingInfo::new( - ED * 20, - ED, // Vesting over 20 blocks - 10, - ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![user2_vesting_schedule]); - - // Fails due to too low transfer amount. - let new_vesting_schedule_too_low = VestingInfo::new(::MinVestedTransfer::get() - 1, 64, 10); - assert_noop!( - Vesting::vested_transfer(Some(3).into(), 4, new_vesting_schedule_too_low), - Error::::AmountLow, - ); - - // `per_block` is 0, which would result in a schedule with infinite duration. - let schedule_per_block_0 = VestingInfo::new(::MinVestedTransfer::get(), 0, 10); - assert_noop!( - Vesting::vested_transfer(Some(13).into(), 4, schedule_per_block_0), - Error::::InvalidScheduleParams, - ); - - // `locked` is 0. - let schedule_locked_0 = VestingInfo::new(0, 1, 10); - assert_noop!(Vesting::vested_transfer(Some(3).into(), 4, schedule_locked_0), Error::::AmountLow,); - - // Free balance has not changed. - assert_eq!(user2_free_balance, Balances::free_balance(&2)); - assert_eq!(user4_free_balance, Balances::free_balance(&4)); - // Account 4 has no schedules. - vest_and_assert_no_vesting::(4); - }); -} - -#[test] -fn vested_transfer_allows_max_schedules() { - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - let mut user_4_free_balance = Balances::free_balance(&4); - let max_schedules = ::MAX_VESTING_SCHEDULES; - let sched = VestingInfo::new( - ::MinVestedTransfer::get(), - 1, // Vest over 2 * 256 blocks. - 10, - ); - - // Add max amount schedules to user 4. - for _ in 0..max_schedules { - assert_ok!(Vesting::vested_transfer(Some(13).into(), 4, sched)); - } - - // The schedules count towards vesting balance - let transferred_amount = ::MinVestedTransfer::get() * max_schedules as u64; - assert_eq!(Vesting::vesting_balance(&4), Some(transferred_amount)); - // and free balance. - user_4_free_balance += transferred_amount; - assert_eq!(Balances::free_balance(&4), user_4_free_balance); - - // Cannot insert a 4th vesting schedule when `MaxVestingSchedules` === 3, - assert_noop!(Vesting::vested_transfer(Some(3).into(), 4, sched), Error::::AtMaxVestingSchedules,); - // so the free balance does not change. - assert_eq!(Balances::free_balance(&4), user_4_free_balance); - - // Account 4 has fully vested when all the schedules end, - System::set_block_number(::MinVestedTransfer::get() + sched.starting_block()); - assert_eq!(Vesting::vesting_balance(&4), Some(0)); - // and after unlocking its schedules are removed from storage. - vest_and_assert_no_vesting::(4); - }); -} - -#[test] -fn force_vested_transfer_works() { - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - let user3_free_balance = Balances::free_balance(&3); - let user4_free_balance = Balances::free_balance(&4); - assert_eq!(user3_free_balance, ED * 30); - assert_eq!(user4_free_balance, ED * 40); - // Account 4 should not have any vesting yet. - assert_eq!(Vesting::vesting(&4), None); - // Make the schedule for the new transfer. - let new_vesting_schedule = VestingInfo::new( - ED * 5, - 64, // Vesting over 20 blocks - 10, - ); - - assert_noop!(Vesting::force_vested_transfer(Some(4).into(), 3, 4, new_vesting_schedule), BadOrigin); - assert_ok!(Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, new_vesting_schedule)); - // Now account 4 should have vesting. - assert_eq!(Vesting::vesting(&4).unwrap()[0], new_vesting_schedule); - assert_eq!(Vesting::vesting(&4).unwrap().len(), 1); - // Ensure the transfer happened correctly. - let user3_free_balance_updated = Balances::free_balance(&3); - assert_eq!(user3_free_balance_updated, ED * 25); - let user4_free_balance_updated = Balances::free_balance(&4); - assert_eq!(user4_free_balance_updated, ED * 45); - // Account 4 has 5 * ED locked. - assert_eq!(Vesting::vesting_balance(&4), Some(ED * 5)); - - System::set_block_number(20); - assert_eq!(System::block_number(), 20); - - // Account 4 has 5 * 64 units vested by block 20. - assert_eq!(Vesting::vesting_balance(&4), Some(10 * 64)); - - System::set_block_number(30); - assert_eq!(System::block_number(), 30); - - // Account 4 has fully vested, - assert_eq!(Vesting::vesting_balance(&4), Some(0)); - // and after unlocking its schedules are removed from storage. - vest_and_assert_no_vesting::(4); - }); -} - -#[test] -fn force_vested_transfer_correctly_fails() { - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - let user2_free_balance = Balances::free_balance(&2); - let user4_free_balance = Balances::free_balance(&4); - assert_eq!(user2_free_balance, ED * 21); - assert_eq!(user4_free_balance, ED * 40); - // Account 2 should already have a vesting schedule. - let user2_vesting_schedule = VestingInfo::new( - ED * 20, - ED, // Vesting over 20 blocks - 10, - ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![user2_vesting_schedule]); - - // Too low transfer amount. - let new_vesting_schedule_too_low = VestingInfo::new(::MinVestedTransfer::get() - 1, 64, 10); - assert_noop!( - Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, new_vesting_schedule_too_low), - Error::::AmountLow, - ); - - // `per_block` is 0. - let schedule_per_block_0 = VestingInfo::new(::MinVestedTransfer::get(), 0, 10); - assert_noop!( - Vesting::force_vested_transfer(RawOrigin::Root.into(), 13, 4, schedule_per_block_0), - Error::::InvalidScheduleParams, - ); - - // `locked` is 0. - let schedule_locked_0 = VestingInfo::new(0, 1, 10); - assert_noop!( - Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, schedule_locked_0), - Error::::AmountLow, - ); - - // Verify no currency transfer happened. - assert_eq!(user2_free_balance, Balances::free_balance(&2)); - assert_eq!(user4_free_balance, Balances::free_balance(&4)); - // Account 4 has no schedules. - vest_and_assert_no_vesting::(4); - }); -} - -#[test] -fn force_vested_transfer_allows_max_schedules() { - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - let mut user_4_free_balance = Balances::free_balance(&4); - let max_schedules = ::MAX_VESTING_SCHEDULES; - let sched = VestingInfo::new( - ::MinVestedTransfer::get(), - 1, // Vest over 2 * 256 blocks. - 10, - ); - - // Add max amount schedules to user 4. - for _ in 0..max_schedules { - assert_ok!(Vesting::force_vested_transfer(RawOrigin::Root.into(), 13, 4, sched)); - } - - // The schedules count towards vesting balance. - let transferred_amount = ::MinVestedTransfer::get() * max_schedules as u64; - assert_eq!(Vesting::vesting_balance(&4), Some(transferred_amount)); - // and free balance. - user_4_free_balance += transferred_amount; - assert_eq!(Balances::free_balance(&4), user_4_free_balance); - - // Cannot insert a 4th vesting schedule when `MaxVestingSchedules` === 3 - assert_noop!( - Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, sched), - Error::::AtMaxVestingSchedules, - ); - // so the free balance does not change. - assert_eq!(Balances::free_balance(&4), user_4_free_balance); - - // Account 4 has fully vested when all the schedules end, - System::set_block_number(::MinVestedTransfer::get() + 10); - assert_eq!(Vesting::vesting_balance(&4), Some(0)); - // and after unlocking its schedules are removed from storage. - vest_and_assert_no_vesting::(4); - }); -} - -#[test] -fn merge_schedules_that_have_not_started() { - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - // Account 2 should already have a vesting schedule. - let sched0 = VestingInfo::new( - ED * 20, - ED, // Vest over 20 blocks. - 10, - ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); - assert_eq!(Balances::usable_balance(&2), 0); - - // Add a schedule that is identical to the one that already exists. - assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched0)); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched0]); - assert_eq!(Balances::usable_balance(&2), 0); - assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); - - // Since we merged identical schedules, the new schedule finishes at the same - // time as the original, just with double the amount. - let sched1 = VestingInfo::new( - sched0.locked() * 2, - sched0.per_block() * 2, - 10, // Starts at the block the schedules are merged/ - ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched1]); - - assert_eq!(Balances::usable_balance(&2), 0); - }); -} - -#[test] -fn merge_ongoing_schedules() { - // Merging two schedules that have started will vest both before merging. - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - // Account 2 should already have a vesting schedule. - let sched0 = VestingInfo::new( - ED * 20, - ED, // Vest over 20 blocks. - 10, - ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); - - let sched1 = VestingInfo::new( - ED * 10, - ED, // Vest over 10 blocks. - sched0.starting_block() + 5, // Start at block 15. - ); - assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1)); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); - - // Got to half way through the second schedule where both schedules are actively vesting. - let cur_block = 20; - System::set_block_number(cur_block); - - // Account 2 has no usable balances prior to the merge because they have not unlocked - // with `vest` yet. - assert_eq!(Balances::usable_balance(&2), 0); - - assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); - - // Merging schedules un-vests all pre-existing schedules prior to merging, which is - // reflected in account 2's updated usable balance. - let sched0_vested_now = sched0.per_block() * (cur_block - sched0.starting_block()); - let sched1_vested_now = sched1.per_block() * (cur_block - sched1.starting_block()); - assert_eq!(Balances::usable_balance(&2), sched0_vested_now + sched1_vested_now); - - // The locked amount is the sum of what both schedules have locked at the current block. - let sched2_locked = - sched1.locked_at::(cur_block).saturating_add(sched0.locked_at::(cur_block)); - // End block of the new schedule is the greater of either merged schedule. - let sched2_end = sched1.ending_block_as_balance::().max(sched0.ending_block_as_balance::()); - let sched2_duration = sched2_end - cur_block; - // Based off the new schedules total locked and its duration, we can calculate the - // amount to unlock per block. - let sched2_per_block = sched2_locked / sched2_duration; - - let sched2 = VestingInfo::new(sched2_locked, sched2_per_block, cur_block); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2]); - - // And just to double check, we assert the new merged schedule we be cleaned up as expected. - System::set_block_number(30); - vest_and_assert_no_vesting::(2); - }); -} - -#[test] -fn merging_shifts_other_schedules_index() { - // Schedules being merged are filtered out, schedules to the right of any merged - // schedule shift left and the merged schedule is always last. - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - let sched0 = VestingInfo::new( - ED * 10, - ED, // Vesting over 10 blocks. - 10, - ); - let sched1 = VestingInfo::new( - ED * 11, - ED, // Vesting over 11 blocks. - 11, - ); - let sched2 = VestingInfo::new( - ED * 12, - ED, // Vesting over 12 blocks. - 12, - ); - - // Account 3 starts out with no schedules, - assert_eq!(Vesting::vesting(&3), None); - // and some usable balance. - let usable_balance = Balances::usable_balance(&3); - assert_eq!(usable_balance, 30 * ED); - - let cur_block = 1; - assert_eq!(System::block_number(), cur_block); - - // Transfer the above 3 schedules to account 3. - assert_ok!(Vesting::vested_transfer(Some(4).into(), 3, sched0)); - assert_ok!(Vesting::vested_transfer(Some(4).into(), 3, sched1)); - assert_ok!(Vesting::vested_transfer(Some(4).into(), 3, sched2)); - - // With no schedules vested or merged they are in the order they are created - assert_eq!(Vesting::vesting(&3).unwrap(), vec![sched0, sched1, sched2]); - // and the usable balance has not changed. - assert_eq!(usable_balance, Balances::usable_balance(&3)); - - assert_ok!(Vesting::merge_schedules(Some(3).into(), 0, 2)); - - // Create the merged schedule of sched0 & sched2. - // The merged schedule will have the max possible starting block, - let sched3_start = sched1.starting_block().max(sched2.starting_block()); - // `locked` equal to the sum of the two schedules locked through the current block, - let sched3_locked = sched2.locked_at::(cur_block) + sched0.locked_at::(cur_block); - // and will end at the max possible block. - let sched3_end = sched2.ending_block_as_balance::().max(sched0.ending_block_as_balance::()); - let sched3_duration = sched3_end - sched3_start; - let sched3_per_block = sched3_locked / sched3_duration; - let sched3 = VestingInfo::new(sched3_locked, sched3_per_block, sched3_start); - - // The not touched schedule moves left and the new merged schedule is appended. - assert_eq!(Vesting::vesting(&3).unwrap(), vec![sched1, sched3]); - // The usable balance hasn't changed since none of the schedules have started. - assert_eq!(Balances::usable_balance(&3), usable_balance); - }); -} - -#[test] -fn merge_ongoing_and_yet_to_be_started_schedules() { - // Merge an ongoing schedule that has had `vest` called and a schedule that has not already - // started. - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - // Account 2 should already have a vesting schedule. - let sched0 = VestingInfo::new( - ED * 20, - ED, // Vesting over 20 blocks - 10, - ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); - - // Fast forward to half way through the life of sched1. - let mut cur_block = (sched0.starting_block() + sched0.ending_block_as_balance::()) / 2; - assert_eq!(cur_block, 20); - System::set_block_number(cur_block); - - // Prior to vesting there is no usable balance. - let mut usable_balance = 0; - assert_eq!(Balances::usable_balance(&2), usable_balance); - // Vest the current schedules (which is just sched0 now). - Vesting::vest(Some(2).into()).unwrap(); - - // After vesting the usable balance increases by the unlocked amount. - let sched0_vested_now = sched0.locked() - sched0.locked_at::(cur_block); - usable_balance += sched0_vested_now; - assert_eq!(Balances::usable_balance(&2), usable_balance); - - // Go forward a block. - cur_block += 1; - System::set_block_number(cur_block); - - // And add a schedule that starts after this block, but before sched0 finishes. - let sched1 = VestingInfo::new( - ED * 10, - 1, // Vesting over 256 * 10 (2560) blocks - cur_block + 1, - ); - assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1)); - - // Merge the schedules before sched1 starts. - assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); - // After merging, the usable balance only changes by the amount sched0 vested since we - // last called `vest` (which is just 1 block). The usable balance is not affected by - // sched1 because it has not started yet. - usable_balance += sched0.per_block(); - assert_eq!(Balances::usable_balance(&2), usable_balance); - - // The resulting schedule will have the later starting block of the two, - let sched2_start = sched1.starting_block(); - // `locked` equal to the sum of the two schedules locked through the current block, - let sched2_locked = sched0.locked_at::(cur_block) + sched1.locked_at::(cur_block); - // and will end at the max possible block. - let sched2_end = sched0.ending_block_as_balance::().max(sched1.ending_block_as_balance::()); - let sched2_duration = sched2_end - sched2_start; - let sched2_per_block = sched2_locked / sched2_duration; - - let sched2 = VestingInfo::new(sched2_locked, sched2_per_block, sched2_start); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2]); - }); -} - -#[test] -fn merge_finished_and_ongoing_schedules() { - // If a schedule finishes by the current block we treat the ongoing schedule, - // without any alterations, as the merged one. - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - // Account 2 should already have a vesting schedule. - let sched0 = VestingInfo::new( - ED * 20, - ED, // Vesting over 20 blocks. - 10, - ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); - - let sched1 = VestingInfo::new( - ED * 40, - ED, // Vesting over 40 blocks. - 10, - ); - assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1)); - - // Transfer a 3rd schedule, so we can demonstrate how schedule indices change. - // (We are not merging this schedule.) - let sched2 = VestingInfo::new( - ED * 30, - ED, // Vesting over 30 blocks. - 10, - ); - assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched2)); - - // The schedules are in expected order prior to merging. - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); - - // Fast forward to sched0's end block. - let cur_block = sched0.ending_block_as_balance::(); - System::set_block_number(cur_block); - assert_eq!(System::block_number(), 30); - - // Prior to `merge_schedules` and with no vest/vest_other called the user has no usable - // balance. - assert_eq!(Balances::usable_balance(&2), 0); - assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); - - // sched2 is now the first, since sched0 & sched1 get filtered out while "merging". - // sched1 gets treated like the new merged schedule by getting pushed onto back - // of the vesting schedules vec. Note: sched0 finished at the current block. - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2, sched1]); - - // sched0 has finished, so its funds are fully unlocked. - let sched0_unlocked_now = sched0.locked(); - // The remaining schedules are ongoing, so their funds are partially unlocked. - let sched1_unlocked_now = sched1.locked() - sched1.locked_at::(cur_block); - let sched2_unlocked_now = sched2.locked() - sched2.locked_at::(cur_block); - - // Since merging also vests all the schedules, the users usable balance after merging - // includes all pre-existing schedules unlocked through the current block, including - // schedules not merged. - assert_eq!(Balances::usable_balance(&2), sched0_unlocked_now + sched1_unlocked_now + sched2_unlocked_now); - }); -} - -#[test] -fn merge_finishing_schedules_does_not_create_a_new_one() { - // If both schedules finish by the current block we don't create new one - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - // Account 2 should already have a vesting schedule. - let sched0 = VestingInfo::new( - ED * 20, - ED, // 20 block duration. - 10, - ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); - - // Create sched1 and transfer it to account 2. - let sched1 = VestingInfo::new( - ED * 30, - ED, // 30 block duration. - 10, - ); - assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched1)); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); - - let all_scheds_end = - sched0.ending_block_as_balance::().max(sched1.ending_block_as_balance::()); - - assert_eq!(all_scheds_end, 40); - System::set_block_number(all_scheds_end); - - // Prior to merge_schedules and with no vest/vest_other called the user has no usable - // balance. - assert_eq!(Balances::usable_balance(&2), 0); - - // Merge schedule 0 and 1. - assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); - // The user no longer has any more vesting schedules because they both ended at the - // block they where merged, - assert!(!>::contains_key(&2)); - // and their usable balance has increased by the total amount locked in the merged - // schedules. - assert_eq!(Balances::usable_balance(&2), sched0.locked() + sched1.locked()); - }); -} - -#[test] -fn merge_finished_and_yet_to_be_started_schedules() { - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - // Account 2 should already have a vesting schedule. - let sched0 = VestingInfo::new( - ED * 20, - ED, // 20 block duration. - 10, // Ends at block 30 - ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); - - let sched1 = VestingInfo::new( - ED * 30, - ED * 2, // 30 block duration. - 35, - ); - assert_ok!(Vesting::vested_transfer(Some(13).into(), 2, sched1)); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); - - let sched2 = VestingInfo::new( - ED * 40, - ED, // 40 block duration. - 30, - ); - // Add a 3rd schedule to demonstrate how sched1 shifts. - assert_ok!(Vesting::vested_transfer(Some(13).into(), 2, sched2)); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); - - System::set_block_number(30); - - // At block 30, sched0 has finished unlocking while sched1 and sched2 are still fully - // locked, - assert_eq!(Vesting::vesting_balance(&2), Some(sched1.locked() + sched2.locked())); - // but since we have not vested usable balance is still 0. - assert_eq!(Balances::usable_balance(&2), 0); - - // Merge schedule 0 and 1. - assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); - - // sched0 is removed since it finished, and sched1 is removed and then pushed on the back - // because it is treated as the merged schedule - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2, sched1]); - - // The usable balance is updated because merging fully unlocked sched0. - assert_eq!(Balances::usable_balance(&2), sched0.locked()); - }); -} - -#[test] -fn merge_schedules_throws_proper_errors() { - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - // Account 2 should already have a vesting schedule. - let sched0 = VestingInfo::new( - ED * 20, - ED, // 20 block duration. - 10, - ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); - - // Account 2 only has 1 vesting schedule. - assert_noop!(Vesting::merge_schedules(Some(2).into(), 0, 1), Error::::ScheduleIndexOutOfBounds); - - // Account 4 has 0 vesting schedules. - assert_eq!(Vesting::vesting(&4), None); - assert_noop!(Vesting::merge_schedules(Some(4).into(), 0, 1), Error::::NotVesting); - - // There are enough schedules to merge but an index is non-existent. - Vesting::vested_transfer(Some(3).into(), 2, sched0).unwrap(); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched0]); - assert_noop!(Vesting::merge_schedules(Some(2).into(), 0, 2), Error::::ScheduleIndexOutOfBounds); - - // It is a storage noop with no errors if the indexes are the same. - assert_storage_noop!(Vesting::merge_schedules(Some(2).into(), 0, 0).unwrap()); - }); -} - -#[test] -fn merge_vesting_handles_per_block_0() { - ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - let sched0 = VestingInfo::new( - ED, 0, // Vesting over 256 blocks. - 1, - ); - assert_eq!(sched0.ending_block_as_balance::(), 257); - let sched1 = VestingInfo::new( - ED * 2, - 0, // Vesting over 512 blocks. - 10, - ); - assert_eq!(sched1.ending_block_as_balance::(), 512u64 + 10); - - let merged = VestingInfo::new(764, 1, 10); - assert_eq!(Vesting::merge_vesting_info(5, sched0, sched1), Some(merged)); - }); -} - -#[test] -fn vesting_info_validate_works() { - let min_transfer = ::MinVestedTransfer::get(); - // Does not check for min transfer. - assert_eq!(VestingInfo::new(min_transfer - 1, 1u64, 10u64).is_valid(), true); - - // `locked` cannot be 0. - assert_eq!(VestingInfo::new(0, 1u64, 10u64).is_valid(), false); - - // `per_block` cannot be 0. - assert_eq!(VestingInfo::new(min_transfer + 1, 0u64, 10u64).is_valid(), false); - - // With valid inputs it does not error. - assert_eq!(VestingInfo::new(min_transfer, 1u64, 10u64).is_valid(), true); -} - -#[test] -fn vesting_info_ending_block_as_balance_works() { - // Treats `per_block` 0 as 1. - let per_block_0 = VestingInfo::new(256u32, 0u32, 10u32); - assert_eq!(per_block_0.ending_block_as_balance::(), 256 + 10); - - // `per_block >= locked` always results in a schedule ending the block after it starts - let per_block_gt_locked = VestingInfo::new(256u32, 256 * 2u32, 10u32); - assert_eq!(per_block_gt_locked.ending_block_as_balance::(), 1 + per_block_gt_locked.starting_block()); - let per_block_eq_locked = VestingInfo::new(256u32, 256u32, 10u32); - assert_eq!( - per_block_gt_locked.ending_block_as_balance::(), - per_block_eq_locked.ending_block_as_balance::() - ); - - // Correctly calcs end if `locked % per_block != 0`. (We need a block to unlock the remainder). - let imperfect_per_block = VestingInfo::new(256u32, 250u32, 10u32); - assert_eq!(imperfect_per_block.ending_block_as_balance::(), imperfect_per_block.starting_block() + 2u32,); - assert_eq!(imperfect_per_block.locked_at::(imperfect_per_block.ending_block_as_balance::()), 0); -} - -#[test] -fn per_block_works() { - let per_block_0 = VestingInfo::new(256u32, 0u32, 10u32); - assert_eq!(per_block_0.per_block(), 1u32); - assert_eq!(per_block_0.raw_per_block(), 0u32); - - let per_block_1 = VestingInfo::new(256u32, 1u32, 10u32); - assert_eq!(per_block_1.per_block(), 1u32); - assert_eq!(per_block_1.raw_per_block(), 1u32); -} - -// When an accounts free balance + schedule.locked is less than ED, the vested transfer will fail. -#[test] -fn vested_transfer_less_than_existential_deposit_fails() { - ExtBuilder::default().existential_deposit(4 * ED).build().execute_with(|| { - // MinVestedTransfer is less the ED. - assert!(::Currency::minimum_balance() > ::MinVestedTransfer::get()); - - let sched = VestingInfo::new(::MinVestedTransfer::get() as u64, 1u64, 10u64); - // The new account balance with the schedule's locked amount would be less than ED. - assert!(Balances::free_balance(&99) + sched.locked() < ::Currency::minimum_balance()); - - // vested_transfer fails. - assert_noop!(Vesting::vested_transfer(Some(3).into(), 99, sched), TokenError::BelowMinimum,); - // force_vested_transfer fails. - assert_noop!(Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 99, sched), TokenError::BelowMinimum,); - }); -} +// #[test] +// fn check_vesting_status() { +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// let user1_free_balance = Balances::free_balance(&1); +// let user2_free_balance = Balances::free_balance(&2); +// let user12_free_balance = Balances::free_balance(&12); +// assert_eq!(user1_free_balance, ED * 5); // Account 1 has free balance +// assert_eq!(user2_free_balance, ED * 1); // Account 2 has free balance +// assert_eq!(user12_free_balance, ED * 5); // Account 12 has free balance +// let user1_vesting_schedule = VestingInfo::new( +// ED * 5, +// 128, // Vesting over 10 blocks +// 0, +// ); +// let user2_vesting_schedule = VestingInfo::new( +// ED * 20, +// ED, // Vesting over 19 blocks +// 10, +// ); +// let user12_vesting_schedule = VestingInfo::new( +// ED * 5, +// 64, // Vesting over 20 blocks +// 10, +// ); +// assert_eq!(Vesting::vesting(&1).unwrap(), vec![user1_vesting_schedule]); // Account 1 has a vesting schedule +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![user2_vesting_schedule]); // Account 2 has a vesting schedule +// assert_eq!(Vesting::vesting(&12).unwrap(), vec![user12_vesting_schedule]); // Account 12 has a vesting schedule + +// // Account 1 has only 128 units vested from their illiquid ED * 5 units at block 1 +// assert_eq!(Vesting::vesting_balance(&1), Some(128 * 9)); +// // Account 2 has their full balance locked +// assert_eq!(Vesting::vesting_balance(&2), Some(user2_free_balance)); +// // Account 12 has only their illiquid funds locked +// assert_eq!(Vesting::vesting_balance(&12), Some(user12_free_balance)); + +// System::set_block_number(10); +// assert_eq!(System::block_number(), 10); + +// // Account 1 has fully vested by block 10 +// assert_eq!(Vesting::vesting_balance(&1), Some(0)); +// // Account 2 has started vesting by block 10 +// assert_eq!(Vesting::vesting_balance(&2), Some(user2_free_balance)); +// // Account 12 has started vesting by block 10 +// assert_eq!(Vesting::vesting_balance(&12), Some(user12_free_balance)); + +// System::set_block_number(30); +// assert_eq!(System::block_number(), 30); + +// assert_eq!(Vesting::vesting_balance(&1), Some(0)); // Account 1 is still fully vested, and not negative +// assert_eq!(Vesting::vesting_balance(&2), Some(0)); // Account 2 has fully vested by block 30 +// assert_eq!(Vesting::vesting_balance(&12), Some(0)); // Account 2 has fully vested by block 30 + +// // Once we unlock the funds, they are removed from storage. +// vest_and_assert_no_vesting::(1); +// vest_and_assert_no_vesting::(2); +// vest_and_assert_no_vesting::(12); +// }); +// } + +// #[test] +// fn check_vesting_status_for_multi_schedule_account() { +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// assert_eq!(System::block_number(), 1); +// let sched0 = VestingInfo::new( +// ED * 20, +// ED, // Vesting over 20 blocks +// 10, +// ); +// // Account 2 already has a vesting schedule. +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + +// // Account 2's free balance is from sched0. +// let free_balance = Balances::free_balance(&2); +// assert_eq!(free_balance, ED * (1)); +// assert_eq!(Vesting::vesting_balance(&2), Some(free_balance)); + +// // Add a 2nd schedule that is already unlocking by block #1. +// let sched1 = VestingInfo::new( +// ED * 10, +// ED, // Vesting over 10 blocks +// 0, +// ); +// assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1)); +// // Free balance is equal to the two existing schedules total amount. +// let free_balance = Balances::free_balance(&2); +// assert_eq!(free_balance, ED * (10 + 20)); +// // The most recently added schedule exists. +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); +// // sched1 has free funds at block #1, but nothing else. +// assert_eq!(Vesting::vesting_balance(&2), Some(free_balance - sched1.per_block())); + +// // Add a 3rd schedule. +// let sched2 = VestingInfo::new( +// ED * 30, +// ED, // Vesting over 30 blocks +// 5, +// ); +// assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched2)); + +// System::set_block_number(9); +// // Free balance is equal to the 3 existing schedules total amount. +// let free_balance = Balances::free_balance(&2); +// assert_eq!(free_balance, ED * (10 + 20 + 30)); +// // sched1 and sched2 are freeing funds at block #9. +// assert_eq!(Vesting::vesting_balance(&2), Some(free_balance - sched1.per_block() * 9 - sched2.per_block() * 4)); + +// System::set_block_number(20); +// // At block #20 sched1 is fully unlocked while sched2 and sched0 are partially unlocked. +// assert_eq!( +// Vesting::vesting_balance(&2), +// Some(free_balance - sched1.locked() - sched2.per_block() * 15 - sched0.per_block() * 10) +// ); + +// System::set_block_number(30); +// // At block #30 sched0 and sched1 are fully unlocked while sched2 is partially unlocked. +// assert_eq!( +// Vesting::vesting_balance(&2), +// Some(free_balance - sched1.locked() - sched2.per_block() * 25 - sched0.locked()) +// ); + +// // At block #35 sched2 fully unlocks and thus all schedules funds are unlocked. +// System::set_block_number(35); +// assert_eq!(Vesting::vesting_balance(&2), Some(0)); +// // Since we have not called any extrinsics that would unlock funds the schedules +// // are still in storage, +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); +// // but once we unlock the funds, they are removed from storage. +// vest_and_assert_no_vesting::(2); +// }); +// } + +// #[test] +// fn unvested_balance_should_not_transfer() { +// ExtBuilder::default().existential_deposit(10).build().execute_with(|| { +// let user1_free_balance = Balances::free_balance(&1); +// assert_eq!(user1_free_balance, 100); // Account 1 has free balance +// // Account 1 has only 5 units vested at block 1 (plus 50 unvested) +// assert_eq!(Vesting::vesting_balance(&1), Some(45)); +// println!("{}", Balances::balance_on_hold(&LockType::Evaluation(0), &1)); +// // Account 1 cannot send more than vested amount... +// assert_noop!(Balances::transfer_allow_death(Some(1).into(), 2, 56), TokenError::Frozen); +// }); +// } + +// #[test] +// fn vested_balance_should_transfer() { +// ExtBuilder::default().existential_deposit(10).build().execute_with(|| { +// let user1_free_balance = Balances::free_balance(&1); +// assert_eq!(user1_free_balance, 100); // Account 1 has free balance +// // Account 1 has only 5 units vested at block 1 (plus 50 unvested) +// assert_eq!(Vesting::vesting_balance(&1), Some(45)); +// assert_ok!(Vesting::vest(Some(1).into())); +// assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 55)); +// }); +// } + +// #[test] +// fn vested_balance_should_transfer_with_multi_sched() { +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// let sched0 = VestingInfo::new(5 * ED, 128, 0); +// assert_ok!(Vesting::vested_transfer(Some(13).into(), 1, sched0)); +// // Total 10*ED locked for all the schedules. +// assert_eq!(Vesting::vesting(&1).unwrap(), vec![sched0, sched0]); + +// let user1_free_balance = Balances::free_balance(&1); +// assert_eq!(user1_free_balance, 3840); // Account 1 has free balance + +// // Account 1 has only 256 units unlocking at block 1 (plus 1280 already fee). +// assert_eq!(Vesting::vesting_balance(&1), Some(2304)); +// assert_ok!(Vesting::vest(Some(1).into())); +// assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 1536)); +// }); +// } + +// #[test] +// fn non_vested_cannot_vest() { +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// assert!(!>::contains_key(4)); +// assert_noop!(Vesting::vest(Some(4).into()), Error::::NotVesting); +// }); +// } + +// #[test] +// fn vested_balance_should_transfer_using_vest_other() { +// ExtBuilder::default().existential_deposit(10).build().execute_with(|| { +// let user1_free_balance = Balances::free_balance(&1); +// assert_eq!(user1_free_balance, 100); // Account 1 has free balance +// // Account 1 has only 5 units vested at block 1 (plus 50 unvested) +// assert_eq!(Vesting::vesting_balance(&1), Some(45)); +// assert_ok!(Vesting::vest_other(Some(2).into(), 1)); +// assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 55)); +// }); +// } + +// #[test] +// fn vested_balance_should_transfer_using_vest_other_with_multi_sched() { +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// let sched0 = VestingInfo::new(5 * ED, 128, 0); +// assert_ok!(Vesting::vested_transfer(Some(13).into(), 1, sched0)); +// // Total of 10*ED of locked for all the schedules. +// assert_eq!(Vesting::vesting(&1).unwrap(), vec![sched0, sched0]); + +// let user1_free_balance = Balances::free_balance(&1); +// assert_eq!(user1_free_balance, 3840); // Account 1 has free balance + +// // Account 1 has only 256 units unlocking at block 1 (plus 1280 already free). +// assert_eq!(Vesting::vesting_balance(&1), Some(2304)); +// assert_ok!(Vesting::vest_other(Some(2).into(), 1)); +// assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 1536)); +// }); +// } + +// #[test] +// fn non_vested_cannot_vest_other() { +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// assert!(!>::contains_key(4)); +// assert_noop!(Vesting::vest_other(Some(3).into(), 4), Error::::NotVesting); +// }); +// } + +// #[test] +// fn extra_balance_should_transfer() { +// ExtBuilder::default().existential_deposit(10).build().execute_with(|| { +// assert_ok!(Balances::transfer_allow_death(Some(3).into(), 1, 100)); +// assert_ok!(Balances::transfer_allow_death(Some(3).into(), 2, 100)); + +// let user1_free_balance = Balances::free_balance(&1); +// assert_eq!(user1_free_balance, 150); // Account 1 has 100 more free balance than normal + +// let user2_free_balance = Balances::free_balance(&2); +// assert_eq!(user2_free_balance, 110); // Account 2 has 100 more free balance than normal + +// // Account 1 has only 5 units vested at block 1 (plus 150 unvested) +// assert_eq!(Vesting::vesting_balance(&1), Some(45)); +// assert_ok!(Vesting::vest(Some(1).into())); +// let user1_free_balance2 = Balances::free_balance(&1); +// assert_eq!(user1_free_balance2, 195); // Account 1 has 100 more free balance than normal +// assert_ok!(Balances::transfer_allow_death(Some(1).into(), 3, 155)); // Account 1 can send extra units gained + +// // Account 2 has no units vested at block 1, but gained 100 +// assert_eq!(Vesting::vesting_balance(&2), Some(110)); +// assert_ok!(Vesting::vest(Some(2).into())); +// assert_ok!(Balances::transfer_allow_death(Some(2).into(), 3, 100)); // Account 2 can send extra +// // units gained +// }); +// } + +// #[test] +// fn liquid_funds_should_transfer_with_delayed_vesting() { +// ExtBuilder::default().existential_deposit(256).build().execute_with(|| { +// let user12_free_balance = Balances::free_balance(&12); + +// assert_eq!(user12_free_balance, 2560); // Account 12 has free balance +// // Account 12 has liquid funds +// assert_eq!(Vesting::vesting_balance(&12), Some(user12_free_balance - 256 * 5)); + +// // Account 12 has delayed vesting +// let user12_vesting_schedule = VestingInfo::new( +// 256 * 5, +// 64, // Vesting over 20 blocks +// 10, +// ); +// assert_eq!(Vesting::vesting(&12).unwrap(), vec![user12_vesting_schedule]); + +// // Account 12 can still send liquid funds +// assert_ok!(Balances::transfer_allow_death(Some(12).into(), 3, 256 * 5)); +// }); +// } + +// #[test] +// fn vested_transfer_works() { +// ExtBuilder::default().existential_deposit(256).build().execute_with(|| { +// let user3_free_balance = Balances::free_balance(&3); +// let user4_free_balance = Balances::free_balance(&4); +// assert_eq!(user3_free_balance, 256 * 30); +// assert_eq!(user4_free_balance, 256 * 40); +// // Account 4 should not have any vesting yet. +// assert_eq!(Vesting::vesting(&4), None); +// // Make the schedule for the new transfer. +// let new_vesting_schedule = VestingInfo::new( +// 256 * 5, +// 64, // Vesting over 20 blocks +// 10, +// ); +// assert_ok!(Vesting::vested_transfer(Some(3).into(), 4, new_vesting_schedule)); +// // Now account 4 should have vesting. +// assert_eq!(Vesting::vesting(&4).unwrap(), vec![new_vesting_schedule]); +// // Ensure the transfer happened correctly. +// let user3_free_balance_updated = Balances::free_balance(&3); +// assert_eq!(user3_free_balance_updated, 256 * 25); +// let user4_free_balance_updated = Balances::free_balance(&4); +// assert_eq!(user4_free_balance_updated, 256 * 45); +// // Account 4 has 5 * 256 locked. +// assert_eq!(Vesting::vesting_balance(&4), Some(256 * 5)); + +// System::set_block_number(20); +// assert_eq!(System::block_number(), 20); + +// // Account 4 has 5 * 64 units vested by block 20. +// assert_eq!(Vesting::vesting_balance(&4), Some(10 * 64)); + +// System::set_block_number(30); +// assert_eq!(System::block_number(), 30); + +// // Account 4 has fully vested, +// assert_eq!(Vesting::vesting_balance(&4), Some(0)); +// // and after unlocking its schedules are removed from storage. +// vest_and_assert_no_vesting::(4); +// }); +// } + +// #[test] +// fn vested_transfer_correctly_fails() { +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// let user2_free_balance = Balances::free_balance(&2); +// let user4_free_balance = Balances::free_balance(&4); +// assert_eq!(user2_free_balance, ED * 20); +// assert_eq!(user4_free_balance, ED * 40); + +// // Account 2 should already have a vesting schedule. +// let user2_vesting_schedule = VestingInfo::new( +// ED * 20, +// ED, // Vesting over 20 blocks +// 10, +// ); +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![user2_vesting_schedule]); + +// // Fails due to too low transfer amount. +// let new_vesting_schedule_too_low = VestingInfo::new(::MinVestedTransfer::get() - 1, 64, 10); +// assert_noop!( +// Vesting::vested_transfer(Some(3).into(), 4, new_vesting_schedule_too_low), +// Error::::AmountLow, +// ); + +// // `per_block` is 0, which would result in a schedule with infinite duration. +// let schedule_per_block_0 = VestingInfo::new(::MinVestedTransfer::get(), 0, 10); +// assert_noop!( +// Vesting::vested_transfer(Some(13).into(), 4, schedule_per_block_0), +// Error::::InvalidScheduleParams, +// ); + +// // `locked` is 0. +// let schedule_locked_0 = VestingInfo::new(0, 1, 10); +// assert_noop!(Vesting::vested_transfer(Some(3).into(), 4, schedule_locked_0), Error::::AmountLow,); + +// // Free balance has not changed. +// assert_eq!(user2_free_balance, Balances::free_balance(&2)); +// assert_eq!(user4_free_balance, Balances::free_balance(&4)); +// // Account 4 has no schedules. +// vest_and_assert_no_vesting::(4); +// }); +// } + +// #[test] +// fn vested_transfer_allows_max_schedules() { +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// let mut user_4_free_balance = Balances::free_balance(&4); +// let max_schedules = ::MAX_VESTING_SCHEDULES; +// let sched = VestingInfo::new( +// ::MinVestedTransfer::get(), +// 1, // Vest over 2 * 256 blocks. +// 10, +// ); + +// // Add max amount schedules to user 4. +// for _ in 0..max_schedules { +// assert_ok!(Vesting::vested_transfer(Some(13).into(), 4, sched)); +// } + +// // The schedules count towards vesting balance +// let transferred_amount = ::MinVestedTransfer::get() * max_schedules as u64; +// assert_eq!(Vesting::vesting_balance(&4), Some(transferred_amount)); +// // and free balance. +// user_4_free_balance += transferred_amount; +// assert_eq!(Balances::free_balance(&4), user_4_free_balance); + +// // Cannot insert a 4th vesting schedule when `MaxVestingSchedules` === 3, +// assert_noop!(Vesting::vested_transfer(Some(3).into(), 4, sched), Error::::AtMaxVestingSchedules,); +// // so the free balance does not change. +// assert_eq!(Balances::free_balance(&4), user_4_free_balance); + +// // Account 4 has fully vested when all the schedules end, +// System::set_block_number(::MinVestedTransfer::get() + sched.starting_block()); +// assert_eq!(Vesting::vesting_balance(&4), Some(0)); +// // and after unlocking its schedules are removed from storage. +// vest_and_assert_no_vesting::(4); +// }); +// } + +// #[test] +// fn force_vested_transfer_works() { +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// let user3_free_balance = Balances::free_balance(&3); +// let user4_free_balance = Balances::free_balance(&4); +// assert_eq!(user3_free_balance, ED * 30); +// assert_eq!(user4_free_balance, ED * 40); +// // Account 4 should not have any vesting yet. +// assert_eq!(Vesting::vesting(&4), None); +// // Make the schedule for the new transfer. +// let new_vesting_schedule = VestingInfo::new( +// ED * 5, +// 64, // Vesting over 20 blocks +// 10, +// ); + +// assert_noop!(Vesting::force_vested_transfer(Some(4).into(), 3, 4, new_vesting_schedule), BadOrigin); +// assert_ok!(Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, new_vesting_schedule)); +// // Now account 4 should have vesting. +// assert_eq!(Vesting::vesting(&4).unwrap()[0], new_vesting_schedule); +// assert_eq!(Vesting::vesting(&4).unwrap().len(), 1); +// // Ensure the transfer happened correctly. +// let user3_free_balance_updated = Balances::free_balance(&3); +// assert_eq!(user3_free_balance_updated, ED * 25); +// let user4_free_balance_updated = Balances::free_balance(&4); +// assert_eq!(user4_free_balance_updated, ED * 45); +// // Account 4 has 5 * ED locked. +// assert_eq!(Vesting::vesting_balance(&4), Some(ED * 5)); + +// System::set_block_number(20); +// assert_eq!(System::block_number(), 20); + +// // Account 4 has 5 * 64 units vested by block 20. +// assert_eq!(Vesting::vesting_balance(&4), Some(10 * 64)); + +// System::set_block_number(30); +// assert_eq!(System::block_number(), 30); + +// // Account 4 has fully vested, +// assert_eq!(Vesting::vesting_balance(&4), Some(0)); +// // and after unlocking its schedules are removed from storage. +// vest_and_assert_no_vesting::(4); +// }); +// } + +// #[test] +// fn force_vested_transfer_correctly_fails() { +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// let user2_free_balance = Balances::free_balance(&2); +// let user4_free_balance = Balances::free_balance(&4); +// assert_eq!(user2_free_balance, ED * 21); +// assert_eq!(user4_free_balance, ED * 40); +// // Account 2 should already have a vesting schedule. +// let user2_vesting_schedule = VestingInfo::new( +// ED * 20, +// ED, // Vesting over 20 blocks +// 10, +// ); +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![user2_vesting_schedule]); + +// // Too low transfer amount. +// let new_vesting_schedule_too_low = VestingInfo::new(::MinVestedTransfer::get() - 1, 64, 10); +// assert_noop!( +// Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, new_vesting_schedule_too_low), +// Error::::AmountLow, +// ); + +// // `per_block` is 0. +// let schedule_per_block_0 = VestingInfo::new(::MinVestedTransfer::get(), 0, 10); +// assert_noop!( +// Vesting::force_vested_transfer(RawOrigin::Root.into(), 13, 4, schedule_per_block_0), +// Error::::InvalidScheduleParams, +// ); + +// // `locked` is 0. +// let schedule_locked_0 = VestingInfo::new(0, 1, 10); +// assert_noop!( +// Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, schedule_locked_0), +// Error::::AmountLow, +// ); + +// // Verify no currency transfer happened. +// assert_eq!(user2_free_balance, Balances::free_balance(&2)); +// assert_eq!(user4_free_balance, Balances::free_balance(&4)); +// // Account 4 has no schedules. +// vest_and_assert_no_vesting::(4); +// }); +// } + +// #[test] +// fn force_vested_transfer_allows_max_schedules() { +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// let mut user_4_free_balance = Balances::free_balance(&4); +// let max_schedules = ::MAX_VESTING_SCHEDULES; +// let sched = VestingInfo::new( +// ::MinVestedTransfer::get(), +// 1, // Vest over 2 * 256 blocks. +// 10, +// ); + +// // Add max amount schedules to user 4. +// for _ in 0..max_schedules { +// assert_ok!(Vesting::force_vested_transfer(RawOrigin::Root.into(), 13, 4, sched)); +// } + +// // The schedules count towards vesting balance. +// let transferred_amount = ::MinVestedTransfer::get() * max_schedules as u64; +// assert_eq!(Vesting::vesting_balance(&4), Some(transferred_amount)); +// // and free balance. +// user_4_free_balance += transferred_amount; +// assert_eq!(Balances::free_balance(&4), user_4_free_balance); + +// // Cannot insert a 4th vesting schedule when `MaxVestingSchedules` === 3 +// assert_noop!( +// Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, sched), +// Error::::AtMaxVestingSchedules, +// ); +// // so the free balance does not change. +// assert_eq!(Balances::free_balance(&4), user_4_free_balance); + +// // Account 4 has fully vested when all the schedules end, +// System::set_block_number(::MinVestedTransfer::get() + 10); +// assert_eq!(Vesting::vesting_balance(&4), Some(0)); +// // and after unlocking its schedules are removed from storage. +// vest_and_assert_no_vesting::(4); +// }); +// } + +// #[test] +// fn merge_schedules_that_have_not_started() { +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// // Account 2 should already have a vesting schedule. +// let sched0 = VestingInfo::new( +// ED * 20, +// ED, // Vest over 20 blocks. +// 10, +// ); +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); +// assert_eq!(Balances::usable_balance(&2), 0); + +// // Add a schedule that is identical to the one that already exists. +// assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched0)); +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched0]); +// assert_eq!(Balances::usable_balance(&2), 0); +// assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); + +// // Since we merged identical schedules, the new schedule finishes at the same +// // time as the original, just with double the amount. +// let sched1 = VestingInfo::new( +// sched0.locked() * 2, +// sched0.per_block() * 2, +// 10, // Starts at the block the schedules are merged/ +// ); +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched1]); + +// assert_eq!(Balances::usable_balance(&2), 0); +// }); +// } + +// #[test] +// fn merge_ongoing_schedules() { +// // Merging two schedules that have started will vest both before merging. +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// // Account 2 should already have a vesting schedule. +// let sched0 = VestingInfo::new( +// ED * 20, +// ED, // Vest over 20 blocks. +// 10, +// ); +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + +// let sched1 = VestingInfo::new( +// ED * 10, +// ED, // Vest over 10 blocks. +// sched0.starting_block() + 5, // Start at block 15. +// ); +// assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1)); +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); + +// // Got to half way through the second schedule where both schedules are actively vesting. +// let cur_block = 20; +// System::set_block_number(cur_block); + +// // Account 2 has no usable balances prior to the merge because they have not unlocked +// // with `vest` yet. +// assert_eq!(Balances::usable_balance(&2), 0); + +// assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); + +// // Merging schedules un-vests all pre-existing schedules prior to merging, which is +// // reflected in account 2's updated usable balance. +// let sched0_vested_now = sched0.per_block() * (cur_block - sched0.starting_block()); +// let sched1_vested_now = sched1.per_block() * (cur_block - sched1.starting_block()); +// assert_eq!(Balances::usable_balance(&2), sched0_vested_now + sched1_vested_now); + +// // The locked amount is the sum of what both schedules have locked at the current block. +// let sched2_locked = +// sched1.locked_at::(cur_block).saturating_add(sched0.locked_at::(cur_block)); +// // End block of the new schedule is the greater of either merged schedule. +// let sched2_end = sched1.ending_block_as_balance::().max(sched0.ending_block_as_balance::()); +// let sched2_duration = sched2_end - cur_block; +// // Based off the new schedules total locked and its duration, we can calculate the +// // amount to unlock per block. +// let sched2_per_block = sched2_locked / sched2_duration; + +// let sched2 = VestingInfo::new(sched2_locked, sched2_per_block, cur_block); +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2]); + +// // And just to double check, we assert the new merged schedule we be cleaned up as expected. +// System::set_block_number(30); +// vest_and_assert_no_vesting::(2); +// }); +// } + +// #[test] +// fn merging_shifts_other_schedules_index() { +// // Schedules being merged are filtered out, schedules to the right of any merged +// // schedule shift left and the merged schedule is always last. +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// let sched0 = VestingInfo::new( +// ED * 10, +// ED, // Vesting over 10 blocks. +// 10, +// ); +// let sched1 = VestingInfo::new( +// ED * 11, +// ED, // Vesting over 11 blocks. +// 11, +// ); +// let sched2 = VestingInfo::new( +// ED * 12, +// ED, // Vesting over 12 blocks. +// 12, +// ); + +// // Account 3 starts out with no schedules, +// assert_eq!(Vesting::vesting(&3), None); +// // and some usable balance. +// let usable_balance = Balances::usable_balance(&3); +// assert_eq!(usable_balance, 30 * ED); + +// let cur_block = 1; +// assert_eq!(System::block_number(), cur_block); + +// // Transfer the above 3 schedules to account 3. +// assert_ok!(Vesting::vested_transfer(Some(4).into(), 3, sched0)); +// assert_ok!(Vesting::vested_transfer(Some(4).into(), 3, sched1)); +// assert_ok!(Vesting::vested_transfer(Some(4).into(), 3, sched2)); + +// // With no schedules vested or merged they are in the order they are created +// assert_eq!(Vesting::vesting(&3).unwrap(), vec![sched0, sched1, sched2]); +// // and the usable balance has not changed. +// assert_eq!(usable_balance, Balances::usable_balance(&3)); + +// assert_ok!(Vesting::merge_schedules(Some(3).into(), 0, 2)); + +// // Create the merged schedule of sched0 & sched2. +// // The merged schedule will have the max possible starting block, +// let sched3_start = sched1.starting_block().max(sched2.starting_block()); +// // `locked` equal to the sum of the two schedules locked through the current block, +// let sched3_locked = sched2.locked_at::(cur_block) + sched0.locked_at::(cur_block); +// // and will end at the max possible block. +// let sched3_end = sched2.ending_block_as_balance::().max(sched0.ending_block_as_balance::()); +// let sched3_duration = sched3_end - sched3_start; +// let sched3_per_block = sched3_locked / sched3_duration; +// let sched3 = VestingInfo::new(sched3_locked, sched3_per_block, sched3_start); + +// // The not touched schedule moves left and the new merged schedule is appended. +// assert_eq!(Vesting::vesting(&3).unwrap(), vec![sched1, sched3]); +// // The usable balance hasn't changed since none of the schedules have started. +// assert_eq!(Balances::usable_balance(&3), usable_balance); +// }); +// } + +// #[test] +// fn merge_ongoing_and_yet_to_be_started_schedules() { +// // Merge an ongoing schedule that has had `vest` called and a schedule that has not already +// // started. +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// // Account 2 should already have a vesting schedule. +// let sched0 = VestingInfo::new( +// ED * 20, +// ED, // Vesting over 20 blocks +// 10, +// ); +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + +// // Fast forward to half way through the life of sched1. +// let mut cur_block = (sched0.starting_block() + sched0.ending_block_as_balance::()) / 2; +// assert_eq!(cur_block, 20); +// System::set_block_number(cur_block); + +// // Prior to vesting there is no usable balance. +// let mut usable_balance = 0; +// assert_eq!(Balances::usable_balance(&2), usable_balance); +// // Vest the current schedules (which is just sched0 now). +// Vesting::vest(Some(2).into()).unwrap(); + +// // After vesting the usable balance increases by the unlocked amount. +// let sched0_vested_now = sched0.locked() - sched0.locked_at::(cur_block); +// usable_balance += sched0_vested_now; +// assert_eq!(Balances::usable_balance(&2), usable_balance); + +// // Go forward a block. +// cur_block += 1; +// System::set_block_number(cur_block); + +// // And add a schedule that starts after this block, but before sched0 finishes. +// let sched1 = VestingInfo::new( +// ED * 10, +// 1, // Vesting over 256 * 10 (2560) blocks +// cur_block + 1, +// ); +// assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1)); + +// // Merge the schedules before sched1 starts. +// assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); +// // After merging, the usable balance only changes by the amount sched0 vested since we +// // last called `vest` (which is just 1 block). The usable balance is not affected by +// // sched1 because it has not started yet. +// usable_balance += sched0.per_block(); +// assert_eq!(Balances::usable_balance(&2), usable_balance); + +// // The resulting schedule will have the later starting block of the two, +// let sched2_start = sched1.starting_block(); +// // `locked` equal to the sum of the two schedules locked through the current block, +// let sched2_locked = sched0.locked_at::(cur_block) + sched1.locked_at::(cur_block); +// // and will end at the max possible block. +// let sched2_end = sched0.ending_block_as_balance::().max(sched1.ending_block_as_balance::()); +// let sched2_duration = sched2_end - sched2_start; +// let sched2_per_block = sched2_locked / sched2_duration; + +// let sched2 = VestingInfo::new(sched2_locked, sched2_per_block, sched2_start); +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2]); +// }); +// } + +// #[test] +// fn merge_finished_and_ongoing_schedules() { +// // If a schedule finishes by the current block we treat the ongoing schedule, +// // without any alterations, as the merged one. +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// // Account 2 should already have a vesting schedule. +// let sched0 = VestingInfo::new( +// ED * 20, +// ED, // Vesting over 20 blocks. +// 10, +// ); +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + +// let sched1 = VestingInfo::new( +// ED * 40, +// ED, // Vesting over 40 blocks. +// 10, +// ); +// assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1)); + +// // Transfer a 3rd schedule, so we can demonstrate how schedule indices change. +// // (We are not merging this schedule.) +// let sched2 = VestingInfo::new( +// ED * 30, +// ED, // Vesting over 30 blocks. +// 10, +// ); +// assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched2)); + +// // The schedules are in expected order prior to merging. +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); + +// // Fast forward to sched0's end block. +// let cur_block = sched0.ending_block_as_balance::(); +// System::set_block_number(cur_block); +// assert_eq!(System::block_number(), 30); + +// // Prior to `merge_schedules` and with no vest/vest_other called the user has no usable +// // balance. +// assert_eq!(Balances::usable_balance(&2), 0); +// assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); + +// // sched2 is now the first, since sched0 & sched1 get filtered out while "merging". +// // sched1 gets treated like the new merged schedule by getting pushed onto back +// // of the vesting schedules vec. Note: sched0 finished at the current block. +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2, sched1]); + +// // sched0 has finished, so its funds are fully unlocked. +// let sched0_unlocked_now = sched0.locked(); +// // The remaining schedules are ongoing, so their funds are partially unlocked. +// let sched1_unlocked_now = sched1.locked() - sched1.locked_at::(cur_block); +// let sched2_unlocked_now = sched2.locked() - sched2.locked_at::(cur_block); + +// // Since merging also vests all the schedules, the users usable balance after merging +// // includes all pre-existing schedules unlocked through the current block, including +// // schedules not merged. +// assert_eq!(Balances::usable_balance(&2), sched0_unlocked_now + sched1_unlocked_now + sched2_unlocked_now); +// }); +// } + +// #[test] +// fn merge_finishing_schedules_does_not_create_a_new_one() { +// // If both schedules finish by the current block we don't create new one +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// // Account 2 should already have a vesting schedule. +// let sched0 = VestingInfo::new( +// ED * 20, +// ED, // 20 block duration. +// 10, +// ); +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + +// // Create sched1 and transfer it to account 2. +// let sched1 = VestingInfo::new( +// ED * 30, +// ED, // 30 block duration. +// 10, +// ); +// assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched1)); +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); + +// let all_scheds_end = +// sched0.ending_block_as_balance::().max(sched1.ending_block_as_balance::()); + +// assert_eq!(all_scheds_end, 40); +// System::set_block_number(all_scheds_end); + +// // Prior to merge_schedules and with no vest/vest_other called the user has no usable +// // balance. +// assert_eq!(Balances::usable_balance(&2), 0); + +// // Merge schedule 0 and 1. +// assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); +// // The user no longer has any more vesting schedules because they both ended at the +// // block they where merged, +// assert!(!>::contains_key(&2)); +// // and their usable balance has increased by the total amount locked in the merged +// // schedules. +// assert_eq!(Balances::usable_balance(&2), sched0.locked() + sched1.locked()); +// }); +// } + +// #[test] +// fn merge_finished_and_yet_to_be_started_schedules() { +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// // Account 2 should already have a vesting schedule. +// let sched0 = VestingInfo::new( +// ED * 20, +// ED, // 20 block duration. +// 10, // Ends at block 30 +// ); +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + +// let sched1 = VestingInfo::new( +// ED * 30, +// ED * 2, // 30 block duration. +// 35, +// ); +// assert_ok!(Vesting::vested_transfer(Some(13).into(), 2, sched1)); +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); + +// let sched2 = VestingInfo::new( +// ED * 40, +// ED, // 40 block duration. +// 30, +// ); +// // Add a 3rd schedule to demonstrate how sched1 shifts. +// assert_ok!(Vesting::vested_transfer(Some(13).into(), 2, sched2)); +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); + +// System::set_block_number(30); + +// // At block 30, sched0 has finished unlocking while sched1 and sched2 are still fully +// // locked, +// assert_eq!(Vesting::vesting_balance(&2), Some(sched1.locked() + sched2.locked())); +// // but since we have not vested usable balance is still 0. +// assert_eq!(Balances::usable_balance(&2), 0); + +// // Merge schedule 0 and 1. +// assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); + +// // sched0 is removed since it finished, and sched1 is removed and then pushed on the back +// // because it is treated as the merged schedule +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2, sched1]); + +// // The usable balance is updated because merging fully unlocked sched0. +// assert_eq!(Balances::usable_balance(&2), sched0.locked()); +// }); +// } + +// #[test] +// fn merge_schedules_throws_proper_errors() { +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// // Account 2 should already have a vesting schedule. +// let sched0 = VestingInfo::new( +// ED * 20, +// ED, // 20 block duration. +// 10, +// ); +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + +// // Account 2 only has 1 vesting schedule. +// assert_noop!(Vesting::merge_schedules(Some(2).into(), 0, 1), Error::::ScheduleIndexOutOfBounds); + +// // Account 4 has 0 vesting schedules. +// assert_eq!(Vesting::vesting(&4), None); +// assert_noop!(Vesting::merge_schedules(Some(4).into(), 0, 1), Error::::NotVesting); + +// // There are enough schedules to merge but an index is non-existent. +// Vesting::vested_transfer(Some(3).into(), 2, sched0).unwrap(); +// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched0]); +// assert_noop!(Vesting::merge_schedules(Some(2).into(), 0, 2), Error::::ScheduleIndexOutOfBounds); + +// // It is a storage noop with no errors if the indexes are the same. +// assert_storage_noop!(Vesting::merge_schedules(Some(2).into(), 0, 0).unwrap()); +// }); +// } + +// #[test] +// fn merge_vesting_handles_per_block_0() { +// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// let sched0 = VestingInfo::new( +// ED, 0, // Vesting over 256 blocks. +// 1, +// ); +// assert_eq!(sched0.ending_block_as_balance::(), 257); +// let sched1 = VestingInfo::new( +// ED * 2, +// 0, // Vesting over 512 blocks. +// 10, +// ); +// assert_eq!(sched1.ending_block_as_balance::(), 512u64 + 10); + +// let merged = VestingInfo::new(764, 1, 10); +// assert_eq!(Vesting::merge_vesting_info(5, sched0, sched1), Some(merged)); +// }); +// } + +// #[test] +// fn vesting_info_validate_works() { +// let min_transfer = ::MinVestedTransfer::get(); +// // Does not check for min transfer. +// assert_eq!(VestingInfo::new(min_transfer - 1, 1u64, 10u64).is_valid(), true); + +// // `locked` cannot be 0. +// assert_eq!(VestingInfo::new(0, 1u64, 10u64).is_valid(), false); + +// // `per_block` cannot be 0. +// assert_eq!(VestingInfo::new(min_transfer + 1, 0u64, 10u64).is_valid(), false); + +// // With valid inputs it does not error. +// assert_eq!(VestingInfo::new(min_transfer, 1u64, 10u64).is_valid(), true); +// } + +// #[test] +// fn vesting_info_ending_block_as_balance_works() { +// // Treats `per_block` 0 as 1. +// let per_block_0 = VestingInfo::new(256u32, 0u32, 10u32); +// assert_eq!(per_block_0.ending_block_as_balance::(), 256 + 10); + +// // `per_block >= locked` always results in a schedule ending the block after it starts +// let per_block_gt_locked = VestingInfo::new(256u32, 256 * 2u32, 10u32); +// assert_eq!(per_block_gt_locked.ending_block_as_balance::(), 1 + per_block_gt_locked.starting_block()); +// let per_block_eq_locked = VestingInfo::new(256u32, 256u32, 10u32); +// assert_eq!( +// per_block_gt_locked.ending_block_as_balance::(), +// per_block_eq_locked.ending_block_as_balance::() +// ); + +// // Correctly calcs end if `locked % per_block != 0`. (We need a block to unlock the remainder). +// let imperfect_per_block = VestingInfo::new(256u32, 250u32, 10u32); +// assert_eq!(imperfect_per_block.ending_block_as_balance::(), imperfect_per_block.starting_block() + 2u32,); +// assert_eq!(imperfect_per_block.locked_at::(imperfect_per_block.ending_block_as_balance::()), 0); +// } + +// #[test] +// fn per_block_works() { +// let per_block_0 = VestingInfo::new(256u32, 0u32, 10u32); +// assert_eq!(per_block_0.per_block(), 1u32); +// assert_eq!(per_block_0.raw_per_block(), 0u32); + +// let per_block_1 = VestingInfo::new(256u32, 1u32, 10u32); +// assert_eq!(per_block_1.per_block(), 1u32); +// assert_eq!(per_block_1.raw_per_block(), 1u32); +// } + +// // When an accounts free balance + schedule.locked is less than ED, the vested transfer will fail. +// #[test] +// fn vested_transfer_less_than_existential_deposit_fails() { +// ExtBuilder::default().existential_deposit(4 * ED).build().execute_with(|| { +// // MinVestedTransfer is less the ED. +// assert!(::Currency::minimum_balance() > ::MinVestedTransfer::get()); + +// let sched = VestingInfo::new(::MinVestedTransfer::get() as u64, 1u64, 10u64); +// // The new account balance with the schedule's locked amount would be less than ED. +// assert!(Balances::free_balance(&99) + sched.locked() < ::Currency::minimum_balance()); + +// // vested_transfer fails. +// assert_noop!(Vesting::vested_transfer(Some(3).into(), 99, sched), TokenError::BelowMinimum,); +// // force_vested_transfer fails. +// assert_noop!(Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 99, sched), TokenError::BelowMinimum,); +// }); +// } // TODO @@ -1047,14 +1047,20 @@ fn set_release_schedule() { assert_ok!(Vesting::release_schedule(Some(3).into(), user3_vesting_schedule)); assert_eq!(Vesting::vesting_balance(&3), Some(15 * ED)); - // 1 ED can be "released" + // 1 ED can be "released", we need to call vest to release it. System::set_block_number(2); assert_eq!(Vesting::vesting_balance(&3), Some(14 * ED)); + assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(0))); + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 16 * ED); // 2 ED can be "released" System::set_block_number(3); assert_eq!(Vesting::vesting_balance(&3), Some(13 * ED)); + assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(0))); + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 17 * ED); // Go to the end of the schedule System::set_block_number(16); diff --git a/polimec-skeleton/pallets/linear-release/src/traits.rs b/polimec-skeleton/pallets/linear-release/src/traits.rs index b5d8e7a62..0e53bd67f 100644 --- a/polimec-skeleton/pallets/linear-release/src/traits.rs +++ b/polimec-skeleton/pallets/linear-release/src/traits.rs @@ -4,7 +4,7 @@ use frame_support::{pallet_prelude::DispatchResult, traits::tokens::fungible}; /// A release schedule over a fungible. This allows a particular fungible to have release limits /// applied to it. -pub trait ReleaseSchedule { +pub trait ReleaseSchedule { /// The quantity used to denote time; usually just a `BlockNumber`. type Moment; @@ -31,6 +31,7 @@ pub trait ReleaseSchedule { locked: >::Balance, per_block: >::Balance, starting_block: Self::Moment, + reason: Reason, ) -> DispatchResult; /// Ser a release schedule to a given account, without locking any funds. @@ -59,5 +60,5 @@ pub trait ReleaseSchedule { /// Remove a release schedule for a given account. /// /// NOTE: This doesn't alter the free balance of the account. - fn remove_vesting_schedule(who: &AccountId, schedule_index: u32) -> DispatchResult; + fn remove_vesting_schedule(who: &AccountId, schedule_index: u32, reason: Reason) -> DispatchResult; } From 2a394d68744d7ed01474d300746ef9a20b4e6e3d Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Wed, 19 Jul 2023 11:52:30 +0200 Subject: [PATCH 10/80] feat: relax the genesis config type --- .../pallets/linear-release/src/lib.rs | 26 ++++++++++--------- .../pallets/linear-release/src/mock.rs | 22 +++++++++------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/lib.rs b/polimec-skeleton/pallets/linear-release/src/lib.rs index e279a73a9..898c8085b 100644 --- a/polimec-skeleton/pallets/linear-release/src/lib.rs +++ b/polimec-skeleton/pallets/linear-release/src/lib.rs @@ -123,7 +123,7 @@ pub mod pallet { type Balance: Balance + From + MaybeSerializeDeserialize; // TODO: Still I dont-like this. I want to be able to use the `LockType` from the pallet_balances, without coupling it. - type Reason: Parameter + Copy; + type Reason: Parameter + Copy + MaybeSerializeDeserialize; type Currency: InspectHold, Balance = BalanceOf> + MutateHold, Balance = BalanceOf, Reason = ReasonOf> @@ -157,7 +157,7 @@ pub mod pallet { #[pallet::genesis_config] pub struct GenesisConfig { - pub vesting: Vec<(AccountIdOf, T::BlockNumber, T::BlockNumber, BalanceOf)>, + pub vesting: Vec<(AccountIdOf, T::BlockNumber, T::BlockNumber, BalanceOf, ReasonOf)>, } #[cfg(feature = "std")] @@ -177,7 +177,7 @@ pub mod pallet { // * begin - Block when the account will start to vest // * length - Number of blocks from `begin` until fully vested // * liquid - Number of units which can be spent before vesting begins - for &(ref who, begin, length, liquid) in self.vesting.iter() { + for &(ref who, begin, length, liquid, reason) in self.vesting.iter() { let balance = T::Currency::balance(who); assert!(!balance.is_zero(), "Currencies must be init'd before vesting"); // Total genesis `balance` minus `liquid` equals funds locked for vesting @@ -191,12 +191,9 @@ pub mod pallet { Vesting::::try_append(who, vesting_info).expect("Too many vesting schedules at genesis."); - // TODO: Use T::Currency::hold to lock the funds, using the T::Reasons - // FIXME: Re-add it, otherwise the tests will fail - - // T::Currency::hold(&LockType::Participation(0u32.into()), who, locked) - // .map_err(|err| panic!("{:?}", err)) - // .unwrap(); + T::Currency::hold(&reason, who, locked) + .map_err(|err| panic!("{:?}", err)) + .unwrap(); } } } @@ -308,7 +305,7 @@ pub mod pallet { origin: OriginFor, target: AccountIdOf, schedule: VestingInfo, BlockNumberFor>, - reason: ReasonOf + reason: ReasonOf, ) -> DispatchResult { let transactor = ensure_signed(origin)?; Self::do_vested_transfer(transactor, target, schedule, reason) @@ -334,7 +331,7 @@ pub mod pallet { source: AccountIdOf, target: AccountIdOf, schedule: VestingInfo, BlockNumberFor>, - reason: ReasonOf + reason: ReasonOf, ) -> DispatchResult { ensure_root(origin)?; Self::do_vested_transfer(source, target, schedule, reason) @@ -362,7 +359,12 @@ pub mod pallet { /// - `schedule1_index`: index of the first schedule to merge. /// - `schedule2_index`: index of the second schedule to merge. #[pallet::call_index(4)] - pub fn merge_schedules(origin: OriginFor, schedule1_index: u32, schedule2_index: u32, reason: ReasonOf) -> DispatchResult { + pub fn merge_schedules( + origin: OriginFor, + schedule1_index: u32, + schedule2_index: u32, + reason: ReasonOf, + ) -> DispatchResult { let who = ensure_signed(origin)?; if schedule1_index == schedule2_index { return Ok(()); diff --git a/polimec-skeleton/pallets/linear-release/src/mock.rs b/polimec-skeleton/pallets/linear-release/src/mock.rs index 5d6fa6842..397b07448 100644 --- a/polimec-skeleton/pallets/linear-release/src/mock.rs +++ b/polimec-skeleton/pallets/linear-release/src/mock.rs @@ -53,6 +53,13 @@ impl frame_system::Config for Test { type Version = (); } +parameter_types! { + pub const MinVestedTransfer: u64 = 256 * 2; + pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons = + WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); + pub static ExistentialDeposit: u64 = 1; +} + impl pallet_balances::Config for Test { type AccountStore = System; type Balance = u64; @@ -68,12 +75,7 @@ impl pallet_balances::Config for Test { type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } -parameter_types! { - pub const MinVestedTransfer: u64 = 256 * 2; - pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons = - WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); - pub static ExistentialDeposit: u64 = 1; -} + impl Config for Test { type Balance = u64; type BlockNumberToBalance = Identity; @@ -89,7 +91,7 @@ impl Config for Test { #[derive(Default)] pub struct ExtBuilder { existential_deposit: u64, - vesting_genesis_config: Option>, + vesting_genesis_config: Option)>>, } impl ExtBuilder { @@ -119,9 +121,9 @@ impl ExtBuilder { vesting_config } else { vec![ - (1, 0, 10, 5 * self.existential_deposit), - (2, 10, 20, self.existential_deposit), - (12, 10, 20, 5 * self.existential_deposit), + (1, 0, 10, 5 * self.existential_deposit, LockType::Participation(0)), + (2, 10, 20, self.existential_deposit, LockType::Participation(0)), + (12, 10, 20, 5 * self.existential_deposit, LockType::Participation(0)), ] }; From a898aba8b3016bf0a7a5442409b04d040203cfa5 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Wed, 19 Jul 2023 11:53:05 +0200 Subject: [PATCH 11/80] feat: the lock should now implement Ser and Des --- polimec-skeleton/pallets/linear-release/Cargo.toml | 4 +++- polimec-skeleton/pallets/linear-release/src/types.rs | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/polimec-skeleton/pallets/linear-release/Cargo.toml b/polimec-skeleton/pallets/linear-release/Cargo.toml index 4dae5bf16..f1b056962 100644 --- a/polimec-skeleton/pallets/linear-release/Cargo.toml +++ b/polimec-skeleton/pallets/linear-release/Cargo.toml @@ -13,6 +13,7 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] +serde = { version = "1.0.136", optional = true } codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false } log = { version = "0.4.17", default-features = false } scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } @@ -36,6 +37,7 @@ std = [ "scale-info/std", "sp-runtime/std", "sp-std/std", - "pallet-balances/std" + "pallet-balances/std", + "serde" ] try-runtime = ["frame-support/try-runtime"] diff --git a/polimec-skeleton/pallets/linear-release/src/types.rs b/polimec-skeleton/pallets/linear-release/src/types.rs index c39383cf2..b13bf4469 100644 --- a/polimec-skeleton/pallets/linear-release/src/types.rs +++ b/polimec-skeleton/pallets/linear-release/src/types.rs @@ -2,6 +2,7 @@ use super::*; /// Enum used to identify PLMC holds #[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo, Ord, PartialOrd)] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub enum LockType { Evaluation(ProjectId), Participation(ProjectId), From 4f31ef3783522cb2975f88539483d5e4a22a7cc1 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Wed, 19 Jul 2023 11:53:26 +0200 Subject: [PATCH 12/80] fix: few tests --- polimec-skeleton/Cargo.lock | 1 + .../pallets/linear-release/src/impls.rs | 42 +- .../pallets/linear-release/src/tests.rs | 477 ++++++++++-------- 3 files changed, 291 insertions(+), 229 deletions(-) diff --git a/polimec-skeleton/Cargo.lock b/polimec-skeleton/Cargo.lock index cf0b813f0..1a7f6c645 100644 --- a/polimec-skeleton/Cargo.lock +++ b/polimec-skeleton/Cargo.lock @@ -6015,6 +6015,7 @@ dependencies = [ "pallet-balances", "parity-scale-codec", "scale-info", + "serde", "sp-core", "sp-io", "sp-runtime", diff --git a/polimec-skeleton/pallets/linear-release/src/impls.rs b/polimec-skeleton/pallets/linear-release/src/impls.rs index ee67da94d..f8d05f755 100644 --- a/polimec-skeleton/pallets/linear-release/src/impls.rs +++ b/polimec-skeleton/pallets/linear-release/src/impls.rs @@ -1,4 +1,4 @@ -use crate::types::LockType; +use frame_support::traits::tokens::Precision; use super::*; @@ -53,7 +53,7 @@ impl Pallet { source: AccountIdOf, target: AccountIdOf, schedule: VestingInfo, BlockNumberFor>, - reason: ReasonOf + reason: ReasonOf, ) -> DispatchResult { // Validate user inputs. ensure!(schedule.locked() >= T::MinVestedTransfer::get(), Error::::AmountLow); @@ -64,17 +64,24 @@ impl Pallet { // Check we can add to this account prior to any storage writes. Self::can_add_release_schedule(&target, schedule.locked(), schedule.per_block(), schedule.starting_block())?; - T::Currency::transfer( + let amount_transferred = T::Currency::transfer_and_hold( + &reason, &source, &target, schedule.locked(), - // TODO: Set a proper Preservation + Precision::BestEffort, frame_support::traits::tokens::Preservation::Expendable, + frame_support::traits::tokens::Fortitude::Polite, )?; // We can't let this fail because the currency transfer has already happened. - let res = - Self::add_release_schedule(&target, schedule.locked(), schedule.per_block(), schedule.starting_block(), reason); + let res = Self::add_release_schedule( + &target, + amount_transferred, + schedule.per_block(), + schedule.starting_block(), + reason, + ); debug_assert!(res.is_ok(), "{:#?}", res.err()); Ok(()) @@ -113,7 +120,11 @@ impl Pallet { } /// Write an accounts updated vesting lock to storage. - pub fn write_lock(who: &T::AccountId, total_locked_now: BalanceOf, reason: ReasonOf) -> Result<(), DispatchError> { + pub fn write_lock( + who: &T::AccountId, + total_locked_now: BalanceOf, + reason: ReasonOf, + ) -> Result<(), DispatchError> { if total_locked_now.is_zero() { T::Currency::release( &reason, @@ -123,14 +134,13 @@ impl Pallet { )?; Self::deposit_event(Event::::VestingCompleted { account: who.clone() }); } else { - let amount = T::Currency::balance_on_hold(&reason, who); - let amount = amount.saturating_sub(total_locked_now); - T::Currency::release( - &reason, - who, - amount, - frame_support::traits::tokens::Precision::BestEffort, - )?; + let free_balance_now = T::Currency::balance(who); + let alredy_holded = T::Currency::balance_on_hold(&reason, who); + println!("write_lock: free_balance_now: {:?}", free_balance_now); + println!("write_lock: alredy_holded: {:?}", alredy_holded); + println!("write_lock: total_locked_now: {:?}", total_locked_now); + let to_release = alredy_holded.saturating_sub(total_locked_now); + T::Currency::release(&reason, who, to_release, Precision::BestEffort)?; Self::deposit_event(Event::::VestingUpdated { account: who.clone(), unvested: total_locked_now }); }; @@ -295,7 +305,7 @@ impl ReleaseSchedule, ReasonOf> for Pallet } /// Remove a vesting schedule for a given account. - fn remove_vesting_schedule(who: &T::AccountId, schedule_index: u32, reason: ReasonOf,) -> DispatchResult { + fn remove_vesting_schedule(who: &T::AccountId, schedule_index: u32, reason: ReasonOf) -> DispatchResult { let schedules = Self::vesting(who).ok_or(Error::::NotVesting)?; let remove_action = VestingAction::Remove { index: schedule_index as usize }; diff --git a/polimec-skeleton/pallets/linear-release/src/tests.rs b/polimec-skeleton/pallets/linear-release/src/tests.rs index ea3f66d85..2cc05ea64 100644 --- a/polimec-skeleton/pallets/linear-release/src/tests.rs +++ b/polimec-skeleton/pallets/linear-release/src/tests.rs @@ -6,7 +6,10 @@ use sp_runtime::{ }; use super::{Vesting as VestingStorage, *}; -use crate::{mock::{Balances, ExtBuilder, System, Test, Vesting}, types::LockType}; +use crate::{ + mock::{Balances, ExtBuilder, System, Test, Vesting}, + types::LockType, +}; /// A default existential deposit. const ED: u64 = 256; @@ -23,217 +26,235 @@ where assert!(!>::contains_key(account)); } -// #[test] -// fn check_vesting_status() { -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// let user1_free_balance = Balances::free_balance(&1); -// let user2_free_balance = Balances::free_balance(&2); -// let user12_free_balance = Balances::free_balance(&12); -// assert_eq!(user1_free_balance, ED * 5); // Account 1 has free balance -// assert_eq!(user2_free_balance, ED * 1); // Account 2 has free balance -// assert_eq!(user12_free_balance, ED * 5); // Account 12 has free balance -// let user1_vesting_schedule = VestingInfo::new( -// ED * 5, -// 128, // Vesting over 10 blocks -// 0, -// ); -// let user2_vesting_schedule = VestingInfo::new( -// ED * 20, -// ED, // Vesting over 19 blocks -// 10, -// ); -// let user12_vesting_schedule = VestingInfo::new( -// ED * 5, -// 64, // Vesting over 20 blocks -// 10, -// ); -// assert_eq!(Vesting::vesting(&1).unwrap(), vec![user1_vesting_schedule]); // Account 1 has a vesting schedule -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![user2_vesting_schedule]); // Account 2 has a vesting schedule -// assert_eq!(Vesting::vesting(&12).unwrap(), vec![user12_vesting_schedule]); // Account 12 has a vesting schedule - -// // Account 1 has only 128 units vested from their illiquid ED * 5 units at block 1 -// assert_eq!(Vesting::vesting_balance(&1), Some(128 * 9)); -// // Account 2 has their full balance locked -// assert_eq!(Vesting::vesting_balance(&2), Some(user2_free_balance)); -// // Account 12 has only their illiquid funds locked -// assert_eq!(Vesting::vesting_balance(&12), Some(user12_free_balance)); - -// System::set_block_number(10); -// assert_eq!(System::block_number(), 10); - -// // Account 1 has fully vested by block 10 -// assert_eq!(Vesting::vesting_balance(&1), Some(0)); -// // Account 2 has started vesting by block 10 -// assert_eq!(Vesting::vesting_balance(&2), Some(user2_free_balance)); -// // Account 12 has started vesting by block 10 -// assert_eq!(Vesting::vesting_balance(&12), Some(user12_free_balance)); - -// System::set_block_number(30); -// assert_eq!(System::block_number(), 30); - -// assert_eq!(Vesting::vesting_balance(&1), Some(0)); // Account 1 is still fully vested, and not negative -// assert_eq!(Vesting::vesting_balance(&2), Some(0)); // Account 2 has fully vested by block 30 -// assert_eq!(Vesting::vesting_balance(&12), Some(0)); // Account 2 has fully vested by block 30 - -// // Once we unlock the funds, they are removed from storage. -// vest_and_assert_no_vesting::(1); -// vest_and_assert_no_vesting::(2); -// vest_and_assert_no_vesting::(12); -// }); -// } - -// #[test] -// fn check_vesting_status_for_multi_schedule_account() { -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// assert_eq!(System::block_number(), 1); -// let sched0 = VestingInfo::new( -// ED * 20, -// ED, // Vesting over 20 blocks -// 10, -// ); -// // Account 2 already has a vesting schedule. -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); - -// // Account 2's free balance is from sched0. -// let free_balance = Balances::free_balance(&2); -// assert_eq!(free_balance, ED * (1)); -// assert_eq!(Vesting::vesting_balance(&2), Some(free_balance)); - -// // Add a 2nd schedule that is already unlocking by block #1. -// let sched1 = VestingInfo::new( -// ED * 10, -// ED, // Vesting over 10 blocks -// 0, -// ); -// assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1)); -// // Free balance is equal to the two existing schedules total amount. -// let free_balance = Balances::free_balance(&2); -// assert_eq!(free_balance, ED * (10 + 20)); -// // The most recently added schedule exists. -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); -// // sched1 has free funds at block #1, but nothing else. -// assert_eq!(Vesting::vesting_balance(&2), Some(free_balance - sched1.per_block())); - -// // Add a 3rd schedule. -// let sched2 = VestingInfo::new( -// ED * 30, -// ED, // Vesting over 30 blocks -// 5, -// ); -// assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched2)); - -// System::set_block_number(9); -// // Free balance is equal to the 3 existing schedules total amount. -// let free_balance = Balances::free_balance(&2); -// assert_eq!(free_balance, ED * (10 + 20 + 30)); -// // sched1 and sched2 are freeing funds at block #9. -// assert_eq!(Vesting::vesting_balance(&2), Some(free_balance - sched1.per_block() * 9 - sched2.per_block() * 4)); - -// System::set_block_number(20); -// // At block #20 sched1 is fully unlocked while sched2 and sched0 are partially unlocked. -// assert_eq!( -// Vesting::vesting_balance(&2), -// Some(free_balance - sched1.locked() - sched2.per_block() * 15 - sched0.per_block() * 10) -// ); - -// System::set_block_number(30); -// // At block #30 sched0 and sched1 are fully unlocked while sched2 is partially unlocked. -// assert_eq!( -// Vesting::vesting_balance(&2), -// Some(free_balance - sched1.locked() - sched2.per_block() * 25 - sched0.locked()) -// ); - -// // At block #35 sched2 fully unlocks and thus all schedules funds are unlocked. -// System::set_block_number(35); -// assert_eq!(Vesting::vesting_balance(&2), Some(0)); -// // Since we have not called any extrinsics that would unlock funds the schedules -// // are still in storage, -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); -// // but once we unlock the funds, they are removed from storage. -// vest_and_assert_no_vesting::(2); -// }); -// } - -// #[test] -// fn unvested_balance_should_not_transfer() { -// ExtBuilder::default().existential_deposit(10).build().execute_with(|| { -// let user1_free_balance = Balances::free_balance(&1); -// assert_eq!(user1_free_balance, 100); // Account 1 has free balance -// // Account 1 has only 5 units vested at block 1 (plus 50 unvested) -// assert_eq!(Vesting::vesting_balance(&1), Some(45)); -// println!("{}", Balances::balance_on_hold(&LockType::Evaluation(0), &1)); -// // Account 1 cannot send more than vested amount... -// assert_noop!(Balances::transfer_allow_death(Some(1).into(), 2, 56), TokenError::Frozen); -// }); -// } - -// #[test] -// fn vested_balance_should_transfer() { -// ExtBuilder::default().existential_deposit(10).build().execute_with(|| { -// let user1_free_balance = Balances::free_balance(&1); -// assert_eq!(user1_free_balance, 100); // Account 1 has free balance -// // Account 1 has only 5 units vested at block 1 (plus 50 unvested) -// assert_eq!(Vesting::vesting_balance(&1), Some(45)); -// assert_ok!(Vesting::vest(Some(1).into())); -// assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 55)); -// }); -// } - -// #[test] -// fn vested_balance_should_transfer_with_multi_sched() { -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// let sched0 = VestingInfo::new(5 * ED, 128, 0); -// assert_ok!(Vesting::vested_transfer(Some(13).into(), 1, sched0)); -// // Total 10*ED locked for all the schedules. -// assert_eq!(Vesting::vesting(&1).unwrap(), vec![sched0, sched0]); +#[test] +fn check_vesting_status() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + let user1_free_balance = Balances::free_balance(&1); + let user2_free_balance = Balances::free_balance(&2); + let user12_free_balance = Balances::free_balance(&12); + assert_eq!(user1_free_balance, ED * 5); // Account 1 has free balance + assert_eq!(user2_free_balance, ED * 1); // Account 2 has free balance + assert_eq!(user12_free_balance, ED * 5); // Account 12 has free balance + let user1_vesting_schedule = VestingInfo::new( + ED * 5, + 128, // Vesting over 10 blocks + 0, + ); + let user2_vesting_schedule = VestingInfo::new( + ED * 20, + ED, // Vesting over 19 blocks + 10, + ); + let user12_vesting_schedule = VestingInfo::new( + ED * 5, + 64, // Vesting over 20 blocks + 10, + ); + assert_eq!(Vesting::vesting(&1).unwrap(), vec![user1_vesting_schedule]); // Account 1 has a vesting schedule + assert_eq!(Vesting::vesting(&2).unwrap(), vec![user2_vesting_schedule]); // Account 2 has a vesting schedule + assert_eq!(Vesting::vesting(&12).unwrap(), vec![user12_vesting_schedule]); // Account 12 has a vesting schedule + + // Account 1 has only 128 units vested from their illiquid ED * 5 units at block 1 + assert_eq!(Vesting::vesting_balance(&1), Some(128 * 9)); + // Account 2 has their full balance locked + assert_eq!(Vesting::vesting_balance(&2), Some(user2_free_balance)); + // Account 12 has only their illiquid funds locked + assert_eq!(Vesting::vesting_balance(&12), Some(user12_free_balance)); + + System::set_block_number(10); + assert_eq!(System::block_number(), 10); + + // Account 1 has fully vested by block 10 + assert_eq!(Vesting::vesting_balance(&1), Some(0)); + // Account 2 has started vesting by block 10 + assert_eq!(Vesting::vesting_balance(&2), Some(user2_free_balance)); + // Account 12 has started vesting by block 10 + assert_eq!(Vesting::vesting_balance(&12), Some(user12_free_balance)); + + System::set_block_number(30); + assert_eq!(System::block_number(), 30); + + assert_eq!(Vesting::vesting_balance(&1), Some(0)); // Account 1 is still fully vested, and not negative + assert_eq!(Vesting::vesting_balance(&2), Some(0)); // Account 2 has fully vested by block 30 + assert_eq!(Vesting::vesting_balance(&12), Some(0)); // Account 2 has fully vested by block 30 + + // Once we unlock the funds, they are removed from storage. + vest_and_assert_no_vesting::(1); + vest_and_assert_no_vesting::(2); + vest_and_assert_no_vesting::(12); + }); +} -// let user1_free_balance = Balances::free_balance(&1); -// assert_eq!(user1_free_balance, 3840); // Account 1 has free balance +// // #[test] +// // fn check_vesting_status_for_multi_schedule_account() { +// // ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { +// // assert_eq!(System::block_number(), 1); +// // let sched0 = VestingInfo::new( +// // ED * 20, +// // ED, // Vesting over 20 blocks +// // 10, +// // ); +// // // Account 2 already has a vesting schedule. +// // assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + +// // // Account 2's free balance is from sched0. +// // let free_balance = Balances::free_balance(&2); +// // assert_eq!(free_balance, ED * (1)); +// // assert_eq!(Vesting::vesting_balance(&2), Some(free_balance)); + +// // // Add a 2nd schedule that is already unlocking by block #1. +// // let sched1 = VestingInfo::new( +// // ED * 10, +// // ED, // Vesting over 10 blocks +// // 0, +// // ); +// // assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1, LockType::Participation(0))); +// // // Free balance is equal to the two existing schedules total amount. +// // // TODO ^: Why? The free balance is still the same, no? +// // // let free_balance = Balances::free_balance(&2); +// // // OG: assert_eq!(free_balance, ED * (10 + 20)); +// // // The most recently added schedule exists. +// // assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); +// // // sched1 has free funds at block #1, but nothing else. +// // // TODO: Why? +// // // OG: assert_eq!(Vesting::vesting_balance(&2), Some(free_balance - sched1.per_block())); + +// // // Add a 3rd schedule. +// // let sched2 = VestingInfo::new( +// // ED * 30, +// // ED, // Vesting over 30 blocks +// // 5, +// // ); +// // assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched2, LockType::Participation(0))); + +// // System::set_block_number(9); +// // // Free balance is equal to the 3 existing schedules total amount. +// // let free_balance = Balances::free_balance(&2); +// // assert_eq!(free_balance, ED * (10 + 20 + 30)); +// // // sched1 and sched2 are freeing funds at block #9. +// // assert_eq!(Vesting::vesting_balance(&2), Some(free_balance - sched1.per_block() * 9 - sched2.per_block() * 4)); + +// // System::set_block_number(20); +// // // At block #20 sched1 is fully unlocked while sched2 and sched0 are partially unlocked. +// // assert_eq!( +// // Vesting::vesting_balance(&2), +// // Some(free_balance - sched1.locked() - sched2.per_block() * 15 - sched0.per_block() * 10) +// // ); + +// // System::set_block_number(30); +// // // At block #30 sched0 and sched1 are fully unlocked while sched2 is partially unlocked. +// // assert_eq!( +// // Vesting::vesting_balance(&2), +// // Some(free_balance - sched1.locked() - sched2.per_block() * 25 - sched0.locked()) +// // ); + +// // // At block #35 sched2 fully unlocks and thus all schedules funds are unlocked. +// // System::set_block_number(35); +// // assert_eq!(Vesting::vesting_balance(&2), Some(0)); +// // // Since we have not called any extrinsics that would unlock funds the schedules +// // // are still in storage, +// // assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); +// // // but once we unlock the funds, they are removed from storage. +// // vest_and_assert_no_vesting::(2); +// // }); +// // } -// // Account 1 has only 256 units unlocking at block 1 (plus 1280 already fee). -// assert_eq!(Vesting::vesting_balance(&1), Some(2304)); -// assert_ok!(Vesting::vest(Some(1).into())); -// assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 1536)); -// }); -// } +#[test] +fn unvested_balance_should_not_transfer() { + ExtBuilder::default().existential_deposit(10).build().execute_with(|| { + let user1_free_balance = Balances::free_balance(&1); + assert_eq!(user1_free_balance, 50); // Account 1 has free balance + // Account 1 has only 5 units vested at block 1 (plus 50 unvested) + assert_eq!(Vesting::vesting_balance(&1), Some(45)); + println!("{}", Balances::balance_on_hold(&LockType::Evaluation(0), &1)); + // Account 1 cannot send more than vested amount... + assert_noop!(Balances::transfer_allow_death(Some(1).into(), 2, 56), TokenError::FundsUnavailable); + }); +} -// #[test] -// fn non_vested_cannot_vest() { -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// assert!(!>::contains_key(4)); -// assert_noop!(Vesting::vest(Some(4).into()), Error::::NotVesting); -// }); -// } +#[test] +fn vested_balance_should_transfer() { + ExtBuilder::default().existential_deposit(10).build().execute_with(|| { + assert_eq!(System::block_number(), 1); + let user1_free_balance = Balances::free_balance(&1); + assert_eq!(user1_free_balance, 50); // Account 1 has free balance + // Account 1 has only 5 units vested at block 1 (plus 50 unvested) + assert_eq!(Vesting::vesting_balance(&1), Some(45)); + assert_noop!(Balances::transfer_allow_death(Some(1).into(), 2, 45), TokenError::Frozen); // Account 1 free balance - ED is < 45 + assert_ok!(Vesting::vest(Some(1).into(), LockType::Participation(0))); + let user1_free_balance = Balances::free_balance(&1); + assert_eq!(user1_free_balance, 55); // Account 1 has free balance + // Account 1 has vested 1 unit at block 1 (plus 50 unvested) + assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 45)); // After the vest it can now send the 45 UNIT + }); +} -// #[test] -// fn vested_balance_should_transfer_using_vest_other() { -// ExtBuilder::default().existential_deposit(10).build().execute_with(|| { -// let user1_free_balance = Balances::free_balance(&1); -// assert_eq!(user1_free_balance, 100); // Account 1 has free balance -// // Account 1 has only 5 units vested at block 1 (plus 50 unvested) -// assert_eq!(Vesting::vesting_balance(&1), Some(45)); -// assert_ok!(Vesting::vest_other(Some(2).into(), 1)); -// assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 55)); -// }); -// } +#[test] +fn vested_balance_should_transfer_with_multi_sched() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + // Prep + assert_eq!(System::block_number(), 1); + let sched0 = VestingInfo::new(5 * ED, 128, 0); + let user1_initial_free_balance = Balances::free_balance(&1); + assert_eq!(user1_initial_free_balance, 1280); // Account 1 has free balance + + // Account "13" checks + let user13_initial_free_balance = Balances::balance(&13); + // Amount set in Genesis + assert_eq!(user13_initial_free_balance, 2559744); + assert_ok!(Vesting::vested_transfer(Some(13).into(), 1, sched0, LockType::Participation(0))); + let user13_free_balance = Balances::balance(&13); + assert_eq!(user13_free_balance, user13_initial_free_balance - sched0.locked()); + + // Account "1" has 2 release schedule applied now: one from the Genesis and one from the transfer + assert_eq!(Vesting::vesting(&1).unwrap(), vec![sched0, sched0]); + let user1_free_balance = Balances::free_balance(&1); + assert_eq!(user1_free_balance, user1_initial_free_balance + (2 * sched0.per_block())); + + // + assert_eq!(Vesting::vesting_balance(&1), Some(1536)); + assert_ok!(Vesting::vest(Some(1).into(), LockType::Participation(0))); + assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 1536 - ED)); + }); +} -// #[test] -// fn vested_balance_should_transfer_using_vest_other_with_multi_sched() { -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// let sched0 = VestingInfo::new(5 * ED, 128, 0); -// assert_ok!(Vesting::vested_transfer(Some(13).into(), 1, sched0)); -// // Total of 10*ED of locked for all the schedules. -// assert_eq!(Vesting::vesting(&1).unwrap(), vec![sched0, sched0]); +#[test] +fn non_vested_cannot_vest() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + assert!(!>::contains_key(4)); + assert_noop!(Vesting::vest(Some(4).into(), LockType::Participation(0)), Error::::NotVesting); + }); +} -// let user1_free_balance = Balances::free_balance(&1); -// assert_eq!(user1_free_balance, 3840); // Account 1 has free balance +#[test] +fn vested_balance_should_transfer_using_vest_other() { + ExtBuilder::default().existential_deposit(10).build().execute_with(|| { + let user1_free_balance = Balances::free_balance(&1); + assert_eq!(user1_free_balance, 50); // Account 1 has free balance + // Account 1 has only 5 units vested at block 1 (plus 50 unvested) + assert_eq!(Vesting::vesting_balance(&1), Some(45)); + assert_ok!(Vesting::vest_other(Some(2).into(), 1, LockType::Participation(0))); + assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 55 - 10)); + }); +} -// // Account 1 has only 256 units unlocking at block 1 (plus 1280 already free). -// assert_eq!(Vesting::vesting_balance(&1), Some(2304)); -// assert_ok!(Vesting::vest_other(Some(2).into(), 1)); -// assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 1536)); -// }); -// } +#[test] +fn vested_balance_should_transfer_using_vest_other_with_multi_sched() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + let sched0 = VestingInfo::new(5 * ED, 128, 0); + assert_ok!(Vesting::vested_transfer(Some(13).into(), 1, sched0, LockType::Participation(0))); + // Total of 10*ED of locked for all the schedules. + assert_eq!(Vesting::vesting(&1).unwrap(), vec![sched0, sched0]); + + let user1_free_balance = Balances::free_balance(&1); + assert_eq!(user1_free_balance, 1536); // Account 1 has free balance + + // Account 1 has only 256 units unlocking at block 1 (plus 1280 already free). + assert_eq!(Vesting::vesting_balance(&1), Some(1536)); + assert_ok!(Vesting::vest_other(Some(2).into(), 1, LockType::Participation(0))); + assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 1536 - ED)); + }); +} // #[test] // fn non_vested_cannot_vest_other() { @@ -1013,7 +1034,6 @@ where // }); // } - // TODO #[test] fn set_release_schedule() { @@ -1039,11 +1059,7 @@ fn set_release_schedule() { assert_eq!(Vesting::vesting_balance(&3), None); // Set release schedule to release the locked amount, starting from now, one ED per block. - let user3_vesting_schedule = VestingInfo::new( - user_3_on_hold_balance, - ED, - System::block_number(), - ); + let user3_vesting_schedule = VestingInfo::new(user_3_on_hold_balance, ED, System::block_number()); assert_ok!(Vesting::release_schedule(Some(3).into(), user3_vesting_schedule)); assert_eq!(Vesting::vesting_balance(&3), Some(15 * ED)); @@ -1054,7 +1070,6 @@ fn set_release_schedule() { let user_3_free_balance = Balances::free_balance(&3); assert_eq!(user_3_free_balance, 16 * ED); - // 2 ED can be "released" System::set_block_number(3); assert_eq!(Vesting::vesting_balance(&3), Some(13 * ED)); @@ -1069,7 +1084,43 @@ fn set_release_schedule() { vest_and_assert_no_vesting::(3); let user_3_free_balance = Balances::free_balance(&3); assert_eq!(user_3_free_balance, 30 * ED); + }); +} + +// TODO +#[test] +fn cannot_release_different_reason() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + assert_eq!(System::block_number(), 1); + // Initial Status + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 30 * ED); // 7680 ED + let user_3_reserved_balance = Balances::reserved_balance(&3); + assert_eq!(user_3_reserved_balance, 0); + let user_3_on_hold_balance = Balances::balance_on_hold(&LockType::Participation(0), &3); + assert_eq!(user_3_on_hold_balance, 0); + assert_eq!(Vesting::vesting_balance(&3), None); + + // Hold 15 ED + assert_ok!(Balances::hold(&LockType::Participation(0), &3, 15 * ED)); + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 15 * ED); + let user_3_on_hold_balance = Balances::balance_on_hold(&LockType::Participation(0), &3); + assert_eq!(user_3_on_hold_balance, 15 * ED); + let user_3_reserved_balance = Balances::reserved_balance(&3); + assert_eq!(user_3_reserved_balance, 15 * ED); + assert_eq!(Vesting::vesting_balance(&3), None); + // Set release schedule to release the locked amount, starting from now, one ED per block. + let user3_vesting_schedule = VestingInfo::new(user_3_on_hold_balance, ED, System::block_number()); + assert_ok!(Vesting::release_schedule(Some(3).into(), user3_vesting_schedule)); + assert_eq!(Vesting::vesting_balance(&3), Some(15 * ED)); + // 1 ED can be "released", we need to call vest to release it. + System::set_block_number(2); + assert_eq!(Vesting::vesting_balance(&3), Some(14 * ED)); + assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(1))); + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 15 * ED); }); -} \ No newline at end of file +} From 280713a84a3440447e3eb599ba2581e43735bbf6 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Wed, 19 Jul 2023 15:39:22 +0200 Subject: [PATCH 13/80] feat: add the Ser and Des trait to LockType --- polimec-skeleton/pallets/funding/src/types.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/polimec-skeleton/pallets/funding/src/types.rs b/polimec-skeleton/pallets/funding/src/types.rs index 150bb0929..a828ba790 100644 --- a/polimec-skeleton/pallets/funding/src/types.rs +++ b/polimec-skeleton/pallets/funding/src/types.rs @@ -55,6 +55,7 @@ pub mod config_types { /// Enum used to identify PLMC holds #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen, Copy, Ord, PartialOrd)] + #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub enum LockType { Evaluation(ProjectId), Participation(ProjectId), From f0f063f8a9b7ed61435918d67c394f53e399d4ce Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Wed, 19 Jul 2023 15:40:09 +0200 Subject: [PATCH 14/80] feat: the vesting_balance now uses the latest Inspect API --- .../pallets/linear-release/src/impls.rs | 16 +++------------- .../pallets/linear-release/src/traits.rs | 2 +- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/impls.rs b/polimec-skeleton/pallets/linear-release/src/impls.rs index f8d05f755..577bb028c 100644 --- a/polimec-skeleton/pallets/linear-release/src/impls.rs +++ b/polimec-skeleton/pallets/linear-release/src/impls.rs @@ -134,11 +134,7 @@ impl Pallet { )?; Self::deposit_event(Event::::VestingCompleted { account: who.clone() }); } else { - let free_balance_now = T::Currency::balance(who); let alredy_holded = T::Currency::balance_on_hold(&reason, who); - println!("write_lock: free_balance_now: {:?}", free_balance_now); - println!("write_lock: alredy_holded: {:?}", alredy_holded); - println!("write_lock: total_locked_now: {:?}", total_locked_now); let to_release = alredy_holded.saturating_sub(total_locked_now); T::Currency::release(&reason, who, to_release, Precision::BestEffort)?; Self::deposit_event(Event::::VestingUpdated { account: who.clone(), unvested: total_locked_now }); @@ -170,9 +166,6 @@ impl Pallet { let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), VestingAction::Passive)?; - println!("do_vest: schedules: {:?}", schedules); - println!("do_vest: locked_now: {:?}", locked_now); - Self::write_vesting(&who, schedules)?; Self::write_lock(&who, locked_now, reason)?; @@ -221,21 +214,18 @@ impl Pallet { } } -impl ReleaseSchedule, ReasonOf> for Pallet -// where -// BalanceOf: MaybeSerializeDeserialize + Debug, -{ +impl ReleaseSchedule, ReasonOf> for Pallet { type Currency = T::Currency; type Moment = BlockNumberFor; /// Get the amount that is currently being vested and cannot be transferred out of this account. - fn vesting_balance(who: &T::AccountId) -> Option> { + fn vesting_balance(who: &T::AccountId, reason: ReasonOf) -> Option> { if let Some(v) = Self::vesting(who) { let now = >::block_number(); let total_locked_now = v.iter().fold(Zero::zero(), |total, schedule| { schedule.locked_at::(now).saturating_add(total) }); - Some(T::Currency::balance(who).min(total_locked_now)) + Some(T::Currency::balance_on_hold(&reason, who).min(total_locked_now)) } else { None } diff --git a/polimec-skeleton/pallets/linear-release/src/traits.rs b/polimec-skeleton/pallets/linear-release/src/traits.rs index 0e53bd67f..dec58e76f 100644 --- a/polimec-skeleton/pallets/linear-release/src/traits.rs +++ b/polimec-skeleton/pallets/linear-release/src/traits.rs @@ -16,7 +16,7 @@ pub trait ReleaseSchedule { /// Get the amount that is currently being vested and cannot be transferred out of this account. /// Returns `None` if the account has no vesting schedule. - fn vesting_balance(who: &AccountId) -> Option<>::Balance>; + fn vesting_balance(who: &AccountId, reason: Reason) -> Option<>::Balance>; /// Adds a release schedule to a given account. /// From b5830d8c789df4ea2b62e7688945e353d249b6fc Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Wed, 19 Jul 2023 15:40:30 +0200 Subject: [PATCH 15/80] tests: git gud --- .../pallets/linear-release/src/tests.rs | 1822 +++++++++-------- 1 file changed, 942 insertions(+), 880 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/tests.rs b/polimec-skeleton/pallets/linear-release/src/tests.rs index 2cc05ea64..fe63f1a72 100644 --- a/polimec-skeleton/pallets/linear-release/src/tests.rs +++ b/polimec-skeleton/pallets/linear-release/src/tests.rs @@ -22,7 +22,7 @@ where T: pallet::Config, { // Its ok for this to fail because the user may already have no schedules. - let _result = Vesting::vest(Some(account).into(), LockType::Participation(0)); + let _result: Result<(), DispatchError> = Vesting::vest(Some(account).into(), LockType::Participation(0)); assert!(!>::contains_key(account)); } @@ -55,28 +55,28 @@ fn check_vesting_status() { assert_eq!(Vesting::vesting(&12).unwrap(), vec![user12_vesting_schedule]); // Account 12 has a vesting schedule // Account 1 has only 128 units vested from their illiquid ED * 5 units at block 1 - assert_eq!(Vesting::vesting_balance(&1), Some(128 * 9)); + assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(128 * 9)); // Account 2 has their full balance locked - assert_eq!(Vesting::vesting_balance(&2), Some(user2_free_balance)); + assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(ED * 20)); // Account 12 has only their illiquid funds locked - assert_eq!(Vesting::vesting_balance(&12), Some(user12_free_balance)); + assert_eq!(Vesting::vesting_balance(&12, LockType::Participation(0)), Some(ED * 5)); System::set_block_number(10); assert_eq!(System::block_number(), 10); // Account 1 has fully vested by block 10 - assert_eq!(Vesting::vesting_balance(&1), Some(0)); + assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(0)); // Account 2 has started vesting by block 10 - assert_eq!(Vesting::vesting_balance(&2), Some(user2_free_balance)); + assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(ED * 20)); // Account 12 has started vesting by block 10 - assert_eq!(Vesting::vesting_balance(&12), Some(user12_free_balance)); + assert_eq!(Vesting::vesting_balance(&12, LockType::Participation(0)), Some(ED * 5)); System::set_block_number(30); assert_eq!(System::block_number(), 30); - assert_eq!(Vesting::vesting_balance(&1), Some(0)); // Account 1 is still fully vested, and not negative - assert_eq!(Vesting::vesting_balance(&2), Some(0)); // Account 2 has fully vested by block 30 - assert_eq!(Vesting::vesting_balance(&12), Some(0)); // Account 2 has fully vested by block 30 + assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(0)); // Account 1 is still fully vested, and not negative + assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(0)); // Account 2 has fully vested by block 30 + assert_eq!(Vesting::vesting_balance(&12, LockType::Participation(0)), Some(0)); // Account 2 has fully vested by block 30 // Once we unlock the funds, they are removed from storage. vest_and_assert_no_vesting::(1); @@ -85,79 +85,84 @@ fn check_vesting_status() { }); } -// // #[test] -// // fn check_vesting_status_for_multi_schedule_account() { -// // ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// // assert_eq!(System::block_number(), 1); -// // let sched0 = VestingInfo::new( -// // ED * 20, -// // ED, // Vesting over 20 blocks -// // 10, -// // ); -// // // Account 2 already has a vesting schedule. -// // assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); - -// // // Account 2's free balance is from sched0. -// // let free_balance = Balances::free_balance(&2); -// // assert_eq!(free_balance, ED * (1)); -// // assert_eq!(Vesting::vesting_balance(&2), Some(free_balance)); - -// // // Add a 2nd schedule that is already unlocking by block #1. -// // let sched1 = VestingInfo::new( -// // ED * 10, -// // ED, // Vesting over 10 blocks -// // 0, -// // ); -// // assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1, LockType::Participation(0))); -// // // Free balance is equal to the two existing schedules total amount. -// // // TODO ^: Why? The free balance is still the same, no? -// // // let free_balance = Balances::free_balance(&2); -// // // OG: assert_eq!(free_balance, ED * (10 + 20)); -// // // The most recently added schedule exists. -// // assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); -// // // sched1 has free funds at block #1, but nothing else. -// // // TODO: Why? -// // // OG: assert_eq!(Vesting::vesting_balance(&2), Some(free_balance - sched1.per_block())); - -// // // Add a 3rd schedule. -// // let sched2 = VestingInfo::new( -// // ED * 30, -// // ED, // Vesting over 30 blocks -// // 5, -// // ); -// // assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched2, LockType::Participation(0))); - -// // System::set_block_number(9); -// // // Free balance is equal to the 3 existing schedules total amount. -// // let free_balance = Balances::free_balance(&2); -// // assert_eq!(free_balance, ED * (10 + 20 + 30)); -// // // sched1 and sched2 are freeing funds at block #9. -// // assert_eq!(Vesting::vesting_balance(&2), Some(free_balance - sched1.per_block() * 9 - sched2.per_block() * 4)); - -// // System::set_block_number(20); -// // // At block #20 sched1 is fully unlocked while sched2 and sched0 are partially unlocked. -// // assert_eq!( -// // Vesting::vesting_balance(&2), -// // Some(free_balance - sched1.locked() - sched2.per_block() * 15 - sched0.per_block() * 10) -// // ); - -// // System::set_block_number(30); -// // // At block #30 sched0 and sched1 are fully unlocked while sched2 is partially unlocked. -// // assert_eq!( -// // Vesting::vesting_balance(&2), -// // Some(free_balance - sched1.locked() - sched2.per_block() * 25 - sched0.locked()) -// // ); - -// // // At block #35 sched2 fully unlocks and thus all schedules funds are unlocked. -// // System::set_block_number(35); -// // assert_eq!(Vesting::vesting_balance(&2), Some(0)); -// // // Since we have not called any extrinsics that would unlock funds the schedules -// // // are still in storage, -// // assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); -// // // but once we unlock the funds, they are removed from storage. -// // vest_and_assert_no_vesting::(2); -// // }); -// // } +#[test] +fn check_vesting_status_for_multi_schedule_account() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + assert_eq!(System::block_number(), 1); + let sched0 = VestingInfo::new( + ED * 20, + ED, // Vesting over 20 blocks + 10, + ); + // Account 2 already has a vesting schedule. + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + + // Account 2's free balance is the one set in Genesis inside the Balances pallet. + let balance = Balances::balance(&2); + assert_eq!(balance, ED * (1)); + assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(ED * (20))); + + // Add a 2nd schedule that is already unlocking by block #1. + let sched1 = VestingInfo::new( + ED * 10, + ED, // Vesting over 10 blocks + 0, + ); + assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1, LockType::Participation(0))); + // Free balance is the one set in Genesis inside the Balances pallet + // + the one from the vested transfer. + // BUT NOT the one in sched0, since the vesting will start at block #10. + let balance = Balances::balance(&2); + assert_eq!(balance, ED * (2)); + // The most recently added schedule exists. + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); + + // Add a 3rd schedule. + let sched2 = VestingInfo::new( + ED * 30, + ED, // Vesting over 30 blocks + 5, + ); + assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched2, LockType::Participation(0))); + + System::set_block_number(9); + assert_eq!(System::block_number(), 9); + + // Free balance is still the same. + let balance = Balances::balance(&2); + assert_eq!(balance, ED * (2)); + // Let's release some funds from sched1 and sched2. + assert_ok!(Vesting::vest(Some(2).into(), LockType::Participation(0))); + let balance = Balances::balance(&2); + assert_eq!(balance, ED * (1 + 9 + 4)); // 1 from Genesis + 9 from sched1 + 4 from sched2 + + // sched1 and sched2 are freeing funds at block #9, but sched0 is not. + assert_eq!( + Vesting::vesting_balance(&2, LockType::Participation(0)), + Some(sched0.per_block() * 20 + sched1.per_block() * 1 + sched2.per_block() * 26) + ); + + System::set_block_number(20); + // At block #20 sched1 is fully unlocked while sched2 and sched0 are partially unlocked. + assert_eq!( + Vesting::vesting_balance(&2, LockType::Participation(0)), + Some(sched0.per_block() * 10 + sched2.per_block() * 15) + ); + + System::set_block_number(30); + // At block #30 sched0 and sched1 are fully unlocked while sched2 is partially unlocked. + assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(sched2.per_block() * 5)); + + // At block #35 sched2 fully unlocks and thus all schedules funds are unlocked. + System::set_block_number(35); + assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(0)); + // Since we have not called any extrinsics that would unlock funds the schedules + // are still in storage, + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); + // but once we unlock the funds, they are removed from storage. + vest_and_assert_no_vesting::(2); + }); +} #[test] fn unvested_balance_should_not_transfer() { @@ -165,9 +170,7 @@ fn unvested_balance_should_not_transfer() { let user1_free_balance = Balances::free_balance(&1); assert_eq!(user1_free_balance, 50); // Account 1 has free balance // Account 1 has only 5 units vested at block 1 (plus 50 unvested) - assert_eq!(Vesting::vesting_balance(&1), Some(45)); - println!("{}", Balances::balance_on_hold(&LockType::Evaluation(0), &1)); - // Account 1 cannot send more than vested amount... + assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(45)); // Account 1 cannot send more than vested amount... assert_noop!(Balances::transfer_allow_death(Some(1).into(), 2, 56), TokenError::FundsUnavailable); }); } @@ -179,7 +182,7 @@ fn vested_balance_should_transfer() { let user1_free_balance = Balances::free_balance(&1); assert_eq!(user1_free_balance, 50); // Account 1 has free balance // Account 1 has only 5 units vested at block 1 (plus 50 unvested) - assert_eq!(Vesting::vesting_balance(&1), Some(45)); + assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(45)); assert_noop!(Balances::transfer_allow_death(Some(1).into(), 2, 45), TokenError::Frozen); // Account 1 free balance - ED is < 45 assert_ok!(Vesting::vest(Some(1).into(), LockType::Participation(0))); let user1_free_balance = Balances::free_balance(&1); @@ -211,10 +214,11 @@ fn vested_balance_should_transfer_with_multi_sched() { let user1_free_balance = Balances::free_balance(&1); assert_eq!(user1_free_balance, user1_initial_free_balance + (2 * sched0.per_block())); - // - assert_eq!(Vesting::vesting_balance(&1), Some(1536)); + // + assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(9 * ED)); assert_ok!(Vesting::vest(Some(1).into(), LockType::Participation(0))); - assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 1536 - ED)); + let user1_free_balance = Balances::balance(&1); + assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, user1_free_balance - ED)); }); } @@ -231,8 +235,8 @@ fn vested_balance_should_transfer_using_vest_other() { ExtBuilder::default().existential_deposit(10).build().execute_with(|| { let user1_free_balance = Balances::free_balance(&1); assert_eq!(user1_free_balance, 50); // Account 1 has free balance - // Account 1 has only 5 units vested at block 1 (plus 50 unvested) - assert_eq!(Vesting::vesting_balance(&1), Some(45)); + // Account 1 has only 5 units vested at block 1 (plus 50 unvested) + assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(45)); assert_ok!(Vesting::vest_other(Some(2).into(), 1, LockType::Participation(0))); assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 55 - 10)); }); @@ -250,789 +254,847 @@ fn vested_balance_should_transfer_using_vest_other_with_multi_sched() { assert_eq!(user1_free_balance, 1536); // Account 1 has free balance // Account 1 has only 256 units unlocking at block 1 (plus 1280 already free). - assert_eq!(Vesting::vesting_balance(&1), Some(1536)); + assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(9 * ED)); assert_ok!(Vesting::vest_other(Some(2).into(), 1, LockType::Participation(0))); assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 1536 - ED)); }); } -// #[test] -// fn non_vested_cannot_vest_other() { -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// assert!(!>::contains_key(4)); -// assert_noop!(Vesting::vest_other(Some(3).into(), 4), Error::::NotVesting); -// }); -// } - -// #[test] -// fn extra_balance_should_transfer() { -// ExtBuilder::default().existential_deposit(10).build().execute_with(|| { -// assert_ok!(Balances::transfer_allow_death(Some(3).into(), 1, 100)); -// assert_ok!(Balances::transfer_allow_death(Some(3).into(), 2, 100)); - -// let user1_free_balance = Balances::free_balance(&1); -// assert_eq!(user1_free_balance, 150); // Account 1 has 100 more free balance than normal - -// let user2_free_balance = Balances::free_balance(&2); -// assert_eq!(user2_free_balance, 110); // Account 2 has 100 more free balance than normal - -// // Account 1 has only 5 units vested at block 1 (plus 150 unvested) -// assert_eq!(Vesting::vesting_balance(&1), Some(45)); -// assert_ok!(Vesting::vest(Some(1).into())); -// let user1_free_balance2 = Balances::free_balance(&1); -// assert_eq!(user1_free_balance2, 195); // Account 1 has 100 more free balance than normal -// assert_ok!(Balances::transfer_allow_death(Some(1).into(), 3, 155)); // Account 1 can send extra units gained - -// // Account 2 has no units vested at block 1, but gained 100 -// assert_eq!(Vesting::vesting_balance(&2), Some(110)); -// assert_ok!(Vesting::vest(Some(2).into())); -// assert_ok!(Balances::transfer_allow_death(Some(2).into(), 3, 100)); // Account 2 can send extra -// // units gained -// }); -// } - -// #[test] -// fn liquid_funds_should_transfer_with_delayed_vesting() { -// ExtBuilder::default().existential_deposit(256).build().execute_with(|| { -// let user12_free_balance = Balances::free_balance(&12); - -// assert_eq!(user12_free_balance, 2560); // Account 12 has free balance -// // Account 12 has liquid funds -// assert_eq!(Vesting::vesting_balance(&12), Some(user12_free_balance - 256 * 5)); - -// // Account 12 has delayed vesting -// let user12_vesting_schedule = VestingInfo::new( -// 256 * 5, -// 64, // Vesting over 20 blocks -// 10, -// ); -// assert_eq!(Vesting::vesting(&12).unwrap(), vec![user12_vesting_schedule]); - -// // Account 12 can still send liquid funds -// assert_ok!(Balances::transfer_allow_death(Some(12).into(), 3, 256 * 5)); -// }); -// } - -// #[test] -// fn vested_transfer_works() { -// ExtBuilder::default().existential_deposit(256).build().execute_with(|| { -// let user3_free_balance = Balances::free_balance(&3); -// let user4_free_balance = Balances::free_balance(&4); -// assert_eq!(user3_free_balance, 256 * 30); -// assert_eq!(user4_free_balance, 256 * 40); -// // Account 4 should not have any vesting yet. -// assert_eq!(Vesting::vesting(&4), None); -// // Make the schedule for the new transfer. -// let new_vesting_schedule = VestingInfo::new( -// 256 * 5, -// 64, // Vesting over 20 blocks -// 10, -// ); -// assert_ok!(Vesting::vested_transfer(Some(3).into(), 4, new_vesting_schedule)); -// // Now account 4 should have vesting. -// assert_eq!(Vesting::vesting(&4).unwrap(), vec![new_vesting_schedule]); -// // Ensure the transfer happened correctly. -// let user3_free_balance_updated = Balances::free_balance(&3); -// assert_eq!(user3_free_balance_updated, 256 * 25); -// let user4_free_balance_updated = Balances::free_balance(&4); -// assert_eq!(user4_free_balance_updated, 256 * 45); -// // Account 4 has 5 * 256 locked. -// assert_eq!(Vesting::vesting_balance(&4), Some(256 * 5)); - -// System::set_block_number(20); -// assert_eq!(System::block_number(), 20); - -// // Account 4 has 5 * 64 units vested by block 20. -// assert_eq!(Vesting::vesting_balance(&4), Some(10 * 64)); - -// System::set_block_number(30); -// assert_eq!(System::block_number(), 30); - -// // Account 4 has fully vested, -// assert_eq!(Vesting::vesting_balance(&4), Some(0)); -// // and after unlocking its schedules are removed from storage. -// vest_and_assert_no_vesting::(4); -// }); -// } - -// #[test] -// fn vested_transfer_correctly_fails() { -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// let user2_free_balance = Balances::free_balance(&2); -// let user4_free_balance = Balances::free_balance(&4); -// assert_eq!(user2_free_balance, ED * 20); -// assert_eq!(user4_free_balance, ED * 40); - -// // Account 2 should already have a vesting schedule. -// let user2_vesting_schedule = VestingInfo::new( -// ED * 20, -// ED, // Vesting over 20 blocks -// 10, -// ); -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![user2_vesting_schedule]); - -// // Fails due to too low transfer amount. -// let new_vesting_schedule_too_low = VestingInfo::new(::MinVestedTransfer::get() - 1, 64, 10); -// assert_noop!( -// Vesting::vested_transfer(Some(3).into(), 4, new_vesting_schedule_too_low), -// Error::::AmountLow, -// ); - -// // `per_block` is 0, which would result in a schedule with infinite duration. -// let schedule_per_block_0 = VestingInfo::new(::MinVestedTransfer::get(), 0, 10); -// assert_noop!( -// Vesting::vested_transfer(Some(13).into(), 4, schedule_per_block_0), -// Error::::InvalidScheduleParams, -// ); - -// // `locked` is 0. -// let schedule_locked_0 = VestingInfo::new(0, 1, 10); -// assert_noop!(Vesting::vested_transfer(Some(3).into(), 4, schedule_locked_0), Error::::AmountLow,); - -// // Free balance has not changed. -// assert_eq!(user2_free_balance, Balances::free_balance(&2)); -// assert_eq!(user4_free_balance, Balances::free_balance(&4)); -// // Account 4 has no schedules. -// vest_and_assert_no_vesting::(4); -// }); -// } - -// #[test] -// fn vested_transfer_allows_max_schedules() { -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// let mut user_4_free_balance = Balances::free_balance(&4); -// let max_schedules = ::MAX_VESTING_SCHEDULES; -// let sched = VestingInfo::new( -// ::MinVestedTransfer::get(), -// 1, // Vest over 2 * 256 blocks. -// 10, -// ); - -// // Add max amount schedules to user 4. -// for _ in 0..max_schedules { -// assert_ok!(Vesting::vested_transfer(Some(13).into(), 4, sched)); -// } - -// // The schedules count towards vesting balance -// let transferred_amount = ::MinVestedTransfer::get() * max_schedules as u64; -// assert_eq!(Vesting::vesting_balance(&4), Some(transferred_amount)); -// // and free balance. -// user_4_free_balance += transferred_amount; -// assert_eq!(Balances::free_balance(&4), user_4_free_balance); - -// // Cannot insert a 4th vesting schedule when `MaxVestingSchedules` === 3, -// assert_noop!(Vesting::vested_transfer(Some(3).into(), 4, sched), Error::::AtMaxVestingSchedules,); -// // so the free balance does not change. -// assert_eq!(Balances::free_balance(&4), user_4_free_balance); - -// // Account 4 has fully vested when all the schedules end, -// System::set_block_number(::MinVestedTransfer::get() + sched.starting_block()); -// assert_eq!(Vesting::vesting_balance(&4), Some(0)); -// // and after unlocking its schedules are removed from storage. -// vest_and_assert_no_vesting::(4); -// }); -// } - -// #[test] -// fn force_vested_transfer_works() { -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// let user3_free_balance = Balances::free_balance(&3); -// let user4_free_balance = Balances::free_balance(&4); -// assert_eq!(user3_free_balance, ED * 30); -// assert_eq!(user4_free_balance, ED * 40); -// // Account 4 should not have any vesting yet. -// assert_eq!(Vesting::vesting(&4), None); -// // Make the schedule for the new transfer. -// let new_vesting_schedule = VestingInfo::new( -// ED * 5, -// 64, // Vesting over 20 blocks -// 10, -// ); - -// assert_noop!(Vesting::force_vested_transfer(Some(4).into(), 3, 4, new_vesting_schedule), BadOrigin); -// assert_ok!(Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, new_vesting_schedule)); -// // Now account 4 should have vesting. -// assert_eq!(Vesting::vesting(&4).unwrap()[0], new_vesting_schedule); -// assert_eq!(Vesting::vesting(&4).unwrap().len(), 1); -// // Ensure the transfer happened correctly. -// let user3_free_balance_updated = Balances::free_balance(&3); -// assert_eq!(user3_free_balance_updated, ED * 25); -// let user4_free_balance_updated = Balances::free_balance(&4); -// assert_eq!(user4_free_balance_updated, ED * 45); -// // Account 4 has 5 * ED locked. -// assert_eq!(Vesting::vesting_balance(&4), Some(ED * 5)); - -// System::set_block_number(20); -// assert_eq!(System::block_number(), 20); - -// // Account 4 has 5 * 64 units vested by block 20. -// assert_eq!(Vesting::vesting_balance(&4), Some(10 * 64)); - -// System::set_block_number(30); -// assert_eq!(System::block_number(), 30); - -// // Account 4 has fully vested, -// assert_eq!(Vesting::vesting_balance(&4), Some(0)); -// // and after unlocking its schedules are removed from storage. -// vest_and_assert_no_vesting::(4); -// }); -// } - -// #[test] -// fn force_vested_transfer_correctly_fails() { -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// let user2_free_balance = Balances::free_balance(&2); -// let user4_free_balance = Balances::free_balance(&4); -// assert_eq!(user2_free_balance, ED * 21); -// assert_eq!(user4_free_balance, ED * 40); -// // Account 2 should already have a vesting schedule. -// let user2_vesting_schedule = VestingInfo::new( -// ED * 20, -// ED, // Vesting over 20 blocks -// 10, -// ); -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![user2_vesting_schedule]); - -// // Too low transfer amount. -// let new_vesting_schedule_too_low = VestingInfo::new(::MinVestedTransfer::get() - 1, 64, 10); -// assert_noop!( -// Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, new_vesting_schedule_too_low), -// Error::::AmountLow, -// ); - -// // `per_block` is 0. -// let schedule_per_block_0 = VestingInfo::new(::MinVestedTransfer::get(), 0, 10); -// assert_noop!( -// Vesting::force_vested_transfer(RawOrigin::Root.into(), 13, 4, schedule_per_block_0), -// Error::::InvalidScheduleParams, -// ); - -// // `locked` is 0. -// let schedule_locked_0 = VestingInfo::new(0, 1, 10); -// assert_noop!( -// Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, schedule_locked_0), -// Error::::AmountLow, -// ); - -// // Verify no currency transfer happened. -// assert_eq!(user2_free_balance, Balances::free_balance(&2)); -// assert_eq!(user4_free_balance, Balances::free_balance(&4)); -// // Account 4 has no schedules. -// vest_and_assert_no_vesting::(4); -// }); -// } - -// #[test] -// fn force_vested_transfer_allows_max_schedules() { -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// let mut user_4_free_balance = Balances::free_balance(&4); -// let max_schedules = ::MAX_VESTING_SCHEDULES; -// let sched = VestingInfo::new( -// ::MinVestedTransfer::get(), -// 1, // Vest over 2 * 256 blocks. -// 10, -// ); - -// // Add max amount schedules to user 4. -// for _ in 0..max_schedules { -// assert_ok!(Vesting::force_vested_transfer(RawOrigin::Root.into(), 13, 4, sched)); -// } - -// // The schedules count towards vesting balance. -// let transferred_amount = ::MinVestedTransfer::get() * max_schedules as u64; -// assert_eq!(Vesting::vesting_balance(&4), Some(transferred_amount)); -// // and free balance. -// user_4_free_balance += transferred_amount; -// assert_eq!(Balances::free_balance(&4), user_4_free_balance); - -// // Cannot insert a 4th vesting schedule when `MaxVestingSchedules` === 3 -// assert_noop!( -// Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, sched), -// Error::::AtMaxVestingSchedules, -// ); -// // so the free balance does not change. -// assert_eq!(Balances::free_balance(&4), user_4_free_balance); - -// // Account 4 has fully vested when all the schedules end, -// System::set_block_number(::MinVestedTransfer::get() + 10); -// assert_eq!(Vesting::vesting_balance(&4), Some(0)); -// // and after unlocking its schedules are removed from storage. -// vest_and_assert_no_vesting::(4); -// }); -// } - -// #[test] -// fn merge_schedules_that_have_not_started() { -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// // Account 2 should already have a vesting schedule. -// let sched0 = VestingInfo::new( -// ED * 20, -// ED, // Vest over 20 blocks. -// 10, -// ); -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); -// assert_eq!(Balances::usable_balance(&2), 0); - -// // Add a schedule that is identical to the one that already exists. -// assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched0)); -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched0]); -// assert_eq!(Balances::usable_balance(&2), 0); -// assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); - -// // Since we merged identical schedules, the new schedule finishes at the same -// // time as the original, just with double the amount. -// let sched1 = VestingInfo::new( -// sched0.locked() * 2, -// sched0.per_block() * 2, -// 10, // Starts at the block the schedules are merged/ -// ); -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched1]); - -// assert_eq!(Balances::usable_balance(&2), 0); -// }); -// } - -// #[test] -// fn merge_ongoing_schedules() { -// // Merging two schedules that have started will vest both before merging. -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// // Account 2 should already have a vesting schedule. -// let sched0 = VestingInfo::new( -// ED * 20, -// ED, // Vest over 20 blocks. -// 10, -// ); -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); - -// let sched1 = VestingInfo::new( -// ED * 10, -// ED, // Vest over 10 blocks. -// sched0.starting_block() + 5, // Start at block 15. -// ); -// assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1)); -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); - -// // Got to half way through the second schedule where both schedules are actively vesting. -// let cur_block = 20; -// System::set_block_number(cur_block); - -// // Account 2 has no usable balances prior to the merge because they have not unlocked -// // with `vest` yet. -// assert_eq!(Balances::usable_balance(&2), 0); - -// assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); - -// // Merging schedules un-vests all pre-existing schedules prior to merging, which is -// // reflected in account 2's updated usable balance. -// let sched0_vested_now = sched0.per_block() * (cur_block - sched0.starting_block()); -// let sched1_vested_now = sched1.per_block() * (cur_block - sched1.starting_block()); -// assert_eq!(Balances::usable_balance(&2), sched0_vested_now + sched1_vested_now); - -// // The locked amount is the sum of what both schedules have locked at the current block. -// let sched2_locked = -// sched1.locked_at::(cur_block).saturating_add(sched0.locked_at::(cur_block)); -// // End block of the new schedule is the greater of either merged schedule. -// let sched2_end = sched1.ending_block_as_balance::().max(sched0.ending_block_as_balance::()); -// let sched2_duration = sched2_end - cur_block; -// // Based off the new schedules total locked and its duration, we can calculate the -// // amount to unlock per block. -// let sched2_per_block = sched2_locked / sched2_duration; - -// let sched2 = VestingInfo::new(sched2_locked, sched2_per_block, cur_block); -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2]); - -// // And just to double check, we assert the new merged schedule we be cleaned up as expected. -// System::set_block_number(30); -// vest_and_assert_no_vesting::(2); -// }); -// } - -// #[test] -// fn merging_shifts_other_schedules_index() { -// // Schedules being merged are filtered out, schedules to the right of any merged -// // schedule shift left and the merged schedule is always last. -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// let sched0 = VestingInfo::new( -// ED * 10, -// ED, // Vesting over 10 blocks. -// 10, -// ); -// let sched1 = VestingInfo::new( -// ED * 11, -// ED, // Vesting over 11 blocks. -// 11, -// ); -// let sched2 = VestingInfo::new( -// ED * 12, -// ED, // Vesting over 12 blocks. -// 12, -// ); - -// // Account 3 starts out with no schedules, -// assert_eq!(Vesting::vesting(&3), None); -// // and some usable balance. -// let usable_balance = Balances::usable_balance(&3); -// assert_eq!(usable_balance, 30 * ED); - -// let cur_block = 1; -// assert_eq!(System::block_number(), cur_block); - -// // Transfer the above 3 schedules to account 3. -// assert_ok!(Vesting::vested_transfer(Some(4).into(), 3, sched0)); -// assert_ok!(Vesting::vested_transfer(Some(4).into(), 3, sched1)); -// assert_ok!(Vesting::vested_transfer(Some(4).into(), 3, sched2)); - -// // With no schedules vested or merged they are in the order they are created -// assert_eq!(Vesting::vesting(&3).unwrap(), vec![sched0, sched1, sched2]); -// // and the usable balance has not changed. -// assert_eq!(usable_balance, Balances::usable_balance(&3)); - -// assert_ok!(Vesting::merge_schedules(Some(3).into(), 0, 2)); - -// // Create the merged schedule of sched0 & sched2. -// // The merged schedule will have the max possible starting block, -// let sched3_start = sched1.starting_block().max(sched2.starting_block()); -// // `locked` equal to the sum of the two schedules locked through the current block, -// let sched3_locked = sched2.locked_at::(cur_block) + sched0.locked_at::(cur_block); -// // and will end at the max possible block. -// let sched3_end = sched2.ending_block_as_balance::().max(sched0.ending_block_as_balance::()); -// let sched3_duration = sched3_end - sched3_start; -// let sched3_per_block = sched3_locked / sched3_duration; -// let sched3 = VestingInfo::new(sched3_locked, sched3_per_block, sched3_start); - -// // The not touched schedule moves left and the new merged schedule is appended. -// assert_eq!(Vesting::vesting(&3).unwrap(), vec![sched1, sched3]); -// // The usable balance hasn't changed since none of the schedules have started. -// assert_eq!(Balances::usable_balance(&3), usable_balance); -// }); -// } - -// #[test] -// fn merge_ongoing_and_yet_to_be_started_schedules() { -// // Merge an ongoing schedule that has had `vest` called and a schedule that has not already -// // started. -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// // Account 2 should already have a vesting schedule. -// let sched0 = VestingInfo::new( -// ED * 20, -// ED, // Vesting over 20 blocks -// 10, -// ); -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); - -// // Fast forward to half way through the life of sched1. -// let mut cur_block = (sched0.starting_block() + sched0.ending_block_as_balance::()) / 2; -// assert_eq!(cur_block, 20); -// System::set_block_number(cur_block); - -// // Prior to vesting there is no usable balance. -// let mut usable_balance = 0; -// assert_eq!(Balances::usable_balance(&2), usable_balance); -// // Vest the current schedules (which is just sched0 now). -// Vesting::vest(Some(2).into()).unwrap(); - -// // After vesting the usable balance increases by the unlocked amount. -// let sched0_vested_now = sched0.locked() - sched0.locked_at::(cur_block); -// usable_balance += sched0_vested_now; -// assert_eq!(Balances::usable_balance(&2), usable_balance); - -// // Go forward a block. -// cur_block += 1; -// System::set_block_number(cur_block); - -// // And add a schedule that starts after this block, but before sched0 finishes. -// let sched1 = VestingInfo::new( -// ED * 10, -// 1, // Vesting over 256 * 10 (2560) blocks -// cur_block + 1, -// ); -// assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1)); - -// // Merge the schedules before sched1 starts. -// assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); -// // After merging, the usable balance only changes by the amount sched0 vested since we -// // last called `vest` (which is just 1 block). The usable balance is not affected by -// // sched1 because it has not started yet. -// usable_balance += sched0.per_block(); -// assert_eq!(Balances::usable_balance(&2), usable_balance); - -// // The resulting schedule will have the later starting block of the two, -// let sched2_start = sched1.starting_block(); -// // `locked` equal to the sum of the two schedules locked through the current block, -// let sched2_locked = sched0.locked_at::(cur_block) + sched1.locked_at::(cur_block); -// // and will end at the max possible block. -// let sched2_end = sched0.ending_block_as_balance::().max(sched1.ending_block_as_balance::()); -// let sched2_duration = sched2_end - sched2_start; -// let sched2_per_block = sched2_locked / sched2_duration; - -// let sched2 = VestingInfo::new(sched2_locked, sched2_per_block, sched2_start); -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2]); -// }); -// } - -// #[test] -// fn merge_finished_and_ongoing_schedules() { -// // If a schedule finishes by the current block we treat the ongoing schedule, -// // without any alterations, as the merged one. -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// // Account 2 should already have a vesting schedule. -// let sched0 = VestingInfo::new( -// ED * 20, -// ED, // Vesting over 20 blocks. -// 10, -// ); -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); - -// let sched1 = VestingInfo::new( -// ED * 40, -// ED, // Vesting over 40 blocks. -// 10, -// ); -// assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1)); - -// // Transfer a 3rd schedule, so we can demonstrate how schedule indices change. -// // (We are not merging this schedule.) -// let sched2 = VestingInfo::new( -// ED * 30, -// ED, // Vesting over 30 blocks. -// 10, -// ); -// assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched2)); - -// // The schedules are in expected order prior to merging. -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); - -// // Fast forward to sched0's end block. -// let cur_block = sched0.ending_block_as_balance::(); -// System::set_block_number(cur_block); -// assert_eq!(System::block_number(), 30); - -// // Prior to `merge_schedules` and with no vest/vest_other called the user has no usable -// // balance. -// assert_eq!(Balances::usable_balance(&2), 0); -// assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); - -// // sched2 is now the first, since sched0 & sched1 get filtered out while "merging". -// // sched1 gets treated like the new merged schedule by getting pushed onto back -// // of the vesting schedules vec. Note: sched0 finished at the current block. -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2, sched1]); - -// // sched0 has finished, so its funds are fully unlocked. -// let sched0_unlocked_now = sched0.locked(); -// // The remaining schedules are ongoing, so their funds are partially unlocked. -// let sched1_unlocked_now = sched1.locked() - sched1.locked_at::(cur_block); -// let sched2_unlocked_now = sched2.locked() - sched2.locked_at::(cur_block); - -// // Since merging also vests all the schedules, the users usable balance after merging -// // includes all pre-existing schedules unlocked through the current block, including -// // schedules not merged. -// assert_eq!(Balances::usable_balance(&2), sched0_unlocked_now + sched1_unlocked_now + sched2_unlocked_now); -// }); -// } - -// #[test] -// fn merge_finishing_schedules_does_not_create_a_new_one() { -// // If both schedules finish by the current block we don't create new one -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// // Account 2 should already have a vesting schedule. -// let sched0 = VestingInfo::new( -// ED * 20, -// ED, // 20 block duration. -// 10, -// ); -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); - -// // Create sched1 and transfer it to account 2. -// let sched1 = VestingInfo::new( -// ED * 30, -// ED, // 30 block duration. -// 10, -// ); -// assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched1)); -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); - -// let all_scheds_end = -// sched0.ending_block_as_balance::().max(sched1.ending_block_as_balance::()); - -// assert_eq!(all_scheds_end, 40); -// System::set_block_number(all_scheds_end); - -// // Prior to merge_schedules and with no vest/vest_other called the user has no usable -// // balance. -// assert_eq!(Balances::usable_balance(&2), 0); - -// // Merge schedule 0 and 1. -// assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); -// // The user no longer has any more vesting schedules because they both ended at the -// // block they where merged, -// assert!(!>::contains_key(&2)); -// // and their usable balance has increased by the total amount locked in the merged -// // schedules. -// assert_eq!(Balances::usable_balance(&2), sched0.locked() + sched1.locked()); -// }); -// } - -// #[test] -// fn merge_finished_and_yet_to_be_started_schedules() { -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// // Account 2 should already have a vesting schedule. -// let sched0 = VestingInfo::new( -// ED * 20, -// ED, // 20 block duration. -// 10, // Ends at block 30 -// ); -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); - -// let sched1 = VestingInfo::new( -// ED * 30, -// ED * 2, // 30 block duration. -// 35, -// ); -// assert_ok!(Vesting::vested_transfer(Some(13).into(), 2, sched1)); -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); - -// let sched2 = VestingInfo::new( -// ED * 40, -// ED, // 40 block duration. -// 30, -// ); -// // Add a 3rd schedule to demonstrate how sched1 shifts. -// assert_ok!(Vesting::vested_transfer(Some(13).into(), 2, sched2)); -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); - -// System::set_block_number(30); - -// // At block 30, sched0 has finished unlocking while sched1 and sched2 are still fully -// // locked, -// assert_eq!(Vesting::vesting_balance(&2), Some(sched1.locked() + sched2.locked())); -// // but since we have not vested usable balance is still 0. -// assert_eq!(Balances::usable_balance(&2), 0); - -// // Merge schedule 0 and 1. -// assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1)); - -// // sched0 is removed since it finished, and sched1 is removed and then pushed on the back -// // because it is treated as the merged schedule -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2, sched1]); - -// // The usable balance is updated because merging fully unlocked sched0. -// assert_eq!(Balances::usable_balance(&2), sched0.locked()); -// }); -// } - -// #[test] -// fn merge_schedules_throws_proper_errors() { -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// // Account 2 should already have a vesting schedule. -// let sched0 = VestingInfo::new( -// ED * 20, -// ED, // 20 block duration. -// 10, -// ); -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); - -// // Account 2 only has 1 vesting schedule. -// assert_noop!(Vesting::merge_schedules(Some(2).into(), 0, 1), Error::::ScheduleIndexOutOfBounds); - -// // Account 4 has 0 vesting schedules. -// assert_eq!(Vesting::vesting(&4), None); -// assert_noop!(Vesting::merge_schedules(Some(4).into(), 0, 1), Error::::NotVesting); - -// // There are enough schedules to merge but an index is non-existent. -// Vesting::vested_transfer(Some(3).into(), 2, sched0).unwrap(); -// assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched0]); -// assert_noop!(Vesting::merge_schedules(Some(2).into(), 0, 2), Error::::ScheduleIndexOutOfBounds); - -// // It is a storage noop with no errors if the indexes are the same. -// assert_storage_noop!(Vesting::merge_schedules(Some(2).into(), 0, 0).unwrap()); -// }); -// } - -// #[test] -// fn merge_vesting_handles_per_block_0() { -// ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { -// let sched0 = VestingInfo::new( -// ED, 0, // Vesting over 256 blocks. -// 1, -// ); -// assert_eq!(sched0.ending_block_as_balance::(), 257); -// let sched1 = VestingInfo::new( -// ED * 2, -// 0, // Vesting over 512 blocks. -// 10, -// ); -// assert_eq!(sched1.ending_block_as_balance::(), 512u64 + 10); - -// let merged = VestingInfo::new(764, 1, 10); -// assert_eq!(Vesting::merge_vesting_info(5, sched0, sched1), Some(merged)); -// }); -// } - -// #[test] -// fn vesting_info_validate_works() { -// let min_transfer = ::MinVestedTransfer::get(); -// // Does not check for min transfer. -// assert_eq!(VestingInfo::new(min_transfer - 1, 1u64, 10u64).is_valid(), true); - -// // `locked` cannot be 0. -// assert_eq!(VestingInfo::new(0, 1u64, 10u64).is_valid(), false); - -// // `per_block` cannot be 0. -// assert_eq!(VestingInfo::new(min_transfer + 1, 0u64, 10u64).is_valid(), false); - -// // With valid inputs it does not error. -// assert_eq!(VestingInfo::new(min_transfer, 1u64, 10u64).is_valid(), true); -// } - -// #[test] -// fn vesting_info_ending_block_as_balance_works() { -// // Treats `per_block` 0 as 1. -// let per_block_0 = VestingInfo::new(256u32, 0u32, 10u32); -// assert_eq!(per_block_0.ending_block_as_balance::(), 256 + 10); - -// // `per_block >= locked` always results in a schedule ending the block after it starts -// let per_block_gt_locked = VestingInfo::new(256u32, 256 * 2u32, 10u32); -// assert_eq!(per_block_gt_locked.ending_block_as_balance::(), 1 + per_block_gt_locked.starting_block()); -// let per_block_eq_locked = VestingInfo::new(256u32, 256u32, 10u32); -// assert_eq!( -// per_block_gt_locked.ending_block_as_balance::(), -// per_block_eq_locked.ending_block_as_balance::() -// ); - -// // Correctly calcs end if `locked % per_block != 0`. (We need a block to unlock the remainder). -// let imperfect_per_block = VestingInfo::new(256u32, 250u32, 10u32); -// assert_eq!(imperfect_per_block.ending_block_as_balance::(), imperfect_per_block.starting_block() + 2u32,); -// assert_eq!(imperfect_per_block.locked_at::(imperfect_per_block.ending_block_as_balance::()), 0); -// } - -// #[test] -// fn per_block_works() { -// let per_block_0 = VestingInfo::new(256u32, 0u32, 10u32); -// assert_eq!(per_block_0.per_block(), 1u32); -// assert_eq!(per_block_0.raw_per_block(), 0u32); - -// let per_block_1 = VestingInfo::new(256u32, 1u32, 10u32); -// assert_eq!(per_block_1.per_block(), 1u32); -// assert_eq!(per_block_1.raw_per_block(), 1u32); -// } - -// // When an accounts free balance + schedule.locked is less than ED, the vested transfer will fail. -// #[test] -// fn vested_transfer_less_than_existential_deposit_fails() { -// ExtBuilder::default().existential_deposit(4 * ED).build().execute_with(|| { -// // MinVestedTransfer is less the ED. -// assert!(::Currency::minimum_balance() > ::MinVestedTransfer::get()); - -// let sched = VestingInfo::new(::MinVestedTransfer::get() as u64, 1u64, 10u64); -// // The new account balance with the schedule's locked amount would be less than ED. -// assert!(Balances::free_balance(&99) + sched.locked() < ::Currency::minimum_balance()); - -// // vested_transfer fails. -// assert_noop!(Vesting::vested_transfer(Some(3).into(), 99, sched), TokenError::BelowMinimum,); -// // force_vested_transfer fails. -// assert_noop!(Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 99, sched), TokenError::BelowMinimum,); -// }); -// } +#[test] +fn non_vested_cannot_vest_other() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + assert!(!>::contains_key(4)); + assert_noop!(Vesting::vest_other(Some(3).into(), 4, LockType::Participation(0)), Error::::NotVesting); + }); +} + +#[test] +fn extra_balance_should_transfer() { + ExtBuilder::default().existential_deposit(10).build().execute_with(|| { + // Account 1 and 2 cannot send more than their free balance + assert_noop!(Balances::transfer_allow_death(Some(2).into(), 3, 100 - 10), TokenError::FundsUnavailable); + assert_noop!(Balances::transfer_allow_death(Some(1).into(), 3, 155 - 10), TokenError::FundsUnavailable); + // Account 3 sends 100 units to account 1 and 2 + assert_ok!(Balances::transfer_allow_death(Some(3).into(), 1, 100)); + assert_ok!(Balances::transfer_allow_death(Some(3).into(), 2, 100)); + + let user1_free_balance = Balances::free_balance(&1); + assert_eq!(user1_free_balance, 150); // Account 1 has 100 more free balance than normal + + let user2_free_balance = Balances::free_balance(&2); + assert_eq!(user2_free_balance, 110); // Account 2 has 100 more free balance than normal + + // Account 1 has only 5 units vested at block 1 (plus 150 unvested) + assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(45)); + assert_ok!(Vesting::vest(Some(1).into(), LockType::Participation(0))); + let user1_free_balance2 = Balances::free_balance(&1); + assert_eq!(user1_free_balance2, 155); // Account 1 has 100 more free balance than normal + assert_ok!(Balances::transfer_allow_death(Some(1).into(), 3, 155 - 10)); // Account 1 can send extra units gained + + // Account 2 has no units vested at block 1, but gained 100 + assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(200)); + assert_ok!(Vesting::vest(Some(2).into(), LockType::Participation(0))); + assert_ok!(Balances::transfer_allow_death(Some(2).into(), 3, 100 - 10)); // Account 2 can send extra + // units gained + }); +} + +#[test] +fn liquid_funds_should_transfer_with_delayed_vesting() { + ExtBuilder::default().existential_deposit(256).build().execute_with(|| { + let user12_free_balance = Balances::free_balance(&12); + + assert_eq!(user12_free_balance, 1280); // Account 12 has free balance + // Account 12 has liquid funds + assert_eq!(Vesting::vesting_balance(&12, LockType::Participation(0)), Some(256 * 5)); + + // Account 12 has delayed vesting + let user12_vesting_schedule = VestingInfo::new( + 256 * 5, + 64, // Vesting over 20 blocks + 10, + ); + assert_eq!(Vesting::vesting(&12).unwrap(), vec![user12_vesting_schedule]); + + // Account 12 can still send liquid funds + assert_ok!(Balances::transfer_allow_death(Some(12).into(), 3, 256 * 5 - 256)); + }); +} + +#[test] +fn vested_transfer_works() { + ExtBuilder::default().existential_deposit(256).build().execute_with(|| { + let user3_free_balance = Balances::free_balance(&3); + let user4_free_balance = Balances::free_balance(&4); + assert_eq!(user3_free_balance, 256 * 30); + assert_eq!(user4_free_balance, 256 * 40); + // Account 4 should not have any vesting yet. + assert_eq!(Vesting::vesting(&4), None); + // Make the schedule for the new transfer. + let new_vesting_schedule = VestingInfo::new( + 256 * 5, + 64, // Vesting over 20 blocks + 10, + ); + assert_ok!(Vesting::vested_transfer(Some(3).into(), 4, new_vesting_schedule, LockType::Participation(0))); + // Now account 4 should have vesting. + assert_eq!(Vesting::vesting(&4).unwrap(), vec![new_vesting_schedule]); + // Ensure the transfer happened correctly. + let user3_free_balance_updated = Balances::free_balance(&3); + assert_eq!(user3_free_balance_updated, 256 * 25); + let user4_free_balance_updated = Balances::free_balance(&4); + assert_eq!(user4_free_balance_updated, 256 * 40); + // Account 4 has 5 * 256 locked. + assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(256 * 5)); + + System::set_block_number(20); + assert_eq!(System::block_number(), 20); + + // Account 4 has 5 * 64 units vested by block 20. + assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(10 * 64)); + + System::set_block_number(30); + assert_eq!(System::block_number(), 30); + + // Account 4 has fully vested, + assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(0)); + // and after unlocking its schedules are removed from storage. + vest_and_assert_no_vesting::(4); + }); +} + +#[test] +fn vested_transfer_correctly_fails() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + let user2_free_balance = Balances::free_balance(&2); + let user4_free_balance = Balances::free_balance(&4); + assert_eq!(user2_free_balance, ED * 1); + assert_eq!(user4_free_balance, ED * 40); + + // Account 2 should already have a vesting schedule. + let user2_vesting_schedule = VestingInfo::new( + ED * 20, + ED, // Vesting over 20 blocks + 10, + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![user2_vesting_schedule]); + + // Fails due to too low transfer amount. + let new_vesting_schedule_too_low = VestingInfo::new(::MinVestedTransfer::get() - 1, 64, 10); + assert_noop!( + Vesting::vested_transfer(Some(3).into(), 4, new_vesting_schedule_too_low, LockType::Participation(0)), + Error::::AmountLow, + ); + + // `per_block` is 0, which would result in a schedule with infinite duration. + let schedule_per_block_0 = VestingInfo::new(::MinVestedTransfer::get(), 0, 10); + assert_noop!( + Vesting::vested_transfer(Some(13).into(), 4, schedule_per_block_0, LockType::Participation(0)), + Error::::InvalidScheduleParams, + ); + + // `locked` is 0. + let schedule_locked_0 = VestingInfo::new(0, 1, 10); + assert_noop!( + Vesting::vested_transfer(Some(3).into(), 4, schedule_locked_0, LockType::Participation(0)), + Error::::AmountLow, + ); + + // Free balance has not changed. + assert_eq!(user2_free_balance, Balances::free_balance(&2)); + assert_eq!(user4_free_balance, Balances::free_balance(&4)); + // Account 4 has no schedules. + vest_and_assert_no_vesting::(4); + }); +} + +#[test] +fn vested_transfer_allows_max_schedules() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + let user_4_free_balance = Balances::free_balance(&4); + let max_schedules = ::MAX_VESTING_SCHEDULES; + let sched = VestingInfo::new( + ::MinVestedTransfer::get(), + 1, // Vest over 2 * 256 blocks. + 10, + ); + + // Add max amount schedules to user 4. + for _ in 0..max_schedules { + assert_ok!(Vesting::vested_transfer(Some(13).into(), 4, sched, LockType::Participation(0))); + } + + // The schedules count towards vesting balance + let transferred_amount = ::MinVestedTransfer::get() * max_schedules as u64; + assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(transferred_amount)); + // BUT NOT the free balance. + assert_eq!(Balances::free_balance(&4), user_4_free_balance); + + // Cannot insert a 4th vesting schedule when `MaxVestingSchedules` === 3, + assert_noop!( + Vesting::vested_transfer(Some(3).into(), 4, sched, LockType::Participation(0)), + Error::::AtMaxVestingSchedules, + ); + // so the free balance does not change. + assert_eq!(Balances::free_balance(&4), user_4_free_balance); + + // Account 4 has fully vested when all the schedules end, + System::set_block_number(::MinVestedTransfer::get() + sched.starting_block()); + assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(0)); + // and after unlocking its schedules are removed from storage. + vest_and_assert_no_vesting::(4); + }); +} + +#[test] +fn force_vested_transfer_works() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + let user3_free_balance = Balances::free_balance(&3); + let user4_free_balance = Balances::free_balance(&4); + assert_eq!(user3_free_balance, ED * 30); + assert_eq!(user4_free_balance, ED * 40); + // Account 4 should not have any vesting yet. + assert_eq!(Vesting::vesting(&4), None); + // Make the schedule for the new transfer. + let new_vesting_schedule = VestingInfo::new( + ED * 5, + 64, // Vesting over 20 blocks + 10, + ); + + assert_noop!( + Vesting::force_vested_transfer(Some(4).into(), 3, 4, new_vesting_schedule, LockType::Participation(0)), + BadOrigin + ); + assert_ok!(Vesting::force_vested_transfer( + RawOrigin::Root.into(), + 3, + 4, + new_vesting_schedule, + LockType::Participation(0) + )); + // Now account 4 should have vesting. + assert_eq!(Vesting::vesting(&4).unwrap()[0], new_vesting_schedule); + assert_eq!(Vesting::vesting(&4).unwrap().len(), 1); + // Ensure the transfer happened correctly. + let user3_free_balance_updated = Balances::free_balance(&3); + assert_eq!(user3_free_balance_updated, ED * 25); + let user4_free_balance_updated = Balances::free_balance(&4); + assert_eq!(user4_free_balance_updated, ED * 40); + // Account 4 has 5 * ED locked. + assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(ED * 5)); + + System::set_block_number(20); + assert_eq!(System::block_number(), 20); + + // Account 4 has 5 * 64 units vested by block 20. + assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(10 * 64)); + + System::set_block_number(30); + assert_eq!(System::block_number(), 30); + + // Account 4 has fully vested, + assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(0)); + // and after unlocking its schedules are removed from storage. + vest_and_assert_no_vesting::(4); + }); +} + +#[test] +fn force_vested_transfer_correctly_fails() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + let user2_free_balance = Balances::free_balance(&2); + let user4_free_balance = Balances::free_balance(&4); + assert_eq!(user2_free_balance, ED * 1); + assert_eq!(user4_free_balance, ED * 40); + // Account 2 should already have a vesting schedule. + let user2_vesting_schedule = VestingInfo::new( + ED * 20, + ED, // Vesting over 20 blocks + 10, + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![user2_vesting_schedule]); + + // Too low transfer amount. + let new_vesting_schedule_too_low = VestingInfo::new(::MinVestedTransfer::get() - 1, 64, 10); + assert_noop!( + Vesting::force_vested_transfer( + RawOrigin::Root.into(), + 3, + 4, + new_vesting_schedule_too_low, + LockType::Participation(0) + ), + Error::::AmountLow, + ); + + // `per_block` is 0. + let schedule_per_block_0 = VestingInfo::new(::MinVestedTransfer::get(), 0, 10); + assert_noop!( + Vesting::force_vested_transfer( + RawOrigin::Root.into(), + 13, + 4, + schedule_per_block_0, + LockType::Participation(0) + ), + Error::::InvalidScheduleParams, + ); + + // `locked` is 0. + let schedule_locked_0 = VestingInfo::new(0, 1, 10); + assert_noop!( + Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, schedule_locked_0, LockType::Participation(0)), + Error::::AmountLow, + ); + + // Verify no currency transfer happened. + assert_eq!(user2_free_balance, Balances::free_balance(&2)); + assert_eq!(user4_free_balance, Balances::free_balance(&4)); + // Account 4 has no schedules. + vest_and_assert_no_vesting::(4); + }); +} + +#[test] +fn force_vested_transfer_allows_max_schedules() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + let user_4_free_balance = Balances::free_balance(&4); + let max_schedules = ::MAX_VESTING_SCHEDULES; + let sched = VestingInfo::new( + ::MinVestedTransfer::get(), + 1, // Vest over 2 * 256 blocks. + 10, + ); + + // Add max amount schedules to user 4. + for _ in 0..max_schedules { + assert_ok!(Vesting::force_vested_transfer( + RawOrigin::Root.into(), + 13, + 4, + sched, + LockType::Participation(0) + )); + } + + // The schedules count towards vesting balance. + let transferred_amount = ::MinVestedTransfer::get() * max_schedules as u64; + assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(transferred_amount)); + // but NOT free balance. + assert_eq!(Balances::free_balance(&4), user_4_free_balance); + + // Cannot insert a 4th vesting schedule when `MaxVestingSchedules` === 3 + assert_noop!( + Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 4, sched, LockType::Participation(0)), + Error::::AtMaxVestingSchedules, + ); + // so the free balance does not change. + assert_eq!(Balances::free_balance(&4), user_4_free_balance); + + // Account 4 has fully vested when all the schedules end, + System::set_block_number(::MinVestedTransfer::get() + 10); + assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(0)); + // and after unlocking its schedules are removed from storage. + vest_and_assert_no_vesting::(4); + }); +} + +#[test] +fn merge_schedules_that_have_not_started() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + // Account 2 should already have a vesting schedule. + let sched0 = VestingInfo::new( + ED * 20, + ED, // Vest over 20 blocks. + 10, + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + assert_eq!(Balances::balance(&2), ED); + + // Add a schedule that is identical to the one that already exists. + assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched0, LockType::Participation(0))); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched0]); + assert_eq!(Balances::balance(&2), ED); + assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1, LockType::Participation(0))); + + // Since we merged identical schedules, the new schedule finishes at the same + // time as the original, just with double the amount. + let sched1 = VestingInfo::new( + sched0.locked() * 2, + sched0.per_block() * 2, + 10, // Starts at the block the schedules are merged/ + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched1]); + + assert_eq!(Balances::balance(&2), ED); + }); +} + +#[test] +fn merge_ongoing_schedules() { + // Merging two schedules that have started will vest both before merging. + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + // Account 2 should already have a vesting schedule. + let sched0 = VestingInfo::new( + ED * 20, + ED, // Vest over 20 blocks. + 10, + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + + let sched1 = VestingInfo::new( + ED * 10, + ED, // Vest over 10 blocks. + sched0.starting_block() + 5, // Start at block 15. + ); + assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1, LockType::Participation(0))); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); + + // Got to half way through the second schedule where both schedules are actively vesting. + let cur_block = 20; + System::set_block_number(cur_block); + + // Account 2 has no usable balances prior to the merge because they have not unlocked + // with `vest` yet. + assert_eq!(Balances::balance(&2), ED); + + assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1, LockType::Participation(0))); + + // Merging schedules un-vests all pre-existing schedules prior to merging, which is + // reflected in account 2's updated usable balance. + let sched0_vested_now = sched0.per_block() * (cur_block - sched0.starting_block()); + let sched1_vested_now = sched1.per_block() * (cur_block - sched1.starting_block()); + assert_eq!(Balances::balance(&2), ED + sched0_vested_now + sched1_vested_now); + + // The locked amount is the sum of what both schedules have locked at the current block. + let sched2_locked = + sched1.locked_at::(cur_block).saturating_add(sched0.locked_at::(cur_block)); + // End block of the new schedule is the greater of either merged schedule. + let sched2_end = sched1.ending_block_as_balance::().max(sched0.ending_block_as_balance::()); + let sched2_duration = sched2_end - cur_block; + // Based off the new schedules total locked and its duration, we can calculate the + // amount to unlock per block. + let sched2_per_block = sched2_locked / sched2_duration; + + let sched2 = VestingInfo::new(sched2_locked, sched2_per_block, cur_block); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2]); + + // And just to double check, we assert the new merged schedule we be cleaned up as expected. + System::set_block_number(30); + vest_and_assert_no_vesting::(2); + }); +} + +#[test] +fn merging_shifts_other_schedules_index() { + // Schedules being merged are filtered out, schedules to the right of any merged + // schedule shift left and the merged schedule is always last. + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + let sched0 = VestingInfo::new( + ED * 10, + ED, // Vesting over 10 blocks. + 10, + ); + let sched1 = VestingInfo::new( + ED * 11, + ED, // Vesting over 11 blocks. + 11, + ); + let sched2 = VestingInfo::new( + ED * 12, + ED, // Vesting over 12 blocks. + 12, + ); + + // Account 3 starts out with no schedules, + assert_eq!(Vesting::vesting(&3), None); + // and some free balance. + let free_balance = Balances::balance(&3); + + let cur_block = 1; + assert_eq!(System::block_number(), cur_block); + + // Transfer the above 3 schedules to account 3. + assert_ok!(Vesting::vested_transfer(Some(4).into(), 3, sched0, LockType::Participation(0))); + assert_ok!(Vesting::vested_transfer(Some(4).into(), 3, sched1, LockType::Participation(0))); + assert_ok!(Vesting::vested_transfer(Some(4).into(), 3, sched2, LockType::Participation(0))); + + // With no schedules vested or merged they are in the order they are created + assert_eq!(Vesting::vesting(&3).unwrap(), vec![sched0, sched1, sched2]); + // and the free balance has not changed. + assert_eq!(free_balance, Balances::balance(&3)); + + assert_ok!(Vesting::merge_schedules(Some(3).into(), 0, 2, LockType::Participation(0))); + + // Create the merged schedule of sched0 & sched2. + // The merged schedule will have the max possible starting block, + let sched3_start = sched1.starting_block().max(sched2.starting_block()); + // `locked` equal to the sum of the two schedules locked through the current block, + let sched3_locked = sched2.locked_at::(cur_block) + sched0.locked_at::(cur_block); + // and will end at the max possible block. + let sched3_end = sched2.ending_block_as_balance::().max(sched0.ending_block_as_balance::()); + let sched3_duration = sched3_end - sched3_start; + let sched3_per_block = sched3_locked / sched3_duration; + let sched3 = VestingInfo::new(sched3_locked, sched3_per_block, sched3_start); + + // The not touched schedule moves left and the new merged schedule is appended. + assert_eq!(Vesting::vesting(&3).unwrap(), vec![sched1, sched3]); + // The usable balance hasn't changed since none of the schedules have started. + assert_eq!(Balances::balance(&3), free_balance); + }); +} + +#[test] +fn merge_ongoing_and_yet_to_be_started_schedules() { + // Merge an ongoing schedule that has had `vest` called and a schedule that has not already + // started. + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + // Account 2 should already have a vesting schedule. + let sched0 = VestingInfo::new( + ED * 20, + ED, // Vesting over 20 blocks + 10, + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + + // Fast forward to half way through the life of sched1. + let mut cur_block = (sched0.starting_block() + sched0.ending_block_as_balance::()) / 2; + assert_eq!(cur_block, 20); + System::set_block_number(cur_block); + + // Prior to vesting there is ED usable balance. + let mut balance = ED; + assert_eq!(Balances::balance(&2), balance); + // Vest the current schedules (which is just sched0 now). + Vesting::vest(Some(2).into(), LockType::Participation(0)).unwrap(); + + // After vesting the usable balance increases by the unlocked amount. + let sched0_vested_now = sched0.locked() - sched0.locked_at::(cur_block); + balance += sched0_vested_now; + assert_eq!(Balances::balance(&2), balance); + + // Go forward a block. + cur_block += 1; + System::set_block_number(cur_block); + + // And add a schedule that starts after this block, but before sched0 finishes. + let sched1 = VestingInfo::new( + ED * 10, + 1, // Vesting over 256 * 10 (2560) blocks + cur_block + 1, + ); + assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1, LockType::Participation(0))); + + // Merge the schedules before sched1 starts. + assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1, LockType::Participation(0))); + // After merging, the usable balance only changes by the amount sched0 vested since we + // last called `vest` (which is just 1 block). The usable balance is not affected by + // sched1 because it has not started yet. + balance += sched0.per_block(); + assert_eq!(Balances::balance(&2), balance); + + // The resulting schedule will have the later starting block of the two, + let sched2_start = sched1.starting_block(); + // `locked` equal to the sum of the two schedules locked through the current block, + let sched2_locked = sched0.locked_at::(cur_block) + sched1.locked_at::(cur_block); + // and will end at the max possible block. + let sched2_end = sched0.ending_block_as_balance::().max(sched1.ending_block_as_balance::()); + let sched2_duration = sched2_end - sched2_start; + let sched2_per_block = sched2_locked / sched2_duration; + + let sched2 = VestingInfo::new(sched2_locked, sched2_per_block, sched2_start); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2]); + }); +} + +#[test] +fn merge_finished_and_ongoing_schedules() { + // If a schedule finishes by the current block we treat the ongoing schedule, + // without any alterations, as the merged one. + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + // Account 2 should already have a vesting schedule. + let sched0 = VestingInfo::new( + ED * 20, + ED, // Vesting over 20 blocks. + 10, + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + + let sched1 = VestingInfo::new( + ED * 40, + ED, // Vesting over 40 blocks. + 10, + ); + assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1, LockType::Participation(0))); + + // Transfer a 3rd schedule, so we can demonstrate how schedule indices change. + // (We are not merging this schedule.) + let sched2 = VestingInfo::new( + ED * 30, + ED, // Vesting over 30 blocks. + 10, + ); + assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched2, LockType::Participation(0))); + + // The schedules are in expected order prior to merging. + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); + + // Fast forward to sched0's end block. + let cur_block = sched0.ending_block_as_balance::(); + System::set_block_number(cur_block); + assert_eq!(System::block_number(), 30); + + // Prior to `merge_schedules` and with no vest/vest_other called the user has no usable + // balance. + assert_eq!(Balances::balance(&2), ED); + assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1, LockType::Participation(0))); + + // sched2 is now the first, since sched0 & sched1 get filtered out while "merging". + // sched1 gets treated like the new merged schedule by getting pushed onto back + // of the vesting schedules vec. Note: sched0 finished at the current block. + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2, sched1]); + + // sched0 has finished, so its funds are fully unlocked. + let sched0_unlocked_now = sched0.locked(); + // The remaining schedules are ongoing, so their funds are partially unlocked. + let sched1_unlocked_now = sched1.locked() - sched1.locked_at::(cur_block); + let sched2_unlocked_now = sched2.locked() - sched2.locked_at::(cur_block); + + // Since merging also vests all the schedules, the users usable balance after merging + // includes all pre-existing schedules unlocked through the current block, including + // schedules not merged. + assert_eq!(Balances::balance(&2), ED + sched0_unlocked_now + sched1_unlocked_now + sched2_unlocked_now); + }); +} + +#[test] +fn merge_finishing_schedules_does_not_create_a_new_one() { + // If both schedules finish by the current block we don't create new one + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + // Account 2 should already have a vesting schedule. + let sched0 = VestingInfo::new( + ED * 20, + ED, // 20 block duration. + 10, + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + + // Create sched1 and transfer it to account 2. + let sched1 = VestingInfo::new( + ED * 30, + ED, // 30 block duration. + 10, + ); + assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched1, LockType::Participation(0))); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); + + let all_scheds_end = + sched0.ending_block_as_balance::().max(sched1.ending_block_as_balance::()); + + assert_eq!(all_scheds_end, 40); + System::set_block_number(all_scheds_end); + + // Prior to merge_schedules and with no vest/vest_other called the user has no usable + // balance. + assert_eq!(Balances::balance(&2), ED); + + // Merge schedule 0 and 1. + assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1, LockType::Participation(0))); + // The user no longer has any more vesting schedules because they both ended at the + // block they where merged, + assert!(!>::contains_key(&2)); + // and their usable balance has increased by the total amount locked in the merged + // schedules. + assert_eq!(Balances::balance(&2), ED + sched0.locked() + sched1.locked()); + }); +} + +#[test] +fn merge_finished_and_yet_to_be_started_schedules() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + // Account 2 should already have a vesting schedule from the Genesis. + let sched0 = VestingInfo::new( + ED * 20, + ED, // 20 block duration. + 10, // Ends at block 30 + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + + let sched1 = VestingInfo::new( + ED * 30, + ED * 2, // 30 block duration. + 35, + ); + assert_ok!(Vesting::vested_transfer(Some(13).into(), 2, sched1, LockType::Participation(0))); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); + + let sched2 = VestingInfo::new( + ED * 40, + ED, // 40 block duration. + 30, + ); + // Add a 3rd schedule to demonstrate how sched1 shifts. + assert_ok!(Vesting::vested_transfer(Some(13).into(), 2, sched2, LockType::Participation(0))); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); + + assert_eq!( + Vesting::vesting_balance(&2, LockType::Participation(0)).unwrap(), + Balances::balance_on_hold(&LockType::Participation(0), &2) + ); + assert_eq!( + Vesting::vesting_balance(&2, LockType::Participation(0)), + Some(sched0.locked() + sched1.locked() + sched2.locked()) + ); + + System::set_block_number(30); + + // At block 30, sched0 has finished unlocking while sched1 and sched2 are still fully + // locked, + assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(sched1.locked() + sched2.locked())); + // but since we have not vested usable balance is still 0. + assert_eq!(Balances::balance(&2), ED); + + // Merge schedule 0 and 1. + assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1, LockType::Participation(0))); + + // sched0 is removed since it finished, and sched1 is removed and then pushed on the back + // because it is treated as the merged schedule + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2, sched1]); + + // The usable balance is updated because merging fully unlocked sched0. + assert_eq!(Balances::balance(&2), ED + sched0.locked()); + }); +} + +#[test] +fn merge_schedules_throws_proper_errors() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + // Account 2 should already have a vesting schedule. + let sched0 = VestingInfo::new( + ED * 20, + ED, // 20 block duration. + 10, + ); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + + // Account 2 only has 1 vesting schedule. + assert_noop!( + Vesting::merge_schedules(Some(2).into(), 0, 1, LockType::Participation(0)), + Error::::ScheduleIndexOutOfBounds + ); + + // Account 4 has 0 vesting schedules. + assert_eq!(Vesting::vesting(&4), None); + assert_noop!( + Vesting::merge_schedules(Some(4).into(), 0, 1, LockType::Participation(0)), + Error::::NotVesting + ); + + // There are enough schedules to merge but an index is non-existent. + assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched0, LockType::Participation(0))); + assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched0]); + assert_noop!( + Vesting::merge_schedules(Some(2).into(), 0, 2, LockType::Participation(0)), + Error::::ScheduleIndexOutOfBounds + ); + + // It is a storage noop with no errors if the indexes are the same. + assert_storage_noop!(Vesting::merge_schedules(Some(2).into(), 0, 0, LockType::Participation(0)).unwrap()); + }); +} + +#[test] +fn merge_vesting_handles_per_block_0() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + let sched0 = VestingInfo::new( + ED, 0, // Vesting over 256 blocks. + 1, + ); + assert_eq!(sched0.ending_block_as_balance::(), 257); + let sched1 = VestingInfo::new( + ED * 2, + 0, // Vesting over 512 blocks. + 10, + ); + assert_eq!(sched1.ending_block_as_balance::(), 512u64 + 10); + + let merged = VestingInfo::new(764, 1, 10); + assert_eq!(Vesting::merge_vesting_info(5, sched0, sched1), Some(merged)); + }); +} + +#[test] +fn vesting_info_validate_works() { + let min_transfer = ::MinVestedTransfer::get(); + // Does not check for min transfer. + assert_eq!(VestingInfo::new(min_transfer - 1, 1u64, 10u64).is_valid(), true); + + // `locked` cannot be 0. + assert_eq!(VestingInfo::new(0, 1u64, 10u64).is_valid(), false); + + // `per_block` cannot be 0. + assert_eq!(VestingInfo::new(min_transfer + 1, 0u64, 10u64).is_valid(), false); + + // With valid inputs it does not error. + assert_eq!(VestingInfo::new(min_transfer, 1u64, 10u64).is_valid(), true); +} + +#[test] +fn vesting_info_ending_block_as_balance_works() { + // Treats `per_block` 0 as 1. + let per_block_0 = VestingInfo::new(256u32, 0u32, 10u32); + assert_eq!(per_block_0.ending_block_as_balance::(), 256 + 10); + + // `per_block >= locked` always results in a schedule ending the block after it starts + let per_block_gt_locked = VestingInfo::new(256u32, 256 * 2u32, 10u32); + assert_eq!(per_block_gt_locked.ending_block_as_balance::(), 1 + per_block_gt_locked.starting_block()); + let per_block_eq_locked = VestingInfo::new(256u32, 256u32, 10u32); + assert_eq!( + per_block_gt_locked.ending_block_as_balance::(), + per_block_eq_locked.ending_block_as_balance::() + ); + + // Correctly calcs end if `locked % per_block != 0`. (We need a block to unlock the remainder). + let imperfect_per_block = VestingInfo::new(256u32, 250u32, 10u32); + assert_eq!(imperfect_per_block.ending_block_as_balance::(), imperfect_per_block.starting_block() + 2u32,); + assert_eq!(imperfect_per_block.locked_at::(imperfect_per_block.ending_block_as_balance::()), 0); +} + +#[test] +fn per_block_works() { + let per_block_0 = VestingInfo::new(256u32, 0u32, 10u32); + assert_eq!(per_block_0.per_block(), 1u32); + assert_eq!(per_block_0.raw_per_block(), 0u32); + + let per_block_1 = VestingInfo::new(256u32, 1u32, 10u32); + assert_eq!(per_block_1.per_block(), 1u32); + assert_eq!(per_block_1.raw_per_block(), 1u32); +} + +// When an accounts free balance + schedule.locked is less than ED, the vested transfer will fail. +#[test] +fn vested_transfer_less_than_existential_deposit_fails() { + ExtBuilder::default().existential_deposit(4 * ED).build().execute_with(|| { + // MinVestedTransfer is less the ED. + assert!(::Currency::minimum_balance() > ::MinVestedTransfer::get()); + + let sched = VestingInfo::new(::MinVestedTransfer::get() as u64, 1u64, 10u64); + // The new account balance with the schedule's locked amount would be less than ED. + assert!(Balances::free_balance(&99) + sched.locked() < ::Currency::minimum_balance()); + + // vested_transfer fails. + assert_noop!( + Vesting::vested_transfer(Some(3).into(), 99, sched, LockType::Participation(0)), + TokenError::CannotCreateHold, + ); + // force_vested_transfer fails. + assert_noop!( + Vesting::force_vested_transfer(RawOrigin::Root.into(), 3, 99, sched, LockType::Participation(0)), + TokenError::CannotCreateHold, + ); + }); +} // TODO #[test] @@ -1046,7 +1108,7 @@ fn set_release_schedule() { assert_eq!(user_3_reserved_balance, 0); let user_3_on_hold_balance = Balances::balance_on_hold(&LockType::Participation(0), &3); assert_eq!(user_3_on_hold_balance, 0); - assert_eq!(Vesting::vesting_balance(&3), None); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), None); // Hold 15 ED assert_ok!(Balances::hold(&LockType::Participation(0), &3, 15 * ED)); @@ -1056,23 +1118,23 @@ fn set_release_schedule() { assert_eq!(user_3_on_hold_balance, 15 * ED); let user_3_reserved_balance = Balances::reserved_balance(&3); assert_eq!(user_3_reserved_balance, 15 * ED); - assert_eq!(Vesting::vesting_balance(&3), None); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), None); // Set release schedule to release the locked amount, starting from now, one ED per block. let user3_vesting_schedule = VestingInfo::new(user_3_on_hold_balance, ED, System::block_number()); assert_ok!(Vesting::release_schedule(Some(3).into(), user3_vesting_schedule)); - assert_eq!(Vesting::vesting_balance(&3), Some(15 * ED)); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(15 * ED)); // 1 ED can be "released", we need to call vest to release it. System::set_block_number(2); - assert_eq!(Vesting::vesting_balance(&3), Some(14 * ED)); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(14 * ED)); assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(0))); let user_3_free_balance = Balances::free_balance(&3); assert_eq!(user_3_free_balance, 16 * ED); // 2 ED can be "released" System::set_block_number(3); - assert_eq!(Vesting::vesting_balance(&3), Some(13 * ED)); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(13 * ED)); assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(0))); let user_3_free_balance = Balances::free_balance(&3); assert_eq!(user_3_free_balance, 17 * ED); @@ -1080,7 +1142,7 @@ fn set_release_schedule() { // Go to the end of the schedule System::set_block_number(16); assert_eq!(System::block_number(), 16); - assert_eq!(Vesting::vesting_balance(&3), Some(0)); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(0)); vest_and_assert_no_vesting::(3); let user_3_free_balance = Balances::free_balance(&3); assert_eq!(user_3_free_balance, 30 * ED); @@ -1099,7 +1161,7 @@ fn cannot_release_different_reason() { assert_eq!(user_3_reserved_balance, 0); let user_3_on_hold_balance = Balances::balance_on_hold(&LockType::Participation(0), &3); assert_eq!(user_3_on_hold_balance, 0); - assert_eq!(Vesting::vesting_balance(&3), None); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), None); // Hold 15 ED assert_ok!(Balances::hold(&LockType::Participation(0), &3, 15 * ED)); @@ -1109,16 +1171,16 @@ fn cannot_release_different_reason() { assert_eq!(user_3_on_hold_balance, 15 * ED); let user_3_reserved_balance = Balances::reserved_balance(&3); assert_eq!(user_3_reserved_balance, 15 * ED); - assert_eq!(Vesting::vesting_balance(&3), None); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), None); // Set release schedule to release the locked amount, starting from now, one ED per block. let user3_vesting_schedule = VestingInfo::new(user_3_on_hold_balance, ED, System::block_number()); assert_ok!(Vesting::release_schedule(Some(3).into(), user3_vesting_schedule)); - assert_eq!(Vesting::vesting_balance(&3), Some(15 * ED)); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(15 * ED)); // 1 ED can be "released", we need to call vest to release it. System::set_block_number(2); - assert_eq!(Vesting::vesting_balance(&3), Some(14 * ED)); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(14 * ED)); assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(1))); let user_3_free_balance = Balances::free_balance(&3); assert_eq!(user_3_free_balance, 15 * ED); From 38857e650735b9ea4a48d5e68296ed47bdcfaa15 Mon Sep 17 00:00:00 2001 From: Juan Ignacio RIos Date: Fri, 14 Jul 2023 18:08:13 +0200 Subject: [PATCH 16/80] wip: save --- polimec-skeleton/pallets/funding/src/functions.rs | 14 +++++--------- polimec-skeleton/pallets/funding/src/lib.rs | 1 - 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/polimec-skeleton/pallets/funding/src/functions.rs b/polimec-skeleton/pallets/funding/src/functions.rs index 91cc07a1a..e764fd3fe 100644 --- a/polimec-skeleton/pallets/funding/src/functions.rs +++ b/polimec-skeleton/pallets/funding/src/functions.rs @@ -241,9 +241,7 @@ impl Pallet { .fold(total, |acc, bond| acc.saturating_add(bond.original_plmc_bond)); total.saturating_add(user_total_plmc_bond) }); - // TODO: PLMC-142. 10% is hardcoded, check if we want to configure it a runtime as explained here: - // https://substrate.stackexchange.com/questions/2784/how-to-get-a-percent-portion-of-a-balance: - // TODO: PLMC-143. Check if it's safe to use * here + let evaluation_target_usd = Perbill::from_percent(10) * fundraising_target_usd; let evaluation_target_plmc = current_plmc_price .reciprocal() @@ -288,7 +286,7 @@ impl Pallet { } else { // * Update storage * project_details.status = ProjectStatus::EvaluationFailed; - project_details.cleanup = ProjectCleanup::Ready(ProjectFinalizer::Failure(Default::default())); + project_details.cleanup = ProjectCleanup::Ready(ProjectFinalizer::Failure(FailureFinalizer::Initialized)); ProjectsDetails::::insert(project_id, project_details); // * Emit events * @@ -654,7 +652,7 @@ impl Pallet { let evaluation_reward_or_slash_info = Self::generate_evaluation_reward_or_slash_info(project_id)?; if funding_is_successful { project_details.status = ProjectStatus::FundingSuccessful; - project_details.cleanup = ProjectCleanup::Ready(ProjectFinalizer::Success(Default::default())); + project_details.cleanup = ProjectCleanup::Ready(ProjectFinalizer::Success(SuccessFinalizer::Initialized)); project_details.evaluation_reward_or_slash_info = Some(evaluation_reward_or_slash_info); // * Update Storage * @@ -819,8 +817,7 @@ impl Pallet { .fold(BalanceOf::::zero(), |acc, evaluation| acc.saturating_add(evaluation)); let remaining_bond_to_reach_threshold = early_evaluation_reward_threshold_usd - .checked_sub(&previous_total_evaluation_bonded_usd) - .unwrap_or(BalanceOf::::zero()); + .saturating_sub(&previous_total_evaluation_bonded_usd) let early_usd_amount = if usd_amount <= remaining_bond_to_reach_threshold { usd_amount @@ -1567,8 +1564,7 @@ impl Pallet { evaluation.late_usd_amount.saturating_add(evaluation.early_usd_amount), reward_info.normal_evaluator_total_bonded_usd, ); - let total_reward_amount_usd = early_reward_weight * reward_info.early_evaluator_reward_pot_usd - + normal_reward_weight * reward_info.normal_evaluator_reward_pot_usd; + let total_reward_amount_usd = (early_reward_weight * reward_info.early_evaluator_reward_pot_usd).saturating_add(normal_reward_weight * reward_info.normal_evaluator_reward_pot_usd); let reward_amount_ct: BalanceOf = ct_price .reciprocal() .ok_or(Error::::BadMath)? diff --git a/polimec-skeleton/pallets/funding/src/lib.rs b/polimec-skeleton/pallets/funding/src/lib.rs index b78b1cd22..442c6924d 100644 --- a/polimec-skeleton/pallets/funding/src/lib.rs +++ b/polimec-skeleton/pallets/funding/src/lib.rs @@ -968,7 +968,6 @@ pub mod pallet { } } - // TODO: PLMC-127. Set a proper weight max_weight.saturating_sub(remaining_weight) } } From 8d3f835953f4012fa68561cc1ffeb634124b173e Mon Sep 17 00:00:00 2001 From: Juan Ignacio RIos Date: Tue, 18 Jul 2023 16:18:11 +0200 Subject: [PATCH 17/80] feat(214): ProjectDetails changed. Evaluation total bond now stored in it. --- .../pallets/funding/src/functions.rs | 37 ++++++++++--------- polimec-skeleton/pallets/funding/src/impls.rs | 4 +- polimec-skeleton/pallets/funding/src/lib.rs | 5 ++- polimec-skeleton/pallets/funding/src/tests.rs | 6 ++- polimec-skeleton/pallets/funding/src/types.rs | 19 +++++++--- 5 files changed, 42 insertions(+), 29 deletions(-) diff --git a/polimec-skeleton/pallets/funding/src/functions.rs b/polimec-skeleton/pallets/funding/src/functions.rs index e764fd3fe..883e4dc35 100644 --- a/polimec-skeleton/pallets/funding/src/functions.rs +++ b/polimec-skeleton/pallets/funding/src/functions.rs @@ -102,7 +102,11 @@ impl Pallet { remaining_contribution_tokens: initial_metadata.total_allocation_size, funding_amount_reached: BalanceOf::::zero(), cleanup: ProjectCleanup::NotReady, - evaluation_reward_or_slash_info: None, + evaluation_round_info: EvaluationRoundInfoOf:: { + total_bonded_usd: Zero::zero(), + total_bonded_plmc: Zero::zero(), + evaluators_outcome: EvaluatorsOutcome::Unchanged, + }, }; let project_metadata = initial_metadata; @@ -649,11 +653,11 @@ impl Pallet { let funding_reached = project_details.funding_amount_reached; let funding_is_successful = !(project_details.status == ProjectStatus::FundingFailed || funding_reached < funding_target); - let evaluation_reward_or_slash_info = Self::generate_evaluation_reward_or_slash_info(project_id)?; + let evaluators_outcome = Self::generate_evaluators_outcome(project_id)?; + project_details.evaluation_round_info.evaluators_outcome = evaluators_outcome; if funding_is_successful { project_details.status = ProjectStatus::FundingSuccessful; project_details.cleanup = ProjectCleanup::Ready(ProjectFinalizer::Success(SuccessFinalizer::Initialized)); - project_details.evaluation_reward_or_slash_info = Some(evaluation_reward_or_slash_info); // * Update Storage * ProjectsDetails::::insert(project_id, project_details.clone()); @@ -781,14 +785,14 @@ impl Pallet { evaluator: AccountIdOf, project_id: T::ProjectIdentifier, usd_amount: BalanceOf, ) -> Result<(), DispatchError> { // * Get variables * - let project_details = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_details = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); let evaluation_id = Self::next_evaluation_id(); let mut caller_existing_evaluations = Evaluations::::get(project_id, evaluator.clone()); let plmc_usd_price = T::PriceProvider::get_price(PLMC_STATEMINT_ID).ok_or(Error::::PLMCPriceNotAvailable)?; let early_evaluation_reward_threshold_usd = T::EarlyEvaluationThreshold::get() * project_details.fundraising_target; - let all_existing_evaluations = Evaluations::::iter_prefix(project_id); + let evaluation_round_info = &mut project_details.evaluation_round_info; // * Validity Checks * ensure!( @@ -807,17 +811,10 @@ impl Pallet { .checked_mul_int(usd_amount) .ok_or(Error::::BadMath)?; - let previous_total_evaluation_bonded_usd = all_existing_evaluations - .map(|(_evaluator, evaluations)| { - evaluations.iter().fold(BalanceOf::::zero(), |acc, evaluation| { - acc.saturating_add(evaluation.early_usd_amount) - .saturating_add(evaluation.late_usd_amount) - }) - }) - .fold(BalanceOf::::zero(), |acc, evaluation| acc.saturating_add(evaluation)); + let previous_total_evaluation_bonded_usd = evaluation_round_info.total_bonded_usd; let remaining_bond_to_reach_threshold = early_evaluation_reward_threshold_usd - .saturating_sub(&previous_total_evaluation_bonded_usd) + .saturating_sub(previous_total_evaluation_bonded_usd); let early_usd_amount = if usd_amount <= remaining_bond_to_reach_threshold { usd_amount @@ -878,6 +875,10 @@ impl Pallet { Evaluations::::set(project_id, evaluator.clone(), caller_existing_evaluations); NextEvaluationId::::set(evaluation_id.saturating_add(One::one())); + evaluation_round_info.total_bonded_usd += usd_amount; + evaluation_round_info.total_bonded_plmc += plmc_bond; + ProjectsDetails::::insert(project_id, project_details); + // * Emit events * Self::deposit_event(Event::::FundsBonded { @@ -1537,7 +1538,7 @@ impl Pallet { .weighted_average_price .ok_or(Error::::ImpossibleState)?; let reward_info = - if let Some(EvaluationRewardOrSlashInfo::Rewards(info)) = project_details.evaluation_reward_or_slash_info { + if let EvaluatorsOutcome::Rewarded(info) = project_details.evaluation_round_info.evaluators_outcome { info } else { return Err(Error::::NotAllowed.into()); @@ -2179,9 +2180,9 @@ impl Pallet { )) } - pub fn generate_evaluation_reward_or_slash_info( + pub fn generate_evaluators_outcome( project_id: T::ProjectIdentifier, - ) -> Result, DispatchError> { + ) -> Result, DispatchError> { let project_details = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; let funding_target = project_details.fundraising_target; let funding_reached = project_details.funding_amount_reached; @@ -2204,7 +2205,7 @@ impl Pallet { early_evaluator_total_bonded_usd, normal_evaluator_total_bonded_usd, ) = Self::get_evaluator_rewards_info(project_id)?; - Ok(EvaluationRewardOrSlashInfo::Rewards(RewardInfo { + Ok(EvaluatorsOutcome::Rewarded(RewardInfo { early_evaluator_reward_pot_usd, normal_evaluator_reward_pot_usd, early_evaluator_total_bonded_usd, diff --git a/polimec-skeleton/pallets/funding/src/impls.rs b/polimec-skeleton/pallets/funding/src/impls.rs index 1426737ec..4c67c102a 100644 --- a/polimec-skeleton/pallets/funding/src/impls.rs +++ b/polimec-skeleton/pallets/funding/src/impls.rs @@ -316,8 +316,8 @@ fn reward_or_slash_one_evaluation(project_id: T::ProjectIdentifier) - .find(|evaluation| !evaluation.rewarded_or_slashed) .expect("user_evaluations can only exist if an item here is found; qed"); - match project_details.evaluation_reward_or_slash_info { - Some(EvaluationRewardOrSlashInfo::Rewards(_)) => { + match project_details.evaluation_round_info.evaluators_outcome { + EvaluatorsOutcome::Rewarded(_) => { match Pallet::::do_evaluation_reward( T::PalletId::get().into_account_truncating(), evaluation.project_id, diff --git a/polimec-skeleton/pallets/funding/src/lib.rs b/polimec-skeleton/pallets/funding/src/lib.rs index 442c6924d..8aa43afc4 100644 --- a/polimec-skeleton/pallets/funding/src/lib.rs +++ b/polimec-skeleton/pallets/funding/src/lib.rs @@ -228,11 +228,12 @@ pub type HashOf = ::Hash; pub type AssetIdOf = <::FundingCurrency as fungibles::Inspect<::AccountId>>::AssetId; +pub type EvaluatorsOutcomeOf = EvaluatorsOutcome, BalanceOf>; pub type ProjectMetadataOf = ProjectMetadata>, BalanceOf, PriceOf, AccountIdOf, HashOf>; pub type ProjectDetailsOf = - ProjectDetails, BlockNumberOf, PriceOf, BalanceOf, EvaluationRewardOrSlashInfoOf>; -pub type EvaluationRewardOrSlashInfoOf = EvaluationRewardOrSlashInfo, BalanceOf>; + ProjectDetails, BlockNumberOf, PriceOf, BalanceOf, EvaluationRoundInfoOf>; +pub type EvaluationRoundInfoOf = EvaluationRoundInfo, BalanceOf>; pub type VestingOf = Vesting, BalanceOf>; pub type EvaluationInfoOf = EvaluationInfo, ProjectIdOf, AccountIdOf, BalanceOf, BlockNumberOf>; diff --git a/polimec-skeleton/pallets/funding/src/tests.rs b/polimec-skeleton/pallets/funding/src/tests.rs index f7ed711f2..958106867 100644 --- a/polimec-skeleton/pallets/funding/src/tests.rs +++ b/polimec-skeleton/pallets/funding/src/tests.rs @@ -536,7 +536,11 @@ impl<'a> CreatedProject<'a> { remaining_contribution_tokens: expected_metadata.total_allocation_size, funding_amount_reached: BalanceOf::::zero(), cleanup: ProjectCleanup::NotReady, - evaluation_reward_or_slash_info: None, + evaluation_round_info: EvaluationRoundInfoOf:: { + total_bonded_usd: Zero::zero(), + total_bonded_plmc: Zero::zero(), + evaluators_outcome: EvaluatorsOutcome::Unchanged, + }, }; assert_eq!(metadata, expected_metadata); assert_eq!(details, expected_details); diff --git a/polimec-skeleton/pallets/funding/src/types.rs b/polimec-skeleton/pallets/funding/src/types.rs index a828ba790..655218865 100644 --- a/polimec-skeleton/pallets/funding/src/types.rs +++ b/polimec-skeleton/pallets/funding/src/types.rs @@ -118,7 +118,7 @@ pub mod storage_types { } #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)] - pub struct ProjectDetails { + pub struct ProjectDetails { pub issuer: AccountId, /// Whether the project is frozen, so no `metadata` changes are allowed. pub is_frozen: bool, @@ -136,8 +136,8 @@ pub mod storage_types { pub funding_amount_reached: Balance, /// Cleanup operations remaining pub cleanup: ProjectCleanup, - /// Evaluator rewards/penalties - pub evaluation_reward_or_slash_info: Option, + /// Information about the total amount bonded, and the outcome in regards to reward/slash/nothing + pub evaluation_round_info: EvaluationRoundInfo, } /// Tells on_initialize what to do with the project @@ -533,10 +533,17 @@ pub mod inner_types { } #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] - pub enum EvaluationRewardOrSlashInfo { - Rewards(RewardInfo), - Slashes(Vec<(AccountId, Balance)>), + pub struct EvaluationRoundInfo { + pub total_bonded_usd: Balance, + pub total_bonded_plmc: Balance, + pub evaluators_outcome: EvaluatorsOutcome + } + + #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] + pub enum EvaluatorsOutcome { Unchanged, + Rewarded(RewardInfo), + Slashed(Vec<(AccountId, Balance)>), } #[derive(Default, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] From 065dbe1efec11e1353269792f358f28db403eace Mon Sep 17 00:00:00 2001 From: Juan Ignacio RIos Date: Wed, 19 Jul 2023 11:46:47 +0200 Subject: [PATCH 18/80] feat(214): bid refunds on failure due to candle end and ct soldout implemented and tested --- .../pallets/funding/src/functions.rs | 101 ++++++++--- polimec-skeleton/pallets/funding/src/tests.rs | 171 +++++++++++++++++- polimec-skeleton/pallets/funding/src/types.rs | 13 +- 3 files changed, 252 insertions(+), 33 deletions(-) diff --git a/polimec-skeleton/pallets/funding/src/functions.rs b/polimec-skeleton/pallets/funding/src/functions.rs index 883e4dc35..94836b6fd 100644 --- a/polimec-skeleton/pallets/funding/src/functions.rs +++ b/polimec-skeleton/pallets/funding/src/functions.rs @@ -32,7 +32,8 @@ use frame_support::{ Get, }, }; -use sp_arithmetic::Perbill; +use itertools::Itertools; +use sp_arithmetic::Perquintill; use sp_arithmetic::traits::{CheckedSub, Zero}; use sp_std::prelude::*; @@ -246,7 +247,7 @@ impl Pallet { total.saturating_add(user_total_plmc_bond) }); - let evaluation_target_usd = Perbill::from_percent(10) * fundraising_target_usd; + let evaluation_target_usd = Perquintill::from_percent(10) * fundraising_target_usd; let evaluation_target_plmc = current_plmc_price .reciprocal() .ok_or(Error::::BadMath)? @@ -813,8 +814,8 @@ impl Pallet { let previous_total_evaluation_bonded_usd = evaluation_round_info.total_bonded_usd; - let remaining_bond_to_reach_threshold = early_evaluation_reward_threshold_usd - .saturating_sub(previous_total_evaluation_bonded_usd); + let remaining_bond_to_reach_threshold = + early_evaluation_reward_threshold_usd.saturating_sub(previous_total_evaluation_bonded_usd); let early_usd_amount = if usd_amount <= remaining_bond_to_reach_threshold { usd_amount @@ -879,7 +880,6 @@ impl Pallet { evaluation_round_info.total_bonded_plmc += plmc_bond; ProjectsDetails::::insert(project_id, project_details); - // * Emit events * Self::deposit_event(Event::::FundsBonded { project_id, @@ -1538,7 +1538,7 @@ impl Pallet { .weighted_average_price .ok_or(Error::::ImpossibleState)?; let reward_info = - if let EvaluatorsOutcome::Rewarded(info) = project_details.evaluation_round_info.evaluators_outcome { + if let EvaluatorsOutcome::Rewarded(info) = project_details.evaluation_round_info.evaluators_outcome { info } else { return Err(Error::::NotAllowed.into()); @@ -1557,15 +1557,16 @@ impl Pallet { ); // * Calculate variables * - let early_reward_weight = Perbill::from_rational( + let early_reward_weight = Perquintill::from_rational( evaluation.early_usd_amount, reward_info.early_evaluator_total_bonded_usd, ); - let normal_reward_weight = Perbill::from_rational( + let normal_reward_weight = Perquintill::from_rational( evaluation.late_usd_amount.saturating_add(evaluation.early_usd_amount), reward_info.normal_evaluator_total_bonded_usd, ); - let total_reward_amount_usd = (early_reward_weight * reward_info.early_evaluator_reward_pot_usd).saturating_add(normal_reward_weight * reward_info.normal_evaluator_reward_pot_usd); + let total_reward_amount_usd = (early_reward_weight * reward_info.early_evaluator_reward_pot_usd) + .saturating_add(normal_reward_weight * reward_info.normal_evaluator_reward_pot_usd); let reward_amount_ct: BalanceOf = ct_price .reciprocal() .ok_or(Error::::BadMath)? @@ -1726,8 +1727,9 @@ impl Pallet { let mut bid_usd_value_sum = BalanceOf::::zero(); let project_account = Self::fund_account_id(project_id); let plmc_price = T::PriceProvider::get_price(PLMC_STATEMINT_ID).ok_or(Error::::PLMCPriceNotAvailable)?; - // sort bids by price + // sort bids by price, and equal prices sorted by block number bids.sort(); + bids.reverse(); // accept only bids that were made before `end_block` i.e end of candle auction let bids: Result, DispatchError> = bids .into_iter() @@ -1735,11 +1737,49 @@ impl Pallet { if bid.when > end_block { bid.status = BidStatus::Rejected(RejectionReason::AfterCandleEnd); // TODO: PLMC-147. Unlock funds. We can do this inside the "on_idle" hook, and change the `status` of the `Bid` to "Unreserved" + bid.final_ct_amount = 0_u32.into(); + bid.final_ct_usd_price = PriceOf::::zero(); + + T::FundingCurrency::transfer( + bid.funding_asset.to_statemint_id(), + &project_account, + &bid.bidder, + bid.funding_asset_amount_locked, + Preservation::Preserve, + )?; + T::NativeCurrency::release( + &LockType::Participation(project_id), + &bid.bidder, + bid.plmc_bond, + Precision::Exact, + )?; + bid.funding_asset_amount_locked = BalanceOf::::zero(); + bid.plmc_bond = BalanceOf::::zero(); + return Ok(bid); } let buyable_amount = total_allocation_size.saturating_sub(bid_token_amount_sum); if buyable_amount == 0_u32.into() { bid.status = BidStatus::Rejected(RejectionReason::NoTokensLeft); + bid.final_ct_amount = 0_u32.into(); + bid.final_ct_usd_price = PriceOf::::zero(); + + T::FundingCurrency::transfer( + bid.funding_asset.to_statemint_id(), + &project_account, + &bid.bidder, + bid.funding_asset_amount_locked, + Preservation::Preserve, + )?; + T::NativeCurrency::release( + &LockType::Participation(project_id), + &bid.bidder, + bid.plmc_bond, + Precision::Exact, + )?; + bid.funding_asset_amount_locked = BalanceOf::::zero(); + bid.plmc_bond = BalanceOf::::zero(); + return Ok(bid); } else if bid.original_ct_amount <= buyable_amount { let maybe_ticket_size = bid.original_ct_usd_price.checked_mul_int(bid.original_ct_amount); if let Some(ticket_size) = maybe_ticket_size { @@ -1748,6 +1788,25 @@ impl Pallet { bid.status = BidStatus::Accepted; } else { bid.status = BidStatus::Rejected(RejectionReason::BadMath); + + bid.final_ct_amount = 0_u32.into(); + bid.final_ct_usd_price = PriceOf::::zero(); + + T::FundingCurrency::transfer( + bid.funding_asset.to_statemint_id(), + &project_account, + &bid.bidder, + bid.funding_asset_amount_locked, + Preservation::Preserve, + )?; + T::NativeCurrency::release( + &LockType::Participation(project_id), + &bid.bidder, + bid.plmc_bond, + Precision::Exact, + )?; + bid.funding_asset_amount_locked = BalanceOf::::zero(); + bid.plmc_bond = BalanceOf::::zero(); return Ok(bid); } } else { @@ -1815,8 +1874,6 @@ impl Pallet { return Ok(bid); } - - // TODO: PLMC-147. Refund remaining amount } Ok(bid) @@ -2100,8 +2157,8 @@ impl Pallet { let evaluator_usd_rewards = evaluation_usd_amounts .into_iter() .map(|(evaluator, (early, late))| { - let early_evaluator_weight = Perbill::from_rational(early, early_evaluator_total_locked); - let all_evaluator_weight = Perbill::from_rational(early + late, all_evaluator_total_locked); + let early_evaluator_weight = Perquintill::from_rational(early, early_evaluator_total_locked); + let all_evaluator_weight = Perquintill::from_rational(early + late, all_evaluator_total_locked); let early_reward = early_evaluator_weight * early_evaluator_rewards; let all_reward = all_evaluator_weight * all_evaluator_rewards; @@ -2155,13 +2212,13 @@ impl Pallet { let funding_reached = project_details.funding_amount_reached; // This is the "Y" variable from the knowledge hub - let percentage_of_target_funding = Perbill::from_rational(funding_reached, target_funding); + let percentage_of_target_funding = Perquintill::from_rational(funding_reached, target_funding); let fees = Self::calculate_fees(project_id)?; - let evaluator_fees = percentage_of_target_funding * (Perbill::from_percent(30) * fees); + let evaluator_fees = percentage_of_target_funding * (Perquintill::from_percent(30) * fees); - let early_evaluator_rewards = Perbill::from_percent(20) * evaluator_fees; - let all_evaluator_rewards = Perbill::from_percent(80) * evaluator_fees; + let early_evaluator_rewards = Perquintill::from_percent(20) * evaluator_fees; + let all_evaluator_rewards = Perquintill::from_percent(80) * evaluator_fees; let early_evaluator_total_locked = evaluation_usd_amounts .iter() @@ -2186,16 +2243,16 @@ impl Pallet { let project_details = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; let funding_target = project_details.fundraising_target; let funding_reached = project_details.funding_amount_reached; - let funding_ratio = Perbill::from_rational(funding_reached, funding_target); + let funding_ratio = Perquintill::from_rational(funding_reached, funding_target); // Project Automatically rejected, evaluators slashed - if funding_ratio <= Perbill::from_percent(33) { + if funding_ratio <= Perquintill::from_percent(33) { todo!() // Project Manually accepted, evaluators slashed - } else if funding_ratio < Perbill::from_percent(75) { + } else if funding_ratio < Perquintill::from_percent(75) { todo!() // Project Manually accepted, evaluators unaffected - } else if funding_ratio < Perbill::from_percent(90) { + } else if funding_ratio < Perquintill::from_percent(90) { todo!() // Project Automatically accepted, evaluators rewarded } else { diff --git a/polimec-skeleton/pallets/funding/src/tests.rs b/polimec-skeleton/pallets/funding/src/tests.rs index 958106867..1148bf22e 100644 --- a/polimec-skeleton/pallets/funding/src/tests.rs +++ b/polimec-skeleton/pallets/funding/src/tests.rs @@ -1740,7 +1740,7 @@ mod creation_round_failure { #[cfg(test)] mod evaluation_round_success { use super::*; - use sp_arithmetic::Perbill; + use sp_arithmetic::Perquintill; use testing_macros::assert_close_enough; #[test] @@ -1883,7 +1883,8 @@ mod evaluation_round_success { for (real, desired) in zip(actual_reward_balances.iter(), expected_ct_rewards.iter()) { assert_eq!(real.0, desired.0, "bad accounts order"); - assert_close_enough!(real.1, desired.1, Perbill::from_parts(1u32)); + // 0.01 parts of a Perbill + assert_close_enough!(real.1, desired.1, Perquintill::from_parts(10_000_000u64)); } } } @@ -2644,6 +2645,164 @@ mod auction_round_failure { let details = bidding_project.get_project_details(); assert_eq!(details.status, ProjectStatus::FundingFailed); } + + #[test] + fn after_ct_soldout_bid_gets_refunded() { + let test_env = TestEnvironment::new(); + let auctioning_project = + AuctioningProject::new_with(&test_env, default_project(0), ISSUER, default_evaluations()); + let metadata = auctioning_project.get_project_metadata(); + let max_cts_for_bids = metadata.total_allocation_size.clone(); + let project_id = auctioning_project.get_project_id(); + + let glutton_bid = TestBid::new( + BIDDER_1, + max_cts_for_bids, + 10_u128.into(), + None, + AcceptedFundingAsset::USDT, + ); + let rejected_bid = TestBid::new( + BIDDER_2, + 10_000 * ASSET_UNIT, + 5_u128.into(), + None, + AcceptedFundingAsset::USDT, + ); + + let mut plmc_fundings: UserToPLMCBalance = + calculate_auction_plmc_spent(vec![glutton_bid.clone(), rejected_bid.clone()]); + plmc_fundings.push((BIDDER_1, get_ed())); + plmc_fundings.push((BIDDER_2, get_ed())); + + let usdt_fundings = calculate_auction_funding_asset_spent(vec![glutton_bid.clone(), rejected_bid.clone()]); + + test_env.mint_plmc_to(plmc_fundings.clone()); + test_env.mint_statemint_asset_to(usdt_fundings.clone()); + + auctioning_project + .bid_for_users(vec![glutton_bid, rejected_bid]) + .expect("Bids should pass"); + + test_env.do_free_plmc_assertions(vec![(BIDDER_1, get_ed()), (BIDDER_2, get_ed())]); + test_env.do_reserved_plmc_assertions( + vec![(BIDDER_1, plmc_fundings[0].1), (BIDDER_2, plmc_fundings[1].1)], + LockType::Participation(project_id), + ); + test_env.do_bid_transferred_statemint_asset_assertions( + vec![ + ( + BIDDER_1, + usdt_fundings[0].1, + AcceptedFundingAsset::USDT.to_statemint_id(), + ), + ( + BIDDER_2, + usdt_fundings[1].1, + AcceptedFundingAsset::USDT.to_statemint_id(), + ), + ], + project_id, + ); + + let community_funding_project = auctioning_project.start_community_funding(); + let details = community_funding_project.get_project_details(); + + test_env.do_free_plmc_assertions(vec![(BIDDER_1, get_ed()), (BIDDER_2, plmc_fundings[1].1 + get_ed())]); + + test_env.do_reserved_plmc_assertions( + vec![(BIDDER_1, plmc_fundings[0].1), (BIDDER_2, 0)], + LockType::Participation(project_id), + ); + + test_env.do_bid_transferred_statemint_asset_assertions( + vec![ + ( + BIDDER_1, + usdt_fundings[0].1, + AcceptedFundingAsset::USDT.to_statemint_id(), + ), + (BIDDER_2, 0, AcceptedFundingAsset::USDT.to_statemint_id()), + ], + project_id, + ); + } + + #[test] + fn after_random_end_bid_gets_refunded() { + let test_env = TestEnvironment::new(); + let auctioning_project = + AuctioningProject::new_with(&test_env, default_project(0), ISSUER, default_evaluations()); + let project_id = auctioning_project.get_project_id(); + + let (bid_in, bid_out) = (default_bids()[0], default_bids()[1]); + + let mut plmc_fundings: UserToPLMCBalance = calculate_auction_plmc_spent(vec![bid_in.clone(), bid_out.clone()]); + plmc_fundings.push((BIDDER_1, get_ed())); + plmc_fundings.push((BIDDER_2, get_ed())); + + let usdt_fundings = calculate_auction_funding_asset_spent(vec![bid_in.clone(), bid_out.clone()]); + + test_env.mint_plmc_to(plmc_fundings.clone()); + test_env.mint_statemint_asset_to(usdt_fundings.clone()); + + auctioning_project + .bid_for_users(vec![bid_in]) + .expect("Bids should pass"); + + test_env.advance_time( + ::EnglishAuctionDuration::get() + + ::CandleAuctionDuration::get() + - 1, + ).unwrap(); + + auctioning_project + .bid_for_users(vec![bid_out]) + .expect("Bids should pass"); + + test_env.do_free_plmc_assertions(vec![(BIDDER_1, get_ed()), (BIDDER_2, get_ed())]); + test_env.do_reserved_plmc_assertions( + vec![(BIDDER_1, plmc_fundings[0].1), (BIDDER_2, plmc_fundings[1].1)], + LockType::Participation(project_id), + ); + test_env.do_bid_transferred_statemint_asset_assertions( + vec![ + ( + BIDDER_1, + usdt_fundings[0].1, + AcceptedFundingAsset::USDT.to_statemint_id(), + ), + ( + BIDDER_2, + usdt_fundings[1].1, + AcceptedFundingAsset::USDT.to_statemint_id(), + ), + ], + project_id, + ); + + let community_funding_project = auctioning_project.start_community_funding(); + let details = community_funding_project.get_project_details(); + + test_env.do_free_plmc_assertions(vec![(BIDDER_1, get_ed()), (BIDDER_2, plmc_fundings[1].1 + get_ed())]); + + test_env.do_reserved_plmc_assertions( + vec![(BIDDER_1, plmc_fundings[0].1), (BIDDER_2, 0)], + LockType::Participation(project_id), + ); + + test_env.do_bid_transferred_statemint_asset_assertions( + vec![ + ( + BIDDER_1, + usdt_fundings[0].1, + AcceptedFundingAsset::USDT.to_statemint_id(), + ), + (BIDDER_2, 0, AcceptedFundingAsset::USDT.to_statemint_id()), + ], + project_id, + ); + } } #[cfg(test)] @@ -3870,9 +4029,11 @@ mod misc_features { mod testing_macros { #[allow(unused_macros)] macro_rules! assert_close_enough { - ($real:expr, $desired:expr, $min_approximation:expr) => { - let real_approximation = Perbill::from_rational($real, $desired); - assert!(real_approximation >= $min_approximation); + ($real:expr, $desired:expr, $max_approximation:expr) => { + let real_parts = Perquintill::from_rational($real, $desired); + let one = Perquintill::from_percent(100u64); + let real_approximation = one - real_parts; + assert!(real_approximation <= $max_approximation); }; } pub(crate) use assert_close_enough; diff --git a/polimec-skeleton/pallets/funding/src/types.rs b/polimec-skeleton/pallets/funding/src/types.rs index 655218865..75e92f121 100644 --- a/polimec-skeleton/pallets/funding/src/types.rs +++ b/polimec-skeleton/pallets/funding/src/types.rs @@ -204,16 +204,17 @@ pub mod storage_types { Balance: BalanceT + FixedPointOperand + Ord, Price: FixedPointNumber, AccountId: Eq, - BlockNumber: Eq, + BlockNumber: Eq + Ord, PlmcVesting: Eq, CTVesting: Eq, Multiplier: Eq, > Ord for BidInfo { fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering { - let self_ticket_size = self.original_ct_usd_price.saturating_mul_int(self.original_ct_amount); - let other_ticket_size = other.original_ct_usd_price.saturating_mul_int(other.original_ct_amount); - self_ticket_size.cmp(&other_ticket_size) + match self.original_ct_usd_price.cmp(&other.original_ct_usd_price) { + sp_std::cmp::Ordering::Equal => Ord::cmp(&self.when, &other.when), + other => other, + } } } @@ -223,7 +224,7 @@ pub mod storage_types { Balance: BalanceT + FixedPointOperand, Price: FixedPointNumber, AccountId: Eq, - BlockNumber: Eq, + BlockNumber: Eq + Ord, PlmcVesting: Eq, CTVesting: Eq, Multiplier: Eq, @@ -536,7 +537,7 @@ pub mod inner_types { pub struct EvaluationRoundInfo { pub total_bonded_usd: Balance, pub total_bonded_plmc: Balance, - pub evaluators_outcome: EvaluatorsOutcome + pub evaluators_outcome: EvaluatorsOutcome, } #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)] From 926cb93b6c57ef3903c5e36e52d36a6910a21362 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Wed, 19 Jul 2023 15:51:18 +0200 Subject: [PATCH 19/80] fix(funding): re-add serde into the Cargo.toml --- polimec-skeleton/Cargo.lock | 1 + polimec-skeleton/pallets/funding/Cargo.toml | 2 ++ polimec-skeleton/pallets/linear-release/src/tests.rs | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/polimec-skeleton/Cargo.lock b/polimec-skeleton/Cargo.lock index 1a7f6c645..c94f071d5 100644 --- a/polimec-skeleton/Cargo.lock +++ b/polimec-skeleton/Cargo.lock @@ -5908,6 +5908,7 @@ dependencies = [ "parity-scale-codec", "polimec-traits", "scale-info", + "serde", "sp-arithmetic", "sp-core", "sp-io", diff --git a/polimec-skeleton/pallets/funding/Cargo.toml b/polimec-skeleton/pallets/funding/Cargo.toml index ee456ee6e..6f72aa543 100644 --- a/polimec-skeleton/pallets/funding/Cargo.toml +++ b/polimec-skeleton/pallets/funding/Cargo.toml @@ -11,6 +11,7 @@ version = "0.1.0" rust-version = "1.69.0" [dependencies] +serde = { version = "*", optional = true } parity-scale-codec = { version = "3.0.0", features = [ "derive", ], default-features = false } @@ -55,6 +56,7 @@ std = [ "polimec-traits/std", "pallet-linear-release/std", "frame-benchmarking?/std", + "serde", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", diff --git a/polimec-skeleton/pallets/linear-release/src/tests.rs b/polimec-skeleton/pallets/linear-release/src/tests.rs index fe63f1a72..f26dce97a 100644 --- a/polimec-skeleton/pallets/linear-release/src/tests.rs +++ b/polimec-skeleton/pallets/linear-release/src/tests.rs @@ -170,7 +170,7 @@ fn unvested_balance_should_not_transfer() { let user1_free_balance = Balances::free_balance(&1); assert_eq!(user1_free_balance, 50); // Account 1 has free balance // Account 1 has only 5 units vested at block 1 (plus 50 unvested) - assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(45)); // Account 1 cannot send more than vested amount... + assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(45)); // Account 1 cannot send more than vested amount... assert_noop!(Balances::transfer_allow_death(Some(1).into(), 2, 56), TokenError::FundsUnavailable); }); } From c513dd628bde3eb60edce0e9e618f748a5b1ff29 Mon Sep 17 00:00:00 2001 From: Juan Ignacio RIos Date: Wed, 19 Jul 2023 16:23:34 +0200 Subject: [PATCH 20/80] feat(214): tried to add final price check on new_with for CommunityFundingProject but it is already implemented if the caller adds it in teh BidInfoFilter --- .../pallets/funding/src/functions.rs | 14 +- polimec-skeleton/pallets/funding/src/tests.rs | 367 +++++++++++++++--- 2 files changed, 323 insertions(+), 58 deletions(-) diff --git a/polimec-skeleton/pallets/funding/src/functions.rs b/polimec-skeleton/pallets/funding/src/functions.rs index 94836b6fd..edc18deae 100644 --- a/polimec-skeleton/pallets/funding/src/functions.rs +++ b/polimec-skeleton/pallets/funding/src/functions.rs @@ -637,14 +637,12 @@ impl Pallet { let remainder_end_block = project_details.phase_transition_points.remainder.end(); // * Validity checks * - if let Some(end_block) = remainder_end_block { - ensure!(now > end_block, Error::::TooEarlyForFundingEnd); - } else { - ensure!( - remaining_cts == 0u32.into() || project_details.status == ProjectStatus::FundingFailed, - Error::::TooEarlyForFundingEnd - ); - } + ensure!( + remaining_cts == 0u32.into() + || project_details.status == ProjectStatus::FundingFailed + || matches!(remainder_end_block, Some(end_block) if now > end_block), + Error::::TooEarlyForFundingEnd + ); // * Calculate new variables * let funding_target = project_metadata diff --git a/polimec-skeleton/pallets/funding/src/tests.rs b/polimec-skeleton/pallets/funding/src/tests.rs index 1148bf22e..b2b01e84d 100644 --- a/polimec-skeleton/pallets/funding/src/tests.rs +++ b/polimec-skeleton/pallets/funding/src/tests.rs @@ -100,19 +100,24 @@ impl TestContribution { pub type TestContributions = Vec; #[derive(Clone, PartialEq, Eq, Debug)] -pub struct BidInfoFilter { - pub bid_id: Option, - pub when: Option, - pub status: Option>, - pub project: Option, +pub struct BidInfoFilter { + pub id: Option, + pub project_id: Option, pub bidder: Option, - pub ct_amount: Option, - pub ct_usd_price: Option, + pub status: Option>, + pub original_ct_amount: Option, + pub original_ct_usd_price: Option, + pub final_ct_amount: Option, + pub final_ct_usd_price: Option, + pub funding_asset: Option, + pub funding_asset_amount_locked: Option, + pub multiplier: Option, + pub plmc_bond: Option, pub funded: Option, pub plmc_vesting_period: Option, pub ct_vesting_period: Option, - pub funding_asset: Option, - pub funding_asset_amount: Option, + pub when: Option, + pub funds_released: Option, } type BidInfoFilterOf = BidInfoFilter< ::StorageItemId, @@ -120,6 +125,7 @@ type BidInfoFilterOf = BidInfoFilter< BalanceOf, PriceOf, ::AccountId, + MultiplierOf, BlockNumberOf, VestingOf, VestingOf, @@ -127,60 +133,77 @@ type BidInfoFilterOf = BidInfoFilter< impl Default for BidInfoFilterOf { fn default() -> Self { BidInfoFilter { - bid_id: None, - when: None, - status: None, - project: None, + id: None, + project_id: None, bidder: None, - ct_amount: None, - ct_usd_price: None, + status: None, + original_ct_amount: None, + original_ct_usd_price: None, + final_ct_amount: None, + final_ct_usd_price: None, + funding_asset: None, + funding_asset_amount_locked: None, + multiplier: None, + plmc_bond: None, funded: None, plmc_vesting_period: None, ct_vesting_period: None, - funding_asset: None, - funding_asset_amount: None, + when: None, + funds_released: None, } } } impl BidInfoFilterOf { fn matches_bid(&self, bid: &BidInfoOf) -> bool { - if self.bid_id.is_some() && self.bid_id.unwrap() != bid.id { + if self.id.is_some() && self.id.unwrap() != bid.id { return false; } - if self.when.is_some() && self.when.unwrap() != bid.when { + if self.project_id.is_some() && self.project_id.unwrap() != bid.project_id { + return false; + } + if self.bidder.is_some() && self.bidder.unwrap() != bid.bidder { return false; } if self.status.is_some() && self.status.as_ref().unwrap() != &bid.status { return false; } - if self.project.is_some() && self.project.unwrap() != bid.project_id { + if self.original_ct_amount.is_some() && self.original_ct_amount.unwrap() != bid.original_ct_amount { return false; } - if self.bidder.is_some() && self.bidder.unwrap() != bid.bidder { + if self.original_ct_usd_price.is_some() && self.original_ct_usd_price.unwrap() != bid.original_ct_usd_price { + return false; + } + if self.final_ct_amount.is_some() && self.final_ct_amount.unwrap() != bid.final_ct_amount { + return false; + } + if self.final_ct_usd_price.is_some() && self.final_ct_usd_price.unwrap() != bid.final_ct_usd_price { + return false; + } + if self.funding_asset.is_some() && self.funding_asset.unwrap() != bid.funding_asset { return false; } - if self.ct_amount.is_some() && self.ct_amount.unwrap() != bid.original_ct_amount { + if self.funding_asset_amount_locked.is_some() && self.funding_asset_amount_locked.unwrap() != bid.funding_asset_amount_locked { return false; } - if self.ct_usd_price.is_some() && self.ct_usd_price.unwrap() != bid.original_ct_usd_price { + if self.multiplier.is_some() && self.multiplier.unwrap() != bid.multiplier { + return false; + } + if self.plmc_bond.is_some() && self.plmc_bond.unwrap() != bid.plmc_bond { return false; } if self.funded.is_some() && self.funded.unwrap() != bid.funded { return false; } - if self.plmc_vesting_period.is_some() && self.plmc_vesting_period.as_ref().unwrap() != &bid.plmc_vesting_period - { + if self.plmc_vesting_period.is_some() && self.plmc_vesting_period.unwrap() != bid.plmc_vesting_period { return false; } - if self.ct_vesting_period.is_some() && self.ct_vesting_period.as_ref().unwrap() != &bid.ct_vesting_period { + if self.ct_vesting_period.is_some() && self.ct_vesting_period.unwrap() != bid.ct_vesting_period { return false; } - if self.funding_asset.is_some() && self.funding_asset.as_ref().unwrap() != &bid.funding_asset { + if self.when.is_some() && self.when.unwrap() != bid.when { return false; } - if self.funding_asset_amount.is_some() - && self.funding_asset_amount.as_ref().unwrap() != &bid.funding_asset_amount_locked - { + if self.funds_released.is_some() && self.funds_released.unwrap() != bid.funds_released { return false; } @@ -325,6 +348,17 @@ impl TestEnvironment { balances }) } + fn get_all_reserved_plmc_balances(&self, reserve_type: LockType>) -> UserToPLMCBalance { + self.ext_env.borrow_mut().execute_with(|| { + let mut fundings = UserToPLMCBalance::new(); + let user_keys: Vec = frame_system::Account::::iter_keys().collect(); + for user in user_keys { + let funding = Balances::balance_on_hold(&reserve_type, &user); + fundings.push((user, funding)); + } + fundings + }) + } #[allow(dead_code)] fn get_all_free_statemint_asset_balances(&self, asset_id: AssetId) -> UserToStatemintAsset { self.ext_env.borrow_mut().execute_with(|| { @@ -338,6 +372,7 @@ impl TestEnvironment { balances }) } + fn get_free_plmc_balances_for(&self, user_keys: Vec) -> UserToPLMCBalance { self.ext_env.borrow_mut().execute_with(|| { let mut balances = UserToPLMCBalance::new(); @@ -349,6 +384,17 @@ impl TestEnvironment { balances }) } + fn get_reserved_plmc_balances_for(&self, user_keys: Vec, lock_type: LockType>) -> UserToPLMCBalance { + self.ext_env.borrow_mut().execute_with(|| { + let mut balances = UserToPLMCBalance::new(); + for user in user_keys { + let funding = Balances::balance_on_hold(&lock_type, &user); + balances.push((user, funding)); + } + balances.sort_by(|a, b| a.0.cmp(&b.0)); + balances + }) + } fn get_free_statemint_asset_balances_for( &self, asset_id: AssetId, user_keys: Vec, ) -> UserToStatemintAsset { @@ -377,18 +423,7 @@ impl TestEnvironment { }); } } - #[allow(dead_code)] - fn get_reserved_fundings(&self, reserve_type: LockType>) -> UserToPLMCBalance { - self.ext_env.borrow_mut().execute_with(|| { - let mut fundings = UserToPLMCBalance::new(); - let user_keys: Vec = frame_system::Account::::iter_keys().collect(); - for user in user_keys { - let funding = Balances::balance_on_hold(&reserve_type, &user); - fundings.push((user, funding)); - } - fundings - }) - } + fn mint_plmc_to(&self, mapping: UserToPLMCBalance) { self.ext_env.borrow_mut().execute_with(|| { for (account, amount) in mapping { @@ -866,8 +901,8 @@ impl<'a> CommunityFundingProject<'a> { "Weighted average price should exist" ); - for filter in bid_expectations { - assert!(flattened_bids.iter().any(|bid| filter.matches_bid(&bid))) + for mut filter in bid_expectations { + let _found_bid = flattened_bids.iter().find(|bid| filter.matches_bid(&bid)).unwrap(); } // Remaining CTs are updated @@ -1559,13 +1594,22 @@ pub mod helper_functions { pub fn err_if_on_initialize_failed( events: Vec>, - ) -> Result<(), DispatchError> { + ) -> Result<(), Error> { let last_event = events.into_iter().last().expect("No events found for this action."); match last_event { frame_system::EventRecord { event: RuntimeEvent::FundingModule(Event::TransitionError { project_id: _, error }), .. - } => Err(error), + } => { + match error { + DispatchError::Module(module_error) => { + let pallet_error: Error = Decode::decode(&mut &module_error.error[..]).unwrap(); + Err(pallet_error) + + } + _ => panic!("wrong conversion") + } + }, _ => Ok(()), } } @@ -1887,6 +1931,79 @@ mod evaluation_round_success { assert_close_enough!(real.1, desired.1, Perquintill::from_parts(10_000_000u64)); } } + + #[test] + fn plmc_unbonded_after_funding_success() { + let test_env = TestEnvironment::new(); + let evaluations = default_evaluations(); + let evaluators = evaluations.iter().map(|ev|ev.0.clone()).collect::>(); + + let remainder_funding_project = RemainderFundingProject::new_with( + &test_env, + default_project(test_env.get_new_nonce()), + ISSUER, + evaluations.clone(), + default_bids(), + default_community_buys(), + ); + let project_id = remainder_funding_project.get_project_id(); + let prev_reserved_plmc = test_env.get_reserved_plmc_balances_for(evaluators.clone(), LockType::Evaluation(project_id)); + + let prev_free_plmc = test_env.get_free_plmc_balances_for(evaluators.clone()); + + remainder_funding_project.end_funding(); + test_env.advance_time(10).unwrap(); + + let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc.iter().map(|(evaluator, amount)| (*evaluator, Zero::zero())).collect(); + + let temp_actual_par_lock = test_env.get_all_reserved_plmc_balances(LockType::Participation(project_id)); + + test_env.do_reserved_plmc_assertions(post_unbond_amounts.clone(), LockType::Evaluation(project_id)); + test_env.do_reserved_plmc_assertions(post_unbond_amounts, LockType::Participation(project_id)); + + let post_free_plmc = test_env.get_free_plmc_balances_for(evaluators.clone()); + + let increased_amounts = merge_subtract_mappings_by_user(post_free_plmc, vec![prev_free_plmc]); + + assert_eq!(increased_amounts, calculate_evaluation_plmc_spent(evaluations)) + } + + #[test] + fn plmc_unbonded_after_funding_failure() { + let test_env = TestEnvironment::new(); + let evaluations = default_evaluations(); + let evaluators = evaluations.iter().map(|ev|ev.0.clone()).collect::>(); + + let remainder_funding_project = RemainderFundingProject::new_with( + &test_env, + default_project(test_env.get_new_nonce()), + ISSUER, + evaluations.clone(), + default_bids(), , + ); + let project_id = remainder_funding_project.get_project_id(); + let prev_reserved_plmc = test_env.get_reserved_plmc_balances_for(evaluators.clone(), LockType::Evaluation(project_id)); + + let prev_free_plmc = test_env.get_free_plmc_balances_for(evaluators.clone()); + + remainder_funding_project.end_funding(); + test_env.advance_time(10).unwrap(); + + let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc.iter().map(|(evaluator, amount)| (*evaluator, Zero::zero())).collect(); + + let temp_actual_par_lock = test_env.get_all_reserved_plmc_balances(LockType::Participation(project_id)); + + test_env.do_reserved_plmc_assertions(post_unbond_amounts.clone(), LockType::Evaluation(project_id)); + test_env.do_reserved_plmc_assertions(post_unbond_amounts, LockType::Participation(project_id)); + + let post_free_plmc = test_env.get_free_plmc_balances_for(evaluators.clone()); + + let increased_amounts = merge_subtract_mappings_by_user(post_free_plmc, vec![prev_free_plmc]); + + assert_eq!(increased_amounts, calculate_evaluation_plmc_spent(evaluations)) + } + + } #[cfg(test)] @@ -2601,12 +2718,13 @@ mod auction_round_failure { auctioning_project.bid_for_users(bids).expect("Bids should pass"); test_env.ext_env.borrow_mut().execute_with(|| { - let stored_bids = FundingModule::bids(project_id, DAVE); + let mut stored_bids = FundingModule::bids(project_id, DAVE); assert_eq!(stored_bids.len(), 4); + stored_bids.sort(); assert_eq!(stored_bids[0].original_ct_usd_price, 5_u128.into()); - assert_eq!(stored_bids[1].original_ct_usd_price, 8_u128.into()); - assert_eq!(stored_bids[2].original_ct_usd_price, 5_u128.into()); - assert_eq!(stored_bids[3].original_ct_usd_price, 2_u128.into()); + assert_eq!(stored_bids[1].original_ct_usd_price, 5_u128.into()); + assert_eq!(stored_bids[2].original_ct_usd_price, 7_u128.into()); + assert_eq!(stored_bids[3].original_ct_usd_price, 8_u128.into()); }); } @@ -3543,6 +3661,155 @@ mod remainder_round_success { }); assert_eq!(evaluation_bond, 0); } + + #[test] + fn remainder_round_ends_on_all_ct_sold_exact() { + let test_env = TestEnvironment::new(); + let remainder_funding_project = RemainderFundingProject::new_with( + &test_env, + default_project(0), + ISSUER, + default_evaluations(), + default_bids(), + default_community_buys() + ); + const BOB: AccountId = 808; + + let remaining_ct = remainder_funding_project + .get_project_details() + .remaining_contribution_tokens; + let ct_price = remainder_funding_project + .get_project_details() + .weighted_average_price + .expect("CT Price should exist"); + let project_id = remainder_funding_project.get_project_id(); + + let contributions: TestContributions = vec![TestContribution::new( + BOB, + remaining_ct, + None, + AcceptedFundingAsset::USDT, + )]; + let mut plmc_fundings: UserToPLMCBalance = calculate_contributed_plmc_spent(contributions.clone(), ct_price); + plmc_fundings.push((BOB, get_ed())); + let statemint_asset_fundings: UserToStatemintAsset = + calculate_contributed_funding_asset_spent(contributions.clone(), ct_price); + + test_env.mint_plmc_to(plmc_fundings.clone()); + test_env.mint_statemint_asset_to(statemint_asset_fundings.clone()); + + // Buy remaining CTs + remainder_funding_project + .buy_for_any_user(contributions) + .expect("The Buyer should be able to buy the exact amount of remaining CTs"); + test_env.advance_time(2u64).unwrap(); + + // Check remaining CTs is 0 + assert_eq!( + remainder_funding_project + .get_project_details() + .remaining_contribution_tokens, + 0, + "There are still remaining CTs" + ); + + // Check project is in FundingEnded state + assert_eq!( + remainder_funding_project.get_project_details().status, + ProjectStatus::FundingSuccessful + ); + + test_env.do_free_plmc_assertions(vec![plmc_fundings[1].clone()]); + test_env.do_free_statemint_asset_assertions(vec![(BOB, 0_u128, AcceptedFundingAsset::USDT.to_statemint_id())]); + test_env.do_reserved_plmc_assertions(vec![plmc_fundings[0].clone()], LockType::Participation(project_id)); + test_env.do_contribution_transferred_statemint_asset_assertions( + statemint_asset_fundings, + remainder_funding_project.get_project_id(), + ); + } + + #[test] + fn remainder_round_ends_on_all_ct_sold_overbuy() { + let test_env = TestEnvironment::new(); + let remainder_funding_project = RemainderFundingProject::new_with( + &test_env, + default_project(0), + ISSUER, + default_evaluations(), + default_bids(), + default_community_buys() + ); + const BOB: AccountId = 808; + const OVERBUY_CT: BalanceOf = 40 * ASSET_UNIT; + + let remaining_ct = remainder_funding_project + .get_project_details() + .remaining_contribution_tokens; + + let ct_price = remainder_funding_project + .get_project_details() + .weighted_average_price + .expect("CT Price should exist"); + + let project_id = remainder_funding_project.get_project_id(); + + let contributions: TestContributions = vec![ + TestContribution::new(BOB, remaining_ct, None, AcceptedFundingAsset::USDT), + TestContribution::new(BOB, OVERBUY_CT, None, AcceptedFundingAsset::USDT), + ]; + let mut plmc_fundings: UserToPLMCBalance = calculate_contributed_plmc_spent(contributions.clone(), ct_price); + plmc_fundings.push((BOB, get_ed())); + let mut statemint_asset_fundings: UserToStatemintAsset = + calculate_contributed_funding_asset_spent(contributions.clone(), ct_price); + + test_env.mint_plmc_to(plmc_fundings.clone()); + test_env.mint_statemint_asset_to(statemint_asset_fundings.clone()); + + // Buy remaining CTs + remainder_funding_project + .buy_for_any_user(contributions) + .expect("The Buyer should be able to buy the exact amount of remaining CTs"); + test_env.advance_time(2u64).unwrap(); + + // Check remaining CTs is 0 + assert_eq!( + remainder_funding_project + .get_project_details() + .remaining_contribution_tokens, + 0, + "There are still remaining CTs" + ); + + // Check project is in FundingEnded state + assert_eq!( + remainder_funding_project.get_project_details().status, + ProjectStatus::FundingSuccessful + ); + + let reserved_plmc = plmc_fundings.swap_remove(0).1; + let remaining_plmc: Balance = plmc_fundings.iter().fold(0_u128, |acc, (_, amount)| acc + amount); + + let actual_funding_transferred = statemint_asset_fundings.swap_remove(0).1; + let remaining_statemint_assets: Balance = statemint_asset_fundings + .iter() + .fold(0_u128, |acc, (_, amount, _)| acc + amount); + + test_env.do_free_plmc_assertions(vec![(BOB, remaining_plmc)]); + test_env.do_free_statemint_asset_assertions(vec![( + BOB, + remaining_statemint_assets, + AcceptedFundingAsset::USDT.to_statemint_id(), + )]); + test_env.do_reserved_plmc_assertions(vec![(BOB, reserved_plmc)], LockType::Participation(project_id)); + test_env.do_contribution_transferred_statemint_asset_assertions( + vec![( + BOB, + actual_funding_transferred, + AcceptedFundingAsset::USDT.to_statemint_id(), + )], + remainder_funding_project.get_project_id(), + ); + } } #[cfg(test)] From f3d113b24bc50bc6e781ed6f88d6bb262ce00873 Mon Sep 17 00:00:00 2001 From: Juan Ignacio RIos Date: Wed, 19 Jul 2023 17:03:06 +0200 Subject: [PATCH 21/80] fix(214): reflecting BidInfoFilter changes on tests --- polimec-skeleton/pallets/funding/src/tests.rs | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/polimec-skeleton/pallets/funding/src/tests.rs b/polimec-skeleton/pallets/funding/src/tests.rs index b2b01e84d..b903447bd 100644 --- a/polimec-skeleton/pallets/funding/src/tests.rs +++ b/polimec-skeleton/pallets/funding/src/tests.rs @@ -846,8 +846,8 @@ impl<'a> CommunityFundingProject<'a> { let bid_expectations = bids .iter() .map(|bid| BidInfoFilter { - ct_amount: Some(bid.amount), - ct_usd_price: Some(bid.price), + original_ct_amount: Some(bid.amount), + original_ct_usd_price: Some(bid.price), ..Default::default() }) .collect::>(); @@ -1979,14 +1979,17 @@ mod evaluation_round_success { default_project(test_env.get_new_nonce()), ISSUER, evaluations.clone(), - default_bids(), , + vec![TestBid::new(BUYER_1, 1000 * ASSET_UNIT, 10u128.into(), None, AcceptedFundingAsset::USDT)], + vec![TestContribution::new(BUYER_1, 1000 * US_DOLLAR, None, AcceptedFundingAsset::USDT)], ); + let project_id = remainder_funding_project.get_project_id(); let prev_reserved_plmc = test_env.get_reserved_plmc_balances_for(evaluators.clone(), LockType::Evaluation(project_id)); let prev_free_plmc = test_env.get_free_plmc_balances_for(evaluators.clone()); - remainder_funding_project.end_funding(); + let finished_project = remainder_funding_project.end_funding(); + assert_eq!(finished_project.get_project_details().status, ProjectStatus::FundingFailed); test_env.advance_time(10).unwrap(); let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc.iter().map(|(evaluator, amount)| (*evaluator, Zero::zero())).collect(); @@ -2423,10 +2426,10 @@ mod auction_round_success { let pid = auctioning_project.get_project_id(); let stored_bids = auctioning_project.in_ext(|| FundingModule::bids(pid, bid.bidder)); let desired_bid = BidInfoFilter { - project: Some(pid), + project_id: Some(pid), bidder: Some(bid.bidder), - ct_amount: Some(bid.amount), - ct_usd_price: Some(bid.price), + original_ct_amount: Some(bid.amount), + original_ct_usd_price: Some(bid.price), status: Some(BidStatus::Accepted), ..Default::default() }; @@ -2441,10 +2444,10 @@ mod auction_round_success { let pid = auctioning_project.get_project_id(); let stored_bids = auctioning_project.in_ext(|| FundingModule::bids(pid, bid.bidder)); let desired_bid = BidInfoFilter { - project: Some(pid), + project_id: Some(pid), bidder: Some(bid.bidder), - ct_amount: Some(bid.amount), - ct_usd_price: Some(bid.price), + original_ct_amount: Some(bid.amount), + original_ct_usd_price: Some(bid.price), status: Some(BidStatus::Rejected(RejectionReason::AfterCandleEnd)), ..Default::default() }; From f3d83aad0c40023bd84ad35e0125f8b4e98a28a4 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Thu, 20 Jul 2023 18:25:12 +0200 Subject: [PATCH 22/80] feat: homogeneous parameters --- polimec-skeleton/pallets/linear-release/src/traits.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/polimec-skeleton/pallets/linear-release/src/traits.rs b/polimec-skeleton/pallets/linear-release/src/traits.rs index dec58e76f..2cc5e5e53 100644 --- a/polimec-skeleton/pallets/linear-release/src/traits.rs +++ b/polimec-skeleton/pallets/linear-release/src/traits.rs @@ -47,6 +47,7 @@ pub trait ReleaseSchedule { locked: >::Balance, per_block: >::Balance, starting_block: Self::Moment, + reason: Reason ) -> DispatchResult; /// Checks if `add_release_schedule` would work against `who`. @@ -55,6 +56,7 @@ pub trait ReleaseSchedule { locked: >::Balance, per_block: >::Balance, starting_block: Self::Moment, + reason: Reason ) -> DispatchResult; /// Remove a release schedule for a given account. From 90d126cdec24fb63a576b71434146fd8ca336ca7 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Thu, 20 Jul 2023 18:28:48 +0200 Subject: [PATCH 23/80] feat: use multiple reasons --- .../pallets/linear-release/src/impls.rs | 49 +++-- .../pallets/linear-release/src/lib.rs | 32 +-- .../pallets/linear-release/src/tests.rs | 203 ++++++++++++------ 3 files changed, 177 insertions(+), 107 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/impls.rs b/polimec-skeleton/pallets/linear-release/src/impls.rs index 577bb028c..bad01916f 100644 --- a/polimec-skeleton/pallets/linear-release/src/impls.rs +++ b/polimec-skeleton/pallets/linear-release/src/impls.rs @@ -62,7 +62,7 @@ impl Pallet { }; // Check we can add to this account prior to any storage writes. - Self::can_add_release_schedule(&target, schedule.locked(), schedule.per_block(), schedule.starting_block())?; + Self::can_add_release_schedule(&target, schedule.locked(), schedule.per_block(), schedule.starting_block(), reason)?; let amount_transferred = T::Currency::transfer_and_hold( &reason, @@ -147,14 +147,15 @@ impl Pallet { pub fn write_vesting( who: &T::AccountId, schedules: Vec, BlockNumberFor>>, + reason: ReasonOf, ) -> Result<(), DispatchError> { let schedules: BoundedVec, BlockNumberFor>, MaxVestingSchedulesGet> = schedules.try_into().map_err(|_| Error::::AtMaxVestingSchedules)?; if schedules.len() == 0 { - Vesting::::remove(&who); + Vesting::::remove(&who, reason); } else { - Vesting::::insert(who, schedules) + Vesting::::insert(who, reason, schedules) } Ok(()) @@ -162,11 +163,11 @@ impl Pallet { /// Unlock any vested funds of `who`. pub fn do_vest(who: T::AccountId, reason: ReasonOf) -> DispatchResult { - let schedules = Self::vesting(&who).ok_or(Error::::NotVesting)?; + let schedules = Self::vesting(&who, reason).ok_or(Error::::NotVesting)?; let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), VestingAction::Passive)?; - Self::write_vesting(&who, schedules)?; + Self::write_vesting(&who, schedules, reason)?; Self::write_lock(&who, locked_now, reason)?; Ok(()) @@ -220,7 +221,7 @@ impl ReleaseSchedule, ReasonOf> for Pallet { /// Get the amount that is currently being vested and cannot be transferred out of this account. fn vesting_balance(who: &T::AccountId, reason: ReasonOf) -> Option> { - if let Some(v) = Self::vesting(who) { + if let Some(v) = Self::vesting(who, reason) { let now = >::block_number(); let total_locked_now = v.iter().fold(Zero::zero(), |total, schedule| { schedule.locked_at::(now).saturating_add(total) @@ -260,7 +261,7 @@ impl ReleaseSchedule, ReasonOf> for Pallet { return Err(Error::::InvalidScheduleParams.into()); }; - let mut schedules = Self::vesting(who).unwrap_or_default(); + let mut schedules = Self::vesting(who, reason).unwrap_or_default(); // NOTE: we must push the new schedule so that `exec_action` // will give the correct new locked amount. @@ -268,7 +269,7 @@ impl ReleaseSchedule, ReasonOf> for Pallet { let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), VestingAction::Passive)?; - Self::write_vesting(who, schedules)?; + Self::write_vesting(who, schedules, reason)?; Self::write_lock(who, locked_now, reason)?; Ok(()) } @@ -280,6 +281,7 @@ impl ReleaseSchedule, ReasonOf> for Pallet { locked: BalanceOf, per_block: BalanceOf, starting_block: BlockNumberFor, + reason: ReasonOf ) -> DispatchResult { // Check for `per_block` or `locked` of 0. if !VestingInfo::new(locked, per_block, starting_block).is_valid() { @@ -287,30 +289,19 @@ impl ReleaseSchedule, ReasonOf> for Pallet { } ensure!( - (Vesting::::decode_len(who).unwrap_or_default() as u32) < T::MAX_VESTING_SCHEDULES, + (Vesting::::decode_len(who, reason).unwrap_or_default() as u32) < T::MAX_VESTING_SCHEDULES, Error::::AtMaxVestingSchedules ); Ok(()) } - /// Remove a vesting schedule for a given account. - fn remove_vesting_schedule(who: &T::AccountId, schedule_index: u32, reason: ReasonOf) -> DispatchResult { - let schedules = Self::vesting(who).ok_or(Error::::NotVesting)?; - let remove_action = VestingAction::Remove { index: schedule_index as usize }; - - let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), remove_action)?; - - Self::write_vesting(who, schedules)?; - Self::write_lock(who, locked_now, reason)?; - Ok(()) - } - fn set_release_schedule( who: &T::AccountId, locked: >::Balance, per_block: >::Balance, starting_block: Self::Moment, + reason: ReasonOf ) -> DispatchResult { if locked.is_zero() { return Ok(()); @@ -322,7 +313,7 @@ impl ReleaseSchedule, ReasonOf> for Pallet { return Err(Error::::InvalidScheduleParams.into()); }; - let mut schedules = Self::vesting(who).unwrap_or_default(); + let mut schedules = Self::vesting(who, reason).unwrap_or_default(); // NOTE: we must push the new schedule so that `exec_action` // will give the correct new locked amount. @@ -330,7 +321,19 @@ impl ReleaseSchedule, ReasonOf> for Pallet { let (schedules, _) = Self::exec_action(schedules.to_vec(), VestingAction::Passive)?; - Self::write_vesting(who, schedules)?; + Self::write_vesting(who, schedules, reason)?; + Ok(()) + } + + /// Remove a vesting schedule for a given account. + fn remove_vesting_schedule(who: &T::AccountId, schedule_index: u32, reason: ReasonOf) -> DispatchResult { + let schedules = Self::vesting(who, reason).ok_or(Error::::NotVesting)?; + let remove_action = VestingAction::Remove { index: schedule_index as usize }; + + let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), remove_action)?; + + Self::write_vesting(who, schedules, reason)?; + Self::write_lock(who, locked_now, reason)?; Ok(()) } } diff --git a/polimec-skeleton/pallets/linear-release/src/lib.rs b/polimec-skeleton/pallets/linear-release/src/lib.rs index 898c8085b..cdc187f07 100644 --- a/polimec-skeleton/pallets/linear-release/src/lib.rs +++ b/polimec-skeleton/pallets/linear-release/src/lib.rs @@ -189,11 +189,9 @@ pub mod pallet { panic!("Invalid VestingInfo params at genesis") }; - Vesting::::try_append(who, vesting_info).expect("Too many vesting schedules at genesis."); + Vesting::::try_append(who, reason, vesting_info).expect("Too many vesting schedules at genesis."); - T::Currency::hold(&reason, who, locked) - .map_err(|err| panic!("{:?}", err)) - .unwrap(); + T::Currency::hold(&reason, who, locked).map_err(|err| panic!("{:?}", err)).unwrap(); } } } @@ -236,20 +234,15 @@ pub mod pallet { InvalidScheduleParams, } - /// The MEL requirement for bounded pallets is skipped by `dev_mode`. - /// This means that all storages are marked as unbounded. - /// This is equivalent to specifying `#[pallet::unbounded]` on this type definitions. - /// When the dev_mode is removed, we would need to implement implement `MaxEncodedLen`. - #[pallet::storage] - pub type Dummy = StorageValue<_, Vec>; - /// Information regarding the vesting of a given account. #[pallet::storage] #[pallet::getter(fn vesting)] - pub type Vesting = StorageMap< + pub type Vesting = StorageDoubleMap< _, Blake2_128Concat, - T::AccountId, + AccountIdOf, + Blake2_128Concat, + ReasonOf, BoundedVec, BlockNumberFor>, MaxVestingSchedulesGet>, >; @@ -372,24 +365,15 @@ pub mod pallet { let schedule1_index = schedule1_index as usize; let schedule2_index = schedule2_index as usize; - let schedules = Self::vesting(&who).ok_or(Error::::NotVesting)?; + let schedules = Self::vesting(&who, reason).ok_or(Error::::NotVesting)?; let merge_action = VestingAction::Merge { index1: schedule1_index, index2: schedule2_index }; let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), merge_action)?; - Self::write_vesting(&who, schedules)?; + Self::write_vesting(&who, schedules, reason)?; Self::write_lock(&who, locked_now, reason)?; Ok(()) } - - #[pallet::call_index(5)] - pub fn release_schedule( - origin: OriginFor, - schedule: VestingInfo, BlockNumberFor>, - ) -> DispatchResult { - let transactor = ensure_signed(origin)?; - Self::set_release_schedule(&transactor, schedule.locked(), schedule.per_block(), schedule.starting_block()) - } } } diff --git a/polimec-skeleton/pallets/linear-release/src/tests.rs b/polimec-skeleton/pallets/linear-release/src/tests.rs index f26dce97a..a57c751fb 100644 --- a/polimec-skeleton/pallets/linear-release/src/tests.rs +++ b/polimec-skeleton/pallets/linear-release/src/tests.rs @@ -16,14 +16,15 @@ const ED: u64 = 256; /// Calls vest, and asserts that there is no entry for `account` /// in the `Vesting` storage item. -fn vest_and_assert_no_vesting(account: u64) +fn vest_and_assert_no_vesting(account: u64, reason: LockType) where - u64: EncodeLike<::AccountId>, + u64: EncodeLike>, + LockType: EncodeLike>, T: pallet::Config, { // Its ok for this to fail because the user may already have no schedules. let _result: Result<(), DispatchError> = Vesting::vest(Some(account).into(), LockType::Participation(0)); - assert!(!>::contains_key(account)); + assert!(!>::contains_key(account, reason)); } #[test] @@ -50,9 +51,9 @@ fn check_vesting_status() { 64, // Vesting over 20 blocks 10, ); - assert_eq!(Vesting::vesting(&1).unwrap(), vec![user1_vesting_schedule]); // Account 1 has a vesting schedule - assert_eq!(Vesting::vesting(&2).unwrap(), vec![user2_vesting_schedule]); // Account 2 has a vesting schedule - assert_eq!(Vesting::vesting(&12).unwrap(), vec![user12_vesting_schedule]); // Account 12 has a vesting schedule + assert_eq!(Vesting::vesting(&1, LockType::Participation(0)).unwrap(), vec![user1_vesting_schedule]); // Account 1 has a vesting schedule + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![user2_vesting_schedule]); // Account 2 has a vesting schedule + assert_eq!(Vesting::vesting(&12, LockType::Participation(0)).unwrap(), vec![user12_vesting_schedule]); // Account 12 has a vesting schedule // Account 1 has only 128 units vested from their illiquid ED * 5 units at block 1 assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(128 * 9)); @@ -79,9 +80,9 @@ fn check_vesting_status() { assert_eq!(Vesting::vesting_balance(&12, LockType::Participation(0)), Some(0)); // Account 2 has fully vested by block 30 // Once we unlock the funds, they are removed from storage. - vest_and_assert_no_vesting::(1); - vest_and_assert_no_vesting::(2); - vest_and_assert_no_vesting::(12); + vest_and_assert_no_vesting::(1, LockType::Participation(0)); + vest_and_assert_no_vesting::(2, LockType::Participation(0)); + vest_and_assert_no_vesting::(12, LockType::Participation(0)); }); } @@ -95,7 +96,7 @@ fn check_vesting_status_for_multi_schedule_account() { 10, ); // Account 2 already has a vesting schedule. - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0]); // Account 2's free balance is the one set in Genesis inside the Balances pallet. let balance = Balances::balance(&2); @@ -115,7 +116,7 @@ fn check_vesting_status_for_multi_schedule_account() { let balance = Balances::balance(&2); assert_eq!(balance, ED * (2)); // The most recently added schedule exists. - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0, sched1]); // Add a 3rd schedule. let sched2 = VestingInfo::new( @@ -158,9 +159,9 @@ fn check_vesting_status_for_multi_schedule_account() { assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(0)); // Since we have not called any extrinsics that would unlock funds the schedules // are still in storage, - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0, sched1, sched2]); // but once we unlock the funds, they are removed from storage. - vest_and_assert_no_vesting::(2); + vest_and_assert_no_vesting::(2, LockType::Participation(0)); }); } @@ -210,7 +211,7 @@ fn vested_balance_should_transfer_with_multi_sched() { assert_eq!(user13_free_balance, user13_initial_free_balance - sched0.locked()); // Account "1" has 2 release schedule applied now: one from the Genesis and one from the transfer - assert_eq!(Vesting::vesting(&1).unwrap(), vec![sched0, sched0]); + assert_eq!(Vesting::vesting(&1, LockType::Participation(0)).unwrap(), vec![sched0, sched0]); let user1_free_balance = Balances::free_balance(&1); assert_eq!(user1_free_balance, user1_initial_free_balance + (2 * sched0.per_block())); @@ -225,7 +226,7 @@ fn vested_balance_should_transfer_with_multi_sched() { #[test] fn non_vested_cannot_vest() { ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - assert!(!>::contains_key(4)); + assert!(!>::contains_key(4, LockType::Participation(0))); assert_noop!(Vesting::vest(Some(4).into(), LockType::Participation(0)), Error::::NotVesting); }); } @@ -248,7 +249,7 @@ fn vested_balance_should_transfer_using_vest_other_with_multi_sched() { let sched0 = VestingInfo::new(5 * ED, 128, 0); assert_ok!(Vesting::vested_transfer(Some(13).into(), 1, sched0, LockType::Participation(0))); // Total of 10*ED of locked for all the schedules. - assert_eq!(Vesting::vesting(&1).unwrap(), vec![sched0, sched0]); + assert_eq!(Vesting::vesting(&1, LockType::Participation(0)).unwrap(), vec![sched0, sched0]); let user1_free_balance = Balances::free_balance(&1); assert_eq!(user1_free_balance, 1536); // Account 1 has free balance @@ -263,7 +264,7 @@ fn vested_balance_should_transfer_using_vest_other_with_multi_sched() { #[test] fn non_vested_cannot_vest_other() { ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { - assert!(!>::contains_key(4)); + assert!(!>::contains_key(4, LockType::Participation(0))); assert_noop!(Vesting::vest_other(Some(3).into(), 4, LockType::Participation(0)), Error::::NotVesting); }); } @@ -314,7 +315,7 @@ fn liquid_funds_should_transfer_with_delayed_vesting() { 64, // Vesting over 20 blocks 10, ); - assert_eq!(Vesting::vesting(&12).unwrap(), vec![user12_vesting_schedule]); + assert_eq!(Vesting::vesting(&12, LockType::Participation(0)).unwrap(), vec![user12_vesting_schedule]); // Account 12 can still send liquid funds assert_ok!(Balances::transfer_allow_death(Some(12).into(), 3, 256 * 5 - 256)); @@ -329,7 +330,7 @@ fn vested_transfer_works() { assert_eq!(user3_free_balance, 256 * 30); assert_eq!(user4_free_balance, 256 * 40); // Account 4 should not have any vesting yet. - assert_eq!(Vesting::vesting(&4), None); + assert_eq!(Vesting::vesting(&4, LockType::Participation(0)), None); // Make the schedule for the new transfer. let new_vesting_schedule = VestingInfo::new( 256 * 5, @@ -338,7 +339,7 @@ fn vested_transfer_works() { ); assert_ok!(Vesting::vested_transfer(Some(3).into(), 4, new_vesting_schedule, LockType::Participation(0))); // Now account 4 should have vesting. - assert_eq!(Vesting::vesting(&4).unwrap(), vec![new_vesting_schedule]); + assert_eq!(Vesting::vesting(&4, LockType::Participation(0)).unwrap(), vec![new_vesting_schedule]); // Ensure the transfer happened correctly. let user3_free_balance_updated = Balances::free_balance(&3); assert_eq!(user3_free_balance_updated, 256 * 25); @@ -359,7 +360,7 @@ fn vested_transfer_works() { // Account 4 has fully vested, assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(0)); // and after unlocking its schedules are removed from storage. - vest_and_assert_no_vesting::(4); + vest_and_assert_no_vesting::(4, LockType::Participation(0)); }); } @@ -377,7 +378,7 @@ fn vested_transfer_correctly_fails() { ED, // Vesting over 20 blocks 10, ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![user2_vesting_schedule]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![user2_vesting_schedule]); // Fails due to too low transfer amount. let new_vesting_schedule_too_low = VestingInfo::new(::MinVestedTransfer::get() - 1, 64, 10); @@ -404,7 +405,7 @@ fn vested_transfer_correctly_fails() { assert_eq!(user2_free_balance, Balances::free_balance(&2)); assert_eq!(user4_free_balance, Balances::free_balance(&4)); // Account 4 has no schedules. - vest_and_assert_no_vesting::(4); + vest_and_assert_no_vesting::(4, LockType::Participation(0)); }); } @@ -442,7 +443,7 @@ fn vested_transfer_allows_max_schedules() { System::set_block_number(::MinVestedTransfer::get() + sched.starting_block()); assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(0)); // and after unlocking its schedules are removed from storage. - vest_and_assert_no_vesting::(4); + vest_and_assert_no_vesting::(4, LockType::Participation(0)); }); } @@ -454,7 +455,7 @@ fn force_vested_transfer_works() { assert_eq!(user3_free_balance, ED * 30); assert_eq!(user4_free_balance, ED * 40); // Account 4 should not have any vesting yet. - assert_eq!(Vesting::vesting(&4), None); + assert_eq!(Vesting::vesting(&4, LockType::Participation(0)), None); // Make the schedule for the new transfer. let new_vesting_schedule = VestingInfo::new( ED * 5, @@ -474,8 +475,8 @@ fn force_vested_transfer_works() { LockType::Participation(0) )); // Now account 4 should have vesting. - assert_eq!(Vesting::vesting(&4).unwrap()[0], new_vesting_schedule); - assert_eq!(Vesting::vesting(&4).unwrap().len(), 1); + assert_eq!(Vesting::vesting(&4, LockType::Participation(0)).unwrap()[0], new_vesting_schedule); + assert_eq!(Vesting::vesting(&4, LockType::Participation(0)).unwrap().len(), 1); // Ensure the transfer happened correctly. let user3_free_balance_updated = Balances::free_balance(&3); assert_eq!(user3_free_balance_updated, ED * 25); @@ -496,7 +497,7 @@ fn force_vested_transfer_works() { // Account 4 has fully vested, assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(0)); // and after unlocking its schedules are removed from storage. - vest_and_assert_no_vesting::(4); + vest_and_assert_no_vesting::(4, LockType::Participation(0)); }); } @@ -513,7 +514,7 @@ fn force_vested_transfer_correctly_fails() { ED, // Vesting over 20 blocks 10, ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![user2_vesting_schedule]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![user2_vesting_schedule]); // Too low transfer amount. let new_vesting_schedule_too_low = VestingInfo::new(::MinVestedTransfer::get() - 1, 64, 10); @@ -552,7 +553,7 @@ fn force_vested_transfer_correctly_fails() { assert_eq!(user2_free_balance, Balances::free_balance(&2)); assert_eq!(user4_free_balance, Balances::free_balance(&4)); // Account 4 has no schedules. - vest_and_assert_no_vesting::(4); + vest_and_assert_no_vesting::(4, LockType::Participation(0)); }); } @@ -596,7 +597,7 @@ fn force_vested_transfer_allows_max_schedules() { System::set_block_number(::MinVestedTransfer::get() + 10); assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(0)); // and after unlocking its schedules are removed from storage. - vest_and_assert_no_vesting::(4); + vest_and_assert_no_vesting::(4, LockType::Participation(0)); }); } @@ -609,12 +610,12 @@ fn merge_schedules_that_have_not_started() { ED, // Vest over 20 blocks. 10, ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0]); assert_eq!(Balances::balance(&2), ED); // Add a schedule that is identical to the one that already exists. assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched0, LockType::Participation(0))); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched0]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0, sched0]); assert_eq!(Balances::balance(&2), ED); assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1, LockType::Participation(0))); @@ -625,7 +626,7 @@ fn merge_schedules_that_have_not_started() { sched0.per_block() * 2, 10, // Starts at the block the schedules are merged/ ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched1]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched1]); assert_eq!(Balances::balance(&2), ED); }); @@ -641,7 +642,7 @@ fn merge_ongoing_schedules() { ED, // Vest over 20 blocks. 10, ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0]); let sched1 = VestingInfo::new( ED * 10, @@ -649,7 +650,7 @@ fn merge_ongoing_schedules() { sched0.starting_block() + 5, // Start at block 15. ); assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1, LockType::Participation(0))); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0, sched1]); // Got to half way through the second schedule where both schedules are actively vesting. let cur_block = 20; @@ -678,11 +679,11 @@ fn merge_ongoing_schedules() { let sched2_per_block = sched2_locked / sched2_duration; let sched2 = VestingInfo::new(sched2_locked, sched2_per_block, cur_block); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched2]); // And just to double check, we assert the new merged schedule we be cleaned up as expected. System::set_block_number(30); - vest_and_assert_no_vesting::(2); + vest_and_assert_no_vesting::(2, LockType::Participation(0)); }); } @@ -708,7 +709,7 @@ fn merging_shifts_other_schedules_index() { ); // Account 3 starts out with no schedules, - assert_eq!(Vesting::vesting(&3), None); + assert_eq!(Vesting::vesting(&3, LockType::Participation(0)), None); // and some free balance. let free_balance = Balances::balance(&3); @@ -721,7 +722,7 @@ fn merging_shifts_other_schedules_index() { assert_ok!(Vesting::vested_transfer(Some(4).into(), 3, sched2, LockType::Participation(0))); // With no schedules vested or merged they are in the order they are created - assert_eq!(Vesting::vesting(&3).unwrap(), vec![sched0, sched1, sched2]); + assert_eq!(Vesting::vesting(&3, LockType::Participation(0)).unwrap(), vec![sched0, sched1, sched2]); // and the free balance has not changed. assert_eq!(free_balance, Balances::balance(&3)); @@ -739,7 +740,7 @@ fn merging_shifts_other_schedules_index() { let sched3 = VestingInfo::new(sched3_locked, sched3_per_block, sched3_start); // The not touched schedule moves left and the new merged schedule is appended. - assert_eq!(Vesting::vesting(&3).unwrap(), vec![sched1, sched3]); + assert_eq!(Vesting::vesting(&3, LockType::Participation(0)).unwrap(), vec![sched1, sched3]); // The usable balance hasn't changed since none of the schedules have started. assert_eq!(Balances::balance(&3), free_balance); }); @@ -756,7 +757,7 @@ fn merge_ongoing_and_yet_to_be_started_schedules() { ED, // Vesting over 20 blocks 10, ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0]); // Fast forward to half way through the life of sched1. let mut cur_block = (sched0.starting_block() + sched0.ending_block_as_balance::()) / 2; @@ -804,7 +805,7 @@ fn merge_ongoing_and_yet_to_be_started_schedules() { let sched2_per_block = sched2_locked / sched2_duration; let sched2 = VestingInfo::new(sched2_locked, sched2_per_block, sched2_start); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched2]); }); } @@ -819,7 +820,7 @@ fn merge_finished_and_ongoing_schedules() { ED, // Vesting over 20 blocks. 10, ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0]); let sched1 = VestingInfo::new( ED * 40, @@ -838,7 +839,7 @@ fn merge_finished_and_ongoing_schedules() { assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched2, LockType::Participation(0))); // The schedules are in expected order prior to merging. - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0, sched1, sched2]); // Fast forward to sched0's end block. let cur_block = sched0.ending_block_as_balance::(); @@ -853,7 +854,7 @@ fn merge_finished_and_ongoing_schedules() { // sched2 is now the first, since sched0 & sched1 get filtered out while "merging". // sched1 gets treated like the new merged schedule by getting pushed onto back // of the vesting schedules vec. Note: sched0 finished at the current block. - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2, sched1]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched2, sched1]); // sched0 has finished, so its funds are fully unlocked. let sched0_unlocked_now = sched0.locked(); @@ -878,7 +879,7 @@ fn merge_finishing_schedules_does_not_create_a_new_one() { ED, // 20 block duration. 10, ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0]); // Create sched1 and transfer it to account 2. let sched1 = VestingInfo::new( @@ -887,7 +888,7 @@ fn merge_finishing_schedules_does_not_create_a_new_one() { 10, ); assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched1, LockType::Participation(0))); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0, sched1]); let all_scheds_end = sched0.ending_block_as_balance::().max(sched1.ending_block_as_balance::()); @@ -903,7 +904,7 @@ fn merge_finishing_schedules_does_not_create_a_new_one() { assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1, LockType::Participation(0))); // The user no longer has any more vesting schedules because they both ended at the // block they where merged, - assert!(!>::contains_key(&2)); + assert!(!>::contains_key(&2, LockType::Participation(0))); // and their usable balance has increased by the total amount locked in the merged // schedules. assert_eq!(Balances::balance(&2), ED + sched0.locked() + sched1.locked()); @@ -919,7 +920,7 @@ fn merge_finished_and_yet_to_be_started_schedules() { ED, // 20 block duration. 10, // Ends at block 30 ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0]); let sched1 = VestingInfo::new( ED * 30, @@ -927,7 +928,7 @@ fn merge_finished_and_yet_to_be_started_schedules() { 35, ); assert_ok!(Vesting::vested_transfer(Some(13).into(), 2, sched1, LockType::Participation(0))); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0, sched1]); let sched2 = VestingInfo::new( ED * 40, @@ -936,7 +937,7 @@ fn merge_finished_and_yet_to_be_started_schedules() { ); // Add a 3rd schedule to demonstrate how sched1 shifts. assert_ok!(Vesting::vested_transfer(Some(13).into(), 2, sched2, LockType::Participation(0))); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched1, sched2]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0, sched1, sched2]); assert_eq!( Vesting::vesting_balance(&2, LockType::Participation(0)).unwrap(), @@ -960,7 +961,7 @@ fn merge_finished_and_yet_to_be_started_schedules() { // sched0 is removed since it finished, and sched1 is removed and then pushed on the back // because it is treated as the merged schedule - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched2, sched1]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched2, sched1]); // The usable balance is updated because merging fully unlocked sched0. assert_eq!(Balances::balance(&2), ED + sched0.locked()); @@ -976,7 +977,7 @@ fn merge_schedules_throws_proper_errors() { ED, // 20 block duration. 10, ); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0]); // Account 2 only has 1 vesting schedule. assert_noop!( @@ -985,7 +986,7 @@ fn merge_schedules_throws_proper_errors() { ); // Account 4 has 0 vesting schedules. - assert_eq!(Vesting::vesting(&4), None); + assert_eq!(Vesting::vesting(&4, LockType::Participation(0)), None); assert_noop!( Vesting::merge_schedules(Some(4).into(), 0, 1, LockType::Participation(0)), Error::::NotVesting @@ -993,7 +994,7 @@ fn merge_schedules_throws_proper_errors() { // There are enough schedules to merge but an index is non-existent. assert_ok!(Vesting::vested_transfer(Some(3).into(), 2, sched0, LockType::Participation(0))); - assert_eq!(Vesting::vesting(&2).unwrap(), vec![sched0, sched0]); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0, sched0]); assert_noop!( Vesting::merge_schedules(Some(2).into(), 0, 2, LockType::Participation(0)), Error::::ScheduleIndexOutOfBounds @@ -1122,7 +1123,13 @@ fn set_release_schedule() { // Set release schedule to release the locked amount, starting from now, one ED per block. let user3_vesting_schedule = VestingInfo::new(user_3_on_hold_balance, ED, System::block_number()); - assert_ok!(Vesting::release_schedule(Some(3).into(), user3_vesting_schedule)); + assert_ok!(Vesting::set_release_schedule( + &3, + user3_vesting_schedule.locked, + user3_vesting_schedule.per_block(), + user3_vesting_schedule.starting_block, + LockType::Participation(0) + )); assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(15 * ED)); // 1 ED can be "released", we need to call vest to release it. @@ -1143,7 +1150,7 @@ fn set_release_schedule() { System::set_block_number(16); assert_eq!(System::block_number(), 16); assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(0)); - vest_and_assert_no_vesting::(3); + vest_and_assert_no_vesting::(3, LockType::Participation(0)); let user_3_free_balance = Balances::free_balance(&3); assert_eq!(user_3_free_balance, 30 * ED); }); @@ -1175,14 +1182,90 @@ fn cannot_release_different_reason() { // Set release schedule to release the locked amount, starting from now, one ED per block. let user3_vesting_schedule = VestingInfo::new(user_3_on_hold_balance, ED, System::block_number()); - assert_ok!(Vesting::release_schedule(Some(3).into(), user3_vesting_schedule)); + assert_ok!(Vesting::set_release_schedule( + &3, + user3_vesting_schedule.locked, + user3_vesting_schedule.per_block(), + user3_vesting_schedule.starting_block, + LockType::Participation(0) + )); assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(15 * ED)); // 1 ED can be "released", we need to call vest to release it. System::set_block_number(2); assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(14 * ED)); - assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(1))); + assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(0))); + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 16 * ED); + }); +} + +// TODO +#[test] +fn multile_holds_release_schedule() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + assert_eq!(System::block_number(), 1); + // Initial Status + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 30 * ED); // 7680 ED + let user_3_reserved_balance = Balances::reserved_balance(&3); + assert_eq!(user_3_reserved_balance, 0); + let user_3_on_hold_balance = Balances::balance_on_hold(&LockType::Participation(0), &3); + assert_eq!(user_3_on_hold_balance, 0); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), None); + + // Hold 15 ED + assert_ok!(Balances::hold(&LockType::Participation(0), &3, 15 * ED)); let user_3_free_balance = Balances::free_balance(&3); assert_eq!(user_3_free_balance, 15 * ED); + let user_3_on_hold_balance = Balances::balance_on_hold(&LockType::Participation(0), &3); + assert_eq!(user_3_on_hold_balance, 15 * ED); + let user_3_reserved_balance = Balances::reserved_balance(&3); + assert_eq!(user_3_reserved_balance, 15 * ED); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), None); + + // Set release schedule to release the locked amount, starting from now, one ED per block. + let user3_vesting_schedule = VestingInfo::new(user_3_on_hold_balance, ED, 1); + assert_ok!(Vesting::set_release_schedule( + &3, + user3_vesting_schedule.locked, + user3_vesting_schedule.per_block, + user3_vesting_schedule.starting_block, + LockType::Participation(0) + )); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(15 * ED)); + + // Hold 7 ED more + assert_ok!(Balances::hold(&LockType::Participation(1), &3, 7 * ED)); + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 8 * ED); + let user_3_on_hold_balance = Balances::balance_on_hold(&LockType::Participation(1), &3); + assert_eq!(user_3_on_hold_balance, 7 * ED); + let user_3_reserved_balance = Balances::reserved_balance(&3); + assert_eq!(user_3_reserved_balance, 22 * ED); + + // Set release schedule to release the locked amount, starting from now, one ED per block. + let user3_vesting_schedule = VestingInfo::new(user_3_on_hold_balance, ED, System::block_number() + 21); + assert_ok!(Vesting::set_release_schedule( + &3, + user3_vesting_schedule.locked, + user3_vesting_schedule.per_block, + user3_vesting_schedule.starting_block, + LockType::Participation(1) + )); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(15 * ED)); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(1)), Some(7 * ED)); + + System::set_block_number(16); + assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(0))); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), None); + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 23 * ED); + + System::set_block_number(100); + assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(1))); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(1)), None); + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 30 * ED); }); } From 0f503c6cc3e4f3cb7fe2fe2eeb7b7de55339cd9e Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Thu, 20 Jul 2023 18:31:16 +0200 Subject: [PATCH 24/80] doc: add TODO about different reasons --- polimec-skeleton/pallets/linear-release/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/polimec-skeleton/pallets/linear-release/src/lib.rs b/polimec-skeleton/pallets/linear-release/src/lib.rs index cdc187f07..7725aa3aa 100644 --- a/polimec-skeleton/pallets/linear-release/src/lib.rs +++ b/polimec-skeleton/pallets/linear-release/src/lib.rs @@ -364,6 +364,7 @@ pub mod pallet { }; let schedule1_index = schedule1_index as usize; let schedule2_index = schedule2_index as usize; + // TODO: Add the different reasons check. let schedules = Self::vesting(&who, reason).ok_or(Error::::NotVesting)?; let merge_action = VestingAction::Merge { index1: schedule1_index, index2: schedule2_index }; From e7261980b19b77632bd810f1c0aa8a659a3dc592 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 12:01:24 +0200 Subject: [PATCH 25/80] test: add a new account --- polimec-skeleton/pallets/linear-release/src/mock.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/polimec-skeleton/pallets/linear-release/src/mock.rs b/polimec-skeleton/pallets/linear-release/src/mock.rs index 397b07448..30124247c 100644 --- a/polimec-skeleton/pallets/linear-release/src/mock.rs +++ b/polimec-skeleton/pallets/linear-release/src/mock.rs @@ -112,6 +112,7 @@ impl ExtBuilder { (4, 40 * self.existential_deposit), (12, 10 * self.existential_deposit), (13, 9999 * self.existential_deposit), + (14, 2000 * self.existential_deposit), ], } .assimilate_storage(&mut t) From 2facc32d0eb971628aa52aeec2cc675bac0566ea Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 12:01:52 +0200 Subject: [PATCH 26/80] test: check what happens when merging different locks --- .../pallets/linear-release/src/tests.rs | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/polimec-skeleton/pallets/linear-release/src/tests.rs b/polimec-skeleton/pallets/linear-release/src/tests.rs index a57c751fb..3703b0a01 100644 --- a/polimec-skeleton/pallets/linear-release/src/tests.rs +++ b/polimec-skeleton/pallets/linear-release/src/tests.rs @@ -1269,3 +1269,37 @@ fn multile_holds_release_schedule() { assert_eq!(user_3_free_balance, 30 * ED); }); } + +#[test] +fn merge_schedules_different_reason() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + // Account 2 should already have a vesting schedule. + let sched0 = VestingInfo::new( + ED * 20, + ED, // Vest over 20 blocks. + 10, + ); + assert_eq!(Balances::balance(&2), ED); + assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0]); + + + // Add a schedule that is identical to the one that already exists. + assert_ok!(Vesting::vested_transfer(Some(14).into(), 2, sched0, LockType::Participation(1))); + assert_ok!(Vesting::vested_transfer(Some(14).into(), 2, sched0, LockType::Participation(1))); + assert_eq!(Vesting::vesting(&2, LockType::Participation(1)).unwrap(), vec![sched0, sched0]); + assert_eq!(Balances::balance(&2), ED); + assert_noop!(Vesting::merge_schedules(Some(2).into(), 0, 1, LockType::Participation(0)), Error::::ScheduleIndexOutOfBounds); + assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1, LockType::Participation(1))); + + // Since we merged identical schedules, the new schedule finishes at the same + // time as the original, just with double the amount. + let sched1 = VestingInfo::new( + sched0.locked() * 2, + sched0.per_block() * 2, + 10, // Starts at the block the schedules are merged/ + ); + assert_eq!(Vesting::vesting(&2, LockType::Participation(1)).unwrap(), vec![sched1]); + + assert_eq!(Balances::balance(&2), ED); + }); +} \ No newline at end of file From b32ff48241024455740e4602d233e4536eb2ffe6 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:34:43 +0200 Subject: [PATCH 27/80] chore: move the imports to the main lib.rs --- polimec-skeleton/pallets/linear-release/src/impls.rs | 2 -- polimec-skeleton/pallets/linear-release/src/lib.rs | 6 +++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/impls.rs b/polimec-skeleton/pallets/linear-release/src/impls.rs index bad01916f..a18d8fb91 100644 --- a/polimec-skeleton/pallets/linear-release/src/impls.rs +++ b/polimec-skeleton/pallets/linear-release/src/impls.rs @@ -1,5 +1,3 @@ -use frame_support::traits::tokens::Precision; - use super::*; impl Pallet { diff --git a/polimec-skeleton/pallets/linear-release/src/lib.rs b/polimec-skeleton/pallets/linear-release/src/lib.rs index 7725aa3aa..bb2af559a 100644 --- a/polimec-skeleton/pallets/linear-release/src/lib.rs +++ b/polimec-skeleton/pallets/linear-release/src/lib.rs @@ -33,7 +33,11 @@ use frame_support::{ dispatch::DispatchResult, ensure, pallet_prelude::*, - traits::{fungible::*, tokens::Balance, Get, WithdrawReasons}, + traits::{ + fungible::*, + tokens::{Balance, Precision}, + Get, WithdrawReasons, + }, }; use frame_system::{pallet_prelude::*, WeightInfo}; From 7ca926252a891cb02730daf41d4660ce11d53daf Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:35:20 +0200 Subject: [PATCH 28/80] feat: remove unused constraint --- polimec-skeleton/pallets/linear-release/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polimec-skeleton/pallets/linear-release/src/lib.rs b/polimec-skeleton/pallets/linear-release/src/lib.rs index bb2af559a..f57a65ee9 100644 --- a/polimec-skeleton/pallets/linear-release/src/lib.rs +++ b/polimec-skeleton/pallets/linear-release/src/lib.rs @@ -124,7 +124,7 @@ pub mod pallet { /// The overarching event type. type RuntimeEvent: From> + IsType<::RuntimeEvent>; - type Balance: Balance + From + MaybeSerializeDeserialize; + type Balance: Balance + MaybeSerializeDeserialize; // TODO: Still I dont-like this. I want to be able to use the `LockType` from the pallet_balances, without coupling it. type Reason: Parameter + Copy + MaybeSerializeDeserialize; From 0bd5d85296be7c500ed4675f13278c2029e3fb6c Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:36:03 +0200 Subject: [PATCH 29/80] feat: add VestingTransferred event --- .../pallets/linear-release/src/impls.rs | 14 +++++++++++--- polimec-skeleton/pallets/linear-release/src/lib.rs | 14 ++++++++++++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/impls.rs b/polimec-skeleton/pallets/linear-release/src/impls.rs index a18d8fb91..b21431814 100644 --- a/polimec-skeleton/pallets/linear-release/src/impls.rs +++ b/polimec-skeleton/pallets/linear-release/src/impls.rs @@ -60,7 +60,13 @@ impl Pallet { }; // Check we can add to this account prior to any storage writes. - Self::can_add_release_schedule(&target, schedule.locked(), schedule.per_block(), schedule.starting_block(), reason)?; + Self::can_add_release_schedule( + &target, + schedule.locked(), + schedule.per_block(), + schedule.starting_block(), + reason, + )?; let amount_transferred = T::Currency::transfer_and_hold( &reason, @@ -72,6 +78,8 @@ impl Pallet { frame_support::traits::tokens::Fortitude::Polite, )?; + Self::deposit_event(Event::::VestingTransferred { to: target.clone(), amount: amount_transferred }); + // We can't let this fail because the currency transfer has already happened. let res = Self::add_release_schedule( &target, @@ -279,7 +287,7 @@ impl ReleaseSchedule, ReasonOf> for Pallet { locked: BalanceOf, per_block: BalanceOf, starting_block: BlockNumberFor, - reason: ReasonOf + reason: ReasonOf, ) -> DispatchResult { // Check for `per_block` or `locked` of 0. if !VestingInfo::new(locked, per_block, starting_block).is_valid() { @@ -299,7 +307,7 @@ impl ReleaseSchedule, ReasonOf> for Pallet { locked: >::Balance, per_block: >::Balance, starting_block: Self::Moment, - reason: ReasonOf + reason: ReasonOf, ) -> DispatchResult { if locked.is_zero() { return Ok(()); diff --git a/polimec-skeleton/pallets/linear-release/src/lib.rs b/polimec-skeleton/pallets/linear-release/src/lib.rs index f57a65ee9..ceb9645b3 100644 --- a/polimec-skeleton/pallets/linear-release/src/lib.rs +++ b/polimec-skeleton/pallets/linear-release/src/lib.rs @@ -217,9 +217,19 @@ pub mod pallet { pub enum Event { /// The amount vested has been updated. This could indicate a change in funds available. /// The balance given is the amount which is left unvested (and thus locked). - VestingUpdated { account: T::AccountId, unvested: BalanceOf }, + VestingUpdated { + account: T::AccountId, + unvested: BalanceOf, + }, /// An \[account\] has become fully vested. - VestingCompleted { account: T::AccountId }, + VestingCompleted { + account: T::AccountId, + }, + // An \[account\] has reveived a vested transfer of \[amount\]. + VestingTransferred { + to: T::AccountId, + amount: BalanceOf, + }, } /// Error for the vesting pallet. From 927fd91b7fff682033597416929a569d3633bd16 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Wed, 12 Jul 2023 16:05:20 +0200 Subject: [PATCH 30/80] chore: remove unused file --- shell.nix | 35 ----------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 shell.nix diff --git a/shell.nix b/shell.nix deleted file mode 100644 index c08005c16..000000000 --- a/shell.nix +++ /dev/null @@ -1,35 +0,0 @@ -let - mozillaOverlay = - import (builtins.fetchGit { - url = "https://github.com/mozilla/nixpkgs-mozilla.git"; - rev = "57c8084c7ef41366993909c20491e359bbb90f54"; - }); - pinned = builtins.fetchGit { - # Descriptive name to make the store path easier to identify - url = "https://github.com/nixos/nixpkgs/"; - # Commit hash for nixos-unstable as of 2020-04-26 - # `git ls-remote https://github.com/nixos/nixpkgs nixos-unstable` - ref = "refs/heads/nixos-unstable"; - rev = "1fe6ed37fd9beb92afe90671c0c2a662a03463dd"; - }; - nixpkgs = import pinned { overlays = [ mozillaOverlay ]; }; - toolchain = with nixpkgs; (rustChannelOf { date = "2021-09-14"; channel = "nightly"; }); - rust-wasm = toolchain.rust.override { - targets = [ "wasm32-unknown-unknown" ]; - }; -in -with nixpkgs; pkgs.mkShell { - buildInputs = [ - clang - pkg-config - rust-wasm - ] ++ stdenv.lib.optionals stdenv.isDarwin [ - darwin.apple_sdk.frameworks.Security - ]; - - LIBCLANG_PATH = "${llvmPackages.libclang}/lib"; - PROTOC = "${protobuf}/bin/protoc"; - RUST_SRC_PATH = "${toolchain.rust-src}/lib/rustlib/src/rust/library/"; - ROCKSDB_LIB_DIR = "${rocksdb}/lib"; - -} From 485cc436035fa4285995e9ac052d0f29700da735 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Wed, 12 Jul 2023 22:48:10 +0200 Subject: [PATCH 31/80] wip --- Cargo.lock | 563 --- Cargo.toml | 11 +- pallets/asset-registry/Cargo.toml | 70 - pallets/asset-registry/src/benchmarking.rs | 69 - pallets/asset-registry/src/lib.rs | 171 - pallets/asset-registry/src/mock.rs | 124 - pallets/asset-registry/src/tests.rs | 76 - pallets/asset-registry/src/weights.rs | 76 - pallets/credentials/Cargo.toml | 58 - pallets/credentials/src/benchmarking.rs | 1 - pallets/credentials/src/lib.rs | 279 -- pallets/credentials/src/mock.rs | 129 - pallets/credentials/src/tests.rs | 156 - pallets/funding/Cargo.toml | 2 - pallets/funding/src/lib.rs | 3 - pallets/funding/src/mock.rs | 19 - pallets/parachain-staking/Cargo.toml | 70 - pallets/parachain-staking/src/api.rs | 90 - pallets/parachain-staking/src/benchmarking.rs | 638 --- .../parachain-staking/src/default_weights.rs | 843 ---- pallets/parachain-staking/src/inflation.rs | 384 -- pallets/parachain-staking/src/lib.rs | 2573 ---------- pallets/parachain-staking/src/migration.rs | 17 - pallets/parachain-staking/src/mock.rs | 421 -- pallets/parachain-staking/src/set.rs | 553 --- pallets/parachain-staking/src/tests.rs | 4347 ----------------- pallets/parachain-staking/src/types.rs | 321 -- pallets/sandbox/Cargo.toml | 2 - pallets/sandbox/src/mock.rs | 19 - pallets/sandbox/src/tests.rs | 6 - runtime-api/credentials/Cargo.toml | 35 - runtime-api/staking/Cargo.toml | 23 - runtime-api/staking/src/lib.rs | 46 - runtimes/base/Cargo.toml | 8 +- runtimes/base/src/currency.rs | 14 + runtimes/base/src/lib.rs | 176 +- runtimes/common/Cargo.toml | 90 - runtimes/common/src/constants.rs | 358 -- runtimes/common/src/fees.rs | 279 -- runtimes/common/src/lib.rs | 184 - runtimes/common/src/xcm_config.rs | 160 - runtimes/standalone/Cargo.toml | 10 +- runtimes/testnet/Cargo.toml | 12 +- rust-toolchain.toml | 2 +- 44 files changed, 151 insertions(+), 13337 deletions(-) delete mode 100644 pallets/asset-registry/Cargo.toml delete mode 100644 pallets/asset-registry/src/benchmarking.rs delete mode 100644 pallets/asset-registry/src/lib.rs delete mode 100644 pallets/asset-registry/src/mock.rs delete mode 100644 pallets/asset-registry/src/tests.rs delete mode 100644 pallets/asset-registry/src/weights.rs delete mode 100644 pallets/credentials/Cargo.toml delete mode 100644 pallets/credentials/src/benchmarking.rs delete mode 100644 pallets/credentials/src/lib.rs delete mode 100644 pallets/credentials/src/mock.rs delete mode 100644 pallets/credentials/src/tests.rs delete mode 100644 pallets/parachain-staking/Cargo.toml delete mode 100644 pallets/parachain-staking/src/api.rs delete mode 100644 pallets/parachain-staking/src/benchmarking.rs delete mode 100644 pallets/parachain-staking/src/default_weights.rs delete mode 100644 pallets/parachain-staking/src/inflation.rs delete mode 100644 pallets/parachain-staking/src/lib.rs delete mode 100644 pallets/parachain-staking/src/migration.rs delete mode 100644 pallets/parachain-staking/src/mock.rs delete mode 100644 pallets/parachain-staking/src/set.rs delete mode 100644 pallets/parachain-staking/src/tests.rs delete mode 100644 pallets/parachain-staking/src/types.rs delete mode 100644 runtime-api/credentials/Cargo.toml delete mode 100644 runtime-api/staking/Cargo.toml delete mode 100644 runtime-api/staking/src/lib.rs create mode 100644 runtimes/base/src/currency.rs delete mode 100644 runtimes/common/Cargo.toml delete mode 100644 runtimes/common/src/constants.rs delete mode 100644 runtimes/common/src/fees.rs delete mode 100644 runtimes/common/src/lib.rs delete mode 100644 runtimes/common/src/xcm_config.rs diff --git a/Cargo.lock b/Cargo.lock index b66c71d01..cb0864f2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -450,26 +450,6 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" -[[package]] -name = "attestation" -version = "1.11.0-dev" -source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" -dependencies = [ - "ctype", - "frame-benchmarking", - "frame-support", - "frame-system", - "kilt-support", - "log", - "pallet-balances", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - [[package]] name = "atty" version = "0.2.14" @@ -2255,58 +2235,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "dip-provider-runtime-template" -version = "1.11.0-dev" -source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" -dependencies = [ - "cumulus-pallet-aura-ext", - "cumulus-pallet-dmp-queue", - "cumulus-pallet-parachain-system", - "cumulus-pallet-xcm", - "cumulus-pallet-xcmp-queue", - "cumulus-primitives-core", - "cumulus-primitives-timestamp", - "cumulus-primitives-utility", - "did", - "dip-support", - "frame-executive", - "frame-support", - "frame-system", - "frame-system-rpc-runtime-api", - "kilt-runtime-api-dip-provider", - "pallet-aura", - "pallet-authorship", - "pallet-balances", - "pallet-collator-selection", - "pallet-dip-provider", - "pallet-session", - "pallet-sudo", - "pallet-timestamp", - "pallet-transaction-payment", - "pallet-transaction-payment-rpc-runtime-api", - "pallet-xcm", - "parachain-info", - "parity-scale-codec", - "runtime-common 1.11.0-dev", - "scale-info", - "sp-api", - "sp-block-builder", - "sp-consensus-aura", - "sp-core", - "sp-inherents", - "sp-offchain", - "sp-runtime", - "sp-session", - "sp-std", - "sp-transaction-pool", - "sp-version", - "substrate-wasm-builder", - "xcm", - "xcm-builder", - "xcm-executor", -] - [[package]] name = "dip-support" version = "1.11.0-dev" @@ -3747,46 +3675,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "integration-tests" -version = "0.1.0" -dependencies = [ - "cumulus-pallet-xcm", - "cumulus-primitives-core", - "did", - "dip-provider-runtime-template", - "dip-support", - "frame-support", - "frame-system", - "kilt-dip-support", - "kilt-support", - "pallet-assets", - "pallet-balances", - "pallet-did-lookup", - "pallet-xcm", - "parachain-info", - "parity-scale-codec", - "penpal-runtime", - "polimec-parachain-runtime", - "polkadot-core-primitives", - "polkadot-parachain", - "polkadot-runtime", - "polkadot-runtime-parachains", - "runtime-common 0.1.0", - "runtime-common 1.11.0-dev", - "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", - "statemint-runtime", - "substrate-wasm-builder", - "xcm", - "xcm-builder", - "xcm-emulator", - "xcm-executor", -] - [[package]] name = "interceptor" version = "0.8.2" @@ -4031,22 +3919,6 @@ dependencies = [ "cpufeatures", ] -[[package]] -name = "kilt-asset-dids" -version = "1.11.0-dev" -source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" -dependencies = [ - "base58", - "frame-support", - "hex", - "hex-literal", - "log", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-std", -] - [[package]] name = "kilt-dip-support" version = "1.11.0-dev" @@ -4064,36 +3936,6 @@ dependencies = [ "sp-trie", ] -[[package]] -name = "kilt-runtime-api-dip-provider" -version = "1.11.0-dev" -source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" -dependencies = [ - "parity-scale-codec", - "sp-api", -] - -[[package]] -name = "kilt-runtime-api-staking" -version = "0.1.0" -dependencies = [ - "parity-scale-codec", - "scale-info", - "sp-api", - "sp-runtime", -] - -[[package]] -name = "kilt-runtime-api-staking" -version = "1.11.0-dev" -source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" -dependencies = [ - "parity-scale-codec", - "scale-info", - "sp-api", - "sp-runtime", -] - [[package]] name = "kilt-support" version = "1.11.0-dev" @@ -5643,37 +5485,6 @@ dependencies = [ "libm 0.1.4", ] -[[package]] -name = "pallet-asset-registry" -version = "0.0.1" -dependencies = [ - "cumulus-pallet-dmp-queue", - "cumulus-pallet-xcmp-queue", - "cumulus-primitives-core", - "frame-benchmarking", - "frame-support", - "frame-system", - "pallet-assets", - "pallet-balances", - "pallet-xcm", - "parachain-info", - "parachains-common", - "parity-scale-codec", - "polkadot-core-primitives", - "polkadot-parachain", - "polkadot-runtime-parachains", - "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", - "xcm", - "xcm-builder", - "xcm-executor", - "xcm-primitives", - "xcm-simulator", -] - [[package]] name = "pallet-asset-tx-payment" version = "4.0.0-dev" @@ -5945,23 +5756,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-credentials" -version = "0.1.0" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "pallet-balances", - "parity-scale-codec", - "polimec-traits", - "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-democracy" version = "4.0.0-dev" @@ -6019,20 +5813,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-dip-provider" -version = "1.11.0-dev" -source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" -dependencies = [ - "dip-support", - "frame-support", - "frame-system", - "parity-scale-codec", - "scale-info", - "sp-std", - "xcm", -] - [[package]] name = "pallet-election-provider-multi-phase" version = "4.0.0-dev" @@ -6114,7 +5894,6 @@ dependencies = [ "frame-system", "pallet-assets", "pallet-balances", - "pallet-credentials", "pallet-insecure-randomness-collective-flip", "parity-scale-codec", "polimec-traits", @@ -6464,7 +6243,6 @@ dependencies = [ "frame-system", "pallet-assets", "pallet-balances", - "pallet-credentials", "pallet-funding", "pallet-insecure-randomness-collective-flip", "parachains-common", @@ -6728,21 +6506,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-uniques" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "log", - "parity-scale-codec", - "scale-info", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-utility" version = "4.0.0-dev" @@ -6774,20 +6537,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-web3-names" -version = "1.11.0-dev" -source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" -dependencies = [ - "frame-support", - "frame-system", - "kilt-support", - "parity-scale-codec", - "scale-info", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-whitelist" version = "4.0.0-dev" @@ -6855,53 +6604,6 @@ dependencies = [ "scale-info", ] -[[package]] -name = "parachain-staking" -version = "1.9.0-dev" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "kilt-runtime-api-staking 0.1.0", - "log", - "pallet-aura", - "pallet-authorship", - "pallet-balances", - "pallet-session", - "pallet-timestamp", - "parity-scale-codec", - "scale-info", - "serde", - "sp-consensus-aura", - "sp-core", - "sp-io", - "sp-runtime", - "sp-staking", - "sp-std", -] - -[[package]] -name = "parachain-staking" -version = "1.11.0-dev" -source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "kilt-runtime-api-staking 1.11.0-dev", - "kilt-support", - "log", - "pallet-authorship", - "pallet-balances", - "pallet-session", - "parity-scale-codec", - "scale-info", - "serde", - "sp-runtime", - "sp-staking", - "sp-std", -] - [[package]] name = "parachains-common" version = "1.0.0" @@ -7090,65 +6792,6 @@ dependencies = [ "base64ct", ] -[[package]] -name = "penpal-runtime" -version = "0.9.27" -dependencies = [ - "cumulus-pallet-aura-ext", - "cumulus-pallet-dmp-queue", - "cumulus-pallet-parachain-system", - "cumulus-pallet-session-benchmarking", - "cumulus-pallet-xcm", - "cumulus-pallet-xcmp-queue", - "cumulus-primitives-core", - "cumulus-primitives-timestamp", - "cumulus-primitives-utility", - "frame-benchmarking", - "frame-executive", - "frame-support", - "frame-system", - "frame-system-benchmarking", - "frame-system-rpc-runtime-api", - "frame-try-runtime", - "hex-literal", - "log", - "pallet-asset-tx-payment", - "pallet-assets", - "pallet-aura", - "pallet-authorship", - "pallet-balances", - "pallet-collator-selection", - "pallet-session", - "pallet-sudo", - "pallet-timestamp", - "pallet-transaction-payment", - "pallet-transaction-payment-rpc-runtime-api", - "pallet-xcm", - "parachain-info", - "parachains-common", - "parity-scale-codec", - "polkadot-parachain", - "polkadot-primitives", - "polkadot-runtime-common", - "scale-info", - "smallvec", - "sp-api", - "sp-block-builder", - "sp-consensus-aura", - "sp-core", - "sp-inherents", - "sp-offchain", - "sp-runtime", - "sp-session", - "sp-std", - "sp-transaction-pool", - "sp-version", - "substrate-wasm-builder", - "xcm", - "xcm-builder", - "xcm-executor", -] - [[package]] name = "percent-encoding" version = "2.2.0" @@ -7308,13 +6951,11 @@ dependencies = [ "pallet-treasury", "pallet-xcm", "parachain-info", - "parachain-staking 1.9.0-dev", "parachains-common", "parity-scale-codec", "polkadot-parachain", "polkadot-primitives", "polkadot-runtime-common", - "runtime-common 0.1.0", "scale-info", "smallvec", "sp-api", @@ -7421,14 +7062,12 @@ dependencies = [ "hex-literal", "kilt-dip-support", "log", - "pallet-asset-registry", "pallet-asset-tx-payment", "pallet-assets", "pallet-aura", "pallet-authorship", "pallet-balances", "pallet-collective", - "pallet-credentials", "pallet-democracy", "pallet-did-lookup", "pallet-dip-consumer", @@ -7447,14 +7086,12 @@ dependencies = [ "pallet-vesting", "pallet-xcm", "parachain-info", - "parachain-staking 1.9.0-dev", "parachains-common", "parity-scale-codec", "polimec-traits", "polkadot-parachain", "polkadot-primitives", "polkadot-runtime-common", - "runtime-common 0.1.0", "scale-info", "serde", "smallvec", @@ -7539,7 +7176,6 @@ dependencies = [ "pallet-authorship", "pallet-balances", "pallet-collective", - "pallet-credentials", "pallet-democracy", "pallet-funding", "pallet-grandpa", @@ -7556,7 +7192,6 @@ dependencies = [ "pallet-vesting", "parity-scale-codec", "polimec-traits", - "runtime-common 0.1.0", "scale-info", "sp-api", "sp-block-builder", @@ -9015,24 +8650,6 @@ dependencies = [ "cc", ] -[[package]] -name = "public-credentials" -version = "1.11.0-dev" -source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" -dependencies = [ - "ctype", - "frame-benchmarking", - "frame-support", - "frame-system", - "kilt-support", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - [[package]] name = "quick-error" version = "1.2.3" @@ -9550,79 +9167,6 @@ dependencies = [ "webrtc-util", ] -[[package]] -name = "runtime-common" -version = "0.1.0" -dependencies = [ - "cumulus-primitives-core", - "did", - "dip-support", - "frame-support", - "frame-system", - "log", - "pallet-authorship", - "pallet-balances", - "pallet-did-lookup", - "pallet-dip-consumer", - "pallet-dip-provider", - "pallet-membership", - "pallet-transaction-payment", - "parachain-staking 1.9.0-dev", - "parachains-common", - "parity-scale-codec", - "polkadot-parachain", - "scale-info", - "smallvec", - "sp-consensus-aura", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", - "sp-trie", - "xcm", - "xcm-builder", - "xcm-executor", -] - -[[package]] -name = "runtime-common" -version = "1.11.0-dev" -source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" -dependencies = [ - "attestation", - "ctype", - "cumulus-primitives-core", - "did", - "frame-support", - "frame-system", - "kilt-asset-dids", - "kilt-dip-support", - "kilt-support", - "log", - "pallet-authorship", - "pallet-balances", - "pallet-dip-consumer", - "pallet-dip-provider", - "pallet-membership", - "pallet-transaction-payment", - "pallet-web3-names", - "parachain-staking 1.11.0-dev", - "parity-scale-codec", - "polkadot-parachain", - "public-credentials", - "scale-info", - "smallvec", - "sp-consensus-aura", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", - "sp-trie", - "xcm", - "xcm-builder", - "xcm-executor", -] - [[package]] name = "rustc-demangle" version = "0.1.23" @@ -12066,70 +11610,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "statemint-runtime" -version = "1.0.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" -dependencies = [ - "cumulus-pallet-aura-ext", - "cumulus-pallet-dmp-queue", - "cumulus-pallet-parachain-system", - "cumulus-pallet-session-benchmarking", - "cumulus-pallet-xcm", - "cumulus-pallet-xcmp-queue", - "cumulus-primitives-core", - "cumulus-primitives-timestamp", - "cumulus-primitives-utility", - "frame-benchmarking", - "frame-executive", - "frame-support", - "frame-system", - "frame-system-benchmarking", - "frame-system-rpc-runtime-api", - "hex-literal", - "log", - "pallet-asset-tx-payment", - "pallet-assets", - "pallet-aura", - "pallet-authorship", - "pallet-balances", - "pallet-collator-selection", - "pallet-multisig", - "pallet-proxy", - "pallet-session", - "pallet-timestamp", - "pallet-transaction-payment", - "pallet-transaction-payment-rpc-runtime-api", - "pallet-uniques", - "pallet-utility", - "pallet-xcm", - "pallet-xcm-benchmarks", - "parachain-info", - "parachains-common", - "parity-scale-codec", - "polkadot-core-primitives", - "polkadot-parachain", - "polkadot-runtime-common", - "polkadot-runtime-constants", - "scale-info", - "smallvec", - "sp-api", - "sp-block-builder", - "sp-consensus-aura", - "sp-core", - "sp-inherents", - "sp-offchain", - "sp-runtime", - "sp-session", - "sp-std", - "sp-transaction-pool", - "sp-version", - "substrate-wasm-builder", - "xcm", - "xcm-builder", - "xcm-executor", -] - [[package]] name = "static_assertions" version = "1.1.0" @@ -14288,32 +13768,6 @@ dependencies = [ "xcm-executor", ] -[[package]] -name = "xcm-emulator" -version = "0.1.0" -source = "git+https://github.com/shaunxw/xcm-simulator?rev=aa13dce47596e150806dfc3af99096dae6ffc65e#aa13dce47596e150806dfc3af99096dae6ffc65e" -dependencies = [ - "cumulus-pallet-dmp-queue", - "cumulus-pallet-parachain-system", - "cumulus-pallet-xcmp-queue", - "cumulus-primitives-core", - "cumulus-primitives-parachain-inherent", - "cumulus-test-relay-sproof-builder", - "frame-support", - "frame-system", - "parachain-info", - "parity-scale-codec", - "paste", - "polkadot-primitives", - "polkadot-runtime-parachains", - "quote", - "sp-arithmetic", - "sp-io", - "sp-std", - "xcm", - "xcm-executor", -] - [[package]] name = "xcm-executor" version = "0.9.39-1" @@ -14354,23 +13808,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "xcm-simulator" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" -dependencies = [ - "frame-support", - "parity-scale-codec", - "paste", - "polkadot-core-primitives", - "polkadot-parachain", - "polkadot-runtime-parachains", - "sp-io", - "sp-std", - "xcm", - "xcm-executor", -] - [[package]] name = "yamux" version = "0.10.2" diff --git a/Cargo.toml b/Cargo.toml index b6ca4f082..ebb8ca791 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,10 @@ [workspace] -members = ["nodes/*", "pallets/*", "runtimes/*", "traits", "integration-tests"] +members = [ "nodes/*", + "pallets/*", + "runtimes/*", + "traits", + # "integration-tests" +] [workspace.package] authors = ['Polimec Foundation '] @@ -39,14 +44,10 @@ overflow-checks = true substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } # Internal pallets (with default disabled) -parachain-staking = { path = "pallets/parachain-staking", default-features = false } -pallet-credentials = { path = "pallets/credentials", default-features = false } pallet-funding = { path = "pallets/funding", default-features = false } pallet-sandbox = { path = "pallets/sandbox", default-features = false } -pallet-asset-registry = { path = "pallets/asset-registry", default-features = false } # Internal support (with default disabled) -runtime-common = { path = "runtimes/common", default-features = false } polimec-traits = { path = "traits", default-features = false } xcm-primitives = { path = "primitives/xcm", default-features = false } diff --git a/pallets/asset-registry/Cargo.toml b/pallets/asset-registry/Cargo.toml deleted file mode 100644 index bf8db0140..000000000 --- a/pallets/asset-registry/Cargo.toml +++ /dev/null @@ -1,70 +0,0 @@ -[package] -name = "pallet-asset-registry" -version = "0.0.1" -description = "Trappist pallet for XCM Asset Registry." -edition = "2021" -license = "Apache-2.0" -repository = "https://github.com/paritytech/trappist" - - -[dependencies] -scale-info = { workspace = true, features = ["derive", "serde"] } -parity-scale-codec = { workspace = true, features = [ - "derive", -] } -sp-runtime.workspace = true -sp-std.workspace = true -frame-benchmarking.workspace = true -frame-support.workspace = true -frame-system.workspace = true -pallet-assets.workspace = true -pallet-balances.workspace = true -xcm.workspace = true -xcm-primitives.workspace = true - -[dev-dependencies] -sp-core.workspace = true -sp-io.workspace = true -sp-runtime.workspace = true -xcm.workspace = true -xcm-simulator.workspace = true -xcm-executor.workspace = true -xcm-builder.workspace = true -pallet-xcm.workspace = true -polkadot-core-primitives.workspace = true -polkadot-runtime-parachains.workspace = true -polkadot-parachain.workspace = true -parachain-info.workspace = true -parachains-common.workspace = true -cumulus-pallet-dmp-queue.workspace = true -cumulus-pallet-xcmp-queue.workspace = true -cumulus-primitives-core.workspace = true - -[features] -default = ["std"] -std = [ - "parity-scale-codec/std", - "sp-runtime/std", - "sp-std/std", - "pallet-assets/std", - "pallet-balances/std", - "frame-benchmarking/std", - "frame-support/std", - "frame-system/std", - "scale-info/std", - "xcm-primitives/std", - "xcm/std", - "xcm-executor/std", - "xcm-builder/std", - "pallet-xcm/std", - "polkadot-core-primitives/std", - "polkadot-runtime-parachains/std", - "polkadot-parachain/std", - "parachain-info/std", - "parachains-common/std", - "cumulus-pallet-dmp-queue/std", - "cumulus-pallet-xcmp-queue/std", - "cumulus-primitives-core/std", -] -runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] -try-runtime = ["frame-support/try-runtime", "pallet-assets/try-runtime"] diff --git a/pallets/asset-registry/src/benchmarking.rs b/pallets/asset-registry/src/benchmarking.rs deleted file mode 100644 index d2209faa0..000000000 --- a/pallets/asset-registry/src/benchmarking.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -//! Benchmarking setup for pallet-asset-registry - -use super::*; - -#[allow(unused)] -use crate::Pallet as AssetRegistry; -use frame_benchmarking::benchmarks; -use frame_support::{assert_ok, traits::fungibles::Inspect}; -use frame_system::RawOrigin; -use xcm::opaque::latest::{ - Junction::{GeneralIndex, PalletInstance, Parachain}, - Junctions, MultiLocation, -}; - -pub const LOCAL_ASSET_ID: u32 = 10; - -benchmarks! { - where_clause { - where - T::Assets: Inspect<::AccountId, AssetId = u32>, - } - - register_reserve_asset { - let asset_multi_location = MultiLocation { - parents: 1, - interior: Junctions::X3(Parachain(Default::default()), PalletInstance(Default::default()), GeneralIndex(Default::default())) - }; - - }: _(RawOrigin::Root, LOCAL_ASSET_ID, asset_multi_location.clone()) - verify { - let read_asset_multi_location = AssetRegistry::::asset_id_multilocation(LOCAL_ASSET_ID) - .expect("error reading AssetIdMultiLocation"); - assert_eq!(read_asset_multi_location, asset_multi_location); - } - - unregister_reserve_asset { - let asset_multi_location = MultiLocation { - parents: 1, - interior: Junctions::X3(Parachain(Default::default()), PalletInstance(Default::default()), GeneralIndex(Default::default())) - }; - - assert_ok!(AssetRegistry::::register_reserve_asset(RawOrigin::Root.into(), LOCAL_ASSET_ID, asset_multi_location.clone())); - let read_asset_multi_location = AssetRegistry::::asset_id_multilocation(LOCAL_ASSET_ID) - .expect("error reading AssetIdMultiLocation"); - assert_eq!(read_asset_multi_location, asset_multi_location); - - }: _(RawOrigin::Root, LOCAL_ASSET_ID) - verify { - assert_eq!(AssetRegistry::::asset_id_multilocation(LOCAL_ASSET_ID), None); - } - - impl_benchmark_test_suite!(AssetRegistry, crate::mock::new_test_ext(), crate::mock::Test); -} diff --git a/pallets/asset-registry/src/lib.rs b/pallets/asset-registry/src/lib.rs deleted file mode 100644 index 673e2ed44..000000000 --- a/pallets/asset-registry/src/lib.rs +++ /dev/null @@ -1,171 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -#![cfg_attr(not(feature = "std"), no_std)] - -/// Edit this file to define custom logic or remove it if it is not needed. -/// Learn more about FRAME and the core library of Substrate FRAME pallets: -/// -pub use pallet::*; - -#[cfg(test)] -mod mock; -#[cfg(test)] -mod tests; - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; -pub mod weights; -pub use weights::*; - -#[frame_support::pallet(dev_mode)] -pub mod pallet { - use super::*; - use frame_support::{pallet_prelude::*, sp_runtime::traits::Zero, traits::tokens::fungibles::Inspect}; - use frame_system::pallet_prelude::*; - - use xcm::latest::{ - Junction::{GeneralIndex, PalletInstance, Parachain}, - Junctions, MultiLocation, - }; - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(_); - - type AssetIdOf = <::Assets as Inspect<::AccountId>>::AssetId; - - #[pallet::config] - pub trait Config: frame_system::Config { - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - type ReserveAssetModifierOrigin: EnsureOrigin; - type Assets: Inspect; - type WeightInfo: WeightInfo; - } - - #[pallet::storage] - #[pallet::getter(fn asset_id_multilocation)] - pub type AssetIdMultiLocation = StorageMap<_, Blake2_128Concat, AssetIdOf, MultiLocation>; - - #[pallet::storage] - #[pallet::getter(fn asset_multilocation_id)] - pub type AssetMultiLocationId = StorageMap<_, Blake2_128Concat, MultiLocation, AssetIdOf>; - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - ReserveAssetRegistered { - asset_id: AssetIdOf, - asset_multi_location: MultiLocation, - }, - ReserveAssetUnregistered { - asset_id: AssetIdOf, - asset_multi_location: MultiLocation, - }, - } - - #[pallet::error] - pub enum Error { - /// The Asset ID is already registered - AssetAlreadyRegistered, - /// The Asset ID does not exist - AssetDoesNotExist, - /// The Asset ID is not registered - AssetIsNotRegistered, - /// Invalid MultiLocation - WrongMultiLocation, - } - - #[pallet::call] - impl Pallet { - #[pallet::weight(::WeightInfo::register_reserve_asset())] - pub fn register_reserve_asset( - origin: OriginFor, asset_id: AssetIdOf, asset_multi_location: MultiLocation, - ) -> DispatchResult { - T::ReserveAssetModifierOrigin::ensure_origin(origin)?; - - // verify asset exists on pallet-assets - ensure!(Self::asset_exists(asset_id), Error::::AssetDoesNotExist); - - // verify asset is not yet registered - ensure!( - !AssetIdMultiLocation::::contains_key(asset_id), - Error::::AssetAlreadyRegistered - ); - - // verify MultiLocation is valid - let parents_multi_location_ok = { asset_multi_location.parents == 1 }; - let junctions_multi_location_ok = matches!( - asset_multi_location.interior, - Junctions::X3(Parachain(_), PalletInstance(_), GeneralIndex(_)) - ); - - ensure!( - parents_multi_location_ok && junctions_multi_location_ok, - Error::::WrongMultiLocation - ); - - // register asset - AssetIdMultiLocation::::insert(asset_id, &asset_multi_location); - AssetMultiLocationId::::insert(&asset_multi_location, asset_id); - - Self::deposit_event(Event::ReserveAssetRegistered { - asset_id, - asset_multi_location, - }); - - Ok(()) - } - - #[pallet::weight(::WeightInfo::unregister_reserve_asset())] - pub fn unregister_reserve_asset(origin: OriginFor, asset_id: AssetIdOf) -> DispatchResult { - T::ReserveAssetModifierOrigin::ensure_origin(origin)?; - - // verify asset is registered - let asset_multi_location = - AssetIdMultiLocation::::get(asset_id).ok_or(Error::::AssetIsNotRegistered)?; - - // unregister asset - AssetIdMultiLocation::::remove(asset_id); - AssetMultiLocationId::::remove(&asset_multi_location); - - Self::deposit_event(Event::ReserveAssetUnregistered { - asset_id, - asset_multi_location, - }); - Ok(()) - } - } - - impl xcm_primitives::AssetMultiLocationGetter> for Pallet { - fn get_asset_multi_location(asset_id: AssetIdOf) -> Option { - AssetIdMultiLocation::::get(asset_id) - } - - fn get_asset_id(asset_type: MultiLocation) -> Option> { - AssetMultiLocationId::::get(asset_type) - } - } - - impl Pallet { - // pallet-assets implements the fungibles::Inspect trait - // where minimum_balance(asset_id) always returns non-zero - // for existing assets, and zero for non-existing assets - fn asset_exists(asset_id: AssetIdOf) -> bool { - !T::Assets::minimum_balance(asset_id).is_zero() - } - } -} diff --git a/pallets/asset-registry/src/mock.rs b/pallets/asset-registry/src/mock.rs deleted file mode 100644 index d966bd34c..000000000 --- a/pallets/asset-registry/src/mock.rs +++ /dev/null @@ -1,124 +0,0 @@ -use crate as pallet_asset_registry; -use frame_support::traits::{AsEnsureOriginWithArg, ConstU16, ConstU64, GenesisBuild}; -use frame_system as system; -use sp_core::H256; -use sp_runtime::{ - testing::Header, - traits::{BlakeTwo256, ConstU32, IdentityLookup}, -}; - -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -type Block = frame_system::mocking::MockBlock; - -frame_support::parameter_types! { - pub const StatemineParaIdInfo: u32 = 1000u32; - pub const StatemineAssetsInstanceInfo: u8 = 50u8; - pub const StatemineAssetIdInfo: u128 = 1u128; -} - -// Configure a mock runtime to test the pallet. -frame_support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system, - AssetRegistry: pallet_asset_registry::{Pallet, Call, Storage, Event}, - Assets: pallet_assets::{Pallet, Call, Storage, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - } -); - -impl system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Index = u64; - type BlockNumber = u64; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = ConstU16<42>; - type OnSetCode = (); - type MaxConsumers = ConstU32<16>; -} - -impl pallet_asset_registry::Config for Test { - type RuntimeEvent = RuntimeEvent; - type ReserveAssetModifierOrigin = frame_system::EnsureRoot; - type Assets = Assets; - type WeightInfo = pallet_asset_registry::weights::SubstrateWeight; -} - -impl pallet_balances::Config for Test { - type Balance = u64; - type DustRemoval = (); - type RuntimeEvent = RuntimeEvent; - type ExistentialDeposit = ConstU64<1>; - type AccountStore = System; - type WeightInfo = (); - type MaxLocks = (); - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; -} - -impl pallet_assets::Config for Test { - type RuntimeEvent = RuntimeEvent; - type Balance = u64; - type AssetId = u32; - type Currency = Balances; - type ForceOrigin = frame_system::EnsureRoot; - type AssetDeposit = ConstU64<1>; - type AssetAccountDeposit = ConstU64<10>; - type MetadataDepositBase = ConstU64<1>; - type MetadataDepositPerByte = ConstU64<1>; - type ApprovalDeposit = ConstU64<1>; - type StringLimit = ConstU32<50>; - type Freezer = (); - type WeightInfo = (); - type Extra = (); - type AssetIdParameter = u32; - type CreateOrigin = AsEnsureOriginWithArg>; - type CallbackHandle = (); - type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); -} - -pub const LOCAL_ASSET_ID: u32 = 10; - -// Build genesis storage according to the mock runtime. -pub fn new_test_ext() -> sp_io::TestExternalities { - let mut storage = system::GenesisConfig::default().build_storage::().unwrap(); - - let config: pallet_assets::GenesisConfig = pallet_assets::GenesisConfig { - assets: vec![ - // id, owner, is_sufficient, min_balance - (LOCAL_ASSET_ID, 0, true, 1), - ], - metadata: vec![ - // id, name, symbol, decimals - (LOCAL_ASSET_ID, "Token Name".into(), "TOKEN".into(), 10), - ], - accounts: vec![ - // id, account_id, balance - (LOCAL_ASSET_ID, 1, 100), - ], - }; - config.assimilate_storage(&mut storage).unwrap(); - storage.into() -} diff --git a/pallets/asset-registry/src/tests.rs b/pallets/asset-registry/src/tests.rs deleted file mode 100644 index 7b3029e9b..000000000 --- a/pallets/asset-registry/src/tests.rs +++ /dev/null @@ -1,76 +0,0 @@ -use crate::{mock::*, Error}; -use frame_support::{assert_noop, assert_ok}; -use xcm::latest::prelude::*; - -#[test] -fn register_reserve_asset_works() { - new_test_ext().execute_with(|| { - let statemine_para_id = StatemineParaIdInfo::get(); - let statemine_assets_pallet = StatemineAssetsInstanceInfo::get(); - let statemine_asset_id = StatemineAssetIdInfo::get(); - - let statemine_asset_multi_location = MultiLocation { - parents: 1, - interior: X3( - Parachain(statemine_para_id), - PalletInstance(statemine_assets_pallet), - GeneralIndex(statemine_asset_id), - ), - }; - - assert_ok!(AssetRegistry::register_reserve_asset( - RuntimeOrigin::root(), - LOCAL_ASSET_ID, - statemine_asset_multi_location.clone(), - )); - - let read_asset_multi_location = - AssetRegistry::asset_id_multilocation(LOCAL_ASSET_ID).expect("error reading AssetIdMultiLocation"); - assert_eq!(read_asset_multi_location, statemine_asset_multi_location); - - let read_asset_id = AssetRegistry::asset_multilocation_id(&statemine_asset_multi_location) - .expect("error reading AssetMultiLocationId"); - assert_eq!(read_asset_id, LOCAL_ASSET_ID); - - assert_noop!( - AssetRegistry::register_reserve_asset( - RuntimeOrigin::root(), - LOCAL_ASSET_ID, - statemine_asset_multi_location, - ), - Error::::AssetAlreadyRegistered - ); - }); -} - -#[test] -fn unregister_reserve_asset_works() { - new_test_ext().execute_with(|| { - let statemine_para_id = StatemineParaIdInfo::get(); - let statemine_assets_pallet = StatemineAssetsInstanceInfo::get(); - let statemine_asset_id = StatemineAssetIdInfo::get(); - - let statemine_asset_multi_location = MultiLocation { - parents: 1, - interior: X3( - Parachain(statemine_para_id), - PalletInstance(statemine_assets_pallet), - GeneralIndex(statemine_asset_id), - ), - }; - - assert_ok!(AssetRegistry::register_reserve_asset( - RuntimeOrigin::root(), - LOCAL_ASSET_ID, - statemine_asset_multi_location.clone(), - )); - - assert_ok!(AssetRegistry::unregister_reserve_asset( - RuntimeOrigin::root(), - LOCAL_ASSET_ID - )); - - assert!(AssetRegistry::asset_id_multilocation(LOCAL_ASSET_ID).is_none()); - assert!(AssetRegistry::asset_multilocation_id(statemine_asset_multi_location).is_none()); - }); -} diff --git a/pallets/asset-registry/src/weights.rs b/pallets/asset-registry/src/weights.rs deleted file mode 100644 index 39416c719..000000000 --- a/pallets/asset-registry/src/weights.rs +++ /dev/null @@ -1,76 +0,0 @@ - -//! Autogenerated weights for `pallet_asset_registry` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2022-10-04, STEPS: `20`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! HOSTNAME: `bernardo-benchmarking`, CPU: `AMD EPYC 7B13` -//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 - -// collected on a c2d-highcpu-8 of Google Cloud Platform - -// Executed Command: -// ./target/release/trappist-collator -// benchmark -// pallet -// --chain -// dev -// --pallet -// pallet_asset_registry -// --extrinsic -// * -// --steps -// 20 -// --repeat -// 10 -// --output -// pallets/asset-registry/src/weights.rs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use sp_std::marker::PhantomData; - -pub trait WeightInfo { - fn register_reserve_asset() -> Weight; - fn unregister_reserve_asset() -> Weight; -} - -/// Weight functions for `pallet_asset_registry`. -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - // Storage: Assets Asset (r:1 w:0) - // Storage: AssetRegistry AssetIdMultiLocation (r:1 w:1) - // Storage: AssetRegistry AssetMultiLocationId (r:0 w:1) - fn register_reserve_asset() -> Weight { - Weight::from_ref_time(18_710_000) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(2)) - } - // Storage: AssetRegistry AssetIdMultiLocation (r:1 w:1) - // Storage: AssetRegistry AssetMultiLocationId (r:0 w:1) - fn unregister_reserve_asset() -> Weight { - Weight::from_ref_time(16_570_000) - .saturating_add(T::DbWeight::get().reads(1)) - .saturating_add(T::DbWeight::get().writes(2)) - } -} - -impl WeightInfo for () { - // Storage: Assets Asset (r:1 w:0) - // Storage: AssetRegistry AssetIdMultiLocation (r:1 w:1) - // Storage: AssetRegistry AssetMultiLocationId (r:0 w:1) - fn register_reserve_asset() -> Weight { - Weight::from_ref_time(18_710_000) - .saturating_add(RocksDbWeight::get().reads(2)) - .saturating_add(RocksDbWeight::get().writes(2)) - } - // Storage: AssetRegistry AssetIdMultiLocation (r:1 w:1) - // Storage: AssetRegistry AssetMultiLocationId (r:0 w:1) - fn unregister_reserve_asset() -> Weight { - Weight::from_ref_time(16_570_000) - .saturating_add(RocksDbWeight::get().reads(1)) - .saturating_add(RocksDbWeight::get().writes(2)) - } -} diff --git a/pallets/credentials/Cargo.toml b/pallets/credentials/Cargo.toml deleted file mode 100644 index 9fe1014a2..000000000 --- a/pallets/credentials/Cargo.toml +++ /dev/null @@ -1,58 +0,0 @@ -[package] -name = 'pallet-credentials' -description = 'FRAME pallet handle credentials' -authors.workspace = true -documentation.workspace = true -edition.workspace = true -homepage.workspace = true -license-file.workspace = true -readme.workspace = true -repository.workspace = true -version.workspace = true - - -[dependencies] -parity-scale-codec = { workspace = true, features = [ - "derive", -] } -scale-info = { workspace = true, features = ["derive"] } - -# Benchmarking dependencies -frame-benchmarking = { workspace = true, optional = true } -# Substrate dependencies -frame-support.workspace = true -frame-system.workspace = true -sp-std.workspace = true -sp-runtime.workspace = true -polimec-traits.workspace = true - -[dev-dependencies] -sp-core.workspace = true -sp-io.workspace = true -pallet-balances.workspace = true - -[features] -try-runtime = [ - "frame-support/try-runtime", - "frame-system/try-runtime", - "polimec-traits/try-runtime", -] -default = ["std"] -runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "polimec-traits/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", -] -std = [ - "parity-scale-codec/std", - "sp-std/std", - "sp-runtime/std", - "pallet-balances/std", - "polimec-traits/std", - "frame-support/std", - "frame-system/std", - "scale-info/std", - "frame-benchmarking?/std", -] diff --git a/pallets/credentials/src/benchmarking.rs b/pallets/credentials/src/benchmarking.rs deleted file mode 100644 index 8b1378917..000000000 --- a/pallets/credentials/src/benchmarking.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/pallets/credentials/src/lib.rs b/pallets/credentials/src/lib.rs deleted file mode 100644 index 5f3b325af..000000000 --- a/pallets/credentials/src/lib.rs +++ /dev/null @@ -1,279 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -#![cfg_attr(not(feature = "std"), no_std)] - -pub use pallet::*; - -#[cfg(test)] -mod mock; - -#[cfg(test)] -mod tests; - -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; - -use frame_support::{ - ensure, - pallet_prelude::DispatchResult, - traits::{ChangeMembers, InitializeMembers}, -}; -use polimec_traits::{Credential, MemberRole, PolimecMembers}; -use sp_runtime::{traits::StaticLookup, DispatchError}; - -type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; - -#[frame_support::pallet(dev_mode)] -pub mod pallet { - use super::*; - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - /// Configure the pallet by specifying the parameters and types on which it depends. - #[pallet::config] - pub trait Config: frame_system::Config { - /// The overarching event type. - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - - /// Required origin for adding a member (though can always be Root). - type AddOrigin: EnsureOrigin; - - /// Required origin for removing a member (though can always be Root). - type RemoveOrigin: EnsureOrigin; - - /// Required origin for adding and removing a member in a single action. - /// TODO: Not used ATM - type SwapOrigin: EnsureOrigin; - - /// Required origin for resetting membership. - /// TODO: Not used ATM - type ResetOrigin: EnsureOrigin; - - /// Required origin for setting or resetting the prime member. - /// TODO: Not used ATM - type PrimeOrigin: EnsureOrigin; - - /// The receiver of the signal for when the membership has been initialized. This happens - /// pre-genesis and will usually be the same as `MembershipChanged`. If you need to do - /// something different on initialization, then you can change this accordingly. - type MembershipInitialized: InitializeMembers; - - /// The receiver of the signal for when the membership has changed. - type MembershipChanged: ChangeMembers; - - // Weight information for extrinsics in this pallet. - // type WeightInfo: WeightInfo; - } - - #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] - pub struct Pallet(_); - - /// Maps member type to members of each type. - #[pallet::storage] - #[pallet::getter(fn members)] - pub type Members = StorageDoubleMap<_, Twox64Concat, MemberRole, Twox64Concat, T::AccountId, ()>; - - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - /// The given member was added; see the transaction for who. - MemberAdded, - /// The given member was removed; see the transaction for who. - MemberRemoved, - /// Two members were swapped; see the transaction for who. - MembersSwapped, - /// The membership was reset; see the transaction for who the new set is. - MembersReset, - /// One of the members' keys changed. - KeyChanged, - } - - #[pallet::error] - pub enum Error { - /// Already a member. - AlreadyMember, - /// Not a member. - NotMember, - } - - #[pallet::hooks] - impl Hooks> for Pallet {} - - #[pallet::genesis_config] - pub struct GenesisConfig { - pub issuers: Vec, - pub retails: Vec, - pub professionals: Vec, - pub institutionals: Vec, - } - - #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - Self { - issuers: Default::default(), - retails: Default::default(), - professionals: Default::default(), - institutionals: Default::default(), - } - } - } - - #[pallet::genesis_build] - impl GenesisBuild for GenesisConfig { - fn build(&self) { - use sp_std::collections::btree_set::BTreeSet; - - let issuers_set: BTreeSet<_> = self.issuers.iter().collect(); - assert_eq!( - issuers_set.len(), - self.issuers.len(), - "Issuers cannot contain duplicate accounts." - ); - - let retails_set: BTreeSet<_> = self.retails.iter().collect(); - assert_eq!( - retails_set.len(), - self.retails.len(), - "Issuers cannot contain duplicate accounts." - ); - - let professionals_set: BTreeSet<_> = self.professionals.iter().collect(); - assert_eq!( - professionals_set.len(), - self.professionals.len(), - "Issuers cannot contain duplicate accounts." - ); - - let institutionals_set: BTreeSet<_> = self.institutionals.iter().collect(); - assert_eq!( - institutionals_set.len(), - self.institutionals.len(), - "Issuers cannot contain duplicate accounts." - ); - - Pallet::::initialize_members(&MemberRole::Issuer, &self.issuers); - Pallet::::initialize_members(&MemberRole::Retail, &self.retails); - Pallet::::initialize_members(&MemberRole::Professional, &self.professionals); - Pallet::::initialize_members(&MemberRole::Institutional, &self.institutionals); - } - } - - #[pallet::call] - impl Pallet { - /// Add a member `who` to the set. - /// - /// May only be called from `T::AddOrigin`. - // TODO: Set a proper weight - #[pallet::weight(1)] - pub fn add_member(origin: OriginFor, credential: Credential, who: AccountIdLookupOf) -> DispatchResult { - T::AddOrigin::ensure_origin(origin)?; - let who = T::Lookup::lookup(who)?; - - Self::do_add_member(&who, &credential)?; - Ok(()) - } - - /// Remove a member `who` from the set. - /// - /// May only be called from `T::RemoveOrigin`. - // TODO: Set a proper weight - #[pallet::weight(1)] - pub fn remove_member( - origin: OriginFor, credential: Credential, who: AccountIdLookupOf, - ) -> DispatchResult { - T::RemoveOrigin::ensure_origin(origin)?; - let who = T::Lookup::lookup(who)?; - - Self::do_remove_member(&who, &credential)?; - Ok(()) - } - } -} - -impl Pallet { - fn do_add_member(who: &T::AccountId, credential: &Credential) -> Result<(), DispatchError> { - // TODO: This is a placeholder, we still dont't know the actual structure of a `Credential` - let role = credential.role; - ensure!(!Self::is_in(&role, who), Error::::AlreadyMember); - - Self::do_add_member_with_role(&role, who)?; - Ok(()) - } - - fn do_add_member_with_role(role: &MemberRole, who: &T::AccountId) -> Result<(), DispatchError> { - Members::::insert(role, who, ()); - Self::deposit_event(Event::MemberAdded); - Ok(()) - } - - fn do_remove_member(who: &T::AccountId, credential: &Credential) -> Result<(), DispatchError> { - // TODO: This is a placeholder, we still dont't know the actual structure of a `Credential` - let role = credential.role; - ensure!(Self::is_in(&role, who), Error::::NotMember); - - Self::do_remove_member_with_role(&role, who)?; - Ok(()) - } - - fn do_remove_member_with_role(role: &MemberRole, who: &T::AccountId) -> Result<(), DispatchError> { - Members::::remove(role, who); - Self::deposit_event(Event::MemberRemoved); - Ok(()) - } -} - -use sp_std::{vec, vec::Vec}; - -impl PolimecMembers for Pallet { - /// Chech if `who` is in the `role` set - fn is_in(role: &MemberRole, who: &T::AccountId) -> bool { - >::contains_key(role, who) - } - - /// Add `who` to the `role` set - fn add_member(role: &MemberRole, who: &T::AccountId) -> Result<(), DispatchError> { - Self::do_add_member_with_role(role, who) - } - - /// Utility function to set a vector of `member` during the genesis - fn initialize_members(role: &MemberRole, members: &[T::AccountId]) { - if !members.is_empty() { - for member in members { - assert!(!Self::is_in(role, member), "Members are already initialized!"); - } - for member in members { - let _ = Self::do_add_member_with_role(role, member); - } - } - } - - fn get_members_of(role: &MemberRole) -> Vec { - >::iter_key_prefix(role).collect() - } - - fn get_roles_of(who: &T::AccountId) -> Vec { - let mut user_roles = vec![]; - for role in MemberRole::iterator() { - if let Some(()) = Members::::get(role, who) { - user_roles.push(*role) - } - } - user_roles - } -} diff --git a/pallets/credentials/src/mock.rs b/pallets/credentials/src/mock.rs deleted file mode 100644 index a57d581f1..000000000 --- a/pallets/credentials/src/mock.rs +++ /dev/null @@ -1,129 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -use crate as pallet_credentials; -use frame_support::{parameter_types, traits::ConstU16}; -use frame_system::EnsureRoot; -use sp_core::H256; -use sp_runtime::{ - testing::Header, - traits::{BlakeTwo256, IdentityLookup}, - BuildStorage, -}; - -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -type Block = frame_system::mocking::MockBlock; - -pub type AccountId = u64; -pub type Balance = u128; -pub type BlockNumber = u64; - -// Configure a mock runtime to test the pallet. -frame_support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system, - Balances: pallet_balances, - Credentials: pallet_credentials, - } -); - -parameter_types! { - pub const BlockHashCount: u32 = 250; -} - -impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Index = u64; - type BlockNumber = BlockNumber; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Header = Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = ConstU16<42>; - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} - -parameter_types! { - pub static ExistentialDeposit: Balance = 1; -} - -impl pallet_balances::Config for Test { - type MaxLocks = frame_support::traits::ConstU32<1024>; - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; - type Balance = Balance; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); -} - -impl pallet_credentials::Config for Test { - type RuntimeEvent = RuntimeEvent; - type AddOrigin = EnsureRoot; - type RemoveOrigin = EnsureRoot; - type SwapOrigin = EnsureRoot; - type ResetOrigin = EnsureRoot; - type PrimeOrigin = EnsureRoot; - type MembershipInitialized = (); - type MembershipChanged = (); -} - -// Build genesis storage according to the mock runtime. -// TODO: Add some mocks projects at Genesis to simplify the tests -pub fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - - GenesisConfig { - balances: BalancesConfig { - balances: vec![(1, 512), (2, 512), (3, 512), (4, 512), (5, 512)], - }, - credentials: CredentialsConfig { - issuers: vec![1], - retails: vec![2], - professionals: vec![3, 5], - institutionals: vec![4, 5], - }, - ..Default::default() - } - .assimilate_storage(&mut t) - .unwrap(); - - let mut ext = sp_io::TestExternalities::new(t); - // In order to emit events the block number must be more than 0 - ext.execute_with(|| System::set_block_number(1)); - ext -} diff --git a/pallets/credentials/src/tests.rs b/pallets/credentials/src/tests.rs deleted file mode 100644 index ad6470204..000000000 --- a/pallets/credentials/src/tests.rs +++ /dev/null @@ -1,156 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -use crate::{mock::*, Error}; -use frame_support::{assert_noop, assert_ok, error::BadOrigin, BoundedVec}; -use polimec_traits::{Country, Credential, Issuers, MemberRole, PolimecMembers}; - -pub fn last_event() -> RuntimeEvent { - frame_system::Pallet::::events() - .pop() - .expect("Event expected") - .event -} - -const ALICE: AccountId = 1; -const BOB: AccountId = 2; -const CHARLIE: AccountId = 3; -const DAVE: AccountId = 4; -const EVE: AccountId = 5; - -fn new_test_credential(role: MemberRole) -> Credential { - Credential { - issuer: Issuers::IssuerOne, - role, - domicile: BoundedVec::default(), - country: Country::Switzerland, - date_of_birth: 10, - } -} - -#[test] -fn add_during_genesis_works() { - new_test_ext().execute_with(|| { - assert!(Credentials::members(MemberRole::Issuer, ALICE).is_some()); - assert!(Credentials::is_in(&MemberRole::Issuer, &ALICE)); - - assert!(Credentials::members(MemberRole::Retail, BOB).is_some()); - assert!(Credentials::is_in(&MemberRole::Retail, &BOB)); - - assert!(Credentials::members(MemberRole::Professional, CHARLIE).is_some()); - assert!(Credentials::is_in(&MemberRole::Professional, &CHARLIE)); - - assert!(Credentials::members(MemberRole::Institutional, DAVE).is_some()); - assert!(Credentials::is_in(&MemberRole::Institutional, &DAVE)); - }) -} - -#[test] -fn add_member_works() { - new_test_ext().execute_with(|| { - let cred = new_test_credential(MemberRole::Issuer); - assert_ok!(Credentials::add_member(RuntimeOrigin::root(), cred, BOB)); - assert_eq!(last_event(), RuntimeEvent::Credentials(crate::Event::MemberAdded)); - }) -} - -#[test] -fn only_root_can_add_member() { - new_test_ext().execute_with(|| { - let cred = new_test_credential(MemberRole::Issuer); - assert_noop!( - Credentials::add_member(RuntimeOrigin::signed(ALICE), cred, BOB), - BadOrigin - ); - }) -} - -#[test] -fn cant_add_already_member() { - new_test_ext().execute_with(|| { - let cred = new_test_credential(MemberRole::Issuer); - assert_noop!( - Credentials::add_member(RuntimeOrigin::root(), cred, ALICE), - Error::::AlreadyMember - ); - }) -} - -#[test] -fn remove_member_works() { - new_test_ext().execute_with(|| { - let cred = new_test_credential(MemberRole::Issuer); - assert_ok!(Credentials::remove_member(RuntimeOrigin::root(), cred, ALICE)); - assert_eq!(last_event(), RuntimeEvent::Credentials(crate::Event::MemberRemoved)); - }) -} - -#[test] -fn only_root_can_remove_member() { - new_test_ext().execute_with(|| { - let cred = new_test_credential(MemberRole::Issuer); - assert_noop!( - Credentials::remove_member(RuntimeOrigin::signed(ALICE), cred, ALICE), - BadOrigin - ); - }) -} - -#[test] -fn cant_remove_not_a_member() { - new_test_ext().execute_with(|| { - let cred = new_test_credential(MemberRole::Issuer); - assert_noop!( - Credentials::remove_member(RuntimeOrigin::root(), cred, EVE), - Error::::NotMember - ); - }) -} - -#[test] -fn get_members_of_works() { - new_test_ext().execute_with(|| { - let issuers = Credentials::get_members_of(&MemberRole::Issuer); - assert!(issuers == vec![1]); - let cred = new_test_credential(MemberRole::Issuer); - let _ = Credentials::add_member(RuntimeOrigin::root(), cred.clone(), BOB); - let issuers = Credentials::get_members_of(&MemberRole::Issuer); - assert!(issuers == vec![1, 2]); - let _ = Credentials::remove_member(RuntimeOrigin::root(), cred, ALICE); - let issuers = Credentials::get_members_of(&MemberRole::Issuer); - assert!(issuers == vec![2]); - }) -} - -#[test] -fn get_roles_of_works() { - new_test_ext().execute_with(|| { - let roles = Credentials::get_roles_of(&EVE); - let expected_roles = vec![MemberRole::Professional, MemberRole::Institutional]; - assert!(roles.len() == 2); - assert!(roles == expected_roles); - }) -} - -#[test] -fn get_roles_of_not_user() { - new_test_ext().execute_with(|| { - let roles = Credentials::get_roles_of(&6); - let expected_roles: Vec = vec![]; - assert!(roles.is_empty()); - assert!(roles == expected_roles); - }) -} diff --git a/pallets/funding/Cargo.toml b/pallets/funding/Cargo.toml index 715a43d3d..1125957c9 100644 --- a/pallets/funding/Cargo.toml +++ b/pallets/funding/Cargo.toml @@ -33,7 +33,6 @@ sp-io.workspace = true pallet-balances.workspace = true pallet-insecure-randomness-collective-flip.workspace = true pallet-assets.workspace = true -pallet-credentials.workspace = true [features] default = ["std"] @@ -47,7 +46,6 @@ std = [ "frame-system/std", "pallet-assets/std", "pallet-balances/std", - "pallet-credentials/std", "polimec-traits/std", "frame-benchmarking?/std", ] diff --git a/pallets/funding/src/lib.rs b/pallets/funding/src/lib.rs index 5e78af3bb..641dd3a33 100644 --- a/pallets/funding/src/lib.rs +++ b/pallets/funding/src/lib.rs @@ -307,9 +307,6 @@ pub mod pallet { /// Something that provides randomness in the runtime. type Randomness: Randomness; - /// Something that provides the members of Polimec - type HandleMembers: PolimecMembers; - /// The maximum length of data stored on-chain. #[pallet::constant] type StringLimit: Get; diff --git a/pallets/funding/src/mock.rs b/pallets/funding/src/mock.rs index ebf310623..602e372a3 100644 --- a/pallets/funding/src/mock.rs +++ b/pallets/funding/src/mock.rs @@ -55,7 +55,6 @@ frame_support::construct_runtime!( Assets: pallet_assets, Balances: pallet_balances, FundingModule: pallet_funding, - Credentials: pallet_credentials, } ); @@ -108,17 +107,6 @@ impl pallet_balances::Config for TestRuntime { impl pallet_insecure_randomness_collective_flip::Config for TestRuntime {} -impl pallet_credentials::Config for TestRuntime { - type RuntimeEvent = RuntimeEvent; - type AddOrigin = EnsureSigned; - type RemoveOrigin = EnsureSigned; - type SwapOrigin = EnsureSigned; - type ResetOrigin = EnsureSigned; - type PrimeOrigin = EnsureSigned; - type MembershipInitialized = (); - type MembershipChanged = (); -} - impl pallet_assets::Config for TestRuntime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; @@ -171,7 +159,6 @@ impl pallet_funding::Config for TestRuntime { type MaxProjectsToUpdatePerBlock = ConstU32<100>; type CommunityFundingDuration = CommunityRoundDuration; type Randomness = RandomnessCollectiveFlip; - type HandleMembers = Credentials; type PreImageLimit = ConstU32<1024>; // Low value to simplify the tests type MaximumBidsPerUser = ConstU32<4>; @@ -195,12 +182,6 @@ pub fn new_test_ext() -> sp_io::TestExternalities { GenesisConfig { balances: BalancesConfig { balances: vec![] }, - credentials: CredentialsConfig { - issuers: vec![1, 16558220937623665250], - retails: vec![2], - professionals: vec![2, 3], - institutionals: vec![4], - }, ..Default::default() } .assimilate_storage(&mut t) diff --git a/pallets/parachain-staking/Cargo.toml b/pallets/parachain-staking/Cargo.toml deleted file mode 100644 index 569bb1636..000000000 --- a/pallets/parachain-staking/Cargo.toml +++ /dev/null @@ -1,70 +0,0 @@ -[package] -authors = ["KILT "] -description = "Parachain parachain-staking pallet for collator delegation and selection as well as reward distribution" -edition = "2021" -name = "parachain-staking" -version = "1.9.0-dev" - -[dev-dependencies] -pallet-aura = {workspace = true, features = ["std"]} -pallet-timestamp = {workspace = true, features = ["std"]} -sp-consensus-aura = {workspace = true, features = ["std"]} -sp-core = {workspace = true, features = ["std"]} -sp-io = {workspace = true, features = ["std"]} - -[dependencies] -# External dependencies -parity-scale-codec = {workspace = true, features = ["derive"]} -log.workspace = true -scale-info = {workspace = true, features = ["derive", "serde"]} -serde = {workspace = true, optional = true} - -# Internal dependencies -kilt-runtime-api-staking.workspace = true - -# Substrate dependencies -frame-support.workspace = true -frame-system.workspace = true -pallet-authorship.workspace = true -pallet-balances.workspace = true -pallet-session.workspace = true -sp-runtime.workspace = true -sp-staking.workspace = true -sp-std.workspace = true - -# Benchmarking dependencies -frame-benchmarking = {workspace = true, optional = true} - -[features] -default = ["std"] -runtime-benchmarks = [ - "frame-benchmarking", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "pallet-balances/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "sp-staking/runtime-benchmarks", -] -std = [ - "parity-scale-codec/std", - "frame-benchmarking?/std", - "frame-support/std", - "frame-system/std", - "kilt-runtime-api-staking/std", - "log/std", - "pallet-authorship/std", - "pallet-balances/std", - "pallet-session/std", - "scale-info/std", - "serde", - "sp-runtime/std", - "sp-staking/std", - "sp-std/std", -] -try-runtime = [ - "frame-system/try-runtime", - "frame-support/try-runtime", - "pallet-authorship/try-runtime", - "pallet-balances/try-runtime", - "pallet-session/try-runtime", -] diff --git a/pallets/parachain-staking/src/api.rs b/pallets/parachain-staking/src/api.rs deleted file mode 100644 index a7ba6a3a5..000000000 --- a/pallets/parachain-staking/src/api.rs +++ /dev/null @@ -1,90 +0,0 @@ -// KILT Blockchain – https://botlabs.org -// Copyright (C) 2019-2023 BOTLabs GmbH - -// The KILT Blockchain 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. - -// The KILT Blockchain 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 this program. If not, see . - -// If you feel like getting in touch with us, you can do so at info@botlabs.org - -use frame_support::traits::Currency; -use sp_runtime::{ - traits::{Saturating, Zero}, - Perquintill, -}; - -use crate::{ - types::BalanceOf, BlocksAuthored, BlocksRewarded, CandidatePool, Config, DelegatorState, InflationConfig, Pallet, - Rewards, TotalCollatorStake, -}; - -impl Pallet { - /// Calculates the staking rewards for a given account address. - /// - /// Subtracts the number of rewarded blocks from the number of authored - /// blocks by the collator and multiplies that with the current stake - /// as well as reward rate. - /// - /// At least used in Runtime API. - pub fn get_unclaimed_staking_rewards(acc: &T::AccountId) -> BalanceOf { - let count_rewarded = BlocksRewarded::::get(acc); - let rewards = Rewards::::get(acc); - - // delegators and collators need to be handled differently - if let Some(delegator_state) = DelegatorState::::get(acc) { - // #blocks for unclaimed staking rewards equals - // #blocks_authored_by_collator - #blocks_claimed_by_delegator - let count_unclaimed = BlocksAuthored::::get(&delegator_state.owner).saturating_sub(count_rewarded); - let stake = delegator_state.amount; - // rewards += stake * reward_count * delegator_reward_rate - rewards.saturating_add(Self::calc_block_rewards_delegator(stake, count_unclaimed.into())) - } else if Self::is_active_candidate(acc).is_some() { - // #blocks for unclaimed staking rewards equals - // #blocks_authored_by_collator - #blocks_claimed_by_collator - let count_unclaimed = BlocksAuthored::::get(acc).saturating_sub(count_rewarded); - let stake = CandidatePool::::get(acc) - .map(|state| state.stake) - .unwrap_or_else(BalanceOf::::zero); - // rewards += stake * self_count * collator_reward_rate - rewards.saturating_add(Self::calc_block_rewards_collator(stake, count_unclaimed.into())) - } else { - rewards - } - } - - /// Calculates the current staking and reward rates for collators and - /// delegators. - /// - /// At least used in Runtime API. - pub fn get_staking_rates() -> kilt_runtime_api_staking::StakingRates { - let total_issuance = T::Currency::total_issuance(); - let total_stake = TotalCollatorStake::::get(); - let inflation_config = InflationConfig::::get(); - let collator_staking_rate = Perquintill::from_rational(total_stake.collators, total_issuance); - let delegator_staking_rate = Perquintill::from_rational(total_stake.delegators, total_issuance); - let collator_reward_rate = Perquintill::from_rational( - inflation_config.collator.max_rate.deconstruct(), - collator_staking_rate.deconstruct(), - ) * inflation_config.collator.reward_rate.annual; - let delegator_reward_rate = Perquintill::from_rational( - inflation_config.delegator.max_rate.deconstruct(), - delegator_staking_rate.deconstruct(), - ) * inflation_config.delegator.reward_rate.annual; - - kilt_runtime_api_staking::StakingRates { - collator_staking_rate, - collator_reward_rate, - delegator_staking_rate, - delegator_reward_rate, - } - } -} diff --git a/pallets/parachain-staking/src/benchmarking.rs b/pallets/parachain-staking/src/benchmarking.rs deleted file mode 100644 index be40ccd41..000000000 --- a/pallets/parachain-staking/src/benchmarking.rs +++ /dev/null @@ -1,638 +0,0 @@ -// KILT Blockchain – https://botlabs.org -// Copyright (C) 2019-2023 BOTLabs GmbH - -// The KILT Blockchain 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. - -// The KILT Blockchain 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 this program. If not, see . - -// If you feel like getting in touch with us, you can do so at info@botlabs.org -#![cfg(feature = "runtime-benchmarks")] - -//! Benchmarking -use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, Zero}; -use frame_support::{ - assert_ok, - traits::{Currency, Get, OnInitialize}, -}; -use frame_system::{Pallet as System, RawOrigin}; -use pallet_session::Pallet as Session; -use sp_runtime::{ - traits::{One, SaturatedConversion, StaticLookup}, - Perquintill, -}; -use sp_std::{convert::TryInto, vec::Vec}; - -use crate::{types::RoundInfo, *}; - -const COLLATOR_ACCOUNT_SEED: u32 = 0; -const DELEGATOR_ACCOUNT_SEED: u32 = 1; - -/// Fills the candidate pool up to `num_candidates`. -fn setup_collator_candidates( - num_candidates: u32, default_amount: Option, -) -> Vec { - let current_collator_count = TopCandidates::::get().len().saturated_into::(); - let collators: Vec = (current_collator_count..num_candidates) - .map(|i| account("collator", i.saturated_into::(), COLLATOR_ACCOUNT_SEED)) - .collect(); - let amount: T::CurrencyBalance = default_amount.unwrap_or_else(T::MinCollatorCandidateStake::get); - - for acc in collators.iter() { - T::Currency::make_free_balance_be(acc, amount); - assert_ok!(Pallet::::join_candidates( - T::RuntimeOrigin::from(Some(acc.clone()).into()), - amount, - )); - assert_eq!(CandidatePool::::get(acc).unwrap().stake, amount); - } - - TopCandidates::::get() - .into_bounded_vec() - .into_inner() - .drain(..) - .map(|c| c.owner) - .collect() -} - -fn fill_delegators(num_delegators: u32, collator: T::AccountId, collator_seed: u32) -> Vec { - let state = CandidatePool::::get(&collator).unwrap(); - let current_delegators = state.delegators.len().saturated_into::(); - - let delegators: Vec = (current_delegators..num_delegators) - .map(|i| { - account( - "delegator", - i.saturated_into::(), - DELEGATOR_ACCOUNT_SEED * 1000 + collator_seed, - ) - }) - .collect(); - - for acc in delegators.iter() { - T::Currency::make_free_balance_be(acc, T::MinDelegatorStake::get()); - assert_ok!(Pallet::::join_delegators( - T::RuntimeOrigin::from(Some(acc.clone()).into()), - T::Lookup::unlookup(collator.clone()), - T::MinDelegatorStake::get(), - )); - } - - delegators -} - -// fills unstake BTreeMap by unstaked many entries of 1 -fn fill_unstaking(collator: &T::AccountId, delegator: Option<&T::AccountId>, unstaked: u64) -where - u64: Into<::BlockNumber>, -{ - let who = delegator.unwrap_or(collator); - assert_eq!(Unstaking::::get(who).len(), 0); - while System::::block_number() < unstaked.into() { - if let Some(delegator) = delegator { - assert_ok!(Pallet::::delegator_stake_less( - RawOrigin::Signed(delegator.clone()).into(), - T::CurrencyBalance::one() - )); - } else { - assert_ok!(Pallet::::candidate_stake_less( - RawOrigin::Signed(collator.clone()).into(), - T::CurrencyBalance::one() - )); - } - System::::set_block_number(System::::block_number() + T::BlockNumber::one()); - } - assert_eq!(Unstaking::::get(who).len() as u64, unstaked); - assert!(Unstaking::::get(who).len() <= T::MaxUnstakeRequests::get().try_into().unwrap()); -} - -benchmarks! { - where_clause { where u64: Into<::BlockNumber> } - - on_initialize_no_action { - assert_eq!(Round::::get().current, 0u32); - let block = T::BlockNumber::one(); - }: { Pallet::::on_initialize(block) } - verify { - assert_eq!(Round::::get().current, 0u32); - } - - on_initialize_round_update { - let round = Round::::get(); - assert_eq!(round.current, 0u32); - }: { Pallet::::on_initialize(round.length) } - verify { - assert_eq!(Round::::get().current, 1u32); - } - - on_initialize_network_rewards { - let issuance = T::Currency::total_issuance(); - // if we only add by one, we also initialize a new year - let block = T::NetworkRewardStart::get() + T::BlockNumber::one() * 2_u64.into(); - }: { Pallet::::on_initialize(block) } - verify { - let new_issuance = T::Currency::total_issuance(); - let max_col_reward = InflationConfig::::get().collator.reward_rate.per_block * MaxCollatorCandidateStake::::get() * MaxSelectedCandidates::::get().into(); - let network_block_reward = T::NetworkRewardRate::get() * max_col_reward; - assert!(new_issuance > issuance); - assert_eq!(new_issuance - issuance, network_block_reward) - } - - force_new_round { - let round = Round::::get(); - let now = System::::block_number(); - assert_eq!(round.current, 0); - assert_eq!(Session::::current_index(), 0); - assert!(!ForceNewRound::::get()); - }: _(RawOrigin::Root) - verify { - assert!(ForceNewRound::::get()); - assert_eq!(Session::::current_index(), 0); - - // jump to next block to trigger new round - let now = now + T::BlockNumber::one(); - System::::set_block_number(now); - Session::::on_initialize(now); - assert_eq!(Session::::current_index(), 1); - assert_eq!(Round::::get(), RoundInfo { - current: 1, - first: now, - length: round.length, - }); - assert!(!ForceNewRound::::get()); - } - - set_inflation { - let n in 0 .. T::MaxTopCandidates::get(); - let m in 0 .. T::MaxDelegatorsPerCollator::get(); - - let candidates = setup_collator_candidates::(n, None); - for (i, c) in candidates.iter().enumerate() { - fill_delegators::(m, c.clone(), i.saturated_into::()); - Rewards::::insert(c, T::Balance::one()); - } - - let inflation = InflationInfo::new( - T::BLOCKS_PER_YEAR.saturated_into(), - Perquintill::from_percent(10), - Perquintill::from_percent(15), - Perquintill::from_percent(40), - Perquintill::from_percent(10) - ); - }: _(RawOrigin::Root, inflation.collator.max_rate, inflation.collator.reward_rate.annual, inflation.delegator.max_rate, inflation.delegator.reward_rate.annual) - verify { - assert_eq!(InflationConfig::::get(), inflation); - candidates.into_iter().for_each(|candidate| { - assert!(!Rewards::::get(&candidate).is_zero()); - }); - } - - set_max_selected_candidates { - let n in (T::MinCollators::get()) .. T::MaxTopCandidates::get(); - let m in 0 .. T::MaxDelegatorsPerCollator::get(); - - let candidates = setup_collator_candidates::(n, None); - for (i, c) in candidates.iter().enumerate() { - fill_delegators::(m, c.clone(), i.saturated_into::()); - } - let old_candidate = candidates[0].clone(); - }: _(RawOrigin::Root, n) - verify { - assert_eq!(MaxSelectedCandidates::::get(), n); - } - - set_blocks_per_round { - let bpr: T::BlockNumber = T::MinBlocksPerRound::get() + T::BlockNumber::one(); - }: _(RawOrigin::Root, bpr) - verify { - assert_eq!(Round::::get().length, bpr); - } - - force_remove_candidate { - let n in (T::MinCollators::get() + 1) .. T::MaxTopCandidates::get(); - let m in 0 .. T::MaxDelegatorsPerCollator::get(); - - let candidates = setup_collator_candidates::(n, None); - for (i, c) in candidates.iter().enumerate() { - fill_delegators::(m, c.clone(), i.saturated_into::()); - } - let candidate = candidates[0].clone(); - let unlookup_candidate = T::Lookup::unlookup(candidate.clone()); - }: _(RawOrigin::Root, unlookup_candidate) - verify { - let candidates = TopCandidates::::get(); - assert!(!candidates.into_iter().any(|other| other.owner == candidate)); - } - - join_candidates { - let n in 1 .. T::MaxTopCandidates::get() - 1; - let m in 0 .. T::MaxDelegatorsPerCollator::get(); - - let min_candidate_stake = T::MinCollatorCandidateStake::get(); - let candidates = setup_collator_candidates::(n, None); - for (i, c) in candidates.iter().enumerate() { - fill_delegators::(m, c.clone(), i.saturated_into::()); - } - - let new_candidate = account("new_collator", u32::MAX , COLLATOR_ACCOUNT_SEED); - T::Currency::make_free_balance_be(&new_candidate, min_candidate_stake); - - let origin = RawOrigin::Signed(new_candidate.clone()); - }: _(origin, min_candidate_stake) - verify { - let candidates = TopCandidates::::get(); - assert!(candidates.into_iter().any(|other| other.owner == new_candidate)); - } - - init_leave_candidates { - let n in (T::MinCollators::get() + 1) .. T::MaxTopCandidates::get() - 1; - let m in 0 .. T::MaxDelegatorsPerCollator::get(); - - let candidates = setup_collator_candidates::(n, None); - for (i, c) in candidates.iter().enumerate() { - fill_delegators::(m, c.clone(), i.saturated_into::()); - } - - let now = Round::::get().current; - let candidate = candidates[0].clone(); - - let origin = RawOrigin::Signed(candidate.clone()); - }: _(origin) - verify { - let candidates = TopCandidates::::get(); - assert!(!candidates.into_iter().any(|other| other.owner == candidate)); - let unlocking_at = now.saturating_add(T::ExitQueueDelay::get()); - assert!(CandidatePool::::get(candidate).unwrap().can_exit(unlocking_at)); - } - - cancel_leave_candidates { - let n in (T::MinCollators::get() + 1) .. T::MaxTopCandidates::get() - 1; - let m in 0 .. T::MaxDelegatorsPerCollator::get(); - - let candidates = setup_collator_candidates::(n, None); - for (i, c) in candidates.iter().enumerate() { - fill_delegators::(m, c.clone(), i.saturated_into::()); - } - - let candidate = candidates[0].clone(); - assert_ok!(Pallet::::init_leave_candidates(RawOrigin::Signed(candidate.clone()).into())); - - let origin = RawOrigin::Signed(candidate.clone()); - }: _(origin) - verify { - let candidates = TopCandidates::::get(); - assert!(candidates.into_iter().any(|other| other.owner == candidate)); - } - - execute_leave_candidates { - let n in (T::MinCollators::get() + 1) .. T::MaxTopCandidates::get() - 1; - let m in 0 .. T::MaxDelegatorsPerCollator::get(); - - let u = T::MaxUnstakeRequests::get() - 1; - let candidates = setup_collator_candidates::(n, None); - for (i, c) in candidates.iter().enumerate() { - fill_delegators::(m, c.clone(), i.saturated_into::()); - } - let candidate = candidates[0].clone(); - - // increase stake so we can unstake, because current stake is minimum - let more_stake = T::MinCollatorCandidateStake::get(); - T::Currency::make_free_balance_be(&candidate, T::CurrencyBalance::from(u128::MAX)); - assert_ok!(Pallet::::candidate_stake_more(RawOrigin::Signed(candidate.clone()).into(), more_stake)); - - // fill unstake BTreeMap by unstaked many entries of 1 - fill_unstaking::(&candidate, None, u as u64); - - // go to block in which we can exit - assert_ok!(Pallet::::init_leave_candidates(RawOrigin::Signed(candidate.clone()).into())); - - for i in 1..=T::ExitQueueDelay::get() { - let round = Round::::get(); - let now = round.first + round.length; - System::::set_block_number(now); - Pallet::::on_initialize(now); - } - let unlookup_candidate = T::Lookup::unlookup(candidate.clone()); - - let origin = RawOrigin::Signed(candidate.clone()); - }: _(origin, unlookup_candidate) - verify { - // should have one more entry in Unstaking - assert_eq!(Unstaking::::get(&candidate).len().saturated_into::(), u.saturating_add(1u32)); - } - - candidate_stake_more { - let n in 1 .. T::MaxTopCandidates::get() - 1; - let m in 0 .. T::MaxDelegatorsPerCollator::get(); - let u in 0 .. (T::MaxUnstakeRequests::get().saturated_into::() - 1); - - let candidates = setup_collator_candidates::(n, None); - for (i, c) in candidates.iter().enumerate() { - fill_delegators::(m, c.clone(), i.saturated_into::()); - } - let candidate = candidates[0].clone(); - - let old_stake = CandidatePool::::get(&candidate).unwrap().stake; - let more_stake = T::MinCollatorCandidateStake::get(); - - // increase stake so we can unstake, because current stake is minimum - T::Currency::make_free_balance_be(&candidate, T::CurrencyBalance::from(u128::MAX)); - assert_ok!(Pallet::::candidate_stake_more(RawOrigin::Signed(candidate.clone()).into(), more_stake)); - - // fill unstake BTreeMap by unstaked many entries of 1 - fill_unstaking::(&candidate, None, u as u64); - - let origin = RawOrigin::Signed(candidate.clone()); - }: _(origin, more_stake) - verify { - let new_stake = CandidatePool::::get(&candidate).unwrap().stake; - assert!(Unstaking::::get(candidate).is_empty()); - assert_eq!(new_stake, old_stake + more_stake + more_stake - T::CurrencyBalance::from(u as u64)); - } - - candidate_stake_less { - let n in 1 .. T::MaxTopCandidates::get() - 1; - let m in 0 .. T::MaxDelegatorsPerCollator::get(); - - let candidates = setup_collator_candidates::(n, None); - for (i, c) in candidates.iter().enumerate() { - fill_delegators::(m, c.clone(), i.saturated_into::()); - } - let candidate = candidates[0].clone(); - - // increase stake of candidate to later decrease it again - let old_stake = CandidatePool::::get(&candidate).unwrap().stake; - let more_stake = T::MinCollatorCandidateStake::get(); - - T::Currency::make_free_balance_be(&candidate, T::CurrencyBalance::from(u128::MAX)); - Pallet::::candidate_stake_more(RawOrigin::Signed(candidate.clone()).into(), more_stake).expect("should increase stake"); - - let new_stake = CandidatePool::::get(&candidate).unwrap().stake; - assert_eq!(new_stake, old_stake + more_stake); - - let origin = RawOrigin::Signed(candidate.clone()); - }: _(origin, more_stake) - verify { - let new_stake = CandidatePool::::get(&candidate).unwrap().stake; - assert_eq!(new_stake, old_stake); - } - - join_delegators { - let n in 1 .. T::MaxTopCandidates::get(); - let m in 1 .. T::MaxDelegatorsPerCollator::get() - 1; - - let candidates = setup_collator_candidates::(n, None); - for (i, c) in candidates.iter().enumerate() { - fill_delegators::(m, c.clone(), i.saturated_into::()); - } - let collator = candidates[0].clone(); - let delegator = account("new-delegator", 0, DELEGATOR_ACCOUNT_SEED); - let amount = T::MinDelegatorStake::get(); - T::Currency::make_free_balance_be(&delegator, amount + amount + amount + amount); - let unlookup_collator = T::Lookup::unlookup(collator.clone()); - - - let origin = RawOrigin::Signed(delegator.clone()); - }: _(origin, unlookup_collator, amount) - verify { - let state = CandidatePool::::get(&collator).unwrap(); - assert!(state.delegators.into_iter().any(|x| x.owner == delegator)); - } - - delegator_stake_more { - // we need at least 1 collators - let n in 1 .. T::MaxTopCandidates::get(); - // we need at least 1 delegator - let m in 1 .. T::MaxDelegatorsPerCollator::get() - 1; - let u in 1 .. (T::MaxUnstakeRequests::get().saturated_into::() - 1); - - let candidates = setup_collator_candidates::(n, None); - for (i, c) in candidates.iter().enumerate() { - fill_delegators::(m, c.clone(), i.saturated_into::()); - } - let collator = candidates[0].clone(); - let amount = T::MinDelegatorStake::get(); - - // make sure delegator collated to collator - let state = CandidatePool::::get(&collator).unwrap(); - let delegator = state.delegators.into_bounded_vec()[0].owner.clone(); - assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, amount); - - // increase stake so we can unstake, because current stake is minimum - T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); - assert_ok!(Pallet::::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::CurrencyBalance::from(u as u64))); - assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, amount + T::CurrencyBalance::from(u as u64)); - - // fill unstake BTreeMap by unstaked many entries of 1 - fill_unstaking::(&collator, Some(&delegator), u as u64); - assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, amount); - - let origin = RawOrigin::Signed(delegator.clone()); - }: _(origin, amount) - verify { - let state = CandidatePool::::get(&collator).unwrap(); - assert!(state.delegators.into_iter().any(|x| x.owner == delegator)); - assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, amount + amount); - assert!(Unstaking::::get(&delegator).is_empty()); - } - - delegator_stake_less { - // we need at least 1 collators - let n in 1 .. T::MaxTopCandidates::get(); - // we need at least 1 delegator - let m in 1 .. T::MaxDelegatorsPerCollator::get() - 1; - - let candidates = setup_collator_candidates::(n, None); - for (i, c) in candidates.iter().enumerate() { - fill_delegators::(m, c.clone(), i.saturated_into::()); - } - let collator = candidates[0].clone(); - let amount = T::CurrencyBalance::one(); - - // make sure delegator collated to collator - let state = CandidatePool::::get(&collator).unwrap(); - let delegator = state.delegators.into_bounded_vec()[0].owner.clone(); - assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get()); - - // increase stake so we can unstake, because current stake is minimum - T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); - assert_ok!(Pallet::::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), amount + amount)); - assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount + amount); - - // decrease stake once so we have an unstaking entry for this block - assert_ok!(Pallet::::delegator_stake_less(RawOrigin::Signed(delegator.clone()).into(), amount)); - assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount); - assert_eq!(Unstaking::::get(&delegator).len(), 1); - - let origin = RawOrigin::Signed(delegator.clone()); - }: _(origin, amount) - verify { - let state = CandidatePool::::get(&collator).unwrap(); - assert!(state.delegators.into_iter().any(|x| x.owner == delegator)); - assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get()); - assert_eq!(Unstaking::::get(&delegator).len(), 2); - } - - leave_delegators { - // we need at least 1 collators - let n in 1 .. T::MaxTopCandidates::get(); - // we need at least 1 delegator - let m in 1 .. T::MaxDelegatorsPerCollator::get() - 1; - - let candidates = setup_collator_candidates::(n, None); - for (i, c) in candidates.iter().enumerate() { - fill_delegators::(m, c.clone(), i.saturated_into::()); - } - let collator = candidates[0].clone(); - let amount = T::CurrencyBalance::one(); - - // make sure delegator collated to collator - let state = CandidatePool::::get(&collator).unwrap(); - let delegator = state.delegators.into_bounded_vec()[0].owner.clone(); - assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get()); - - // increase stake so we can unstake, because current stake is minimum - T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); - assert_ok!(Pallet::::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), amount + amount)); - assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount + amount); - - // decrease stake once so we have an unstaking entry for this block - assert_ok!(Pallet::::delegator_stake_less(RawOrigin::Signed(delegator.clone()).into(), amount)); - assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount); - assert_eq!(Unstaking::::get(&delegator).len(), 1); - - let origin = RawOrigin::Signed(delegator.clone()); - }: _(origin) - verify { - let state = CandidatePool::::get(&collator).unwrap(); - assert!(!state.delegators.into_iter().any(|x| x.owner == delegator)); - assert!(DelegatorState::::get(&delegator).is_none()); - assert_eq!(Unstaking::::get(&delegator).len(), 2); - } - - unlock_unstaked { - let u in 1 .. (T::MaxUnstakeRequests::get() - 1); - - let candidate = account("collator", 0u32, COLLATOR_ACCOUNT_SEED); - let free_balance = T::CurrencyBalance::from(u128::MAX); - let stake = T::MinCollatorCandidateStake::get(); - T::Currency::make_free_balance_be(&candidate, free_balance); - assert_ok!(Pallet::::join_candidates( - T::RuntimeOrigin::from(Some(candidate.clone()).into()), - stake, - )); - assert_eq!(pallet_balances::Pallet::::usable_balance(&candidate), (free_balance - T::MinCollatorCandidateStake::get()).into()); - - // increase stake so we can unstake, because current stake is minimum - assert_ok!(Pallet::::candidate_stake_more(RawOrigin::Signed(candidate.clone()).into(), stake)); - - // fill unstake BTreeMap by unstaked many entries of 1 - fill_unstaking::(&candidate, None, u as u64); - assert_eq!(CandidatePool::::get(&candidate).unwrap().stake, stake + stake - T::CurrencyBalance::from(u as u64)); - - // roll to block in which first unstake can be unlocked - System::::set_block_number(T::StakeDuration::get()); - assert_eq!(pallet_balances::Pallet::::usable_balance(&candidate), (free_balance - stake - stake).into()); - let unlookup_candidate = T::Lookup::unlookup(candidate.clone()); - - let origin = RawOrigin::Signed(candidate.clone()); - }: _(origin, unlookup_candidate) - verify { - assert_eq!(Unstaking::::get(&candidate).len().saturated_into::(), u.saturating_sub(1u32)); - assert_eq!(pallet_balances::Pallet::::usable_balance(&candidate), (free_balance - stake - stake + T::CurrencyBalance::one()).into()); - } - - set_max_candidate_stake { - let old = MaxCollatorCandidateStake::::get(); - let new = MaxCollatorCandidateStake::::get() + T::CurrencyBalance::from(10u128); - }: _(RawOrigin::Root, new) - verify { - assert_eq!(MaxCollatorCandidateStake::::get(), new); - } - - increment_delegator_rewards { - let collator = setup_collator_candidates::(1, None)[0].clone(); - let delegator = fill_delegators::(1, collator.clone(), COLLATOR_ACCOUNT_SEED)[0].clone(); - - // mock high values to compensate for tiny values in unit test env - let stake = T::CurrencyBalance::from(1_000_000_000_000_000_000u128); - DelegatorState::::insert(&delegator, crate::types::Delegator { owner: collator.clone(), amount: stake}); - BlocksAuthored::::insert(&collator, u64::MAX.into()); - - assert!(Rewards::::get(&delegator).is_zero()); - let origin = RawOrigin::Signed(delegator.clone()); - }: _(origin) - verify { - assert!(!Rewards::::get(&delegator).is_zero()); - assert_eq!(BlocksRewarded::::get(&delegator), u64::MAX.into()); - } - - increment_collator_rewards { - let collator = setup_collator_candidates::(1, None)[0].clone(); - - // mock high counter to compensate for tiny amounts in unit test env - BlocksAuthored::::insert(&collator, u64::MAX.into()); - assert!(Rewards::::get(&collator).is_zero(), "reward {:?}", Rewards::::get(&collator)); - let origin = RawOrigin::Signed(collator.clone()); - }: _(origin) - verify { - assert!(!Rewards::::get(&collator).is_zero()); - assert_eq!(BlocksRewarded::::get(&collator), u64::MAX.into()); - } - - claim_rewards { - let beneficiary = account("beneficiary", 0, 0); - let amount = T::MinCollatorCandidateStake::get(); - T::Currency::make_free_balance_be(&beneficiary, amount); - Rewards::::insert(&beneficiary, amount); - assert_eq!(pallet_balances::Pallet::::usable_balance(&beneficiary), amount.into()); - let origin = RawOrigin::Signed(beneficiary.clone()); - }: _(origin) - verify { - assert!(Rewards::::get(&beneficiary).is_zero()); - assert_eq!(pallet_balances::Pallet::::usable_balance(&beneficiary), (amount + amount).into()); - } - - execute_scheduled_reward_change { - // we need at least 1 collators - let n in 0 .. T::MaxTopCandidates::get(); - // we need at least 1 delegator - let m in 0 .. T::MaxDelegatorsPerCollator::get(); - - let candidates = setup_collator_candidates::(n, None); - for (i, c) in candidates.iter().enumerate() { - fill_delegators::(m, c.clone(), i.saturated_into::()); - } - let collator = candidates[0].clone(); - - let old = InflationConfig::::get(); - assert_eq!(LastRewardReduction::::get(), T::BlockNumber::zero()); - System::::set_block_number(T::BLOCKS_PER_YEAR + T::BlockNumber::one()); - }: _(RawOrigin::Signed(collator)) - verify { - let new = InflationConfig::::get(); - assert_eq!(LastRewardReduction::::get(), T::BlockNumber::one()); - assert_eq!(new.collator.max_rate, old.collator.max_rate); - assert_eq!(new.delegator.max_rate, old.delegator.max_rate); - assert!(new.collator.reward_rate.annual < old.collator.reward_rate.annual); - assert!(new.delegator.reward_rate.annual < old.delegator.reward_rate.annual); - } - -} - -impl_benchmark_test_suite!( - Pallet, - crate::mock::ExtBuilder::default() - .with_balances(vec![(u64::MAX, 1000 * crate::mock::MILLI_KILT)]) - .with_collators(vec![(u64::MAX, 1000 * crate::mock::MILLI_KILT)]) - .build(), - crate::mock::Test, -); diff --git a/pallets/parachain-staking/src/default_weights.rs b/pallets/parachain-staking/src/default_weights.rs deleted file mode 100644 index aeb1d1081..000000000 --- a/pallets/parachain-staking/src/default_weights.rs +++ /dev/null @@ -1,843 +0,0 @@ -// KILT Blockchain – https://botlabs.org -// Copyright (C) 2019-2023 BOTLabs GmbH - -// The KILT Blockchain 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. - -// The KILT Blockchain 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 this program. If not, see . - -// If you feel like getting in touch with us, you can do so at info@botlabs.org - -//! Autogenerated weights for parachain_staking -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-02-01, STEPS: {{cmd.steps}}\, REPEAT: {{cmd.repeat}}\, LOW RANGE: {{cmd.lowest_range_values}}\, HIGH RANGE: {{cmd.highest_range_values}}\ -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 - -// Executed Command: -// ./target/release/kilt-parachain -// benchmark -// pallet -// --chain=dev -// --steps=50 -// --repeat=20 -// --pallet=parachain-staking -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./pallets/parachain-staking/src/default_weights.rs -// --template=.maintain/weight-template.hbs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(clippy::unnecessary_cast)] - -use frame_support::{traits::Get, weights::{constants::RocksDbWeight, Weight}}; -use sp_std::marker::PhantomData; - -/// Weight functions needed for parachain_staking. -pub trait WeightInfo { - fn on_initialize_no_action() -> Weight; - fn on_initialize_round_update() -> Weight; - fn on_initialize_network_rewards() -> Weight; - fn force_new_round() -> Weight; - fn set_inflation(n: u32, m: u32, ) -> Weight; - fn set_max_selected_candidates(n: u32, m: u32, ) -> Weight; - fn set_blocks_per_round() -> Weight; - fn force_remove_candidate(n: u32, m: u32, ) -> Weight; - fn join_candidates(n: u32, m: u32, ) -> Weight; - fn init_leave_candidates(n: u32, m: u32, ) -> Weight; - fn cancel_leave_candidates(n: u32, m: u32, ) -> Weight; - fn execute_leave_candidates(n: u32, m: u32, ) -> Weight; - fn candidate_stake_more(n: u32, m: u32, u: u32, ) -> Weight; - fn candidate_stake_less(n: u32, m: u32, ) -> Weight; - fn join_delegators(n: u32, m: u32, ) -> Weight; - fn delegator_stake_more(n: u32, m: u32, u: u32, ) -> Weight; - fn delegator_stake_less(n: u32, m: u32, ) -> Weight; - fn leave_delegators(n: u32, m: u32, ) -> Weight; - fn unlock_unstaked(u: u32, ) -> Weight; - fn set_max_candidate_stake() -> Weight; - fn increment_delegator_rewards() -> Weight; - fn increment_collator_rewards() -> Weight; - fn claim_rewards() -> Weight; - fn execute_scheduled_reward_change(n: u32, m: u32, ) -> Weight; -} - -/// Weights for parachain_staking using the Substrate node and recommended hardware. -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - // Storage: ParachainStaking Round (r:1 w:0) - fn on_initialize_no_action() -> Weight { - Weight::from_ref_time(7_295_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - } - // Storage: ParachainStaking Round (r:1 w:1) - fn on_initialize_round_update() -> Weight { - Weight::from_ref_time(20_334_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking Round (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: System Account (r:1 w:1) - fn on_initialize_network_rewards() -> Weight { - Weight::from_ref_time(53_479_000 as u64) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking ForceNewRound (r:0 w:1) - fn force_new_round() -> Weight { - Weight::from_ref_time(15_272_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking CandidatePool (r:3 w:0) - // Storage: ParachainStaking BlocksAuthored (r:2 w:0) - // Storage: ParachainStaking BlocksRewarded (r:72 w:72) - // Storage: ParachainStaking Rewards (r:72 w:72) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) - // Storage: ParachainStaking InflationConfig (r:1 w:1) - // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) - /// The range of component `n` is `[0, 75]`. - /// The range of component `m` is `[0, 35]`. - fn set_inflation(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(880_206_000 as u64) - // Standard Error: 5_316_702 - .saturating_add(Weight::from_ref_time(170_934_184 as u64).saturating_mul(n as u64)) - // Standard Error: 11_414_842 - .saturating_add(Weight::from_ref_time(326_552_012 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(152 as u64)) - .saturating_add(T::DbWeight::get().reads((27 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().reads((51 as u64).saturating_mul(m as u64))) - .saturating_add(T::DbWeight::get().writes(145 as u64)) - .saturating_add(T::DbWeight::get().writes((25 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes((51 as u64).saturating_mul(m as u64))) - } - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:0) - /// The range of component `n` is `[16, 75]`. - /// The range of component `m` is `[0, 35]`. - fn set_max_selected_candidates(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(71_790_000 as u64) - // Standard Error: 27_483 - .saturating_add(Weight::from_ref_time(3_582_143 as u64).saturating_mul(n as u64)) - // Standard Error: 60_832 - .saturating_add(Weight::from_ref_time(349_083 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking Round (r:1 w:1) - fn set_blocks_per_round() -> Weight { - Weight::from_ref_time(56_977_000 as u64) - .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking CandidatePool (r:17 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking BlocksAuthored (r:1 w:1) - // Storage: ParachainStaking BlocksRewarded (r:36 w:36) - // Storage: ParachainStaking Rewards (r:36 w:36) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - // Storage: ParachainStaking Unstaking (r:36 w:36) - // Storage: ParachainStaking DelegatorState (r:35 w:35) - // Storage: Session Validators (r:1 w:0) - // Storage: Session DisabledValidators (r:1 w:1) - // Storage: System Digest (r:1 w:1) - // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - /// The range of component `n` is `[17, 75]`. - /// The range of component `m` is `[0, 35]`. - fn force_remove_candidate(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(167_630_000 as u64) - // Standard Error: 33_915 - .saturating_add(Weight::from_ref_time(1_267_282 as u64).saturating_mul(n as u64)) - // Standard Error: 75_237 - .saturating_add(Weight::from_ref_time(32_352_601 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(29 as u64)) - .saturating_add(T::DbWeight::get().reads((4 as u64).saturating_mul(m as u64))) - .saturating_add(T::DbWeight::get().writes(10 as u64)) - .saturating_add(T::DbWeight::get().writes((4 as u64).saturating_mul(m as u64))) - } - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:0) - // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) - /// The range of component `n` is `[1, 74]`. - /// The range of component `m` is `[0, 35]`. - fn join_candidates(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(74_868_992 as u64) - // Standard Error: 15_510 - .saturating_add(Weight::from_ref_time(844_907 as u64).saturating_mul(n as u64)) - // Standard Error: 32_208 - .saturating_add(Weight::from_ref_time(1_664_228 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(10 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) - } - // Storage: ParachainStaking CandidatePool (r:17 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking Round (r:1 w:0) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - /// The range of component `n` is `[17, 74]`. - /// The range of component `m` is `[0, 35]`. - fn init_leave_candidates(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(102_892_381 as u64) - // Standard Error: 15_634 - .saturating_add(Weight::from_ref_time(884_087 as u64).saturating_mul(n as u64)) - // Standard Error: 25_354 - .saturating_add(Weight::from_ref_time(1_951_960 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(21 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - } - // Storage: ParachainStaking CandidatePool (r:2 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - /// The range of component `n` is `[17, 74]`. - /// The range of component `m` is `[0, 35]`. - fn cancel_leave_candidates(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(62_163_088 as u64) - // Standard Error: 11_849 - .saturating_add(Weight::from_ref_time(470_670 as u64).saturating_mul(n as u64)) - // Standard Error: 19_216 - .saturating_add(Weight::from_ref_time(1_150_199 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(5 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - } - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Round (r:1 w:0) - // Storage: ParachainStaking BlocksAuthored (r:1 w:1) - // Storage: ParachainStaking BlocksRewarded (r:36 w:36) - // Storage: ParachainStaking Rewards (r:36 w:36) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - // Storage: ParachainStaking Unstaking (r:36 w:36) - // Storage: ParachainStaking DelegatorState (r:35 w:35) - // Storage: Session Validators (r:1 w:0) - // Storage: Session DisabledValidators (r:1 w:1) - // Storage: System Digest (r:1 w:1) - // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) - /// The range of component `n` is `[17, 74]`. - /// The range of component `m` is `[0, 35]`. - fn execute_leave_candidates(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(101_532_000 as u64) - // Standard Error: 33_213 - .saturating_add(Weight::from_ref_time(1_131_850 as u64).saturating_mul(n as u64)) - // Standard Error: 72_738 - .saturating_add(Weight::from_ref_time(32_258_326 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(12 as u64)) - .saturating_add(T::DbWeight::get().reads((4 as u64).saturating_mul(m as u64))) - .saturating_add(T::DbWeight::get().writes(8 as u64)) - .saturating_add(T::DbWeight::get().writes((4 as u64).saturating_mul(m as u64))) - } - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking BlocksAuthored (r:1 w:0) - // Storage: ParachainStaking BlocksRewarded (r:1 w:1) - // Storage: ParachainStaking Rewards (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - /// The range of component `n` is `[1, 74]`. - /// The range of component `m` is `[0, 35]`. - /// The range of component `u` is `[0, 9]`. - fn candidate_stake_more(n: u32, m: u32, u: u32) -> Weight { - Weight::from_ref_time(71_965_734 as u64) - // Standard Error: 13_893 - .saturating_add(Weight::from_ref_time(925_357 as u64).saturating_mul(n as u64)) - // Standard Error: 28_840 - .saturating_add(Weight::from_ref_time(1_887_704 as u64).saturating_mul(m as u64)) - // Standard Error: 106_831 - .saturating_add(Weight::from_ref_time(1_865_718 as u64).saturating_mul(u as u64)) - .saturating_add(T::DbWeight::get().reads(12 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) - } - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking BlocksAuthored (r:1 w:0) - // Storage: ParachainStaking BlocksRewarded (r:1 w:1) - // Storage: ParachainStaking Rewards (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - /// The range of component `n` is `[1, 74]`. - /// The range of component `m` is `[0, 35]`. - fn candidate_stake_less(n: u32, m: u32) -> Weight { - Weight::from_ref_time(62_739_612 as u64) - // Standard Error: 16_793 - .saturating_add(Weight::from_ref_time(864_759 as u64).saturating_mul(n as u64)) - // Standard Error: 34_871 - .saturating_add(Weight::from_ref_time(1_709_617 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) - } - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:2 w:1) - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: ParachainStaking LastDelegation (r:1 w:1) - // Storage: ParachainStaking Round (r:1 w:0) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking BlocksAuthored (r:1 w:0) - // Storage: ParachainStaking BlocksRewarded (r:0 w:1) - /// The range of component `n` is `[1, 75]`. - /// The range of component `m` is `[1, 34]`. - fn join_delegators(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(77_485_243 as u64) - // Standard Error: 14_703 - .saturating_add(Weight::from_ref_time(1_058_123 as u64).saturating_mul(n as u64)) - // Standard Error: 32_678 - .saturating_add(Weight::from_ref_time(2_182_817 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(12 as u64)) - .saturating_add(T::DbWeight::get().writes(9 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking BlocksAuthored (r:1 w:0) - // Storage: ParachainStaking BlocksRewarded (r:1 w:1) - // Storage: ParachainStaking Rewards (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - /// The range of component `n` is `[1, 75]`. - /// The range of component `m` is `[1, 34]`. - /// The range of component `u` is `[1, 9]`. - fn delegator_stake_more(n: u32, m: u32, u: u32) -> Weight { - Weight::from_ref_time(82_500_737 as u64) - // Standard Error: 12_571 - .saturating_add(Weight::from_ref_time(971_252 as u64).saturating_mul(n as u64)) - // Standard Error: 27_929 - .saturating_add(Weight::from_ref_time(1_947_599 as u64).saturating_mul(m as u64)) - // Standard Error: 108_324 - .saturating_add(Weight::from_ref_time(1_782_476 as u64).saturating_mul(u as u64)) - .saturating_add(T::DbWeight::get().reads(12 as u64)) - .saturating_add(T::DbWeight::get().writes(9 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking BlocksAuthored (r:1 w:0) - // Storage: ParachainStaking BlocksRewarded (r:1 w:1) - // Storage: ParachainStaking Rewards (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - /// The range of component `n` is `[1, 75]`. - /// The range of component `m` is `[1, 34]`. - fn delegator_stake_less(n: u32, m: u32) -> Weight { - Weight::from_ref_time(72_772_464 as u64) - // Standard Error: 14_214 - .saturating_add(Weight::from_ref_time(909_175 as u64).saturating_mul(n as u64)) - // Standard Error: 31_591 - .saturating_add(Weight::from_ref_time(1_824_513 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(10 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking BlocksAuthored (r:1 w:0) - // Storage: ParachainStaking BlocksRewarded (r:1 w:1) - // Storage: ParachainStaking Rewards (r:1 w:1) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - /// The range of component `n` is `[1, 75]`. - /// The range of component `m` is `[1, 34]`. - fn leave_delegators(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(80_275_828 as u64) - // Standard Error: 14_671 - .saturating_add(Weight::from_ref_time(913_421 as u64).saturating_mul(n as u64)) - // Standard Error: 32_607 - .saturating_add(Weight::from_ref_time(1_764_476 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(10 as u64)) - .saturating_add(T::DbWeight::get().writes(7 as u64)) - } - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - /// The range of component `u` is `[1, 9]`. - fn unlock_unstaked(u: u32, ) -> Weight { - Weight::from_ref_time(53_730_996 as u64) - // Standard Error: 18_906 - .saturating_add(Weight::from_ref_time(410_777 as u64).saturating_mul(u as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - } - // Storage: ParachainStaking MaxCollatorCandidateStake (r:0 w:1) - fn set_max_candidate_stake() -> Weight { - Weight::from_ref_time(43_109_000 as u64) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:0) - // Storage: ParachainStaking BlocksAuthored (r:1 w:0) - // Storage: ParachainStaking BlocksRewarded (r:1 w:1) - // Storage: ParachainStaking Rewards (r:1 w:1) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - fn increment_delegator_rewards() -> Weight { - Weight::from_ref_time(40_000_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking CandidatePool (r:1 w:0) - // Storage: ParachainStaking BlocksAuthored (r:1 w:0) - // Storage: ParachainStaking BlocksRewarded (r:1 w:1) - // Storage: ParachainStaking Rewards (r:1 w:1) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - fn increment_collator_rewards() -> Weight { - Weight::from_ref_time(35_612_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking Rewards (r:1 w:1) - // Storage: System Account (r:1 w:1) - fn claim_rewards() -> Weight { - Weight::from_ref_time(54_273_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking LastRewardReduction (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:3 w:0) - // Storage: ParachainStaking BlocksAuthored (r:2 w:0) - // Storage: ParachainStaking BlocksRewarded (r:72 w:72) - // Storage: ParachainStaking Rewards (r:72 w:72) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) - // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) - /// The range of component `n` is `[0, 75]`. - /// The range of component `m` is `[0, 35]`. - fn execute_scheduled_reward_change(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(869_446_000 as u64) - // Standard Error: 5_211_771 - .saturating_add(Weight::from_ref_time(166_314_407 as u64).saturating_mul(n as u64)) - // Standard Error: 11_189_560 - .saturating_add(Weight::from_ref_time(321_504_163 as u64).saturating_mul(m as u64)) - .saturating_add(T::DbWeight::get().reads(153 as u64)) - .saturating_add(T::DbWeight::get().reads((27 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().reads((51 as u64).saturating_mul(m as u64))) - .saturating_add(T::DbWeight::get().writes(146 as u64)) - .saturating_add(T::DbWeight::get().writes((25 as u64).saturating_mul(n as u64))) - .saturating_add(T::DbWeight::get().writes((51 as u64).saturating_mul(m as u64))) - } -} - -// For backwards compatibility and tests -impl WeightInfo for () { - // Storage: ParachainStaking Round (r:1 w:0) - fn on_initialize_no_action() -> Weight { - Weight::from_ref_time(7_295_000 as u64) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - } - // Storage: ParachainStaking Round (r:1 w:1) - fn on_initialize_round_update() -> Weight { - Weight::from_ref_time(20_334_000 as u64) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking Round (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: System Account (r:1 w:1) - fn on_initialize_network_rewards() -> Weight { - Weight::from_ref_time(53_479_000 as u64) - .saturating_add(RocksDbWeight::get().reads(5 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking ForceNewRound (r:0 w:1) - fn force_new_round() -> Weight { - Weight::from_ref_time(15_272_000 as u64) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking CandidatePool (r:3 w:0) - // Storage: ParachainStaking BlocksAuthored (r:2 w:0) - // Storage: ParachainStaking BlocksRewarded (r:72 w:72) - // Storage: ParachainStaking Rewards (r:72 w:72) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) - // Storage: ParachainStaking InflationConfig (r:1 w:1) - // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) - /// The range of component `n` is `[0, 75]`. - /// The range of component `m` is `[0, 35]`. - fn set_inflation(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(880_206_000 as u64) - // Standard Error: 5_316_702 - .saturating_add(Weight::from_ref_time(170_934_184 as u64).saturating_mul(n as u64)) - // Standard Error: 11_414_842 - .saturating_add(Weight::from_ref_time(326_552_012 as u64).saturating_mul(m as u64)) - .saturating_add(RocksDbWeight::get().reads(152 as u64)) - .saturating_add(RocksDbWeight::get().reads((27 as u64).saturating_mul(n as u64))) - .saturating_add(RocksDbWeight::get().reads((51 as u64).saturating_mul(m as u64))) - .saturating_add(RocksDbWeight::get().writes(145 as u64)) - .saturating_add(RocksDbWeight::get().writes((25 as u64).saturating_mul(n as u64))) - .saturating_add(RocksDbWeight::get().writes((51 as u64).saturating_mul(m as u64))) - } - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:0) - /// The range of component `n` is `[16, 75]`. - /// The range of component `m` is `[0, 35]`. - fn set_max_selected_candidates(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(71_790_000 as u64) - // Standard Error: 27_483 - .saturating_add(Weight::from_ref_time(3_582_143 as u64).saturating_mul(n as u64)) - // Standard Error: 60_832 - .saturating_add(Weight::from_ref_time(349_083 as u64).saturating_mul(m as u64)) - .saturating_add(RocksDbWeight::get().reads(3 as u64)) - .saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(n as u64))) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking Round (r:1 w:1) - fn set_blocks_per_round() -> Weight { - Weight::from_ref_time(56_977_000 as u64) - .saturating_add(RocksDbWeight::get().reads(1 as u64)) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking CandidatePool (r:17 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking BlocksAuthored (r:1 w:1) - // Storage: ParachainStaking BlocksRewarded (r:36 w:36) - // Storage: ParachainStaking Rewards (r:36 w:36) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - // Storage: ParachainStaking Unstaking (r:36 w:36) - // Storage: ParachainStaking DelegatorState (r:35 w:35) - // Storage: Session Validators (r:1 w:0) - // Storage: Session DisabledValidators (r:1 w:1) - // Storage: System Digest (r:1 w:1) - // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - /// The range of component `n` is `[17, 75]`. - /// The range of component `m` is `[0, 35]`. - fn force_remove_candidate(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(167_630_000 as u64) - // Standard Error: 33_915 - .saturating_add(Weight::from_ref_time(1_267_282 as u64).saturating_mul(n as u64)) - // Standard Error: 75_237 - .saturating_add(Weight::from_ref_time(32_352_601 as u64).saturating_mul(m as u64)) - .saturating_add(RocksDbWeight::get().reads(29 as u64)) - .saturating_add(RocksDbWeight::get().reads((4 as u64).saturating_mul(m as u64))) - .saturating_add(RocksDbWeight::get().writes(10 as u64)) - .saturating_add(RocksDbWeight::get().writes((4 as u64).saturating_mul(m as u64))) - } - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:0) - // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) - /// The range of component `n` is `[1, 74]`. - /// The range of component `m` is `[0, 35]`. - fn join_candidates(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(74_868_992 as u64) - // Standard Error: 15_510 - .saturating_add(Weight::from_ref_time(844_907 as u64).saturating_mul(n as u64)) - // Standard Error: 32_208 - .saturating_add(Weight::from_ref_time(1_664_228 as u64).saturating_mul(m as u64)) - .saturating_add(RocksDbWeight::get().reads(10 as u64)) - .saturating_add(RocksDbWeight::get().writes(7 as u64)) - } - // Storage: ParachainStaking CandidatePool (r:17 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking Round (r:1 w:0) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - /// The range of component `n` is `[17, 74]`. - /// The range of component `m` is `[0, 35]`. - fn init_leave_candidates(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(102_892_381 as u64) - // Standard Error: 15_634 - .saturating_add(Weight::from_ref_time(884_087 as u64).saturating_mul(n as u64)) - // Standard Error: 25_354 - .saturating_add(Weight::from_ref_time(1_951_960 as u64).saturating_mul(m as u64)) - .saturating_add(RocksDbWeight::get().reads(21 as u64)) - .saturating_add(RocksDbWeight::get().writes(3 as u64)) - } - // Storage: ParachainStaking CandidatePool (r:2 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - /// The range of component `n` is `[17, 74]`. - /// The range of component `m` is `[0, 35]`. - fn cancel_leave_candidates(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(62_163_088 as u64) - // Standard Error: 11_849 - .saturating_add(Weight::from_ref_time(470_670 as u64).saturating_mul(n as u64)) - // Standard Error: 19_216 - .saturating_add(Weight::from_ref_time(1_150_199 as u64).saturating_mul(m as u64)) - .saturating_add(RocksDbWeight::get().reads(5 as u64)) - .saturating_add(RocksDbWeight::get().writes(3 as u64)) - } - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Round (r:1 w:0) - // Storage: ParachainStaking BlocksAuthored (r:1 w:1) - // Storage: ParachainStaking BlocksRewarded (r:36 w:36) - // Storage: ParachainStaking Rewards (r:36 w:36) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - // Storage: ParachainStaking Unstaking (r:36 w:36) - // Storage: ParachainStaking DelegatorState (r:35 w:35) - // Storage: Session Validators (r:1 w:0) - // Storage: Session DisabledValidators (r:1 w:1) - // Storage: System Digest (r:1 w:1) - // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) - /// The range of component `n` is `[17, 74]`. - /// The range of component `m` is `[0, 35]`. - fn execute_leave_candidates(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(101_532_000 as u64) - // Standard Error: 33_213 - .saturating_add(Weight::from_ref_time(1_131_850 as u64).saturating_mul(n as u64)) - // Standard Error: 72_738 - .saturating_add(Weight::from_ref_time(32_258_326 as u64).saturating_mul(m as u64)) - .saturating_add(RocksDbWeight::get().reads(12 as u64)) - .saturating_add(RocksDbWeight::get().reads((4 as u64).saturating_mul(m as u64))) - .saturating_add(RocksDbWeight::get().writes(8 as u64)) - .saturating_add(RocksDbWeight::get().writes((4 as u64).saturating_mul(m as u64))) - } - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking BlocksAuthored (r:1 w:0) - // Storage: ParachainStaking BlocksRewarded (r:1 w:1) - // Storage: ParachainStaking Rewards (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - /// The range of component `n` is `[1, 74]`. - /// The range of component `m` is `[0, 35]`. - /// The range of component `u` is `[0, 9]`. - fn candidate_stake_more(n: u32, m: u32, u: u32) -> Weight { - Weight::from_ref_time(71_965_734 as u64) - // Standard Error: 13_893 - .saturating_add(Weight::from_ref_time(925_357 as u64).saturating_mul(n as u64)) - // Standard Error: 28_840 - .saturating_add(Weight::from_ref_time(1_887_704 as u64).saturating_mul(m as u64)) - // Standard Error: 106_831 - .saturating_add(Weight::from_ref_time(1_865_718 as u64).saturating_mul(u as u64)) - .saturating_add(RocksDbWeight::get().reads(12 as u64)) - .saturating_add(RocksDbWeight::get().writes(8 as u64)) - } - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking BlocksAuthored (r:1 w:0) - // Storage: ParachainStaking BlocksRewarded (r:1 w:1) - // Storage: ParachainStaking Rewards (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - /// The range of component `n` is `[1, 74]`. - /// The range of component `m` is `[0, 35]`. - fn candidate_stake_less(n: u32, m: u32) -> Weight { - Weight::from_ref_time(62_739_612 as u64) - // Standard Error: 16_793 - .saturating_add(Weight::from_ref_time(864_759 as u64).saturating_mul(n as u64)) - // Standard Error: 34_871 - .saturating_add(Weight::from_ref_time(1_709_617 as u64).saturating_mul(m as u64)) - .saturating_add(RocksDbWeight::get().reads(9 as u64)) - .saturating_add(RocksDbWeight::get().writes(6 as u64)) - } - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:2 w:1) - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: ParachainStaking LastDelegation (r:1 w:1) - // Storage: ParachainStaking Round (r:1 w:0) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking BlocksAuthored (r:1 w:0) - // Storage: ParachainStaking BlocksRewarded (r:0 w:1) - /// The range of component `n` is `[1, 75]`. - /// The range of component `m` is `[1, 34]`. - fn join_delegators(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(77_485_243 as u64) - // Standard Error: 14_703 - .saturating_add(Weight::from_ref_time(1_058_123 as u64).saturating_mul(n as u64)) - // Standard Error: 32_678 - .saturating_add(Weight::from_ref_time(2_182_817 as u64).saturating_mul(m as u64)) - .saturating_add(RocksDbWeight::get().reads(12 as u64)) - .saturating_add(RocksDbWeight::get().writes(9 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: System Account (r:1 w:1) - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking BlocksAuthored (r:1 w:0) - // Storage: ParachainStaking BlocksRewarded (r:1 w:1) - // Storage: ParachainStaking Rewards (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - /// The range of component `n` is `[1, 75]`. - /// The range of component `m` is `[1, 34]`. - /// The range of component `u` is `[1, 9]`. - fn delegator_stake_more(n: u32, m: u32, u: u32) -> Weight { - Weight::from_ref_time(82_500_737 as u64) - // Standard Error: 12_571 - .saturating_add(Weight::from_ref_time(971_252 as u64).saturating_mul(n as u64)) - // Standard Error: 27_929 - .saturating_add(Weight::from_ref_time(1_947_599 as u64).saturating_mul(m as u64)) - // Standard Error: 108_324 - .saturating_add(Weight::from_ref_time(1_782_476 as u64).saturating_mul(u as u64)) - .saturating_add(RocksDbWeight::get().reads(12 as u64)) - .saturating_add(RocksDbWeight::get().writes(9 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking BlocksAuthored (r:1 w:0) - // Storage: ParachainStaking BlocksRewarded (r:1 w:1) - // Storage: ParachainStaking Rewards (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - /// The range of component `n` is `[1, 75]`. - /// The range of component `m` is `[1, 34]`. - fn delegator_stake_less(n: u32, m: u32) -> Weight { - Weight::from_ref_time(72_772_464 as u64) - // Standard Error: 14_214 - .saturating_add(Weight::from_ref_time(909_175 as u64).saturating_mul(n as u64)) - // Standard Error: 31_591 - .saturating_add(Weight::from_ref_time(1_824_513 as u64).saturating_mul(m as u64)) - .saturating_add(RocksDbWeight::get().reads(10 as u64)) - .saturating_add(RocksDbWeight::get().writes(7 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:1 w:1) - // Storage: ParachainStaking BlocksAuthored (r:1 w:0) - // Storage: ParachainStaking BlocksRewarded (r:1 w:1) - // Storage: ParachainStaking Rewards (r:1 w:1) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: ParachainStaking TopCandidates (r:1 w:1) - // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) - /// The range of component `n` is `[1, 75]`. - /// The range of component `m` is `[1, 34]`. - fn leave_delegators(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(80_275_828 as u64) - // Standard Error: 14_671 - .saturating_add(Weight::from_ref_time(913_421 as u64).saturating_mul(n as u64)) - // Standard Error: 32_607 - .saturating_add(Weight::from_ref_time(1_764_476 as u64).saturating_mul(m as u64)) - .saturating_add(RocksDbWeight::get().reads(10 as u64)) - .saturating_add(RocksDbWeight::get().writes(7 as u64)) - } - // Storage: ParachainStaking Unstaking (r:1 w:1) - // Storage: Balances Locks (r:1 w:1) - // Storage: System Account (r:1 w:1) - /// The range of component `u` is `[1, 9]`. - fn unlock_unstaked(u: u32, ) -> Weight { - Weight::from_ref_time(53_730_996 as u64) - // Standard Error: 18_906 - .saturating_add(Weight::from_ref_time(410_777 as u64).saturating_mul(u as u64)) - .saturating_add(RocksDbWeight::get().reads(3 as u64)) - .saturating_add(RocksDbWeight::get().writes(3 as u64)) - } - // Storage: ParachainStaking MaxCollatorCandidateStake (r:0 w:1) - fn set_max_candidate_stake() -> Weight { - Weight::from_ref_time(43_109_000 as u64) - .saturating_add(RocksDbWeight::get().writes(1 as u64)) - } - // Storage: ParachainStaking DelegatorState (r:1 w:0) - // Storage: ParachainStaking BlocksAuthored (r:1 w:0) - // Storage: ParachainStaking BlocksRewarded (r:1 w:1) - // Storage: ParachainStaking Rewards (r:1 w:1) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - fn increment_delegator_rewards() -> Weight { - Weight::from_ref_time(40_000_000 as u64) - .saturating_add(RocksDbWeight::get().reads(6 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking CandidatePool (r:1 w:0) - // Storage: ParachainStaking BlocksAuthored (r:1 w:0) - // Storage: ParachainStaking BlocksRewarded (r:1 w:1) - // Storage: ParachainStaking Rewards (r:1 w:1) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) - // Storage: ParachainStaking InflationConfig (r:1 w:0) - fn increment_collator_rewards() -> Weight { - Weight::from_ref_time(35_612_000 as u64) - .saturating_add(RocksDbWeight::get().reads(6 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking Rewards (r:1 w:1) - // Storage: System Account (r:1 w:1) - fn claim_rewards() -> Weight { - Weight::from_ref_time(54_273_000 as u64) - .saturating_add(RocksDbWeight::get().reads(2 as u64)) - .saturating_add(RocksDbWeight::get().writes(2 as u64)) - } - // Storage: ParachainStaking LastRewardReduction (r:1 w:1) - // Storage: ParachainStaking InflationConfig (r:1 w:1) - // Storage: ParachainStaking CandidatePool (r:3 w:0) - // Storage: ParachainStaking BlocksAuthored (r:2 w:0) - // Storage: ParachainStaking BlocksRewarded (r:72 w:72) - // Storage: ParachainStaking Rewards (r:72 w:72) - // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) - // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) - /// The range of component `n` is `[0, 75]`. - /// The range of component `m` is `[0, 35]`. - fn execute_scheduled_reward_change(n: u32, m: u32, ) -> Weight { - Weight::from_ref_time(869_446_000 as u64) - // Standard Error: 5_211_771 - .saturating_add(Weight::from_ref_time(166_314_407 as u64).saturating_mul(n as u64)) - // Standard Error: 11_189_560 - .saturating_add(Weight::from_ref_time(321_504_163 as u64).saturating_mul(m as u64)) - .saturating_add(RocksDbWeight::get().reads(153 as u64)) - .saturating_add(RocksDbWeight::get().reads((27 as u64).saturating_mul(n as u64))) - .saturating_add(RocksDbWeight::get().reads((51 as u64).saturating_mul(m as u64))) - .saturating_add(RocksDbWeight::get().writes(146 as u64)) - .saturating_add(RocksDbWeight::get().writes((25 as u64).saturating_mul(n as u64))) - .saturating_add(RocksDbWeight::get().writes((51 as u64).saturating_mul(m as u64))) - } -} diff --git a/pallets/parachain-staking/src/inflation.rs b/pallets/parachain-staking/src/inflation.rs deleted file mode 100644 index 170e4d89c..000000000 --- a/pallets/parachain-staking/src/inflation.rs +++ /dev/null @@ -1,384 +0,0 @@ -// KILT Blockchain – https://botlabs.org -// Copyright (C) 2019-2023 BOTLabs GmbH - -// The KILT Blockchain 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. - -// The KILT Blockchain 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 this program. If not, see . - -// If you feel like getting in touch with us, you can do so at info@botlabs.org - -//! Helper methods for computing issuance based on inflation -use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; -use scale_info::TypeInfo; -#[cfg(feature = "std")] -use serde::{Deserialize, Serialize}; -use sp_runtime::{traits::Saturating, Perquintill, RuntimeDebug}; - -use crate::{pallet::Config, types::BalanceOf}; - -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[derive(Eq, PartialEq, Clone, Encode, Decode, Default, RuntimeDebug, TypeInfo)] -pub struct RewardRate { - pub annual: Perquintill, - pub per_block: Perquintill, -} - -impl MaxEncodedLen for RewardRate { - fn max_encoded_len() -> usize { - // Perquintill is at most u128 - u128::max_encoded_len().saturating_add(u128::max_encoded_len()) - } -} - -/// Convert annual reward rate to per_block. -fn annual_to_per_block(blocks_per_year: u64, rate: Perquintill) -> Perquintill { - rate / blocks_per_year.max(1) -} - -impl RewardRate { - pub fn new(blocks_per_year: u64, rate: Perquintill) -> Self { - RewardRate { - annual: rate, - per_block: annual_to_per_block(blocks_per_year, rate), - } - } -} - -/// Staking info (staking rate and reward rate) for collators and delegators. -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[derive(Eq, PartialEq, Clone, Encode, Decode, Default, RuntimeDebug, TypeInfo)] -pub struct StakingInfo { - /// Maximum staking rate. - pub max_rate: Perquintill, - /// Reward rate annually and per_block. - pub reward_rate: RewardRate, -} - -impl MaxEncodedLen for StakingInfo { - fn max_encoded_len() -> usize { - // Perquintill is at most u128 - RewardRate::max_encoded_len().saturating_add(u128::max_encoded_len()) - } -} - -impl StakingInfo { - pub fn new(blocks_per_year: u64, max_rate: Perquintill, annual_reward_rate: Perquintill) -> Self { - StakingInfo { - max_rate, - reward_rate: RewardRate::new(blocks_per_year, annual_reward_rate), - } - } - - /// Calculate newly minted rewards on coinbase, e.g., - /// reward = rewards_per_block * staking_rate. - /// - /// NOTE: If we exceed the max staking rate, the reward will be reduced by - /// max_rate / current_rate. - pub fn compute_reward( - &self, stake: BalanceOf, current_staking_rate: Perquintill, authors_per_round: BalanceOf, - ) -> BalanceOf { - // Perquintill automatically bounds to [0, 100]% in case staking_rate is greater - // than self.max_rate - let reduction = Perquintill::from_rational(self.max_rate.deconstruct(), current_staking_rate.deconstruct()); - // multiplication with perbill cannot overflow - let reward = (self.reward_rate.per_block * stake).saturating_mul(authors_per_round); - reduction * reward - } -} - -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[derive(Eq, PartialEq, Clone, Encode, Decode, Default, RuntimeDebug, TypeInfo, MaxEncodedLen)] -pub struct InflationInfo { - pub collator: StakingInfo, - pub delegator: StakingInfo, -} - -impl InflationInfo { - /// Create a new inflation info from the max staking rates and annual reward - /// rates for collators and delegators. - /// - /// Example: InflationInfo::new(Perquintill_from_percent(10), ...) - pub fn new( - blocks_per_year: u64, collator_max_rate_percentage: Perquintill, - collator_annual_reward_rate_percentage: Perquintill, delegator_max_rate_percentage: Perquintill, - delegator_annual_reward_rate_percentage: Perquintill, - ) -> Self { - Self { - collator: StakingInfo::new( - blocks_per_year, - collator_max_rate_percentage, - collator_annual_reward_rate_percentage, - ), - delegator: StakingInfo::new( - blocks_per_year, - delegator_max_rate_percentage, - delegator_annual_reward_rate_percentage, - ), - } - } - - /// Check whether the annual reward rate is approx. the per_block reward - /// rate multiplied with the number of blocks per year - pub fn is_valid(&self, blocks_per_year: u64) -> bool { - self.collator.reward_rate.annual - >= Perquintill::from_parts( - self.collator - .reward_rate - .per_block - .deconstruct() - .saturating_mul(blocks_per_year), - ) && self.delegator.reward_rate.annual - >= Perquintill::from_parts( - self.delegator - .reward_rate - .per_block - .deconstruct() - .saturating_mul(blocks_per_year), - ) - } -} - -#[cfg(test)] -mod tests { - use sp_runtime::Perbill; - - use crate::mock::{almost_equal, ExtBuilder, Test, DECIMALS, MAX_COLLATOR_STAKE}; - - use super::*; - - #[test] - fn perquintill() { - assert_eq!( - Perquintill::from_percent(100) * Perquintill::from_percent(50), - Perquintill::from_percent(50) - ); - } - - #[test] - fn annual_to_block_rate() { - let rate = Perquintill::one(); - assert!(almost_equal( - rate * 10_000_000_000u128, - Perquintill::from_parts( - annual_to_per_block(::BLOCKS_PER_YEAR, rate).deconstruct() - * ::BLOCKS_PER_YEAR - ) * 10_000_000_000u128, - Perbill::from_perthousand(1) - )); - } - - #[test] - fn single_block_reward_collator() { - let inflation = InflationInfo::new( - ::BLOCKS_PER_YEAR, - Perquintill::from_percent(10), - Perquintill::from_percent(10), - Perquintill::from_percent(40), - Perquintill::from_percent(8), - ); - let reward = inflation - .collator - .compute_reward::(MAX_COLLATOR_STAKE, Perquintill::from_percent(9), 2); - let expected = ::CurrencyBalance::from(15210282150733u64); - assert!( - almost_equal(reward, expected, Perbill::from_perthousand(1)), - "left {:?}, right {:?}", - reward, - expected - ); - } - - #[test] - fn simple_block_reward_check() { - let precision = Perbill::from_perthousand(1); - ExtBuilder::default() - .with_inflation(10, 15, 40, 10, 5) - .with_balances(vec![(1, 10)]) - .with_collators(vec![(1, 10)]) - .build() - .execute_with(|| { - let inflation = InflationInfo::new( - ::BLOCKS_PER_YEAR, - Perquintill::from_percent(10), - Perquintill::from_percent(15), - Perquintill::from_percent(40), - Perquintill::from_percent(10), - ); - let years_u128: BalanceOf = ::BLOCKS_PER_YEAR as u128; - - // Dummy checks for correct instantiation - assert!(inflation.is_valid(::BLOCKS_PER_YEAR)); - assert_eq!(inflation.collator.max_rate, Perquintill::from_percent(10)); - assert_eq!(inflation.collator.reward_rate.annual, Perquintill::from_percent(15)); - assert!( - almost_equal( - inflation.collator.reward_rate.per_block * DECIMALS * 10_000, - Perquintill::from_percent(15) * 10_000 * DECIMALS / years_u128, - precision - ), - "left = {:?}, right = {:?}", - inflation.collator.reward_rate.per_block * 10_000 * DECIMALS, - Perquintill::from_percent(15) * 10_000 * DECIMALS / years_u128, - ); - assert_eq!(inflation.delegator.max_rate, Perquintill::from_percent(40)); - assert_eq!(inflation.delegator.reward_rate.annual, Perquintill::from_percent(10)); - assert!( - almost_equal( - inflation.delegator.reward_rate.per_block * DECIMALS * 10_000, - Perquintill::from_percent(10) * 10_000 * DECIMALS / years_u128, - precision - ), - "left = {:?}, right = {:?}", - inflation.delegator.reward_rate.per_block * DECIMALS * 10_000, - Perquintill::from_percent(10) * 10_000 * DECIMALS / years_u128, - ); - - // Check collator reward computation - let authors_per_round = 1u128; - let mut current_staking_rate: Perquintill = inflation.collator.max_rate; - assert_eq!( - inflation - .collator - .compute_reward::(0, current_staking_rate, authors_per_round), - 0 - ); - current_staking_rate = Perquintill::from_rational(5000u64, 100_000u64); - assert!( - almost_equal( - inflation.collator.compute_reward::( - 5000 * DECIMALS, - current_staking_rate, - authors_per_round - ) * years_u128, - Perquintill::from_percent(15) * 5000 * DECIMALS, - Perbill::from_percent(1) - ), - "left = {:?}, right = {:?}", - inflation - .collator - .compute_reward::(5000 * DECIMALS, current_staking_rate, authors_per_round) - * years_u128, - Perquintill::from_percent(15) * 5000 * DECIMALS, - ); - // Check for max_rate which is 10% - current_staking_rate = Perquintill::from_rational(10_000u64, 100_000u64); - assert!( - almost_equal( - inflation.collator.compute_reward::( - 10_000 * DECIMALS, - current_staking_rate, - authors_per_round - ) * years_u128, - Perquintill::from_percent(15) * 10_000 * DECIMALS, - Perbill::from_percent(1) - ), - "left = {:?}, right = {:?}", - inflation.collator.compute_reward::( - 10_000 * DECIMALS, - current_staking_rate, - authors_per_round - ) * years_u128, - Perquintill::from_percent(15) * 10_000 * DECIMALS, - ); - - // Check for exceeding max_rate: 50% instead of 10% - current_staking_rate = Perquintill::from_rational(50_000u64, 100_000u64); - assert!( - almost_equal( - inflation.collator.compute_reward::( - 50_000 * DECIMALS, - current_staking_rate, - authors_per_round - ) * years_u128, - Perquintill::from_percent(15) * 10_000 * DECIMALS, - Perbill::from_percent(1) - ), - "left = {:?}, right = {:?}", - inflation.collator.compute_reward::( - 50_000 * DECIMALS, - current_staking_rate, - authors_per_round - ) * years_u128, - Perquintill::from_percent(15) * 10_000 * DECIMALS, - ); - - // Check delegator reward computation - current_staking_rate = inflation.delegator.max_rate; - assert_eq!( - inflation - .delegator - .compute_reward::(0, current_staking_rate, authors_per_round), - 0 - ); - current_staking_rate = Perquintill::from_rational(5000u64, 100_000u64); - assert!( - almost_equal( - inflation.delegator.compute_reward::( - 5000 * DECIMALS, - current_staking_rate, - authors_per_round - ) * years_u128, - Perquintill::from_percent(10) * 5000 * DECIMALS, - Perbill::from_percent(1) - ), - "left = {:?}, right = {:?}", - inflation.delegator.compute_reward::( - 5000 * DECIMALS, - current_staking_rate, - authors_per_round - ) * years_u128, - Perquintill::from_percent(10) * 5000 * DECIMALS, - ); - // Check for max_rate which is 40% - current_staking_rate = Perquintill::from_rational(40_000u64, 100_000u64); - assert!( - almost_equal( - inflation.delegator.compute_reward::( - 40_000 * DECIMALS, - current_staking_rate, - authors_per_round - ) * years_u128, - Perquintill::from_percent(10) * 40_000 * DECIMALS, - Perbill::from_percent(1) - ), - "left = {:?}, right = {:?}", - inflation.delegator.compute_reward::( - 40_000 * DECIMALS, - current_staking_rate, - authors_per_round - ) * years_u128, - Perquintill::from_percent(10) * 40_000 * DECIMALS, - ); - - // Check for exceeding max_rate: 50% instead of 40% - current_staking_rate = Perquintill::from_rational(50_000u64, 100_000u64); - assert!( - almost_equal( - inflation.delegator.compute_reward::( - 50_000 * DECIMALS, - current_staking_rate, - authors_per_round - ) * years_u128, - Perquintill::from_percent(8) * 50_000 * DECIMALS, - Perbill::from_percent(1) - ), - "left = {:?}, right = {:?}", - inflation.delegator.compute_reward::( - 50_000 * DECIMALS, - current_staking_rate, - authors_per_round - ) * years_u128, - Perquintill::from_percent(8) * 50_000 * DECIMALS, - ); - }); - } -} diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs deleted file mode 100644 index 6de3c6988..000000000 --- a/pallets/parachain-staking/src/lib.rs +++ /dev/null @@ -1,2573 +0,0 @@ -// KILT Blockchain – https://botlabs.org -// Copyright (C) 2019-2023 BOTLabs GmbH - -// The KILT Blockchain 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. - -// The KILT Blockchain 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 this program. If not, see . - -// If you feel like getting in touch with us, you can do so at info@botlabs.org - -//! # Parachain Staking -//! -//! A simple staking pallet providing means of selecting a set of collators to -//! become block authors based on their total backed stake. The main difference -//! between this pallet and `frame/pallet-staking` is that this pallet uses -//! direct delegation. Delegators choose exactly who they delegate and with what -//! stake. This is different from `frame/pallet-staking` where you approval vote -//! and then run Phragmen. Moreover, this pallet rewards a collator and their -//! delegators immediately when authoring a block. Rewards are calculated -//! separately between collators and delegators. -//! -//! To join the set of candidates, an account must call `join_candidates` with -//! `MinCollatorCandidateStake` <= stake <= `MaxCollatorCandidateStake`. -//! -//! To leave the set of candidates, the collator calls `leave_candidates`. If -//! the call succeeds, the collator is removed from the pool of candidates so -//! they cannot be selected for future collator sets, but they are not unstaking -//! until executing the exit request by calling the extrinsic -//! `execute_leave_candidates` at least `ExitQueueDelay` rounds later. After -//! doing so, the collator candidate as well as their delegators are unstaked. -//! Both parties then have to wait another `StakeDuration` more blocks to be -//! able to unlock their stake. -//! -//! Candidates which requested to leave can still be in the set of authors for -//! the next round due to the design of the session pallet which at the start of -//! session s(i) chooses a set for the next session s(i+1). Thus, candidates -//! have to keep collating at least until the end of the next session (= round). -//! We extend this by delaying their execute by at least `ExitQueueDelay` many -//! sessions. -//! -//! To join the set of delegators, an account must call `join_delegators` with -//! stake >= `MinDelegatorStake`. There are also runtime methods for delegating -//! additional collators and revoking delegations. -//! -//! -//! - [`Config`] -//! - [`Call`] -//! - [`Pallet`] -//! -//! ## Overview -//! -//! The KILT parachain staking pallet provides functions for: -//! - Joining the set of collator candidates of which the best -//! `MaxSelectedCandidates` are chosen to become active collators for the next -//! session. That makes the set of active collators the set of block authors -//! by handing it over to the session and the authority pallet. -//! - Delegating to a collator candidate by staking for them. -//! - Increasing and reducing your stake as a collator or delegator. -//! - Revoking your delegation entirely. -//! - Requesting to leave the set of collator candidates. -//! - Withdrawing your unstaked balance after waiting for a certain number of -//! blocks. -//! -//! ### Terminology -//! -//! - **Candidate:** A user which locks up tokens to be included into the set of -//! authorities which author blocks and receive rewards for doing so. -//! -//! - **Collator:** A candidate that was chosen to collate this round. -//! -//! - **Delegator:** A user which locks up tokens for collators they trust. When -//! their collator authors a block, the corresponding delegators also receive -//! rewards. -//! -//! - **Total Stake:** A collator’s own stake + the sum of delegated stake to -//! this collator. -//! -//! - **Total collator stake:** The sum of tokens locked for staking from all -//! collator candidates. -//! -//! - **Total delegator stake:** The sum of tokens locked for staking from all -//! delegators. -//! -//! - **To Stake:** Lock tokens for staking. -//! -//! - **To Unstake:** Unlock tokens from staking. -//! -//! - **Round (= Session):** A fixed number of blocks in which the set of -//! collators does not change. We set the length of a session to the length of -//! a staking round, thus both words are interchangeable in the context of -//! this pallet. -//! -//! - **Lock:** A freeze on a specified amount of an account's free balance -//! until a specified block number. Multiple locks always operate over the -//! same funds, so they "overlay" rather than "stack" -//! -//! ## Genesis config -//! -//! The ParachainStaking pallet depends on the [`GenesisConfig`]. -//! -//! ## Assumptions -//! -//! - At the start of session s(i), the set of session ids for session s(i+1) -//! are chosen. These equal the set of selected candidates. Thus, we cannot -//! allow collators to leave at least until the start of session s(i+2). - -#![cfg_attr(not(feature = "std"), no_std)] -#![allow(clippy::unused_unit)] - -use frame_support::pallet; - -pub use crate::{default_weights::WeightInfo, pallet::*}; - -#[cfg(feature = "runtime-benchmarks")] -pub mod benchmarking; -pub mod default_weights; - -pub mod migration; -#[cfg(test)] -pub(crate) mod mock; -#[cfg(test)] -pub(crate) mod tests; - -pub mod api; -mod inflation; -mod set; -mod types; - -#[pallet] -pub mod pallet { - use frame_support::{ - assert_ok, - pallet_prelude::*, - storage::bounded_btree_map::BoundedBTreeMap, - traits::{ - Currency, EstimateNextSessionRotation, Get, Imbalance, LockIdentifier, LockableCurrency, OnUnbalanced, - ReservableCurrency, StorageVersion, WithdrawReasons, - }, - BoundedVec, - }; - use frame_system::pallet_prelude::*; - use pallet_balances::{BalanceLock, Locks}; - use pallet_session::ShouldEndSession; - use scale_info::TypeInfo; - use sp_runtime::{ - traits::{Convert, One, SaturatedConversion, Saturating, StaticLookup, Zero}, - Permill, Perquintill, - }; - use sp_staking::SessionIndex; - use sp_std::{convert::TryInto, fmt::Debug, prelude::*}; - - pub use crate::inflation::{InflationInfo, RewardRate, StakingInfo}; - use crate::{ - set::OrderedSet, - types::{ - BalanceOf, Candidate, CandidateOf, CandidateStatus, DelegationCounter, Delegator, NegativeImbalanceOf, - RoundInfo, Stake, StakeOf, TotalStake, - }, - }; - - use super::*; - - /// Kilt-specific lock for staking rewards. - pub(crate) const STAKING_ID: LockIdentifier = *b"kiltpstk"; - - /// The current storage version. - const STORAGE_VERSION: StorageVersion = StorageVersion::new(8); - - /// Pallet for parachain staking. - #[pallet::pallet] - #[pallet::generate_store(pub (super) trait Store)] - #[pallet::storage_version(STORAGE_VERSION)] - pub struct Pallet(PhantomData); - - /// Configuration trait of this pallet. - #[pallet::config] - pub trait Config: frame_system::Config + pallet_balances::Config + pallet_session::Config { - /// Overarching event type - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - // FIXME: Remove Currency and CurrencyBalance types. Problem: Need to restrict - // pallet_balances::Config::Balance with From for usage with Perquintill - // multiplication - /// The currency type - /// Note: Declaration of Balance taken from pallet_gilt - type Currency: Currency - + ReservableCurrency - + LockableCurrency - + Eq; - - /// Just the `Currency::Balance` type; we have this item to allow us to - /// constrain it to `From`. - /// Note: Definition taken from pallet_gilt - type CurrencyBalance: sp_runtime::traits::AtLeast32BitUnsigned - + parity_scale_codec::FullCodec - + Copy - + MaybeSerializeDeserialize - + sp_std::fmt::Debug - + Default - + From - + From - + Into<::Balance> - + From<::Balance> - + From - + TypeInfo - + MaxEncodedLen; - - /// Minimum number of blocks validation rounds can last. - #[pallet::constant] - type MinBlocksPerRound: Get; - - /// Default number of blocks validation rounds last, as set in the - /// genesis configuration. - #[pallet::constant] - type DefaultBlocksPerRound: Get; - /// Number of blocks for which unstaked balance will still be locked - /// before it can be unlocked by actively calling the extrinsic - /// `unlock_unstaked`. - #[pallet::constant] - type StakeDuration: Get; - /// Number of rounds a collator has to stay active after submitting a - /// request to leave the set of collator candidates. - #[pallet::constant] - type ExitQueueDelay: Get; - - /// Minimum number of collators selected from the set of candidates at - /// every validation round. - #[pallet::constant] - type MinCollators: Get; - - /// Minimum number of collators which cannot leave the network if there - /// are no others. - #[pallet::constant] - type MinRequiredCollators: Get; - - /// Maximum number of delegations which can be made within the same - /// round. - /// - /// NOTE: To prevent re-delegation-reward attacks, we should keep this - /// to be one. - #[pallet::constant] - type MaxDelegationsPerRound: Get; - - /// Maximum number of delegators a single collator can have. - #[pallet::constant] - type MaxDelegatorsPerCollator: Get + Debug + PartialEq; - - /// Maximum size of the top candidates set. - #[pallet::constant] - type MaxTopCandidates: Get + Debug + PartialEq; - - /// Minimum stake required for any account to be elected as validator - /// for a round. - #[pallet::constant] - type MinCollatorStake: Get>; - - /// Minimum stake required for any account to be added to the set of - /// candidates. - #[pallet::constant] - type MinCollatorCandidateStake: Get>; - - /// Minimum stake required for any account to become a delegator. - #[pallet::constant] - type MinDelegatorStake: Get>; - - /// Max number of concurrent active unstaking requests before - /// unlocking. - /// - /// NOTE: To protect against irremovability of a candidate or delegator, - /// we only allow for MaxUnstakeRequests - 1 many manual unstake - /// requests. The last one serves as a placeholder for the cases of - /// calling either `kick_delegator`, force_remove_candidate` or - /// `execute_leave_candidates`. Otherwise, a user could max out their - /// unstake requests and prevent themselves from being kicked from the - /// set of candidates/delegators until they unlock their funds. - #[pallet::constant] - type MaxUnstakeRequests: Get; - - /// The starting block number for the network rewards. Once the current - /// block number exceeds this start, the beneficiary will receive the - /// configured reward in each block. - #[pallet::constant] - type NetworkRewardStart: Get<::BlockNumber>; - - /// The rate in percent for the network rewards which are based on the - /// maximum number of collators and the maximum amount a collator can - /// stake. - #[pallet::constant] - type NetworkRewardRate: Get; - - /// The beneficiary to receive the network rewards. - type NetworkRewardBeneficiary: OnUnbalanced>; - - /// Weight information for extrinsics in this pallet. - type WeightInfo: WeightInfo; - - const BLOCKS_PER_YEAR: Self::BlockNumber; - } - - #[pallet::error] - pub enum Error { - /// The account is not part of the delegators set. - DelegatorNotFound, - /// The account is not part of the collator candidates set. - CandidateNotFound, - /// The account is already part of the delegators set. - DelegatorExists, - /// The account is already part of the collator candidates set. - CandidateExists, - /// The account tried to stake more or less with amount zero. - ValStakeZero, - /// The account has not staked enough funds to be added to the collator - /// candidates set. - ValStakeBelowMin, - /// The account has already staked the maximum amount of funds possible. - ValStakeAboveMax, - /// The account has not staked enough funds to delegate a collator - /// candidate. - DelegationBelowMin, - /// The collator candidate has already trigger the process to leave the - /// set of collator candidates. - AlreadyLeaving, - /// The collator candidate wanted to execute the exit but has not - /// requested to leave before by calling `init_leave_candidates`. - NotLeaving, - /// The collator tried to leave before waiting at least for - /// `ExitQueueDelay` many rounds. - CannotLeaveYet, - /// The account has a full list of unstaking requests and needs to - /// unlock at least one of these before being able to join (again). - /// NOTE: Can only happen if the account was a candidate or - /// delegator before and either got kicked or exited voluntarily. - CannotJoinBeforeUnlocking, - /// The account is already delegating the collator candidate. - AlreadyDelegating, - /// The account has not delegated any collator candidate yet, hence it - /// is not in the set of delegators. - NotYetDelegating, - /// The delegator has exceeded the number of delegations per round which - /// is equal to MaxDelegatorsPerCollator. - /// - /// This protects against attacks in which a delegator can re-delegate - /// from a collator who has already authored a block, to another one - /// which has not in this round. - DelegationsPerRoundExceeded, - /// The collator candidate has already reached the maximum number of - /// delegators. - /// - /// This error is generated in case a new delegation request does not - /// stake enough funds to replace some other existing delegation. - TooManyDelegators, - /// The set of collator candidates would fall below the required minimum - /// if the collator left. - TooFewCollatorCandidates, - /// The collator candidate is in the process of leaving the set of - /// candidates and cannot perform any other actions in the meantime. - CannotStakeIfLeaving, - /// The collator candidate is in the process of leaving the set of - /// candidates and thus cannot be delegated to. - CannotDelegateIfLeaving, - /// The delegator has already delegated the maximum number of candidates - /// allowed. - MaxCollatorsPerDelegatorExceeded, - /// The delegator has already previously delegated the collator - /// candidate. - AlreadyDelegatedCollator, - /// The given delegation does not exist in the set of delegations. - DelegationNotFound, - /// The collator delegate or the delegator is trying to un-stake more - /// funds that are currently staked. - Underflow, - /// The number of selected candidates per staking round is - /// above the maximum value allowed. - CannotSetAboveMax, - /// The number of selected candidates per staking round is - /// below the minimum value allowed. - CannotSetBelowMin, - /// An invalid inflation configuration is trying to be set. - InvalidSchedule, - /// The staking reward being unlocked does not exist. - /// Max unlocking requests reached. - NoMoreUnstaking, - /// The reward rate cannot be adjusted yet as an entire year has not - /// passed. - TooEarly, - /// Provided staked value is zero. Should never be thrown. - StakeNotFound, - /// Cannot unlock when Unstaked is empty. - UnstakingIsEmpty, - /// Cannot claim rewards if empty. - RewardsNotFound, - } - - #[pallet::event] - #[pallet::generate_deposit(pub(crate) fn deposit_event)] - pub enum Event { - /// A new staking round has started. - /// \[block number, round number\] - NewRound(T::BlockNumber, SessionIndex), - /// A new account has joined the set of top candidates. - /// \[account\] - EnteredTopCandidates(T::AccountId), - /// An account was removed from the set of top candidates. - /// \[account\] - LeftTopCandidates(T::AccountId), - /// A new account has joined the set of collator candidates. - /// \[account, amount staked by the new candidate\] - JoinedCollatorCandidates(T::AccountId, BalanceOf), - /// A collator candidate has increased the amount of funds at stake. - /// \[collator's account, previous stake, new stake\] - CollatorStakedMore(T::AccountId, BalanceOf, BalanceOf), - /// A collator candidate has decreased the amount of funds at stake. - /// \[collator's account, previous stake, new stake\] - CollatorStakedLess(T::AccountId, BalanceOf, BalanceOf), - /// A collator candidate has started the process to leave the set of - /// candidates. \[round number, collator's account, round number when - /// the collator will be effectively removed from the set of - /// candidates\] - CollatorScheduledExit(SessionIndex, T::AccountId, SessionIndex), - /// A collator candidate has canceled the process to leave the set of - /// candidates and was added back to the candidate pool. \[collator's - /// account\] - CollatorCanceledExit(T::AccountId), - /// An account has left the set of collator candidates. - /// \[account, amount of funds un-staked\] - CandidateLeft(T::AccountId, BalanceOf), - /// An account was forcedly removed from the set of collator - /// candidates. \[account, amount of funds un-staked\] - CollatorRemoved(T::AccountId, BalanceOf), - /// The maximum candidate stake has been changed. - /// \[new max amount\] - MaxCandidateStakeChanged(BalanceOf), - /// A delegator has increased the amount of funds at stake for a - /// collator. \[delegator's account, collator's account, previous - /// delegation stake, new delegation stake\] - DelegatorStakedMore(T::AccountId, T::AccountId, BalanceOf, BalanceOf), - /// A delegator has decreased the amount of funds at stake for a - /// collator. \[delegator's account, collator's account, previous - /// delegation stake, new delegation stake\] - DelegatorStakedLess(T::AccountId, T::AccountId, BalanceOf, BalanceOf), - /// An account has left the set of delegators. - /// \[account, amount of funds un-staked\] - DelegatorLeft(T::AccountId, BalanceOf), - /// An account has delegated a new collator candidate. - /// \[account, amount of funds staked, total amount of delegators' funds - /// staked for the collator candidate\] - Delegation(T::AccountId, BalanceOf, T::AccountId, BalanceOf), - /// A new delegation has replaced an existing one in the set of ongoing - /// delegations for a collator candidate. \[new delegator's account, - /// amount of funds staked in the new delegation, replaced delegator's - /// account, amount of funds staked in the replace delegation, collator - /// candidate's account, new total amount of delegators' funds staked - /// for the collator candidate\] - DelegationReplaced( - T::AccountId, - BalanceOf, - T::AccountId, - BalanceOf, - T::AccountId, - BalanceOf, - ), - /// An account has stopped delegating a collator candidate. - /// \[account, collator candidate's account, old amount of delegators' - /// funds staked, new amount of delegators' funds staked\] - DelegatorLeftCollator(T::AccountId, T::AccountId, BalanceOf, BalanceOf), - /// A collator or a delegator has received a reward. - /// \[account, amount of reward\] - Rewarded(T::AccountId, BalanceOf), - /// Inflation configuration for future validation rounds has changed. - /// \[maximum collator's staking rate, maximum collator's reward rate, - /// maximum delegator's staking rate, maximum delegator's reward rate\] - RoundInflationSet(Perquintill, Perquintill, Perquintill, Perquintill), - /// The maximum number of collator candidates selected in future - /// validation rounds has changed. \[old value, new value\] - MaxSelectedCandidatesSet(u32, u32), - /// The length in blocks for future validation rounds has changed. - /// \[round number, first block in the current round, old value, new - /// value\] - BlocksPerRoundSet(SessionIndex, T::BlockNumber, T::BlockNumber, T::BlockNumber), - } - - #[pallet::hooks] - impl Hooks> for Pallet { - fn on_initialize(now: T::BlockNumber) -> frame_support::weights::Weight { - let mut post_weight = ::WeightInfo::on_initialize_no_action(); - let mut round = Round::::get(); - - // check for round update - if round.should_update(now) { - // mutate round - round.update(now); - // start next round - Round::::put(round); - - Self::deposit_event(Event::NewRound(round.first, round.current)); - post_weight = ::WeightInfo::on_initialize_round_update(); - } - // check for network reward and mint - // on success, mint each block - if now > T::NetworkRewardStart::get() { - T::NetworkRewardBeneficiary::on_unbalanced(Self::issue_network_reward()); - post_weight = post_weight.saturating_add(::WeightInfo::on_initialize_network_rewards()); - } - post_weight - } - } - - /// The maximum number of collator candidates selected at each round. - #[pallet::storage] - #[pallet::getter(fn max_selected_candidates)] - pub(crate) type MaxSelectedCandidates = StorageValue<_, u32, ValueQuery>; - - /// Current round number and next round scheduled transition. - #[pallet::storage] - #[pallet::getter(fn round)] - pub(crate) type Round = StorageValue<_, RoundInfo, ValueQuery>; - - /// Delegation information for the latest session in which a delegator - /// delegated. - /// - /// It maps from an account to the number of delegations in the last - /// session in which they (re-)delegated. - #[pallet::storage] - #[pallet::getter(fn last_delegation)] - pub(crate) type LastDelegation = - StorageMap<_, Twox64Concat, T::AccountId, DelegationCounter, ValueQuery>; - - /// Delegation staking information. - /// - /// It maps from an account to its delegation details. - #[pallet::storage] - #[pallet::getter(fn delegator_state)] - pub(crate) type DelegatorState = - StorageMap<_, Twox64Concat, T::AccountId, Delegator>, OptionQuery>; - - /// The staking information for a candidate. - /// - /// It maps from an account to its information. - /// Moreover, it counts the number of candidates. - #[pallet::storage] - #[pallet::getter(fn candidate_pool)] - pub(crate) type CandidatePool = CountedStorageMap< - _, - Twox64Concat, - T::AccountId, - Candidate, T::MaxDelegatorsPerCollator>, - OptionQuery, - >; - - /// Total funds locked to back the currently selected collators. - /// The sum of all collator and their delegator stakes. - /// - /// Note: There are more funds locked by this pallet, since the backing for - /// non collating candidates is not included in [TotalCollatorStake]. - #[pallet::storage] - #[pallet::getter(fn total_collator_stake)] - pub(crate) type TotalCollatorStake = StorageValue<_, TotalStake>, ValueQuery>; - - /// The collator candidates with the highest amount of stake. - /// - /// Each time the stake of a collator is increased, it is checked whether - /// this pushes another candidate out of the list. When the stake is - /// reduced however, it is not checked if another candidate has more stake, - /// since this would require iterating over the entire [CandidatePool]. - /// - /// There must always be more candidates than [MaxSelectedCandidates] so - /// that a collator can drop out of the collator set by reducing their - /// stake. - #[pallet::storage] - #[pallet::getter(fn top_candidates)] - pub(crate) type TopCandidates = - StorageValue<_, OrderedSet>, T::MaxTopCandidates>, ValueQuery>; - - /// Inflation configuration. - #[pallet::storage] - #[pallet::getter(fn inflation_config)] - pub(crate) type InflationConfig = StorageValue<_, InflationInfo, ValueQuery>; - - /// The funds waiting to be unstaked. - /// - /// It maps from accounts to all the funds addressed to them in the future - /// blocks. - #[pallet::storage] - #[pallet::getter(fn unstaking)] - pub(crate) type Unstaking = StorageMap< - _, - Twox64Concat, - T::AccountId, - BoundedBTreeMap, T::MaxUnstakeRequests>, - ValueQuery, - >; - - /// The maximum amount a collator candidate can stake. - #[pallet::storage] - #[pallet::getter(fn max_candidate_stake)] - pub(crate) type MaxCollatorCandidateStake = StorageValue<_, BalanceOf, ValueQuery>; - - /// The year in which the last automatic reduction of the reward rates - /// occurred. - /// - /// It starts at zero at genesis and increments by one every BLOCKS_PER_YEAR - /// many blocks. - #[pallet::storage] - #[pallet::getter(fn last_reward_reduction)] - pub(crate) type LastRewardReduction = StorageValue<_, T::BlockNumber, ValueQuery>; - - /// The number of authored blocks for collators. It is updated via the - /// `note_author` hook when authoring a block . - #[pallet::storage] - #[pallet::getter(fn blocks_authored)] - pub(crate) type BlocksAuthored = StorageMap<_, Twox64Concat, T::AccountId, T::BlockNumber, ValueQuery>; - - /// The number of blocks for which rewards have been claimed by an address. - /// - /// For collators, this can be at most BlocksAuthored. It is updated when - /// incrementing collator rewards, either when calling - /// `inc_collator_rewards` or updating the `InflationInfo`. - /// - /// For delegators, this can be at most BlocksAuthored of the collator.It is - /// updated when incrementing delegator rewards, either when calling - /// `inc_delegator_rewards` or updating the `InflationInfo`. - #[pallet::storage] - #[pallet::getter(fn blocks_rewarded)] - pub(crate) type BlocksRewarded = StorageMap<_, Twox64Concat, T::AccountId, T::BlockNumber, ValueQuery>; - - /// The accumulated rewards for collator candidates and delegators. - /// - /// It maps from accounts to their total rewards since the last payout. - #[pallet::storage] - #[pallet::getter(fn rewards)] - pub(crate) type Rewards = StorageMap<_, Twox64Concat, T::AccountId, BalanceOf, ValueQuery>; - - pub type GenesisStaker = Vec<( - ::AccountId, - Option<::AccountId>, - BalanceOf, - )>; - - #[pallet::storage] - #[pallet::getter(fn new_round_forced)] - pub(crate) type ForceNewRound = StorageValue<_, bool, ValueQuery>; - - #[pallet::genesis_config] - pub struct GenesisConfig { - pub stakers: GenesisStaker, - pub inflation_config: InflationInfo, - pub max_candidate_stake: BalanceOf, - } - - #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - Self { - stakers: Default::default(), - inflation_config: Default::default(), - max_candidate_stake: Default::default(), - } - } - } - - #[pallet::genesis_build] - impl GenesisBuild for GenesisConfig { - fn build(&self) { - assert!( - self.inflation_config.is_valid(T::BLOCKS_PER_YEAR.saturated_into()), - "Invalid inflation configuration" - ); - - InflationConfig::::put(self.inflation_config.clone()); - MaxCollatorCandidateStake::::put(self.max_candidate_stake); - - // Setup delegate & collators - for &(ref actor, ref opt_val, balance) in &self.stakers { - assert!( - T::Currency::free_balance(actor) >= balance, - "Account does not have enough balance to stake." - ); - if let Some(delegated_val) = opt_val { - assert_ok!(Pallet::::join_delegators( - T::RuntimeOrigin::from(Some(actor.clone()).into()), - T::Lookup::unlookup(delegated_val.clone()), - balance, - )); - } else { - assert_ok!(Pallet::::join_candidates( - T::RuntimeOrigin::from(Some(actor.clone()).into()), - balance - )); - } - } - // Set total selected candidates to minimum config - MaxSelectedCandidates::::put(T::MinCollators::get()); - - Pallet::::update_total_stake(); - - // Start Round 0 at Block 0 - let round: RoundInfo = RoundInfo::new(0u32, 0u32.into(), T::DefaultBlocksPerRound::get()); - Round::::put(round); - } - } - - #[pallet::call] - impl Pallet { - /// Forces the start of the new round in the next block. - /// - /// The new round will be enforced via >::should_end_session. - /// - /// The dispatch origin must be Root. - #[pallet::call_index(0)] - #[pallet::weight(::WeightInfo::force_new_round())] - pub fn force_new_round(origin: OriginFor) -> DispatchResult { - ensure_root(origin)?; - - // set force_new_round handle which, at the start of the next block, will - // trigger `should_end_session` in `Session::on_initialize` and update the - // current round - ForceNewRound::::put(true); - - Ok(()) - } - - /// Set the annual inflation rate to derive per-round inflation. - /// - /// The inflation details are considered valid if the annual reward rate - /// is approximately the per-block reward rate multiplied by the - /// estimated* total number of blocks per year. - /// - /// The estimated average block time is twelve seconds. - /// - /// NOTE: Iterates over CandidatePool and for each candidate over their - /// delegators to update their rewards before the reward rates change. - /// Needs to be improved when scaling up `MaxTopCandidates`. - /// - /// The dispatch origin must be Root. - /// - /// Emits `RoundInflationSet`. - #[pallet::call_index(1)] - #[pallet::weight(::WeightInfo::set_inflation(T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get()))] - pub fn set_inflation( - origin: OriginFor, collator_max_rate_percentage: Perquintill, - collator_annual_reward_rate_percentage: Perquintill, delegator_max_rate_percentage: Perquintill, - delegator_annual_reward_rate_percentage: Perquintill, - ) -> DispatchResultWithPostInfo { - ensure_root(origin)?; - - // Update inflation and increment rewards - let (num_col, num_del) = Self::do_set_inflation( - T::BLOCKS_PER_YEAR, - collator_max_rate_percentage, - collator_annual_reward_rate_percentage, - delegator_max_rate_percentage, - delegator_annual_reward_rate_percentage, - )?; - - Ok(Some(::WeightInfo::set_inflation(num_col, num_del)).into()) - } - - /// Set the maximum number of collator candidates that can be selected - /// at the beginning of each validation round. - /// - /// Changes are not applied until the start of the next round. - /// - /// The new value must be higher than the minimum allowed as set in the - /// pallet's configuration. - /// - /// The dispatch origin must be Root. - /// - /// Emits `MaxSelectedCandidatesSet`. - #[pallet::call_index(2)] - #[pallet::weight(::WeightInfo::set_max_selected_candidates( - *new, - T::MaxDelegatorsPerCollator::get() - ))] - pub fn set_max_selected_candidates(origin: OriginFor, new: u32) -> DispatchResultWithPostInfo { - ensure_root(origin)?; - ensure!(new >= T::MinCollators::get(), Error::::CannotSetBelowMin); - ensure!(new <= T::MaxTopCandidates::get(), Error::::CannotSetAboveMax); - let old = MaxSelectedCandidates::::get(); - - // *** No Fail beyond this point *** - - MaxSelectedCandidates::::put(new); - - // Update total amount at stake for new top collators and their delegators - let start = old.min(new); - let end = old.max(new); - - // The slice [start, end] contains the added or removed collators. We sum up - // their stake to adjust the total stake. - let (diff_collation, diff_delegation, num_delegators) = TopCandidates::::get() - .into_iter() - .skip(start.saturated_into()) - // SAFETY: we ensured that end > start further above. - .take((end - start).saturated_into()) - .filter_map(|candidate| CandidatePool::::get(&candidate.owner)) - .map(|state| { - ( - state.stake, - // SAFETY: the total is always more than the stake - state.total - state.stake, - state.delegators.len().saturated_into::(), - ) - }) - .reduce(|a, b| (a.0.saturating_add(b.0), a.1.saturating_add(b.1), a.2.max(b.2))) - .unwrap_or((BalanceOf::::zero(), BalanceOf::::zero(), 0u32)); - - TotalCollatorStake::::mutate(|total| { - if new > old { - total.collators = total.collators.saturating_add(diff_collation); - total.delegators = total.delegators.saturating_add(diff_delegation); - } else { - total.collators = total.collators.saturating_sub(diff_collation); - total.delegators = total.delegators.saturating_sub(diff_delegation); - } - }); - - Self::deposit_event(Event::MaxSelectedCandidatesSet(old, new)); - - Ok(Some(::WeightInfo::set_max_selected_candidates( - // SAFETY: we ensured that end > start further above. - end - start, - num_delegators, - )) - .into()) - } - - /// Set the number of blocks each validation round lasts. - /// - /// If the new value is less than the length of the current round, the - /// system will immediately move to the next round in the next block. - /// - /// The new value must be higher than the minimum allowed as set in the - /// pallet's configuration. - /// - /// The dispatch origin must be Root. - /// - /// Emits `BlocksPerRoundSet`. - #[pallet::call_index(3)] - #[pallet::weight(::WeightInfo::set_blocks_per_round())] - pub fn set_blocks_per_round(origin: OriginFor, new: T::BlockNumber) -> DispatchResult { - ensure_root(origin)?; - ensure!(new >= T::MinBlocksPerRound::get(), Error::::CannotSetBelowMin); - - let old_round = Round::::get(); - - // *** No Fail beyond this point *** - - Round::::put(RoundInfo { - length: new, - ..old_round - }); - - Self::deposit_event(Event::BlocksPerRoundSet( - old_round.current, - old_round.first, - old_round.length, - new, - )); - Ok(()) - } - - /// Set the maximal amount a collator can stake. Existing stakes are not - /// changed. - /// - /// The dispatch origin must be Root. - /// - /// Emits `MaxCandidateStakeChanged`. - #[pallet::call_index(4)] - #[pallet::weight(::WeightInfo::set_max_candidate_stake())] - pub fn set_max_candidate_stake(origin: OriginFor, new: BalanceOf) -> DispatchResult { - ensure_root(origin)?; - ensure!( - new >= T::MinCollatorCandidateStake::get(), - Error::::CannotSetBelowMin - ); - - // *** No Fail beyond this point *** - - MaxCollatorCandidateStake::::put(new); - - Self::deposit_event(Event::MaxCandidateStakeChanged(new)); - Ok(()) - } - - /// Forcedly removes a collator candidate from the TopCandidates and - /// clears all associated storage for the candidate and their - /// delegators. - /// - /// Prepares unstaking of the candidates and their delegators stake - /// which can be unlocked via `unlock_unstaked` after waiting at - /// least `StakeDuration` many blocks. Also increments rewards for the - /// collator and their delegators. - /// - /// Increments rewards of candidate and their delegators. - /// - /// Emits `CandidateRemoved`. - #[pallet::call_index(5)] - #[pallet::weight(::WeightInfo::force_remove_candidate( - T::MaxTopCandidates::get(), - T::MaxDelegatorsPerCollator::get() - ))] - pub fn force_remove_candidate( - origin: OriginFor, collator: ::Source, - ) -> DispatchResultWithPostInfo { - ensure_root(origin)?; - let collator = T::Lookup::lookup(collator)?; - let state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; - let total_amount = state.total; - - let mut candidates = TopCandidates::::get(); - ensure!( - candidates.len().saturated_into::() > T::MinRequiredCollators::get(), - Error::::TooFewCollatorCandidates - ); - - // *** No Fail except during remove_candidate beyond this point *** - - // remove candidate storage and increment rewards - Self::remove_candidate(&collator, &state)?; - - let (num_collators, num_delegators) = if candidates - .remove(&Stake { - owner: collator.clone(), - amount: state.total, - }) - .is_some() - { - // update top candidates - TopCandidates::::put(candidates); - // update total amount at stake from scratch - Self::update_total_stake() - } else { - (0u32, 0u32) - }; - - Self::deposit_event(Event::CollatorRemoved(collator, total_amount)); - - Ok(Some(::WeightInfo::force_remove_candidate( - num_collators, - num_delegators, - )) - .into()) - } - - /// Join the set of collator candidates. - /// - /// In the next blocks, if the collator candidate has enough funds - /// staked to be included in any of the top `MaxSelectedCandidates` - /// positions, it will be included in the set of potential authors that - /// will be selected by the stake-weighted random selection function. - /// - /// The staked funds of the new collator candidate are added to the - /// total stake of the system. - /// - /// The total amount of funds staked must be within the allowed range as - /// set in the pallet's configuration. - /// - /// The dispatch origin must not be already part of the collator - /// candidates nor of the delegators set. - /// - /// Emits `JoinedCollatorCandidates`. - #[pallet::call_index(6)] - #[pallet::weight(::WeightInfo::join_candidates( - T::MaxTopCandidates::get(), - T::MaxDelegatorsPerCollator::get() - ))] - pub fn join_candidates(origin: OriginFor, stake: BalanceOf) -> DispatchResultWithPostInfo { - let sender = ensure_signed(origin)?; - if let Some(is_active_candidate) = Self::is_active_candidate(&sender) { - ensure!(is_active_candidate, Error::::AlreadyLeaving); - ensure!(!is_active_candidate, Error::::CandidateExists); - } - ensure!(!Self::is_delegator(&sender), Error::::DelegatorExists); - ensure!( - stake >= T::MinCollatorCandidateStake::get(), - Error::::ValStakeBelowMin - ); - ensure!( - stake <= MaxCollatorCandidateStake::::get(), - Error::::ValStakeAboveMax - ); - ensure!( - Unstaking::::get(&sender).len().saturated_into::() < T::MaxUnstakeRequests::get(), - Error::::CannotJoinBeforeUnlocking - ); - - // *** No Fail except during increase_lock beyond this point *** - - Self::increase_lock(&sender, stake, BalanceOf::::zero())?; - - let candidate = Candidate::new(sender.clone(), stake); - let n = Self::update_top_candidates( - sender.clone(), - BalanceOf::::zero(), - BalanceOf::::zero(), - stake, - BalanceOf::::zero(), - ); - CandidatePool::::insert(&sender, candidate); - - Self::deposit_event(Event::JoinedCollatorCandidates(sender, stake)); - Ok(Some(::WeightInfo::join_candidates( - n, - T::MaxDelegatorsPerCollator::get(), - )) - .into()) - } - - /// Request to leave the set of collator candidates. - /// - /// On success, the account is immediately removed from the candidate - /// pool to prevent selection as a collator in future validation rounds, - /// but unstaking of the funds is executed with a delay of - /// `StakeDuration` blocks. - /// - /// The exit request can be reversed by calling - /// `cancel_leave_candidates`. - /// - /// This operation affects the pallet's total stake amount. It is - /// updated even though the funds of the candidate who signaled to leave - /// are still locked for `ExitDelay` + `StakeDuration` more blocks. - /// - /// NOTE 1: Upon starting a new session_i in `new_session`, the current - /// top candidates are selected to be block authors for session_i+1. Any - /// changes to the top candidates afterwards do not effect the set of - /// authors for session_i+1. - /// Thus, we have to make sure none of these collators can - /// leave before session_i+1 ends by delaying their - /// exit for `ExitDelay` many blocks. - /// - /// NOTE 2: We do not increment rewards in this extrinsic as the - /// candidate could still author blocks, and thus be eligible to receive - /// rewards, until the end of the next session. - /// - /// Emits `CollatorScheduledExit`. - #[pallet::call_index(7)] - #[pallet::weight(::WeightInfo::init_leave_candidates( - T::MaxTopCandidates::get(), - T::MaxTopCandidates::get().saturating_mul(T::MaxDelegatorsPerCollator::get()) - ))] - pub fn init_leave_candidates(origin: OriginFor) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; - ensure!(!state.is_leaving(), Error::::AlreadyLeaving); - let mut candidates = TopCandidates::::get(); - ensure!( - candidates.len().saturated_into::() > T::MinRequiredCollators::get(), - Error::::TooFewCollatorCandidates - ); - - let now = Round::::get().current; - let when = now.saturating_add(T::ExitQueueDelay::get()); - state.leave_candidates(when); - - // *** No Fail beyond this point *** - - let (num_collators, num_delegators) = if candidates - .remove(&Stake { - owner: collator.clone(), - amount: state.total, - }) - .is_some() - { - // update top candidates - TopCandidates::::put(candidates); - Self::deposit_event(Event::LeftTopCandidates(collator.clone())); - // update total amount at stake from scratch - Self::update_total_stake() - } else { - (0u32, 0u32) - }; - CandidatePool::::insert(&collator, state); - - Self::deposit_event(Event::CollatorScheduledExit(now, collator, when)); - Ok(Some(::WeightInfo::init_leave_candidates( - num_collators, - num_delegators, - )) - .into()) - } - - /// Execute the network exit of a candidate who requested to leave at - /// least `ExitQueueDelay` rounds ago. Prepares unstaking of the - /// candidates and their delegators stake which can be unlocked via - /// `unlock_unstaked` after waiting at least `StakeDuration` many - /// blocks. - /// - /// Requires the candidate to previously have called - /// `init_leave_candidates`. - /// - /// The exit request can be reversed by calling - /// `cancel_leave_candidates`. - /// - /// NOTE: Iterates over CandidatePool for each candidate over their - /// delegators to set rewards. Needs to be improved when scaling up - /// `MaxTopCandidates`. - /// - /// Emits `CollatorLeft`. - #[pallet::call_index(8)] - #[pallet::weight(::WeightInfo::execute_leave_candidates( - T::MaxTopCandidates::get(), - T::MaxDelegatorsPerCollator::get(), - ))] - pub fn execute_leave_candidates( - origin: OriginFor, collator: ::Source, - ) -> DispatchResultWithPostInfo { - ensure_signed(origin)?; - let collator = T::Lookup::lookup(collator)?; - let state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; - ensure!(state.is_leaving(), Error::::NotLeaving); - ensure!(state.can_exit(Round::::get().current), Error::::CannotLeaveYet); - - let num_delegators = state.delegators.len().saturated_into::(); - let total_amount = state.total; - - // *** No Fail except during remove_candidate beyond this point *** - - // remove candidate storage and increment rewards - Self::remove_candidate(&collator, &state)?; - - Self::deposit_event(Event::CandidateLeft(collator, total_amount)); - - Ok(Some(::WeightInfo::execute_leave_candidates( - T::MaxTopCandidates::get(), - num_delegators, - )) - .into()) - } - - /// Revert the previously requested exit of the network of a collator - /// candidate. On success, adds back the candidate to the TopCandidates - /// and updates the collators. - /// - /// Requires the candidate to previously have called - /// `init_leave_candidates`. - /// - /// Emits `CollatorCanceledExit`. - #[pallet::call_index(9)] - #[pallet::weight(::WeightInfo::cancel_leave_candidates( - T::MaxTopCandidates::get(), - T::MaxDelegatorsPerCollator::get(), - ))] - pub fn cancel_leave_candidates(origin: OriginFor) -> DispatchResultWithPostInfo { - let candidate = ensure_signed(origin)?; - let mut state = CandidatePool::::get(&candidate).ok_or(Error::::CandidateNotFound)?; - ensure!(state.is_leaving(), Error::::NotLeaving); - - // revert leaving state - state.revert_leaving(); - - // *** No Fail beyond this point *** - - let n = Self::update_top_candidates( - candidate.clone(), - state.stake, - // safe because total >= stake - state.total - state.stake, - state.stake, - state.total - state.stake, - ); - - // update candidates for next round - CandidatePool::::insert(&candidate, state); - - Self::deposit_event(Event::CollatorCanceledExit(candidate)); - - Ok(Some(::WeightInfo::cancel_leave_candidates( - n, - T::MaxDelegatorsPerCollator::get(), - )) - .into()) - } - - /// Stake more funds for a collator candidate. - /// - /// If not in the set of candidates, staking enough funds allows the - /// account to be added to it. The larger amount of funds, the higher - /// chances to be selected as the author of the next block. - /// - /// This operation affects the pallet's total stake amount. - /// - /// The resulting total amount of funds staked must be within the - /// allowed range as set in the pallet's configuration. - /// - /// Emits `CollatorStakedMore`. - #[pallet::call_index(10)] - #[pallet::weight(::WeightInfo::candidate_stake_more( - T::MaxTopCandidates::get(), - T::MaxDelegatorsPerCollator::get(), - T::MaxUnstakeRequests::get().saturated_into::() - ))] - pub fn candidate_stake_more(origin: OriginFor, more: BalanceOf) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - - ensure!(!more.is_zero(), Error::::ValStakeZero); - let mut state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; - ensure!(!state.is_leaving(), Error::::CannotStakeIfLeaving); - - let CandidateOf:: { - stake: before_stake, - total: before_total, - .. - } = state; - state.stake_more(more); - let after_stake = state.stake; - ensure!( - state.stake <= MaxCollatorCandidateStake::::get(), - Error::::ValStakeAboveMax - ); - - // *** No Fail except during increase_lock beyond this point *** - - let unstaking_len = Self::increase_lock(&collator, state.stake, more)?; - - let n = if state.is_active() { - Self::update_top_candidates( - collator.clone(), - before_stake, - // safe because total >= stake - before_total - before_stake, - state.stake, - state.total - state.stake, - ) - } else { - 0u32 - }; - CandidatePool::::insert(&collator, state); - - // increment rewards for collator and update number of rewarded blocks - Self::do_inc_collator_reward(&collator, before_stake); - - Self::deposit_event(Event::CollatorStakedMore(collator, before_stake, after_stake)); - Ok(Some(::WeightInfo::candidate_stake_more( - n, - T::MaxDelegatorsPerCollator::get(), - unstaking_len, - )) - .into()) - } - - /// Stake less funds for a collator candidate. - /// - /// If the new amount of staked fund is not large enough, the account - /// could be removed from the set of collator candidates and not be - /// considered for authoring the next blocks. - /// - /// This operation affects the pallet's total stake amount. - /// - /// The unstaked funds are not released immediately to the account, but - /// they will be available after `StakeDuration` blocks. - /// - /// The resulting total amount of funds staked must be within the - /// allowed range as set in the pallet's configuration. - /// - /// Emits `CollatorStakedLess`. - #[pallet::call_index(11)] - #[pallet::weight(::WeightInfo::candidate_stake_less( - T::MaxTopCandidates::get(), - T::MaxDelegatorsPerCollator::get() - ))] - pub fn candidate_stake_less(origin: OriginFor, less: BalanceOf) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - ensure!(!less.is_zero(), Error::::ValStakeZero); - - let mut state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; - ensure!(!state.is_leaving(), Error::::CannotStakeIfLeaving); - - let CandidateOf:: { - stake: before_stake, - total: before_total, - .. - } = state; - let after = state.stake_less(less).ok_or(Error::::Underflow)?; - ensure!( - after >= T::MinCollatorCandidateStake::get(), - Error::::ValStakeBelowMin - ); - - // *** No Fail except during prep_unstake beyond this point *** - - // we don't unlock immediately - Self::prep_unstake(&collator, less, false)?; - - let n = if state.is_active() { - Self::update_top_candidates( - collator.clone(), - before_stake, - // safe because total >= stake - before_total - before_stake, - state.stake, - state.total - state.stake, - ) - } else { - 0u32 - }; - CandidatePool::::insert(&collator, state); - - // increment rewards and update number of rewarded blocks - Self::do_inc_collator_reward(&collator, before_stake); - - Self::deposit_event(Event::CollatorStakedLess(collator, before_stake, after)); - Ok(Some(::WeightInfo::candidate_stake_less( - n, - T::MaxDelegatorsPerCollator::get(), - )) - .into()) - } - - /// Join the set of delegators by delegating to a collator candidate. - /// - /// The account that wants to delegate cannot be part of the collator - /// candidates set as well. - /// - /// The caller must _not_ have a delegation. If that is the case, they - /// are required to first remove the delegation. - /// - /// The amount staked must be larger than the minimum required to become - /// a delegator as set in the pallet's configuration. - /// - /// As only `MaxDelegatorsPerCollator` are allowed to delegate a given - /// collator, the amount staked must be larger than the lowest one in - /// the current set of delegator for the operation to be meaningful. - /// - /// The collator's total stake as well as the pallet's total stake are - /// increased accordingly. - /// - /// Emits `Delegation`. - /// Emits `DelegationReplaced` if the candidate has - /// `MaxDelegatorsPerCollator` many delegations but this delegator - /// staked more than one of the other delegators of this candidate. - #[pallet::call_index(12)] - #[pallet::weight(::WeightInfo::join_delegators( - T::MaxTopCandidates::get(), - T::MaxDelegatorsPerCollator::get() - ))] - pub fn join_delegators( - origin: OriginFor, collator: ::Source, amount: BalanceOf, - ) -> DispatchResultWithPostInfo { - let acc = ensure_signed(origin)?; - let collator = T::Lookup::lookup(collator)?; - - // check balance - ensure!( - pallet_balances::Pallet::::free_balance(acc.clone()) >= amount.into(), - pallet_balances::Error::::InsufficientBalance - ); - - // first delegation - ensure!(DelegatorState::::get(&acc).is_none(), Error::::AlreadyDelegating); - ensure!(amount >= T::MinDelegatorStake::get(), Error::::DelegationBelowMin); - - // cannot be a collator candidate and delegator with same AccountId - ensure!(Self::is_active_candidate(&acc).is_none(), Error::::CandidateExists); - ensure!( - Unstaking::::get(&acc).len().saturated_into::() < T::MaxUnstakeRequests::get(), - Error::::CannotJoinBeforeUnlocking - ); - // cannot delegate if number of delegations in this round exceeds - // MaxDelegationsPerRound - let delegation_counter = Self::get_delegation_counter(&acc)?; - - // prepare update of collator state - let mut state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; - let num_delegations_pre_insertion: u32 = state.delegators.len().saturated_into(); - - ensure!(!state.is_leaving(), Error::::CannotDelegateIfLeaving); - let delegation = Stake { - owner: acc.clone(), - amount, - }; - - // attempt to insert delegator and check for uniqueness - // NOTE: excess is handled below because we support replacing a delegator with - // fewer stake - let insert_delegator = state - .delegators - // we handle TooManyDelegators error below in do_update_delegator - .try_insert(delegation.clone()) - .unwrap_or(true); - // should never fail but let's be safe - ensure!(insert_delegator, Error::::DelegatorExists); - - let delegator_state = Delegator { - amount, - owner: collator.clone(), - }; - let CandidateOf:: { - stake: old_stake, - total: old_total, - .. - } = state; - - // update state and potentially prepare kicking a delegator with less staked - // amount (includes setting rewards for kicked delegator) - let state = if num_delegations_pre_insertion == T::MaxDelegatorsPerCollator::get() { - Self::do_update_delegator(delegation, state)? - } else { - state.total = state.total.saturating_add(amount); - state - }; - let new_total = state.total; - - // *** No Fail except during increase_lock beyond this point *** - - // lock stake - Self::increase_lock(&acc, amount, BalanceOf::::zero())?; - - // update top candidates and total amount at stake - let n = if state.is_active() { - Self::update_top_candidates( - collator.clone(), - old_stake, - // safe because total >= stake - old_total - old_stake, - state.stake, - state.total - state.stake, - ) - } else { - 0u32 - }; - - // update states - CandidatePool::::insert(&collator, state); - DelegatorState::::insert(&acc, delegator_state); - LastDelegation::::insert(&acc, delegation_counter); - - // initiate rewarded counter to match the current authored counter of the - // candidate - BlocksRewarded::::insert(&acc, BlocksAuthored::::get(&collator)); - - Self::deposit_event(Event::Delegation(acc, amount, collator, new_total)); - Ok(Some(::WeightInfo::join_delegators( - n, - T::MaxDelegatorsPerCollator::get(), - )) - .into()) - } - - /// Leave the set of delegators and, by implication, revoke the ongoing - /// delegation. - /// - /// All staked funds are not unlocked immediately, but they are added to - /// the queue of pending unstaking, and will effectively be released - /// after `StakeDuration` blocks from the moment the delegator leaves. - /// - /// This operation reduces the total stake of the pallet as well as the - /// stakes of all collators that were delegated, potentially affecting - /// their chances to be included in the set of candidates in the next - /// rounds. - /// - /// Automatically increments the accumulated rewards of the origin of - /// the current delegation. - /// - /// Emits `DelegatorLeft`. - #[pallet::call_index(13)] - #[pallet::weight(::WeightInfo::leave_delegators( - T::MaxTopCandidates::get(), - T::MaxDelegatorsPerCollator::get() - ))] - pub fn leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { - let acc = ensure_signed(origin)?; - let delegator = DelegatorState::::get(&acc).ok_or(Error::::DelegatorNotFound)?; - let collator = delegator.owner; - Self::delegator_leaves_collator(acc.clone(), collator)?; - - // *** No Fail beyond this point *** - - DelegatorState::::remove(&acc); - - Self::deposit_event(Event::DelegatorLeft(acc, delegator.amount)); - Ok(Some(::WeightInfo::leave_delegators( - 1, - T::MaxDelegatorsPerCollator::get(), - )) - .into()) - } - - /// Increase the stake for delegating a collator candidate. - /// - /// If not in the set of candidates, staking enough funds allows the - /// collator candidate to be added to it. - /// - /// Emits `DelegatorStakedMore`. - #[pallet::call_index(14)] - #[pallet::weight(::WeightInfo::delegator_stake_more( - T::MaxTopCandidates::get(), - T::MaxDelegatorsPerCollator::get(), - T::MaxUnstakeRequests::get().saturated_into::()) - )] - pub fn delegator_stake_more(origin: OriginFor, more: BalanceOf) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - ensure!(!more.is_zero(), Error::::ValStakeZero); - - let mut delegation = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; - let candidate = delegation.owner.clone(); - let mut collator = CandidatePool::::get(&candidate).ok_or(Error::::CandidateNotFound)?; - ensure!(!collator.is_leaving(), Error::::CannotDelegateIfLeaving); - let stake_after = delegation - .try_increment(candidate.clone(), more) - .map_err(|_| Error::::DelegationNotFound)?; - - // *** No Fail except during increase_lock beyond this point *** - - // update lock - let unstaking_len = Self::increase_lock(&delegator, stake_after, more)?; - - let CandidateOf:: { - stake: before_stake, - total: before_total, - .. - } = collator; - collator.inc_delegator(delegator.clone(), more); - let after = collator.total; - - // update top candidates and total amount at stake - let n = if collator.is_active() { - Self::update_top_candidates( - candidate.clone(), - before_stake, - // safe because total >= stake - before_total - before_stake, - collator.stake, - collator.total - collator.stake, - ) - } else { - 0u32 - }; - - // increment rewards and update number of rewarded blocks - Self::do_inc_delegator_reward(&delegator, stake_after.saturating_sub(more), &candidate); - - CandidatePool::::insert(&candidate, collator); - DelegatorState::::insert(&delegator, delegation); - - Self::deposit_event(Event::DelegatorStakedMore(delegator, candidate, before_total, after)); - Ok(Some(::WeightInfo::delegator_stake_more( - n, - T::MaxDelegatorsPerCollator::get(), - unstaking_len, - )) - .into()) - } - - /// Reduce the stake for delegating a collator candidate. - /// - /// If the new amount of staked fund is not large enough, the collator - /// could be removed from the set of collator candidates and not be - /// considered for authoring the next blocks. - /// - /// The unstaked funds are not release immediately to the account, but - /// they will be available after `StakeDuration` blocks. - /// - /// The remaining staked funds must still be larger than the minimum - /// required by this pallet to maintain the status of delegator. - /// - /// The resulting total amount of funds staked must be within the - /// allowed range as set in the pallet's configuration. - /// - /// Emits `DelegatorStakedLess`. - #[pallet::call_index(15)] - #[pallet::weight(::WeightInfo::delegator_stake_less( - T::MaxTopCandidates::get(), - T::MaxDelegatorsPerCollator::get() - ))] - pub fn delegator_stake_less(origin: OriginFor, less: BalanceOf) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - ensure!(!less.is_zero(), Error::::ValStakeZero); - - let mut delegation = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; - let candidate = delegation.owner.clone(); - let mut collator = CandidatePool::::get(&candidate).ok_or(Error::::CandidateNotFound)?; - ensure!(!collator.is_leaving(), Error::::CannotDelegateIfLeaving); - let stake_after = delegation - .try_decrement(candidate.clone(), less) - .map_err(|_| Error::::DelegationNotFound)? - .ok_or(Error::::Underflow)?; - - ensure!( - stake_after >= T::MinDelegatorStake::get(), - Error::::DelegationBelowMin - ); - - // *** No Fail except during prep_unstake beyond this point *** - - Self::prep_unstake(&delegator, less, false)?; - - let CandidateOf:: { - stake: before_stake, - total: before_total, - .. - } = collator; - collator.dec_delegator(delegator.clone(), less); - let after = collator.total; - - // update top candidates and total amount at stake - let n = if collator.is_active() { - Self::update_top_candidates( - candidate.clone(), - before_stake, - // safe because total >= stake - before_total - before_stake, - collator.stake, - collator.total - collator.stake, - ) - } else { - 0u32 - }; - - // increment rewards and update number of rewarded blocks - Self::do_inc_delegator_reward(&delegator, stake_after.saturating_add(less), &candidate); - - CandidatePool::::insert(&candidate, collator); - DelegatorState::::insert(&delegator, delegation); - - Self::deposit_event(Event::DelegatorStakedLess(delegator, candidate, before_total, after)); - Ok(Some(::WeightInfo::delegator_stake_less( - n, - T::MaxDelegatorsPerCollator::get(), - )) - .into()) - } - - /// Unlock all previously staked funds that are now available for - /// unlocking by the origin account after `StakeDuration` blocks have - /// elapsed. - /// - /// Weight: O(U) where U is the number of locked unstaking requests - /// bounded by `MaxUnstakeRequests`. - /// - Reads: [Origin Account], Unstaking, Locks - /// - Writes: Unstaking, Locks - /// - Kills: Unstaking & Locks if no balance is locked anymore - /// # - #[pallet::call_index(16)] - #[pallet::weight(::WeightInfo::unlock_unstaked( - T::MaxUnstakeRequests::get().saturated_into::() - ))] - pub fn unlock_unstaked( - origin: OriginFor, target: ::Source, - ) -> DispatchResultWithPostInfo { - ensure_signed(origin)?; - let target = T::Lookup::lookup(target)?; - - let unstaking_len = Self::do_unlock(&target)?; - - Ok(Some(::WeightInfo::unlock_unstaked(unstaking_len)).into()) - } - - /// Claim block authoring rewards for the target address. - /// - /// Requires `Rewards` to be set beforehand, which can by triggered by - /// any of the following options - /// * Calling increment_{collator, delegator}_rewards (active) - /// * Altering your stake (active) - /// * Leaving the network as a collator (active) - /// * Revoking a delegation as a delegator (active) - /// * Being a delegator whose collator left the network, altered their - /// stake or incremented rewards (passive) - /// - /// The dispatch origin can be any signed one, e.g., anyone can claim - /// for anyone. - /// - /// Emits `Rewarded`. - #[pallet::call_index(17)] - #[pallet::weight(::WeightInfo::claim_rewards())] - pub fn claim_rewards(origin: OriginFor) -> DispatchResult { - let target = ensure_signed(origin)?; - - // reset rewards - let rewards = Rewards::::take(&target); - ensure!(!rewards.is_zero(), Error::::RewardsNotFound); - - // mint into target - let rewards = T::Currency::deposit_into_existing(&target, rewards)?; - - Self::deposit_event(Event::Rewarded(target, rewards.peek())); - - Ok(()) - } - - /// Actively increment the rewards of a collator. - /// - /// The same effect is triggered by changing the stake or leaving the - /// network. - /// - /// The dispatch origin must be a collator. - #[pallet::call_index(18)] - #[pallet::weight(::WeightInfo::increment_collator_rewards())] - pub fn increment_collator_rewards(origin: OriginFor) -> DispatchResult { - let collator = ensure_signed(origin)?; - let state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; - - // increment rewards and update number of rewarded blocks - Self::do_inc_collator_reward(&collator, state.stake); - - Ok(()) - } - - /// Actively increment the rewards of a delegator. - /// - /// The same effect is triggered by changing the stake or revoking - /// delegations. - /// - /// The dispatch origin must be a delegator. - #[pallet::call_index(19)] - #[pallet::weight(::WeightInfo::increment_delegator_rewards())] - pub fn increment_delegator_rewards(origin: OriginFor) -> DispatchResult { - let delegator = ensure_signed(origin)?; - let delegation = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; - let collator = delegation.owner; - - // increment rewards and update number of rewarded blocks - Self::do_inc_delegator_reward(&delegator, delegation.amount, &collator); - - Ok(()) - } - - /// Executes the annual reduction of the reward rates for collators and - /// delegators. - /// - /// Moreover, sets rewards for all collators and delegators - /// before adjusting the inflation. - /// - /// The dispatch origin can be any signed one because we bail if called - /// too early. - /// - /// Emits `RoundInflationSet`. - #[pallet::call_index(20)] - #[pallet::weight(::WeightInfo::execute_scheduled_reward_change(T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get()))] - pub fn execute_scheduled_reward_change(origin: OriginFor) -> DispatchResultWithPostInfo { - ensure_signed(origin)?; - - let now = frame_system::Pallet::::block_number(); - let year = now / T::BLOCKS_PER_YEAR; - - // We can already mutate thanks to extrinsics being transactional - let last_update = LastRewardReduction::::mutate(|last_year| { - let old = *last_year; - *last_year = old.saturating_add(T::BlockNumber::one()); - old - }); - // Bail if less than a year (in terms of number of blocks) has passed since the - // last update - ensure!(year > last_update, Error::::TooEarly); - - // Calculate new inflation based on last year - let inflation = InflationConfig::::get(); - - // collator reward rate decreases by 2% p.a. of the previous one - let c_reward_rate = inflation.collator.reward_rate.annual * Perquintill::from_percent(98); - - // delegator reward rate should be 6% in 2nd year and 0% afterwards - let d_reward_rate = if year == T::BlockNumber::one() { - Perquintill::from_percent(6) - } else { - Perquintill::zero() - }; - - // Update inflation and increment rewards - let (num_col, num_del) = Self::do_set_inflation( - T::BLOCKS_PER_YEAR, - inflation.collator.max_rate, - c_reward_rate, - inflation.delegator.max_rate, - d_reward_rate, - )?; - - Ok(Some(::WeightInfo::set_inflation(num_col, num_del)).into()) - } - } - - impl Pallet { - /// Check whether an account is currently delegating. - pub fn is_delegator(acc: &T::AccountId) -> bool { - DelegatorState::::get(acc).is_some() - } - - /// Check whether an account is currently a collator candidate and - /// whether their state is CollatorStatus::Active. - /// - /// Returns Some(is_active) if the account is a candidate, else None. - pub fn is_active_candidate(acc: &T::AccountId) -> Option { - if let Some(state) = CandidatePool::::get(acc) { - Some(state.status == CandidateStatus::Active) - } else { - None - } - } - /// Set the annual inflation rate to derive per-round inflation. - /// - /// The inflation details are considered valid if the annual reward rate - /// is approximately the per-block reward rate multiplied by the - /// estimated* total number of blocks per year. - /// - /// The estimated average block time is twelve seconds. - /// - /// NOTE: Iterates over CandidatePool and for each candidate over their - /// delegators to update their rewards before the reward rates change. - /// Needs to be improved when scaling up `MaxTopCandidates`. - /// - /// Emits `RoundInflationSet`. - fn do_set_inflation( - blocks_per_year: T::BlockNumber, col_max_rate: Perquintill, col_reward_rate: Perquintill, - del_max_rate: Perquintill, del_reward_rate: Perquintill, - ) -> Result<(u32, u32), DispatchError> { - // Check validity of new inflation - let inflation = InflationInfo::new( - blocks_per_year.saturated_into(), - col_max_rate, - col_reward_rate, - del_max_rate, - del_reward_rate, - ); - ensure!( - inflation.is_valid(T::BLOCKS_PER_YEAR.saturated_into()), - Error::::InvalidSchedule - ); - - // Increment rewards for all collators and delegators due to change of reward - // rates - let mut num_delegators = 0u32; - CandidatePool::::iter().for_each(|(id, state)| { - // increment collator rewards - Self::do_inc_collator_reward(&id, state.stake); - // increment delegator rewards - state.delegators.into_iter().for_each(|delegator_state| { - Self::do_inc_delegator_reward(&delegator_state.owner, delegator_state.amount, &id); - num_delegators = num_delegators.saturating_add(1u32); - }); - }); - - // Update inflation - InflationConfig::::put(inflation); - Self::deposit_event(Event::RoundInflationSet( - col_max_rate, - col_reward_rate, - del_max_rate, - del_reward_rate, - )); - - Ok((CandidatePool::::count(), num_delegators)) - } - - /// Update the top candidates and total amount at stake after mutating - /// an active candidate's stake. - /// - /// NOTE: It is assumed that the calling context checks whether the - /// collator candidate is currently active before calling this function. - fn update_top_candidates( - candidate: T::AccountId, old_self: BalanceOf, old_delegators: BalanceOf, new_self: BalanceOf, - new_delegators: BalanceOf, - ) -> u32 { - let mut top_candidates = TopCandidates::::get(); - let num_top_candidates: u32 = top_candidates.len().saturated_into(); - let old_stake = Stake { - owner: candidate.clone(), - amount: old_self.saturating_add(old_delegators), - }; - let new_stake = Stake { - owner: candidate.clone(), - amount: new_self.saturating_add(new_delegators), - }; - - // update TopCandidates set - let maybe_top_candidate_update = if let Ok(i) = top_candidates.linear_search(&old_stake) { - // case 1: candidate is member of TopCandidates with old stake - top_candidates.mutate(|vec| { - if let Some(stake) = vec.get_mut(i) { - stake.amount = new_stake.amount; - } - }); - Some((Some(i), top_candidates)) - } else if top_candidates.try_insert_replace(new_stake.clone()).is_ok() { - // case 2: candidate ascends into TopCandidates with new stake - // and might replace another candidate if TopCandidates is full - Self::deposit_event(Event::EnteredTopCandidates(candidate)); - Some((None, top_candidates)) - } else { - // case 3: candidate neither was nor will be member of TopCandidates - None - }; - - // update storage for TotalCollatorStake and TopCandidates - if let Some((maybe_old_idx, top_candidates)) = maybe_top_candidate_update { - let max_selected_candidates = MaxSelectedCandidates::::get().saturated_into::(); - let was_collating = maybe_old_idx.map(|i| i < max_selected_candidates).unwrap_or(false); - let is_collating = top_candidates - .linear_search(&new_stake) - .map(|i| i < max_selected_candidates) - .unwrap_or(false); - - // update TopCollatorStake storage iff candidate was or will be a collator - match (was_collating, is_collating) { - (true, true) => { - Self::update_total_stake_by(new_self, new_delegators, old_self, old_delegators); - } - (true, false) => { - // candidate left the collator set because they staked less and have been - // replaced by the next candidate in the queue at position - // min(max_selected_candidates, top_candidates) - 1 in TopCandidates - let new_col_idx = max_selected_candidates.min(top_candidates.len()).saturating_sub(1); - - // get displacer - let (add_collators, add_delegators) = Self::get_top_candidate_stake_at(&top_candidates, new_col_idx) - // shouldn't be possible to fail, but we handle it gracefully - .unwrap_or((new_self, new_delegators)); - Self::update_total_stake_by(add_collators, add_delegators, old_self, old_delegators); - } - (false, true) => { - // candidate pushed out the least staked collator which is now at position - // min(max_selected_top_candidates, top_candidates - 1) in TopCandidates - let old_col_idx = max_selected_candidates.min(top_candidates.len().saturating_sub(1)); - - // get amount to subtract from TotalCollatorStake - let (drop_self, drop_delegators) = Self::get_top_candidate_stake_at(&top_candidates, old_col_idx) - // default to zero if candidate DNE, e.g. TopCandidates is not full - .unwrap_or((BalanceOf::::zero(), BalanceOf::::zero())); - Self::update_total_stake_by(new_self, new_delegators, drop_self, drop_delegators); - } - _ => {} - } - - // update TopCandidates storage - TopCandidates::::put(top_candidates); - } - - num_top_candidates - } - - /// Retrieve the staked amounts (self, sum of delegators) of member of - /// [TopCandidates] at the given index, if it exists. - fn get_top_candidate_stake_at( - top_candidates: &OrderedSet, T::MaxTopCandidates>, index: usize, - ) -> Option<(BalanceOf, BalanceOf)> { - top_candidates - .get(index) - .and_then(|stake| CandidatePool::::get(&stake.owner)) - // SAFETY: the total is always more than the stake - .map(|state| (state.stake, state.total - state.stake)) - } - - /// Mutate the [TotalCollatorStake] by both incrementing and decreasing - /// it by the provided values. - fn update_total_stake_by( - add_collators: BalanceOf, add_delegators: BalanceOf, sub_collators: BalanceOf, - sub_delegators: BalanceOf, - ) { - TotalCollatorStake::::mutate(|total| { - total.collators = total - .collators - .saturating_sub(sub_collators) - .saturating_add(add_collators); - total.delegators = total - .delegators - .saturating_sub(sub_delegators) - .saturating_add(add_delegators); - }); - } - - /// Iterate over the top `MaxSelectedCandidates` many collators in terms - /// of cumulated stake (self + from delegators) from the [TopCandidates] - /// and recalculate the [TotalCollatorStake] from scratch. - /// - /// NOTE: Should only be called in rare circumstances in which we cannot - /// guarantee a single candidate's stake has changed, e.g. on genesis or - /// when a collator leaves. Otherwise, please use - /// [update_total_stake_by]. - fn update_total_stake() -> (u32, u32) { - let mut num_of_delegators = 0u32; - let mut collator_stake = BalanceOf::::zero(); - let mut delegator_stake = BalanceOf::::zero(); - - let collators = Self::selected_candidates(); - - // Snapshot exposure for round for weighting reward distribution - for account in collators.iter() { - let state = - CandidatePool::::get(account).expect("all members of TopCandidates must be candidates q.e.d"); - num_of_delegators = num_of_delegators.max(state.delegators.len().saturated_into::()); - - // sum up total stake and amount of collators, delegators - let amount_collator = state.stake; - collator_stake = collator_stake.saturating_add(state.stake); - // safe to subtract because total >= stake - let amount_delegators = state.total - amount_collator; - delegator_stake = delegator_stake.saturating_add(amount_delegators); - } - - TotalCollatorStake::::mutate(|total| { - total.collators = collator_stake; - total.delegators = delegator_stake; - }); - - // return number of selected candidates and the corresponding number of their - // delegators for post-weight correction - (collators.len().saturated_into(), num_of_delegators) - } - - /// Update the collator's state by removing the delegator's stake and - /// starting the process to unlock the delegator's staked funds as well - /// as incrementing their accumulated rewards. - /// - /// This operation affects the pallet's total stake. - fn delegator_leaves_collator(delegator: T::AccountId, collator: T::AccountId) -> DispatchResult { - let mut state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; - - let delegator_stake = state - .delegators - .remove(&Stake { - owner: delegator.clone(), - // amount is irrelevant for removal - amount: BalanceOf::::one(), - }) - .map(|nom| nom.amount) - .ok_or(Error::::DelegatorNotFound)?; - - let CandidateOf:: { - stake: old_stake, - total: old_total, - .. - } = state; - state.total = state.total.saturating_sub(delegator_stake); - let new_total = state.total; - - // increment rewards and kill storage for number of rewarded blocks - Self::do_inc_delegator_reward(&delegator, delegator_stake, &collator); - BlocksRewarded::::remove(&delegator); - - // we don't unlock immediately - Self::prep_unstake(&delegator, delegator_stake, false)?; - - // update top candidates and total amount at stake - if state.is_active() { - Self::update_top_candidates( - collator.clone(), - old_stake, - // safe because total >= stake - old_total - old_stake, - state.stake, - state.total - state.stake, - ); - } - CandidatePool::::insert(&collator, state); - - Self::deposit_event(Event::DelegatorLeftCollator( - delegator, - collator, - delegator_stake, - new_total, - )); - Ok(()) - } - - /// Return the best `MaxSelectedCandidates` many candidates. - /// - /// In case a collator from last round was replaced by a candidate with - /// the same total stake during sorting, we revert this swap to - /// prioritize collators over candidates. - pub fn selected_candidates() -> BoundedVec { - let candidates = TopCandidates::::get(); - - // Should never fail since WASM usize are 32bits and native are either 32 or 64 - let top_n = MaxSelectedCandidates::::get().saturated_into::(); - - log::trace!("{} Candidates for {} Collator seats", candidates.len(), top_n); - - // Choose the top MaxSelectedCandidates qualified candidates - let collators = candidates - .into_iter() - .take(top_n) - .filter(|x| x.amount >= T::MinCollatorStake::get()) - .map(|x| x.owner) - .collect::>(); - - collators.try_into().expect("Did not extend Collators q.e.d.") - } - - /// Attempts to add the stake to the set of delegators of a collator - /// which already reached its maximum size by removing an already - /// existing delegator with less staked value. If the given staked - /// amount is at most the minimum staked value of the original delegator - /// set, an error is returned. - /// - /// Sets rewards for the removed delegator. - /// - /// Returns a tuple which contains the updated candidate state as well - /// as the potentially replaced delegation which will be used later when - /// updating the storage of the replaced delegator. - /// - /// Emits `DelegationReplaced` if the stake exceeds one of the current - /// delegations. - #[allow(clippy::type_complexity)] - fn do_update_delegator( - stake: Stake>, - mut state: Candidate, T::MaxDelegatorsPerCollator>, - ) -> Result, DispatchError> { - // attempt to replace the last element of the set - let stake_to_remove = state - .delegators - .try_insert_replace(stake.clone()) - .map_err(|err_too_many| { - if err_too_many { - Error::::TooManyDelegators - } else { - // should never occur because we previously check this case, but let's be sure - Error::::AlreadyDelegating - } - })?; - - state.total = state.total.saturating_add(stake.amount); - - if let Some(stake_to_remove) = stake_to_remove { - // update total stake - state.total = state.total.saturating_sub(stake_to_remove.amount); - - // update rewards for kicked delegator - Self::do_inc_delegator_reward(&stake_to_remove.owner, stake_to_remove.amount, &state.id); - // prepare unstaking for kicked delegator - Self::prep_unstake(&stake_to_remove.owner, stake_to_remove.amount, true)?; - // remove Delegator state for kicked delegator - DelegatorState::::remove(&stake_to_remove.owner); - - Self::deposit_event(Event::DelegationReplaced( - stake.owner, - stake.amount, - stake_to_remove.owner, - stake_to_remove.amount, - state.id.clone(), - state.total, - )); - } - - Ok(state) - } - - /// Either set or increase the BalanceLock of target account to - /// amount. - /// - /// Consumes unstaked balance which can be unlocked in the future up to - /// amount and updates `Unstaking` storage accordingly. - fn increase_lock(who: &T::AccountId, amount: BalanceOf, more: BalanceOf) -> Result { - ensure!( - pallet_balances::Pallet::::free_balance(who) >= amount.into(), - pallet_balances::Error::::InsufficientBalance - ); - - let mut unstaking_len = 0u32; - - // *** No Fail except during Unstaking mutation beyond this point *** - - // update Unstaking by consuming up to {amount | more} - Unstaking::::try_mutate(who, |unstaking| -> DispatchResult { - // reduce {amount | more} by unstaking until either {amount | more} is zero or - // no unstaking is left - // if more is set, we only want to reduce by more to achieve 100 - 40 + 30 = 90 - // locked - let mut amt_consuming_unstaking = if more.is_zero() { amount } else { more }; - unstaking_len = unstaking.len().saturated_into(); - for (block_number, locked_balance) in unstaking.clone() { - if amt_consuming_unstaking.is_zero() { - break; - } else if locked_balance > amt_consuming_unstaking { - // amount is only reducible by locked_balance - amt_consuming_unstaking - let delta = locked_balance.saturating_sub(amt_consuming_unstaking); - // replace old entry with delta - unstaking - .try_insert(block_number, delta) - .map_err(|_| Error::::NoMoreUnstaking)?; - amt_consuming_unstaking = Zero::zero(); - } else { - // amount is either still reducible or reached - amt_consuming_unstaking = amt_consuming_unstaking.saturating_sub(locked_balance); - unstaking.remove(&block_number); - } - } - Ok(()) - })?; - - // Either set a new lock or potentially extend the existing one if amount - // exceeds the currently locked amount - T::Currency::extend_lock(STAKING_ID, who, amount, WithdrawReasons::all()); - - Ok(unstaking_len) - } - - /// Set the unlocking block for the account and corresponding amount - /// which can be unlocked via `unlock_unstaked` after waiting at - /// least for `StakeDuration` many blocks. - /// - /// Throws if the amount is zero (unlikely) or if active unlocking - /// requests exceed limit. The latter defends against stake reduction - /// spamming. - fn prep_unstake(who: &T::AccountId, amount: BalanceOf, is_removal: bool) -> DispatchResult { - // should never occur but let's be safe - ensure!(!amount.is_zero(), Error::::StakeNotFound); - - let now = frame_system::Pallet::::block_number(); - let unlock_block = now.saturating_add(T::StakeDuration::get()); - let mut unstaking = Unstaking::::get(who); - - let allowed_unstakings = if is_removal { - // the account was forcedly removed and we allow to fill all unstake requests - T::MaxUnstakeRequests::get() - } else { - // we need to reserve a free slot for a forced removal of the account - T::MaxUnstakeRequests::get().saturating_sub(1) - }; - ensure!( - unstaking.len().saturated_into::() < allowed_unstakings, - Error::::NoMoreUnstaking, - ); - - // if existent, we have to add the current amount of same unlock_block, because - // insert overwrites the current value - let amount = amount.saturating_add(*unstaking.get(&unlock_block).unwrap_or(&BalanceOf::::zero())); - unstaking - .try_insert(unlock_block, amount) - .map_err(|_| Error::::NoMoreUnstaking)?; - Unstaking::::insert(who, unstaking); - Ok(()) - } - - /// Clear the CandidatePool of the candidate and remove all delegations - /// to the candidate. Moreover, prepare unstaking for the candidate and - /// their former delegations. - fn remove_candidate( - collator: &T::AccountId, state: &CandidateOf, - ) -> DispatchResult { - // iterate over delegators - for stake in &state.delegators[..] { - // increment rewards - Self::do_inc_delegator_reward(&stake.owner, stake.amount, collator); - // prepare unstaking of delegator - Self::prep_unstake(&stake.owner, stake.amount, true)?; - // remove delegation from delegator state - if let Some(mut delegator) = DelegatorState::::get(&stake.owner) { - delegator - .try_clear(collator.clone()) - .map_err(|_| Error::::DelegationNotFound)?; - DelegatorState::::remove(&stake.owner); - } - } - // prepare unstaking of collator candidate - Self::prep_unstake(&state.id, state.stake, true)?; - - // *** No Fail beyond this point *** - - // increment rewards of collator - Self::do_inc_collator_reward(collator, state.stake); - - // disable validator for next session if they were in the set of validators - pallet_session::Pallet::::validators() - .into_iter() - .enumerate() - .find_map(|(i, id)| { - if ::ValidatorIdOf::convert(collator.clone()) - == Some(id) - { - Some(i) - } else { - None - } - }) - .map(u32::saturated_from::) - // FIXME: Does not prevent the collator from being able to author a block in this (or potentially the next) session. See https://github.com/paritytech/substrate/issues/8004 - .map(pallet_session::Pallet::::disable_index); - - // Kill storage - BlocksAuthored::::remove(collator); - BlocksRewarded::::remove(collator); - CandidatePool::::remove(collator); - Ok(()) - } - - /// Withdraw all staked currency which was unstaked at least - /// `StakeDuration` blocks ago. - fn do_unlock(who: &T::AccountId) -> Result { - let now = frame_system::Pallet::::block_number(); - let mut unstaking = Unstaking::::get(who); - let unstaking_len = unstaking.len().saturated_into::(); - ensure!(!unstaking.is_empty(), Error::::UnstakingIsEmpty); - - let mut total_unlocked: BalanceOf = Zero::zero(); - let mut total_locked: BalanceOf = Zero::zero(); - let mut expired = Vec::new(); - - // check potential unlocks - for (block_number, locked_balance) in unstaking.clone().into_iter() { - if block_number <= now { - expired.push(block_number); - total_unlocked = total_unlocked.saturating_add(locked_balance); - } else { - total_locked = total_locked.saturating_add(locked_balance); - } - } - for block_number in expired { - unstaking.remove(&block_number); - } - - // iterate balance locks to retrieve amount of locked balance - let locks = Locks::::get(who); - total_locked = if let Some(BalanceLock { amount, .. }) = locks.iter().find(|l| l.id == STAKING_ID) { - amount.saturating_sub(total_unlocked.into()).into() - } else { - // should never fail to find the lock since we checked whether unstaking is not - // empty but let's be safe - Zero::zero() - }; - - if total_locked.is_zero() { - T::Currency::remove_lock(STAKING_ID, who); - Unstaking::::remove(who); - } else { - T::Currency::set_lock(STAKING_ID, who, total_locked, WithdrawReasons::all()); - Unstaking::::insert(who, unstaking); - } - - Ok(unstaking_len) - } - - /// Checks whether a delegator can still delegate in this round, e.g., - /// if they have not delegated MaxDelegationsPerRound many times - /// already in this round. - fn get_delegation_counter(delegator: &T::AccountId) -> Result { - let last_delegation = LastDelegation::::get(delegator); - let round = Round::::get(); - - // reset counter if the round advanced since last delegation - let counter = if last_delegation.round < round.current { - 0u32 - } else { - last_delegation.counter - }; - - ensure!( - counter < T::MaxDelegationsPerRound::get(), - Error::::DelegationsPerRoundExceeded - ); - - Ok(DelegationCounter { - round: round.current, - counter: counter.saturating_add(1), - }) - } - - /// Calculates the network rewards per block with the current data and - /// issues these rewards to the network. The imbalance will be handled - /// in `on_initialize` by adding it to the free balance of - /// `NetworkRewardBeneficiary`. - /// - /// Over the course of an entire year, the network rewards equal the - /// maximum annual collator staking rewards multiplied with the - /// NetworkRewardRate. E.g., assuming 10% annual collator reward rate, - /// 10% max staking rate, 200k KILT max collator stake and 30 collators: - /// NetworkRewards = NetworkRewardRate * 10% * 10% * 200_000 KILT * 30 - /// - /// The expected rewards are the product of - /// * the current total maximum collator rewards - /// * and the configured NetworkRewardRate - /// - /// `col_reward_rate_per_block * col_max_stake * max_num_of_collators * - /// NetworkRewardRate` - fn issue_network_reward() -> NegativeImbalanceOf { - // Multiplication with Perquintill cannot overflow - let max_col_rewards = InflationConfig::::get().collator.reward_rate.per_block - * MaxCollatorCandidateStake::::get() - * MaxSelectedCandidates::::get().into(); - let network_reward = T::NetworkRewardRate::get() * max_col_rewards; - - T::Currency::issue(network_reward) - } - - /// Calculates the collator staking rewards for authoring `multiplier` - /// many blocks based on the given stake. - /// - /// Depends on the current total issuance and staking reward - /// configuration for collators. - pub(crate) fn calc_block_rewards_collator(stake: BalanceOf, multiplier: BalanceOf) -> BalanceOf { - let total_issuance = T::Currency::total_issuance(); - let TotalStake { - collators: total_collators, - .. - } = TotalCollatorStake::::get(); - let staking_rate = Perquintill::from_rational(total_collators, total_issuance); - - InflationConfig::::get() - .collator - .compute_reward::(stake, staking_rate, multiplier) - } - - /// Calculates the delegator staking rewards for `multiplier` many - /// blocks based on the given stake. - /// - /// Depends on the current total issuance and staking reward - /// configuration for delegators. - pub(crate) fn calc_block_rewards_delegator(stake: BalanceOf, multiplier: BalanceOf) -> BalanceOf { - let total_issuance = T::Currency::total_issuance(); - let TotalStake { - delegators: total_delegators, - .. - } = TotalCollatorStake::::get(); - let staking_rate = Perquintill::from_rational(total_delegators, total_issuance); - - InflationConfig::::get() - .delegator - .compute_reward::(stake, staking_rate, multiplier) - } - - /// Increment the accumulated rewards of a collator. - /// - /// Updates Rewarded(col) and sets BlocksRewarded(col) to equal - /// BlocksAuthored(col). - fn do_inc_collator_reward(acc: &T::AccountId, stake: BalanceOf) { - let count_authored = BlocksAuthored::::get(acc); - // We can already mutate thanks to extrinsics being transactional - let count_rewarded = BlocksRewarded::::mutate(acc, |rewarded| { - let old = *rewarded; - *rewarded = count_authored; - old - }); - let unclaimed_blocks = count_authored.saturating_sub(count_rewarded); - - Rewards::::mutate(acc, |reward| { - *reward = reward.saturating_add(Self::calc_block_rewards_collator(stake, unclaimed_blocks.into())); - }); - } - - /// Increment the accumulated rewards of a delegator by checking the - /// number of authored blocks by the collator. - /// - /// Updates Rewarded(del) and sets BlocksRewarded(del) to equal - /// BlocksAuthored(col). - fn do_inc_delegator_reward(acc: &T::AccountId, stake: BalanceOf, col: &T::AccountId) { - let count_authored = BlocksAuthored::::get(col); - // We can already mutate thanks to extrinsics being transactional - let count_rewarded = BlocksRewarded::::mutate(acc, |rewarded| { - let old = *rewarded; - *rewarded = count_authored; - old - }); - let unclaimed_blocks = count_authored.saturating_sub(count_rewarded); - - Rewards::::mutate(acc, |reward| { - *reward = reward.saturating_add(Self::calc_block_rewards_delegator(stake, unclaimed_blocks.into())) - }); - } - } - - impl pallet_authorship::EventHandler for Pallet - where - T: Config + pallet_authorship::Config + pallet_session::Config, - { - /// Increments the reward counter of the block author by the current - /// number of collators in the session. - fn note_author(author: T::AccountId) { - // should always include state except if the collator has been forcedly removed - // via `force_remove_candidate` in the current or previous round - if CandidatePool::::get(&author).is_some() { - // necessary to compensate for a potentially fluctuating number of collators - let authors = pallet_session::Pallet::::validators(); - BlocksAuthored::::mutate(&author, |count| { - *count = count.saturating_add(authors.len().saturated_into::()); - }); - } - - frame_system::Pallet::::register_extra_weight_unchecked( - T::DbWeight::get().reads_writes(2, 1), - DispatchClass::Mandatory, - ); - } - } - - impl pallet_session::SessionManager for Pallet { - /// 1. A new session starts. - /// 2. In hook new_session: Read the current top n candidates from the - /// TopCandidates and assign this set to author blocks for the next - /// session. - /// 3. AuRa queries the authorities from the session pallet for - /// this session and picks authors on round-robin-basis from list of - /// authorities. - fn new_session(new_index: SessionIndex) -> Option> { - log::debug!( - "assembling new collators for new session {} at #{:?}", - new_index, - frame_system::Pallet::::block_number(), - ); - - frame_system::Pallet::::register_extra_weight_unchecked( - T::DbWeight::get().reads(2), - DispatchClass::Mandatory, - ); - - let collators = Pallet::::selected_candidates().to_vec(); - if collators.is_empty() { - // we never want to pass an empty set of collators. This would brick the chain. - log::error!("💥 keeping old session because of empty collator set!"); - None - } else { - Some(collators) - } - } - - fn end_session(_end_index: SessionIndex) { - // we too are not caring. - } - - fn start_session(_start_index: SessionIndex) { - // we too are not caring. - } - } - - impl ShouldEndSession for Pallet { - fn should_end_session(now: T::BlockNumber) -> bool { - frame_system::Pallet::::register_extra_weight_unchecked( - T::DbWeight::get().reads(2), - DispatchClass::Mandatory, - ); - - let mut round = Round::::get(); - // always update when a new round should start - if round.should_update(now) { - true - } else if ForceNewRound::::get() { - frame_system::Pallet::::register_extra_weight_unchecked( - T::DbWeight::get().writes(2), - DispatchClass::Mandatory, - ); - // check for forced new round - ForceNewRound::::put(false); - round.update(now); - Round::::put(round); - Self::deposit_event(Event::NewRound(round.first, round.current)); - true - } else { - false - } - } - } - - impl EstimateNextSessionRotation for Pallet { - fn average_session_length() -> T::BlockNumber { - Round::::get().length - } - - fn estimate_current_session_progress(now: T::BlockNumber) -> (Option, Weight) { - let round = Round::::get(); - let passed_blocks = now.saturating_sub(round.first); - - ( - Some(Permill::from_rational(passed_blocks, round.length)), - // One read for the round info, blocknumber is read free - T::DbWeight::get().reads(1), - ) - } - - fn estimate_next_session_rotation(_now: T::BlockNumber) -> (Option, Weight) { - let round = Round::::get(); - - ( - Some(round.first + round.length), - // One read for the round info, blocknumber is read free - T::DbWeight::get().reads(1), - ) - } - } -} diff --git a/pallets/parachain-staking/src/migration.rs b/pallets/parachain-staking/src/migration.rs deleted file mode 100644 index 79e74681a..000000000 --- a/pallets/parachain-staking/src/migration.rs +++ /dev/null @@ -1,17 +0,0 @@ -// KILT Blockchain – https://botlabs.org -// Copyright (C) 2019-2023 BOTLabs GmbH - -// The KILT Blockchain 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. - -// The KILT Blockchain 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 this program. If not, see . - -// If you feel like getting in touch with us, you can do so at info@botlabs.org diff --git a/pallets/parachain-staking/src/mock.rs b/pallets/parachain-staking/src/mock.rs deleted file mode 100644 index 838b523ba..000000000 --- a/pallets/parachain-staking/src/mock.rs +++ /dev/null @@ -1,421 +0,0 @@ -// KILT Blockchain – https://botlabs.org -// Copyright (C) 2019-2023 BOTLabs GmbH - -// The KILT Blockchain 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. - -// The KILT Blockchain 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 this program. If not, see . - -// If you feel like getting in touch with us, you can do so at info@botlabs.org -//! Test utilities - -#![allow(clippy::from_over_into)] - -use frame_support::{ - assert_ok, construct_runtime, parameter_types, - traits::{Currency, GenesisBuild, OnFinalize, OnInitialize, OnUnbalanced}, -}; -use pallet_authorship::EventHandler; -use sp_consensus_aura::sr25519::AuthorityId; -use sp_core::H256; -use sp_runtime::{ - impl_opaque_keys, - testing::{Header, UintAuthorityId}, - traits::{BlakeTwo256, ConvertInto, IdentityLookup, OpaqueKeys}, - Perbill, Perquintill, -}; -use sp_std::fmt::Debug; - -use crate::{self as stake, types::NegativeImbalanceOf}; - -use super::*; - -pub(crate) type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -pub(crate) type Block = frame_system::mocking::MockBlock; -pub(crate) type Balance = u128; -pub(crate) type AccountId = u64; -pub(crate) type BlockNumber = u64; - -pub(crate) const MILLI_KILT: Balance = 10u128.pow(12); -pub(crate) const MAX_COLLATOR_STAKE: Balance = 200_000 * 1000 * MILLI_KILT; -pub(crate) const BLOCKS_PER_ROUND: BlockNumber = 5; -pub(crate) const DECIMALS: Balance = 1000 * MILLI_KILT; -pub(crate) const TREASURY_ACC: AccountId = u64::MAX; - -// Configure a mock runtime to test the pallet. -construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - Aura: pallet_aura::{Pallet, Storage}, - Session: pallet_session::{Pallet, Call, Storage, Event, Config}, - StakePallet: stake::{Pallet, Call, Storage, Config, Event}, - Authorship: pallet_authorship::{Pallet, Storage}, - } -); - -parameter_types! { - pub const BlockHashCount: u64 = 250; - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - pub const SS58Prefix: u8 = 42; -} - -impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type DbWeight = (); - type RuntimeOrigin = RuntimeOrigin; - type Index = u64; - type BlockNumber = BlockNumber; - type RuntimeCall = RuntimeCall; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Header = Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type BlockWeights = (); - type BlockLength = (); - type SS58Prefix = SS58Prefix; - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} -parameter_types! { - pub const ExistentialDeposit: Balance = 1; -} - -impl pallet_balances::Config for Test { - type MaxLocks = (); - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; - type Balance = Balance; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); -} - -impl pallet_aura::Config for Test { - type AuthorityId = AuthorityId; - type DisabledValidators = (); - type MaxAuthorities = MaxCollatorCandidates; -} - -impl pallet_authorship::Config for Test { - type FindAuthor = pallet_session::FindAccountFromAuthorIndex; - type EventHandler = Pallet; -} - -parameter_types! { - pub const MinBlocksPerRound: BlockNumber = 3; - pub const StakeDuration: u32 = 2; - pub const ExitQueueDelay: u32 = 2; - pub const DefaultBlocksPerRound: BlockNumber = BLOCKS_PER_ROUND; - pub const MinCollators: u32 = 2; - pub const MaxDelegationsPerRound: u32 = 2; - #[derive(Debug, Eq, PartialEq)] - pub const MaxDelegatorsPerCollator: u32 = 4; - pub const MinCollatorStake: Balance = 10; - #[derive(Debug, Eq, PartialEq)] - pub const MaxCollatorCandidates: u32 = 10; - pub const MinDelegatorStake: Balance = 5; - pub const MaxUnstakeRequests: u32 = 6; - pub const NetworkRewardRate: Perquintill = Perquintill::from_percent(10); - pub const NetworkRewardStart: BlockNumber = 5 * 5 * 60 * 24 * 36525 / 100; -} - -pub struct ToBeneficiary(); -impl OnUnbalanced> for ToBeneficiary { - fn on_nonzero_unbalanced(amount: NegativeImbalanceOf) { - // Must resolve into existing but better to be safe. - ::Currency::resolve_creating(&TREASURY_ACC, amount); - } -} - -impl Config for Test { - type RuntimeEvent = RuntimeEvent; - type Currency = Balances; - type CurrencyBalance = ::Balance; - type MinBlocksPerRound = MinBlocksPerRound; - type DefaultBlocksPerRound = DefaultBlocksPerRound; - type StakeDuration = StakeDuration; - type ExitQueueDelay = ExitQueueDelay; - type MinCollators = MinCollators; - type MinRequiredCollators = MinCollators; - type MaxDelegationsPerRound = MaxDelegationsPerRound; - type MaxDelegatorsPerCollator = MaxDelegatorsPerCollator; - type MinCollatorStake = MinCollatorStake; - type MinCollatorCandidateStake = MinCollatorStake; - type MaxTopCandidates = MaxCollatorCandidates; - type MinDelegatorStake = MinDelegatorStake; - type MaxUnstakeRequests = MaxUnstakeRequests; - type NetworkRewardRate = NetworkRewardRate; - type NetworkRewardStart = NetworkRewardStart; - type NetworkRewardBeneficiary = ToBeneficiary; - type WeightInfo = (); - const BLOCKS_PER_YEAR: Self::BlockNumber = 5 * 60 * 24 * 36525 / 100; -} - -impl_opaque_keys! { - pub struct MockSessionKeys { - pub aura: Aura, - } -} - -parameter_types! { - pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17); -} - -impl pallet_session::Config for Test { - type RuntimeEvent = RuntimeEvent; - type ValidatorId = AccountId; - type ValidatorIdOf = ConvertInto; - type ShouldEndSession = StakePallet; - type NextSessionRotation = StakePallet; - type SessionManager = StakePallet; - type SessionHandler = ::KeyTypeIdProviders; - type Keys = MockSessionKeys; - type WeightInfo = (); -} - -parameter_types! { - pub const MinimumPeriod: u64 = 1; -} - -impl pallet_timestamp::Config for Test { - type Moment = u64; - type OnTimestampSet = (); - type MinimumPeriod = MinimumPeriod; - type WeightInfo = (); -} - -pub(crate) struct ExtBuilder { - // endowed accounts with balances - balances: Vec<(AccountId, Balance)>, - // [collator, amount] - collators: Vec<(AccountId, Balance)>, - // [delegator, collator, delegation_amount] - delegators: Vec<(AccountId, AccountId, Balance)>, - // inflation config - inflation_config: InflationInfo, - // blocks per round - blocks_per_round: BlockNumber, -} - -impl Default for ExtBuilder { - fn default() -> ExtBuilder { - ExtBuilder { - balances: vec![], - delegators: vec![], - collators: vec![], - blocks_per_round: BLOCKS_PER_ROUND, - inflation_config: InflationInfo::new( - ::BLOCKS_PER_YEAR, - Perquintill::from_percent(10), - Perquintill::from_percent(15), - Perquintill::from_percent(40), - Perquintill::from_percent(10), - ), - } - } -} - -impl ExtBuilder { - #[must_use] - pub(crate) fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self { - self.balances = balances; - self - } - - #[must_use] - pub(crate) fn with_collators(mut self, collators: Vec<(AccountId, Balance)>) -> Self { - self.collators = collators; - self - } - - #[must_use] - pub(crate) fn with_delegators(mut self, delegators: Vec<(AccountId, AccountId, Balance)>) -> Self { - self.delegators = delegators; - self - } - - #[must_use] - pub(crate) fn with_inflation( - mut self, col_max: u64, col_rewards: u64, d_max: u64, d_rewards: u64, blocks_per_round: BlockNumber, - ) -> Self { - self.inflation_config = InflationInfo::new( - ::BLOCKS_PER_YEAR, - Perquintill::from_percent(col_max), - Perquintill::from_percent(col_rewards), - Perquintill::from_percent(d_max), - Perquintill::from_percent(d_rewards), - ); - self.blocks_per_round = blocks_per_round; - - self - } - - #[must_use] - pub(crate) fn set_blocks_per_round(mut self, blocks_per_round: BlockNumber) -> Self { - self.blocks_per_round = blocks_per_round; - self - } - - pub(crate) fn build(self) -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default() - .build_storage::() - .expect("Frame system builds valid default genesis config"); - - pallet_balances::GenesisConfig:: { - balances: self.balances.clone(), - } - .assimilate_storage(&mut t) - .expect("Pallet balances storage can be assimilated"); - - let mut stakers: Vec<(AccountId, Option, Balance)> = Vec::new(); - for collator in self.collators.clone() { - stakers.push((collator.0, None, collator.1)); - } - for delegator in self.delegators.clone() { - stakers.push((delegator.0, Some(delegator.1), delegator.2)); - } - stake::GenesisConfig:: { - stakers, - inflation_config: self.inflation_config.clone(), - max_candidate_stake: 160_000_000 * DECIMALS, - } - .assimilate_storage(&mut t) - .expect("Parachain Staking's storage can be assimilated"); - - // stashes are the AccountId - let session_keys: Vec<_> = self - .collators - .iter() - .map(|(k, _)| { - ( - *k, - *k, - MockSessionKeys { - aura: UintAuthorityId(*k).to_public_key(), - }, - ) - }) - .collect(); - - // NOTE: this will initialize the aura authorities - // through OneSessionHandler::on_genesis_session - pallet_session::GenesisConfig:: { keys: session_keys } - .assimilate_storage(&mut t) - .expect("Session Pallet's storage can be assimilated"); - - let mut ext = sp_io::TestExternalities::new(t); - - if self.blocks_per_round != BLOCKS_PER_ROUND { - ext.execute_with(|| { - StakePallet::set_blocks_per_round(RuntimeOrigin::root(), self.blocks_per_round) - .expect("Ran into issues when setting blocks_per_round"); - }); - } - - ext.execute_with(|| System::set_block_number(1)); - ext - } -} - -/// Compare whether the difference of both sides is at most `precision * left`. -pub(crate) fn almost_equal(left: Balance, right: Balance, precision: Perbill) -> bool { - let err = precision * left; - left.max(right) - left.min(right) <= err -} - -/// Incrementelly traverses from the current block to the provided one and -/// potentially sets block authors. -/// -/// If for a block `i` the corresponding index of the authors input is set, this -/// account is regarded to be the block author and thus gets noted. -/// -/// NOTE: At most, this updates the RewardCount of the block author but does not -/// increment rewards or claim them. Please use `roll_to_claim_rewards` in that -/// case. -pub(crate) fn roll_to(n: BlockNumber, authors: Vec>) { - while System::block_number() < n { - if let Some(Some(author)) = authors.get((System::block_number()) as usize) { - StakePallet::note_author(*author); - } - >::on_finalize(System::block_number()); - System::set_block_number(System::block_number() + 1); - >::on_initialize(System::block_number()); - } -} - -#[allow(unused_must_use)] -/// Incrementelly traverses from the current block to the provided one and -/// potentially sets block authors. -/// -/// If existent, rewards of the block author and their delegators are -/// incremented and claimed. -/// -/// If for a block `i` the corresponding index of the authors input is set, this -/// account is regarded to be the block author and thus gets noted. -pub(crate) fn roll_to_claim_rewards(n: BlockNumber, authors: Vec>) { - while System::block_number() < n { - if let Some(Some(author)) = authors.get((System::block_number()) as usize) { - StakePallet::note_author(*author); - // author has to increment rewards before claiming - assert_ok!(StakePallet::increment_collator_rewards(RuntimeOrigin::signed(*author))); - // author claims rewards - assert_ok!(StakePallet::claim_rewards(RuntimeOrigin::signed(*author))); - - // claim rewards for delegators - let col_state = StakePallet::candidate_pool(author).expect("Block author must be candidate"); - for delegation in col_state.delegators { - // delegator has to increment rewards before claiming - StakePallet::increment_delegator_rewards(RuntimeOrigin::signed(delegation.owner)); - // NOTE: cannot use assert_ok! as we sometimes expect zero rewards for - // delegators such that the claiming would throw - StakePallet::claim_rewards(RuntimeOrigin::signed(delegation.owner)); - } - } - >::on_finalize(System::block_number()); - System::set_block_number(System::block_number() + 1); - >::on_initialize(System::block_number()); - } -} - -pub(crate) fn last_event() -> pallet::Event { - events().pop().expect("Event expected") -} - -pub(crate) fn events() -> Vec> { - System::events() - .into_iter() - .map(|r| r.event) - .filter_map(|e| { - if let RuntimeEvent::StakePallet(inner) = e { - Some(inner) - } else { - None - } - }) - .collect::>() -} diff --git a/pallets/parachain-staking/src/set.rs b/pallets/parachain-staking/src/set.rs deleted file mode 100644 index d8bf16bae..000000000 --- a/pallets/parachain-staking/src/set.rs +++ /dev/null @@ -1,553 +0,0 @@ -// KILT Blockchain – https://botlabs.org -// Copyright (C) 2019-2023 BOTLabs GmbH - -// The KILT Blockchain 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. - -// The KILT Blockchain 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 this program. If not, see . - -// If you feel like getting in touch with us, you can do so at info@botlabs.org - -use frame_support::{traits::Get, BoundedVec, DefaultNoBound, RuntimeDebug}; -use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; -use scale_info::TypeInfo; -use sp_runtime::{traits::Zero, SaturatedConversion}; -#[cfg(feature = "std")] -use sp_std::prelude::*; -use sp_std::{ - cmp::Ordering, - convert::TryInto, - ops::{Index, Range, RangeFull}, -}; - -/// An ordered set backed by `BoundedVec`. -#[derive(PartialEq, Eq, Encode, Decode, DefaultNoBound, Clone, TypeInfo, MaxEncodedLen, RuntimeDebug)] -#[scale_info(skip_type_params(S))] -#[codec(mel_bound(T: MaxEncodedLen))] -pub struct OrderedSet>(BoundedVec); - -impl> OrderedSet { - /// Create a new empty set. - pub fn new() -> Self { - Self(BoundedVec::default()) - } - - /// Creates an ordered set from a `BoundedVec`. - /// - /// The vector will be sorted reversily (from greatest to lowest) and - /// deduped first. - pub fn from(bv: BoundedVec) -> Self { - let mut v = bv.into_inner(); - v.sort_by(|a, b| b.cmp(a)); - v.dedup(); - Self::from_sorted_set(v.try_into().map_err(|_| ()).expect("No values were added")) - } - - /// Create a set from a `BoundedVec`. - /// - /// Assumes that `v` is sorted reversely (from greatest to lowest) and only - /// contains unique elements. - pub fn from_sorted_set(bv: BoundedVec) -> Self { - Self(bv) - } - - /// Mutate the set without restrictions. After the set was mutated it will - /// be resorted and deduplicated. - pub fn mutate)>(&mut self, function: F) { - function(&mut self.0); - (self.0[..]).sort_by(|a, b| b.cmp(a)); - - // TODO: add dedup to BoundedVec - let mut i: usize = 0; - let mut next = i.saturating_add(1); - while next < self.len() { - if self[i] == self[next] { - self.0.remove(next); - } else { - i = next; - next = next.saturating_add(1); - } - } - } - - /// Inserts an element, if no equal item exist in the set. - /// - /// Returns an error if insertion would exceed the bounded vec's max size. - /// The error contains the index where the element would be inserted, if - /// enough space would be left. - /// - /// Returns true if the item is unique in the set, otherwise returns false. - pub fn try_insert(&mut self, value: T) -> Result { - match self.linear_search(&value) { - Ok(_) => Ok(false), - Err(loc) => { - self.0.try_insert(loc, value).map_err(|_| loc)?; - Ok(true) - } - } - } - - /// Inserts an element, if no equal item exist in the set. If the set is - /// full, but an element with a lower rank is in the set, the element with - /// the lowest rank will be removed and the new element will be added. - /// - /// Returns - /// * Ok(Some(old_element)) if the new element was added and an old element - /// had to be removed. - /// * Ok(None) if the element was added without removing an element. - /// * Err(true) if the set is full and the new element has a lower rank than - /// the lowest element in the set. - /// * Err(false) if the element is already in the set. - pub fn try_insert_replace(&mut self, value: T) -> Result, bool> { - // the highest allowed index - let highest_index: usize = S::get().saturating_sub(1).saturated_into(); - if S::get().is_zero() { - return Err(true); - } - match self.try_insert(value.clone()) { - Err(loc) if loc <= highest_index => { - // always replace the last element - let last_idx = self.len().saturating_sub(1); - // accessing by index wont panic since we checked the index, inserting the item - // at the end of the list to ensure last-in-least-priority-rule for collators. - // sorting algorithm must be stable! - let old = sp_std::mem::replace(&mut self.0[last_idx], value); - self.sort_greatest_to_lowest(); - Ok(Some(old)) - } - Err(_) => Err(true), - Ok(false) => Err(false), - Ok(_) => Ok(None), - } - } - - /// Inserts a new element or updates the value of an existing one. - /// - /// Returns an error if the maximum size of the bounded vec would be - /// exceeded upon insertion. - /// - /// Returns the old value if existing or None if the value did not exist - /// before. - pub fn try_upsert(&mut self, value: T) -> Result, ()> { - match self.linear_search(&value) { - Ok(i) => { - let old = sp_std::mem::replace(&mut self.0[i], value); - self.sort_greatest_to_lowest(); - Ok(Some(old)) - } - Err(i) => { - // Delegator - self.0.try_insert(i, value).map_err(|_| ())?; - Ok(None) - } - } - } - - /// Removes an element. - /// - /// Returns true if removal happened. - pub fn remove(&mut self, value: &T) -> Option { - match self.linear_search(value) { - Ok(loc) => Some(self.0.remove(loc)), - Err(_) => None, - } - } - - /// Return whether the set contains `value`. - pub fn contains(&self, value: &T) -> bool { - self.linear_search(value).is_ok() - } - - /// Iteratively searches this (from greatest to lowest) ordered set for a - /// given element. - /// - /// 1. If the value is found, then Result::Ok is returned, containing the - /// index of the matching element. - /// 2. If the value is not found, then Result::Err is returned, containing - /// the index where a matching element could be inserted while maintaining - /// sorted order. - pub fn linear_search(&self, value: &T) -> Result { - let size = self.0.len(); - let mut loc: usize = size; - // keep running until we find a smaller item - self.0 - .iter() - .enumerate() - .find_map(|(i, v)| { - match (v.cmp(value), loc == size) { - // prevent to have same items - (Ordering::Equal, _) => Some(Ok(i)), - // eventually, we want to return this index but we need to keep checking for Ordering::Equal in case - // value is still in the set - (Ordering::Less, true) => { - // insert after current element - loc = i; - None - } - _ => None, - } - }) - .unwrap_or(Err(loc)) - } - - /// Clear the set. - pub fn clear(&mut self) { - self.0 = BoundedVec::default(); - } - - /// Return the length of the set. - pub fn len(&self) -> usize { - self.0.len() - } - - /// Return whether the set is empty. - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - /// Convert the set to a bounded vector. - pub fn into_bounded_vec(self) -> BoundedVec { - self.0 - } - - /// Returns a reference to an element or None if out of bounds. - pub fn get(&self, index: usize) -> Option<&T> { - self.0.get(index) - } - - /// Sorts from greatest to lowest. - pub fn sort_greatest_to_lowest(&mut self) { - (self.0[..]).sort_by(|a, b| b.cmp(a)); - } -} - -impl> From> for OrderedSet { - fn from(bv: BoundedVec) -> Self { - Self::from(bv) - } -} - -impl> Index for OrderedSet { - type Output = T; - - fn index(&self, index: usize) -> &Self::Output { - &self.0[index] - } -} - -impl> Index> for OrderedSet { - type Output = [T]; - - fn index(&self, range: Range) -> &Self::Output { - &self.0[range] - } -} - -impl> Index for OrderedSet { - type Output = [T]; - - fn index(&self, range: RangeFull) -> &Self::Output { - &self.0[range] - } -} - -impl> IntoIterator for OrderedSet { - type Item = T; - type IntoIter = sp_std::vec::IntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} - -impl> From> for BoundedVec { - fn from(s: OrderedSet) -> Self { - s.0 - } -} - -#[cfg(test)] -mod tests { - use frame_support::parameter_types; - use sp_runtime::RuntimeDebug; - - use crate::{mock::Test, types::StakeOf}; - - use super::*; - - parameter_types! { - #[derive(Eq, PartialEq, RuntimeDebug)] - pub const Zero: u32 = 0; - #[derive(Eq, PartialEq, RuntimeDebug)] - pub const One: u32 = 1; - #[derive(Eq, PartialEq, RuntimeDebug)] - pub const Eight: u32 = 8; - #[derive(Clone, Eq, PartialEq, RuntimeDebug)] - pub const Five: u32 = 5; - } - - #[test] - fn from() { - let v: BoundedVec = vec![4, 2, 3, 4, 3, 1].try_into().unwrap(); - let set: OrderedSet = v.into(); - assert_eq!( - set, - OrderedSet::::from(vec![1, 2, 3, 4].try_into().unwrap()) - ); - } - - #[test] - fn insert() { - let mut set: OrderedSet = OrderedSet::new(); - assert_eq!(set, OrderedSet::::from(vec![].try_into().unwrap())); - - assert_eq!(set.try_insert(1), Ok(true)); - assert_eq!(set, OrderedSet::::from(vec![1].try_into().unwrap())); - - assert_eq!(set.try_insert(5), Ok(true)); - assert_eq!(set, OrderedSet::::from(vec![1, 5].try_into().unwrap())); - - assert_eq!(set.try_insert(3), Ok(true)); - assert_eq!(set, OrderedSet::::from(vec![1, 3, 5].try_into().unwrap())); - - assert_eq!(set.try_insert(3), Ok(false)); - assert_eq!(set, OrderedSet::::from(vec![1, 3, 5].try_into().unwrap())); - } - - #[test] - fn remove() { - let mut set: OrderedSet = OrderedSet::from(vec![1, 2, 3, 4].try_into().unwrap()); - - assert_eq!(set.remove(&5), None); - assert_eq!( - set, - OrderedSet::::from(vec![1, 2, 3, 4].try_into().unwrap()) - ); - - assert_eq!(set.remove(&1), Some(1)); - assert_eq!(set, OrderedSet::::from(vec![2, 3, 4].try_into().unwrap())); - - assert_eq!(set.remove(&3), Some(3)); - assert_eq!(set, OrderedSet::::from(vec![2, 4].try_into().unwrap())); - - assert_eq!(set.remove(&3), None); - assert_eq!(set, OrderedSet::::from(vec![2, 4].try_into().unwrap())); - - assert_eq!(set.remove(&4), Some(4)); - assert_eq!(set, OrderedSet::::from(vec![2].try_into().unwrap())); - - assert_eq!(set.remove(&2), Some(2)); - assert_eq!(set, OrderedSet::::from(vec![].try_into().unwrap())); - - assert_eq!(set.remove(&2), None); - assert_eq!(set, OrderedSet::::from(vec![].try_into().unwrap())); - } - - #[test] - fn contains() { - let set: OrderedSet = OrderedSet::from(vec![1, 2, 3, 4].try_into().unwrap()); - assert!(!set.contains(&5)); - assert!(set.contains(&1)); - assert!(set.contains(&3)); - } - - #[test] - fn clear() { - let mut set: OrderedSet = OrderedSet::from(vec![1, 2, 3, 4].try_into().unwrap()); - set.clear(); - assert_eq!(set, OrderedSet::new()); - } - - #[test] - fn try_insert_replace_integer() { - let mut set: OrderedSet = OrderedSet::from(vec![].try_into().unwrap()); - assert_eq!(set.try_insert_replace(10), Err(true)); - - let mut set: OrderedSet = OrderedSet::from(vec![].try_into().unwrap()); - assert_eq!(set.try_insert_replace(10), Ok(None)); - assert_eq!(set.try_insert_replace(9), Err(true)); - assert_eq!(set.try_insert_replace(11), Ok(Some(10))); - - let mut set: OrderedSet = OrderedSet::from(vec![].try_into().unwrap()); - assert_eq!(set.try_insert_replace(10), Ok(None)); - assert_eq!(set.try_insert_replace(7), Ok(None)); - assert_eq!(set.try_insert_replace(9), Ok(None)); - assert_eq!(set.try_insert_replace(8), Ok(None)); - - assert_eq!(set.clone().into_bounded_vec().into_inner(), vec![10, 9, 8, 7]); - assert_eq!(set.try_insert_replace(5), Ok(None)); - assert!(set.try_insert(11).is_err()); - - assert_eq!(set.try_insert_replace(6), Ok(Some(5))); - assert_eq!(set.clone().into_bounded_vec().into_inner(), vec![10, 9, 8, 7, 6]); - - assert_eq!(set.try_insert_replace(6), Err(false)); - assert_eq!(set.try_insert_replace(5), Err(true)); - - assert_eq!(set.try_insert_replace(10), Err(false)); - assert_eq!(set.try_insert_replace(11), Ok(Some(6))); - assert_eq!(set.into_bounded_vec().into_inner(), vec![11, 10, 9, 8, 7]); - } - - #[test] - fn try_insert_replace_stake() { - let mut set: OrderedSet, Eight> = OrderedSet::from( - vec![ - StakeOf:: { owner: 1, amount: 100 }, - StakeOf:: { owner: 3, amount: 90 }, - StakeOf:: { owner: 5, amount: 80 }, - StakeOf:: { owner: 7, amount: 70 }, - StakeOf:: { owner: 8, amount: 70 }, - StakeOf:: { owner: 9, amount: 60 }, - ] - .try_into() - .unwrap(), - ); - assert_eq!( - set.try_insert_replace(StakeOf:: { owner: 1, amount: 0 }), - Err(false) - ); - assert_eq!( - set.try_insert_replace(StakeOf:: { owner: 7, amount: 100 }), - Err(false) - ); - assert_eq!( - set.try_insert_replace(StakeOf:: { owner: 7, amount: 50 }), - Err(false) - ); - assert_eq!( - set.try_insert_replace(StakeOf:: { owner: 8, amount: 50 }), - Err(false) - ); - assert_eq!( - set.try_insert_replace(StakeOf:: { owner: 2, amount: 100 }), - Ok(None) - ); - assert_eq!( - set.try_insert_replace(StakeOf:: { owner: 2, amount: 90 }), - Err(false) - ); - assert_eq!( - set.try_insert_replace(StakeOf:: { owner: 10, amount: 65 }), - Ok(None) - ); - assert_eq!( - set.try_insert_replace(StakeOf:: { owner: 11, amount: 60 }), - Err(true) - ); - assert_eq!( - set.try_insert_replace(StakeOf:: { owner: 11, amount: 100 }), - Ok(Some(StakeOf:: { owner: 9, amount: 60 })) - ); - } - - #[test] - fn exceeding_max_size_should_fail() { - let mut set: OrderedSet = OrderedSet::from(vec![1, 2, 3, 4, 5].try_into().unwrap()); - let inserted = set.try_insert(6); - - assert!(inserted.is_err()); - } - - #[test] - fn linear_search() { - let set: OrderedSet, Eight> = OrderedSet::from( - vec![ - StakeOf:: { owner: 1, amount: 100 }, - StakeOf:: { owner: 3, amount: 90 }, - StakeOf:: { owner: 5, amount: 80 }, - StakeOf:: { owner: 7, amount: 70 }, - StakeOf:: { owner: 8, amount: 70 }, - StakeOf:: { owner: 9, amount: 60 }, - ] - .try_into() - .unwrap(), - ); - assert_eq!(set.linear_search(&StakeOf:: { owner: 1, amount: 0 }), Ok(0)); - assert_eq!(set.linear_search(&StakeOf:: { owner: 7, amount: 100 }), Ok(3)); - assert_eq!(set.linear_search(&StakeOf:: { owner: 7, amount: 50 }), Ok(3)); - assert_eq!(set.linear_search(&StakeOf:: { owner: 8, amount: 50 }), Ok(4)); - assert_eq!(set.linear_search(&StakeOf:: { owner: 2, amount: 100 }), Err(1)); - assert_eq!(set.linear_search(&StakeOf:: { owner: 2, amount: 90 }), Err(2)); - assert_eq!(set.linear_search(&StakeOf:: { owner: 2, amount: 65 }), Err(5)); - assert_eq!(set.linear_search(&StakeOf:: { owner: 2, amount: 60 }), Err(6)); - assert_eq!(set.linear_search(&StakeOf:: { owner: 2, amount: 59 }), Err(6)); - } - - #[test] - fn upsert_set() { - let mut set: OrderedSet, Eight> = OrderedSet::from( - vec![ - StakeOf:: { owner: 1, amount: 100 }, - StakeOf:: { owner: 3, amount: 90 }, - StakeOf:: { owner: 5, amount: 80 }, - StakeOf:: { owner: 7, amount: 70 }, - StakeOf:: { owner: 9, amount: 60 }, - ] - .try_into() - .unwrap(), - ); - assert_eq!(set.try_insert(StakeOf:: { owner: 2, amount: 75 }), Ok(true)); - assert_eq!( - set, - OrderedSet::from( - vec![ - StakeOf:: { owner: 1, amount: 100 }, - StakeOf:: { owner: 3, amount: 90 }, - StakeOf:: { owner: 5, amount: 80 }, - StakeOf:: { owner: 2, amount: 75 }, - StakeOf:: { owner: 7, amount: 70 }, - StakeOf:: { owner: 9, amount: 60 }, - ] - .try_into() - .unwrap() - ) - ); - assert_eq!( - set.try_upsert(StakeOf:: { owner: 2, amount: 90 }), - Ok(Some(StakeOf:: { owner: 2, amount: 75 })) - ); - assert_eq!( - set, - OrderedSet::from( - vec![ - StakeOf:: { owner: 1, amount: 100 }, - StakeOf:: { owner: 3, amount: 90 }, - StakeOf:: { owner: 2, amount: 90 }, - StakeOf:: { owner: 5, amount: 80 }, - StakeOf:: { owner: 7, amount: 70 }, - StakeOf:: { owner: 9, amount: 60 }, - ] - .try_into() - .unwrap() - ) - ); - assert_eq!( - set.try_upsert(StakeOf:: { owner: 2, amount: 60 }), - Ok(Some(StakeOf:: { owner: 2, amount: 90 })) - ); - assert_eq!( - set, - OrderedSet::from( - vec![ - StakeOf:: { owner: 1, amount: 100 }, - StakeOf:: { owner: 3, amount: 90 }, - StakeOf:: { owner: 5, amount: 80 }, - StakeOf:: { owner: 7, amount: 70 }, - StakeOf:: { owner: 2, amount: 60 }, - StakeOf:: { owner: 9, amount: 60 }, - ] - .try_into() - .unwrap() - ) - ); - } -} diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs deleted file mode 100644 index accc93d1a..000000000 --- a/pallets/parachain-staking/src/tests.rs +++ /dev/null @@ -1,4347 +0,0 @@ -// KILT Blockchain – https://botlabs.org -// Copyright (C) 2019-2023 BOTLabs GmbH - -// The KILT Blockchain 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. - -// The KILT Blockchain 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 this program. If not, see . - -// If you feel like getting in touch with us, you can do so at info@botlabs.org - -//! Unit testing - -use std::{convert::TryInto, iter}; - -use frame_support::{ - assert_noop, assert_ok, storage::bounded_btree_map::BoundedBTreeMap, traits::EstimateNextSessionRotation, - BoundedVec, -}; -use pallet_authorship::EventHandler; -use pallet_balances::{BalanceLock, Error as BalancesError, Reasons}; -use pallet_session::{SessionManager, ShouldEndSession}; -use sp_runtime::{traits::Zero, Perbill, Permill, Perquintill, SaturatedConversion}; - -use kilt_runtime_api_staking::StakingRates; - -use crate::{ - mock::{ - almost_equal, events, last_event, roll_to, roll_to_claim_rewards, AccountId, Balance, Balances, BlockNumber, - ExtBuilder, RuntimeOrigin, Session, StakePallet, System, Test, BLOCKS_PER_ROUND, DECIMALS, TREASURY_ACC, - }, - set::OrderedSet, - types::{ - BalanceOf, Candidate, CandidateStatus, DelegationCounter, Delegator, RoundInfo, Stake, StakeOf, TotalStake, - }, - CandidatePool, Config, Error, Event, Event as StakeEvent, InflationInfo, RewardRate, StakingInfo, STAKING_ID, -}; - -#[test] -fn should_select_collators_genesis_session() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 20), - (3, 20), - (4, 20), - (5, 20), - (6, 20), - (7, 20), - (8, 20), - (9, 20), - (10, 20), - (11, 20), - ]) - .with_collators(vec![(1, 20), (2, 20)]) - .build() - .execute_with(|| { - assert_eq!( - StakePallet::new_session(0) - .expect("first session must return new collators") - .len(), - 2 - ); - assert_eq!( - StakePallet::new_session(1) - .expect("second session must return new collators") - .len(), - 2 - ); - }); -} - -#[test] -fn genesis() { - ExtBuilder::default() - .with_balances(vec![ - (1, 1000), - (2, 300), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 9), - (9, 4), - ]) - .with_collators(vec![(1, 500), (2, 200)]) - .with_delegators(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) - .build() - .execute_with(|| { - assert!(System::events().is_empty()); - - // Collators - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 700, - delegators: 400 - } - ); - assert_eq!( - vec![ - StakeOf:: { owner: 1, amount: 700 }, - StakeOf:: { owner: 2, amount: 400 } - ] - .try_into(), - Ok(StakePallet::top_candidates().into_bounded_vec()) - ); - assert_eq!(CandidatePool::::count(), 2); - - // 1 - assert_eq!(Balances::usable_balance(&1), 500); - assert_eq!(Balances::free_balance(&1), 1000); - assert!(StakePallet::is_active_candidate(&1).is_some()); - assert_eq!( - StakePallet::candidate_pool(&1), - Some( - Candidate::::MaxDelegatorsPerCollator> { - id: 1, - stake: 500, - delegators: OrderedSet::from_sorted_set( - vec![ - StakeOf:: { owner: 3, amount: 100 }, - StakeOf:: { owner: 4, amount: 100 } - ] - .try_into() - .unwrap() - ), - total: 700, - status: CandidateStatus::Active, - } - ) - ); - // 2 - assert_eq!(Balances::usable_balance(&2), 100); - assert_eq!(Balances::free_balance(&2), 300); - assert!(StakePallet::is_active_candidate(&2).is_some()); - assert_eq!( - StakePallet::candidate_pool(&2), - Some( - Candidate::::MaxDelegatorsPerCollator> { - id: 2, - stake: 200, - delegators: OrderedSet::from_sorted_set( - vec![ - StakeOf:: { owner: 5, amount: 100 }, - StakeOf:: { owner: 6, amount: 100 } - ] - .try_into() - .unwrap() - ), - total: 400, - status: CandidateStatus::Active, - } - ) - ); - // Delegators - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 700, - delegators: 400 - } - ); - for x in 3..7 { - assert!(StakePallet::is_delegator(&x)); - assert_eq!(Balances::usable_balance(&x), 0); - assert_eq!(Balances::free_balance(&x), 100); - } - // Uninvolved - for x in 7..10 { - assert!(!StakePallet::is_delegator(&x)); - } - assert_eq!(Balances::free_balance(&7), 100); - assert_eq!(Balances::usable_balance(&7), 100); - assert_eq!(Balances::free_balance(&8), 9); - assert_eq!(Balances::usable_balance(&8), 9); - assert_eq!(Balances::free_balance(&9), 4); - assert_eq!(Balances::usable_balance(&9), 4); - - // Safety first checks - assert_eq!( - StakePallet::max_selected_candidates(), - ::MinCollators::get() - ); - assert_eq!( - StakePallet::round(), - RoundInfo::new(0u32, 0u32.into(), ::DefaultBlocksPerRound::get()) - ); - }); - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - ]) - .with_collators(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) - .with_delegators(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) - .build() - .execute_with(|| { - assert!(System::events().is_empty()); - assert_eq!(CandidatePool::::count(), 5); - - // Collators - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 40, - delegators: 50 - } - ); - assert_eq!( - Ok(StakePallet::top_candidates().into_bounded_vec()), - vec![ - StakeOf:: { owner: 1, amount: 50 }, - StakeOf:: { owner: 2, amount: 40 }, - StakeOf:: { owner: 3, amount: 20 }, - StakeOf:: { owner: 4, amount: 20 }, - StakeOf:: { owner: 5, amount: 10 } - ] - .try_into() - ); - for x in 1..5 { - assert!(StakePallet::is_active_candidate(&x).is_some()); - assert_eq!(Balances::free_balance(&x), 100); - assert_eq!(Balances::usable_balance(&x), 80); - } - assert!(StakePallet::is_active_candidate(&5).is_some()); - assert_eq!(Balances::free_balance(&5), 100); - assert_eq!(Balances::usable_balance(&5), 90); - // Delegators - for x in 6..11 { - assert!(StakePallet::is_delegator(&x)); - assert_eq!(Balances::free_balance(&x), 100); - assert_eq!(Balances::usable_balance(&x), 90); - } - - // Safety first checks - assert_eq!( - StakePallet::max_selected_candidates(), - ::MinCollators::get() - ); - assert_eq!( - StakePallet::round(), - RoundInfo::new(0, 0, ::DefaultBlocksPerRound::get()) - ); - }); -} - -#[test] -fn join_collator_candidates() { - ExtBuilder::default() - .with_balances(vec![ - (1, 1000), - (2, 300), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 9), - (9, 4), - (10, 161_000_000 * DECIMALS), - ]) - .with_collators(vec![(1, 500), (2, 200)]) - .with_delegators(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) - .build() - .execute_with(|| { - assert_eq!(CandidatePool::::count(), 2); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 700, - delegators: 400 - } - ); - assert_noop!( - StakePallet::join_candidates(RuntimeOrigin::signed(1), 11u128,), - Error::::CandidateExists - ); - assert_noop!( - StakePallet::join_delegators(RuntimeOrigin::signed(1), 1, 11u128,), - Error::::CandidateExists - ); - assert_noop!( - StakePallet::join_candidates(RuntimeOrigin::signed(3), 11u128,), - Error::::DelegatorExists - ); - assert_noop!( - StakePallet::join_candidates(RuntimeOrigin::signed(7), 9u128,), - Error::::ValStakeBelowMin - ); - assert_noop!( - StakePallet::join_candidates(RuntimeOrigin::signed(8), 10u128,), - BalancesError::::InsufficientBalance - ); - - assert_eq!(CandidatePool::::count(), 2); - assert!(System::events().is_empty()); - - assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 5)); - assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(7), 10u128,)); - assert_eq!(last_event(), StakeEvent::JoinedCollatorCandidates(7, 10u128)); - - // MaxCollatorCandidateStake - assert_noop!( - StakePallet::join_candidates(RuntimeOrigin::signed(10), 161_000_000 * DECIMALS), - Error::::ValStakeAboveMax - ); - assert_ok!(StakePallet::join_candidates( - RuntimeOrigin::signed(10), - StakePallet::max_candidate_stake() - )); - assert_eq!(CandidatePool::::count(), 4); - - assert_eq!( - last_event(), - StakeEvent::JoinedCollatorCandidates(10, StakePallet::max_candidate_stake(),) - ); - }); -} - -#[test] -fn collator_exit_executes_after_delay() { - ExtBuilder::default() - .with_balances(vec![ - (1, 1000), - (2, 300), - (3, 110), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 9), - (9, 4), - (10, 10), - ]) - .with_collators(vec![(1, 500), (2, 200), (7, 100)]) - .with_delegators(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) - .build() - .execute_with(|| { - assert_eq!(CandidatePool::::count(), 3); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 700, - delegators: 400 - } - ); - assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 5)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 800, - delegators: 400 - } - ); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 7]); - roll_to(4, vec![]); - assert_noop!( - StakePallet::init_leave_candidates(RuntimeOrigin::signed(3)), - Error::::CandidateNotFound - ); - - roll_to(11, vec![]); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(2))); - // Still three, candidate didn't leave yet - assert_eq!(CandidatePool::::count(), 3); - assert_noop!( - StakePallet::join_delegators(RuntimeOrigin::signed(10), 2, 10), - Error::::CannotDelegateIfLeaving - ); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 7]); - assert_eq!(last_event(), StakeEvent::CollatorScheduledExit(2, 2, 4)); - let info = StakePallet::candidate_pool(&2).unwrap(); - assert_eq!(info.status, CandidateStatus::Leaving(4)); - - roll_to(21, vec![]); - assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(2), 2)); - assert_eq!(CandidatePool::::count(), 2); - - // we must exclude leaving collators from rewards while - // holding them retroactively accountable for previous faults - // (within the last T::StakeDuration blocks) - roll_to(25, vec![]); - let expected = vec![ - Event::MaxSelectedCandidatesSet(2, 5), - Event::NewRound(5, 1), - Event::NewRound(10, 2), - Event::LeftTopCandidates(2), - Event::CollatorScheduledExit(2, 2, 4), - Event::NewRound(15, 3), - Event::NewRound(20, 4), - Event::CandidateLeft(2, 400), - Event::NewRound(25, 5), - ]; - assert_eq!(events(), expected); - }); -} - -#[test] -fn collator_selection_chooses_top_candidates() { - ExtBuilder::default() - .with_balances(vec![ - (1, 1000), - (2, 1000), - (3, 1000), - (4, 1000), - (5, 1000), - (6, 1000), - (7, 33), - (8, 33), - (9, 33), - ]) - .with_collators(vec![(1, 100), (2, 90), (3, 80), (4, 70), (5, 60), (6, 50)]) - .build() - .execute_with(|| { - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2]); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 190, - delegators: 0 - } - ); - assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 5)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 400, - delegators: 0 - } - ); - roll_to(8, vec![]); - // should choose top MaxSelectedCandidates (5), in order - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3, 4, 5]); - let expected = vec![Event::MaxSelectedCandidatesSet(2, 5), Event::NewRound(5, 1)]; - assert_eq!(events(), expected); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(6))); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3, 4, 5],); - assert_eq!(last_event(), StakeEvent::CollatorScheduledExit(1, 6, 3)); - - roll_to(15, vec![]); - assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(6), 6)); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3, 4, 5]); - - roll_to(21, vec![]); - assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(6), 69u128)); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3, 4, 6]); - assert_eq!(last_event(), StakeEvent::JoinedCollatorCandidates(6, 69u128)); - - roll_to(27, vec![]); - // should choose top MaxSelectedCandidates (5), in order - let expected = vec![ - Event::MaxSelectedCandidatesSet(2, 5), - Event::NewRound(5, 1), - Event::LeftTopCandidates(6), - Event::CollatorScheduledExit(1, 6, 3), - // TotalCollatorStake is updated once candidate 6 left in `execute_delayed_collator_exits` - Event::NewRound(10, 2), - Event::NewRound(15, 3), - Event::CandidateLeft(6, 50), - Event::NewRound(20, 4), - // 5 had staked 60 which was exceeded by 69 of 6 - Event::EnteredTopCandidates(6), - Event::JoinedCollatorCandidates(6, 69), - Event::NewRound(25, 5), - ]; - assert_eq!(events(), expected); - }); -} - -#[test] -fn exit_queue_with_events() { - ExtBuilder::default() - .with_balances(vec![ - (1, 1000), - (2, 1000), - (3, 1000), - (4, 1000), - (5, 1000), - (6, 1000), - (7, 33), - (8, 33), - (9, 33), - ]) - .with_collators(vec![(1, 100), (2, 90), (3, 80), (4, 70), (5, 60), (6, 50)]) - .with_inflation(100, 15, 40, 10, BLOCKS_PER_ROUND) - .build() - .execute_with(|| { - assert_eq!(CandidatePool::::count(), 6); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2]); - assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 5)); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3, 4, 5]); - - roll_to(8, vec![]); - // should choose top MaxSelectedCandidates (5), in order - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3, 4, 5]); - let mut expected = vec![Event::MaxSelectedCandidatesSet(2, 5), Event::NewRound(5, 1)]; - assert_eq!(events(), expected); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(6))); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3, 4, 5]); - assert_eq!(last_event(), StakeEvent::CollatorScheduledExit(1, 6, 3)); - - roll_to(11, vec![]); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(5))); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3, 4]); - assert_eq!(last_event(), StakeEvent::CollatorScheduledExit(2, 5, 4)); - - assert_eq!(CandidatePool::::count(), 6, "No collators have left yet."); - roll_to(16, vec![]); - assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(6), 6)); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(4))); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3]); - assert_eq!(last_event(), StakeEvent::CollatorScheduledExit(3, 4, 5)); - assert_noop!( - StakePallet::init_leave_candidates(RuntimeOrigin::signed(4)), - Error::::AlreadyLeaving - ); - - assert_eq!(CandidatePool::::count(), 5, "Collator #5 left."); - roll_to(20, vec![]); - assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(5), 5)); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3]); - assert_eq!(CandidatePool::::count(), 4, "Two out of six collators left."); - - roll_to(26, vec![]); - assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(4), 4)); - assert_eq!(CandidatePool::::count(), 3, "Three out of six collators left."); - - roll_to(30, vec![]); - let mut new_events = vec![ - Event::LeftTopCandidates(6), - Event::CollatorScheduledExit(1, 6, 3), - Event::NewRound(10, 2), - Event::LeftTopCandidates(5), - Event::CollatorScheduledExit(2, 5, 4), - Event::NewRound(15, 3), - Event::CandidateLeft(6, 50), - Event::LeftTopCandidates(4), - Event::CollatorScheduledExit(3, 4, 5), - Event::NewRound(20, 4), - Event::CandidateLeft(5, 60), - Event::NewRound(25, 5), - Event::CandidateLeft(4, 70), - Event::NewRound(30, 6), - ]; - expected.append(&mut new_events); - assert_eq!(events(), expected); - }); -} - -#[test] -fn execute_leave_candidates_with_delay() { - ExtBuilder::default() - .with_balances(vec![ - (1, 1000), - (2, 1000), - (3, 1000), - (4, 1000), - (5, 1000), - (6, 1000), - (7, 1000), - (8, 1000), - (9, 1000), - (10, 1000), - (11, 1000), - (12, 1000), - (13, 1000), - (14, 1000), - ]) - .with_collators(vec![ - (1, 10), - (2, 20), - (3, 30), - (4, 40), - (5, 50), - (6, 60), - (7, 70), - (8, 80), - (9, 90), - (10, 100), - ]) - .with_delegators(vec![(11, 1, 110), (12, 1, 120), (13, 2, 130), (14, 2, 140)]) - .with_inflation(100, 15, 40, 10, BLOCKS_PER_ROUND) - .build() - .execute_with(|| { - assert_eq!(CandidatePool::::count(), 10); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 30, - delegators: 500 - } - ); - assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 5)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 300, - delegators: 500 - } - ); - - roll_to(5, vec![]); - // should choose top MaxSelectedCandidates (5), in order - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 1, 10, 9, 8]); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(10))); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(9))); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(1))); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(7))); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(6))); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(5))); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(8))); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(2))); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![4, 3]); - for owner in vec![1, 2, 5, 6, 7, 8, 9, 10].iter() { - assert!(StakePallet::candidate_pool(owner) - .unwrap() - .can_exit(1 + ::ExitQueueDelay::get())); - } - let total_stake = TotalStake { - collators: 70, - delegators: 0, - }; - assert_eq!(StakePallet::total_collator_stake(), total_stake); - assert_eq!( - StakePallet::candidate_pool(1), - Some( - Candidate::::MaxDelegatorsPerCollator> { - id: 1, - stake: 10, - delegators: OrderedSet::from( - vec![ - StakeOf:: { owner: 11, amount: 110 }, - StakeOf:: { owner: 12, amount: 120 } - ] - .try_into() - .unwrap() - ), - total: 240, - status: CandidateStatus::Leaving(3) - } - ) - ); - assert_eq!( - StakePallet::candidate_pool(2), - Some( - Candidate::::MaxDelegatorsPerCollator> { - id: 2, - stake: 20, - delegators: OrderedSet::from( - vec![ - StakeOf:: { owner: 13, amount: 130 }, - StakeOf:: { owner: 14, amount: 140 } - ] - .try_into() - .unwrap() - ), - total: 290, - status: CandidateStatus::Leaving(3) - } - ) - ); - for collator in 5u64..=10u64 { - assert_eq!( - StakePallet::candidate_pool(collator), - Some( - Candidate::::MaxDelegatorsPerCollator> { - id: collator, - stake: collator as u128 * 10u128, - delegators: OrderedSet::from(BoundedVec::default()), - total: collator as u128 * 10u128, - status: CandidateStatus::Leaving(3) - } - ) - ); - assert!(StakePallet::is_active_candidate(&collator).is_some()); - assert!(StakePallet::unstaking(collator).is_empty()); - } - assert_eq!( - StakePallet::delegator_state(11), - Some(Delegator:: { owner: 1, amount: 110 }) - ); - assert_eq!( - StakePallet::delegator_state(12), - Some(Delegator:: { owner: 1, amount: 120 }) - ); - assert_eq!( - StakePallet::delegator_state(13), - Some(Delegator:: { owner: 2, amount: 130 }) - ); - assert_eq!( - StakePallet::delegator_state(14), - Some(Delegator:: { owner: 2, amount: 140 }) - ); - for delegator in 11u64..=14u64 { - assert!(StakePallet::is_delegator(&delegator)); - assert!(StakePallet::unstaking(delegator).is_empty()); - } - - // exits cannot be executed yet but in the next round - roll_to(10, vec![]); - assert_eq!(StakePallet::total_collator_stake(), total_stake); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![4, 3]); - for owner in vec![1, 2, 5, 6, 7, 8, 9, 10].iter() { - assert!(StakePallet::candidate_pool(owner) - .unwrap() - .can_exit(1 + ::ExitQueueDelay::get())); - assert_noop!( - StakePallet::execute_leave_candidates(RuntimeOrigin::signed(*owner), *owner), - Error::::CannotLeaveYet - ); - } - assert_eq!(StakePallet::total_collator_stake(), total_stake); - assert_eq!( - StakePallet::candidate_pool(1), - Some( - Candidate::::MaxDelegatorsPerCollator> { - id: 1, - stake: 10, - delegators: OrderedSet::from( - vec![ - StakeOf:: { owner: 11, amount: 110 }, - StakeOf:: { owner: 12, amount: 120 } - ] - .try_into() - .unwrap() - ), - total: 240, - status: CandidateStatus::Leaving(3) - } - ) - ); - assert_eq!( - StakePallet::candidate_pool(2), - Some( - Candidate::::MaxDelegatorsPerCollator> { - id: 2, - stake: 20, - delegators: OrderedSet::from( - vec![ - StakeOf:: { owner: 13, amount: 130 }, - StakeOf:: { owner: 14, amount: 140 } - ] - .try_into() - .unwrap() - ), - total: 290, - status: CandidateStatus::Leaving(3) - } - ) - ); - for collator in 5u64..=10u64 { - assert_eq!( - StakePallet::candidate_pool(collator), - Some( - Candidate::::MaxDelegatorsPerCollator> { - id: collator, - stake: collator as u128 * 10u128, - delegators: OrderedSet::from(BoundedVec::default()), - total: collator as u128 * 10u128, - status: CandidateStatus::Leaving(3) - } - ) - ); - assert!(StakePallet::is_active_candidate(&collator).is_some()); - assert!(StakePallet::unstaking(collator).is_empty()); - } - assert_eq!( - StakePallet::delegator_state(11), - Some(Delegator:: { owner: 1, amount: 110 }) - ); - assert_eq!( - StakePallet::delegator_state(12), - Some(Delegator:: { owner: 1, amount: 120 }) - ); - assert_eq!( - StakePallet::delegator_state(13), - Some(Delegator:: { owner: 2, amount: 130 }) - ); - assert_eq!( - StakePallet::delegator_state(14), - Some(Delegator:: { owner: 2, amount: 140 }) - ); - for delegator in 11u64..=14u64 { - assert!(StakePallet::is_delegator(&delegator)); - assert!(StakePallet::unstaking(delegator).is_empty()); - } - - // first five exits are executed - roll_to(15, vec![]); - assert_eq!(StakePallet::total_collator_stake(), total_stake); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![4, 3]); - for collator in vec![1u64, 2u64, 5u64, 6u64, 7u64].iter() { - assert_ok!(StakePallet::execute_leave_candidates( - RuntimeOrigin::signed(*collator), - *collator - )); - assert!(StakePallet::candidate_pool(&collator).is_none()); - assert!(StakePallet::is_active_candidate(collator).is_none()); - assert_eq!(StakePallet::unstaking(collator).len(), 1); - } - assert_eq!(CandidatePool::::count(), 5, "Five collators left."); - - assert_eq!(StakePallet::total_collator_stake(), total_stake); - for delegator in 11u64..=14u64 { - assert!(!StakePallet::is_delegator(&delegator)); - assert_eq!(StakePallet::unstaking(delegator).len(), 1); - } - - // last 3 exits are executed - roll_to(20, vec![]); - for collator in 8u64..=10u64 { - assert_ok!(StakePallet::execute_leave_candidates( - RuntimeOrigin::signed(collator), - collator - )); - assert!(StakePallet::candidate_pool(&collator).is_none()); - assert!(StakePallet::is_active_candidate(&collator).is_none()); - assert_eq!(StakePallet::unstaking(collator).len(), 1); - } - assert_eq!(CandidatePool::::count(), 2, "3 collators left."); - }); -} - -// FIXME: Re-enable or potentially remove entirely -#[test] -fn multiple_delegations() { - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - (11, 100), - (12, 100), - // new - (13, 100), - (14, 100), - (15, 100), - (16, 100), - (17, 100), - (18, 100), - (99, 1), - ]) - .with_collators(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) - .with_delegators(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) - .set_blocks_per_round(5) - .build() - .execute_with(|| { - assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 5)); - roll_to( - 8, - vec![Some(1), Some(2), Some(3), Some(4), Some(5), Some(1), Some(2), Some(3)], - ); - // chooses top MaxSelectedCandidates (5), in order - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3, 4, 5]); - let mut expected = vec![Event::MaxSelectedCandidatesSet(2, 5), Event::NewRound(5, 1)]; - assert_eq!(events(), expected); - assert_noop!( - StakePallet::join_delegators(RuntimeOrigin::signed(13), 2, 2), - Error::::DelegationBelowMin, - ); - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(13), 2, 10)); - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(14), 4, 10)); - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(15), 3, 10)); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 4, 3, 5]); - assert_noop!( - StakePallet::join_delegators(RuntimeOrigin::signed(6), 5, 10), - Error::::AlreadyDelegating, - ); - - roll_to( - 16, - vec![Some(1), Some(2), Some(3), Some(4), Some(5), Some(1), Some(2), Some(3)], - ); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 4, 3, 5]); - let mut new = vec![ - Event::Delegation(13, 10, 2, 50), - Event::Delegation(14, 10, 4, 30), - Event::Delegation(15, 10, 3, 30), - Event::NewRound(10, 2), - Event::NewRound(15, 3), - ]; - expected.append(&mut new); - assert_eq!(events(), expected); - - roll_to(21, vec![Some(1), Some(2), Some(3), Some(4), Some(5)]); - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(16), 2, 80)); - assert_noop!( - StakePallet::join_delegators(RuntimeOrigin::signed(99), 3, 11), - BalancesError::::InsufficientBalance - ); - assert_noop!( - StakePallet::join_delegators(RuntimeOrigin::signed(17), 2, 10), - Error::::TooManyDelegators - ); - // kick 13 by staking 1 more (11 > 10) - assert!(StakePallet::unstaking(13).is_empty()); - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(17), 2, 11)); - assert!(StakePallet::delegator_state(13).is_none()); - assert_eq!(StakePallet::unstaking(13).get(&23), Some(&10u128)); - // kick 9 by staking 1 more (11 > 10) - assert!(StakePallet::unstaking(9).is_empty()); - assert!(StakePallet::rewards(9).is_zero()); - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(11), 2, 11)); - // 11 should be initiated with the same rewarded counter as the authored counter - // by their collator 2 - assert_eq!(StakePallet::blocks_rewarded(2), StakePallet::blocks_authored(11)); - - assert!(StakePallet::delegator_state(9).is_none()); - assert_eq!(StakePallet::unstaking(9).get(&23), Some(&10u128)); - assert!(!StakePallet::candidate_pool(2) - .unwrap() - .delegators - .contains(&StakeOf:: { owner: 9, amount: 10 })); - - roll_to(26, vec![Some(1), Some(2), Some(3), Some(4), Some(5)]); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 1, 4, 3, 5]); - let mut new2 = vec![ - Event::NewRound(20, 4), - Event::Delegation(16, 80, 2, 130), - Event::DelegationReplaced(17, 11, 13, 10, 2, 131), - Event::Delegation(17, 11, 2, 131), - Event::DelegationReplaced(11, 11, 9, 10, 2, 132), - Event::Delegation(11, 11, 2, 132), - Event::NewRound(25, 5), - ]; - expected.append(&mut new2); - assert_eq!(events(), expected); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(2))); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 4, 3, 5]); - assert_eq!(last_event(), StakeEvent::CollatorScheduledExit(5, 2, 7)); - - roll_to(31, vec![Some(1), Some(2), Some(3), Some(4), Some(5)]); - let mut new3 = vec![ - Event::LeftTopCandidates(2), - Event::CollatorScheduledExit(5, 2, 7), - Event::NewRound(30, 6), - ]; - expected.append(&mut new3); - assert_eq!(events(), expected); - - // test join_delegator errors - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(18), 1, 10)); - assert_noop!( - StakePallet::join_delegators(RuntimeOrigin::signed(12), 1, 10), - Error::::TooManyDelegators - ); - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(12), 1, 11)); - - // verify that delegations are removed after collator leaves, not before - assert!(StakePallet::candidate_pool(2) - .unwrap() - .delegators - .contains(&StakeOf:: { owner: 8, amount: 10 })); - assert!(StakePallet::candidate_pool(2) - .unwrap() - .delegators - .contains(&StakeOf:: { owner: 17, amount: 11 })); - assert_eq!(StakePallet::delegator_state(8).unwrap().amount, 10); - assert_eq!(StakePallet::delegator_state(17).unwrap().amount, 11); - assert_eq!(Balances::usable_balance(&8), 90); - assert_eq!(Balances::usable_balance(&17), 89); - assert_eq!(Balances::free_balance(&8), 100); - assert_eq!(Balances::free_balance(&17), 100); - - roll_to(35, vec![Some(1), Some(2), Some(3), Some(4)]); - assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(2), 2)); - let mut unbonding_8: BoundedBTreeMap, ::MaxUnstakeRequests> = - BoundedBTreeMap::new(); - assert_ok!(unbonding_8.try_insert(35u64 + ::StakeDuration::get() as u64, 10)); - assert_eq!(StakePallet::unstaking(8), unbonding_8); - let mut unbonding_17: BoundedBTreeMap, ::MaxUnstakeRequests> = - BoundedBTreeMap::new(); - assert_ok!(unbonding_17.try_insert(35u64 + ::StakeDuration::get() as u64, 11)); - assert_eq!(StakePallet::unstaking(17), unbonding_17); - - roll_to(37, vec![Some(1), Some(2)]); - assert!(StakePallet::delegator_state(8).is_none()); - assert!(StakePallet::delegator_state(17).is_none()); - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(8), 8)); - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(17), 17)); - assert_noop!( - StakePallet::unlock_unstaked(RuntimeOrigin::signed(12), 12), - Error::::UnstakingIsEmpty - ); - assert_eq!(Balances::usable_balance(&17), 100); - assert_eq!(Balances::usable_balance(&8), 100); - assert_eq!(Balances::free_balance(&17), 100); - assert_eq!(Balances::free_balance(&8), 100); - }); -} - -#[test] -fn should_update_total_stake() { - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - (11, 161_000_000 * DECIMALS), - ]) - .with_collators(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) - .with_delegators(vec![(7, 1, 10), (8, 2, 10), (9, 2, 10)]) - .set_blocks_per_round(5) - .build() - .execute_with(|| { - let mut old_stake = StakePallet::total_collator_stake(); - assert_eq!( - old_stake, - TotalStake { - collators: 40, - delegators: 30 - } - ); - assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 50)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: old_stake.collators + 50, - ..old_stake - } - ); - - old_stake = StakePallet::total_collator_stake(); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 50)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: old_stake.collators - 50, - ..old_stake - } - ); - - old_stake = StakePallet::total_collator_stake(); - assert_ok!(StakePallet::delegator_stake_more(RuntimeOrigin::signed(7), 50)); - assert_noop!( - StakePallet::delegator_stake_more(RuntimeOrigin::signed(7), 0), - Error::::ValStakeZero - ); - assert_noop!( - StakePallet::delegator_stake_less(RuntimeOrigin::signed(7), 0), - Error::::ValStakeZero - ); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - delegators: old_stake.delegators + 50, - ..old_stake - } - ); - - old_stake = StakePallet::total_collator_stake(); - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(7), 50)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - delegators: old_stake.delegators - 50, - ..old_stake - } - ); - - old_stake = StakePallet::total_collator_stake(); - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(11), 1, 200)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - delegators: old_stake.delegators + 200, - ..old_stake - } - ); - - old_stake = StakePallet::total_collator_stake(); - assert_eq!(StakePallet::delegator_state(11).unwrap().amount, 200); - assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(11))); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - delegators: old_stake.delegators - 200, - ..old_stake - } - ); - - let old_stake = StakePallet::total_collator_stake(); - assert_eq!(StakePallet::delegator_state(8).unwrap().amount, 10); - assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(8))); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - delegators: old_stake.delegators - 10, - ..old_stake - } - ); - - // should immediately affect total stake because collator can't be chosen in - // active set from now on, thus delegated stake is reduced - let old_stake = StakePallet::total_collator_stake(); - assert_eq!(StakePallet::candidate_pool(2).unwrap().total, 30); - assert_eq!(StakePallet::candidate_pool(2).unwrap().stake, 20); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 1]); - assert_eq!( - StakePallet::candidate_pool(2).unwrap().stake, - StakePallet::candidate_pool(3).unwrap().stake - ); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(2))); - let old_stake = TotalStake { - delegators: old_stake.delegators - 10, - // total active collator stake is unchanged because number of selected candidates is 2 and 2's - // replacement has the same self stake as 2 - collators: old_stake.collators, - }; - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 3]); - assert_eq!(StakePallet::total_collator_stake(), old_stake); - - // shouldn't change total stake when 2 leaves - roll_to(10, vec![]); - assert_eq!(StakePallet::total_collator_stake(), old_stake); - assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(2), 2)); - assert_eq!(StakePallet::total_collator_stake(), old_stake); - }) -} - -#[test] -fn collators_bond() { - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - (11, 161_000_000 * DECIMALS), - ]) - .with_collators(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) - .with_delegators(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) - .set_blocks_per_round(5) - .build() - .execute_with(|| { - roll_to(4, vec![]); - assert_noop!( - StakePallet::candidate_stake_more(RuntimeOrigin::signed(6), 50), - Error::::CandidateNotFound - ); - assert_noop!( - StakePallet::candidate_stake_less(RuntimeOrigin::signed(6), 50), - Error::::CandidateNotFound - ); - assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 50)); - assert_noop!( - StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 40), - BalancesError::::InsufficientBalance - ); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(1))); - assert!(StakePallet::candidate_pool(1) - .unwrap() - .can_exit(::ExitQueueDelay::get())); - - assert_noop!( - StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 30), - Error::::CannotStakeIfLeaving - ); - assert_noop!( - StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10), - Error::::CannotStakeIfLeaving - ); - - roll_to(30, vec![]); - assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_noop!( - StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 40), - Error::::CandidateNotFound - ); - assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(2), 80)); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(2), 90)); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(3), 10)); - assert_noop!( - StakePallet::candidate_stake_less(RuntimeOrigin::signed(2), 11), - Error::::Underflow - ); - assert_noop!( - StakePallet::candidate_stake_less(RuntimeOrigin::signed(2), 1), - Error::::ValStakeBelowMin - ); - assert_noop!( - StakePallet::candidate_stake_less(RuntimeOrigin::signed(3), 1), - Error::::ValStakeBelowMin - ); - assert_noop!( - StakePallet::candidate_stake_less(RuntimeOrigin::signed(4), 11), - Error::::ValStakeBelowMin - ); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(4), 10)); - - // MaxCollatorCandidateStake - assert_ok!(StakePallet::join_candidates( - RuntimeOrigin::signed(11), - StakePallet::max_candidate_stake() - )); - assert_noop!( - StakePallet::candidate_stake_more(RuntimeOrigin::signed(11), 1u128), - Error::::ValStakeAboveMax, - ); - }); -} - -#[test] -fn delegators_bond() { - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - ]) - .with_collators(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) - .with_delegators(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10)]) - .set_blocks_per_round(5) - .build() - .execute_with(|| { - roll_to(4, vec![]); - assert_noop!( - StakePallet::join_delegators(RuntimeOrigin::signed(6), 2, 50), - Error::::AlreadyDelegating - ); - assert_noop!( - StakePallet::delegator_stake_more(RuntimeOrigin::signed(1), 50), - Error::::DelegatorNotFound - ); - assert_noop!( - StakePallet::delegator_stake_less(RuntimeOrigin::signed(1), 50), - Error::::DelegatorNotFound - ); - assert_noop!( - StakePallet::delegator_stake_less(RuntimeOrigin::signed(6), 11), - Error::::Underflow - ); - assert_noop!( - StakePallet::delegator_stake_less(RuntimeOrigin::signed(6), 8), - Error::::DelegationBelowMin - ); - assert_ok!(StakePallet::delegator_stake_more(RuntimeOrigin::signed(6), 10)); - assert_noop!( - StakePallet::delegator_stake_more(RuntimeOrigin::signed(6), 81), - BalancesError::::InsufficientBalance - ); - assert_noop!( - StakePallet::join_delegators(RuntimeOrigin::signed(10), 1, 4), - Error::::DelegationBelowMin - ); - - roll_to(9, vec![]); - assert_eq!(Balances::usable_balance(&6), 80); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(1))); - assert!(StakePallet::candidate_pool(1) - .unwrap() - .can_exit(1 + ::ExitQueueDelay::get())); - - roll_to(31, vec![]); - assert!(StakePallet::is_delegator(&6)); - assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert!(!StakePallet::is_delegator(&6)); - assert_eq!(Balances::usable_balance(&6), 80); - assert_eq!(Balances::free_balance(&6), 100); - }); -} - -#[test] -fn should_leave_delegators() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100)]) - .with_collators(vec![(1, 100)]) - .with_delegators(vec![(2, 1, 100)]) - .build() - .execute_with(|| { - assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); - assert!(StakePallet::delegator_state(2).is_none()); - assert!(!StakePallet::candidate_pool(1) - .unwrap() - .delegators - .contains(&StakeOf:: { owner: 2, amount: 100 })); - assert_noop!( - StakePallet::leave_delegators(RuntimeOrigin::signed(2)), - Error::::DelegatorNotFound - ); - assert_noop!( - StakePallet::leave_delegators(RuntimeOrigin::signed(1)), - Error::::DelegatorNotFound - ); - }); -} - -#[test] -fn round_transitions() { - let col_max = 10; - let col_rewards = 15; - let d_max = 40; - let d_rewards = 10; - let inflation = InflationInfo::new( - ::BLOCKS_PER_YEAR, - Perquintill::from_percent(col_max), - Perquintill::from_percent(col_rewards), - Perquintill::from_percent(d_max), - Perquintill::from_percent(d_rewards), - ); - - // round_immediately_jumps_if_current_duration_exceeds_new_blocks_per_round - // change from 5 bpr to 3 in block 5 -> 8 should be new round - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (6, 100)]) - .with_collators(vec![(1, 20)]) - .with_delegators(vec![(2, 1, 10), (3, 1, 10)]) - .with_inflation(col_max, col_rewards, d_max, d_rewards, 5) - .build() - .execute_with(|| { - assert_eq!(inflation, StakePallet::inflation_config()); - roll_to(5, vec![]); - let init = vec![Event::NewRound(5, 1)]; - assert_eq!(events(), init); - assert_ok!(StakePallet::set_blocks_per_round(RuntimeOrigin::root(), 3)); - assert_noop!( - StakePallet::set_blocks_per_round(RuntimeOrigin::root(), 1), - Error::::CannotSetBelowMin - ); - assert_eq!(last_event(), StakeEvent::BlocksPerRoundSet(1, 5, 5, 3)); - - // inflation config should be untouched after per_block update - assert_eq!(inflation, StakePallet::inflation_config()); - - // last round startet at 5 but we are already at 9, so we expect 9 to be the new - // round - roll_to(8, vec![]); - assert_eq!(last_event(), StakeEvent::NewRound(8, 2)) - }); - - // if duration of current round is less than new bpr, round waits until new bpr - // passes - // change from 5 bpr to 3 in block 6 -> 8 should be new round - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (6, 100)]) - .with_collators(vec![(1, 20)]) - .with_delegators(vec![(2, 1, 10), (3, 1, 10)]) - .with_inflation(col_max, col_rewards, d_max, d_rewards, 5) - .build() - .execute_with(|| { - assert_eq!(inflation, StakePallet::inflation_config()); - // Default round every 5 blocks, but MinBlocksPerRound is 3 and we set it to min - // 3 blocks - roll_to(6, vec![]); - // chooses top MaxSelectedCandidates (5), in order - let init = vec![Event::NewRound(5, 1)]; - assert_eq!(events(), init); - assert_ok!(StakePallet::set_blocks_per_round(RuntimeOrigin::root(), 3)); - assert_eq!(last_event(), StakeEvent::BlocksPerRoundSet(1, 5, 5, 3)); - - // inflation config should be untouched after per_block update - assert_eq!(inflation, StakePallet::inflation_config()); - - // there should not be a new event - roll_to(7, vec![]); - assert_eq!(last_event(), StakeEvent::BlocksPerRoundSet(1, 5, 5, 3)); - - roll_to(8, vec![]); - assert_eq!(last_event(), StakeEvent::NewRound(8, 2)) - }); - - // round_immediately_jumps_if_current_duration_exceeds_new_blocks_per_round - // change from 5 bpr (blocks_per_round) to 3 in block 7 -> 8 should be new round - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (6, 100)]) - .with_collators(vec![(1, 20)]) - .with_delegators(vec![(2, 1, 10), (3, 1, 10)]) - .with_inflation(col_max, col_rewards, d_max, d_rewards, 5) - .build() - .execute_with(|| { - // Default round every 5 blocks, but MinBlocksPerRound is 3 and we set it to min - // 3 blocks - assert_eq!(inflation, StakePallet::inflation_config()); - roll_to(7, vec![]); - // chooses top MaxSelectedCandidates (5), in order - let init = vec![Event::NewRound(5, 1)]; - assert_eq!(events(), init); - assert_ok!(StakePallet::set_blocks_per_round(RuntimeOrigin::root(), 3)); - - // inflation config should be untouched after per_block update - assert_eq!(inflation, StakePallet::inflation_config()); - - assert_eq!( - StakePallet::inflation_config(), - InflationInfo::new( - ::BLOCKS_PER_YEAR, - Perquintill::from_percent(col_max), - Perquintill::from_percent(col_rewards), - Perquintill::from_percent(d_max), - Perquintill::from_percent(d_rewards) - ) - ); - assert_eq!(last_event(), StakeEvent::BlocksPerRoundSet(1, 5, 5, 3)); - roll_to(8, vec![]); - - // last round startet at 5, so we expect 8 to be the new round - assert_eq!(last_event(), StakeEvent::NewRound(8, 2)) - }); -} - -#[test] -fn coinbase_rewards_few_blocks_detailed_check() { - ExtBuilder::default() - .with_balances(vec![ - (1, 40_000_000 * DECIMALS), - (2, 40_000_000 * DECIMALS), - (3, 40_000_000 * DECIMALS), - (4, 20_000_000 * DECIMALS), - (5, 20_000_000 * DECIMALS), - ]) - .with_collators(vec![(1, 8_000_000 * DECIMALS), (2, 8_000_000 * DECIMALS)]) - .with_delegators(vec![ - (3, 1, 32_000_000 * DECIMALS), - (4, 1, 16_000_000 * DECIMALS), - (5, 2, 16_000_000 * DECIMALS), - ]) - .with_inflation(10, 15, 40, 15, 5) - .build() - .execute_with(|| { - let inflation = StakePallet::inflation_config(); - let total_issuance = ::Currency::total_issuance(); - assert_eq!(total_issuance, 160_000_000 * DECIMALS); - - // compute rewards - let c_staking_rate = Perquintill::from_rational(16_000_000 * DECIMALS, total_issuance); - let c_rewards: BalanceOf = - inflation - .collator - .compute_reward::(16_000_000 * DECIMALS, c_staking_rate, 1u128); - let d_staking_rate = Perquintill::from_rational(64_000_000 * DECIMALS, total_issuance); - let d_rewards: BalanceOf = - inflation - .delegator - .compute_reward::(64_000_000 * DECIMALS, d_staking_rate, 2u128); - - // set 1 to be author for blocks 1-3, then 2 for blocks 4-5 - let authors: Vec> = - vec![None, Some(1u64), Some(1u64), Some(1u64), Some(2u64), Some(2u64)]; - // let d_rewards: Balance = 3 * 2469135802453333 / 2; - let user_1 = Balances::usable_balance(&1); - let user_2 = Balances::usable_balance(&2); - let user_3 = Balances::usable_balance(&3); - let user_4 = Balances::usable_balance(&4); - let user_5 = Balances::usable_balance(&5); - - assert_eq!(Balances::usable_balance(&1), user_1); - assert_eq!(Balances::usable_balance(&2), user_2); - assert_eq!(Balances::usable_balance(&3), user_3); - assert_eq!(Balances::usable_balance(&4), user_4); - assert_eq!(Balances::usable_balance(&5), user_5); - - // 1 is block author for 1st block - roll_to_claim_rewards(2, authors.clone()); - assert_eq!(Balances::usable_balance(&1), user_1 + c_rewards); - assert_eq!(Balances::usable_balance(&2), user_2); - assert_eq!(Balances::usable_balance(&3), user_3 + d_rewards / 2); - assert_eq!(Balances::usable_balance(&4), user_4 + d_rewards / 4); - assert_eq!(Balances::usable_balance(&5), user_5); - - // 1 is block author for 2nd block - roll_to_claim_rewards(3, authors.clone()); - assert_eq!(Balances::usable_balance(&1), user_1 + 2 * c_rewards); - assert_eq!(Balances::usable_balance(&2), user_2); - assert_eq!(Balances::usable_balance(&3), user_3 + d_rewards); - assert_eq!(Balances::usable_balance(&4), user_4 + d_rewards / 2); - assert_eq!(Balances::usable_balance(&5), user_5); - - // 1 is block author for 3rd block - roll_to_claim_rewards(4, authors.clone()); - assert_eq!(Balances::usable_balance(&1), user_1 + 3 * c_rewards); - assert_eq!(Balances::usable_balance(&2), user_2); - assert_eq!(Balances::usable_balance(&3), user_3 + d_rewards / 2 * 3); - assert_eq!(Balances::usable_balance(&4), user_4 + d_rewards / 4 * 3); - assert_eq!(Balances::usable_balance(&5), user_5); - - // 2 is block author for 4th block - roll_to_claim_rewards(5, authors.clone()); - assert_eq!(Balances::usable_balance(&1), user_1 + 3 * c_rewards); - assert_eq!(Balances::usable_balance(&2), user_2 + c_rewards); - assert_eq!(Balances::usable_balance(&3), user_3 + d_rewards / 2 * 3); - assert_eq!(Balances::usable_balance(&4), user_4 + d_rewards / 4 * 3); - assert_eq!(Balances::usable_balance(&5), user_5 + d_rewards / 4); - assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(5))); - - // 2 is block author for 5th block - roll_to_claim_rewards(6, authors); - assert_eq!(Balances::usable_balance(&1), user_1 + 3 * c_rewards); - assert_eq!(Balances::usable_balance(&2), user_2 + 2 * c_rewards); - assert_eq!(Balances::usable_balance(&3), user_3 + d_rewards / 2 * 3); - assert_eq!(Balances::usable_balance(&4), user_4 + d_rewards / 4 * 3); - // should not receive rewards due to revoked delegation - assert_eq!(Balances::usable_balance(&5), user_5 + d_rewards / 4); - }); -} - -#[test] -fn delegator_should_not_receive_rewards_after_revoking() { - // test edge case of 1 delegator - ExtBuilder::default() - .with_balances(vec![(1, 10_000_000 * DECIMALS), (2, 10_000_000 * DECIMALS)]) - .with_collators(vec![(1, 10_000_000 * DECIMALS)]) - .with_delegators(vec![(2, 1, 10_000_000 * DECIMALS)]) - .with_inflation(10, 15, 40, 15, 5) - .build() - .execute_with(|| { - assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); - let authors: Vec> = (1u64..100u64).map(|_| Some(1u64)).collect(); - assert_eq!(Balances::usable_balance(&1), Balance::zero()); - assert_eq!(Balances::usable_balance(&2), Balance::zero()); - roll_to_claim_rewards(100, authors); - assert!(Balances::usable_balance(&1) > Balance::zero()); - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); - assert_eq!(Balances::usable_balance(&2), 10_000_000 * DECIMALS); - }); - - ExtBuilder::default() - .with_balances(vec![ - (1, 10_000_000 * DECIMALS), - (2, 10_000_000 * DECIMALS), - (3, 10_000_000 * DECIMALS), - ]) - .with_collators(vec![(1, 10_000_000 * DECIMALS)]) - .with_delegators(vec![(2, 1, 10_000_000 * DECIMALS), (3, 1, 10_000_000 * DECIMALS)]) - .with_inflation(10, 15, 40, 15, 5) - .build() - .execute_with(|| { - assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(3))); - let authors: Vec> = (1u64..100u64).map(|_| Some(1u64)).collect(); - assert_eq!(Balances::usable_balance(&1), Balance::zero()); - assert_eq!(Balances::usable_balance(&2), Balance::zero()); - assert_eq!(Balances::usable_balance(&3), Balance::zero()); - roll_to_claim_rewards(100, authors); - assert!(Balances::usable_balance(&1) > Balance::zero()); - assert!(Balances::usable_balance(&2) > Balance::zero()); - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(3), 3)); - assert_eq!(Balances::usable_balance(&3), 10_000_000 * DECIMALS); - }); -} -#[test] -fn coinbase_rewards_many_blocks_simple_check() { - let num_of_years: Perquintill = Perquintill::from_perthousand(2); - ExtBuilder::default() - .with_balances(vec![ - (1, 40_000_000 * DECIMALS), - (2, 40_000_000 * DECIMALS), - (3, 40_000_000 * DECIMALS), - (4, 20_000_000 * DECIMALS), - (5, 20_000_000 * DECIMALS), - ]) - .with_collators(vec![(1, 8_000_000 * DECIMALS), (2, 8_000_000 * DECIMALS)]) - .with_delegators(vec![ - (3, 1, 32_000_000 * DECIMALS), - (4, 1, 16_000_000 * DECIMALS), - (5, 2, 16_000_000 * DECIMALS), - ]) - .with_inflation(10, 15, 40, 15, 5) - .build() - .execute_with(|| { - let inflation = StakePallet::inflation_config(); - let total_issuance = ::Currency::total_issuance(); - assert_eq!(total_issuance, 160_000_000 * DECIMALS); - let end_block: BlockNumber = num_of_years * Test::BLOCKS_PER_YEAR as BlockNumber; - // set round robin authoring - let authors: Vec> = (0u64..=end_block).map(|i| Some(i % 2 + 1)).collect(); - roll_to_claim_rewards(end_block, authors); - - let rewards_1 = Balances::free_balance(&1).saturating_sub(40_000_000 * DECIMALS); - let rewards_2 = Balances::free_balance(&2).saturating_sub(40_000_000 * DECIMALS); - let rewards_3 = Balances::free_balance(&3).saturating_sub(40_000_000 * DECIMALS); - let rewards_4 = Balances::free_balance(&4).saturating_sub(20_000_000 * DECIMALS); - let rewards_5 = Balances::free_balance(&5).saturating_sub(20_000_000 * DECIMALS); - let expected_collator_rewards = - num_of_years * inflation.collator.reward_rate.annual * 16_000_000 * DECIMALS; - let expected_delegator_rewards = - num_of_years * inflation.delegator.reward_rate.annual * 64_000_000 * DECIMALS; - - // 1200000000000000000000 - // 2399074074058720000 - - // collator rewards should be about the same - assert!(almost_equal(rewards_1, rewards_2, Perbill::from_perthousand(1))); - assert!( - almost_equal( - rewards_1, - num_of_years * inflation.collator.reward_rate.annual * 8_000_000 * DECIMALS, - Perbill::from_perthousand(1) - ), - "left {:?}, right {:?}", - rewards_1, - inflation.collator.reward_rate.annual * 8_000_000 * DECIMALS, - ); - - // delegator rewards should be about the same - assert!( - almost_equal(rewards_3, rewards_4 + rewards_5, Perbill::from_perthousand(1)), - "left {:?}, right {:?}", - rewards_3, - rewards_4 + rewards_5 - ); - assert!(almost_equal( - rewards_3, - num_of_years * inflation.delegator.reward_rate.annual * 32_000_000 * DECIMALS, - Perbill::from_perthousand(1) - )); - - // check rewards in total - assert!( - almost_equal( - rewards_1 + rewards_2, - expected_collator_rewards, - Perbill::from_perthousand(1), - ), - "left {:?}, right {:?}", - rewards_1 + rewards_2, - expected_collator_rewards, - ); - assert!( - almost_equal( - rewards_3 + rewards_4 + rewards_5, - expected_delegator_rewards, - Perbill::from_perthousand(1), - ), - "left {:?}, right {:?}", - rewards_3 + rewards_4 + rewards_5, - expected_delegator_rewards, - ); - - // old issuance + rewards should equal new issuance - assert!( - almost_equal( - total_issuance + expected_collator_rewards + expected_delegator_rewards, - ::Currency::total_issuance(), - Perbill::from_perthousand(1), - ), - "left {:?}, right {:?}", - total_issuance + expected_collator_rewards + expected_delegator_rewards, - ::Currency::total_issuance(), - ); - }); -} - -// Could only occur if we increase MinDelegatorStakeOf::via runtime -// upgrade and don't migrate delegators which fall below minimum -#[test] -fn should_not_reward_delegators_below_min_stake() { - ExtBuilder::default() - .with_balances(vec![(1, 10 * DECIMALS), (2, 10 * DECIMALS), (3, 10 * DECIMALS), (4, 5)]) - .with_collators(vec![(1, 10 * DECIMALS), (2, 10 * DECIMALS)]) - .with_delegators(vec![(3, 2, 10 * DECIMALS)]) - .with_inflation(10, 15, 40, 15, 5) - .build() - .execute_with(|| { - // impossible but lets assume it happened - let mut state = StakePallet::candidate_pool(&1).expect("CollatorState cannot be missing"); - let delegator_stake_below_min = ::MinDelegatorStake::get() - 1; - state.stake += delegator_stake_below_min; - state.total += delegator_stake_below_min; - let impossible_bond = StakeOf:: { - owner: 4u64, - amount: delegator_stake_below_min, - }; - assert_eq!(state.delegators.try_insert(impossible_bond), Ok(true)); - >::insert(1u64, state); - - let authors: Vec> = vec![Some(1u64), Some(1u64), Some(1u64), Some(1u64)]; - assert_eq!(Balances::usable_balance(&1), Balance::zero()); - assert_eq!(Balances::usable_balance(&2), Balance::zero()); - assert_eq!(Balances::usable_balance(&3), Balance::zero()); - assert_eq!(Balances::usable_balance(&4), 5); - - // should only reward 1 - roll_to_claim_rewards(4, authors); - assert!(Balances::usable_balance(&1) > Balance::zero()); - assert_eq!(Balances::usable_balance(&4), 5); - assert_eq!(Balances::usable_balance(&2), Balance::zero()); - assert_eq!(Balances::usable_balance(&3), Balance::zero()); - }); -} - -#[test] -#[should_panic] -fn should_deny_low_delegator_stake() { - ExtBuilder::default() - .with_balances(vec![(1, 10 * DECIMALS), (2, 10 * DECIMALS), (3, 10 * DECIMALS), (4, 1)]) - .with_collators(vec![(1, 10 * DECIMALS), (2, 10 * DECIMALS)]) - .with_delegators(vec![(4, 2, 1)]) - .build() - .execute_with(|| {}); -} - -#[test] -#[should_panic] -fn should_deny_low_collator_stake() { - ExtBuilder::default() - .with_balances(vec![(1, 10 * DECIMALS), (2, 5)]) - .with_collators(vec![(1, 10 * DECIMALS), (2, 5)]) - .build() - .execute_with(|| {}); -} - -#[test] -#[should_panic] -fn should_deny_duplicate_collators() { - ExtBuilder::default() - .with_balances(vec![(1, 10 * DECIMALS)]) - .with_collators(vec![(1, 10 * DECIMALS), (1, 10 * DECIMALS)]) - .build() - .execute_with(|| {}); -} - -#[test] -fn reach_max_top_candidates() { - ExtBuilder::default() - .with_balances(vec![ - (1, 11), - (2, 20), - (3, 11), - (4, 11), - (5, 11), - (6, 11), - (7, 11), - (8, 11), - (9, 11), - (10, 11), - (11, 11), - (12, 12), - (13, 13), - ]) - .with_collators(vec![ - (1, 10), - (2, 20), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - (10, 10), - ]) - .build() - .execute_with(|| { - assert_eq!( - StakePallet::top_candidates().len().saturated_into::(), - ::MaxTopCandidates::get() - ); - // should not be possible to join candidate pool, even with more stake - assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(11), 11)); - assert_eq!( - StakePallet::top_candidates() - .into_iter() - .map(|s| s.owner) - .collect::>(), - vec![2, 11, 1, 3, 4, 5, 6, 7, 8, 9] - ); - // last come, last one in the list - assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(12), 11)); - assert_eq!( - StakePallet::top_candidates() - .into_iter() - .map(|s| s.owner) - .collect::>(), - vec![2, 11, 12, 1, 3, 4, 5, 6, 7, 8] - ); - assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 1)); - assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(3), 1)); - assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(4), 1)); - assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(5), 1)); - assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(6), 1)); - assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(7), 1)); - assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(8), 1)); - assert_eq!( - StakePallet::top_candidates() - .into_iter() - .map(|s| s.owner) - .collect::>(), - vec![2, 11, 12, 1, 3, 4, 5, 6, 7, 8] - ); - }); -} - -#[test] -fn should_estimate_current_session_progress() { - ExtBuilder::default() - .set_blocks_per_round(100) - .with_balances(vec![ - (1, 10), - (2, 20), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - (10, 10), - (11, 10), - ]) - .with_collators(vec![ - (1, 10), - (2, 20), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - (10, 10), - ]) - .build() - .execute_with(|| { - assert_eq!( - StakePallet::estimate_current_session_progress(10).0.unwrap(), - Permill::from_percent(10) - ); - assert_eq!( - StakePallet::estimate_current_session_progress(20).0.unwrap(), - Permill::from_percent(20) - ); - assert_eq!( - StakePallet::estimate_current_session_progress(30).0.unwrap(), - Permill::from_percent(30) - ); - assert_eq!( - StakePallet::estimate_current_session_progress(60).0.unwrap(), - Permill::from_percent(60) - ); - assert_eq!( - StakePallet::estimate_current_session_progress(100).0.unwrap(), - Permill::from_percent(100) - ); - }); -} - -#[test] -fn should_estimate_next_session_rotation() { - ExtBuilder::default() - .set_blocks_per_round(100) - .with_balances(vec![ - (1, 10), - (2, 20), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - (10, 10), - (11, 10), - ]) - .with_collators(vec![ - (1, 10), - (2, 20), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - (10, 10), - ]) - .build() - .execute_with(|| { - assert_eq!(StakePallet::estimate_next_session_rotation(10).0.unwrap(), 100); - assert_eq!(StakePallet::estimate_next_session_rotation(20).0.unwrap(), 100); - assert_eq!(StakePallet::estimate_next_session_rotation(30).0.unwrap(), 100); - assert_eq!(StakePallet::estimate_next_session_rotation(60).0.unwrap(), 100); - assert_eq!(StakePallet::estimate_next_session_rotation(100).0.unwrap(), 100); - }); -} - -#[test] -fn should_end_session_when_appropriate() { - ExtBuilder::default() - .set_blocks_per_round(100) - .with_balances(vec![ - (1, 10), - (2, 20), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - (10, 10), - (11, 10), - ]) - .with_collators(vec![ - (1, 10), - (2, 20), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - (10, 10), - ]) - .build() - .execute_with(|| { - assert!(!StakePallet::should_end_session(10)); - assert!(!StakePallet::should_end_session(20)); - assert!(!StakePallet::should_end_session(30)); - assert!(!StakePallet::should_end_session(60)); - assert!(StakePallet::should_end_session(100)); - }); -} - -#[test] -fn set_max_selected_candidates_safe_guards() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_collators(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_noop!( - StakePallet::set_max_selected_candidates( - RuntimeOrigin::root(), - ::MinCollators::get() - 1 - ), - Error::::CannotSetBelowMin - ); - assert_noop!( - StakePallet::set_max_selected_candidates( - RuntimeOrigin::root(), - ::MaxTopCandidates::get() + 1 - ), - Error::::CannotSetAboveMax - ); - assert_ok!(StakePallet::set_max_selected_candidates( - RuntimeOrigin::root(), - ::MinCollators::get() + 1 - )); - }); -} - -#[test] -fn set_max_selected_candidates_total_stake() { - let balances: Vec<(AccountId, Balance)> = (1..19).map(|x| (x, 100)).collect(); - ExtBuilder::default() - .with_balances(balances) - .with_collators(vec![ - (1, 11), - (2, 12), - (3, 13), - (4, 14), - (5, 15), - (6, 16), - (7, 17), - (8, 18), - ]) - .with_delegators(vec![ - (11, 1, 21), - (12, 2, 22), - (13, 3, 23), - (14, 4, 24), - (15, 5, 25), - (16, 6, 26), - (17, 7, 27), - (18, 8, 28), - ]) - .build() - .execute_with(|| { - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 35, - delegators: 55 - } - ); - - assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 3)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 51, - delegators: 81 - } - ); - - assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 5)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 80, - delegators: 130 - } - ); - - assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 10)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 116, - delegators: 196 - } - ); - - assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 2)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 35, - delegators: 55 - } - ); - }); -} - -#[test] -fn update_inflation() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_collators(vec![(1, 10)]) - .build() - .execute_with(|| { - let mut invalid_inflation = InflationInfo { - collator: StakingInfo { - max_rate: Perquintill::one(), - reward_rate: RewardRate { - annual: Perquintill::from_percent(99), - per_block: Perquintill::from_percent(1), - }, - }, - delegator: StakingInfo { - max_rate: Perquintill::one(), - reward_rate: RewardRate { - annual: Perquintill::from_percent(99), - per_block: Perquintill::from_percent(1), - }, - }, - }; - assert!(!invalid_inflation.is_valid(::BLOCKS_PER_YEAR)); - invalid_inflation.collator.reward_rate.per_block = Perquintill::zero(); - assert!(!invalid_inflation.is_valid(::BLOCKS_PER_YEAR)); - - assert_ok!(StakePallet::set_inflation( - RuntimeOrigin::root(), - Perquintill::from_percent(0), - Perquintill::from_percent(100), - Perquintill::from_percent(100), - Perquintill::from_percent(100), - )); - assert_ok!(StakePallet::set_inflation( - RuntimeOrigin::root(), - Perquintill::from_percent(100), - Perquintill::from_percent(0), - Perquintill::from_percent(100), - Perquintill::from_percent(100), - )); - assert_ok!(StakePallet::set_inflation( - RuntimeOrigin::root(), - Perquintill::from_percent(100), - Perquintill::from_percent(100), - Perquintill::from_percent(0), - Perquintill::from_percent(100), - )); - assert_ok!(StakePallet::set_inflation( - RuntimeOrigin::root(), - Perquintill::from_percent(100), - Perquintill::from_percent(100), - Perquintill::from_percent(100), - Perquintill::from_percent(0), - )); - }); -} - -#[test] -fn unlock_unstaked() { - // same_unstaked_as_restaked - // block 1: stake & unstake for 100 - // block 2: stake & unstake for 100 - // should remove first entry in unstaking BoundedBTreeMap when staking in block - // 2 should still have 100 locked until unlocking - ExtBuilder::default() - .with_balances(vec![(1, 10), (2, 100)]) - .with_collators(vec![(1, 10)]) - .with_delegators(vec![(2, 1, 100)]) - .build() - .execute_with(|| { - assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); - let mut unstaking: BoundedBTreeMap, ::MaxUnstakeRequests> = - BoundedBTreeMap::new(); - assert_ok!(unstaking.try_insert(3, 100)); - let lock = BalanceLock { - id: STAKING_ID, - amount: 100, - reasons: Reasons::All, - }; - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - // shouldn't be able to unlock anything - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - - // join delegators and revoke again --> consume unstaking at block 3 - roll_to(2, vec![]); - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 100)); - assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); - unstaking.remove(&3); - assert_ok!(unstaking.try_insert(4, 100)); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - // shouldn't be able to unlock anything - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - - // should reduce unlocking but not unlock anything - roll_to(3, vec![]); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - // shouldn't be able to unlock anything - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - - roll_to(4, vec![]); - unstaking.remove(&4); - assert_eq!(Balances::locks(2), vec![lock]); - // shouldn't be able to unlock anything - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![]); - }); - - // less_unstaked_than_restaked - // block 1: stake & unstake for 10 - // block 2: stake & unstake for 100 - // should remove first entry in unstaking BoundedBTreeMap when staking in block - // 2 should still have 90 locked until unlocking in block 4 - ExtBuilder::default() - .with_balances(vec![(1, 10), (2, 100)]) - .with_collators(vec![(1, 10)]) - .with_delegators(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); - let mut unstaking: BoundedBTreeMap, ::MaxUnstakeRequests> = - BoundedBTreeMap::new(); - assert_ok!(unstaking.try_insert(3, 10)); - let mut lock = BalanceLock { - id: STAKING_ID, - amount: 10, - reasons: Reasons::All, - }; - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - // shouldn't be able to unlock anything - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - - // join delegators and revoke again - roll_to(2, vec![]); - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 100)); - assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); - unstaking.remove(&3); - assert_ok!(unstaking.try_insert(4, 100)); - lock.amount = 100; - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - // shouldn't be able to unlock anything - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - - roll_to(3, vec![]); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - // shouldn't be able to unlock anything - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - - // unlock unstaked, remove lock, empty unlocking - roll_to(4, vec![]); - unstaking.remove(&4); - assert_eq!(Balances::locks(2), vec![lock]); - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![]); - }); - - // more_unstaked_than_restaked - // block 1: stake & unstake for 100 - // block 2: stake & unstake for 10 - // should reduce first entry from amount 100 to 90 in unstaking BoundedBTreeMap - // when staking in block 2 - // should have 100 locked until unlocking in block 3, then 10 - // should have 10 locked until further unlocking in block 4 - ExtBuilder::default() - .with_balances(vec![(1, 10), (2, 100)]) - .with_collators(vec![(1, 10)]) - .with_delegators(vec![(2, 1, 100)]) - .build() - .execute_with(|| { - assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); - let mut unstaking: BoundedBTreeMap, ::MaxUnstakeRequests> = - BoundedBTreeMap::new(); - assert_ok!(unstaking.try_insert(3, 100)); - let mut lock = BalanceLock { - id: STAKING_ID, - amount: 100, - reasons: Reasons::All, - }; - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - // shouldn't be able to unlock anything - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - - // join delegators and revoke again - roll_to(2, vec![]); - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 10)); - assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); - assert_ok!(unstaking.try_insert(3, 90)); - assert_ok!(unstaking.try_insert(4, 10)); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - // shouldn't be able to unlock anything - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - - // should reduce unlocking but not unlock anything - roll_to(3, vec![]); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - // should be able to unlock 90 of 100 from unstaking - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); - unstaking.remove(&3); - lock.amount = 10; - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - - roll_to(4, vec![]); - assert_eq!(Balances::locks(2), vec![lock]); - // should be able to unlock 10 of remaining 10 - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); - unstaking.remove(&4); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(2), vec![]); - }); - - // test_stake_less - // block 1: stake & unstake for 100 - // block 2: stake & unstake for 10 - // should reduce first entry from amount 100 to 90 in unstaking BoundedBTreeMap - // when staking in block 2 - // should have 100 locked until unlocking in block 3, then 10 - // should have 10 locked until further unlocking in block 4 - ExtBuilder::default() - .with_balances(vec![(1, 200), (2, 200)]) - .with_collators(vec![(1, 200)]) - .with_delegators(vec![(2, 1, 200)]) - .build() - .execute_with(|| { - // should be able to decrease more often than MaxUnstakeRequests because it's - // the same block and thus unstaking is increased at block 3 instead of having - // multiple entries for the same block - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10)); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10)); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10)); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10)); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10)); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10),); - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10)); - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10)); - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10)); - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10)); - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10)); - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10),); - let mut unstaking: BoundedBTreeMap, ::MaxUnstakeRequests> = - BoundedBTreeMap::new(); - assert_ok!(unstaking.try_insert(3, 60)); - let mut lock = BalanceLock { - id: STAKING_ID, - amount: 200, - reasons: Reasons::All, - }; - assert_eq!(Balances::locks(1), vec![lock.clone()]); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - assert_eq!(StakePallet::unstaking(1), unstaking); - assert_eq!(StakePallet::unstaking(2), unstaking); - // shouldn't be able to unlock anything - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(1), 1)); - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); - assert_eq!(StakePallet::unstaking(1), unstaking); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(1), vec![lock.clone()]); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - - roll_to(2, vec![]); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10),); - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10),); - assert_ok!(unstaking.try_insert(4, 10)); - assert_eq!(Balances::locks(1), vec![lock.clone()]); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - assert_eq!(StakePallet::unstaking(1), unstaking); - assert_eq!(StakePallet::unstaking(2), unstaking); - // shouldn't be able to unlock anything - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(1), 1)); - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); - assert_eq!(StakePallet::unstaking(1), unstaking); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(1), vec![lock.clone()]); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - - roll_to(3, vec![]); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10),); - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10),); - assert_ok!(unstaking.try_insert(5, 10)); - assert_ok!(unstaking.try_insert(5, 10)); - assert_eq!(Balances::locks(1), vec![lock.clone()]); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - assert_eq!(StakePallet::unstaking(1), unstaking); - assert_eq!(StakePallet::unstaking(2), unstaking); - // should unlock 60 - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(1), 1)); - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); - lock.amount = 140; - unstaking.remove(&3); - assert_eq!(StakePallet::unstaking(1), unstaking); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(1), vec![lock.clone()]); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - - // reach MaxUnstakeRequests - roll_to(4, vec![]); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10)); - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10)); - roll_to(5, vec![]); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10)); - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10)); - roll_to(6, vec![]); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10)); - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10)); - assert_ok!(unstaking.try_insert(6, 10)); - assert_ok!(unstaking.try_insert(7, 10)); - assert_ok!(unstaking.try_insert(8, 10)); - assert_eq!(StakePallet::unstaking(1), unstaking); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(1), vec![lock.clone()]); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - - roll_to(7, vec![]); - assert_noop!( - StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10), - Error::::NoMoreUnstaking - ); - assert_noop!( - StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10), - Error::::NoMoreUnstaking - ); - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(1), 1)); - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); - unstaking.remove(&4); - unstaking.remove(&5); - unstaking.remove(&6); - unstaking.remove(&7); - lock.amount = 100; - assert_eq!(StakePallet::unstaking(1), unstaking); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(1), vec![lock.clone()]); - assert_eq!(Balances::locks(2), vec![lock.clone()]); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 40)); - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 40)); - assert_ok!(unstaking.try_insert(9, 40)); - assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 30)); - assert_ok!(StakePallet::delegator_stake_more(RuntimeOrigin::signed(2), 30)); - unstaking.remove(&8); - assert_ok!(unstaking.try_insert(9, 20)); - assert_eq!(StakePallet::unstaking(1), unstaking); - assert_eq!(StakePallet::unstaking(2), unstaking); - assert_eq!(Balances::locks(1), vec![lock.clone()]); - assert_eq!(Balances::locks(2), vec![lock]); - }); -} - -#[test] -fn kick_candidate_with_full_unstaking() { - ExtBuilder::default() - .with_balances(vec![(1, 200), (2, 200), (3, 300)]) - .with_collators(vec![(1, 200), (2, 200), (3, 200)]) - .build() - .execute_with(|| { - let max_unstake_reqs: usize = ::MaxUnstakeRequests::get() - .saturating_sub(1) - .saturated_into(); - // Fill unstake requests - for block in 1u64..1u64.saturating_add(max_unstake_reqs as u64) { - System::set_block_number(block); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(3), 1)); - } - assert_eq!(StakePallet::unstaking(3).into_inner().len(), max_unstake_reqs); - - // Additional unstake should fail - System::set_block_number(100); - assert_noop!( - StakePallet::candidate_stake_less(RuntimeOrigin::signed(3), 1), - Error::::NoMoreUnstaking - ); - - // Fill last unstake request by removing candidate and unstaking all stake - assert_ok!(StakePallet::force_remove_candidate(RuntimeOrigin::root(), 3)); - - // Cannot join with full unstaking - assert_eq!(StakePallet::unstaking(3).into_inner().len(), max_unstake_reqs + 1); - assert_noop!( - StakePallet::join_candidates(RuntimeOrigin::signed(3), 100), - Error::::CannotJoinBeforeUnlocking - ); - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(3), 3)); - assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(3), 100)); - }); -} -#[test] -fn kick_delegator_with_full_unstaking() { - ExtBuilder::default() - .with_balances(vec![(1, 200), (2, 200), (3, 200), (4, 200), (5, 420), (6, 200)]) - .with_collators(vec![(1, 200)]) - .with_delegators(vec![(2, 1, 200), (3, 1, 200), (4, 1, 200), (5, 1, 200)]) - .build() - .execute_with(|| { - let max_unstake_reqs: usize = ::MaxUnstakeRequests::get() - .saturating_sub(1) - .saturated_into(); - // Fill unstake requests - for block in 1u64..1u64.saturating_add(max_unstake_reqs as u64) { - System::set_block_number(block); - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(5), 1)); - } - assert_eq!(StakePallet::unstaking(5).into_inner().len(), max_unstake_reqs); - - // Additional unstake should fail - System::set_block_number(100); - assert_noop!( - StakePallet::delegator_stake_less(RuntimeOrigin::signed(5), 1), - Error::::NoMoreUnstaking - ); - - // Fill last unstake request by replacing delegator - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(6), 1, 200)); - assert_eq!(StakePallet::unstaking(5).into_inner().len(), max_unstake_reqs + 1); - assert!(!StakePallet::is_delegator(&5)); - - // Cannot join with full unstaking - assert_noop!( - StakePallet::join_delegators(RuntimeOrigin::signed(5), 1, 100), - Error::::CannotJoinBeforeUnlocking - ); - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(5), 5)); - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(5), 1, 220)); - }); -} - -#[test] -fn candidate_leaves() { - let balances: Vec<(AccountId, Balance)> = (1u64..=15u64).map(|id| (id, 100)).collect(); - ExtBuilder::default() - .with_balances(balances) - .with_collators(vec![(1, 100), (2, 100)]) - .with_delegators(vec![(12, 1, 100), (13, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!( - StakePallet::top_candidates() - .into_iter() - .map(|s| s.owner) - .collect::>(), - vec![1, 2] - ); - assert_noop!( - StakePallet::init_leave_candidates(RuntimeOrigin::signed(11)), - Error::::CandidateNotFound - ); - assert_noop!( - StakePallet::init_leave_candidates(RuntimeOrigin::signed(1)), - Error::::TooFewCollatorCandidates - ); - // add five more collator to max fill TopCandidates - for candidate in 3u64..11u64 { - assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(candidate), 100)); - } - assert_eq!( - StakePallet::top_candidates() - .into_iter() - .map(|s| s.owner) - .collect::>(), - (1u64..11u64).collect::>() - ); - assert_eq!(CandidatePool::::count(), 10); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(1))); - assert_eq!( - StakePallet::top_candidates() - .into_iter() - .map(|s| s.owner) - .collect::>(), - (2u64..11u64).collect::>() - ); - assert_noop!( - StakePallet::join_delegators(RuntimeOrigin::signed(15), 1, 10), - Error::::CannotDelegateIfLeaving - ); - assert_noop!( - StakePallet::delegator_stake_more(RuntimeOrigin::signed(12), 1), - Error::::CannotDelegateIfLeaving - ); - assert_noop!( - StakePallet::delegator_stake_less(RuntimeOrigin::signed(12), 1), - Error::::CannotDelegateIfLeaving - ); - assert_noop!( - StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 1), - Error::::CannotStakeIfLeaving - ); - assert_noop!( - StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 1), - Error::::CannotStakeIfLeaving - ); - assert_noop!( - StakePallet::init_leave_candidates(RuntimeOrigin::signed(1)), - Error::::AlreadyLeaving - ); - assert_eq!( - StakePallet::candidate_pool(1).unwrap().status, - CandidateStatus::Leaving(2) - ); - assert!(StakePallet::candidate_pool(1).unwrap().can_exit(2)); - assert!(!StakePallet::candidate_pool(1).unwrap().can_exit(1)); - assert!(StakePallet::candidate_pool(1).unwrap().can_exit(3)); - - // next rounds starts, cannot leave yet - roll_to(5, vec![]); - assert_noop!( - StakePallet::execute_leave_candidates(RuntimeOrigin::signed(2), 2), - Error::::NotLeaving - ); - assert_noop!( - StakePallet::execute_leave_candidates(RuntimeOrigin::signed(2), 1), - Error::::CannotLeaveYet - ); - // add 11 as candidate to reach max size for TopCandidates and then try leave - // again as 1 which should not be possible - assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(11), 100)); - assert_eq!( - StakePallet::top_candidates() - .into_iter() - .map(|s| s.owner) - .collect::>(), - (2u64..12u64).collect::>() - ); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(11))); - // join back - assert_ok!(StakePallet::cancel_leave_candidates(RuntimeOrigin::signed(1))); - assert_eq!( - StakePallet::top_candidates() - .into_iter() - .map(|s| s.owner) - .collect::>(), - (1u64..11u64).collect::>() - ); - - let stake: Vec> = (1u64..11u64) - .zip(iter::once(210).chain(iter::repeat(100))) - .map(|(id, amount)| StakeOf:: { owner: id, amount }) - .collect(); - assert_eq!( - StakePallet::top_candidates(), - OrderedSet::from(stake.try_into().unwrap()) - ); - let state = StakePallet::candidate_pool(1).unwrap(); - assert_eq!(state.status, CandidateStatus::Active); - assert_eq!(state.delegators.len(), 2); - assert_eq!(state.total, 210); - assert_eq!( - state.total, - StakePallet::top_candidates() - .into_bounded_vec() - .iter() - .find(|other| other.owner == 1) - .unwrap() - .amount - ); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2]); - - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(1))); - - roll_to(15, vec![]); - assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(13), 1)); - let mut unstaking: BoundedBTreeMap, ::MaxUnstakeRequests> = - BoundedBTreeMap::new(); - assert_ok!(unstaking.try_insert(17, 100)); - assert_eq!(StakePallet::unstaking(1), unstaking); - assert_eq!(StakePallet::unstaking(12), unstaking); - - // cannot unlock yet - roll_to(16, vec![]); - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(4), 1)); - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(4), 12)); - assert_eq!(StakePallet::unstaking(1), unstaking); - assert_eq!(StakePallet::unstaking(12), unstaking); - - // can unlock now - roll_to(17, vec![]); - unstaking.remove(&17); - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(4), 1)); - assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(4), 12)); - assert_eq!(StakePallet::unstaking(1), unstaking); - assert_eq!(StakePallet::unstaking(12), unstaking); - }); -} - -#[test] -fn adjust_reward_rates() { - ExtBuilder::default() - .with_balances(vec![(1, 10_000_000 * DECIMALS), (2, 90_000_000 * DECIMALS)]) - .with_collators(vec![(1, 10_000_000 * DECIMALS)]) - .with_delegators(vec![(2, 1, 40_000_000 * DECIMALS)]) - .with_inflation(10, 10, 40, 8, 5) - .build() - .execute_with(|| { - let inflation_0 = StakePallet::inflation_config(); - let num_of_years = 3 * ::BLOCKS_PER_YEAR; - // 1 authors every block - let authors: Vec> = (0u64..=num_of_years).map(|_| Some(1u64)).collect(); - - // reward once in first year - roll_to_claim_rewards(2, authors.clone()); - let c_rewards_0 = Balances::free_balance(&1).saturating_sub(10_000_000 * DECIMALS); - let d_rewards_0 = Balances::free_balance(&2).saturating_sub(90_000_000 * DECIMALS); - assert!(!c_rewards_0.is_zero()); - assert!(!d_rewards_0.is_zero()); - - // finish first year - System::set_block_number(::BLOCKS_PER_YEAR); - roll_to_claim_rewards(::BLOCKS_PER_YEAR + 1, vec![]); - // reward reduction should not happen automatically anymore - assert_eq!(StakePallet::last_reward_reduction(), 0u64); - assert_ok!(StakePallet::execute_scheduled_reward_change(RuntimeOrigin::signed(1))); - assert_eq!(StakePallet::last_reward_reduction(), 1u64); - let inflation_1 = InflationInfo::new( - ::BLOCKS_PER_YEAR, - inflation_0.collator.max_rate, - Perquintill::from_parts(98000000000000000), - inflation_0.delegator.max_rate, - Perquintill::from_percent(6), - ); - assert_eq!(StakePallet::inflation_config(), inflation_1); - // reward once in 2nd year - roll_to_claim_rewards(::BLOCKS_PER_YEAR + 2, authors.clone()); - let c_rewards_1 = Balances::free_balance(&1) - .saturating_sub(10_000_000 * DECIMALS) - .saturating_sub(c_rewards_0); - let d_rewards_1 = Balances::free_balance(&2) - .saturating_sub(90_000_000 * DECIMALS) - .saturating_sub(d_rewards_0); - assert!( - c_rewards_0 > c_rewards_1, - "left {:?}, right {:?}", - c_rewards_0, - c_rewards_1 - ); - assert!(d_rewards_0 > d_rewards_1); - - // finish 2nd year - System::set_block_number(2 * ::BLOCKS_PER_YEAR); - roll_to_claim_rewards(2 * ::BLOCKS_PER_YEAR + 1, vec![]); - // reward reduction should not happen automatically anymore - assert_eq!(StakePallet::last_reward_reduction(), 1u64); - assert_ok!(StakePallet::execute_scheduled_reward_change(RuntimeOrigin::signed(1))); - assert_eq!(StakePallet::last_reward_reduction(), 2u64); - let inflation_2 = InflationInfo::new( - ::BLOCKS_PER_YEAR, - inflation_0.collator.max_rate, - Perquintill::from_parts(96040000000000000), - inflation_0.delegator.max_rate, - Perquintill::zero(), - ); - assert_eq!(StakePallet::inflation_config(), inflation_2); - // reward once in 3rd year - roll_to_claim_rewards(2 * ::BLOCKS_PER_YEAR + 2, authors); - let c_rewards_2 = Balances::free_balance(&1) - .saturating_sub(10_000_000 * DECIMALS) - .saturating_sub(c_rewards_0) - .saturating_sub(c_rewards_1); - assert!(c_rewards_1 > c_rewards_2); - // should be zero because we set reward rate to zero - let d_rewards_2 = Balances::free_balance(&2) - .saturating_sub(90_000_000 * DECIMALS) - .saturating_sub(d_rewards_0) - .saturating_sub(d_rewards_1); - assert!(d_rewards_2.is_zero()); - }); -} - -#[test] -fn increase_max_candidate_stake() { - let max_stake = 160_000_000 * DECIMALS; - ExtBuilder::default() - .with_balances(vec![(1, 200_000_000 * DECIMALS)]) - .with_collators(vec![(1, max_stake)]) - .build() - .execute_with(|| { - assert_eq!(StakePallet::max_candidate_stake(), max_stake); - assert_noop!( - StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 1), - Error::::ValStakeAboveMax - ); - - assert_ok!(StakePallet::set_max_candidate_stake( - RuntimeOrigin::root(), - max_stake + 1 - )); - assert_eq!(last_event(), StakeEvent::MaxCandidateStakeChanged(max_stake + 1)); - assert_eq!(StakePallet::max_candidate_stake(), max_stake + 1); - assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 1)); - assert_noop!( - StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 1), - Error::::ValStakeAboveMax - ); - }); -} - -#[test] -fn decrease_max_candidate_stake() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100)]) - .with_collators(vec![(1, 100), (2, 90), (3, 40)]) - .with_delegators(vec![(4, 2, 10), (5, 3, 20)]) - .build() - .execute_with(|| { - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2]); - assert_eq!( - StakePallet::top_candidates(), - OrderedSet::from_sorted_set( - vec![ - StakeOf:: { owner: 1, amount: 100 }, - StakeOf:: { owner: 2, amount: 100 }, - StakeOf:: { owner: 3, amount: 60 } - ] - .try_into() - .unwrap() - ) - ); - - assert_ok!(StakePallet::set_max_candidate_stake(RuntimeOrigin::root(), 50)); - assert_eq!(StakePallet::max_candidate_stake(), 50); - assert_eq!(last_event(), StakeEvent::MaxCandidateStakeChanged(50)); - - // check collator states, nothing changed - assert_eq!( - StakePallet::top_candidates(), - OrderedSet::from_sorted_set( - vec![ - StakeOf:: { owner: 1, amount: 100 }, - StakeOf:: { owner: 2, amount: 100 }, - StakeOf:: { owner: 3, amount: 60 } - ] - .try_into() - .unwrap() - ) - ); - - assert_noop!( - StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 0), - Error::::ValStakeZero - ); - assert_noop!( - StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 0), - Error::::ValStakeZero - ); - assert_noop!( - StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 1), - Error::::ValStakeAboveMax - ); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 50)); - assert_noop!( - StakePallet::set_max_candidate_stake(RuntimeOrigin::root(), 9), - Error::::CannotSetBelowMin - ); - }); -} - -#[test] -fn exceed_delegations_per_round() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100)]) - .with_collators(vec![(1, 100)]) - .with_delegators(vec![(2, 1, 100)]) - .build() - .execute_with(|| { - // leave and re-join to set counter to 2 (= MaxDelegationsPerRound) - assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 100)); - assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); - // reached max delegations in this round - assert_noop!( - StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 100), - Error::::DelegationsPerRoundExceeded - ); - - // roll to next round to clear DelegationCounter - roll_to(5, vec![]); - assert_eq!( - StakePallet::last_delegation(2), - DelegationCounter { round: 0, counter: 2 } - ); - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 100)); - // counter should be reset because the round changed - assert_eq!( - StakePallet::last_delegation(2), - DelegationCounter { round: 1, counter: 1 } - ); - // leave and re-join to set counter to 2 (= MaxDelegationsPerRound)) - assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 100)); - assert_noop!( - StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 100), - Error::::AlreadyDelegating - ); - assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); - assert_noop!( - StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 100), - Error::::DelegationsPerRoundExceeded - ); - assert_eq!( - StakePallet::last_delegation(2), - DelegationCounter { round: 1, counter: 2 } - ); - }); -} - -#[test] -fn force_remove_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (6, 100)]) - .with_collators(vec![(1, 100), (2, 100), (3, 100)]) - .with_delegators(vec![(4, 1, 50), (5, 1, 50)]) - .build() - .execute_with(|| { - assert_eq!(CandidatePool::::count(), 3); - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(6), 2, 50)); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2]); - assert!(StakePallet::unstaking(1).get(&3).is_none()); - assert!(StakePallet::unstaking(2).get(&3).is_none()); - assert!(StakePallet::unstaking(3).get(&3).is_none()); - - // force remove 1 - assert!(Session::disabled_validators().is_empty()); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 200, - delegators: 150 - } - ); - assert_ok!(StakePallet::force_remove_candidate(RuntimeOrigin::root(), 1)); - // collator stake does not change since 3, who took 1's place, has staked the - // same amount - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 200, - delegators: 50 - } - ); - assert_eq!(Session::disabled_validators(), vec![0]); - assert_eq!(last_event(), StakeEvent::CollatorRemoved(1, 200)); - assert!(!StakePallet::top_candidates().contains(&StakeOf:: { owner: 1, amount: 100 })); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 3]); - assert_eq!(CandidatePool::::count(), 2); - assert!(StakePallet::candidate_pool(1).is_none()); - assert!(StakePallet::delegator_state(4).is_none()); - assert!(StakePallet::delegator_state(5).is_none()); - assert_eq!(StakePallet::unstaking(1).get(&3), Some(&100)); - assert_eq!(StakePallet::unstaking(4).get(&3), Some(&50)); - assert_eq!(StakePallet::unstaking(5).get(&3), Some(&50)); - - assert_noop!( - StakePallet::force_remove_candidate(RuntimeOrigin::root(), 2), - Error::::TooFewCollatorCandidates - ); - assert_noop!( - StakePallet::force_remove_candidate(RuntimeOrigin::root(), 4), - Error::::CandidateNotFound - ); - - // session 1: expect 1 to still be in validator set but as disabled - roll_to(5, vec![]); - assert_eq!(Session::current_index(), 1); - assert_eq!(Session::validators(), vec![1, 2]); - assert_eq!(Session::disabled_validators(), vec![0]); - - // session 2: expect validator set to have changed - roll_to(10, vec![]); - assert_eq!(Session::validators(), vec![2, 3]); - assert!(Session::disabled_validators().is_empty()); - }); -} - -#[test] -fn prioritize_collators() { - ExtBuilder::default() - .with_balances(vec![ - (1, 200), - (2, 200), - (3, 200), - (4, 200), - (5, 200), - (6, 200), - (7, 200), - ]) - .with_collators(vec![(2, 100), (3, 100)]) - .build() - .execute_with(|| { - assert_eq!( - StakePallet::top_candidates(), - OrderedSet::from_sorted_set( - vec![2, 3] - .into_iter() - .map(|id| StakeOf:: { owner: id, amount: 100 }) - .collect::>>() - .try_into() - .unwrap() - ) - ); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 3]); - assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(1), 100)); - assert_eq!( - StakePallet::top_candidates(), - OrderedSet::from_sorted_set( - vec![2, 3, 1] - .into_iter() - .map(|id| StakeOf:: { owner: id, amount: 100 }) - .collect::>>() - .try_into() - .unwrap() - ) - ); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 3]); - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(2))); - assert_eq!(StakePallet::top_candidates().len(), 2); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![3, 1]); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(3), 10)); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 3]); - - // add 6 - assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(6), 100)); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 6]); - assert_eq!( - StakePallet::top_candidates(), - OrderedSet::from_sorted_set( - vec![1, 6] - .into_iter() - .map(|id| StakeOf:: { owner: id, amount: 100 }) - .chain(vec![StakeOf:: { owner: 3, amount: 90 }]) - .collect::>>() - .try_into() - .unwrap() - ) - ); - - // add 4 - assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(4), 100)); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 6]); - assert_eq!( - StakePallet::top_candidates(), - OrderedSet::from_sorted_set( - vec![1, 6, 4] - .into_iter() - .map(|id| StakeOf:: { owner: id, amount: 100 }) - .chain(vec![StakeOf:: { owner: 3, amount: 90 }]) - .collect::>>() - .try_into() - .unwrap() - ) - ); - - // add 5 - assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(5), 100)); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 6]); - assert_eq!( - StakePallet::top_candidates(), - OrderedSet::from_sorted_set( - vec![1, 6, 4, 5] - .into_iter() - .map(|id| StakeOf:: { owner: id, amount: 100 }) - .chain(vec![StakeOf:: { owner: 3, amount: 90 }]) - .collect::>>() - .try_into() - .unwrap() - ) - ); - - // 3 stake_more - assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(3), 20)); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![3, 1]); - assert_eq!( - StakePallet::top_candidates(), - OrderedSet::from_sorted_set( - vec![ - StakeOf:: { owner: 3, amount: 110 }, - StakeOf:: { owner: 1, amount: 100 }, - StakeOf:: { owner: 6, amount: 100 }, - StakeOf:: { owner: 4, amount: 100 }, - StakeOf:: { owner: 5, amount: 100 }, - ] - .try_into() - .unwrap() - ) - ); - - // 1 stake_less - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 1)); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![3, 6]); - assert_eq!( - StakePallet::top_candidates(), - OrderedSet::from_sorted_set( - vec![ - StakeOf:: { owner: 3, amount: 110 }, - StakeOf:: { owner: 6, amount: 100 }, - StakeOf:: { owner: 4, amount: 100 }, - StakeOf:: { owner: 5, amount: 100 }, - StakeOf:: { owner: 1, amount: 99 }, - ] - .try_into() - .unwrap() - ) - ); - - // 7 delegates to 4 - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(7), 5, 20)); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![5, 3]); - assert_eq!( - StakePallet::top_candidates(), - OrderedSet::from_sorted_set( - vec![ - StakeOf:: { owner: 5, amount: 120 }, - StakeOf:: { owner: 3, amount: 110 }, - StakeOf:: { owner: 6, amount: 100 }, - StakeOf:: { owner: 4, amount: 100 }, - StakeOf:: { owner: 1, amount: 99 }, - ] - .try_into() - .unwrap() - ) - ); - - // 7 decreases delegation - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(7), 10)); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![5, 3]); - assert_eq!( - StakePallet::top_candidates(), - OrderedSet::from_sorted_set( - vec![ - StakeOf:: { owner: 5, amount: 110 }, - StakeOf:: { owner: 3, amount: 110 }, - StakeOf:: { owner: 6, amount: 100 }, - StakeOf:: { owner: 4, amount: 100 }, - StakeOf:: { owner: 1, amount: 99 }, - ] - .try_into() - .unwrap() - ) - ); - assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(7))); - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![3, 5]); - assert_eq!( - StakePallet::top_candidates(), - OrderedSet::from_sorted_set( - vec![ - StakeOf:: { owner: 3, amount: 110 }, - StakeOf:: { owner: 5, amount: 100 }, - StakeOf:: { owner: 6, amount: 100 }, - StakeOf:: { owner: 4, amount: 100 }, - StakeOf:: { owner: 1, amount: 99 }, - ] - .try_into() - .unwrap() - ) - ); - }); -} - -#[test] -fn prioritize_delegators() { - ExtBuilder::default() - .with_balances(vec![ - (1, 1000), - (2, 1000), - (3, 1000), - (4, 1000), - (5, 1000), - (6, 1000), - (7, 1000), - (8, 1000), - (9, 1000), - ]) - .with_collators(vec![(1, 100), (2, 100), (3, 100)]) - .with_delegators(vec![(4, 2, 100), (7, 2, 100), (6, 2, 100)]) - .build() - .execute_with(|| { - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 1]); - assert_eq!( - StakePallet::candidate_pool(2).unwrap().delegators, - OrderedSet::from_sorted_set( - vec![ - StakeOf:: { owner: 4, amount: 100 }, - StakeOf:: { owner: 7, amount: 100 }, - StakeOf:: { owner: 6, amount: 100 }, - ] - .try_into() - .unwrap() - ) - ); - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(5), 2, 110)); - assert_eq!( - StakePallet::candidate_pool(2).unwrap().delegators, - OrderedSet::from_sorted_set( - vec![ - StakeOf:: { owner: 5, amount: 110 }, - StakeOf:: { owner: 4, amount: 100 }, - StakeOf:: { owner: 7, amount: 100 }, - StakeOf:: { owner: 6, amount: 100 }, - ] - .try_into() - .unwrap() - ) - ); - - // delegate_less - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(5), 10)); - assert_eq!( - StakePallet::candidate_pool(2).unwrap().delegators, - OrderedSet::from_sorted_set( - vec![ - StakeOf:: { owner: 5, amount: 100 }, - StakeOf:: { owner: 4, amount: 100 }, - StakeOf:: { owner: 7, amount: 100 }, - StakeOf:: { owner: 6, amount: 100 }, - ] - .try_into() - .unwrap() - ) - ); - - // delegate_more - assert_ok!(StakePallet::delegator_stake_more(RuntimeOrigin::signed(6), 10)); - assert_eq!( - StakePallet::candidate_pool(2).unwrap().delegators, - OrderedSet::from_sorted_set( - vec![ - StakeOf:: { owner: 6, amount: 110 }, - StakeOf:: { owner: 5, amount: 100 }, - StakeOf:: { owner: 4, amount: 100 }, - StakeOf:: { owner: 7, amount: 100 }, - ] - .try_into() - .unwrap() - ) - ); - assert_ok!(StakePallet::delegator_stake_more(RuntimeOrigin::signed(7), 10)); - assert_eq!( - StakePallet::candidate_pool(2).unwrap().delegators, - OrderedSet::from_sorted_set( - vec![ - StakeOf:: { owner: 6, amount: 110 }, - StakeOf:: { owner: 7, amount: 110 }, - StakeOf:: { owner: 5, amount: 100 }, - StakeOf:: { owner: 4, amount: 100 }, - ] - .try_into() - .unwrap() - ) - ); - }); -} - -#[test] -fn authorities_per_round() { - let stake = 100 * DECIMALS; - ExtBuilder::default() - .with_balances(vec![ - (1, stake), - (2, stake), - (3, stake), - (4, stake), - (5, stake), - (6, stake), - (7, stake), - (8, stake), - (9, stake), - (10, stake), - (11, 100 * stake), - ]) - .with_collators(vec![(1, stake), (2, stake), (3, stake), (4, stake)]) - .build() - .execute_with(|| { - assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2]); - // reward 1 once per round - let authors: Vec> = (0u64..=100) - .map(|i| if i % 5 == 2 { Some(1u64) } else { None }) - .collect(); - let inflation = StakePallet::inflation_config(); - - // roll to last block of round 0 - roll_to_claim_rewards(4, authors.clone()); - let reward_0 = inflation.collator.reward_rate.per_block * stake * 2; - assert_eq!(Balances::free_balance(1), stake + reward_0); - // increase max selected candidates which will become effective in round 2 - assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 10)); - - // roll to last block of round 1 - // should still multiply with 2 because the Authority set was chosen at start of - // round 1 - roll_to_claim_rewards(9, authors.clone()); - let reward_1 = inflation.collator.reward_rate.per_block * stake * 2; - assert_eq!(Balances::free_balance(1), stake + reward_0 + reward_1); - - // roll to last block of round 2 - // should multiply with 4 because there are only 4 candidates - roll_to_claim_rewards(14, authors.clone()); - let reward_2 = inflation.collator.reward_rate.per_block * stake * 4; - assert_eq!(Balances::free_balance(1), stake + reward_0 + reward_1 + reward_2); - - // roll to last block of round 3 - // should multiply with 4 because there are only 4 candidates - roll_to_claim_rewards(19, authors); - let reward_3 = inflation.collator.reward_rate.per_block * stake * 4; - assert_eq!( - Balances::free_balance(1), - stake + reward_0 + reward_1 + reward_2 + reward_3 - ); - }); -} - -#[test] -fn force_new_round() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (6, 100)]) - .with_collators(vec![(1, 100), (2, 100), (3, 100), (4, 100)]) - .build() - .execute_with(|| { - let mut round = RoundInfo { - current: 0, - first: 0, - length: 5, - }; - assert_eq!(StakePallet::round(), round); - assert_eq!(Session::validators(), vec![1, 2]); - assert_eq!(Session::current_index(), 0); - // 3 should be validator in round 2 - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(5), 3, 100)); - - // init force new round from 0 to 1, updating the authorities - assert_ok!(StakePallet::force_new_round(RuntimeOrigin::root())); - assert_eq!(StakePallet::round(), round); - assert_eq!(Session::current_index(), 0); - assert!(StakePallet::new_round_forced()); - - // force new round should become active by starting next block - roll_to(2, vec![]); - round = RoundInfo { - current: 1, - first: 2, - length: 5, - }; - assert_eq!(Session::current_index(), 1); - assert_eq!(Session::validators(), vec![1, 2]); - assert!(!StakePallet::new_round_forced()); - - // roll to next block in same round 1 - roll_to(3, vec![]); - assert_eq!(Session::current_index(), 1); - assert_eq!(StakePallet::round(), round); - // assert_eq!(Session::validators(), vec![3, 1]); - assert!(!StakePallet::new_round_forced()); - // 4 should become validator in session 3 if we do not force a new round - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(6), 4, 100)); - - // end session 2 naturally - roll_to(7, vec![]); - round = RoundInfo { - current: 2, - first: 7, - length: 5, - }; - assert_eq!(StakePallet::round(), round); - assert_eq!(Session::current_index(), 2); - assert!(!StakePallet::new_round_forced()); - assert_eq!(Session::validators(), vec![3, 1]); - - // force new round 3 - assert_ok!(StakePallet::force_new_round(RuntimeOrigin::root())); - assert_eq!(StakePallet::round(), round); - assert_eq!(Session::current_index(), 2); - // validator set should not change until next round - assert_eq!(Session::validators(), vec![3, 1]); - assert!(StakePallet::new_round_forced()); - - // force new round should become active by starting next block - roll_to(8, vec![]); - round = RoundInfo { - current: 3, - first: 8, - length: 5, - }; - assert_eq!(Session::current_index(), 3); - assert_eq!(StakePallet::round(), round); - assert_eq!(Session::validators(), vec![3, 4]); - assert!(!StakePallet::new_round_forced()); - }); -} - -#[test] -fn replace_lowest_delegator() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (6, 100)]) - .with_collators(vec![(1, 100)]) - .with_delegators(vec![(2, 1, 51), (3, 1, 51), (4, 1, 51), (5, 1, 50)]) - .build() - .execute_with(|| { - assert_eq!( - StakePallet::candidate_pool(1).unwrap().delegators.len() as u32, - ::MaxDelegatorsPerCollator::get() - ); - - // 6 replaces 5 - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(6), 1, 51)); - assert!(StakePallet::delegator_state(5).is_none()); - assert_eq!( - StakePallet::candidate_pool(1) - .unwrap() - .delegators - .into_bounded_vec() - .into_inner(), - vec![ - Stake { owner: 2, amount: 51 }, - Stake { owner: 3, amount: 51 }, - Stake { owner: 4, amount: 51 }, - Stake { owner: 6, amount: 51 } - ] - ); - - // 5 attempts to replace 6 with more balance than available - frame_support::assert_noop!( - StakePallet::join_delegators(RuntimeOrigin::signed(5), 1, 101), - BalancesError::::InsufficientBalance - ); - assert!(StakePallet::delegator_state(6).is_some()); - }) -} - -#[test] -fn network_reward_multiple_blocks() { - let max_stake: Balance = 160_000_000 * DECIMALS; - let collators: Vec<(AccountId, Balance)> = (1u64..=::MinCollators::get().saturating_add(1).into()) - .map(|acc_id| (acc_id, max_stake)) - .collect(); - - ExtBuilder::default() - .with_balances(collators.clone()) - .with_collators(collators) - .build() - .execute_with(|| { - assert_eq!(max_stake, StakePallet::max_candidate_stake()); - let total_collator_stake = max_stake.saturating_mul(::MinCollators::get().into()); - assert_eq!(total_collator_stake, StakePallet::total_collator_stake().collators); - assert!(Balances::free_balance(&TREASURY_ACC).is_zero()); - let total_issuance = ::Currency::total_issuance(); - - // total issuance should not increase when not noting authors because we haven't - // reached NetworkRewardStart yet - roll_to(10, vec![None]); - assert!(Balances::free_balance(&TREASURY_ACC).is_zero()); - assert_eq!(total_issuance, ::Currency::total_issuance()); - - // set current block to one block before NetworkRewardStart - let network_reward_start = ::NetworkRewardStart::get(); - System::set_block_number(network_reward_start.saturating_sub(1)); - - // network rewards should only appear 1 block after start - roll_to(network_reward_start, vec![None]); - assert!(Balances::free_balance(&TREASURY_ACC).is_zero()); - assert_eq!(total_issuance, ::Currency::total_issuance()); - - // should mint to treasury now - roll_to(network_reward_start + 1, vec![None]); - let network_reward = Balances::free_balance(&TREASURY_ACC); - assert!(!network_reward.is_zero()); - assert_eq!( - total_issuance + network_reward, - ::Currency::total_issuance() - ); - let inflation_config = StakePallet::inflation_config(); - let col_rewards = inflation_config.collator.reward_rate.per_block * total_collator_stake; - assert_eq!(network_reward, ::NetworkRewardRate::get() * col_rewards); - - // should mint exactly the same amount - roll_to(network_reward_start + 2, vec![None]); - assert_eq!(2 * network_reward, Balances::free_balance(&TREASURY_ACC)); - assert_eq!( - total_issuance + 2 * network_reward, - ::Currency::total_issuance() - ); - - // should mint exactly the same amount in each block - roll_to(network_reward_start + 100, vec![None]); - assert_eq!(100 * network_reward, Balances::free_balance(&TREASURY_ACC)); - assert_eq!( - total_issuance + 100 * network_reward, - ::Currency::total_issuance() - ); - - // should mint the same amount even if a collator exits because reward is only - // based on MaxCollatorCandidateStake and MaxSelectedCandidates - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(1))); - roll_to(network_reward_start + 101, vec![None]); - assert_eq!(101 * network_reward, Balances::free_balance(&TREASURY_ACC)); - assert_eq!( - total_issuance + 101 * network_reward, - ::Currency::total_issuance() - ); - }); -} - -#[test] -fn network_reward_increase_max_candidate_stake() { - let max_stake: Balance = 160_000_000 * DECIMALS; - let collators: Vec<(AccountId, Balance)> = (1u64..=::MinCollators::get().into()) - .map(|acc_id| (acc_id, max_stake)) - .collect(); - - ExtBuilder::default() - .with_balances(collators.clone()) - .with_collators(collators) - .build() - .execute_with(|| { - let network_reward_start = ::NetworkRewardStart::get(); - let total_issuance = ::Currency::total_issuance(); - System::set_block_number(network_reward_start); - - // should mint to treasury now - roll_to(network_reward_start + 1, vec![None]); - let reward_before = Balances::free_balance(&TREASURY_ACC); - assert!(!reward_before.is_zero()); - assert_eq!( - total_issuance + reward_before, - ::Currency::total_issuance() - ); - - // double max stake - let max_stake_doubled = 320_000_000 * DECIMALS; - let reward_after = 2 * reward_before; - assert_ok!(StakePallet::set_max_candidate_stake( - RuntimeOrigin::root(), - max_stake_doubled - )); - roll_to(network_reward_start + 2, vec![None]); - assert_eq!(reward_before + reward_after, Balances::free_balance(&TREASURY_ACC)); - assert_eq!( - reward_before + reward_after + total_issuance, - ::Currency::total_issuance() - ); - }); -} - -#[test] -fn network_reward_increase_max_collator_count() { - let max_stake: Balance = 160_000_000 * DECIMALS; - let collators: Vec<(AccountId, Balance)> = (1u64..=::MinCollators::get().into()) - .map(|acc_id| (acc_id, max_stake)) - .collect(); - - ExtBuilder::default() - .with_balances(collators.clone()) - .with_collators(collators) - .build() - .execute_with(|| { - let network_reward_start = ::NetworkRewardStart::get(); - let total_issuance = ::Currency::total_issuance(); - System::set_block_number(network_reward_start); - - // should mint to treasury now - roll_to(network_reward_start + 1, vec![None]); - let reward_before = Balances::free_balance(&TREASURY_ACC); - assert!(!reward_before.is_zero()); - assert_eq!( - total_issuance + reward_before, - ::Currency::total_issuance() - ); - - // tripple number of max collators - let reward_after = 3 * reward_before; - assert_ok!(StakePallet::set_max_selected_candidates( - RuntimeOrigin::root(), - ::MinCollators::get() * 3 - )); - roll_to(network_reward_start + 2, vec![None]); - assert_eq!(reward_before + reward_after, Balances::free_balance(&TREASURY_ACC)); - assert_eq!( - reward_before + reward_after + total_issuance, - ::Currency::total_issuance() - ); - }); -} - -#[test] -fn update_total_stake_collators_stay() { - ExtBuilder::default() - .with_balances(vec![(1, 200), (2, 200), (3, 200), (4, 200)]) - .with_collators(vec![(1, 100), (2, 50)]) - .with_delegators(vec![(3, 1, 100), (4, 2, 50)]) - .build() - .execute_with(|| { - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 150, - delegators: 150 - } - ); - assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 10)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 160, - delegators: 150 - } - ); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(2), 5)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 155, - delegators: 150 - } - ); - assert_ok!(StakePallet::delegator_stake_more(RuntimeOrigin::signed(3), 10)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 155, - delegators: 160 - } - ); - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(4), 5)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 155, - delegators: 155 - } - ); - }); -} - -#[test] -fn update_total_stake_displace_collators() { - ExtBuilder::default() - .with_balances(vec![ - (1, 200), - (2, 200), - (3, 200), - (4, 200), - (5, 200), - (6, 200), - (7, 200), - (8, 200), - (1337, 200), - ]) - .with_collators(vec![(1, 10), (2, 20), (3, 30), (4, 40)]) - .with_delegators(vec![(5, 1, 50), (6, 2, 50), (7, 3, 55), (8, 4, 55)]) - .build() - .execute_with(|| { - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 70, - delegators: 110 - } - ); - - // 4 is pushed out by staking less - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(4), 30)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 50, - delegators: 105 - } - ); - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(8), 45)); - - // 3 is pushed out by delegator staking less - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(7), 45)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 30, - delegators: 100 - } - ); - - // 1 is pushed out by new candidate - assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(1337), 100)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 120, - delegators: 50 - } - ); - }); -} - -#[test] -fn update_total_stake_new_collators() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100)]) - .with_collators(vec![(1, 100)]) - .with_delegators(vec![(4, 1, 100)]) - .build() - .execute_with(|| { - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 100, - delegators: 100 - } - ); - assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(2), 100)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 200, - delegators: 100 - } - ); - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(3), 2, 50)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 200, - delegators: 150 - } - ); - assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(4))); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 200, - delegators: 50 - } - ); - }); -} - -#[test] -fn update_total_stake_no_collator_changes() { - ExtBuilder::default() - .with_balances(vec![ - (1, 200), - (2, 200), - (3, 200), - (4, 200), - (5, 200), - (6, 200), - (7, 200), - (8, 200), - (1337, 200), - ]) - .with_collators(vec![(1, 10), (2, 20), (3, 30), (4, 40)]) - .with_delegators(vec![(5, 1, 50), (6, 2, 50), (7, 3, 55), (8, 4, 55)]) - .build() - .execute_with(|| { - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 70, - delegators: 110 - } - ); - assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 10)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 70, - delegators: 110 - } - ); - assert_ok!(StakePallet::delegator_stake_more(RuntimeOrigin::signed(5), 10)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 70, - delegators: 110 - } - ); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(2), 10)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 70, - delegators: 110 - } - ); - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(6), 10)); - assert_eq!( - StakePallet::total_collator_stake(), - TotalStake { - collators: 70, - delegators: 110 - } - ); - }); -} - -#[test] -fn rewards_candidate_stake_more() { - ExtBuilder::default() - .with_balances(vec![(1, 2 * DECIMALS), (2, DECIMALS), (3, DECIMALS)]) - .with_collators(vec![(1, DECIMALS)]) - .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) - .build() - .execute_with(|| { - // note once to set counter to 1 - StakePallet::note_author(1); - assert_eq!(StakePallet::blocks_authored(1), 1); - assert!(StakePallet::blocks_authored(2).is_zero()); - assert!(StakePallet::blocks_authored(3).is_zero()); - (1..=3).for_each(|id| { - assert!(StakePallet::blocks_rewarded(id).is_zero()); - assert!(StakePallet::rewards(id).is_zero()); - }); - - // stake less to trigger reward incrementing for collator - assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), DECIMALS)); - assert!(!StakePallet::rewards(1).is_zero()); - assert!(!StakePallet::blocks_rewarded(1).is_zero()); - // delegator reward storage should be untouched - (2..=3).for_each(|id| { - assert!( - StakePallet::rewards(id).is_zero(), - "Rewards not zero for acc_id {:?}", - id - ); - assert!( - StakePallet::blocks_rewarded(id).is_zero(), - "BlocksRewaeded not zero for acc_id {:?}", - id - ); - }); - }); -} - -#[test] -fn rewards_candidate_stake_less() { - ExtBuilder::default() - .with_balances(vec![(1, 2 * DECIMALS), (2, DECIMALS), (3, DECIMALS)]) - .with_collators(vec![(1, 2 * DECIMALS)]) - .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) - .build() - .execute_with(|| { - // note once to set counter to 1 - StakePallet::note_author(1); - assert_eq!(StakePallet::blocks_authored(1), 1); - assert!(StakePallet::blocks_authored(2).is_zero()); - assert!(StakePallet::blocks_authored(3).is_zero()); - (1..=3).for_each(|id| { - assert!(StakePallet::blocks_rewarded(id).is_zero()); - assert!(StakePallet::rewards(id).is_zero()); - }); - - // stake less to trigger reward incrementing for collator - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), DECIMALS)); - assert!(!StakePallet::rewards(1).is_zero()); - assert!(!StakePallet::blocks_rewarded(1).is_zero()); - // delegator reward storage should be untouched - (2..=3).for_each(|id| { - assert!( - StakePallet::rewards(id).is_zero(), - "Rewards not zero for acc_id {:?}", - id - ); - assert!( - StakePallet::blocks_rewarded(id).is_zero(), - "BlocksRewaeded not zero for acc_id {:?}", - id - ); - }); - }); -} - -#[test] -fn rewards_candidate_leave_network() { - ExtBuilder::default() - .with_balances(vec![ - (1, 2 * DECIMALS), - (2, DECIMALS), - (3, DECIMALS), - (4, DECIMALS), - (5, DECIMALS), - ]) - .with_collators(vec![(1, 2 * DECIMALS), (4, DECIMALS), (5, DECIMALS)]) - .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) - .build() - .execute_with(|| { - // init does not increment rewards - assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(1))); - - // advance two rounds to enable leaving - roll_to( - 10, - vec![ - // we're already in block 1, so cant note_author for block 1 - None, - Some(1), - Some(2), - Some(1), - Some(2), - Some(1), - Some(2), - Some(1), - Some(2), - ], - ); - // Only authored should be bumped for collator, not rewarded - assert_eq!(StakePallet::blocks_authored(1), 4 * 2); - assert!(StakePallet::blocks_rewarded(1).is_zero()); - - // count for delegators should not be incremented - assert!(StakePallet::blocks_rewarded(2).is_zero()); - assert!(StakePallet::blocks_rewarded(3).is_zero()); - - // rewards should not be incremented - (1..=3).for_each(|id| { - assert!(StakePallet::rewards(id).is_zero()); - }); - - // execute leave intent to trigger reward incrementing for collator and - // delegators - assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(1), 1)); - - // reward counting storages should be killed for collator - assert!(StakePallet::blocks_authored(1).is_zero()); - assert!(StakePallet::blocks_rewarded(1).is_zero()); - assert!(!StakePallet::rewards(1).is_zero()); - - // reward counting storages should NOT be killed for delegators - (2..=3).for_each(|id| { - assert!(!StakePallet::rewards(id).is_zero(), "Zero rewards acc_id {:?}", id); - assert_eq!( - StakePallet::blocks_rewarded(id), - 4 * 2, - "Rewarded blocks Delegator {:?} do not match up with exited collator", - id - ); - }); - }); -} - -#[test] -fn rewards_force_remove_candidate() { - ExtBuilder::default() - .with_balances(vec![ - (1, DECIMALS), - (2, DECIMALS), - (3, DECIMALS), - (4, DECIMALS), - (5, DECIMALS), - ]) - .with_collators(vec![(1, DECIMALS), (4, DECIMALS), (5, DECIMALS)]) - .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) - .build() - .execute_with(|| { - // init does not increment rewards - StakePallet::note_author(1); - StakePallet::note_author(2); - - // removing triggers reward increment for collator 1 and delegators 4, 5 - assert_ok!(StakePallet::force_remove_candidate(RuntimeOrigin::root(), 1)); - // rewarded counter storage should be killed for collator - assert!(StakePallet::blocks_authored(1).is_zero()); - assert!(StakePallet::blocks_rewarded(1).is_zero()); - // rewards should be set - assert!(!StakePallet::rewards(1).is_zero()); - - (1..=3).for_each(|id| { - // rewards should be non zero - assert!(!StakePallet::rewards(id).is_zero(), "Zero rewards for acc_id {:?}", id); - // rewards should equal API call - assert_eq!( - StakePallet::get_unclaimed_staking_rewards(&id), - StakePallet::rewards(id) - ); - if id > 1 { - assert_eq!( - StakePallet::blocks_rewarded(id), - 2, - "Rewarded counter does not match for delegator {:?}", - id - ); - } - }); - assert_eq!(StakePallet::get_unclaimed_staking_rewards(&1), StakePallet::rewards(1)); - - (4..=5).for_each(|id| { - assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); - assert!(StakePallet::blocks_rewarded(id).is_zero(), "acc_id {:?}", id); - }); - }); -} - -#[test] -fn blocks_rewarded_join_delegators() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100)]) - .with_collators(vec![(1, 100)]) - .build() - .execute_with(|| { - // note once to set counter to 1 - StakePallet::note_author(1); - assert_eq!(StakePallet::blocks_authored(1), 1); - assert!(StakePallet::blocks_rewarded(1).is_zero()); - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 100)); - // delegator's rewarded counter should equal of collator's authored counter upon - // joining - assert_eq!(StakePallet::blocks_rewarded(2), StakePallet::blocks_authored(1)); - }); -} - -#[test] -fn rewards_delegator_stake_more() { - ExtBuilder::default() - .with_balances(vec![(1, DECIMALS), (2, DECIMALS), (3, 2 * DECIMALS)]) - .with_collators(vec![(1, DECIMALS)]) - .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) - .build() - .execute_with(|| { - // note once to set counter to 1 - StakePallet::note_author(1); - assert_eq!(StakePallet::blocks_authored(1), 1); - assert!(StakePallet::blocks_rewarded(2).is_zero()); - assert!(StakePallet::blocks_rewarded(3).is_zero()); - (1..=3).for_each(|id| { - assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); - }); - - // stake less to trigger reward incrementing just for 3 - assert_ok!(StakePallet::delegator_stake_more(RuntimeOrigin::signed(3), DECIMALS)); - // 1 should still have counter 1 but no rewards - assert_eq!(StakePallet::blocks_authored(1), 1); - assert!(StakePallet::blocks_rewarded(1).is_zero()); - assert!(StakePallet::rewards(1).is_zero()); - // 2 should still have neither rewards nor counter - assert!(StakePallet::blocks_rewarded(2).is_zero()); - assert!(StakePallet::rewards(2).is_zero()); - // 3 should have rewards and the same counter as 1 - assert_eq!(StakePallet::blocks_rewarded(3), 1); - assert!(!StakePallet::rewards(3).is_zero()); - }); -} - -#[test] -fn rewards_delegator_stake_less() { - ExtBuilder::default() - .with_balances(vec![(1, DECIMALS), (2, DECIMALS), (3, 2 * DECIMALS)]) - .with_collators(vec![(1, DECIMALS)]) - .with_delegators(vec![(2, 1, DECIMALS), (3, 1, 2 * DECIMALS)]) - .build() - .execute_with(|| { - // note once to set counter to 1 - StakePallet::note_author(1); - assert_eq!(StakePallet::blocks_authored(1), 1); - assert!(StakePallet::blocks_rewarded(2).is_zero()); - assert!(StakePallet::blocks_rewarded(3).is_zero()); - (1..=3).for_each(|id| { - assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); - }); - - // stake less to trigger reward incrementing just for 3 - assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(3), DECIMALS)); - // 1 should still have counter 1 but no rewards - assert_eq!(StakePallet::blocks_authored(1), 1); - assert!(StakePallet::blocks_rewarded(1).is_zero()); - assert!(StakePallet::rewards(1).is_zero()); - // 2 should still have neither rewards nor counter - assert!(StakePallet::blocks_rewarded(2).is_zero()); - assert!(StakePallet::rewards(2).is_zero()); - // 3 should have rewards and the same counter as 1 - assert_eq!(StakePallet::blocks_rewarded(3), 1); - assert!(!StakePallet::rewards(3).is_zero()); - }); -} - -#[test] -fn rewards_delegator_replaced() { - ExtBuilder::default() - .with_balances(vec![ - (1, 2 * DECIMALS), - (2, 2 * DECIMALS), - (3, 2 * DECIMALS), - (4, 2 * DECIMALS), - (5, 2 * DECIMALS), - (6, 2 * DECIMALS), - ]) - .with_collators(vec![(1, 2 * DECIMALS)]) - .with_delegators(vec![ - (2, 1, 2 * DECIMALS), - (3, 1, 2 * DECIMALS), - (4, 1, 2 * DECIMALS), - (5, 1, DECIMALS), - ]) - .build() - .execute_with(|| { - // note once to set counter to 1 - StakePallet::note_author(1); - assert_eq!(StakePallet::blocks_authored(1), 1); - - // 6 kicks 5 - assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(6), 1, 2 * DECIMALS)); - // 5 should have rewards and counter updated - assert!(!StakePallet::rewards(5).is_zero()); - assert_eq!(StakePallet::blocks_rewarded(5), 1); - // 6 should not have rewards but same counter as former collator - assert!(StakePallet::rewards(6).is_zero()); - assert_eq!(StakePallet::blocks_rewarded(6), 1); - }); -} - -#[test] -fn rewards_delegator_leaves() { - ExtBuilder::default() - .with_balances(vec![(1, DECIMALS), (2, DECIMALS), (3, DECIMALS)]) - .with_collators(vec![(1, DECIMALS)]) - .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) - .build() - .execute_with(|| { - // note collator once to set their counter to 1 - StakePallet::note_author(1); - assert_eq!(StakePallet::blocks_authored(1), 1); - assert!(StakePallet::blocks_rewarded(2).is_zero()); - assert!(StakePallet::blocks_rewarded(3).is_zero()); - (1..=3).for_each(|id| { - assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); - }); - - // only 3 should have non-zero rewards - assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(3))); - assert!(StakePallet::blocks_rewarded(1).is_zero()); - assert!(StakePallet::rewards(1).is_zero()); - assert!(StakePallet::blocks_rewarded(2).is_zero()); - assert!(StakePallet::rewards(2).is_zero()); - assert!(!StakePallet::rewards(3).is_zero()); - assert_eq!(StakePallet::get_unclaimed_staking_rewards(&3), StakePallet::rewards(3)); - // counter should be reset due to leaving - assert!(StakePallet::blocks_rewarded(3).is_zero()); - }); -} - -#[test] -fn rewards_set_inflation() { - let hundred = Perquintill::from_percent(100); - ExtBuilder::default() - .with_balances(vec![ - (1, DECIMALS), - (2, DECIMALS), - (3, DECIMALS), - (4, DECIMALS), - (5, DECIMALS), - ]) - .with_collators(vec![(1, DECIMALS), (2, DECIMALS)]) - .with_delegators(vec![(3, 1, DECIMALS), (4, 1, DECIMALS), (5, 2, DECIMALS)]) - .build() - .execute_with(|| { - // note collators - StakePallet::note_author(1); - StakePallet::note_author(1); - StakePallet::note_author(2); - - // set inflation to trigger reward setting - assert_ok!(StakePallet::set_inflation( - RuntimeOrigin::root(), - hundred, - hundred, - hundred, - hundred - )); - // rewards and counters should be set - (1..=5).for_each(|id| { - assert!(!StakePallet::blocks_rewarded(id).is_zero(), "acc_id {:?}", id); - assert!(!StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); - }); - }); -} - -#[test] -fn rewards_yearly_inflation_adjustment() { - ExtBuilder::default() - .with_balances(vec![ - (1, DECIMALS), - (2, DECIMALS), - (3, DECIMALS), - (4, DECIMALS), - (5, DECIMALS), - ]) - .with_collators(vec![(1, DECIMALS), (2, DECIMALS)]) - .with_delegators(vec![(3, 1, DECIMALS), (4, 1, DECIMALS), (5, 2, DECIMALS)]) - .build() - .execute_with(|| { - // init counter and go to next year - StakePallet::note_author(1); - StakePallet::note_author(2); - System::set_block_number(::BLOCKS_PER_YEAR - 1); - roll_to_claim_rewards(::BLOCKS_PER_YEAR + 1, vec![]); - assert!(!StakePallet::blocks_authored(1).is_zero()); - assert!(!StakePallet::blocks_authored(2).is_zero()); - - // rewards should not be triggered before executing pending adjustment - (1..=5).for_each(|id| { - assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); - }); - - // execute to trigger reward increment - assert_ok!(StakePallet::execute_scheduled_reward_change(RuntimeOrigin::signed(1))); - (1..=5).for_each(|id| { - assert!( - !StakePallet::blocks_rewarded(id).is_zero(), - "Zero rewarded blocks for acc_id {:?}", - id - ); - assert!(!StakePallet::rewards(id).is_zero(), "Zero rewards for acc_id {:?}", id); - }); - }); -} - -#[test] -fn rewards_incrementing_and_claiming() { - ExtBuilder::default() - .with_balances(vec![(1, DECIMALS), (2, DECIMALS), (3, DECIMALS)]) - .with_collators(vec![(1, DECIMALS)]) - .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) - .build() - .execute_with(|| { - // claiming should not be possible with zero counters - (1..=3).for_each(|id| { - assert_noop!( - StakePallet::claim_rewards(RuntimeOrigin::signed(id)), - Error::::RewardsNotFound, - ); - }); - - // note once to set counter to 1 - StakePallet::note_author(1); - assert_eq!(StakePallet::blocks_authored(1), 1); - assert!(StakePallet::blocks_rewarded(2).is_zero()); - - // claiming should not be possible before incrementing rewards - (1..=3).for_each(|id| { - assert_noop!( - StakePallet::claim_rewards(RuntimeOrigin::signed(id)), - Error::::RewardsNotFound - ); - }); - - // increment rewards for 2 and match counter to collator - assert_ok!(StakePallet::increment_delegator_rewards(RuntimeOrigin::signed(2))); - assert_eq!(StakePallet::blocks_rewarded(2), 1); - let rewards_2 = StakePallet::rewards(2); - assert!(!rewards_2.is_zero()); - assert!(StakePallet::blocks_rewarded(3).is_zero()); - assert!(StakePallet::rewards(3).is_zero()); - - // should only update rewards for collator as well - assert_ok!(StakePallet::increment_collator_rewards(RuntimeOrigin::signed(1))); - assert_eq!(StakePallet::blocks_rewarded(1), StakePallet::blocks_authored(1)); - assert!(!StakePallet::rewards(1).is_zero()); - // rewards of 2 should not be changed - assert_eq!(StakePallet::rewards(2), rewards_2); - // 3 should still not have blocks rewarded bumped - assert!(StakePallet::blocks_rewarded(3).is_zero()); - - // claim for 1 to move rewards into balance - assert_ok!(StakePallet::claim_rewards(RuntimeOrigin::signed(1))); - assert!(StakePallet::rewards(1).is_zero()); - // delegator situation should be unchanged - assert!(Balances::free_balance(&1) > DECIMALS); - assert_eq!(Balances::free_balance(&2), DECIMALS); - assert_eq!(Balances::free_balance(&3), DECIMALS); - - // incrementing again should not change anything because collator has not - // authored blocks since last inc - assert_ok!(StakePallet::increment_delegator_rewards(RuntimeOrigin::signed(2))); - assert_eq!(StakePallet::blocks_rewarded(2), 1); - // claim for 2 to move rewards into balance - assert_ok!(StakePallet::claim_rewards(RuntimeOrigin::signed(2))); - assert!(Balances::free_balance(&2) > DECIMALS); - assert!(StakePallet::rewards(2).is_zero()); - assert_eq!(Balances::free_balance(&3), DECIMALS); - - // should not be able to claim for incorrect role - assert_noop!( - StakePallet::increment_collator_rewards(RuntimeOrigin::signed(2)), - Error::::CandidateNotFound - ); - assert_noop!( - StakePallet::increment_delegator_rewards(RuntimeOrigin::signed(1)), - Error::::DelegatorNotFound - ); - }); -} - -#[test] -fn api_get_unclaimed_staking_rewards() { - let stake = 100_000 * DECIMALS; - ExtBuilder::default() - .with_balances(vec![(1, stake), (2, stake), (3, 100 * stake)]) - .with_collators(vec![(1, stake), (3, 2 * stake)]) - .with_delegators(vec![(2, 1, stake)]) - .build() - .execute_with(|| { - let inflation_config = StakePallet::inflation_config(); - - // Increment rewards of 1 and 2 - roll_to(2, vec![None, Some(1)]); - assert_eq!( - StakePallet::get_unclaimed_staking_rewards(&1), - // Multiplying with 2 because there are two authors - inflation_config.collator.reward_rate.per_block * stake * 2 - ); - assert_eq!( - StakePallet::get_unclaimed_staking_rewards(&2), - inflation_config.delegator.reward_rate.per_block * stake * 2 - ); - assert!(StakePallet::get_unclaimed_staking_rewards(&3).is_zero()); - - // Should only increment rewards of 3 - roll_to(3, vec![None, None, Some(3)]); - let rewards_1 = StakePallet::get_unclaimed_staking_rewards(&1); - let rewards_2 = StakePallet::get_unclaimed_staking_rewards(&2); - let rewards_3 = StakePallet::get_unclaimed_staking_rewards(&3); - assert_eq!(2 * rewards_1, rewards_3,); - assert_eq!(rewards_2, inflation_config.delegator.reward_rate.per_block * stake * 2); - - // API and actual claiming should match - assert_ok!(StakePallet::increment_collator_rewards(RuntimeOrigin::signed(1))); - assert_ok!(StakePallet::claim_rewards(RuntimeOrigin::signed(1))); - assert_eq!(rewards_1, Balances::usable_balance(&1)); - assert!(StakePallet::get_unclaimed_staking_rewards(&1).is_zero()); - - assert_ok!(StakePallet::increment_delegator_rewards(RuntimeOrigin::signed(2))); - assert_ok!(StakePallet::claim_rewards(RuntimeOrigin::signed(2))); - assert_eq!(rewards_2, Balances::usable_balance(&2)); - assert!(StakePallet::get_unclaimed_staking_rewards(&2).is_zero()); - - assert_ok!(StakePallet::increment_collator_rewards(RuntimeOrigin::signed(3))); - assert_ok!(StakePallet::claim_rewards(RuntimeOrigin::signed(3))); - assert_eq!(rewards_3 + 98 * stake, Balances::usable_balance(&3)); - assert!(StakePallet::get_unclaimed_staking_rewards(&3).is_zero()); - }); -} - -#[test] -fn api_get_staking_rates() { - let stake = 100_000 * DECIMALS; - ExtBuilder::default() - .with_balances(vec![(1, stake), (2, stake), (3, 2 * stake)]) - .with_collators(vec![(1, stake), (2, stake)]) - .with_delegators(vec![(3, 1, stake)]) - .with_inflation(25, 10, 25, 8, ::BLOCKS_PER_YEAR) - .build() - .execute_with(|| { - let mut rates = StakingRates { - collator_staking_rate: Perquintill::from_percent(50), - collator_reward_rate: Perquintill::from_percent(5), - delegator_staking_rate: Perquintill::from_percent(25), - delegator_reward_rate: Perquintill::from_percent(8), - }; - // collators exceed max staking rate - assert_eq!(rates, StakePallet::get_staking_rates()); - - // candidates stake less to not exceed max staking rate - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), stake / 2)); - assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(2), stake / 2)); - // delegator stakes more to exceed - assert_ok!(StakePallet::delegator_stake_more(RuntimeOrigin::signed(3), stake)); - rates.collator_staking_rate = Perquintill::from_percent(25); - rates.collator_reward_rate = Perquintill::from_percent(10); - rates.delegator_staking_rate = Perquintill::from_percent(50); - rates.delegator_reward_rate = Perquintill::from_percent(4); - assert_eq!(rates, StakePallet::get_staking_rates()); - }); -} diff --git a/pallets/parachain-staking/src/types.rs b/pallets/parachain-staking/src/types.rs deleted file mode 100644 index 0bc0d59ad..000000000 --- a/pallets/parachain-staking/src/types.rs +++ /dev/null @@ -1,321 +0,0 @@ -// KILT Blockchain – https://botlabs.org -// Copyright (C) 2019-2023 BOTLabs GmbH - -// The KILT Blockchain 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. - -// The KILT Blockchain 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 this program. If not, see . - -// If you feel like getting in touch with us, you can do so at info@botlabs.org - -use frame_support::traits::{Currency, Get}; -use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; -use scale_info::TypeInfo; -use sp_runtime::{ - traits::{AtLeast32BitUnsigned, CheckedSub, Saturating, Zero}, - RuntimeDebug, -}; -use sp_staking::SessionIndex; -use sp_std::{ - cmp::Ordering, - fmt::Debug, - ops::{Add, Sub}, -}; - -use crate::{set::OrderedSet, Config}; - -/// A struct represented an amount of staked funds. -/// -/// The stake has a destination account (to which the stake is directed) and an -/// amount of funds staked. -#[derive(Default, Clone, Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo, MaxEncodedLen)] -#[codec(mel_bound(AccountId: MaxEncodedLen, Balance: MaxEncodedLen))] -pub struct Stake -where - AccountId: Eq + Ord, - Balance: Eq + Ord, -{ - /// The account that is backed by the stake. - pub owner: AccountId, - - /// The amount of backing the `owner` received. - pub amount: Balance, -} - -impl From for Stake -where - A: Eq + Ord, - B: Default + Eq + Ord, -{ - fn from(owner: A) -> Self { - Stake { - owner, - amount: B::default(), - } - } -} - -impl PartialOrd for Stake { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -// We order by stake and only return an equal order, if both account ids match. -// This prevents the same account ids to be in the same OrderedSet. Otherwise, -// it is ordered from greatest to lowest stake (primary) and from first joined -// to last joined (primary). -impl Ord for Stake { - fn cmp(&self, other: &Self) -> Ordering { - match (self.owner.cmp(&other.owner), self.amount.cmp(&other.amount)) { - // enforce unique account ids - (Ordering::Equal, _) => Ordering::Equal, - // prioritize existing members if stakes match - (_, Ordering::Equal) => Ordering::Greater, - // order by stake - (_, ord) => ord, - } - } -} - -/// The activity status of the collator. -#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)] -pub enum CandidateStatus { - /// Committed to be online and producing valid blocks (not equivocating) - Active, - /// Staked until the inner round - Leaving(SessionIndex), -} - -impl Default for CandidateStatus { - fn default() -> CandidateStatus { - CandidateStatus::Active - } -} - -#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo, MaxEncodedLen)] -#[scale_info(skip_type_params(MaxDelegatorsPerCandidate))] -#[codec(mel_bound(AccountId: MaxEncodedLen, Balance: MaxEncodedLen))] -/// Global collator state with commission fee, staked funds, and delegations -pub struct Candidate -where - AccountId: Eq + Ord + Debug, - Balance: Eq + Ord + Debug, - MaxDelegatorsPerCandidate: Get + Debug + PartialEq, -{ - /// Account id of the candidate. - pub id: AccountId, - - /// The stake that the candidate put down. - pub stake: Balance, - - /// The delegators that back the candidate. - pub delegators: OrderedSet, MaxDelegatorsPerCandidate>, - - /// The total backing a collator has. - /// - /// Should equal the sum of all delegators stake adding collators stake - pub total: Balance, - - /// The current status of the candidate. Indicates whether a candidate is - /// active or leaving the candidate pool - pub status: CandidateStatus, -} - -impl Candidate -where - A: Ord + Clone + Debug, - B: AtLeast32BitUnsigned + Ord + Copy + Saturating + Debug + Zero, - S: Get + Debug + PartialEq, -{ - pub fn new(id: A, stake: B) -> Self { - let total = stake; - Candidate { - id, - stake, - delegators: OrderedSet::new(), - total, - status: CandidateStatus::default(), // default active - } - } - - pub fn is_active(&self) -> bool { - self.status == CandidateStatus::Active - } - - pub fn is_leaving(&self) -> bool { - matches!(self.status, CandidateStatus::Leaving(_)) - } - - pub fn can_exit(&self, when: u32) -> bool { - matches!(self.status, CandidateStatus::Leaving(at) if at <= when ) - } - - pub fn revert_leaving(&mut self) { - self.status = CandidateStatus::Active; - } - - pub fn stake_more(&mut self, more: B) { - self.stake = self.stake.saturating_add(more); - self.total = self.total.saturating_add(more); - } - - // Returns None if underflow or less == self.stake (in which case collator - // should leave). - pub fn stake_less(&mut self, less: B) -> Option { - if self.stake > less { - self.stake = self.stake.saturating_sub(less); - self.total = self.total.saturating_sub(less); - Some(self.stake) - } else { - None - } - } - - pub fn inc_delegator(&mut self, delegator: A, more: B) { - if let Ok(i) = self.delegators.linear_search(&Stake:: { - owner: delegator, - amount: B::zero(), - }) { - self.delegators - .mutate(|vec| vec[i].amount = vec[i].amount.saturating_add(more)); - self.total = self.total.saturating_add(more); - self.delegators.sort_greatest_to_lowest() - } - } - - pub fn dec_delegator(&mut self, delegator: A, less: B) { - if let Ok(i) = self.delegators.linear_search(&Stake:: { - owner: delegator, - amount: B::zero(), - }) { - self.delegators - .mutate(|vec| vec[i].amount = vec[i].amount.saturating_sub(less)); - self.total = self.total.saturating_sub(less); - self.delegators.sort_greatest_to_lowest() - } - } - - pub fn leave_candidates(&mut self, round: SessionIndex) { - self.status = CandidateStatus::Leaving(round); - } -} - -pub type Delegator = Stake; -impl Delegator -where - AccountId: Eq + Ord + Clone + Debug, - Balance: Copy + Add + Saturating + PartialOrd + Eq + Ord + Debug + Zero + Default + CheckedSub, -{ - /// Returns Ok if the delegation for the - /// collator exists and `Err` otherwise. - pub fn try_clear(&mut self, collator: AccountId) -> Result<(), ()> { - if self.owner == collator { - self.amount = Balance::zero(); - Ok(()) - } else { - Err(()) - } - } - - /// Returns Ok(delegated_amount) if successful, `Err` if delegation was - /// not found. - pub fn try_increment(&mut self, collator: AccountId, more: Balance) -> Result { - if self.owner == collator { - self.amount = self.amount.saturating_add(more); - Ok(self.amount) - } else { - Err(()) - } - } - - /// Returns Ok(Some(delegated_amount)) if successful, `Err` if delegation - /// was not found and Ok(None) if delegated stake would underflow. - pub fn try_decrement(&mut self, collator: AccountId, less: Balance) -> Result, ()> { - if self.owner == collator { - Ok(self.amount.checked_sub(&less).map(|new| { - self.amount = new; - self.amount - })) - } else { - Err(()) - } - } -} - -/// The current round index and transition information. -#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)] -pub struct RoundInfo { - /// Current round index. - pub current: SessionIndex, - /// The first block of the current round. - pub first: BlockNumber, - /// The length of the current round in blocks. - pub length: BlockNumber, -} - -impl RoundInfo -where - B: Copy + Saturating + From + PartialOrd, -{ - pub fn new(current: SessionIndex, first: B, length: B) -> RoundInfo { - RoundInfo { current, first, length } - } - - /// Checks if the round should be updated. - /// - /// The round should update if `self.length` or more blocks where produced - /// after `self.first`. - pub fn should_update(&self, now: B) -> bool { - let l = now.saturating_sub(self.first); - l >= self.length - } - - /// Starts a new round. - pub fn update(&mut self, now: B) { - self.current = self.current.saturating_add(1u32); - self.first = now; - } -} - -impl Default for RoundInfo -where - B: Copy + Saturating + Add + Sub + From + PartialOrd, -{ - fn default() -> RoundInfo { - RoundInfo::new(0u32, 0u32.into(), 20.into()) - } -} - -/// The total stake of the pallet. -/// -/// The stake includes both collators' and delegators' staked funds. -#[derive(Default, Clone, Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo, MaxEncodedLen)] -pub struct TotalStake { - pub collators: Balance, - pub delegators: Balance, -} - -/// The number of delegations a delegator has done within the last session in -/// which they delegated. -#[derive(Default, Clone, Encode, Decode, Eq, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)] -pub struct DelegationCounter { - /// The index of the last delegation. - pub round: SessionIndex, - /// The number of delegations made within round. - pub counter: u32, -} - -pub type AccountIdOf = ::AccountId; -pub type BalanceOf = <::Currency as Currency>>::Balance; -pub type CandidateOf = Candidate, BalanceOf, S>; -pub type StakeOf = Stake, BalanceOf>; -pub type NegativeImbalanceOf = <::Currency as Currency>>::NegativeImbalance; diff --git a/pallets/sandbox/Cargo.toml b/pallets/sandbox/Cargo.toml index 7fd58da17..2fbc67cbf 100644 --- a/pallets/sandbox/Cargo.toml +++ b/pallets/sandbox/Cargo.toml @@ -40,7 +40,6 @@ sp-runtime.workspace = true pallet-balances.workspace = true pallet-insecure-randomness-collective-flip.workspace = true pallet-assets.workspace = true -pallet-credentials.workspace = true [features] @@ -58,7 +57,6 @@ std = [ "sp-runtime/std", "pallet-assets/std", "pallet-balances/std", - "pallet-credentials/std", "polimec-traits/std", "frame-benchmarking?/std", "parachains-common/std", diff --git a/pallets/sandbox/src/mock.rs b/pallets/sandbox/src/mock.rs index b1dacf3bf..f23912681 100644 --- a/pallets/sandbox/src/mock.rs +++ b/pallets/sandbox/src/mock.rs @@ -50,7 +50,6 @@ frame_support::construct_runtime!( Assets: pallet_assets, Balances: pallet_balances, FundingModule: pallet_funding, - Credentials: pallet_credentials, Sandbox: crate, } ); @@ -106,17 +105,6 @@ impl pallet_balances::Config for TestRuntime { impl pallet_insecure_randomness_collective_flip::Config for TestRuntime {} -impl pallet_credentials::Config for TestRuntime { - type RuntimeEvent = RuntimeEvent; - type AddOrigin = EnsureSigned; - type RemoveOrigin = EnsureSigned; - type SwapOrigin = EnsureSigned; - type ResetOrigin = EnsureSigned; - type PrimeOrigin = EnsureSigned; - type MembershipInitialized = (); - type MembershipChanged = (); -} - impl pallet_assets::Config for TestRuntime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; @@ -167,7 +155,6 @@ impl pallet_funding::Config for TestRuntime { type MaxProjectsToUpdatePerBlock = ConstU32<100>; type CommunityFundingDuration = CommunityRoundDuration; type Randomness = RandomnessCollectiveFlip; - type HandleMembers = Credentials; type PreImageLimit = ConstU32<1024>; // Low value to simplify the tests type MaximumBidsPerUser = ConstU32<4>; @@ -192,12 +179,6 @@ pub fn new_test_ext() -> sp_io::TestExternalities { GenesisConfig { balances: BalancesConfig { balances: vec![] }, - credentials: CredentialsConfig { - issuers: vec![1, 16558220937623665250], - retails: vec![2], - professionals: vec![2, 3], - institutionals: vec![4], - }, ..Default::default() } .assimilate_storage(&mut t) diff --git a/pallets/sandbox/src/tests.rs b/pallets/sandbox/src/tests.rs index 71fdc3562..c6ef58158 100644 --- a/pallets/sandbox/src/tests.rs +++ b/pallets/sandbox/src/tests.rs @@ -133,12 +133,6 @@ pub fn new_test_ext() -> sp_io::TestExternalities { (4, 10_000_000 * PLMC), ], }, - credentials: CredentialsConfig { - issuers: vec![1, 16558220937623665250], - retails: vec![2], - professionals: vec![2, 3], - institutionals: vec![4], - }, ..Default::default() } .assimilate_storage(&mut t) diff --git a/runtime-api/credentials/Cargo.toml b/runtime-api/credentials/Cargo.toml deleted file mode 100644 index 6874844cf..000000000 --- a/runtime-api/credentials/Cargo.toml +++ /dev/null @@ -1,35 +0,0 @@ -[package] -name = 'polimec-runtime-api-credentials' -description = "Runtime APIs for dealing with credentials and membership." -authors.workspace = true -documentation.workspace = true -edition.workspace = true -homepage.workspace = true -license-file.workspace = true -readme.workspace = true -repository.workspace = true -version.workspace = true - - -[dependencies] -parity-scale-codec = { workspace = true, features = [ - "derive", -] } -scale-info = { workspace = true, features = ["derive"] } - -sp-runtime.workspace = true -sp-api.workspace = true -sp-std.workspace = true -polimec-traits.workspace = true - - -[features] -default = ["std"] -std = [ - "sp-api/std", - "parity-scale-codec/std", - "scale-info/std", - "sp-std/std", - "sp-runtime/std", - "polimec-traits/std", -] diff --git a/runtime-api/staking/Cargo.toml b/runtime-api/staking/Cargo.toml deleted file mode 100644 index ff0109a09..000000000 --- a/runtime-api/staking/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -version = "0.1.0" -authors = ["KILT "] -edition = "2021" -repository = 'https://github.com/polimec/polimec-node' -name = "kilt-runtime-api-staking" -description = "Runtime APIs for dealing with parachain staking." - -[dependencies] -# External dependencies -parity-scale-codec = { workspace = true, features = [ - "derive", -] } -scale-info = { workspace = true, features = ["derive"] } - -# Substrate dependencies -sp-api.workspace = true -sp-runtime.workspace = true - - -[features] -default = ["std"] -std = ["parity-scale-codec/std", "sp-api/std", "sp-runtime/std", "scale-info/std"] diff --git a/runtime-api/staking/src/lib.rs b/runtime-api/staking/src/lib.rs deleted file mode 100644 index 197ee3502..000000000 --- a/runtime-api/staking/src/lib.rs +++ /dev/null @@ -1,46 +0,0 @@ -// KILT Blockchain – https://botlabs.org -// Copyright (C) 2019-2023 BOTLabs GmbH - -// The KILT Blockchain 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. - -// The KILT Blockchain 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 this program. If not, see . - -// If you feel like getting in touch with us, you can do so at info@botlabs.org - -#![cfg_attr(not(feature = "std"), no_std)] - -use parity_scale_codec::{Codec, Decode, Encode, MaxEncodedLen}; -use scale_info::TypeInfo; -use sp_runtime::Perquintill; - -#[derive(Decode, Encode, TypeInfo, MaxEncodedLen, PartialEq, Eq, Debug)] -pub struct StakingRates { - pub collator_staking_rate: Perquintill, - pub collator_reward_rate: Perquintill, - pub delegator_staking_rate: Perquintill, - pub delegator_reward_rate: Perquintill, -} - -sp_api::decl_runtime_apis! { - /// The API to query staking and reward rates. - pub trait Staking - where - AccountId: Codec, - Balance: Codec - { - /// Returns the current staking rewards for a given account address. - fn get_unclaimed_staking_rewards(account: &AccountId) -> Balance; - /// Returns the current staking and reward rates for collators and - /// delegators. - fn get_staking_rates() -> StakingRates; - } -} diff --git a/runtimes/base/Cargo.toml b/runtimes/base/Cargo.toml index 8f9a0d5d2..73809d8af 100644 --- a/runtimes/base/Cargo.toml +++ b/runtimes/base/Cargo.toml @@ -25,8 +25,6 @@ scale-info = { version = "2.3.1", default-features = false, features = [ smallvec = "1.10.0" # Local -runtime-common.workspace = true -parachain-staking.workspace = true # Substrate frame-benchmarking = { workspace = true, optional = true } @@ -82,7 +80,7 @@ polkadot-primitives.workspace = true [features] default = ["std"] -fast-gov = ["runtime-common/fast-gov"] +fast-gov = [] std = [ "polkadot-primitives/std", "frame-benchmarking?/std", @@ -110,7 +108,6 @@ std = [ "pallet-transaction-payment-rpc-runtime-api/std", "pallet-transaction-payment/std", "pallet-treasury/std", - "parachain-staking/std", "pallet-xcm/std", "parachain-info/std", "polkadot-parachain/std", @@ -129,7 +126,6 @@ std = [ "xcm-builder/std", "xcm-executor/std", "xcm/std", - "runtime-common/std", ] runtime-benchmarks = [ @@ -145,7 +141,6 @@ runtime-benchmarks = [ "xcm-builder/runtime-benchmarks", "cumulus-pallet-session-benchmarking/runtime-benchmarks", "cumulus-pallet-xcmp-queue/runtime-benchmarks", - "runtime-common/runtime-benchmarks", ] try-runtime = [ @@ -166,5 +161,4 @@ try-runtime = [ "pallet-transaction-payment/try-runtime", "pallet-xcm/try-runtime", "parachain-info/try-runtime", - "runtime-common/try-runtime", ] diff --git a/runtimes/base/src/currency.rs b/runtimes/base/src/currency.rs new file mode 100644 index 000000000..3d89c4f25 --- /dev/null +++ b/runtimes/base/src/currency.rs @@ -0,0 +1,14 @@ +use crate::Balance; + +/// One PLMC +pub const PLMC: Balance = 10u128.pow(10); +/// 0.001 PLMC +pub const MILLI_PLMC: Balance = 10u128.pow(7); +/// 0.000_001 PLMC +pub const MICRO_PLMC: Balance = 10u128.pow(4); + +pub const EXISTENTIAL_DEPOSIT: Balance = MILLI_PLMC; + +pub const fn deposit(items: u32, bytes: u32) -> Balance { + (items as Balance * 20 * PLMC + (bytes as Balance) * 100 * MICRO_PLMC) / 100 +} \ No newline at end of file diff --git a/runtimes/base/src/lib.rs b/runtimes/base/src/lib.rs index 6f2b46cf7..230849198 100644 --- a/runtimes/base/src/lib.rs +++ b/runtimes/base/src/lib.rs @@ -53,16 +53,15 @@ use sp_std::prelude::*; use sp_version::NativeVersion; use sp_version::RuntimeVersion; // XCM Imports -use xcm::latest::prelude::BodyId; -use xcm_executor::XcmExecutor; - -pub use runtime_common::constants::*; -use runtime_common::{ - fees::{ToAuthor, WeightToFee}, - FeeSplit, -}; +use parachains_common::AVERAGE_ON_INITIALIZE_RATIO; +use parachains_common::HOURS; +use parachains_common::MAXIMUM_BLOCK_WEIGHT; +use parachains_common::NORMAL_DISPATCH_RATIO; +use parachains_common::SLOT_DURATION; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; +use xcm::latest::prelude::BodyId; use xcm_config::{XcmConfig, XcmOriginToTransactDispatchOrigin}; +use xcm_executor::XcmExecutor; // Make the WASM binary available. #[cfg(feature = "std")] @@ -127,16 +126,123 @@ pub type CheckedExtrinsic = generic::CheckedExtrinsic, Runtime, AllPalletsWithSystem>; +pub mod fee { + use super::{currency::MICRO_PLMC, Balance, ExtrinsicBaseWeight}; + use frame_support::weights::{Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}; + use smallvec::smallvec; + use sp_arithmetic::traits::{BaseArithmetic, Unsigned}; + use sp_runtime::{Perbill, SaturatedConversion}; + + /// Handles converting a weight scalar to a fee value, based on the scale and granularity of the + /// node's balance type. + /// + /// This should typically create a mapping between the following ranges: + /// - `[0, MAXIMUM_BLOCK_WEIGHT]` + /// - `[Balance::min, Balance::max]` + /// + /// Yet, it can be used for any other sort of change to weight-fee. Some examples being: + /// - Setting it to `0` will essentially disable the weight fee. + /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. + pub struct WeightToFee; + impl frame_support::weights::WeightToFee for WeightToFee { + type Balance = Balance; + + fn weight_to_fee(weight: &Weight) -> Self::Balance { + let ref_time = Balance::saturated_from(weight.ref_time()); + let proof_size = Balance::saturated_from(weight.proof_size()); + + let ref_polynomial = RefTimeToFee::polynomial(); + let proof_polynomial = ProofSizeToFee::polynomial(); + + // Get fee amount from ref_time based on the RefTime polynomial + let ref_fee: Balance = ref_polynomial + .iter() + .fold(0, |acc, term| term.saturating_eval(acc, ref_time)); + + // Get fee amount from proof_size based on the ProofSize polynomial + let proof_fee: Balance = proof_polynomial + .iter() + .fold(0, |acc, term| term.saturating_eval(acc, proof_size)); + + // Take the maximum instead of the sum to charge by the more scarce resource. + ref_fee.max(proof_fee) + } + } + + /// Maps the Ref time component of `Weight` to a fee. + pub struct RefTimeToFee; + impl WeightToFeePolynomial for RefTimeToFee { + type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { + // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 MILLIUNIT: + // in our template, we map to 1/10 of that, or 1/10 MILLIUNIT + let p = MILLIUNIT / 10; + let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } + } + + /// Maps the proof size component of `Weight` to a fee. + pub struct ProofSizeToFee; + impl WeightToFeePolynomial for ProofSizeToFee { + type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { + // Map 10kb proof to 1 CENT. + let p = MILLIUNIT / 10; + let q = 10_000; + + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } + } + + // TODO: Refactor out this code to use `FeePolynomial` on versions using polkadot-v0.9.42 and above: + pub trait WeightCoefficientCalc { + fn saturating_eval(&self, result: Balance, x: Balance) -> Balance; + } + + impl WeightCoefficientCalc for WeightToFeeCoefficient + where + Balance: BaseArithmetic + From + Copy + Unsigned + SaturatedConversion, + { + fn saturating_eval(&self, mut result: Balance, x: Balance) -> Balance { + let power = x.saturating_pow(self.degree.into()); + + let frac = self.coeff_frac * power; // Overflow safe since coeff_frac is strictly less than 1. + let integer = self.coeff_integer.saturating_mul(power); + // Do not add them together here to avoid an underflow. + + if self.negative { + result = result.saturating_sub(frac); + result = result.saturating_sub(integer); + } else { + result = result.saturating_add(frac); + result = result.saturating_add(integer); + } + + result + } + } +} + /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know /// the specifics of the runtime. They can then be made to be agnostic over specific formats /// of data like extrinsics, allowing for them to continue syncing the network through upgrades /// to even the core data structures. pub mod opaque { - pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; - use sp_runtime::{generic, traits::BlakeTwo256}; - use super::*; + use sp_runtime::{generic, traits::BlakeTwo256}; + pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; /// Opaque block header type. pub type Header = generic::Header; /// Opaque block type. @@ -267,7 +373,7 @@ impl pallet_timestamp::Config for Runtime { impl pallet_authorship::Config for Runtime { type FindAuthor = pallet_session::FindAccountFromAuthorIndex; - type EventHandler = ParachainStaking; + type EventHandler = (); } parameter_types! { @@ -295,12 +401,11 @@ parameter_types! { impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = - pallet_transaction_payment::CurrencyAdapter>>; - type OperationalFeeMultiplier = runtime_common::constants::fee::OperationalFeeMultiplier; - type WeightToFee = WeightToFee; - type LengthToFee = ConstantMultiplier; + type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter>; + type WeightToFee = WeightToFee; + type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type OperationalFeeMultiplier = ConstU8<5>; } parameter_types! { @@ -351,9 +456,9 @@ impl pallet_session::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ValidatorId = AccountId; type ValidatorIdOf = ConvertInto; - type ShouldEndSession = ParachainStaking; - type NextSessionRotation = ParachainStaking; - type SessionManager = ParachainStaking; + type ShouldEndSession = (); + type NextSessionRotation = (); + type SessionManager = (); type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; // type WeightInfo = weights::pallet_session::WeightInfo; @@ -404,33 +509,6 @@ impl pallet_treasury::Config for Runtime { type MaxApprovals = MaxApprovals; } -impl parachain_staking::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Currency = Balances; - type CurrencyBalance = Balance; - - type MinBlocksPerRound = runtime_common::constants::staking::MinBlocksPerRound; - type DefaultBlocksPerRound = runtime_common::constants::staking::DefaultBlocksPerRound; - type StakeDuration = runtime_common::constants::staking::StakeDuration; - type ExitQueueDelay = runtime_common::constants::staking::ExitQueueDelay; - type MinCollators = runtime_common::constants::staking::MinCollators; - type MinRequiredCollators = runtime_common::constants::staking::MinRequiredCollators; - type MaxDelegationsPerRound = runtime_common::constants::staking::MaxDelegationsPerRound; - type MaxDelegatorsPerCollator = runtime_common::constants::staking::MaxDelegatorsPerCollator; - type MinCollatorStake = runtime_common::constants::staking::MinCollatorStake; - type MinCollatorCandidateStake = runtime_common::constants::staking::MinCollatorStake; - type MaxTopCandidates = runtime_common::constants::staking::MaxCollatorCandidates; - type MinDelegatorStake = runtime_common::constants::staking::MinDelegatorStake; - type MaxUnstakeRequests = runtime_common::constants::staking::MaxUnstakeRequests; - type NetworkRewardRate = runtime_common::constants::staking::NetworkRewardRate; - type NetworkRewardStart = runtime_common::constants::staking::NetworkRewardStart; - type NetworkRewardBeneficiary = Treasury; - // type WeightInfo = weights::parachain_staking::WeightInfo; - type WeightInfo = (); - - const BLOCKS_PER_YEAR: Self::BlockNumber = runtime_common::constants::BLOCKS_PER_YEAR; -} - impl pallet_sudo::Config for Runtime { type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; @@ -460,7 +538,6 @@ construct_runtime!( // Dependencies: AuraExt on Aura, Authorship and Session on ParachainStaking Aura: pallet_aura = 23, Session: pallet_session = 22, - ParachainStaking: parachain_staking = 21, Authorship: pallet_authorship = 20, AuraExt: cumulus_pallet_aura_ext = 24, @@ -686,7 +763,8 @@ struct CheckInherents; impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { fn check_inherents( - block: &Block, relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, + block: &Block, + relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, ) -> sp_inherents::CheckInherentsResult { let relay_chain_slot = relay_state_proof .read_slot() diff --git a/runtimes/common/Cargo.toml b/runtimes/common/Cargo.toml deleted file mode 100644 index f4ae2a40e..000000000 --- a/runtimes/common/Cargo.toml +++ /dev/null @@ -1,90 +0,0 @@ -[package] -authors.workspace = true -documentation.workspace = true -edition.workspace = true -homepage.workspace = true -license-file.workspace = true -readme.workspace = true -repository.workspace = true -version.workspace = true -name = "runtime-common" -description = "Common interfaces, types, constants and functionality for all Polimec runtimes." - -[dev-dependencies] -sp-io = { workspace = true, features = ["std"] } - -[dependencies] -# External dependencies -parity-scale-codec = { workspace = true, features = [ - "derive", -] } -log.workspace = true -scale-info = { workspace = true, features = ["derive"] } -smallvec.workspace = true - -# Internal dependencies -parachain-staking.workspace = true -did.workspace = true -dip-support.workspace = true -pallet-did-lookup = { workspace = true, optional = true } -pallet-dip-consumer.workspace = true -pallet-dip-provider.workspace = true - -# Substrate dependencies -frame-support.workspace = true -frame-system.workspace = true -pallet-authorship.workspace = true -pallet-balances.workspace = true -pallet-transaction-payment.workspace = true -sp-consensus-aura.workspace = true -sp-core.workspace = true -sp-io.workspace = true -sp-trie.workspace = true -sp-runtime.workspace = true -sp-std.workspace = true -pallet-membership.workspace = true - -# Cumulus dependencies -cumulus-primitives-core.workspace = true - -# Polkadot dependencies -polkadot-parachain.workspace = true -xcm.workspace = true -xcm-builder.workspace = true -xcm-executor.workspace = true -parachains-common.workspace = true - -[features] -default = ["std"] -fast-gov = [] -runtime-benchmarks = [ - "frame-support/runtime-benchmarks", - "parachain-staking/runtime-benchmarks", - "polkadot-parachain/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", - "xcm-builder/runtime-benchmarks", -] -std = [ - "parity-scale-codec/std", - "frame-support/std", - "frame-system/std", - "cumulus-primitives-core/std", - "pallet-authorship/std", - "pallet-balances/std", - "pallet-transaction-payment/std", - "pallet-membership/std", - "parachain-staking/std", - "polkadot-parachain/std", - "scale-info/std", - "sp-consensus-aura/std", - "sp-core/std", - "sp-io/std", - "sp-runtime/std", - "sp-std/std", - "xcm-builder/std", - "xcm-executor/std", - "xcm/std", - "parachains-common/std", - "dip-support/std", -] -try-runtime = ["frame-support/try-runtime"] diff --git a/runtimes/common/src/constants.rs b/runtimes/common/src/constants.rs deleted file mode 100644 index 72e961558..000000000 --- a/runtimes/common/src/constants.rs +++ /dev/null @@ -1,358 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -use frame_support::{ - parameter_types, - traits::WithdrawReasons, - weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}, -}; -use sp_runtime::{Perbill, Percent, Perquintill}; - -pub use parachain_staking::InflationInfo; - -use crate::{Balance, BlockNumber}; - -/// This determines the average expected block time that we are targetting. -/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`. -/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked -/// up by `pallet_aura` to implement `fn slot_duration()`. -/// -/// Change this to adjust the block time. -pub const MILLISECS_PER_BLOCK: u64 = 12_000; - -pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; - -// Time is measured by number of blocks. -pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); -pub const HOURS: BlockNumber = MINUTES * 60; -pub const DAYS: BlockNumber = HOURS * 24; -// Julian year as Substrate handles it -pub const BLOCKS_PER_YEAR: BlockNumber = DAYS * 36525 / 100; - -pub const MAX_COLLATOR_STAKE: Balance = 200_000 * PLMC; - -/// One PLMC -pub const PLMC: Balance = 10u128.pow(10); - -/// 0.001 PLMC -pub const MILLI_PLMC: Balance = 10u128.pow(7); - -/// 0.000_001 PLMC -pub const MICRO_PLMC: Balance = 10u128.pow(4); - -pub const EXISTENTIAL_DEPOSIT: Balance = 10 * MILLI_PLMC; - -// 1 in 4 blocks (on average, not counting collisions) will be primary babe -// blocks. -pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4); - -/// We assume that ~10% of the block weight is consumed by `on_initalize` -/// handlers. This is used to limit the maximal weight of a single extrinsic. -pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); -/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be -/// used by Operational extrinsics. -pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); -/// We allow for 0.5 of a second of compute with a 12 second average block time. -pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_ref_time(WEIGHT_REF_TIME_PER_SECOND) - .saturating_div(2) - .set_proof_size(cumulus_primitives_core::relay_chain::MAX_POV_SIZE as u64); - -pub const INFLATION_CONFIG: (Perquintill, Perquintill, Perquintill, Perquintill) = ( - // max collator staking rate - Perquintill::from_percent(40), - // collator reward rate - Perquintill::from_percent(10), - // max delegator staking rate - Perquintill::from_percent(10), - // delegator reward rate - Perquintill::from_percent(8), -); - -/// Inflation configuration which is used at genesis -pub fn polimec_inflation_config() -> InflationInfo { - InflationInfo::new( - BLOCKS_PER_YEAR.into(), - // max collator staking rate - Perquintill::from_percent(40), - // collator reward rate - Perquintill::from_percent(10), - // max delegator staking rate - Perquintill::from_percent(10), - // delegator reward rate - Perquintill::from_percent(8), - ) -} - -/// Calculate the storage deposit based on the number of storage items and the -/// combined byte size of those items. -pub const fn deposit(items: u32, bytes: u32) -> Balance { - items as Balance * 56 * MILLI_PLMC + (bytes as Balance) * 50 * MICRO_PLMC -} - -/// The size of an index in the index pallet. -/// The size is checked in the runtime by a test. -pub const MAX_INDICES_BYTE_LENGTH: u32 = 49; - -/// Copied from Kusama & Polkadot runtime -pub const MAX_VESTING_SCHEDULES: u32 = 28; - -parameter_types! { - /// Vesting Pallet. Copied from Kusama & Polkadot runtime - pub const MinVestedTransfer: Balance = 100 * MILLI_PLMC; - /// Deposits per byte - pub const ByteDeposit: Balance = deposit(0, 1); - /// Index Pallet. Deposit taken for an account index - pub const IndicesDeposit: Balance = deposit(1, MAX_INDICES_BYTE_LENGTH); - /// CType Pallet. Per byte fee for a ctype. - pub const CtypeFee: Balance = MILLI_PLMC; - pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons = - WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); -} - -pub mod delegation { - use super::*; - - pub const DELEGATION_DEPOSIT: Balance = PLMC; - pub const MAX_SIGNATURE_BYTE_LENGTH: u16 = 64; - pub const MAX_PARENT_CHECKS: u32 = 5; - pub const MAX_REVOCATIONS: u32 = 5; - pub const MAX_REMOVALS: u32 = MAX_REVOCATIONS; - pub const MAX_CHILDREN: u32 = 1000; - - parameter_types! { - pub const MaxSignatureByteLength: u16 = MAX_SIGNATURE_BYTE_LENGTH; - pub const MaxParentChecks: u32 = MAX_PARENT_CHECKS; - pub const MaxRevocations: u32 = MAX_REVOCATIONS; - pub const MaxRemovals: u32 = MAX_REMOVALS; - #[derive(Clone)] - pub const MaxChildren: u32 = MAX_CHILDREN; - pub const DelegationDeposit: Balance = DELEGATION_DEPOSIT; - } -} - -pub mod staking { - use super::*; - - /// Minimum round length is 1 hour (300 * 12 second block times) - #[cfg(feature = "fast-gov")] - pub const MIN_BLOCKS_PER_ROUND: BlockNumber = 10; - #[cfg(not(feature = "fast-gov"))] - pub const MIN_BLOCKS_PER_ROUND: BlockNumber = HOURS; - - #[cfg(feature = "fast-gov")] - pub const DEFAULT_BLOCKS_PER_ROUND: BlockNumber = 20; - #[cfg(not(feature = "fast-gov"))] - pub const DEFAULT_BLOCKS_PER_ROUND: BlockNumber = 2 * HOURS; - - #[cfg(feature = "fast-gov")] - pub const STAKE_DURATION: BlockNumber = 30; - #[cfg(not(feature = "fast-gov"))] - pub const STAKE_DURATION: BlockNumber = 7 * DAYS; - - #[cfg(feature = "fast-gov")] - pub const MIN_COLLATORS: u32 = 4; - #[cfg(not(feature = "fast-gov"))] - pub const MIN_COLLATORS: u32 = 16; - - #[cfg(feature = "fast-gov")] - pub const MAX_CANDIDATES: u32 = 16; - #[cfg(not(feature = "fast-gov"))] - pub const MAX_CANDIDATES: u32 = 75; - - pub const MAX_DELEGATORS_PER_COLLATOR: u32 = 35; - pub const MIN_DELEGATOR_STAKE: Balance = 20 * PLMC; - - pub const NETWORK_REWARD_RATE: Perquintill = Perquintill::from_percent(10); - - parameter_types! { - /// Minimum round length is 1 hour - pub const MinBlocksPerRound: BlockNumber = MIN_BLOCKS_PER_ROUND; - /// Default length of a round/session is 2 hours - pub const DefaultBlocksPerRound: BlockNumber = DEFAULT_BLOCKS_PER_ROUND; - /// Unstaked balance can be unlocked after 7 days - pub const StakeDuration: BlockNumber = STAKE_DURATION; - /// Collator exit requests are delayed by 4 hours (2 rounds/sessions) - pub const ExitQueueDelay: u32 = 2; - /// Minimum 16 collators selected per round, default at genesis and minimum forever after - pub const MinCollators: u32 = MIN_COLLATORS; - /// At least 4 candidates which cannot leave the network if there are no other candidates. - pub const MinRequiredCollators: u32 = 4; - /// We only allow one delegation per round. - pub const MaxDelegationsPerRound: u32 = 1; - /// Maximum 25 delegators per collator at launch, might be increased later - #[derive(Debug, Eq, PartialEq)] - pub const MaxDelegatorsPerCollator: u32 = MAX_DELEGATORS_PER_COLLATOR; - /// Minimum stake required to be reserved to be a collator is 10_000 - pub const MinCollatorStake: Balance = 10_000 * PLMC; - /// Minimum stake required to be reserved to be a delegator is 1000 - pub const MinDelegatorStake: Balance = MIN_DELEGATOR_STAKE; - /// Maximum number of collator candidates - #[derive(Debug, Eq, PartialEq)] - pub const MaxCollatorCandidates: u32 = MAX_CANDIDATES; - /// Maximum number of concurrent requests to unlock unstaked balance - pub const MaxUnstakeRequests: u32 = 10; - /// The starting block number for the network rewards - pub const NetworkRewardStart: BlockNumber = super::treasury::INITIAL_PERIOD_LENGTH; - /// The rate in percent for the network rewards - pub const NetworkRewardRate: Perquintill = NETWORK_REWARD_RATE; - } -} - -pub mod governance { - use super::*; - - pub const MIN_DEPOSIT: Balance = PLMC; - - #[cfg(feature = "fast-gov")] - pub const LAUNCH_PERIOD: BlockNumber = 7 * MINUTES; - #[cfg(not(feature = "fast-gov"))] - pub const LAUNCH_PERIOD: BlockNumber = 7 * DAYS; - - #[cfg(feature = "fast-gov")] - pub const VOTING_PERIOD: BlockNumber = 7 * MINUTES; - #[cfg(not(feature = "fast-gov"))] - pub const VOTING_PERIOD: BlockNumber = 7 * DAYS; - - #[cfg(feature = "fast-gov")] - pub const FAST_TRACK_VOTING_PERIOD: BlockNumber = 3 * MINUTES; - #[cfg(not(feature = "fast-gov"))] - pub const FAST_TRACK_VOTING_PERIOD: BlockNumber = 3 * HOURS; - - #[cfg(feature = "fast-gov")] - pub const ENACTMENT_PERIOD: BlockNumber = 8 * MINUTES; - #[cfg(not(feature = "fast-gov"))] - pub const ENACTMENT_PERIOD: BlockNumber = DAYS; - - #[cfg(feature = "fast-gov")] - pub const COOLOFF_PERIOD: BlockNumber = 7 * MINUTES; - #[cfg(not(feature = "fast-gov"))] - pub const COOLOFF_PERIOD: BlockNumber = 7 * DAYS; - - #[cfg(feature = "fast-gov")] - pub const SPEND_PERIOD: BlockNumber = 6 * MINUTES; - #[cfg(not(feature = "fast-gov"))] - pub const SPEND_PERIOD: BlockNumber = 6 * DAYS; - - #[cfg(feature = "fast-gov")] - pub const ROTATION_PERIOD: BlockNumber = 80 * MINUTES; - #[cfg(not(feature = "fast-gov"))] - pub const ROTATION_PERIOD: BlockNumber = 80 * HOURS; - - #[cfg(feature = "fast-gov")] - pub const TERM_DURATION: BlockNumber = 15 * MINUTES; - #[cfg(not(feature = "fast-gov"))] - pub const TERM_DURATION: BlockNumber = DAYS; - - #[cfg(feature = "fast-gov")] - pub const COUNCIL_MOTION_DURATION: BlockNumber = 4 * MINUTES; - #[cfg(not(feature = "fast-gov"))] - pub const COUNCIL_MOTION_DURATION: BlockNumber = 3 * DAYS; - - #[cfg(feature = "fast-gov")] - pub const TECHNICAL_MOTION_DURATION: BlockNumber = 4 * MINUTES; - #[cfg(not(feature = "fast-gov"))] - pub const TECHNICAL_MOTION_DURATION: BlockNumber = 3 * DAYS; - - parameter_types! { - // Democracy Pallet - pub const LaunchPeriod: BlockNumber = LAUNCH_PERIOD; - pub const VotingPeriod: BlockNumber = VOTING_PERIOD; - pub const FastTrackVotingPeriod: BlockNumber = FAST_TRACK_VOTING_PERIOD; - pub const MinimumDeposit: Balance = MIN_DEPOSIT; - pub const EnactmentPeriod: BlockNumber = ENACTMENT_PERIOD; - pub const CooloffPeriod: BlockNumber = COOLOFF_PERIOD; - pub const MaxProposals: u32 = 100; - // Council Pallet - pub const CouncilMotionDuration: BlockNumber = COUNCIL_MOTION_DURATION; - pub const CouncilMaxProposals: u32 = 100; - pub const CouncilMaxMembers: u32 = 100; - // Technical Committee - pub const TechnicalMotionDuration: BlockNumber = TECHNICAL_MOTION_DURATION; - pub const TechnicalMaxProposals: u32 = 100; - pub const TechnicalMaxMembers: u32 = 100; - } -} - -pub mod treasury { - use super::*; - - pub const INITIAL_PERIOD_LENGTH: BlockNumber = BLOCKS_PER_YEAR.saturating_mul(5); - const YEARLY_REWARD: Balance = 2_000_000u128 * PLMC; - pub const INITIAL_PERIOD_REWARD_PER_BLOCK: Balance = YEARLY_REWARD / (BLOCKS_PER_YEAR as Balance); - - parameter_types! { - pub const InitialPeriodLength: BlockNumber = INITIAL_PERIOD_LENGTH; - pub const InitialPeriodReward: Balance = INITIAL_PERIOD_REWARD_PER_BLOCK; - } -} - -pub mod proxy { - use super::*; - - parameter_types! { - // One storage item; key size 32, value size 8; . - pub const ProxyDepositBase: Balance = deposit(1, 8); - // Additional storage item size of 33 bytes. - pub const ProxyDepositFactor: Balance = deposit(0, 33); - pub const MaxProxies: u16 = 10; - pub const AnnouncementDepositBase: Balance = deposit(1, 8); - pub const AnnouncementDepositFactor: Balance = deposit(0, 66); - pub const MaxPending: u16 = 10; - } -} - -pub mod preimage { - use super::*; - - parameter_types! { - pub const PreimageMaxSize: u32 = 4096 * 1024; - pub const PreimageBaseDeposit: Balance = deposit(2, 64); - } -} - -pub mod tips { - use super::*; - - parameter_types! { - pub const MaximumReasonLength: u32 = 16384; - pub const TipCountdown: BlockNumber = DAYS; - pub const TipFindersFee: Percent = Percent::from_percent(20); - pub const TipReportDepositBase: Balance = deposit(1, 1); - } -} - -pub mod fee { - use super::*; - - parameter_types! { - /// This value increases the priority of `Operational` transactions by adding - /// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`. - pub const OperationalFeeMultiplier: u8 = 5; - pub const TransactionByteFee: Balance = MICRO_PLMC; - } -} - -#[cfg(test)] -mod tests { - use super::*; - - // TODO: static assert - #[allow(clippy::assertions_on_constants)] - #[test] - fn blocks_per_year_saturation() { - assert!(BLOCKS_PER_YEAR < u32::MAX); - } -} diff --git a/runtimes/common/src/fees.rs b/runtimes/common/src/fees.rs deleted file mode 100644 index 88f5ebefb..000000000 --- a/runtimes/common/src/fees.rs +++ /dev/null @@ -1,279 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -use frame_support::{ - dispatch::DispatchClass, - traits::{Currency, Get, Imbalance, OnUnbalanced}, - weights::{ - Weight, WeightToFee as WeightToFeeT, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, - }, -}; -use pallet_balances::WeightInfo; -use pallet_transaction_payment::OnChargeTransaction; -use smallvec::smallvec; -use sp_runtime::Perbill; - -use crate::{constants::MILLI_PLMC, AccountId, Balance, NegativeImbalanceOf}; - -/// Split two Imbalances between two unbalanced handlers. -/// The first Imbalance will be split according to the given ratio. The second -/// Imbalance will be handled by the second beneficiary. -/// -/// In case of transaction payment, the first Imbalance is the fee and the -/// second imbalance the tip. -pub struct SplitFeesByRatio( - sp_std::marker::PhantomData<(R, Ratio, Beneficiary1, Beneficiary2)>, -); -impl OnUnbalanced> - for SplitFeesByRatio -where - R: pallet_balances::Config, - Beneficiary1: OnUnbalanced>, - Beneficiary2: OnUnbalanced>, - Ratio: Get<(u32, u32)>, -{ - fn on_unbalanceds(mut fees_then_tips: impl Iterator>) { - let ratio = Ratio::get(); - if let Some(fees) = fees_then_tips.next() { - let mut split = fees.ration(ratio.0, ratio.1); - if let Some(tips) = fees_then_tips.next() { - // for tips, if any, 100% to author - tips.merge_into(&mut split.1); - } - Beneficiary1::on_unbalanced(split.0); - Beneficiary2::on_unbalanced(split.1); - } - } -} - -/// Logic for the author to get a portion of fees. -pub struct ToAuthor(sp_std::marker::PhantomData); - -impl OnUnbalanced> for ToAuthor -where - R: pallet_balances::Config + pallet_authorship::Config, - ::AccountId: From, - ::AccountId: Into, - ::Balance: Into, -{ - fn on_nonzero_unbalanced(amount: NegativeImbalanceOf) { - if let Some(author) = >::author() { - >::resolve_creating(&author, amount); - } - } -} - -/// Handles converting a weight scalar to a fee value, based on the scale and -/// granularity of the node's balance type. -/// -/// This should typically create a mapping between the following ranges: -/// - [0, MAXIMUM_BLOCK_WEIGHT] -/// - [Balance::min, Balance::max] -/// -/// Yet, it can be used for any other sort of change to weight-fee. Some -/// examples being: -/// - Setting it to `0` will essentially disable the weight fee. -/// - Setting it to `1` will cause the literal `#[weight = x]` values to be -/// charged. -pub struct WeightToFee(sp_std::marker::PhantomData); -impl WeightToFeePolynomial for WeightToFee -where - R: pallet_transaction_payment::Config, - R: frame_system::Config, - R: pallet_balances::Config, - u128: From<<::OnChargeTransaction as OnChargeTransaction>::Balance>, -{ - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - // The should be fee - let wanted_fee: Balance = 10 * MILLI_PLMC; - - // TODO: transfer_keep_alive is 288 byte long? - let tx_len: u64 = 288; - let byte_fee: Balance = - ::LengthToFee::weight_to_fee(&Weight::from_ref_time(tx_len)) - .into(); - let base_weight: Weight = ::BlockWeights::get() - .get(DispatchClass::Normal) - .base_extrinsic; - let base_weight_fee: Balance = - ::LengthToFee::weight_to_fee(&base_weight).into(); - let tx_weight_fee: Balance = ::LengthToFee::weight_to_fee( - &::WeightInfo::transfer_keep_alive(), - ) - .into(); - let unbalanced_fee: Balance = base_weight_fee.saturating_add(tx_weight_fee); - - let wanted_weight_fee: Balance = wanted_fee.saturating_sub(byte_fee); - - smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(wanted_weight_fee % unbalanced_fee, unbalanced_fee), - coeff_integer: wanted_weight_fee / unbalanced_fee, - }] - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{ - AccountId, BlockExecutionWeight, ExtrinsicBaseWeight, AVERAGE_ON_INITIALIZE_RATIO, MAXIMUM_BLOCK_WEIGHT, - NORMAL_DISPATCH_RATIO, - }; - use frame_support::{dispatch::DispatchClass, parameter_types, traits::FindAuthor}; - use frame_system::limits; - use sp_core::H256; - use sp_runtime::{ - testing::Header, - traits::{BlakeTwo256, IdentityLookup}, - Perbill, - }; - - type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; - type Block = frame_system::mocking::MockBlock; - - frame_support::construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Authorship: pallet_authorship::{Pallet, Storage}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - } - ); - - parameter_types! { - pub const BlockHashCount: u64 = 250; - // One to one clone of our runtimes' blockweight - pub BlockWeights: limits::BlockWeights = limits::BlockWeights::builder() - .base_block(BlockExecutionWeight::get()) - .for_class(DispatchClass::all(), |weights| { - weights.base_extrinsic = ExtrinsicBaseWeight::get(); - }) - .for_class(DispatchClass::Normal, |weights| { - weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); - }) - .for_class(DispatchClass::Operational, |weights| { - weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); - // Operational transactions have some extra reserved space, so that they - // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. - weights.reserved = Some( - MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT - ); - }) - .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) - .build_or_panic(); - pub BlockLength: limits::BlockLength = limits::BlockLength::max(2 * 1024); - pub const AvailableBlockRatio: Perbill = Perbill::one(); - } - - impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type RuntimeOrigin = RuntimeOrigin; - type Index = u64; - type BlockNumber = u64; - type RuntimeCall = RuntimeCall; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Header = Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type BlockLength = BlockLength; - type BlockWeights = BlockWeights; - type DbWeight = (); - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; - } - - impl pallet_balances::Config for Test { - type Balance = u64; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = (); - type AccountStore = System; - type MaxLocks = (); - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; - type WeightInfo = (); - } - - pub const TREASURY_ACC: AccountId = crate::AccountId::new([1u8; 32]); - const AUTHOR_ACC: AccountId = AccountId::new([2; 32]); - - pub struct ToBeneficiary(); - impl OnUnbalanced> for ToBeneficiary { - fn on_nonzero_unbalanced(amount: NegativeImbalanceOf) { - // Must resolve into existing but better to be safe. - >::resolve_creating(&TREASURY_ACC, amount); - } - } - - pub struct OneAuthor; - impl FindAuthor for OneAuthor { - fn find_author<'a, I>(_: I) -> Option - where - I: 'a, - { - Some(AUTHOR_ACC) - } - } - impl pallet_authorship::Config for Test { - type FindAuthor = OneAuthor; - type EventHandler = (); - } - - pub fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - // We use default for brevity, but you can configure as desired if needed. - pallet_balances::GenesisConfig::::default() - .assimilate_storage(&mut t) - .unwrap(); - t.into() - } - - parameter_types! { - pub const Ratio: (u32, u32) = (50, 50); - } - - #[test] - fn test_fees_and_tip_split() { - new_test_ext().execute_with(|| { - let fee = Balances::issue(10); - let tip = Balances::issue(20); - - assert_eq!(Balances::free_balance(TREASURY_ACC), 0); - assert_eq!(Balances::free_balance(AUTHOR_ACC), 0); - - SplitFeesByRatio::>::on_unbalanceds(vec![fee, tip].into_iter()); - - assert_eq!(Balances::free_balance(TREASURY_ACC), 5); - assert_eq!(Balances::free_balance(AUTHOR_ACC), 25); - }); - } -} diff --git a/runtimes/common/src/lib.rs b/runtimes/common/src/lib.rs deleted file mode 100644 index 7a2d83e10..000000000 --- a/runtimes/common/src/lib.rs +++ /dev/null @@ -1,184 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -#![cfg_attr(not(feature = "std"), no_std)] - -use constants::{AVERAGE_ON_INITIALIZE_RATIO, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO}; -use fees::SplitFeesByRatio; - -pub use sp_consensus_aura::sr25519::AuthorityId; - -pub use opaque::*; - -pub use frame_support::weights::constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; -use frame_support::{ - dispatch::DispatchClass, - parameter_types, - traits::{Contains, ContainsLengthBound, Currency, Get, SortedMembers}, -}; -use frame_system::limits; -use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment}; -use parachains_common::{Balance, BlockNumber}; -use sp_runtime::{ - generic, - traits::{Bounded, IdentifyAccount, Verify}, - FixedPointNumber, MultiSignature, Perquintill, SaturatedConversion, -}; -use sp_std::marker::PhantomData; - -pub mod constants; -pub mod fees; -pub mod xcm_config; - -/// Opaque types. These are used by the CLI to instantiate machinery that don't -/// need to know the specifics of the runtime. They can then be made to be -/// agnostic over specific formats of data like extrinsics, allowing for them to -/// continue syncing the network through upgrades to even the core data -/// structures. -pub mod opaque { - use super::*; - use sp_runtime::{generic, traits::BlakeTwo256}; - - pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; - /// Opaque block header type. - pub type Header = generic::Header; - /// Opaque block type. - pub type Block = generic::Block; - /// Opaque block identifier type. - pub type BlockId = generic::BlockId; -} - -/// Alias to 512-bit hash when used in the context of a transaction signature on -/// the chain. -pub type Signature = MultiSignature; - -/// Alias to the public key used for this chain, actually a `MultiSigner`. Like -/// the signature, this also isn't a fixed size when encoded, as different -/// cryptos have different size public keys. -pub type AccountPublic = ::Signer; - -/// Alias to the opaque account ID type for this chain, actually a -/// `AccountId32`. This is always 32 bytes. -pub type AccountId = ::AccountId; - -/// The type for looking up accounts. We don't expect more than 4 billion of -/// them, but you never know... -pub type AccountIndex = u32; - -/// Identifier for a chain. 32-bit should be plenty. -pub type ChainId = u32; - -pub type Amount = i128; - -/// Index of a transaction in the chain. -pub type Index = u64; - -/// A hash of some data used by the chain. -pub type Hash = sp_core::H256; - -/// Digest item type. -pub type DigestItem = generic::DigestItem; - -/// A Kilt DID subject identifier. -pub type DidIdentifier = AccountId; - -pub type NegativeImbalanceOf = - as Currency<::AccountId>>::NegativeImbalance; - -// Common constants used in all runtimes. -parameter_types! { - pub const BlockHashCount: BlockNumber = 2400; - /// The portion of the `NORMAL_DISPATCH_RATIO` that we adjust the fees with. Blocks filled less - /// than this will decrease the weight and more will increase. - pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); - /// The adjustment variable of the runtime. Higher values will cause `TargetBlockFullness` to - /// change the fees more rapidly. - pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(3, 100_000); - /// Minimum amount of the multiplier. This value cannot be too low. A test case should ensure - /// that combined with `AdjustmentVariable`, we can recover from the minimum. - /// See `multiplier_can_grow_from_zero`. - pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000u128); - /// The maximum amount of the multiplier. - pub MaximumMultiplier: Multiplier = Bounded::max_value(); - /// Maximum length of block. Up to 5MB. - pub RuntimeBlockLength: limits::BlockLength = - limits::BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); - /// Block weights base values and limits. - pub RuntimeBlockWeights: limits::BlockWeights = limits::BlockWeights::builder() - .base_block(BlockExecutionWeight::get()) - .for_class(DispatchClass::all(), |weights| { - weights.base_extrinsic = ExtrinsicBaseWeight::get(); - }) - .for_class(DispatchClass::Normal, |weights| { - weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); - }) - .for_class(DispatchClass::Operational, |weights| { - weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); - // Operational transactions have some extra reserved space, so that they - // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. - weights.reserved = Some( - MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT, - ); - }) - .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) - .build_or_panic(); - - /// Fee split ratio between treasury and block author (order is important). - pub const FeeSplitRatio: (u32, u32) = (50, 50); -} - -/// Split the fees using a preconfigured Ratio -/// (`runtime_common::FeeSplitRatio`). -pub type FeeSplit = SplitFeesByRatio; - -/// Parameterized slow adjusting fee updated based on -/// https://w3f-research.readthedocs.io/en/latest/polkadot/Token%20Economics.html#-2.-slow-adjusting-mechanism -pub type SlowAdjustingFeeUpdate = - TargetedFeeAdjustment; - -pub struct Tippers(PhantomData, PhantomData); -impl ContainsLengthBound for Tippers -where - R: pallet_membership::Config, -{ - fn max_len() -> usize { - >::MaxMembers::get().saturated_into() - } - - fn min_len() -> usize { - 0 - } -} - -impl SortedMembers for Tippers -where - R: pallet_membership::Config, - pallet_membership::Pallet: SortedMembers + Contains, -{ - fn sorted_members() -> sp_std::vec::Vec { - pallet_membership::Pallet::::sorted_members() - } - - #[cfg(feature = "runtime-benchmarks")] - fn add(who: &R::AccountId) { - pallet_membership::Members::::mutate(|members| match members.binary_search_by(|m| m.cmp(who)) { - Ok(_) => (), - Err(pos) => members - .try_insert(pos, who.clone()) - .expect("Should not fail to add members"), - }) - } -} diff --git a/runtimes/common/src/xcm_config.rs b/runtimes/common/src/xcm_config.rs deleted file mode 100644 index f685ddc7d..000000000 --- a/runtimes/common/src/xcm_config.rs +++ /dev/null @@ -1,160 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -use core::marker::PhantomData; - -use frame_support::{log, match_types, parameter_types}; -use polkadot_parachain::primitives::Sibling; -use xcm::{latest::prelude::*, v3::Weight}; -use xcm_builder::{ - AccountId32Aliases, AllowUnpaidExecutionFrom, CurrencyAdapter, IsConcrete, ParentIsPreset, - SiblingParachainConvertsVia, -}; -use xcm_executor::traits::ShouldExecute; - -use crate::AccountId; - -parameter_types! { - // One XCM operation is 1_000_000_000 weight, almost certainly a conservative estimate. - pub UnitWeightCost: u64 = 1_000_000_000; - pub const MaxInstructions: u32 = 100; -} - -match_types! { - // The legislative of our parent (i.e. Polkadot majority vote for Spiritnet). - pub type ParentLegislative: impl Contains = { - MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Legislative, .. }) } - }; -} - -// Note: This might move to polkadot's xcm module. -/// Deny executing the xcm message if it matches any of the Deny filter -/// regardless of anything else. If it passes the Deny and matches one of the -/// Allow cases, then it is let through. -pub struct DenyThenTry(PhantomData<(Deny, Allow)>); - -impl ShouldExecute for DenyThenTry -where - Deny: ShouldExecute, - Allow: ShouldExecute, -{ - fn should_execute( - origin: &MultiLocation, message: &mut [Instruction], max_weight: Weight, weight_credit: &mut Weight, - ) -> Result<(), ()> { - Deny::should_execute(origin, message, max_weight, weight_credit)?; - Allow::should_execute(origin, message, max_weight, weight_credit) - } -} - -/// Explicitly deny ReserveTransfer to the relay chain. Allow calls from the -/// relay chain governance. -pub type XcmBarrier = DenyThenTry< - DenyReserveTransferToRelayChain, - ( - // We don't allow anything from any sibling chain, therefore the following is not included here: - // * TakeWeightCredit - // * AllowTopLevelPaidExecutionFrom - - // We allow everything from the relay chain if it was sent by the relay chain legislative (i.e., democracy - // vote). Since the relaychain doesn't own KILTs and missing fees shouldn't prevent calls from the relaychain - // legislative, we allow unpaid execution. - AllowUnpaidExecutionFrom, - ), ->; - -/// Reserved funds to the relay chain can't return. See https://github.com/paritytech/polkadot/issues/5233 -pub struct DenyReserveTransferToRelayChain; -impl ShouldExecute for DenyReserveTransferToRelayChain { - fn should_execute( - origin: &MultiLocation, message: &mut [Instruction], _max_weight: Weight, _weight_credit: &mut Weight, - ) -> Result<(), ()> { - if message.iter().any(|inst| { - matches!( - inst, - InitiateReserveWithdraw { - reserve: MultiLocation { - parents: 1, - interior: Here - }, - .. - } | DepositReserveAsset { - dest: MultiLocation { - parents: 1, - interior: Here - }, - .. - } | TransferReserveAsset { - dest: MultiLocation { - parents: 1, - interior: Here - }, - .. - } - ) - }) { - return Err(()); // Deny - } - - // Allow reserve transfers to arrive from relay chain - if matches!( - origin, - MultiLocation { - parents: 1, - interior: Here - } - ) && message.iter().any(|inst| matches!(inst, ReserveAssetDeposited { .. })) - { - log::warn!( - target: "xcm::barriers", - "Unexpected ReserveAssetDeposited from the relay chain", - ); - } - // Permit everything else - Ok(()) - } -} - -parameter_types! { - pub const RelayLocation: MultiLocation = MultiLocation::parent(); - pub const HereLocation: MultiLocation = MultiLocation::here(); -} - -/// Type for specifying how a `MultiLocation` can be converted into an -/// `AccountId`. This is used when determining ownership of accounts for asset -/// transacting and when attempting to use XCM `Transact` in order to determine -/// the dispatch Origin. -pub type LocationToAccountId = ( - // The parent (Relay-chain) origin converts to the b"parent" `AccountId`. - ParentIsPreset, - // Sibling parachain origins convert to AccountId via the `ParaId::into`. - SiblingParachainConvertsVia, - // Straight up local `AccountId32` origins just alias directly to `AccountId`. - AccountId32Aliases, -); - -/// Means for transacting assets on this chain. -pub type LocalAssetTransactor = CurrencyAdapter< - // Use this currency: - Currency, - // Use this currency when it is a fungible asset matching the given location or name: - IsConcrete, - // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID: - LocationToAccountId, - // Our chain's account ID type (we can't get away without mentioning it explicitly): - AccountId, - // We don't track any teleports. - (), ->; diff --git a/runtimes/standalone/Cargo.toml b/runtimes/standalone/Cargo.toml index fc036bdc1..d2b067ff1 100644 --- a/runtimes/standalone/Cargo.toml +++ b/runtimes/standalone/Cargo.toml @@ -66,16 +66,14 @@ hex-literal = { workspace = true, optional = true } # Local Dependencies pallet-funding.workspace = true -pallet-credentials.workspace = true polimec-traits.workspace = true -runtime-common.workspace = true [build-dependencies] substrate-wasm-builder.workspace = true [features] default = ["std"] -fast-gov = ["runtime-common/fast-gov"] +fast-gov = [] std = [ "frame-benchmarking?/std", "parity-scale-codec/std", @@ -107,7 +105,6 @@ std = [ "sp-std/std", "sp-transaction-pool/std", "sp-version/std", - "pallet-credentials/std", "pallet-funding/std", "pallet-democracy/std", "pallet-collective/std", @@ -117,7 +114,6 @@ std = [ "pallet-insecure-randomness-collective-flip/std", "polimec-traits/std", "pallet-vesting/std", - "runtime-common/std" ] runtime-benchmarks = [ @@ -132,13 +128,11 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-collective/runtime-benchmarks", - "pallet-credentials/runtime-benchmarks", "pallet-democracy/runtime-benchmarks", "pallet-funding/runtime-benchmarks", "pallet-scheduler/runtime-benchmarks", "polimec-traits/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", - "runtime-common/runtime-benchmarks" ] try-runtime = [ "frame-executive/try-runtime", @@ -154,7 +148,6 @@ try-runtime = [ "pallet-transaction-payment/try-runtime", "pallet-authorship/try-runtime", "pallet-collective/try-runtime", - "pallet-credentials/try-runtime", "pallet-democracy/try-runtime", "pallet-funding/try-runtime", "pallet-insecure-randomness-collective-flip/try-runtime", @@ -162,5 +155,4 @@ try-runtime = [ "pallet-session/try-runtime", "polimec-traits/try-runtime", "pallet-vesting/try-runtime", - "runtime-common/try-runtime" ] diff --git a/runtimes/testnet/Cargo.toml b/runtimes/testnet/Cargo.toml index e526e248d..7cb6f4dbc 100644 --- a/runtimes/testnet/Cargo.toml +++ b/runtimes/testnet/Cargo.toml @@ -25,11 +25,7 @@ smallvec.workspace = true # Polimec specific pallet-funding.workspace = true -parachain-staking.workspace = true -pallet-credentials.workspace = true -pallet-asset-registry.workspace = true polimec-traits.workspace = true -runtime-common.workspace = true # KILT specific pallet-dip-consumer.workspace = true @@ -107,7 +103,7 @@ polkadot-primitives.workspace = true [features] default = ["std"] -fast-gov = ["runtime-common/fast-gov"] +fast-gov = [] std = [ "pallet-asset-tx-payment/std", "pallet-assets/std", @@ -131,12 +127,10 @@ std = [ "frame-system/std", "pallet-assets/std", "pallet-asset-tx-payment/std", - "pallet-asset-registry/std", "pallet-aura/std", "pallet-authorship/std", "pallet-balances/std", "pallet-collective/std", - "pallet-credentials/std", "pallet-democracy/std", "pallet-scheduler/std", "pallet-session/std", @@ -153,12 +147,10 @@ std = [ "pallet-preimage/std", "pallet-insecure-randomness-collective-flip/std", "parachains-common/std", - "parachain-staking/std", "parachain-info/std", "polkadot-parachain/std", "polkadot-runtime-common/std", "polimec-traits/std", - "runtime-common/std", "sp-api/std", "sp-block-builder/std", "sp-consensus-aura/std", @@ -195,7 +187,6 @@ runtime-benchmarks = [ "cumulus-pallet-xcmp-queue/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", - "runtime-common/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-collective/runtime-benchmarks", ] @@ -219,7 +210,6 @@ try-runtime = [ "pallet-xcm/try-runtime", "parachain-info/try-runtime", "pallet-vesting/try-runtime", - "runtime-common/try-runtime", "pallet-assets/try-runtime", "pallet-asset-tx-payment/try-runtime", ] diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 6f5d27ec8..f805bace5 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "stable" +channel = "nightly-2022-11-15" components = [ "rustfmt", "clippy" ] targets = [ "wasm32-unknown-unknown" ] \ No newline at end of file From ebc45aff9ba07db3f56af71856e4c3e24c7a2d07 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Thu, 13 Jul 2023 17:17:18 +0200 Subject: [PATCH 32/80] feat: the big cleanup --- Cargo.lock | 1308 +++++++++-------- Cargo.toml | 32 +- integration-tests/Cargo.toml | 16 +- integration-tests/src/lib.rs | 176 +-- nodes/parachain/Cargo.toml | 1 + nodes/parachain/src/chain_spec.rs | 6 +- nodes/parachain/src/chain_spec/base.rs | 197 +-- nodes/parachain/src/chain_spec/testnet.rs | 350 ++--- nodes/parachain/src/cli.rs | 9 +- nodes/parachain/src/command.rs | 110 +- nodes/parachain/src/rpc.rs | 10 +- nodes/parachain/src/service.rs | 136 +- nodes/standalone/src/benchmarking.rs | 5 +- nodes/standalone/src/chain_spec.rs | 12 +- nodes/standalone/src/command.rs | 104 +- nodes/standalone/src/rpc.rs | 10 +- nodes/standalone/src/service.rs | 128 +- pallets/funding/Cargo.toml | 2 - pallets/funding/src/benchmarking.rs | 16 +- pallets/funding/src/functions.rs | 315 ++-- pallets/funding/src/lib.rs | 128 +- pallets/funding/src/mock.rs | 13 +- pallets/funding/src/tests.rs | 429 +++--- pallets/funding/src/types.rs | 107 +- pallets/sandbox/Cargo.toml | 2 - pallets/sandbox/src/lib.rs | 15 +- pallets/sandbox/src/mock.rs | 13 +- pallets/sandbox/src/tests.rs | 46 +- polimec-skeleton/pallets/funding/src/mock.rs | 1 - primitives/xcm/Cargo.toml | 18 - primitives/xcm/src/lib.rs | 63 - runtimes/base/Cargo.toml | 9 +- runtimes/base/src/currency.rs | 14 - runtimes/base/src/lib.rs | 320 +--- runtimes/base/src/xcm_config.rs | 16 +- runtimes/shared-configuration/Cargo.toml | 28 + .../src/assets.rs} | 25 +- runtimes/shared-configuration/src/currency.rs | 64 + runtimes/shared-configuration/src/fee.rs | 48 + runtimes/shared-configuration/src/funding.rs | 64 + .../shared-configuration/src/governance.rs | 105 ++ .../src/lib.rs} | 19 +- runtimes/shared-configuration/src/staking.rs | 38 + .../src/weights/block_weights.rs | 2 +- .../src/weights/extrinsic_weights.rs | 2 +- .../shared-configuration/src/weights/mod.rs | 63 + .../src/weights/paritydb_weights.rs | 0 .../src/weights/rocksdb_weights.rs | 0 runtimes/standalone/Cargo.toml | 4 - runtimes/standalone/src/lib.rs | 103 +- runtimes/testnet/Cargo.toml | 20 +- runtimes/testnet/src/dip.rs | 169 --- runtimes/testnet/src/lib.rs | 457 ++---- runtimes/testnet/src/weights/block_weights.rs | 53 - .../testnet/src/weights/extrinsic_weights.rs | 52 - .../testnet/src/weights/pallet_funding.rs | 202 --- .../testnet/src/weights/paritydb_weights.rs | 62 - .../testnet/src/weights/rocksdb_weights.rs | 62 - runtimes/testnet/src/xcm_config.rs | 59 +- rustfmt.toml | 30 +- traits/Cargo.toml | 42 - traits/src/lib.rs | 83 -- 62 files changed, 2594 insertions(+), 3399 deletions(-) delete mode 100644 primitives/xcm/Cargo.toml delete mode 100644 primitives/xcm/src/lib.rs delete mode 100644 runtimes/base/src/currency.rs create mode 100644 runtimes/shared-configuration/Cargo.toml rename runtimes/{testnet/src/weights/mod.rs => shared-configuration/src/assets.rs} (59%) create mode 100644 runtimes/shared-configuration/src/currency.rs create mode 100644 runtimes/shared-configuration/src/fee.rs create mode 100644 runtimes/shared-configuration/src/funding.rs create mode 100644 runtimes/shared-configuration/src/governance.rs rename runtimes/{base/src/weights/mod.rs => shared-configuration/src/lib.rs} (67%) create mode 100644 runtimes/shared-configuration/src/staking.rs rename runtimes/{base => shared-configuration}/src/weights/block_weights.rs (94%) rename runtimes/{base => shared-configuration}/src/weights/extrinsic_weights.rs (94%) create mode 100644 runtimes/shared-configuration/src/weights/mod.rs rename runtimes/{base => shared-configuration}/src/weights/paritydb_weights.rs (100%) rename runtimes/{base => shared-configuration}/src/weights/rocksdb_weights.rs (100%) delete mode 100644 runtimes/testnet/src/dip.rs delete mode 100644 runtimes/testnet/src/weights/block_weights.rs delete mode 100644 runtimes/testnet/src/weights/extrinsic_weights.rs delete mode 100644 runtimes/testnet/src/weights/pallet_funding.rs delete mode 100644 runtimes/testnet/src/weights/paritydb_weights.rs delete mode 100644 runtimes/testnet/src/weights/rocksdb_weights.rs delete mode 100644 traits/Cargo.toml delete mode 100644 traits/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index cb0864f2c..9949fb987 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,11 +23,11 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" dependencies = [ - "gimli 0.27.2", + "gimli 0.27.3", ] [[package]] @@ -90,9 +90,9 @@ dependencies = [ [[package]] name = "aes" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241" +checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" dependencies = [ "cfg-if", "cipher 0.4.4", @@ -120,7 +120,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "209b47e8954a928e1d72e86eca7000ebb6655fe1436d33eefc2201cad027e237" dependencies = [ "aead 0.5.2", - "aes 0.8.2", + "aes 0.8.3", "cipher 0.4.4", "ctr 0.9.2", "ghash 0.5.0", @@ -153,7 +153,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.9", + "getrandom 0.2.10", "once_cell", "version_check", ] @@ -165,25 +165,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ "cfg-if", - "getrandom 0.2.9", + "getrandom 0.2.10", "once_cell", "version_check", ] [[package]] name = "aho-corasick" -version = "0.7.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" -dependencies = [ - "memchr", -] - -[[package]] -name = "aho-corasick" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" dependencies = [ "memchr", ] @@ -194,6 +185,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4436e0292ab1bb631b42973c61205e704475fe8126af845c8d923c0996328127" +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -229,15 +226,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" +checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" [[package]] name = "anstyle-parse" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" dependencies = [ "utf8parse", ] @@ -308,9 +305,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "arrayvec" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "asn1-rs" @@ -325,7 +322,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.21", + "time 0.3.23", ] [[package]] @@ -341,7 +338,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.21", + "time 0.3.23", ] [[package]] @@ -405,9 +402,9 @@ dependencies = [ "log", "parking", "polling", - "rustix 0.37.19", + "rustix 0.37.23", "slab", - "socket2", + "socket2 0.4.9", "waker-fn", ] @@ -422,13 +419,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.25", ] [[package]] @@ -441,7 +438,7 @@ dependencies = [ "futures-sink", "futures-util", "memchr", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", ] [[package]] @@ -469,16 +466,16 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" dependencies = [ - "addr2line 0.19.0", + "addr2line 0.20.0", "cc", "cfg-if", "libc", - "miniz_oxide 0.6.2", - "object 0.30.3", + "miniz_oxide", + "object 0.31.1", "rustc-demangle", ] @@ -508,9 +505,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.1" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f1e31e207a6b8fb791a38ea3105e6cb541f55e4d029902d3039a4ad07cc4105" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" [[package]] name = "base64ct" @@ -604,7 +601,7 @@ version = "0.64.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cexpr", "clang-sys", "lazy_static", @@ -624,6 +621,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" + [[package]] name = "bitvec" version = "1.0.1" @@ -652,8 +655,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc" dependencies = [ "arrayref", - "arrayvec 0.7.2", - "constant_time_eq", + "arrayvec 0.7.4", + "constant_time_eq 0.2.6", ] [[package]] @@ -663,21 +666,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6637f448b9e61dfadbdcbae9a885fadee1f3eaffb1f8d3c1965d3ade8bdfd44f" dependencies = [ "arrayref", - "arrayvec 0.7.2", - "constant_time_eq", + "arrayvec 0.7.4", + "constant_time_eq 0.2.6", ] [[package]] name = "blake3" -version = "1.3.3" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef" +checksum = "199c42ab6972d92c9f8995f086273d25c42fc0f7b2a1fcefba465c1352d25ba5" dependencies = [ "arrayref", - "arrayvec 0.7.2", + "arrayvec 0.7.4", "cc", "cfg-if", - "constant_time_eq", + "constant_time_eq 0.3.0", "digest 0.10.7", ] @@ -738,9 +741,9 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "bounded-collections" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07fbd1d11282a1eb134d3c3b7cf8ce213b5161c6e5f73fb1b98618482c606b64" +checksum = "eb5b05133427c07c4776906f673ccf36c21b102c9829c641a5b56bd151d44fd6" dependencies = [ "log", "parity-scale-codec", @@ -765,9 +768,9 @@ checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] name = "bstr" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a246e68bb43f6cd9db24bea052a53e40405417c5fb372e3d1a8a7f770a564ef5" +checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" dependencies = [ "memchr", "serde", @@ -831,9 +834,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.4" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" dependencies = [ "serde", ] @@ -938,13 +941,13 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.24" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" dependencies = [ + "android-tzdata", "iana-time-zone", "js-sys", - "num-integer", "num-traits", "time 0.1.45", "wasm-bindgen", @@ -1014,9 +1017,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.0" +version = "4.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93aae7a4192245f70fe75dd9157fc7b4a5bf53e88d30bd4396f7d8f9284d5acc" +checksum = "1640e5cc7fb47dbb8338fd471b105e7ed6c3cb2aeb00c2e067127ffd3764a05d" dependencies = [ "clap_builder", "clap_derive", @@ -1025,27 +1028,26 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.3.0" +version = "4.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f423e341edefb78c9caba2d9c7f7687d0e72e89df3ce3394554754393ac3990" +checksum = "98c59138d527eeaf9b53f35a77fcc1fad9d883116070c63d5de1c7dc7b00c72b" dependencies = [ "anstream", "anstyle", - "bitflags", "clap_lex", "strsim", ] [[package]] name = "clap_derive" -version = "4.3.0" +version = "4.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "191d9573962933b4027f932c600cd252ce27a8ad5979418fe78e43c07996f27b" +checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.25", ] [[package]] @@ -1084,9 +1086,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "comfy-table" -version = "6.1.4" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e7b787b0dc42e8111badfdbe4c3059158ccb2db8780352fa1b01e8ccf45cc4d" +checksum = "7e959d788268e3bf9d35ace83e81b124190378e4c91c9067524675e33394b8ba" dependencies = [ "strum", "strum_macros", @@ -1104,15 +1106,21 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" +checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" [[package]] name = "constant_time_eq" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13418e745008f7349ec7e449155f419a61b92b58a99cc3616942b926825ec76b" +checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" + +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" [[package]] name = "convert_case" @@ -1166,9 +1174,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] @@ -1188,7 +1196,7 @@ version = "0.93.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "253531aca9b6f56103c9420369db3263e784df39aa1c90685a1f69cfbba0623e" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "bumpalo", "cranelift-bforest", "cranelift-codegen-meta", @@ -1319,14 +1327,14 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.14" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", - "memoffset 0.8.0", + "memoffset 0.9.0", "scopeguard", ] @@ -1342,9 +1350,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", ] @@ -1375,7 +1383,7 @@ checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array 0.14.7", "rand_core 0.6.4", - "typenum", + "typenum 1.16.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1416,26 +1424,6 @@ dependencies = [ "cipher 0.4.4", ] -[[package]] -name = "ctype" -version = "1.11.0-dev" -source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "kilt-support", - "log", - "pallet-balances", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-io", - "sp-keystore", - "sp-runtime", - "sp-std", -] - [[package]] name = "cumulus-client-cli" version = "0.1.0" @@ -1972,9 +1960,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.94" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" +checksum = "e928d50d5858b744d1ea920b790641129c347a770d1530c3a85b77705a5ee031" dependencies = [ "cc", "cxxbridge-flags", @@ -1984,9 +1972,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.94" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" +checksum = "8332ba63f8a8040ca479de693150129067304a3496674477fff6d0c372cc34ae" dependencies = [ "cc", "codespan-reporting", @@ -1994,24 +1982,24 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.16", + "syn 2.0.25", ] [[package]] name = "cxxbridge-flags" -version = "1.0.94" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" +checksum = "5966a5a87b6e9bb342f5fab7170a93c77096efe199872afffc4b477cfeb86957" [[package]] name = "cxxbridge-macro" -version = "1.0.94" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" +checksum = "81b2dab6991c7ab1572fea8cb049db819b1aeea1e2dac74c0869f244d9f21a7c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.25", ] [[package]] @@ -2180,26 +2168,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "did" -version = "1.11.0-dev" -source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" -dependencies = [ - "ctype", - "frame-support", - "frame-system", - "kilt-support", - "log", - "pallet-balances", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-io", - "sp-keystore", - "sp-runtime", - "sp-std", -] - [[package]] name = "difflib" version = "0.4.0" @@ -2235,16 +2203,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "dip-support" -version = "1.11.0-dev" -source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" -dependencies = [ - "frame-support", - "parity-scale-codec", - "scale-info", -] - [[package]] name = "directories" version = "4.0.1" @@ -2294,7 +2252,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.25", ] [[package]] @@ -2311,9 +2269,9 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" [[package]] name = "dtoa" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65d09067bfacaa79114679b279d7f5885b53295b1e2cfb4e79c8e4bd3d633169" +checksum = "519b83cd10f5f6e969625a409f735182bea5558cd8b64c655806ceaae36f1999" [[package]] name = "dyn-clonable" @@ -2448,18 +2406,18 @@ checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.25", ] [[package]] name = "enumn" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48016319042fb7c87b78d2993084a831793a897a5cd1a2a67cab9d1eeb4b7d76" +checksum = "c9838a970f5de399d3070ae1739e131986b2f5dcc223c7423ca0927e3a878522" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.25", ] [[package]] @@ -2494,6 +2452,12 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "errno" version = "0.3.1" @@ -2593,7 +2557,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5aa1e3ae159e592ad222dc90c5acbad632b527779ba88486abe92782ab268bd" dependencies = [ "expander 0.0.4", - "indexmap", + "indexmap 1.9.3", "proc-macro-crate", "proc-macro2", "quote", @@ -2690,7 +2654,7 @@ checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" dependencies = [ "crc32fast", "libz-sys", - "miniz_oxide 0.7.1", + "miniz_oxide", ] [[package]] @@ -2718,9 +2682,9 @@ dependencies = [ [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] @@ -2881,7 +2845,7 @@ name = "frame-support" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ - "bitflags", + "bitflags 1.3.2", "frame-metadata", "frame-support-procedural", "impl-trait-for-tuples", @@ -3081,7 +3045,7 @@ dependencies = [ "futures-io", "memchr", "parking", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "waker-fn", ] @@ -3093,7 +3057,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.25", ] [[package]] @@ -3138,7 +3102,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "pin-utils", "slab", ] @@ -3158,7 +3122,7 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" dependencies = [ - "typenum", + "typenum 1.16.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3167,7 +3131,7 @@ version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ - "typenum", + "typenum 1.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "version_check", ] @@ -3194,9 +3158,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", @@ -3220,7 +3184,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" dependencies = [ "opaque-debug 0.3.0", - "polyval 0.6.0", + "polyval 0.6.1", ] [[package]] @@ -3230,15 +3194,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" dependencies = [ "fallible-iterator", - "indexmap", + "indexmap 1.9.3", "stable_deref_trait", ] [[package]] name = "gimli" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" [[package]] name = "glob" @@ -3248,11 +3212,11 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +checksum = "1391ab1f92ffcc08911957149833e682aa3fe252b9f45f966d2ef972274c97df" dependencies = [ - "aho-corasick 0.7.20", + "aho-corasick", "bstr", "fnv", "log", @@ -3272,9 +3236,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.19" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" +checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" dependencies = [ "bytes", "fnv", @@ -3282,7 +3246,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 1.9.3", "slab", "tokio", "tokio-util", @@ -3336,6 +3300,12 @@ dependencies = [ "ahash 0.8.3", ] +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + [[package]] name = "heck" version = "0.4.1" @@ -3353,18 +3323,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "hex" @@ -3457,7 +3418,7 @@ checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", "http", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", ] [[package]] @@ -3486,9 +3447,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.26" +version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ "bytes", "futures-channel", @@ -3500,8 +3461,8 @@ dependencies = [ "httparse", "httpdate", "itoa", - "pin-project-lite 0.2.9", - "socket2", + "pin-project-lite 0.2.10", + "socket2 0.4.9", "tokio", "tower-service", "tracing", @@ -3525,9 +3486,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.56" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3565,9 +3526,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -3642,6 +3603,16 @@ dependencies = [ "serde", ] +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown 0.14.0", +] + [[package]] name = "inout" version = "0.1.3" @@ -3675,6 +3646,38 @@ dependencies = [ "num-traits", ] +[[package]] +name = "integration-tests" +version = "0.1.0" +dependencies = [ + "cumulus-pallet-xcm", + "cumulus-primitives-core", + "frame-support", + "frame-system", + "pallet-assets", + "pallet-balances", + "pallet-xcm", + "parachain-info", + "parity-scale-codec", + "penpal-runtime", + "polimec-parachain-runtime", + "polkadot-core-primitives", + "polkadot-parachain", + "polkadot-runtime", + "polkadot-runtime-parachains", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "statemint-runtime", + "substrate-wasm-builder", + "xcm", + "xcm-builder", + "xcm-emulator", + "xcm-executor", +] + [[package]] name = "interceptor" version = "0.8.2" @@ -3696,11 +3699,11 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi 0.3.2", "libc", "windows-sys 0.48.0", ] @@ -3713,31 +3716,30 @@ checksum = "aa2f047c0a98b2f299aa5d6d7088443570faae494e9ae1305e48be000c9e0eb1" [[package]] name = "ipconfig" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd302af1b90f2463a98fa5ad469fc212c8e3175a41c3068601bfa2727591c5be" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2", + "socket2 0.5.3", "widestring", - "winapi", + "windows-sys 0.48.0", "winreg", ] [[package]] name = "ipnet" -version = "2.7.2" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" +checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" [[package]] name = "is-terminal" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.1", - "io-lifetimes", - "rustix 0.37.19", + "hermit-abi 0.3.2", + "rustix 0.38.4", "windows-sys 0.48.0", ] @@ -3752,9 +3754,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" [[package]] name = "jobserver" @@ -3767,9 +3769,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.63" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] @@ -3816,7 +3818,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4e70b4439a751a5de7dd5ed55eacff78ebf4ffe0fc009cb1ebb11417f5b536b" dependencies = [ "anyhow", - "arrayvec 0.7.2", + "arrayvec 0.7.4", "async-lock", "async-trait", "beef", @@ -3907,7 +3909,7 @@ dependencies = [ "cfg-if", "ecdsa", "elliptic-curve", - "sha2 0.10.6", + "sha2 0.10.7", ] [[package]] @@ -3919,39 +3921,6 @@ dependencies = [ "cpufeatures", ] -[[package]] -name = "kilt-dip-support" -version = "1.11.0-dev" -source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" -dependencies = [ - "did", - "frame-support", - "frame-system", - "pallet-dip-consumer", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-runtime", - "sp-std", - "sp-trie", -] - -[[package]] -name = "kilt-support" -version = "1.11.0-dev" -source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" -dependencies = [ - "frame-support", - "frame-system", - "log", - "parity-scale-codec", - "scale-info", - "serde", - "sp-core", - "sp-runtime", - "sp-std", -] - [[package]] name = "kusama-runtime" version = "0.9.39-1" @@ -4111,9 +4080,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.144" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libloading" @@ -4146,7 +4115,7 @@ dependencies = [ "bytes", "futures", "futures-timer", - "getrandom 0.2.9", + "getrandom 0.2.10", "instant", "libp2p-core 0.38.0", "libp2p-dns", @@ -4197,7 +4166,7 @@ dependencies = [ "rand 0.8.5", "rw-stream-sink", "sec1", - "sha2 0.10.6", + "sha2 0.10.7", "smallvec", "thiserror", "unsigned-varint", @@ -4281,7 +4250,7 @@ dependencies = [ "multihash 0.17.0", "quick-protobuf", "rand 0.8.5", - "sha2 0.10.6", + "sha2 0.10.7", "thiserror", "zeroize", ] @@ -4292,7 +4261,7 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2766dcd2be8c87d5e1f35487deb22d765f49c6ae1251b3633efe3b25698bd3d2" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "asynchronous-codec", "bytes", "either", @@ -4306,7 +4275,7 @@ dependencies = [ "prost", "prost-build", "rand 0.8.5", - "sha2 0.10.6", + "sha2 0.10.7", "smallvec", "thiserror", "uint", @@ -4328,7 +4297,7 @@ dependencies = [ "log", "rand 0.8.5", "smallvec", - "socket2", + "socket2 0.4.9", "tokio", "trust-dns-proto", "void", @@ -4381,7 +4350,7 @@ dependencies = [ "prost", "prost-build", "rand 0.8.5", - "sha2 0.10.6", + "sha2 0.10.7", "snow", "static_assertions", "thiserror", @@ -4489,7 +4458,7 @@ dependencies = [ "libc", "libp2p-core 0.38.0", "log", - "socket2", + "socket2 0.4.9", "tokio", ] @@ -4621,7 +4590,7 @@ dependencies = [ "rand 0.8.5", "serde", "sha2 0.9.9", - "typenum", + "typenum 1.16.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -4666,9 +4635,9 @@ dependencies = [ [[package]] name = "link-cplusplus" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" dependencies = [ "cc", ] @@ -4690,9 +4659,9 @@ dependencies = [ [[package]] name = "linregress" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "475015a7f8f017edb28d2e69813be23500ad4b32cfe3421c4148efc97324ee52" +checksum = "4de0b5f52a9f84544d268f5fabb71b38962d6aa3c6600b8bcd27d44ccf9c9c45" dependencies = [ "nalgebra", ] @@ -4709,11 +4678,17 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +[[package]] +name = "linux-raw-sys" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" + [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", @@ -4721,12 +4696,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "lru" @@ -4796,7 +4768,7 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] @@ -4836,7 +4808,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffc89ccdc6e10d6907450f753537ebc5c5d3460d2e4e62ea74bd571db62c0f9e" dependencies = [ - "rustix 0.37.19", + "rustix 0.37.23", ] [[package]] @@ -4868,9 +4840,9 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] @@ -4920,15 +4892,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.7.1" @@ -4940,14 +4903,13 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -5072,7 +5034,7 @@ dependencies = [ "core2", "digest 0.10.7", "multihash-derive", - "sha2 0.10.6", + "sha2 0.10.7", "sha3", "unsigned-varint", ] @@ -5124,9 +5086,9 @@ dependencies = [ [[package]] name = "nalgebra" -version = "0.32.2" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d68d47bba83f9e2006d117a9a33af1524e655516b8919caac694427a6fb1e511" +checksum = "307ed9b18cc2423f29e83f84fd23a8e73628727990181f18641a8b5dc2ab1caa" dependencies = [ "approx", "matrixmultiply", @@ -5135,14 +5097,14 @@ dependencies = [ "num-rational", "num-traits", "simba", - "typenum", + "typenum 1.16.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "nalgebra-macros" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d232c68884c0c99810a5a4d333ef7e47689cfd0edc85efc9e54e1e6bf5212766" +checksum = "91761aed67d03ad966ef783ae962ef9bbaca728d2dd7ceb7939ec110fffad998" dependencies = [ "proc-macro2", "quote", @@ -5183,7 +5145,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9ea4302b9759a7a88242299225ea3688e63c85ea136371bb6cf94fd674efaab" dependencies = [ "anyhow", - "bitflags", + "bitflags 1.3.2", "byteorder", "libc", "netlink-packet-core", @@ -5236,7 +5198,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "libc", "memoffset 0.6.5", @@ -5248,7 +5210,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "libc", "memoffset 0.7.1", @@ -5304,7 +5266,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "itoa", ] @@ -5341,11 +5303,11 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi 0.3.2", "libc", ] @@ -5357,15 +5319,15 @@ checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ "crc32fast", "hashbrown 0.12.3", - "indexmap", + "indexmap 1.9.3", "memchr", ] [[package]] name = "object" -version = "0.30.3" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" dependencies = [ "memchr", ] @@ -5390,9 +5352,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "opaque-debug" @@ -5461,7 +5423,7 @@ checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" dependencies = [ "ecdsa", "elliptic-curve", - "sha2 0.10.6", + "sha2 0.10.7", ] [[package]] @@ -5472,7 +5434,7 @@ checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa" dependencies = [ "ecdsa", "elliptic-curve", - "sha2 0.10.6", + "sha2 0.10.7", ] [[package]] @@ -5774,45 +5736,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-did-lookup" -version = "1.11.0-dev" -source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" -dependencies = [ - "base58", - "blake2", - "frame-benchmarking", - "frame-support", - "frame-system", - "hex", - "kilt-support", - "libsecp256k1", - "log", - "parity-scale-codec", - "scale-info", - "serde", - "sha3", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - -[[package]] -name = "pallet-dip-consumer" -version = "1.11.0-dev" -source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" -dependencies = [ - "cumulus-pallet-xcm", - "dip-support", - "frame-support", - "frame-system", - "kilt-support", - "parity-scale-codec", - "scale-info", - "sp-std", -] - [[package]] name = "pallet-election-provider-multi-phase" version = "4.0.0-dev" @@ -5896,7 +5819,6 @@ dependencies = [ "pallet-balances", "pallet-insecure-randomness-collective-flip", "parity-scale-codec", - "polimec-traits", "scale-info", "sp-arithmetic", "sp-core", @@ -6150,6 +6072,26 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-parachain-staking" +version = "3.0.0" +source = "git+https://gitlab.com/Omegabit/stake-patch#28a788327c7dbf408060cbe0b1f0109bd8533260" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-authorship", + "pallet-session", + "parity-scale-codec", + "scale-info", + "serde", + "sp-runtime", + "sp-staking", + "sp-std", + "substrate-fixed", +] + [[package]] name = "pallet-preimage" version = "4.0.0-dev" @@ -6247,7 +6189,6 @@ dependencies = [ "pallet-insecure-randomness-collective-flip", "parachains-common", "parity-scale-codec", - "polimec-traits", "scale-info", "serde", "sp-arithmetic", @@ -6506,6 +6447,21 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-uniques" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-utility" version = "4.0.0-dev" @@ -6633,9 +6589,9 @@ dependencies = [ [[package]] name = "parity-db" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4890dcb9556136a4ec2b0c51fa4a08c8b733b829506af8fff2e853f3a065985b" +checksum = "0dab3ac198341b2f0fec6e7f8a6eeed07a41201d98a124260611598c142e76df" dependencies = [ "blake2", "crc32fast", @@ -6653,11 +6609,11 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.5.0" +version = "3.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ddb756ca205bd108aee3c62c6d3c994e1df84a59b9d6d4a5ea42ee1fd5a9a28" +checksum = "756d439303e94fae44f288ba881ad29670c65b0c4b0e05674ca81061bb65f2c5" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "bitvec", "byte-slice-cast", "bytes", @@ -6668,9 +6624,9 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.1.4" +version = "3.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b26a931f824dd4eca30b3e43bb4f31cd5f0d3a403c5f5ff27106b805bfde7b" +checksum = "9d884d78fcf214d70b1e239fcd1c6e5e95aa3be1881918da2e488cc946c7a476" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -6714,7 +6670,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.7", + "parking_lot_core 0.9.8", ] [[package]] @@ -6733,22 +6689,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.7" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.2.16", + "redox_syscall 0.3.5", "smallvec", - "windows-sys 0.45.0", + "windows-targets 0.48.1", ] [[package]] name = "paste" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +checksum = "b4b27ab7be369122c218afc2079489cdcb4b517c0a3fc386ff11e1fedfcc2b35" [[package]] name = "pbkdf2" @@ -6792,17 +6748,76 @@ dependencies = [ "base64ct", ] +[[package]] +name = "penpal-runtime" +version = "0.9.27" +dependencies = [ + "cumulus-pallet-aura-ext", + "cumulus-pallet-dmp-queue", + "cumulus-pallet-parachain-system", + "cumulus-pallet-session-benchmarking", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "cumulus-primitives-timestamp", + "cumulus-primitives-utility", + "frame-benchmarking", + "frame-executive", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "hex-literal", + "log", + "pallet-asset-tx-payment", + "pallet-assets", + "pallet-aura", + "pallet-authorship", + "pallet-balances", + "pallet-collator-selection", + "pallet-session", + "pallet-sudo", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-xcm", + "parachain-info", + "parachains-common", + "parity-scale-codec", + "polkadot-parachain", + "polkadot-primitives", + "polkadot-runtime-common", + "scale-info", + "smallvec", + "sp-api", + "sp-block-builder", + "sp-consensus-aura", + "sp-core", + "sp-inherents", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std", + "sp-transaction-pool", + "sp-version", + "substrate-wasm-builder", + "xcm", + "xcm-builder", + "xcm-executor", +] + [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e68e84bfb01f0507134eac1e9b410a12ba379d064eab48c50ba4ce329a527b70" +checksum = "f73935e4d55e2abf7f130186537b19e7a4abc886a0252380b59248af473a3fc9" dependencies = [ "thiserror", "ucd-trie", @@ -6810,9 +6825,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b79d4c71c865a25a4322296122e3924d30bc8ee0834c8bfc8b95f7f054afbfb" +checksum = "aef623c9bbfa0eedf5a0efba11a5ee83209c326653ca31ff019bec3a95bfff2b" dependencies = [ "pest", "pest_generator", @@ -6820,26 +6835,26 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c435bf1076437b851ebc8edc3a18442796b30f1728ffea6262d59bbe28b077e" +checksum = "b3e8cba4ec22bada7fc55ffe51e2deb6a0e0db2d0b7ab0b103acc80d2510c190" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.25", ] [[package]] name = "pest_meta" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "745a452f8eb71e39ffd8ee32b3c5f51d03845f99786fa9b68db6ff509c505411" +checksum = "a01f71cb40bd8bb94232df14b946909e14660e33fc05db3e50ae2a82d7ea0ca0" dependencies = [ "once_cell", "pest", - "sha2 0.10.6", + "sha2 0.10.7", ] [[package]] @@ -6849,27 +6864,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ "fixedbitset", - "indexmap", + "indexmap 1.9.3", ] [[package]] name = "pin-project" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.25", ] [[package]] @@ -6880,9 +6895,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" [[package]] name = "pin-utils" @@ -6943,6 +6958,7 @@ dependencies = [ "pallet-aura", "pallet-authorship", "pallet-balances", + "pallet-parachain-staking", "pallet-session", "pallet-sudo", "pallet-timestamp", @@ -6957,8 +6973,10 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-common", "scale-info", + "shared-configuration", "smallvec", "sp-api", + "sp-arithmetic", "sp-block-builder", "sp-consensus-aura", "sp-core", @@ -6992,6 +7010,7 @@ dependencies = [ "cumulus-relay-chain-minimal-node", "frame-benchmarking", "frame-benchmarking-cli", + "hex-literal", "jsonrpsee", "log", "pallet-transaction-payment-rpc", @@ -7051,7 +7070,6 @@ dependencies = [ "cumulus-primitives-core", "cumulus-primitives-timestamp", "cumulus-primitives-utility", - "did", "frame-benchmarking", "frame-executive", "frame-support", @@ -7060,7 +7078,6 @@ dependencies = [ "frame-system-rpc-runtime-api", "frame-try-runtime", "hex-literal", - "kilt-dip-support", "log", "pallet-asset-tx-payment", "pallet-assets", @@ -7069,11 +7086,10 @@ dependencies = [ "pallet-balances", "pallet-collective", "pallet-democracy", - "pallet-did-lookup", - "pallet-dip-consumer", "pallet-funding", "pallet-insecure-randomness-collective-flip", "pallet-multisig", + "pallet-parachain-staking", "pallet-preimage", "pallet-scheduler", "pallet-session", @@ -7088,12 +7104,12 @@ dependencies = [ "parachain-info", "parachains-common", "parity-scale-codec", - "polimec-traits", "polkadot-parachain", "polkadot-primitives", "polkadot-runtime-common", "scale-info", "serde", + "shared-configuration", "smallvec", "sp-api", "sp-block-builder", @@ -7111,7 +7127,6 @@ dependencies = [ "xcm", "xcm-builder", "xcm-executor", - "xcm-primitives", ] [[package]] @@ -7191,7 +7206,6 @@ dependencies = [ "pallet-utility", "pallet-vesting", "parity-scale-codec", - "polimec-traits", "scale-info", "sp-api", "sp-block-builder", @@ -7207,22 +7221,6 @@ dependencies = [ "substrate-wasm-builder", ] -[[package]] -name = "polimec-traits" -version = "0.1.0" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "parity-scale-codec", - "scale-info", - "serde", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - [[package]] name = "polkadot-approval-distribution" version = "0.9.39-1" @@ -7409,7 +7407,7 @@ dependencies = [ "fatality", "futures", "futures-timer", - "indexmap", + "indexmap 1.9.3", "lru 0.9.0", "parity-scale-codec", "polkadot-erasure-coding", @@ -8190,7 +8188,7 @@ name = "polkadot-runtime-parachains" version = "0.9.39-1" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ - "bitflags", + "bitflags 1.3.2", "bitvec", "derive_more", "frame-benchmarking", @@ -8345,7 +8343,7 @@ dependencies = [ "arrayvec 0.5.2", "fatality", "futures", - "indexmap", + "indexmap 1.9.3", "parity-scale-codec", "polkadot-node-network-protocol", "polkadot-node-primitives", @@ -8375,12 +8373,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" dependencies = [ "autocfg", - "bitflags", + "bitflags 1.3.2", "cfg-if", "concurrent-queue", "libc", "log", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "windows-sys 0.48.0", ] @@ -8409,9 +8407,9 @@ dependencies = [ [[package]] name = "polyval" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef234e08c11dfcb2e56f79fd70f6f2eb7f025c0ce2333e82f4f0518ecad30c6" +checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" dependencies = [ "cfg-if", "cpufeatures", @@ -8530,9 +8528,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.58" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8" +checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" dependencies = [ "unicode-ident", ] @@ -8696,9 +8694,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.27" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" +checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" dependencies = [ "proc-macro2", ] @@ -8768,7 +8766,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.9", + "getrandom 0.2.10", ] [[package]] @@ -8825,7 +8823,7 @@ checksum = "6413f3de1edee53342e6138e75b56d32e7bc6e332b3bd62d497b1929d4cfbcdd" dependencies = [ "pem", "ring", - "time 0.3.21", + "time 0.3.23", "x509-parser 0.13.2", "yasna", ] @@ -8838,7 +8836,7 @@ checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" dependencies = [ "pem", "ring", - "time 0.3.21", + "time 0.3.23", "yasna", ] @@ -8848,7 +8846,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -8857,7 +8855,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -8866,7 +8864,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.9", + "getrandom 0.2.10", "redox_syscall 0.2.16", "thiserror", ] @@ -8886,22 +8884,22 @@ dependencies = [ [[package]] name = "ref-cast" -version = "1.0.16" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43faa91b1c8b36841ee70e97188a869d37ae21759da6846d4be66de5bf7b12c" +checksum = "1641819477c319ef452a075ac34a4be92eb9ba09f6841f62d594d50fdcf0bf6b" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.16" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d2275aab483050ab2a7364c1a46604865ee7d6906684e08db0f090acf74f9e7" +checksum = "68bf53dad9b6086826722cdc99140793afd9f62faa14a1ad07eb4f955e7a7216" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.25", ] [[package]] @@ -8918,13 +8916,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.2" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1a59b5d8e97dee33696bf13c5ba8ab85341c002922fba050069326b9c498974" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" dependencies = [ - "aho-corasick 1.0.1", + "aho-corasick", "memchr", - "regex-syntax 0.7.2", + "regex-automata 0.3.3", + "regex-syntax 0.7.4", ] [[package]] @@ -8936,6 +8935,17 @@ dependencies = [ "regex-syntax 0.6.29", ] +[[package]] +name = "regex-automata" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.7.4", +] + [[package]] name = "regex-syntax" version = "0.6.29" @@ -8944,9 +8954,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "region" @@ -8954,7 +8964,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e" dependencies = [ - "bitflags", + "bitflags 1.3.2", "libc", "mach", "winapi", @@ -9214,11 +9224,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.36.14" +version = "0.36.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e4d67015953998ad0eb82887a0eb0129e18a7e2f3b7b0f6c422fddcd503d62" +checksum = "c37f1bd5ef1b5422177b7646cba67430579cfe2ace80f284fee876bca52ad941" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", @@ -9228,11 +9238,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.19" +version = "0.37.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" +checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", @@ -9240,6 +9250,19 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "rustix" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" +dependencies = [ + "bitflags 2.3.3", + "errno", + "libc", + "linux-raw-sys 0.4.3", + "windows-sys 0.48.0", +] + [[package]] name = "rustls" version = "0.19.1" @@ -9267,9 +9290,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ "openssl-probe", "rustls-pemfile", @@ -9279,18 +9302,18 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ - "base64 0.21.1", + "base64 0.21.2", ] [[package]] name = "rustversion" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +checksum = "dc31bd9b61a32c31f9650d18add92aa83a49ba979c143eefd27fe7177b05bd5f" [[package]] name = "rw-stream-sink" @@ -9305,9 +9328,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" [[package]] name = "safe-mix" @@ -9320,9 +9343,9 @@ dependencies = [ [[package]] name = "safe_arch" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "794821e4ccb0d9f979512f9c1973480123f9bd62a90d74ab0f9426fcf8f4a529" +checksum = "62a7484307bd40f8f7ccbacccac730108f2cae119a3b11c74485b48aa9ea650f" dependencies = [ "bytemuck", ] @@ -9742,7 +9765,7 @@ dependencies = [ "libc", "log", "once_cell", - "rustix 0.36.14", + "rustix 0.36.15", "sc-allocator", "sc-executor-common", "sp-runtime-interface", @@ -9908,7 +9931,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", - "bitflags", + "bitflags 1.3.2", "bytes", "futures", "futures-timer", @@ -10409,9 +10432,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.7.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b569c32c806ec3abdf3b5869fb8bf1e0d275a7c1c9b0b05603d9464632649edf" +checksum = "35c0a159d0c45c12b20c5a844feb1fe4bea86e28f17b92a5f0c42193634d3782" dependencies = [ "bitvec", "cfg-if", @@ -10423,9 +10446,9 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.6.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53012eae69e5aa5c14671942a5dd47de59d4cdcff8532a6dd0e081faf1119482" +checksum = "912e55f6d20e0e80d63733872b40e1227c0bce1e1ab81ba67d696339bfd7fd29" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -10435,11 +10458,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" dependencies = [ - "windows-sys 0.42.0", + "windows-sys 0.48.0", ] [[package]] @@ -10479,9 +10502,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scratch" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" +checksum = "764cad9e7e1ca5fe15b552859ff5d96a314e6ed2934f2260168cd5dfa5891409" [[package]] name = "sct" @@ -10562,7 +10585,7 @@ version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -10614,29 +10637,29 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.163" +version = "1.0.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.163" +version = "1.0.171" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.25", ] [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "b5062a995d481b2308b6064e9af76011f2921c35f97b0468811ed9f6cd91dfed" dependencies = [ "itoa", "ryu", @@ -10694,9 +10717,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ "cfg-if", "cpufeatures", @@ -10722,6 +10745,17 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shared-configuration" +version = "0.1.0" +dependencies = [ + "frame-support", + "frame-system", + "parachains-common", + "smallvec", + "sp-arithmetic", +] + [[package]] name = "shlex" version = "1.1.0" @@ -10804,9 +10838,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "snap" @@ -10827,7 +10861,7 @@ dependencies = [ "rand_core 0.6.4", "ring", "rustc_version 0.4.0", - "sha2 0.10.6", + "sha2 0.10.7", "subtle", ] @@ -10841,6 +10875,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "socket2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "soketto" version = "0.7.1" @@ -11068,7 +11112,7 @@ source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c dependencies = [ "array-bytes 4.2.0", "base58", - "bitflags", + "bitflags 1.3.2", "blake2", "bounded-collections", "dyn-clonable", @@ -11112,7 +11156,7 @@ dependencies = [ "blake2", "byteorder", "digest 0.10.7", - "sha2 0.10.6", + "sha2 0.10.7", "sha3", "sp-std", "twox-hash", @@ -11591,9 +11635,9 @@ dependencies = [ [[package]] name = "ss58-registry" -version = "1.40.0" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47a8ad42e5fc72d5b1eb104a5546937eaf39843499948bb666d6e93c62423b" +checksum = "bfc443bad666016e012538782d9e3006213a7db43e9fb1dda91657dc06a6fa08" dependencies = [ "Inflector", "num-format", @@ -11610,6 +11654,70 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "statemint-runtime" +version = "1.0.0" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +dependencies = [ + "cumulus-pallet-aura-ext", + "cumulus-pallet-dmp-queue", + "cumulus-pallet-parachain-system", + "cumulus-pallet-session-benchmarking", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "cumulus-primitives-timestamp", + "cumulus-primitives-utility", + "frame-benchmarking", + "frame-executive", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "hex-literal", + "log", + "pallet-asset-tx-payment", + "pallet-assets", + "pallet-aura", + "pallet-authorship", + "pallet-balances", + "pallet-collator-selection", + "pallet-multisig", + "pallet-proxy", + "pallet-session", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-uniques", + "pallet-utility", + "pallet-xcm", + "pallet-xcm-benchmarks", + "parachain-info", + "parachains-common", + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain", + "polkadot-runtime-common", + "polkadot-runtime-constants", + "scale-info", + "smallvec", + "sp-api", + "sp-block-builder", + "sp-consensus-aura", + "sp-core", + "sp-inherents", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std", + "sp-transaction-pool", + "sp-version", + "substrate-wasm-builder", + "xcm", + "xcm-builder", + "xcm-executor", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -11634,7 +11742,7 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a2a1c578e98c1c16fc3b8ec1328f7659a500737d7a0c6d625e73e830ff9c1f6" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg_aliases", "libc", "parking_lot 0.11.2", @@ -11737,6 +11845,16 @@ dependencies = [ "platforms 2.0.0", ] +[[package]] +name = "substrate-fixed" +version = "0.5.9" +source = "git+https://github.com/encointer/substrate-fixed#a4fb461aae6205ffc55bed51254a40c52be04e5d" +dependencies = [ + "parity-scale-codec", + "scale-info", + "typenum 1.16.0 (git+https://github.com/encointer/typenum?tag=v1.16.0)", +] + [[package]] name = "substrate-frame-rpc-system" version = "4.0.0-dev" @@ -11845,9 +11963,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.16" +version = "2.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" +checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2" dependencies = [ "proc-macro2", "quote", @@ -11872,7 +11990,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "system-configuration-sys", ] @@ -11895,21 +12013,22 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.12.7" +version = "0.12.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd1ba337640d60c3e96bc6f0638a939b9c9a7f2c316a1598c279828b3d1dc8c5" +checksum = "df8e77cb757a61f51b947ec4a7e3646efd825b73561db1c232a8ccb639e611a0" [[package]] name = "tempfile" -version = "3.5.0" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" dependencies = [ + "autocfg", "cfg-if", "fastrand", "redox_syscall 0.3.5", - "rustix 0.37.19", - "windows-sys 0.45.0", + "rustix 0.37.23", + "windows-sys 0.48.0", ] [[package]] @@ -11929,22 +12048,22 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.25", ] [[package]] @@ -12019,9 +12138,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc" +checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" dependencies = [ "itoa", "serde", @@ -12037,9 +12156,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4" dependencies = [ "time-core", ] @@ -12056,7 +12175,7 @@ dependencies = [ "pbkdf2 0.11.0", "rand 0.8.5", "rustc-hash", - "sha2 0.10.6", + "sha2 0.10.7", "thiserror", "unicode-normalization", "wasm-bindgen", @@ -12090,19 +12209,20 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.28.1" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg", + "backtrace", "bytes", "libc", "mio", "num_cpus", "parking_lot 0.12.1", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "signal-hook-registry", - "socket2", + "socket2 0.4.9", "tokio-macros", "windows-sys 0.48.0", ] @@ -12115,7 +12235,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.25", ] [[package]] @@ -12136,7 +12256,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" dependencies = [ "futures-core", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "tokio", "tokio-util", ] @@ -12151,7 +12271,7 @@ dependencies = [ "futures-core", "futures-io", "futures-sink", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "tokio", "tracing", ] @@ -12167,17 +12287,17 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" [[package]] name = "toml_edit" -version = "0.19.9" +version = "0.19.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d964908cec0d030b812013af25a0e57fddfadb1e066ecc6681d86253129d4f" +checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78" dependencies = [ - "indexmap", + "indexmap 2.0.0", "toml_datetime", "winnow", ] @@ -12199,14 +12319,14 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" dependencies = [ - "bitflags", + "bitflags 1.3.2", "bytes", "futures-core", "futures-util", "http", "http-body", "http-range-header", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "tower-layer", "tower-service", ] @@ -12231,20 +12351,20 @@ checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", "log", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "tracing-attributes", "tracing-core", ] [[package]] name = "tracing-attributes" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.25", ] [[package]] @@ -12374,7 +12494,7 @@ dependencies = [ "lazy_static", "rand 0.8.5", "smallvec", - "socket2", + "socket2 0.4.9", "thiserror", "tinyvec", "tokio", @@ -12488,11 +12608,20 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +[[package]] +name = "typenum" +version = "1.16.0" +source = "git+https://github.com/encointer/typenum?tag=v1.16.0#4c8dddaa8bdd13130149e43b4085ad14e960617f" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + [[package]] name = "ucd-trie" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "uint" @@ -12514,9 +12643,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" [[package]] name = "unicode-normalization" @@ -12579,12 +12708,12 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" dependencies = [ "form_urlencoded", - "idna 0.3.0", + "idna 0.4.0", "percent-encoding", ] @@ -12596,11 +12725,11 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.3.3" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" +checksum = "d023da39d1fde5a8a3fe1f3e01ca9632ada0a63e9797de55a879d6e2236277be" dependencies = [ - "getrandom 0.2.9", + "getrandom 0.2.10", ] [[package]] @@ -12654,11 +12783,10 @@ dependencies = [ [[package]] name = "want" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "log", "try-lock", ] @@ -12682,9 +12810,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -12692,24 +12820,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.25", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.36" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" dependencies = [ "cfg-if", "js-sys", @@ -12719,9 +12847,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -12729,22 +12857,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.25", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wasm-instrument" @@ -12851,7 +12979,7 @@ version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64b20236ab624147dfbb62cf12a19aaf66af0e41b8398838b66e997d07d269d4" dependencies = [ - "indexmap", + "indexmap 1.9.3", "url", ] @@ -12864,7 +12992,7 @@ dependencies = [ "anyhow", "bincode", "cfg-if", - "indexmap", + "indexmap 1.9.3", "libc", "log", "object 0.29.0", @@ -12904,9 +13032,9 @@ dependencies = [ "directories-next", "file-per-thread-logger", "log", - "rustix 0.36.14", + "rustix 0.36.15", "serde", - "sha2 0.10.6", + "sha2 0.10.7", "toml", "windows-sys 0.42.0", "zstd", @@ -12942,7 +13070,7 @@ dependencies = [ "anyhow", "cranelift-entity", "gimli 0.26.2", - "indexmap", + "indexmap 1.9.3", "log", "object 0.29.0", "serde", @@ -12984,7 +13112,7 @@ checksum = "eed41cbcbf74ce3ff6f1d07d1b707888166dc408d1a880f651268f4f7c9194b2" dependencies = [ "object 0.29.0", "once_cell", - "rustix 0.36.14", + "rustix 0.36.15", ] [[package]] @@ -13007,7 +13135,7 @@ dependencies = [ "anyhow", "cc", "cfg-if", - "indexmap", + "indexmap 1.9.3", "libc", "log", "mach", @@ -13015,7 +13143,7 @@ dependencies = [ "memoffset 0.6.5", "paste", "rand 0.8.5", - "rustix 0.36.14", + "rustix 0.36.15", "wasmtime-asm-macros", "wasmtime-environ", "wasmtime-jit-debug", @@ -13036,9 +13164,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.63" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" dependencies = [ "js-sys", "wasm-bindgen", @@ -13096,10 +13224,10 @@ dependencies = [ "sdp", "serde", "serde_json", - "sha2 0.10.6", + "sha2 0.10.7", "stun", "thiserror", - "time 0.3.21", + "time 0.3.23", "tokio", "turn", "url", @@ -13159,7 +13287,7 @@ dependencies = [ "sec1", "serde", "sha1", - "sha2 0.10.6", + "sha2 0.10.7", "signature", "subtle", "thiserror", @@ -13201,7 +13329,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f08dfd7a6e3987e255c4dbe710dde5d94d0f0574f8a21afa95d171376c143106" dependencies = [ "log", - "socket2", + "socket2 0.4.9", "thiserror", "tokio", "webrtc-util", @@ -13268,7 +13396,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f1db1727772c05cf7a2cfece52c3aca8045ca1e176cd517d323489aa3c6d87" dependencies = [ "async-trait", - "bitflags", + "bitflags 1.3.2", "bytes", "cc", "ipnet", @@ -13401,9 +13529,9 @@ dependencies = [ [[package]] name = "wide" -version = "0.7.9" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cd0496a71f3cc6bc4bf0ed91346426a5099e93d89807e663162dc5a1069ff65" +checksum = "aa469ffa65ef7e0ba0f164183697b89b854253fd31aeb92358b7b6155177d62f" dependencies = [ "bytemuck", "safe_arch", @@ -13411,9 +13539,9 @@ dependencies = [ [[package]] name = "widestring" -version = "0.5.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" [[package]] name = "winapi" @@ -13465,7 +13593,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.48.1", ] [[package]] @@ -13498,7 +13626,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.48.1", ] [[package]] @@ -13518,9 +13646,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ "windows_aarch64_gnullvm 0.48.0", "windows_aarch64_msvc 0.48.0", @@ -13647,20 +13775,21 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.4.6" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699" +checksum = "81a2094c43cc94775293eaa0e499fbc30048a6d824ac82c0351a8c0bf9112529" dependencies = [ "memchr", ] [[package]] name = "winreg" -version = "0.10.1" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "winapi", + "cfg-if", + "windows-sys 0.48.0", ] [[package]] @@ -13710,7 +13839,7 @@ dependencies = [ "ring", "rusticata-macros", "thiserror", - "time 0.3.21", + "time 0.3.23", ] [[package]] @@ -13728,7 +13857,7 @@ dependencies = [ "oid-registry 0.6.1", "rusticata-macros", "thiserror", - "time 0.3.21", + "time 0.3.23", ] [[package]] @@ -13768,6 +13897,32 @@ dependencies = [ "xcm-executor", ] +[[package]] +name = "xcm-emulator" +version = "0.1.0" +source = "git+https://github.com/shaunxw/xcm-simulator?rev=aa13dce47596e150806dfc3af99096dae6ffc65e#aa13dce47596e150806dfc3af99096dae6ffc65e" +dependencies = [ + "cumulus-pallet-dmp-queue", + "cumulus-pallet-parachain-system", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "cumulus-primitives-parachain-inherent", + "cumulus-test-relay-sproof-builder", + "frame-support", + "frame-system", + "parachain-info", + "parity-scale-codec", + "paste", + "polkadot-primitives", + "polkadot-runtime-parachains", + "quote", + "sp-arithmetic", + "sp-io", + "sp-std", + "xcm", + "xcm-executor", +] + [[package]] name = "xcm-executor" version = "0.9.39-1" @@ -13788,15 +13943,6 @@ dependencies = [ "xcm", ] -[[package]] -name = "xcm-primitives" -version = "0.0.1" -dependencies = [ - "sp-std", - "xcm", - "xcm-executor", -] - [[package]] name = "xcm-procedural" version = "0.9.39-1" @@ -13828,7 +13974,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" dependencies = [ - "time 0.3.21", + "time 0.3.23", ] [[package]] @@ -13848,7 +13994,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.25", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ebb8ca791..f71ec117a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,9 @@ [workspace] -members = [ "nodes/*", - "pallets/*", - "runtimes/*", - "traits", - # "integration-tests" +members = [ + "nodes/*", + "pallets/*", + "runtimes/*", + "integration-tests" ] [workspace.package] @@ -46,21 +46,21 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran # Internal pallets (with default disabled) pallet-funding = { path = "pallets/funding", default-features = false } pallet-sandbox = { path = "pallets/sandbox", default-features = false } +pallet-parachain-staking = { git = "https://gitlab.com/Omegabit/stake-patch", default-features = false } + # Internal support (with default disabled) -polimec-traits = { path = "traits", default-features = false } -xcm-primitives = { path = "primitives/xcm", default-features = false } +shared-configuration = { path = "runtimes/shared-configuration", default-features = false } # External support (with default disabled) -dip-support = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } -kilt-support = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } -kilt-dip-support = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } -did = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } -pallet-did-lookup = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } -pallet-dip-provider = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } -pallet-dip-consumer = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } -# Internal runtime API (with default disabled) -kilt-runtime-api-staking = { path = "runtime-api/staking", default-features = false } +# dip-support = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } +# kilt-support = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } +# kilt-dip-support = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } +# did = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } +# pallet-did-lookup = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } +# pallet-dip-provider = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } +# pallet-dip-consumer = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } + # External (without extra features and with default disabled if necessary) parity-scale-codec = { version = "3.3.0", default-features = false } diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index 2b641803c..4776bedfa 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -46,14 +46,14 @@ polkadot-runtime.workspace = true statemint-runtime.workspace = true polimec-parachain-runtime.workspace = true penpal-runtime.workspace = true -dip-provider-runtime-template = { workspace = true, features = ["std"] } -did = { workspace = true, features = ["std"] } -kilt-support = { workspace = true, features = ["std"] } -pallet-did-lookup = { workspace = true, features = ["std"] } -dip-support = { workspace = true, features = ["std"] } -runtime-common = { workspace = true, features = ["std"] } -kilt-dip-support = { workspace = true, features = ["std"] } -kilt-runtime-common = { workspace = true, features = ["std"] } +# dip-provider-runtime-template = { workspace = true, features = ["std"] } +# did = { workspace = true, features = ["std"] } +# kilt-support = { workspace = true, features = ["std"] } +# pallet-did-lookup = { workspace = true, features = ["std"] } +# dip-support = { workspace = true, features = ["std"] } +# runtime-common = { workspace = true, features = ["std"] } +# kilt-dip-support = { workspace = true, features = ["std"] } +# kilt-runtime-common = { workspace = true, features = ["std"] } [features] default = ["std"] diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs index dd2f3374f..09b481930 100644 --- a/integration-tests/src/lib.rs +++ b/integration-tests/src/lib.rs @@ -28,11 +28,6 @@ use xcm_emulator::{ TestExt, }; -// DIP -use did::did_details::{DidDetails, DidEncryptionKey, DidVerificationKey}; -use dip_provider_runtime_template::DidIdentifier; -use kilt_support::deposit::Deposit; - const RELAY_ASSET_ID: u32 = 0; const RESERVE_TRANSFER_AMOUNT: u128 = 10_0_000_000_000; //10 UNITS when 10 decimals pub const INITIAL_BALANCE: u128 = 100_0_000_000_000; @@ -81,16 +76,6 @@ decl_test_parachain! { } } -decl_test_parachain! { - pub struct ProviderParachain { - Runtime = dip_provider_runtime_template::Runtime, - RuntimeOrigin = dip_provider_runtime_template::RuntimeOrigin, - XcmpMessageHandler = dip_provider_runtime_template::XcmpQueue, - DmpMessageHandler = dip_provider_runtime_template::DmpQueue, - new_ext = provider_ext(provider_id()), - } -} - decl_test_network! { pub struct Network { relay_chain = PolkadotNet, @@ -98,7 +83,6 @@ decl_test_network! { (2000u32, PolimecNet), (1000u32, StatemintNet), (3000u32, PenpalNet), - (2001u32, ProviderParachain), ], } } @@ -252,12 +236,6 @@ pub fn polimec_ext(para_id: u32) -> sp_io::TestExternalities { .unwrap(); pallet_assets::GenesisConfig:: { - assets: vec![( - RELAY_ASSET_ID, - polimec_runtime::AssetsPalletId::get().into_account_truncating(), - false, - 1_0_000_000_000, - )], metadata: vec![( RELAY_ASSET_ID, "Local DOT".as_bytes().to_vec(), @@ -265,6 +243,7 @@ pub fn polimec_ext(para_id: u32) -> sp_io::TestExternalities { 12, )], accounts: vec![(RELAY_ASSET_ID, ALICE, INITIAL_BALANCE)], + ..Default::default() } .assimilate_storage(&mut t) .unwrap(); @@ -341,55 +320,6 @@ pub fn penpal_ext(para_id: u32) -> sp_io::TestExternalities { ext } -pub fn provider_ext(para_id: u32) -> sp_io::TestExternalities { - use dip_provider_runtime_template::{Runtime, System}; - - let mut t = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); - - let parachain_info_config = parachain_info::GenesisConfig { - parachain_id: para_id.into(), - }; - >::assimilate_storage(¶chain_info_config, &mut t) - .unwrap(); - - let mut ext = sp_io::TestExternalities::new(t); - let did: DidIdentifier = did_auth_key().public().into(); - let details = generate_did_details(); - ext.execute_with(|| { - did::pallet::Did::::insert(&did, details); - System::set_block_number(1); - }); - ext -} - -pub(crate) fn did_auth_key() -> ed25519::Pair { - ed25519::Pair::from_seed(&[200u8; 32]) -} - -fn generate_did_details() -> DidDetails { - let auth_key: DidVerificationKey = did_auth_key().public().into(); - let att_key: DidVerificationKey = sr25519::Pair::from_seed(&[100u8; 32]).public().into(); - let del_key: DidVerificationKey = ecdsa::Pair::from_seed(&[101u8; 32]).public().into(); - - let mut details = DidDetails::new( - auth_key, - 0u32, - Deposit { - amount: 1u64.into(), - owner: dip_provider_runtime_template::AccountId::new([1u8; 32]), - }, - ) - .unwrap(); - details.update_attestation_key(att_key, 0u32).unwrap(); - details.update_delegation_key(del_key, 0u32).unwrap(); - details - .add_key_agreement_key(DidEncryptionKey::X25519([100u8; 32]), 0u32) - .unwrap(); - details -} - /// Shortcuts to reduce boilerplate on runtime types pub mod shortcuts { use super::*; @@ -398,7 +328,6 @@ pub mod shortcuts { pub type PolimecRuntime = polimec_runtime::Runtime; pub type StatemintRuntime = statemint_runtime::Runtime; pub type PenpalRuntime = penpal_runtime::Runtime; - pub type ProviderRuntime = dip_provider_runtime_template::Runtime; pub type PolkadotXcmPallet = polkadot_runtime::XcmPallet; pub type PolimecXcmPallet = polimec_runtime::PolkadotXcm; @@ -429,7 +358,6 @@ pub mod shortcuts { pub type PolimecAccountId = polkadot_primitives::AccountId; pub type StatemintAccountId = polkadot_primitives::AccountId; pub type PenpalAccountId = polkadot_primitives::AccountId; - pub type ProviderAccountId = dip_provider_runtime_template::AccountId; } #[cfg(test)] @@ -663,7 +591,7 @@ mod reserve_backed_transfers { let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; assert!( - polimec_delta_alice_dot_balance >= RESERVE_TRANSFER_AMOUNT - polimec_runtime::WeightToFee::::weight_to_fee(&MAX_XCM_WEIGHT) && + polimec_delta_alice_dot_balance >= RESERVE_TRANSFER_AMOUNT - polimec_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) && polimec_delta_alice_dot_balance <= RESERVE_TRANSFER_AMOUNT, "Polimec ALICE DOT balance should have increased by at least the transfer amount minus the XCM execution fee" ); @@ -671,7 +599,7 @@ mod reserve_backed_transfers { assert!( polimec_delta_dot_issuance >= RESERVE_TRANSFER_AMOUNT - - polimec_runtime::WeightToFee::::weight_to_fee(&MAX_XCM_WEIGHT) + - polimec_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) && polimec_delta_dot_issuance <= RESERVE_TRANSFER_AMOUNT, "Polimec DOT issuance should have increased by at least the transfer amount minus the XCM execution fee" ); @@ -1406,100 +1334,4 @@ mod reserve_backed_transfers { "Polimec PLMC issuance should not have changed" ); } -} - -#[cfg(test)] -mod dip { - use super::*; - use did::{Did, DidSignature}; - use dip_provider_runtime_template::DipProvider; - use pallet_did_lookup::linkable_account::LinkableAccountId; - use polimec_runtime::DipConsumer; - - #[test] - fn commit_identity() { - Network::reset(); - use frame_system::RawOrigin; - use kilt_dip_support::{ - did::{MerkleEntriesAndDidSignature, TimeBoundDidSignature}, - merkle::MerkleProof, - }; - use kilt_runtime_common::dip::merkle::CompleteMerkleProof; - use kilt_runtime_common::dip::merkle::DidMerkleRootGenerator; - use polimec_parachain_runtime::{ - BlockNumber, DidLookup, Runtime as ConsumerRuntime, RuntimeCall as ConsumerRuntimeCall, RuntimeEvent, - System, - }; - use sp_runtime::traits::Zero; - - let did: DidIdentifier = did_auth_key().public().into(); - - // 1. Send identity proof from DIP provider to DIP consumer. - ProviderParachain::execute_with(|| { - assert_ok!(DipProvider::commit_identity( - RawOrigin::Signed(ProviderAccountId::from([0u8; 32])).into(), - did.clone(), - Box::new(ParentThen(X1(Parachain(polimec_id()))).into()), - Box::new((Here, 1_000_000_000).into()), - Weight::from_ref_time(4_000), - )); - }); - // 2. Verify that the proof has made it to the DIP consumer. - PolimecNet::execute_with(|| { - // 2.1 Verify that there was no XCM error. - assert!(!System::events().iter().any(|r| matches!( - r.event, - RuntimeEvent::XcmpQueue(XcmpEvent::Fail { - error: _, - message_hash: _, - weight: _ - }) - ))); - // 2.2 Verify the proof digest was stored correctly. - assert!(DipConsumer::identity_proofs(&did).is_some()); - }); - // 3. Call an extrinsic on the consumer chain with a valid proof and signature - let did_details = ProviderParachain::execute_with(|| { - Did::get(&did).expect("DID details should be stored on the provider chain.") - }); - let call = ConsumerRuntimeCall::DidLookup(pallet_did_lookup::Call::::associate_sender {}); - // 3.1 Generate a proof - let CompleteMerkleProof { proof, .. } = DidMerkleRootGenerator::::generate_proof( - &did_details, - [did_details.authentication_key].iter(), - ) - .expect("Proof generation should not fail"); - // 3.2 Generate a DID signature - let genesis_hash = - PolimecNet::execute_with(|| frame_system::Pallet::::block_hash(BlockNumber::zero())); - let system_block = PolimecNet::execute_with(frame_system::Pallet::::block_number); - let payload = (call.clone(), 0u128, DISPATCHER_ACCOUNT, system_block, genesis_hash); - let signature: DidSignature = did_auth_key().sign(&payload.encode()).into(); - // 3.3 Call the `dispatch_as` extrinsic on the consumer chain with the generated - // proof - PolimecNet::execute_with(|| { - assert_ok!(DipConsumer::dispatch_as( - RawOrigin::Signed(DISPATCHER_ACCOUNT).into(), - did.clone(), - MerkleEntriesAndDidSignature { - merkle_entries: MerkleProof { - blinded: proof.blinded, - revealed: proof.revealed, - }, - did_signature: TimeBoundDidSignature { - signature, - block_number: system_block - } - }, - Box::new(call), - )); - // Verify the account -> DID link exists and contains the right information - let linked_did = - DidLookup::connected_dids::(DISPATCHER_ACCOUNT.into()).map(|link| link.did); - assert_eq!(linked_did, Some(did.clone())); - // Verify that the details of the DID subject have been bumped - let details = DipConsumer::identity_proofs(&did).map(|entry| entry.details); - assert_eq!(details, Some(1u128)); - }); - } -} +} \ No newline at end of file diff --git a/nodes/parachain/Cargo.toml b/nodes/parachain/Cargo.toml index bcbf88b45..e564a5e40 100644 --- a/nodes/parachain/Cargo.toml +++ b/nodes/parachain/Cargo.toml @@ -16,6 +16,7 @@ log.workspace = true parity-scale-codec = { workspace = true } serde = { workspace = true, features = ["derive"] } jsonrpsee = { workspace = true, features = ["server"] } +hex-literal.workspace = true # Local polimec-parachain-runtime.workspace = true diff --git a/nodes/parachain/src/chain_spec.rs b/nodes/parachain/src/chain_spec.rs index 67fd4a24c..c7ff83f19 100644 --- a/nodes/parachain/src/chain_spec.rs +++ b/nodes/parachain/src/chain_spec.rs @@ -28,8 +28,6 @@ use sp_runtime::traits::{IdentifyAccount, Verify}; pub mod base; pub mod testnet; -// TODO: Set a proper TELEMETRY_URL -const TELEMETRY_URL: &str = "wss://tbd"; const DEFAULT_PARA_ID: ParaId = LOWEST_PUBLIC_ID; /// Helper function to generate a crypto pair from seed @@ -40,7 +38,9 @@ pub fn get_from_seed(seed: &str) -> ::Pu } /// The extensions for the [`ChainSpec`]. -#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)] +#[derive( + Debug, Clone, Eq, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension, +)] #[serde(deny_unknown_fields)] pub struct Extensions { /// The relay chain of the Parachain. diff --git a/nodes/parachain/src/chain_spec/base.rs b/nodes/parachain/src/chain_spec/base.rs index f10a85790..48fa084bc 100644 --- a/nodes/parachain/src/chain_spec/base.rs +++ b/nodes/parachain/src/chain_spec/base.rs @@ -22,13 +22,18 @@ use crate::chain_spec::Extensions; use cumulus_primitives_core::ParaId; use polimec_base_runtime as base_runtime; use sc_service::ChainType; -use sp_core::sr25519; +use sp_core::{crypto::UncheckedInto, sr25519}; +use sp_runtime::{Perbill, Percent}; -use crate::chain_spec::{get_account_id_from_seed, get_from_seed, get_properties, DEFAULT_PARA_ID}; +use crate::chain_spec::{get_account_id_from_seed, get_properties, DEFAULT_PARA_ID}; use base_runtime::{ - polimec_inflation_config, staking::MinCollatorStake, AccountId, AuraId as AuthorityId, Balance, BalancesConfig, - GenesisConfig, InflationInfo, ParachainInfoConfig, ParachainStakingConfig, PolkadotXcmConfig, SessionConfig, - SudoConfig, SystemConfig, MAX_COLLATOR_STAKE, PLMC, + pallet_parachain_staking::{ + inflation::{perbill_annual_to_perbill_round, BLOCKS_PER_YEAR}, + InflationInfo, Range, + }, + AccountId, AuraId as AuthorityId, Balance, BalancesConfig, GenesisConfig, MinCandidateStk, + ParachainInfoConfig, ParachainStakingConfig, PolkadotXcmConfig, SessionConfig, SudoConfig, + SystemConfig, PLMC, }; /// The default XCM version to set in genesis config. @@ -37,13 +42,45 @@ const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION; /// Specialized `ChainSpec` for the shell parachain runtime. pub type ChainSpec = sc_service::GenericChainSpec; +const COLLATOR_COMMISSION: Perbill = Perbill::from_percent(30); +const PARACHAIN_BOND_RESERVE_PERCENT: Percent = Percent::from_percent(0); +const BLOCKS_PER_ROUND: u32 = 2 * 10; +const NUM_SELECTED_CANDIDATES: u32 = 5; +pub fn polimec_inflation_config() -> InflationInfo { + fn to_round_inflation(annual: Range) -> Range { + perbill_annual_to_perbill_round( + annual, + // rounds per year + BLOCKS_PER_YEAR / BLOCKS_PER_ROUND, + ) + } + + let annual = Range { + min: Perbill::from_percent(2), + ideal: Perbill::from_percent(3), + max: Perbill::from_percent(3), + }; + + InflationInfo { + // staking expectations + expect: Range { min: 100_000 * PLMC, ideal: 200_000 * PLMC, max: 500_000 * PLMC }, + // annual inflation + annual, + round: to_round_inflation(annual), + } +} + +pub fn get_base_session_keys(keys: AuthorityId) -> base_runtime::SessionKeys { + base_runtime::SessionKeys { aura: keys } +} + pub fn get_local_base_chain_spec() -> Result { let properties = get_properties("PLMC", 10, 41); let wasm = base_runtime::WASM_BINARY.ok_or("No WASM")?; Ok(ChainSpec::from_genesis( "Polimec Base Develop", - "polimec", + "polimec-base", ChainType::Local, move || { base_testnet_genesis( @@ -52,58 +89,46 @@ pub fn get_local_base_chain_spec() -> Result { ( get_account_id_from_seed::("Alice"), None, - 2 * MinCollatorStake::get(), + 2 * MinCandidateStk::get(), ), ( get_account_id_from_seed::("Bob"), None, - 2 * MinCollatorStake::get(), + 2 * MinCandidateStk::get(), ), ], polimec_inflation_config(), - MAX_COLLATOR_STAKE, vec![ - ( - get_account_id_from_seed::("Alice"), - get_from_seed::("Alice"), - ), - ( - get_account_id_from_seed::("Bob"), - get_from_seed::("Bob"), - ), + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), ], vec![ - (get_account_id_from_seed::("Alice"), 10000000 * PLMC), - (get_account_id_from_seed::("Bob"), 10000000 * PLMC), - (get_account_id_from_seed::("Charlie"), 10000000 * PLMC), - (get_account_id_from_seed::("Dave"), 10000000 * PLMC), - (get_account_id_from_seed::("Eve"), 10000000 * PLMC), - (get_account_id_from_seed::("Ferdie"), 10000000 * PLMC), ( - get_account_id_from_seed::("Alice//stash"), - 10000000 * PLMC, + get_account_id_from_seed::("Alice"), + 5 * MinCandidateStk::get(), ), ( - get_account_id_from_seed::("Bob//stash"), - 10000000 * PLMC, + get_account_id_from_seed::("Bob"), + 5 * MinCandidateStk::get(), ), ( - get_account_id_from_seed::("Charlie//stash"), - 10000000 * PLMC, + get_account_id_from_seed::("Charlie"), + 5 * MinCandidateStk::get(), ), ( - get_account_id_from_seed::("Dave//stash"), - 10000000 * PLMC, + get_account_id_from_seed::("Dave"), + 5 * MinCandidateStk::get(), ), ( - get_account_id_from_seed::("Eve//stash"), - 10000000 * PLMC, + get_account_id_from_seed::("Eve"), + 5 * MinCandidateStk::get(), ), ( - get_account_id_from_seed::("Ferdie//stash"), - 10000000 * PLMC, + get_account_id_from_seed::("Ferdie"), + 5 * MinCandidateStk::get(), ), ], + get_account_id_from_seed::("Alice"), DEFAULT_PARA_ID, ) }, @@ -112,58 +137,42 @@ pub fn get_local_base_chain_spec() -> Result { Some("polimec"), None, Some(properties), - Extensions { - relay_chain: "rococo_local_testnet".into(), - para_id: DEFAULT_PARA_ID.into(), - }, + Extensions { relay_chain: "rococo_local_testnet".into(), para_id: DEFAULT_PARA_ID.into() }, )) } -pub fn get_live_base_chain_spec() -> Result { +pub fn get_kusama_base_chain_spec() -> Result { let properties = get_properties("PLMC", 10, 41); let wasm = base_runtime::WASM_BINARY.ok_or("No WASM")?; // TODO: Update this after reserving a ParaId - let id: u32 = 2105; + let id: u32 = 4261; + + const PLMC_SUDO_ACC: [u8; 32] = + hex_literal::hex!["d4192a54c9caa4a38eeb3199232ed0d8568b22956cafb76c7d5a1afbf4e2dc38"]; + const PLMC_COL_ACC_1: [u8; 32] = + hex_literal::hex!["6603f63a4091ba074b4384e64c6bba1dd96f6af49331ebda686b0a0f27dd961c"]; + const PLMC_COL_ACC_2: [u8; 32] = + hex_literal::hex!["ba48ab77461ef53f9ebfdc94a12c780b57354f986e31eb2504b9e3ed580fab51"]; Ok(ChainSpec::from_genesis( - "Polimec Base", + "Polimec Kusama Testnet", "polimec", ChainType::Live, move || { base_testnet_genesis( wasm, - // TODO: Update stakers vec![ - ( - get_account_id_from_seed::("Alice"), - None, - 2 * MinCollatorStake::get(), - ), - ( - get_account_id_from_seed::("Bob"), - None, - 2 * MinCollatorStake::get(), - ), + (PLMC_COL_ACC_1.into(), None, 2 * MinCandidateStk::get()), + (PLMC_COL_ACC_2.into(), None, 2 * MinCandidateStk::get()), ], polimec_inflation_config(), - MAX_COLLATOR_STAKE, - // TODO: Update initial authorities + vec![(PLMC_COL_ACC_1.into()), (PLMC_COL_ACC_2.into())], vec![ - ( - get_account_id_from_seed::("Alice"), - get_from_seed::("Alice"), - ), - ( - get_account_id_from_seed::("Bob"), - get_from_seed::("Bob"), - ), - ], - // TODO: Update initial balances - vec![ - (get_account_id_from_seed::("Alice"), 10000000 * PLMC), - (get_account_id_from_seed::("Bob"), 10000000 * PLMC), + (PLMC_COL_ACC_1.into(), 3 * MinCandidateStk::get()), + (PLMC_COL_ACC_2.into(), 3 * MinCandidateStk::get()), ], + PLMC_SUDO_ACC.into(), id.into(), ) }, @@ -172,35 +181,34 @@ pub fn get_live_base_chain_spec() -> Result { Some("polimec"), None, Some(properties), - Extensions { - relay_chain: "polkadot".into(), - para_id: id, - }, + Extensions { relay_chain: "kusama".into(), para_id: id }, )) } fn base_testnet_genesis( - wasm_binary: &[u8], stakers: Vec<(AccountId, Option, Balance)>, inflation_config: InflationInfo, - max_candidate_stake: Balance, initial_authorities: Vec<(AccountId, AuthorityId)>, - endowed_accounts: Vec<(AccountId, Balance)>, id: ParaId, + wasm_binary: &[u8], + stakers: Vec<(AccountId, Option, Balance)>, + inflation_config: InflationInfo, + initial_authorities: Vec, + endowed_accounts: Vec<(AccountId, Balance)>, + sudo_account: AccountId, + id: ParaId, ) -> GenesisConfig { - let accounts = endowed_accounts - .iter() - .map(|(account, _)| account.clone()) - .collect::>(); - GenesisConfig { - system: SystemConfig { - code: wasm_binary.to_vec(), - }, - balances: BalancesConfig { - balances: endowed_accounts.clone(), - }, + system: SystemConfig { code: wasm_binary.to_vec() }, + balances: BalancesConfig { balances: endowed_accounts.clone() }, parachain_info: ParachainInfoConfig { parachain_id: id }, parachain_staking: ParachainStakingConfig { - stakers, + candidates: stakers + .iter() + .map(|(accunt, _, balance)| (accunt.clone(), balance.clone())) + .collect::>(), inflation_config, - max_candidate_stake, + delegations: vec![], + collator_commission: COLLATOR_COMMISSION, + parachain_bond_reserve_percent: PARACHAIN_BOND_RESERVE_PERCENT, + blocks_per_round: BLOCKS_PER_ROUND, + num_selected_candidates: NUM_SELECTED_CANDIDATES, }, aura: Default::default(), aura_ext: Default::default(), @@ -208,22 +216,17 @@ fn base_testnet_genesis( session: SessionConfig { keys: initial_authorities .iter() - .map(|(acc, key)| { + .map(|acc| { ( acc.clone(), acc.clone(), - base_runtime::SessionKeys { aura: key.clone() }, + get_base_session_keys(Into::<[u8; 32]>::into(acc.clone()).unchecked_into()), ) }) .collect::>(), }, - treasury: Default::default(), - polkadot_xcm: PolkadotXcmConfig { - safe_xcm_version: Some(SAFE_XCM_VERSION), - }, - sudo: SudoConfig { - key: Some(accounts.first().expect("").to_owned()), - }, + polkadot_xcm: PolkadotXcmConfig { safe_xcm_version: Some(SAFE_XCM_VERSION) }, + sudo: SudoConfig { key: Some(sudo_account) }, transaction_payment: Default::default(), } } diff --git a/nodes/parachain/src/chain_spec/testnet.rs b/nodes/parachain/src/chain_spec/testnet.rs index 0e13db10b..d71f3cb6a 100644 --- a/nodes/parachain/src/chain_spec/testnet.rs +++ b/nodes/parachain/src/chain_spec/testnet.rs @@ -20,19 +20,23 @@ use cumulus_primitives_core::ParaId; use polimec_parachain_runtime::{ - polimec_inflation_config, AuraId as AuthorityId, MinCollatorStake, MAX_COLLATOR_STAKE, PLMC, + pallet_parachain_staking::{ + inflation::{perbill_annual_to_perbill_round, BLOCKS_PER_YEAR}, + InflationInfo, Range, + }, + AuraId as AuthorityId, MinCandidateStk, ParachainStakingConfig, PLMC, }; use polimec_parachain_runtime::{ - AccountId, Balance, BalancesConfig, CouncilConfig, CredentialsConfig, GenesisConfig, InflationInfo, - ParachainInfoConfig, PolkadotXcmConfig, SessionConfig, SessionKeys, SudoConfig, SystemConfig, - TechnicalCommitteeConfig, VestingConfig, WASM_BINARY, + AccountId, Balance, BalancesConfig, CouncilConfig, GenesisConfig, ParachainInfoConfig, + PolkadotXcmConfig, SessionConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig, + VestingConfig, }; use sc_service::ChainType; -use sc_telemetry::TelemetryEndpoints; -use sp_core::sr25519; +use sp_core::{crypto::UncheckedInto, sr25519}; +use sp_runtime::{Perbill, Percent}; -use crate::chain_spec::{get_account_id_from_seed, get_from_seed, DEFAULT_PARA_ID, TELEMETRY_URL}; +use crate::chain_spec::{get_account_id_from_seed, DEFAULT_PARA_ID}; use super::{get_properties, Extensions}; @@ -41,9 +45,41 @@ const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION; /// Specialized `ChainSpec` for the normal parachain runtime. pub type ChainSpec = sc_service::GenericChainSpec; +const COLLATOR_COMMISSION: Perbill = Perbill::from_percent(30); +const PARACHAIN_BOND_RESERVE_PERCENT: Percent = Percent::from_percent(0); +const BLOCKS_PER_ROUND: u32 = 2 * 10; +const NUM_SELECTED_CANDIDATES: u32 = 5; +pub fn polimec_inflation_config() -> InflationInfo { + fn to_round_inflation(annual: Range) -> Range { + perbill_annual_to_perbill_round( + annual, + // rounds per year + BLOCKS_PER_YEAR / BLOCKS_PER_ROUND, + ) + } + + let annual = Range { + min: Perbill::from_percent(2), + ideal: Perbill::from_percent(3), + max: Perbill::from_percent(3), + }; + + InflationInfo { + // staking expectations + expect: Range { min: 100_000 * PLMC, ideal: 200_000 * PLMC, max: 500_000 * PLMC }, + // annual inflation + annual, + round: to_round_inflation(annual), + } +} + +pub fn get_testnet_session_keys(keys: AuthorityId) -> polimec_parachain_runtime::SessionKeys { + polimec_parachain_runtime::SessionKeys { aura: keys } +} + pub fn get_chain_spec_dev() -> Result { let properties = get_properties("PLMC", 10, 41); - let wasm = WASM_BINARY.ok_or("No WASM")?; + let wasm = polimec_parachain_runtime::WASM_BINARY.ok_or("No WASM")?; Ok(ChainSpec::from_genesis( "Polimec Develop", @@ -56,58 +92,46 @@ pub fn get_chain_spec_dev() -> Result { ( get_account_id_from_seed::("Alice"), None, - 2 * MinCollatorStake::get(), + 2 * MinCandidateStk::get(), ), ( get_account_id_from_seed::("Bob"), None, - 2 * MinCollatorStake::get(), + 2 * MinCandidateStk::get(), ), ], polimec_inflation_config(), - MAX_COLLATOR_STAKE, vec![ - ( - get_account_id_from_seed::("Alice"), - get_from_seed::("Alice"), - ), - ( - get_account_id_from_seed::("Bob"), - get_from_seed::("Bob"), - ), + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), ], vec![ - (get_account_id_from_seed::("Alice"), 10000000 * PLMC), - (get_account_id_from_seed::("Bob"), 10000000 * PLMC), - (get_account_id_from_seed::("Charlie"), 10000000 * PLMC), - (get_account_id_from_seed::("Dave"), 10000000 * PLMC), - (get_account_id_from_seed::("Eve"), 10000000 * PLMC), - (get_account_id_from_seed::("Ferdie"), 10000000 * PLMC), ( - get_account_id_from_seed::("Alice//stash"), - 10000000 * PLMC, + get_account_id_from_seed::("Alice"), + 5 * MinCandidateStk::get(), ), ( - get_account_id_from_seed::("Bob//stash"), - 10000000 * PLMC, + get_account_id_from_seed::("Bob"), + 5 * MinCandidateStk::get(), ), ( - get_account_id_from_seed::("Charlie//stash"), - 10000000 * PLMC, + get_account_id_from_seed::("Charlie"), + 5 * MinCandidateStk::get(), ), ( - get_account_id_from_seed::("Dave//stash"), - 10000000 * PLMC, + get_account_id_from_seed::("Dave"), + 5 * MinCandidateStk::get(), ), ( - get_account_id_from_seed::("Eve//stash"), - 10000000 * PLMC, + get_account_id_from_seed::("Eve"), + 5 * MinCandidateStk::get(), ), ( - get_account_id_from_seed::("Ferdie//stash"), - 10000000 * PLMC, + get_account_id_from_seed::("Ferdie"), + 5 * MinCandidateStk::get(), ), ], + get_account_id_from_seed::("Alice"), DEFAULT_PARA_ID, ) }, @@ -116,252 +140,110 @@ pub fn get_chain_spec_dev() -> Result { None, None, Some(properties), - Extensions { - relay_chain: "rococo-local".into(), - para_id: DEFAULT_PARA_ID.into(), - }, + Extensions { relay_chain: "rococo-local".into(), para_id: DEFAULT_PARA_ID.into() }, )) } pub fn get_prod_chain_spec() -> Result { let properties = get_properties("PLMC", 10, 41); - let wasm = WASM_BINARY.ok_or("No WASM")?; - let id: ParaId = 2105.into(); + let wasm = polimec_parachain_runtime::WASM_BINARY.ok_or("No WASM")?; - Ok(ChainSpec::from_genesis( - "Polimec", - "polimec", - ChainType::Live, - move || { - testnet_genesis( - wasm, - vec![ - ( - get_account_id_from_seed::("Alice"), - None, - 2 * MinCollatorStake::get(), - ), - ( - get_account_id_from_seed::("Bob"), - None, - 2 * MinCollatorStake::get(), - ), - ], - polimec_inflation_config(), - MAX_COLLATOR_STAKE, - vec![ - ( - get_account_id_from_seed::("Alice"), - get_from_seed::("Alice"), - ), - ( - get_account_id_from_seed::("Bob"), - get_from_seed::("Bob"), - ), - ], - vec![ - (get_account_id_from_seed::("Alice"), 10000000 * PLMC), - (get_account_id_from_seed::("Bob"), 10000000 * PLMC), - (get_account_id_from_seed::("Charlie"), 10000000 * PLMC), - (get_account_id_from_seed::("Dave"), 10000000 * PLMC), - (get_account_id_from_seed::("Eve"), 10000000 * PLMC), - (get_account_id_from_seed::("Ferdie"), 10000000 * PLMC), - ( - get_account_id_from_seed::("Alice//stash"), - 10000000 * PLMC, - ), - ( - get_account_id_from_seed::("Bob//stash"), - 10000000 * PLMC, - ), - ( - get_account_id_from_seed::("Charlie//stash"), - 10000000 * PLMC, - ), - ( - get_account_id_from_seed::("Dave//stash"), - 10000000 * PLMC, - ), - ( - get_account_id_from_seed::("Eve//stash"), - 10000000 * PLMC, - ), - ( - get_account_id_from_seed::("Ferdie//stash"), - 10000000 * PLMC, - ), - ], - id, - ) - }, - vec![], - Some( - TelemetryEndpoints::new(vec![(TELEMETRY_URL.to_string(), 0)]).expect("Polimec telemetry url is valid; qed"), - ), - Some("polimec"), - None, - Some(properties), - Extensions { - relay_chain: "polkadot".into(), - para_id: id.into(), - }, - )) -} + // TODO: Update this after reserving a ParaId + let id: u32 = 4261; -pub fn get_local_prod_chain_spec() -> Result { - let properties = get_properties("PLMC", 10, 41); - let wasm = WASM_BINARY.ok_or("No WASM")?; - let id: ParaId = 2000.into(); + const PLMC_SUDO_ACC: [u8; 32] = + hex_literal::hex!["d4192a54c9caa4a38eeb3199232ed0d8568b22956cafb76c7d5a1afbf4e2dc38"]; + const PLMC_COL_ACC_1: [u8; 32] = + hex_literal::hex!["6603f63a4091ba074b4384e64c6bba1dd96f6af49331ebda686b0a0f27dd961c"]; + const PLMC_COL_ACC_2: [u8; 32] = + hex_literal::hex!["ba48ab77461ef53f9ebfdc94a12c780b57354f986e31eb2504b9e3ed580fab51"]; Ok(ChainSpec::from_genesis( - "Polimec", + "Polimec Kusama Testnet", "polimec", ChainType::Live, move || { testnet_genesis( wasm, vec![ - ( - get_account_id_from_seed::("Alice"), - None, - 2 * MinCollatorStake::get(), - ), - ( - get_account_id_from_seed::("Bob"), - None, - 2 * MinCollatorStake::get(), - ), + (PLMC_COL_ACC_1.into(), None, 2 * MinCandidateStk::get()), + (PLMC_COL_ACC_2.into(), None, 2 * MinCandidateStk::get()), ], polimec_inflation_config(), - MAX_COLLATOR_STAKE, - vec![ - ( - get_account_id_from_seed::("Alice"), - get_from_seed::("Alice"), - ), - ( - get_account_id_from_seed::("Bob"), - get_from_seed::("Bob"), - ), - ], + vec![(PLMC_COL_ACC_1.into()), (PLMC_COL_ACC_2.into())], vec![ - (get_account_id_from_seed::("Alice"), 10000000 * PLMC), - (get_account_id_from_seed::("Bob"), 10000000 * PLMC), - (get_account_id_from_seed::("Charlie"), 10000000 * PLMC), - (get_account_id_from_seed::("Dave"), 10000000 * PLMC), - (get_account_id_from_seed::("Eve"), 10000000 * PLMC), - (get_account_id_from_seed::("Ferdie"), 10000000 * PLMC), - ( - get_account_id_from_seed::("Alice//stash"), - 10000000 * PLMC, - ), - ( - get_account_id_from_seed::("Bob//stash"), - 10000000 * PLMC, - ), - ( - get_account_id_from_seed::("Charlie//stash"), - 10000000 * PLMC, - ), - ( - get_account_id_from_seed::("Dave//stash"), - 10000000 * PLMC, - ), - ( - get_account_id_from_seed::("Eve//stash"), - 10000000 * PLMC, - ), - ( - get_account_id_from_seed::("Ferdie//stash"), - 10000000 * PLMC, - ), + (PLMC_COL_ACC_1.into(), 3 * MinCandidateStk::get()), + (PLMC_COL_ACC_2.into(), 3 * MinCandidateStk::get()), ], - id, + PLMC_SUDO_ACC.into(), + id.into(), ) }, vec![], - Some( - TelemetryEndpoints::new(vec![(TELEMETRY_URL.to_string(), 0)]).expect("Polimec telemetry url is valid; qed"), - ), + None, Some("polimec"), None, Some(properties), - Extensions { - relay_chain: "rococo-local".into(), - para_id: id.into(), - }, + Extensions { relay_chain: "polkadot".into(), para_id: id }, )) } #[allow(clippy::too_many_arguments)] fn testnet_genesis( - wasm_binary: &[u8], _stakers: Vec<(AccountId, Option, Balance)>, _inflation_config: InflationInfo, - _max_candidate_stake: Balance, initial_authorities: Vec<(AccountId, AuthorityId)>, - endowed_accounts: Vec<(AccountId, Balance)>, id: ParaId, + wasm_binary: &[u8], + stakers: Vec<(AccountId, Option, Balance)>, + inflation_config: InflationInfo, + initial_authorities: Vec, + endowed_accounts: Vec<(AccountId, Balance)>, + sudo_account: AccountId, + id: ParaId, ) -> GenesisConfig { - // type VestingPeriod = BlockNumber; - // type LockingPeriod = BlockNumber; - - // // vesting and locks as initially designed - // let claimable_accounts_json = &include_bytes!("../../res/genesis/claimable-accounts.json")[..]; - // let claimable_accounts: Vec<(AccountId, Balance, VestingPeriod, LockingPeriod)> = - // serde_json::from_slice(claimable_accounts_json) - // .expect("The file genesis_accounts.json exists and is valid; qed"); - - // // botlabs account should not be migrated but some have vesting - // let owned_accounts_json = &include_bytes!("../../res/genesis/owned-accounts.json")[..]; - // let owned_accounts: Vec<(AccountId, Balance, VestingPeriod, LockingPeriod)> = - // serde_json::from_slice(owned_accounts_json) - // .expect("The file botlabs_accounts.json exists and is valid; qed"); - - let accounts = endowed_accounts - .iter() - .map(|(account, _)| account.clone()) - .collect::>(); + let accounts = endowed_accounts.iter().map(|(account, _)| account.clone()).collect::>(); GenesisConfig { - system: SystemConfig { - code: wasm_binary.to_vec(), - }, - balances: BalancesConfig { - balances: endowed_accounts.clone(), - }, + system: SystemConfig { code: wasm_binary.to_vec() }, + balances: BalancesConfig { balances: endowed_accounts.clone() }, parachain_info: ParachainInfoConfig { parachain_id: id }, - parachain_staking: Default::default(), + parachain_staking: ParachainStakingConfig { + candidates: stakers + .iter() + .map(|(accunt, _, balance)| (accunt.clone(), balance.clone())) + .collect::>(), + inflation_config, + delegations: vec![], + collator_commission: COLLATOR_COMMISSION, + parachain_bond_reserve_percent: PARACHAIN_BOND_RESERVE_PERCENT, + blocks_per_round: BLOCKS_PER_ROUND, + num_selected_candidates: NUM_SELECTED_CANDIDATES, + }, // no need to pass anything to aura, in fact it will panic if we do. Session will take care // of this. aura: Default::default(), aura_ext: Default::default(), parachain_system: Default::default(), - credentials: CredentialsConfig { - issuers: accounts.clone(), - retails: accounts.clone(), - professionals: accounts.clone(), - institutionals: accounts.clone(), - }, session: SessionConfig { keys: initial_authorities .iter() - .map(|(acc, key)| (acc.clone(), acc.clone(), SessionKeys { aura: key.clone() })) + .map(|acc| { + ( + acc.clone(), + acc.clone(), + get_testnet_session_keys( + Into::<[u8; 32]>::into(acc.clone()).unchecked_into(), + ), + ) + }) .collect::>(), }, - polkadot_xcm: PolkadotXcmConfig { - safe_xcm_version: Some(SAFE_XCM_VERSION), - }, + polkadot_xcm: PolkadotXcmConfig { safe_xcm_version: Some(SAFE_XCM_VERSION) }, treasury: Default::default(), - sudo: SudoConfig { - key: Some(accounts.first().expect("").to_owned()), - }, - council: CouncilConfig { - members: initial_authorities.iter().map(|(acc, _)| acc).cloned().collect(), - phantom: Default::default(), - }, + sudo: SudoConfig { key: Some(sudo_account) }, + council: CouncilConfig { members: accounts.clone(), phantom: Default::default() }, technical_committee: TechnicalCommitteeConfig { - members: initial_authorities.iter().map(|(acc, _)| acc).cloned().collect(), + members: accounts.clone(), phantom: Default::default(), }, democracy: Default::default(), - did_lookup: Default::default(), vesting: VestingConfig { vesting: vec![] }, } } diff --git a/nodes/parachain/src/cli.rs b/nodes/parachain/src/cli.rs index 8e2d1efa7..e99d6dc94 100644 --- a/nodes/parachain/src/cli.rs +++ b/nodes/parachain/src/cli.rs @@ -103,15 +103,12 @@ pub struct RelayChainCli { impl RelayChainCli { /// Parse the relay chain CLI parameters using the para chain `Configuration`. pub fn new<'a>( - para_config: &sc_service::Configuration, relay_chain_args: impl Iterator, + para_config: &sc_service::Configuration, + relay_chain_args: impl Iterator, ) -> Self { let extension = crate::chain_spec::Extensions::try_get(&*para_config.chain_spec); let chain_id = extension.map(|e| e.relay_chain.clone()); let base_path = para_config.base_path.as_ref().map(|x| x.path().join("polkadot")); - Self { - base_path, - chain_id, - base: clap::Parser::parse_from(relay_chain_args), - } + Self { base_path, chain_id, base: clap::Parser::parse_from(relay_chain_args) } } } diff --git a/nodes/parachain/src/command.rs b/nodes/parachain/src/command.rs index 1451df942..3ce35ff93 100644 --- a/nodes/parachain/src/command.rs +++ b/nodes/parachain/src/command.rs @@ -23,8 +23,8 @@ use log::{info, warn}; use parity_scale_codec::Encode; use polimec_parachain_runtime::Block; use sc_cli::{ - ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, NetworkParams, Result, - RuntimeVersion, SharedParams, SubstrateCli, + ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, + NetworkParams, Result, RuntimeVersion, SharedParams, SubstrateCli, }; use sc_service::config::{BasePath, PrometheusConfig}; use sp_core::hexdisplay::HexDisplay; @@ -65,8 +65,8 @@ impl RuntimeResolver for PathBuf { let file = std::fs::File::open(self).expect("Failed to open file"); let reader = std::io::BufReader::new(file); - let chain_spec: EmptyChainSpecWithId = - sp_serializer::from_reader(reader).expect("Failed to read 'json' file with ChainSpec configuration"); + let chain_spec: EmptyChainSpecWithId = sp_serializer::from_reader(reader) + .expect("Failed to read 'json' file with ChainSpec configuration"); runtime(&chain_spec.id) } } @@ -92,16 +92,17 @@ fn load_spec(id: &str) -> std::result::Result, String> { Ok(match id { // Base runtime "base-rococo-local" => Box::new(chain_spec::base::get_local_base_chain_spec()?), - "base-polkadot" => Box::new(chain_spec::base::get_live_base_chain_spec()?), + "base-kusama" => Box::new(chain_spec::base::get_kusama_base_chain_spec()?), // Testnet runtime "polimec-rococo-local" => Box::new(chain_spec::testnet::get_chain_spec_dev()?), "polimec-polkadot" => Box::new(chain_spec::testnet::get_prod_chain_spec()?), - "polimec-polkadot-local" => Box::new(chain_spec::testnet::get_local_prod_chain_spec()?), // -- Fallback (generic chainspec) "" => { - log::warn!("No ChainSpec.id specified, so using default one, based on polimec-rococo-local"); + log::warn!( + "No ChainSpec.id specified, so using default one, based on polimec-rococo-local" + ); Box::new(chain_spec::testnet::get_chain_spec_dev()?) - } + }, // A custom chainspec path path => { let path: PathBuf = path.into(); @@ -110,7 +111,7 @@ fn load_spec(id: &str) -> std::result::Result, String> { Runtime::Testnet => Box::new(chain_spec::testnet::ChainSpec::from_json_file(path)?), Runtime::Base => Box::new(chain_spec::base::ChainSpec::from_json_file(path)?), } - } + }, }) } @@ -213,46 +214,51 @@ pub fn run() -> Result<()> { Some(Subcommand::BuildSpec(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) - } + }, Some(Subcommand::CheckBlock(cmd)) => { construct_async_run!(|components, cli, cmd, config| { Ok(cmd.run(components.client, components.import_queue)) }) - } + }, Some(Subcommand::ExportBlocks(cmd)) => { - construct_async_run!(|components, cli, cmd, config| Ok(cmd.run(components.client, config.database))) - } + construct_async_run!(|components, cli, cmd, config| Ok( + cmd.run(components.client, config.database) + )) + }, Some(Subcommand::ExportState(cmd)) => { - construct_async_run!(|components, cli, cmd, config| Ok(cmd.run(components.client, config.chain_spec))) - } + construct_async_run!(|components, cli, cmd, config| Ok( + cmd.run(components.client, config.chain_spec) + )) + }, Some(Subcommand::ImportBlocks(cmd)) => { construct_async_run!(|components, cli, cmd, config| { Ok(cmd.run(components.client, components.import_queue)) }) - } + }, Some(Subcommand::Revert(cmd)) => { construct_async_run!(|components, cli, cmd, config| { Ok(cmd.run(components.client, components.backend, None)) }) - } + }, Some(Subcommand::PurgeChain(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| { let polkadot_cli = RelayChainCli::new( &config, - [RelayChainCli::executable_name()] - .iter() - .chain(cli.relay_chain_args.iter()), + [RelayChainCli::executable_name()].iter().chain(cli.relay_chain_args.iter()), ); - let polkadot_config = - SubstrateCli::create_configuration(&polkadot_cli, &polkadot_cli, config.tokio_handle.clone()) - .map_err(|err| format!("Relay chain argument error: {}", err))?; + let polkadot_config = SubstrateCli::create_configuration( + &polkadot_cli, + &polkadot_cli, + config.tokio_handle.clone(), + ) + .map_err(|err| format!("Relay chain argument error: {}", err))?; cmd.run(config, polkadot_config) }) - } + }, Some(Subcommand::ExportGenesisState(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|_config| { @@ -260,40 +266,38 @@ pub fn run() -> Result<()> { let state_version = Cli::native_runtime_version(&spec).state_version(); cmd.run::(&*spec, state_version) }) - } + }, Some(Subcommand::ExportGenesisWasm(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|_config| { let spec = cli.load_spec(&cmd.shared_params.chain.clone().unwrap_or_default())?; cmd.run(&*spec) }) - } + }, Some(Subcommand::Benchmark(cmd)) => { let runner = cli.create_runner(cmd)?; // Switch on the concrete benchmark sub-command- match cmd { - BenchmarkCmd::Pallet(cmd) => { + BenchmarkCmd::Pallet(cmd) => if cfg!(feature = "runtime-benchmarks") { runner.sync_run(|config| cmd.run::(config)) } else { Err("Benchmarking wasn't enabled when building the node. \ You can enable it with `--features runtime-benchmarks`." .into()) - } - } + }, BenchmarkCmd::Block(cmd) => runner.sync_run(|config| { let partials = new_partial(&config)?; cmd.run(partials.client) }), #[cfg(not(feature = "runtime-benchmarks"))] - BenchmarkCmd::Storage(_) => { + BenchmarkCmd::Storage(_) => return Err(sc_cli::Error::Input( "Compile with --features=runtime-benchmarks \ to enable storage benchmarks." .into(), ) - .into()) - } + .into()), #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { let partials = new_partial(&config)?; @@ -301,15 +305,14 @@ pub fn run() -> Result<()> { let storage = partials.backend.expose_storage(); cmd.run(config, partials.client.clone(), db, storage) }), - BenchmarkCmd::Machine(cmd) => { - runner.sync_run(|config| cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone())) - } + BenchmarkCmd::Machine(cmd) => + runner.sync_run(|config| cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone())), // NOTE: this allows the Client to leniently implement // new benchmark commands without requiring a companion MR. #[allow(unreachable_patterns)] _ => Err("Benchmarking sub-command unsupported".into()), } - } + }, #[cfg(feature = "try-runtime")] Some(Subcommand::TryRuntime(cmd)) => { let runner = cli.create_runner(cmd)?; @@ -322,16 +325,14 @@ pub fn run() -> Result<()> { // grab the task manager. let registry = &runner.config().prometheus_config.as_ref().map(|cfg| &cfg.registry); - let task_manager = sc_service::TaskManager::new(runner.config().tokio_handle.clone(), *registry) - .map_err(|e| format!("Error: {:?}", e))?; + let task_manager = + sc_service::TaskManager::new(runner.config().tokio_handle.clone(), *registry) + .map_err(|e| format!("Error: {:?}", e))?; runner.async_run(|_| { - Ok(( - cmd.run::>(), - task_manager, - )) + Ok((cmd.run::>(), task_manager)) }) - } + }, #[cfg(not(feature = "try-runtime"))] Some(Subcommand::TryRuntime) => Err("Try-runtime was not enabled when building the node. \ You can enable it with `--features try-runtime`." @@ -394,7 +395,7 @@ pub fn run() -> Result<()> { .map(|r| r.0) .map_err(Into::into) }) - } + }, } } @@ -453,13 +454,19 @@ impl CliConfiguration for RelayChainCli { } fn prometheus_config( - &self, default_listen_port: u16, chain_spec: &Box, + &self, + default_listen_port: u16, + chain_spec: &Box, ) -> Result> { self.base.base.prometheus_config(default_listen_port, chain_spec) } fn init( - &self, _support_url: &String, _impl_version: &String, _logger_hook: F, _config: &sc_service::Configuration, + &self, + _support_url: &String, + _impl_version: &String, + _logger_hook: F, + _config: &sc_service::Configuration, ) -> Result<()> where F: FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration), @@ -470,11 +477,7 @@ impl CliConfiguration for RelayChainCli { fn chain_id(&self, is_dev: bool) -> Result { let chain_id = self.base.base.chain_id(is_dev)?; - Ok(if chain_id.is_empty() { - self.chain_id.clone().unwrap_or_default() - } else { - chain_id - }) + Ok(if chain_id.is_empty() { self.chain_id.clone().unwrap_or_default() } else { chain_id }) } fn role(&self, is_dev: bool) -> Result { @@ -521,7 +524,10 @@ impl CliConfiguration for RelayChainCli { self.base.base.announce_block() } - fn telemetry_endpoints(&self, chain_spec: &Box) -> Result> { + fn telemetry_endpoints( + &self, + chain_spec: &Box, + ) -> Result> { self.base.base.telemetry_endpoints(chain_spec) } diff --git a/nodes/parachain/src/rpc.rs b/nodes/parachain/src/rpc.rs index ae5a4ed96..6cff4195a 100644 --- a/nodes/parachain/src/rpc.rs +++ b/nodes/parachain/src/rpc.rs @@ -43,7 +43,9 @@ pub struct FullDeps { } /// Instantiate all RPC extensions. -pub fn create_full(deps: FullDeps) -> Result> +pub fn create_full( + deps: FullDeps, +) -> Result> where C: ProvideRuntimeApi + HeaderBackend @@ -61,11 +63,7 @@ where use substrate_frame_rpc_system::{System, SystemApiServer}; let mut module = RpcExtension::new(()); - let FullDeps { - client, - pool, - deny_unsafe, - } = deps; + let FullDeps { client, pool, deny_unsafe } = deps; module.merge(System::new(client.clone(), pool, deny_unsafe).into_rpc())?; module.merge(TransactionPayment::new(client).into_rpc())?; diff --git a/nodes/parachain/src/service.rs b/nodes/parachain/src/service.rs index 49dd30d28..352435bc0 100644 --- a/nodes/parachain/src/service.rs +++ b/nodes/parachain/src/service.rs @@ -25,10 +25,12 @@ use polimec_parachain_runtime::{opaque::Block, Hash, RuntimeApi}; // Cumulus Imports use cumulus_client_consensus_aura::{AuraConsensus, BuildAuraConsensusParams, SlotProportion}; -use cumulus_client_consensus_common::{ParachainBlockImport as TParachainBlockImport, ParachainConsensus}; +use cumulus_client_consensus_common::{ + ParachainBlockImport as TParachainBlockImport, ParachainConsensus, +}; use cumulus_client_service::{ - build_network, build_relay_chain_interface, prepare_node_config, start_collator, start_full_node, - BuildNetworkParams, StartCollatorParams, StartFullNodeParams, + build_network, build_relay_chain_interface, prepare_node_config, start_collator, + start_full_node, BuildNetworkParams, StartCollatorParams, StartFullNodeParams, }; use cumulus_primitives_core::ParaId; use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface}; @@ -102,11 +104,12 @@ pub fn new_partial( config.runtime_cache_size, ); - let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( - config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; + let (client, backend, keystore_container, task_manager) = + sc_service::new_full_parts::( + config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, + )?; let client = Arc::new(client); let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle()); @@ -151,8 +154,11 @@ pub fn new_partial( /// This is the actual implementation that is abstract over the executor and the runtime api. #[sc_tracing::logging::prefix_logs_with("Parachain")] async fn start_node_impl( - parachain_config: Configuration, polkadot_config: Configuration, collator_options: CollatorOptions, - para_id: ParaId, hwbench: Option, + parachain_config: Configuration, + polkadot_config: Configuration, + collator_options: CollatorOptions, + para_id: ParaId, + hwbench: Option, ) -> sc_service::error::Result<(TaskManager, Arc)> { let parachain_config = prepare_node_config(parachain_config); @@ -183,16 +189,17 @@ async fn start_node_impl( let transaction_pool = params.transaction_pool.clone(); let import_queue_service = params.import_queue.service(); - let (network, system_rpc_tx, tx_handler_controller, start_network) = build_network(BuildNetworkParams { - parachain_config: ¶chain_config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - para_id, - spawn_handle: task_manager.spawn_handle(), - relay_chain_interface: relay_chain_interface.clone(), - import_queue: params.import_queue, - }) - .await?; + let (network, system_rpc_tx, tx_handler_controller, start_network) = + build_network(BuildNetworkParams { + parachain_config: ¶chain_config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + para_id, + spawn_handle: task_manager.spawn_handle(), + relay_chain_interface: relay_chain_interface.clone(), + import_queue: params.import_queue, + }) + .await?; if parachain_config.offchain_worker.enabled { sc_service::build_offchain_workers( @@ -238,7 +245,9 @@ async fn start_node_impl( // in there and swapping out the requirements for your own are probably a good idea. The // requirements for a para-chain are dictated by its relay-chain. if !SUBSTRATE_REFERENCE_HARDWARE.check_hardware(&hwbench) && validator { - log::warn!("⚠️ The hardware does not meet the minimal requirements for role 'Authority'."); + log::warn!( + "⚠️ The hardware does not meet the minimal requirements for role 'Authority'." + ); } if let Some(ref mut telemetry) = telemetry { @@ -316,39 +325,52 @@ async fn start_node_impl( /// Build the import queue for the parachain runtime. fn build_import_queue( - client: Arc, block_import: ParachainBlockImport, config: &Configuration, - telemetry: Option, task_manager: &TaskManager, + client: Arc, + block_import: ParachainBlockImport, + config: &Configuration, + telemetry: Option, + task_manager: &TaskManager, ) -> Result, sc_service::Error> { let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; - cumulus_client_consensus_aura::import_queue::( - cumulus_client_consensus_aura::ImportQueueParams { - block_import, - client, - create_inherent_data_providers: move |_, _| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + cumulus_client_consensus_aura::import_queue::< + sp_consensus_aura::sr25519::AuthorityPair, + _, + _, + _, + _, + _, + >(cumulus_client_consensus_aura::ImportQueueParams { + block_import, + client, + create_inherent_data_providers: move |_, _| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, slot_duration, ); - Ok((slot, timestamp)) - }, - registry: config.prometheus_registry(), - spawner: &task_manager.spawn_essential_handle(), - telemetry, + Ok((slot, timestamp)) }, - ) + registry: config.prometheus_registry(), + spawner: &task_manager.spawn_essential_handle(), + telemetry, + }) .map_err(Into::into) } fn build_consensus( - client: Arc, block_import: ParachainBlockImport, prometheus_registry: Option<&Registry>, - telemetry: Option, task_manager: &TaskManager, + client: Arc, + block_import: ParachainBlockImport, + prometheus_registry: Option<&Registry>, + telemetry: Option, + task_manager: &TaskManager, relay_chain_interface: Arc, transaction_pool: Arc>, - sync_oracle: Arc>, keystore: SyncCryptoStorePtr, force_authoring: bool, + sync_oracle: Arc>, + keystore: SyncCryptoStorePtr, + force_authoring: bool, para_id: ParaId, ) -> Result>, sc_service::Error> { let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; @@ -366,13 +388,14 @@ fn build_consensus( create_inherent_data_providers: move |_, (relay_parent, validation_data)| { let relay_chain_interface = relay_chain_interface.clone(); async move { - let parachain_inherent = cumulus_primitives_parachain_inherent::ParachainInherentData::create_at( - relay_parent, - &relay_chain_interface, - &validation_data, - para_id, - ) - .await; + let parachain_inherent = + cumulus_primitives_parachain_inherent::ParachainInherentData::create_at( + relay_parent, + &relay_chain_interface, + &validation_data, + para_id, + ) + .await; let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( @@ -381,7 +404,9 @@ fn build_consensus( ); let parachain_inherent = parachain_inherent.ok_or_else(|| { - Box::::from("Failed to create parachain inherent") + Box::::from( + "Failed to create parachain inherent", + ) })?; Ok((slot, timestamp, parachain_inherent)) } @@ -400,21 +425,16 @@ fn build_consensus( telemetry, }; - Ok(AuraConsensus::build::< - sp_consensus_aura::sr25519::AuthorityPair, - _, - _, - _, - _, - _, - _, - >(params)) + Ok(AuraConsensus::build::(params)) } /// Start a parachain node. pub async fn start_parachain_node( - parachain_config: Configuration, polkadot_config: Configuration, collator_options: CollatorOptions, - para_id: ParaId, hwbench: Option, + parachain_config: Configuration, + polkadot_config: Configuration, + collator_options: CollatorOptions, + para_id: ParaId, + hwbench: Option, ) -> sc_service::error::Result<(TaskManager, Arc)> { start_node_impl(parachain_config, polkadot_config, collator_options, para_id, hwbench).await } diff --git a/nodes/standalone/src/benchmarking.rs b/nodes/standalone/src/benchmarking.rs index 4b4a86d95..9ecb50ae6 100644 --- a/nodes/standalone/src/benchmarking.rs +++ b/nodes/standalone/src/benchmarking.rs @@ -115,7 +115,10 @@ impl frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder { /// /// Note: Should only be used for benchmarking. pub fn create_benchmark_extrinsic( - client: &FullClient, sender: sp_core::sr25519::Pair, call: runtime::RuntimeCall, nonce: u32, + client: &FullClient, + sender: sp_core::sr25519::Pair, + call: runtime::RuntimeCall, + nonce: u32, ) -> runtime::UncheckedExtrinsic { let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); let best_hash = client.chain_info().best_hash; diff --git a/nodes/standalone/src/chain_spec.rs b/nodes/standalone/src/chain_spec.rs index ebfc0ddee..6db1a7883 100644 --- a/nodes/standalone/src/chain_spec.rs +++ b/nodes/standalone/src/chain_spec.rs @@ -15,7 +15,7 @@ // along with this program. If not, see . use polimec_standalone_runtime::{ - AccountId, BalancesConfig, CredentialsConfig, GenesisConfig, SessionConfig, Signature, SudoConfig, SystemConfig, + AccountId, BalancesConfig, GenesisConfig, SessionConfig, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use sc_service::{ChainType, Properties}; @@ -153,7 +153,9 @@ pub fn local_testnet_config() -> Result { /// Configure initial storage state for FRAME modules. fn testnet_genesis( - wasm_binary: &[u8], initial_authorities: Vec<(AccountId, AuraId, GrandpaId)>, root_key: AccountId, + wasm_binary: &[u8], + initial_authorities: Vec<(AccountId, AuraId, GrandpaId)>, + root_key: AccountId, endowed_accounts: Vec, ) -> GenesisConfig { GenesisConfig { @@ -175,12 +177,6 @@ fn testnet_genesis( council: Default::default(), technical_committee: Default::default(), democracy: Default::default(), - credentials: CredentialsConfig { - issuers: endowed_accounts.clone(), - retails: endowed_accounts.clone(), - professionals: endowed_accounts.clone(), - institutionals: endowed_accounts.clone(), - }, session: SessionConfig { keys: initial_authorities .iter() diff --git a/nodes/standalone/src/command.rs b/nodes/standalone/src/command.rs index d9145c6aa..7b4d488f6 100644 --- a/nodes/standalone/src/command.rs +++ b/nodes/standalone/src/command.rs @@ -55,7 +55,8 @@ impl SubstrateCli for Cli { Ok(match id { "dev" => Box::new(chain_spec::development_config()?), "" | "local" => Box::new(chain_spec::local_testnet_config()?), - path => Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?), + path => + Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?), }) } @@ -73,69 +74,53 @@ pub fn run() -> sc_cli::Result<()> { Some(Subcommand::BuildSpec(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) - } + }, Some(Subcommand::CheckBlock(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { - client, - task_manager, - import_queue, - .. - } = service::new_partial(&config)?; + let PartialComponents { client, task_manager, import_queue, .. } = + service::new_partial(&config)?; Ok((cmd.run(client, import_queue), task_manager)) }) - } + }, Some(Subcommand::ExportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { - client, task_manager, .. - } = service::new_partial(&config)?; + let PartialComponents { client, task_manager, .. } = service::new_partial(&config)?; Ok((cmd.run(client, config.database), task_manager)) }) - } + }, Some(Subcommand::ExportState(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { - client, task_manager, .. - } = service::new_partial(&config)?; + let PartialComponents { client, task_manager, .. } = service::new_partial(&config)?; Ok((cmd.run(client, config.chain_spec), task_manager)) }) - } + }, Some(Subcommand::ImportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { - client, - task_manager, - import_queue, - .. - } = service::new_partial(&config)?; + let PartialComponents { client, task_manager, import_queue, .. } = + service::new_partial(&config)?; Ok((cmd.run(client, import_queue), task_manager)) }) - } + }, Some(Subcommand::PurgeChain(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| cmd.run(config.database)) - } + }, Some(Subcommand::Revert(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { - client, - task_manager, - backend, - .. - } = service::new_partial(&config)?; + let PartialComponents { client, task_manager, backend, .. } = + service::new_partial(&config)?; let aux_revert = Box::new(|client, _, blocks| { sc_finality_grandpa::revert(client, blocks)?; Ok(()) }); Ok((cmd.run(client, backend, Some(aux_revert)), task_manager)) }) - } + }, Some(Subcommand::Benchmark(cmd)) => { let runner = cli.create_runner(cmd)?; @@ -145,35 +130,45 @@ pub fn run() -> sc_cli::Result<()> { match cmd { BenchmarkCmd::Pallet(cmd) => { if !cfg!(feature = "runtime-benchmarks") { - return Err("Runtime benchmarking wasn't enabled when building the node. \ + return Err( + "Runtime benchmarking wasn't enabled when building the node. \ You can enable it with `--features runtime-benchmarks`." - .into()); + .into(), + ) } cmd.run::(config) - } + }, BenchmarkCmd::Block(cmd) => { let PartialComponents { client, .. } = service::new_partial(&config)?; cmd.run(client) - } + }, #[cfg(not(feature = "runtime-benchmarks"))] - BenchmarkCmd::Storage(_) => { - Err("Storage benchmarking can be enabled with `--features runtime-benchmarks`.".into()) - } + BenchmarkCmd::Storage(_) => Err( + "Storage benchmarking can be enabled with `--features runtime-benchmarks`." + .into(), + ), #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => { - let PartialComponents { client, backend, .. } = service::new_partial(&config)?; + let PartialComponents { client, backend, .. } = + service::new_partial(&config)?; let db = backend.expose_db(); let storage = backend.expose_storage(); cmd.run(config, client, db, storage) - } + }, BenchmarkCmd::Overhead(cmd) => { let PartialComponents { client, .. } = service::new_partial(&config)?; let ext_builder = RemarkBuilder::new(client.clone()); - cmd.run(config, client, inherent_benchmark_data()?, Vec::new(), &ext_builder) - } + cmd.run( + config, + client, + inherent_benchmark_data()?, + Vec::new(), + &ext_builder, + ) + }, BenchmarkCmd::Extrinsic(cmd) => { let PartialComponents { client, .. } = service::new_partial(&config)?; // Register the *Remark* and *TKA* builders. @@ -187,11 +182,12 @@ pub fn run() -> sc_cli::Result<()> { ]); cmd.run(client, inherent_benchmark_data()?, Vec::new(), &ext_factory) - } - BenchmarkCmd::Machine(cmd) => cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone()), + }, + BenchmarkCmd::Machine(cmd) => + cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone()), } }) - } + }, #[cfg(feature = "try-runtime")] Some(Subcommand::TryRuntime(cmd)) => { let runner = cli.create_runner(cmd)?; @@ -199,11 +195,12 @@ pub fn run() -> sc_cli::Result<()> { // we don't need any of the components of new_partial, just a runtime, or a task // manager to do `async_run`. let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); - let task_manager = sc_service::TaskManager::new(config.tokio_handle.clone(), registry) - .map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?; + let task_manager = + sc_service::TaskManager::new(config.tokio_handle.clone(), registry) + .map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?; Ok((cmd.run::(config), task_manager)) }) - } + }, #[cfg(not(feature = "try-runtime"))] Some(Subcommand::TryRuntime) => Err("TryRuntime wasn't enabled when building the node. \ You can enable it with `--features try-runtime`." @@ -211,11 +208,12 @@ pub fn run() -> sc_cli::Result<()> { Some(Subcommand::ChainInfo(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| cmd.run::(&config)) - } + }, None => { let runner = cli.create_runner(&cli.run)?; - runner - .run_node_until_exit(|config| async move { service::new_full(config).map_err(sc_cli::Error::Service) }) - } + runner.run_node_until_exit(|config| async move { + service::new_full(config).map_err(sc_cli::Error::Service) + }) + }, } } diff --git a/nodes/standalone/src/rpc.rs b/nodes/standalone/src/rpc.rs index c0051d536..d1cd753fd 100644 --- a/nodes/standalone/src/rpc.rs +++ b/nodes/standalone/src/rpc.rs @@ -43,7 +43,9 @@ pub struct FullDeps { } /// Instantiate all full RPC extensions. -pub fn create_full(deps: FullDeps) -> Result, Box> +pub fn create_full( + deps: FullDeps, +) -> Result, Box> where C: ProvideRuntimeApi, C: HeaderBackend + HeaderMetadata + 'static, @@ -57,11 +59,7 @@ where use substrate_frame_rpc_system::{System, SystemApiServer}; let mut module = RpcModule::new(()); - let FullDeps { - client, - pool, - deny_unsafe, - } = deps; + let FullDeps { client, pool, deny_unsafe } = deps; module.merge(System::new(client.clone(), pool.clone(), deny_unsafe).into_rpc())?; module.merge(TransactionPayment::new(client).into_rpc())?; diff --git a/nodes/standalone/src/service.rs b/nodes/standalone/src/service.rs index e7297d0f7..b92c2e81d 100644 --- a/nodes/standalone/src/service.rs +++ b/nodes/standalone/src/service.rs @@ -47,7 +47,8 @@ impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { } } -pub(crate) type FullClient = sc_service::TFullClient>; +pub(crate) type FullClient = + sc_service::TFullClient>; type FullBackend = sc_service::TFullBackend; type FullSelectChain = sc_consensus::LongestChain; @@ -61,7 +62,12 @@ pub fn new_partial( sc_consensus::DefaultImportQueue, sc_transaction_pool::FullPool, ( - sc_finality_grandpa::GrandpaBlockImport, + sc_finality_grandpa::GrandpaBlockImport< + FullBackend, + Block, + FullClient, + FullSelectChain, + >, sc_finality_grandpa::LinkHalf, Option, ), @@ -69,7 +75,7 @@ pub fn new_partial( ServiceError, > { if config.keystore_remote.is_some() { - return Err(ServiceError::Other("Remote Keystores are not supported.".into())); + return Err(ServiceError::Other("Remote Keystores are not supported.".into())) } let telemetry = config @@ -90,11 +96,12 @@ pub fn new_partial( config.runtime_cache_size, ); - let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( - config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; + let (client, backend, keystore_container, task_manager) = + sc_service::new_full_parts::( + config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, + )?; let client = Arc::new(client); let telemetry = telemetry.map(|(worker, telemetry)| { @@ -121,26 +128,27 @@ pub fn new_partial( let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { - block_import: grandpa_block_import.clone(), - justification_import: Some(Box::new(grandpa_block_import.clone())), - client: client.clone(), - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + let import_queue = + sc_consensus_aura::import_queue::(ImportQueueParams { + block_import: grandpa_block_import.clone(), + justification_import: Some(Box::new(grandpa_block_import.clone())), + client: client.clone(), + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, slot_duration, ); - Ok((slot, timestamp)) - }, - spawner: &task_manager.spawn_essential_handle(), - registry: config.prometheus_registry(), - check_for_equivocation: Default::default(), - telemetry: telemetry.as_ref().map(|x| x.handle()), - compatibility_mode: Default::default(), - })?; + Ok((slot, timestamp)) + }, + spawner: &task_manager.spawn_essential_handle(), + registry: config.prometheus_registry(), + check_for_equivocation: Default::default(), + telemetry: telemetry.as_ref().map(|x| x.handle()), + compatibility_mode: Default::default(), + })?; Ok(sc_service::PartialComponents { client, @@ -177,12 +185,11 @@ pub fn new_full(mut config: Configuration) -> Result if let Some(url) = &config.keystore_remote { match remote_keystore(url) { Ok(k) => keystore_container.set_remote_keystore(k), - Err(e) => { + Err(e) => return Err(ServiceError::Other(format!( "Error hooking up remote keystore for {}: {}", url, e - ))) - } + ))), }; } let grandpa_protocol_name = sc_finality_grandpa::protocol_standard_name( @@ -193,9 +200,7 @@ pub fn new_full(mut config: Configuration) -> Result config .network .extra_sets - .push(sc_finality_grandpa::grandpa_peers_set_config( - grandpa_protocol_name.clone(), - )); + .push(sc_finality_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone())); let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), @@ -214,7 +219,12 @@ pub fn new_full(mut config: Configuration) -> Result })?; if config.offchain_worker.enabled { - sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); + sc_service::build_offchain_workers( + &config, + task_manager.spawn_handle(), + client.clone(), + network.clone(), + ); } let role = config.role.clone(); @@ -229,11 +239,8 @@ pub fn new_full(mut config: Configuration) -> Result let pool = transaction_pool.clone(); Box::new(move |deny_unsafe, _| { - let deps = crate::rpc::FullDeps { - client: client.clone(), - pool: pool.clone(), - deny_unsafe, - }; + let deps = + crate::rpc::FullDeps { client: client.clone(), pool: pool.clone(), deny_unsafe }; crate::rpc::create_full(deps).map_err(Into::into) }) }; @@ -263,32 +270,34 @@ pub fn new_full(mut config: Configuration) -> Result let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - let aura = sc_consensus_aura::start_aura::(StartAuraParams { - slot_duration, - client, - select_chain, - block_import, - proposer_factory, - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + let aura = sc_consensus_aura::start_aura::( + StartAuraParams { + slot_duration, + client, + select_chain, + block_import, + proposer_factory, + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, slot_duration, ); - Ok((slot, timestamp)) + Ok((slot, timestamp)) + }, + force_authoring, + backoff_authoring_blocks, + keystore: keystore_container.sync_keystore(), + sync_oracle: network.clone(), + justification_sync_link: network.clone(), + block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), + max_block_proposal_slot_portion: None, + telemetry: telemetry.as_ref().map(|x| x.handle()), + compatibility_mode: Default::default(), }, - force_authoring, - backoff_authoring_blocks, - keystore: keystore_container.sync_keystore(), - sync_oracle: network.clone(), - justification_sync_link: network.clone(), - block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), - max_block_proposal_slot_portion: None, - telemetry: telemetry.as_ref().map(|x| x.handle()), - compatibility_mode: Default::default(), - })?; + )?; // the AURA authoring task is considered essential, i.e. if it // fails we take down the service with it. @@ -300,11 +309,8 @@ pub fn new_full(mut config: Configuration) -> Result if enable_grandpa { // if the node isn't actively participating in consensus then it doesn't // need a keystore, regardless of which protocol we use below. - let keystore = if role.is_authority() { - Some(keystore_container.sync_keystore()) - } else { - None - }; + let keystore = + if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None }; let grandpa_config = sc_finality_grandpa::Config { // FIXME #1578 make this available through chainspec diff --git a/pallets/funding/Cargo.toml b/pallets/funding/Cargo.toml index 1125957c9..88731b9bb 100644 --- a/pallets/funding/Cargo.toml +++ b/pallets/funding/Cargo.toml @@ -22,7 +22,6 @@ frame-system.workspace = true sp-std.workspace = true sp-runtime.workspace = true sp-arithmetic.workspace = true -polimec-traits.workspace = true # Benchmarking dependencies frame-benchmarking = { workspace = true, optional = true } @@ -46,7 +45,6 @@ std = [ "frame-system/std", "pallet-assets/std", "pallet-balances/std", - "polimec-traits/std", "frame-benchmarking?/std", ] runtime-benchmarks = [ diff --git a/pallets/funding/src/benchmarking.rs b/pallets/funding/src/benchmarking.rs index 2e789b8c7..e443e7cb3 100644 --- a/pallets/funding/src/benchmarking.rs +++ b/pallets/funding/src/benchmarking.rs @@ -68,7 +68,9 @@ fn get_events() -> frame_benchmarking::Vec<>() } -fn create_default_project(id: Option) -> (T::ProjectIdParameter, T::AccountId, ProjectMetadataOf) { +fn create_default_project( + id: Option, +) -> (T::ProjectIdParameter, T::AccountId, ProjectMetadataOf) { let issuer: T::AccountId = account::("Alice", 1, 1); let project_id_parameter = id.unwrap_or(0); let project_id = T::BenchmarkHelper::create_project_id_parameter(project_id_parameter); @@ -77,9 +79,13 @@ fn create_default_project(id: Option) -> (T::ProjectIdParameter, (project_id, issuer, project) } -fn create_default_minted_project(id: Option) -> (T::ProjectIdParameter, T::AccountId) { +fn create_default_minted_project( + id: Option, +) -> (T::ProjectIdParameter, T::AccountId) { let (project_id, issuer, project) = create_default_project::(id); - assert!(PolimecFunding::::create(SystemOrigin::Signed(issuer.clone()).into(), project).is_ok()); + assert!( + PolimecFunding::::create(SystemOrigin::Signed(issuer.clone()).into(), project).is_ok() + ); (project_id, issuer) } @@ -89,7 +95,9 @@ pub fn run_to_block(n: T::BlockNumber) { crate::Pallet::::on_finalize(frame_system::Pallet::::block_number()); frame_system::Pallet::::on_finalize(frame_system::Pallet::::block_number()); crate::Pallet::::on_idle(frame_system::Pallet::::block_number(), max_weight); - frame_system::Pallet::::set_block_number(frame_system::Pallet::::block_number() + One::one()); + frame_system::Pallet::::set_block_number( + frame_system::Pallet::::block_number() + One::one(), + ); frame_system::Pallet::::on_initialize(frame_system::Pallet::::block_number()); crate::Pallet::::on_initialize(frame_system::Pallet::::block_number()); crate::Pallet::::on_idle(frame_system::Pallet::::block_number(), max_weight); diff --git a/pallets/funding/src/functions.rs b/pallets/funding/src/functions.rs index 2e0e44c8d..9c2e4e839 100644 --- a/pallets/funding/src/functions.rs +++ b/pallets/funding/src/functions.rs @@ -48,7 +48,10 @@ impl Pallet { /// # Next step /// The issuer will call an extrinsic to start the evaluation round of the project. /// [`do_evaluation_start`](Self::do_evaluation_start) will be executed. - pub fn do_create(issuer: T::AccountId, project: ProjectMetadataOf) -> Result<(), DispatchError> { + pub fn do_create( + issuer: T::AccountId, + project: ProjectMetadataOf, + ) -> Result<(), DispatchError> { // TODO: Probably the issuers don't want to sell all of their tokens. Is there some logic for this? // also even if an issuer wants to sell all their tokens, they could target a lower amount than that to consider it a success // * Get variables * @@ -63,9 +66,10 @@ impl Pallet { if let Err(error) = project.validity_check() { return match error { ValidityError::PriceTooLow => Err(Error::::PriceTooLow.into()), - ValidityError::ParticipantsSizeError => Err(Error::::ParticipantsSizeError.into()), + ValidityError::ParticipantsSizeError => + Err(Error::::ParticipantsSizeError.into()), ValidityError::TicketSizeError => Err(Error::::TicketSizeError.into()), - }; + } } // * Calculate new variables * @@ -75,7 +79,10 @@ impl Pallet { fundraising_target, project_status: ProjectStatus::Application, phase_transition_points: PhaseTransitionPoints { - application: BlockNumberPair::new(Some(>::block_number()), None), + application: BlockNumberPair::new( + Some(>::block_number()), + None, + ), evaluation: BlockNumberPair::new(None, None), auction_initialize_period: BlockNumberPair::new(None, None), english_auction: BlockNumberPair::new(None, None), @@ -121,7 +128,8 @@ impl Pallet { /// to the next round by `on_initialize` using [`do_evaluation_end`](Self::do_evaluation_end) pub fn do_evaluation_start(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; let now = >::block_number(); @@ -131,10 +139,7 @@ impl Pallet { Error::::ProjectNotInApplicationRound ); ensure!(!project_info.is_frozen, Error::::ProjectAlreadyFrozen); - ensure!( - project.offchain_information_hash.is_some(), - Error::::MetadataNotProvided - ); + ensure!(project.offchain_information_hash.is_some(), Error::::MetadataNotProvided); // * Calculate new variables * let evaluation_end_block = now + T::EvaluationDuration::get(); @@ -191,7 +196,8 @@ impl Pallet { /// unbonds the evaluators funds. pub fn do_evaluation_end(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); let evaluation_end_block = project_info .phase_transition_points @@ -285,7 +291,8 @@ impl Pallet { /// [`do_candle_auction`](Self::do_candle_auction). pub fn do_english_auction(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); let auction_initialize_period_start_block = project_info .phase_transition_points @@ -362,7 +369,8 @@ impl Pallet { /// by calling [`do_community_funding`](Self::do_community_funding). pub fn do_candle_auction(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); let english_end_block = project_info .phase_transition_points @@ -424,7 +432,8 @@ impl Pallet { /// starts the remainder round, where anyone can buy at that price point. pub fn do_community_funding(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); let auction_candle_start_block = project_info .phase_transition_points @@ -438,24 +447,27 @@ impl Pallet { .ok_or(Error::::FieldIsNone)?; // * Validity checks * - ensure!( - now > auction_candle_end_block, - Error::::TooEarlyForCommunityRoundStart - ); + ensure!(now > auction_candle_end_block, Error::::TooEarlyForCommunityRoundStart); ensure!( project_info.project_status == ProjectStatus::AuctionRound(AuctionPhase::Candle), Error::::ProjectNotInCandleAuctionRound ); // * Calculate new variables * - let end_block = Self::select_random_block(auction_candle_start_block, auction_candle_end_block); + let end_block = + Self::select_random_block(auction_candle_start_block, auction_candle_end_block); let community_start_block = now + 1u32.into(); let community_end_block = now + T::CommunityFundingDuration::get(); // * Update Storage * - Self::calculate_weighted_average_price(project_id, end_block, project_info.fundraising_target)?; + Self::calculate_weighted_average_price( + project_id, + end_block, + project_info.fundraising_target, + )?; // Get info again after updating it with new price. - let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; project_info.phase_transition_points.random_candle_ending = Some(end_block); project_info .phase_transition_points @@ -497,7 +509,8 @@ impl Pallet { /// [`do_end_funding`](Self::do_end_funding). pub fn do_remainder_funding(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); let community_end_block = project_info .phase_transition_points @@ -524,7 +537,10 @@ impl Pallet { project_info.project_status = ProjectStatus::RemainderRound; ProjectsDetails::::insert(project_id, project_info); // Schedule for automatic transition by `on_initialize` - Self::add_to_update_store(remainder_end_block + 1u32.into(), (&project_id, UpdateType::FundingEnd)); + Self::add_to_update_store( + remainder_end_block + 1u32.into(), + (&project_id, UpdateType::FundingEnd), + ); // * Emit events * Self::deposit_event(Event::::RemainderFundingStarted { project_id }); @@ -564,10 +580,12 @@ impl Pallet { /// If **unsuccessful**, users every user should have their PLMC vesting unbonded. pub fn do_end_funding(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); // TODO: PLMC-149 Check if make sense to set the admin as T::fund_account_id(project_id) - let issuer = ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; + let issuer = + ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; let project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; let token_information = project.token_information; let remaining_cts = project_info.remaining_contribution_tokens; @@ -622,7 +640,8 @@ impl Pallet { /// WIP pub fn do_ready_to_launch(project_id: &T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; // * Validity checks * ensure!( @@ -653,17 +672,18 @@ impl Pallet { /// * [`ProjectsDetails`] - Check that the project is not frozen /// * [`ProjectsMetadata`] - Update the metadata hash pub fn do_edit_metadata( - issuer: T::AccountId, project_id: T::ProjectIdentifier, project_metadata_hash: T::Hash, + issuer: T::AccountId, + project_id: T::ProjectIdentifier, + project_metadata_hash: T::Hash, ) -> Result<(), DispatchError> { // * Get variables * - let mut project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; - let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project = + ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; + let project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; // * Validity checks * - ensure!( - ProjectsIssuers::::get(project_id) == Some(issuer), - Error::::NotAllowed - ); + ensure!(ProjectsIssuers::::get(project_id) == Some(issuer), Error::::NotAllowed); ensure!(!project_info.is_frozen, Error::::Frozen); ensure!( !Images::::contains_key(project_metadata_hash), @@ -701,11 +721,15 @@ impl Pallet { /// * [`EvaluationBonds`] - Update the storage with the evaluators bond, by either increasing an existing /// one, or appending a new bond pub fn do_evaluation_bond( - evaluator: T::AccountId, project_id: T::ProjectIdentifier, amount: BalanceOf, + evaluator: T::AccountId, + project_id: T::ProjectIdentifier, + amount: BalanceOf, ) -> Result<(), DispatchError> { // * Get variables * - let project_issuer = ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; - let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let project_issuer = + ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; + let project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; // * Validity checks * // TODO: PLMC-133. Replace this when this PR is merged: https://github.com/KILTprotocol/kilt-node/pull/448 @@ -730,7 +754,7 @@ impl Pallet { bond.amount += amount; T::NativeCurrency::reserve_named(&BondType::Evaluation, &evaluator, amount) .map_err(|_| Error::::InsufficientBalance)?; - } + }, None => { // If the user has not bonded yet, create a new bond *maybe_bond = Some(EvaluationBond { @@ -743,7 +767,7 @@ impl Pallet { // Reserve the required PLMC T::NativeCurrency::reserve_named(&BondType::Evaluation, &evaluator, amount) .map_err(|_| Error::::InsufficientBalance)?; - } + }, } Self::deposit_event(Event::::FundsBonded { project_id, @@ -754,11 +778,7 @@ impl Pallet { })?; // * Emit events * - Self::deposit_event(Event::::FundsBonded { - project_id, - amount, - bonder: evaluator, - }); + Self::deposit_event(Event::::FundsBonded { project_id, amount, bonder: evaluator }); Ok(()) } @@ -772,10 +792,12 @@ impl Pallet { /// * [`ProjectsDetails`] - Check that the project is in the evaluation failed stage /// * [`EvaluationBonds`] - Remove the bond from storage pub fn do_failed_evaluation_unbond_for( - bond: EvaluationBond, releaser: T::AccountId, + bond: EvaluationBond, + releaser: T::AccountId, ) -> Result<(), DispatchError> { // * Get variables * - let project_info = ProjectsDetails::::get(bond.project).ok_or(Error::::ProjectInfoNotFound)?; + let project_info = + ProjectsDetails::::get(bond.project).ok_or(Error::::ProjectInfoNotFound)?; // * Validity checks * ensure!( @@ -815,12 +837,17 @@ impl Pallet { /// * [`BiddingBonds`] - Update the storage with the bidder's PLMC bond for that bid /// * [`AuctionsInfo`] - Check previous bids by that user, and update the storage with the new bid pub fn do_bid( - bidder: T::AccountId, project_id: T::ProjectIdentifier, amount: BalanceOf, price: BalanceOf, + bidder: T::AccountId, + project_id: T::ProjectIdentifier, + amount: BalanceOf, + price: BalanceOf, multiplier: Option>, ) -> Result<(), DispatchError> { // * Get variables * - let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; - let project_issuer = ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; + let project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let project_issuer = + ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; let project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; let project_ticket_size = amount.saturating_mul(price); let now = >::block_number(); @@ -844,9 +871,14 @@ impl Pallet { }; // * Calculate new variables * - let (plmc_vesting_period, ct_vesting_period) = - Self::calculate_vesting_periods(bidder.clone(), multiplier.clone(), amount, price, decimals) - .map_err(|_| Error::::BadMath)?; + let (plmc_vesting_period, ct_vesting_period) = Self::calculate_vesting_periods( + bidder.clone(), + multiplier.clone(), + amount, + price, + decimals, + ) + .map_err(|_| Error::::BadMath)?; let bid_id = Self::next_bid_id(); let required_plmc_bond = plmc_vesting_period.amount; let bid = BidInfo::new( @@ -886,13 +918,8 @@ impl Pallet { // Alternative TODO: PLMC-159. The user should have the specified currency (e.g: USDC) already on Polimec user_bids.sort_by_key(|bid| Reverse(bid.price)); AuctionsInfo::::set(project_id, bidder, Some(user_bids)); - Self::deposit_event(Event::::Bid { - project_id, - amount, - price, - multiplier, - }); - } + Self::deposit_event(Event::::Bid { project_id, amount, price, multiplier }); + }, Err(_) => { // Since the bids are sorted by price, and in this branch the Vec is full, the last element is the lowest bid let lowest_bid_index: usize = (T::MaximumBidsPerUser::get() - 1) @@ -911,13 +938,8 @@ impl Pallet { user_bids.sort_by_key(|bid| Reverse(bid.price)); AuctionsInfo::::set(project_id, bidder, Some(user_bids)); // TODO: PLMC-159. Send an XCM message to Statemine to transfer amount * multiplier USDT to the PalletId Account - Self::deposit_event(Event::::Bid { - project_id, - amount, - price, - multiplier, - }); - } + Self::deposit_event(Event::::Bid { project_id, amount, price, multiplier }); + }, }; NextBidId::::set(bid_id.saturating_add(One::one())); @@ -940,26 +962,29 @@ impl Pallet { /// * [`Contributions`] - Update storage with the new contribution /// * [`T::NativeCurrency`] - Update the balance of the contributor and the project pot pub fn do_contribute( - contributor: T::AccountId, project_id: T::ProjectIdentifier, token_amount: BalanceOf, + contributor: T::AccountId, + project_id: T::ProjectIdentifier, + token_amount: BalanceOf, multiplier: Option>, ) -> Result<(), DispatchError> { // * Get variables * - let project_issuer = ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; - let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let project_issuer = + ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; + let project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; // Default should normally be multiplier of 1 let multiplier = multiplier.unwrap_or_default(); - let weighted_average_price = project_info - .weighted_average_price - .ok_or(Error::::AuctionNotStarted)?; + let weighted_average_price = + project_info.weighted_average_price.ok_or(Error::::AuctionNotStarted)?; let decimals = project.token_information.decimals; let fund_account = Self::fund_account_id(project_id); // * Validity checks * ensure!(contributor != project_issuer, Error::::ContributionToThemselves); ensure!( - project_info.project_status == ProjectStatus::CommunityRound - || project_info.project_status == ProjectStatus::RemainderRound, + project_info.project_status == ProjectStatus::CommunityRound || + project_info.project_status == ProjectStatus::RemainderRound, Error::::AuctionNotStarted ); @@ -1000,15 +1025,15 @@ impl Pallet { let bonded_plmc = ContributingBonds::::get(project_id, contributor.clone()) .map(|bond| bond.amount) .unwrap_or_else(Zero::zero); - let mut user_contributions = Contributions::::get(project_id, contributor.clone()).unwrap_or_default(); + let mut user_contributions = + Contributions::::get(project_id, contributor.clone()).unwrap_or_default(); for contribution in user_contributions.iter() { bonded_plmc.saturating_sub(contribution.plmc_vesting.amount); } required_plmc_bond.saturating_sub(bonded_plmc); - let remaining_cts_after_purchase = project_info - .remaining_contribution_tokens - .saturating_sub(buyable_tokens); + let remaining_cts_after_purchase = + project_info.remaining_contribution_tokens.saturating_sub(buyable_tokens); let now = >::block_number(); // * Update storage * @@ -1020,9 +1045,10 @@ impl Pallet { Ok(_) => { // TODO: PLMC-159. Send an XCM message to Statemint/e to transfer a `bid.market_cap` amount of USDC (or the Currency specified by the issuer) to the PalletId Account // Alternative TODO: PLMC-159. The user should have the specified currency (e.g: USDC) already on Polimec - user_contributions.sort_by_key(|contribution| Reverse(contribution.plmc_vesting.amount)); + user_contributions + .sort_by_key(|contribution| Reverse(contribution.plmc_vesting.amount)); Contributions::::set(project_id, contributor.clone(), Some(user_contributions)); - } + }, Err(_) => { // The contributions are sorted by highest PLMC bond. If the contribution vector for the user is full, we drop the lowest/last item let lowest_contribution_index: usize = (T::MaxContributionsPerUser::get() - 1) @@ -1051,7 +1077,8 @@ impl Pallet { // Update the ContributingBonds storage ContributingBonds::::mutate(project_id, contributor.clone(), |maybe_bond| { if let Some(bond) = maybe_bond { - bond.amount = bond.amount.saturating_sub(lowest_contribution.plmc_vesting.amount); + bond.amount = + bond.amount.saturating_sub(lowest_contribution.plmc_vesting.amount); } }); @@ -1059,10 +1086,11 @@ impl Pallet { user_contributions .try_push(contribution) .expect("We removed an element, so there is always space; qed"); - user_contributions.sort_by_key(|contribution| Reverse(contribution.plmc_vesting.amount)); + user_contributions + .sort_by_key(|contribution| Reverse(contribution.plmc_vesting.amount)); Contributions::::set(project_id, contributor.clone(), Some(user_contributions)); // TODO: PLMC-159. Send an XCM message to Statemine to transfer amount * multiplier USDT to the PalletId Account - } + }, }; // Transfer funds from contributor to fund account @@ -1107,7 +1135,9 @@ impl Pallet { /// * [`BiddingBonds`] - Update the bid with the new vesting period struct, reflecting this withdrawal /// * [`T::NativeCurrency`] - Unreserve the unbonded amount pub fn do_vested_plmc_bid_unbond_for( - releaser: T::AccountId, project_id: T::ProjectIdentifier, bidder: T::AccountId, + releaser: T::AccountId, + project_id: T::ProjectIdentifier, + bidder: T::AccountId, ) -> Result<(), DispatchError> { // * Get variables * let bids = AuctionsInfo::::get(project_id, &bidder).ok_or(Error::::BidNotFound)?; @@ -1120,7 +1150,7 @@ impl Pallet { // * Validity checks * // check that it is not too early to withdraw the next amount if plmc_vesting.next_withdrawal > now { - continue; + continue } // * Calculate variables * @@ -1129,7 +1159,7 @@ impl Pallet { while let Ok(amount) = plmc_vesting.calculate_next_withdrawal() { unbond_amount = unbond_amount.saturating_add(amount); if plmc_vesting.next_withdrawal > now { - break; + break } } bid.plmc_vesting_period = plmc_vesting; @@ -1140,7 +1170,8 @@ impl Pallet { // Update the new vector that will go in AuctionInfo with the updated vesting period struct new_bids.push(bid.clone()); // Update the BiddingBonds map with the reduced amount for that project-user - let mut bond = BiddingBonds::::get(bid.project, bid.bidder.clone()).ok_or(Error::::FieldIsNone)?; + let mut bond = BiddingBonds::::get(bid.project, bid.bidder.clone()) + .ok_or(Error::::FieldIsNone)?; bond.amount = bond.amount.saturating_sub(unbond_amount); // TODO: maybe the BiddingBonds map is redundant, since we can iterate over the Bids vec and calculate it ourselves BiddingBonds::::insert(bid.project, bid.bidder.clone(), bond); @@ -1175,7 +1206,9 @@ impl Pallet { /// * `AuctionsInfo` - Check if its time to mint some tokens based on the bid vesting period, and update the bid after minting. /// * `T::ContributionTokenCurrency` - Mint the tokens to the bidder pub fn do_vested_contribution_token_bid_mint_for( - releaser: T::AccountId, project_id: T::ProjectIdentifier, bidder: T::AccountId, + releaser: T::AccountId, + project_id: T::ProjectIdentifier, + bidder: T::AccountId, ) -> Result<(), DispatchError> { // * Get variables * let bids = AuctionsInfo::::get(project_id, &bidder).ok_or(Error::::BidNotFound)?; @@ -1188,7 +1221,7 @@ impl Pallet { // * Validity checks * // check that it is not too early to withdraw the next amount if ct_vesting.next_withdrawal > now { - continue; + continue } // * Calculate variables * @@ -1196,7 +1229,7 @@ impl Pallet { while let Ok(amount) = ct_vesting.calculate_next_withdrawal() { mint_amount = mint_amount.saturating_add(amount); if ct_vesting.next_withdrawal > now { - break; + break } } bid.ct_vesting_period = ct_vesting; @@ -1233,11 +1266,15 @@ impl Pallet { /// * [`BiddingBonds`] - Update the bid with the new vesting period struct, reflecting this withdrawal /// * [`T::NativeCurrency`] - Unreserve the unbonded amount pub fn do_vested_plmc_purchase_unbond_for( - releaser: T::AccountId, project_id: T::ProjectIdentifier, claimer: T::AccountId, + releaser: T::AccountId, + project_id: T::ProjectIdentifier, + claimer: T::AccountId, ) -> Result<(), DispatchError> { // * Get variables * - let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; - let contributions = Contributions::::get(project_id, &claimer).ok_or(Error::::BidNotFound)?; + let project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; + let contributions = + Contributions::::get(project_id, &claimer).ok_or(Error::::BidNotFound)?; let now = >::block_number(); let mut updated_contributions = vec![]; @@ -1260,7 +1297,7 @@ impl Pallet { // * Validity checks * // check that it is not too early to withdraw the next amount if plmc_vesting.next_withdrawal > now { - continue; + continue } // * Calculate variables * @@ -1268,7 +1305,7 @@ impl Pallet { while let Ok(amount) = plmc_vesting.calculate_next_withdrawal() { unbond_amount = unbond_amount.saturating_add(amount); if plmc_vesting.next_withdrawal > now { - break; + break } } contribution.plmc_vesting = plmc_vesting; @@ -1293,9 +1330,7 @@ impl Pallet { // Obviously also the participants of the Auction Round should be able to claim their tokens // In theory this should never fail, since we insert the same number of contributions as before let updated_contributions: BoundedVec, T::MaxContributionsPerUser> = - updated_contributions - .try_into() - .map_err(|_| Error::::TooManyContributions)?; + updated_contributions.try_into().map_err(|_| Error::::TooManyContributions)?; Contributions::::insert(project_id, &claimer, updated_contributions); Ok(()) @@ -1312,11 +1347,15 @@ impl Pallet { /// * [`Contributions`] - Check if its time to mint some tokens based on the contributions vesting periods, and update the contribution after minting. /// * [`T::ContributionTokenCurrency`] - Mint the tokens to the claimer pub fn do_vested_contribution_token_purchase_mint_for( - releaser: T::AccountId, project_id: T::ProjectIdentifier, claimer: T::AccountId, + releaser: T::AccountId, + project_id: T::ProjectIdentifier, + claimer: T::AccountId, ) -> Result<(), DispatchError> { // * Get variables * - let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; - let contributions = Contributions::::get(project_id, &claimer).ok_or(Error::::BidNotFound)?; + let project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; + let contributions = + Contributions::::get(project_id, &claimer).ok_or(Error::::BidNotFound)?; let now = >::block_number(); let mut updated_contributions = vec![]; @@ -1339,7 +1378,7 @@ impl Pallet { // * Validity checks * // check that it is not too early to withdraw the next amount if ct_vesting.next_withdrawal > now { - continue; + continue } // * Calculate variables * @@ -1347,7 +1386,7 @@ impl Pallet { while let Ok(amount) = ct_vesting.calculate_next_withdrawal() { mint_amount = mint_amount.saturating_add(amount); if ct_vesting.next_withdrawal > now { - break; + break } } contribution.ct_vesting = ct_vesting; @@ -1372,9 +1411,7 @@ impl Pallet { // Obviously also the participants of the Auction Round should be able to claim their tokens // In theory this should never fail, since we insert the same number of contributions as before let updated_contributions: BoundedVec, T::MaxContributionsPerUser> = - updated_contributions - .try_into() - .map_err(|_| Error::::TooManyContributions)?; + updated_contributions.try_into().map_err(|_| Error::::TooManyContributions)?; Contributions::::insert(project_id, &claimer, updated_contributions); Ok(()) @@ -1393,7 +1430,9 @@ impl Pallet { } pub fn bond_bidding( - caller: T::AccountId, project_id: T::ProjectIdentifier, amount: BalanceOf, + caller: T::AccountId, + project_id: T::ProjectIdentifier, + amount: BalanceOf, ) -> Result<(), DispatchError> { let now = >::block_number(); let project_info = ProjectsDetails::::get(project_id) @@ -1411,7 +1450,7 @@ impl Pallet { bond.amount += amount; T::NativeCurrency::reserve_named(&BondType::Bidding, &caller, amount) .map_err(|_| Error::::InsufficientBalance)?; - } + }, None => { // If the user has not bonded yet, create a new bond *maybe_bond = Some(BiddingBond { @@ -1424,7 +1463,7 @@ impl Pallet { // Reserve the required PLMC T::NativeCurrency::reserve_named(&BondType::Bidding, &caller, amount) .map_err(|_| Error::::InsufficientBalance)?; - } + }, } Self::deposit_event(Event::::FundsBonded { project_id, @@ -1438,7 +1477,9 @@ impl Pallet { } pub fn bond_contributing( - caller: T::AccountId, project_id: T::ProjectIdentifier, amount: BalanceOf, + caller: T::AccountId, + project_id: T::ProjectIdentifier, + amount: BalanceOf, ) -> Result<(), DispatchError> { let now = >::block_number(); let project_info = ProjectsDetails::::get(project_id) @@ -1456,7 +1497,7 @@ impl Pallet { bond.amount += amount; T::NativeCurrency::reserve_named(&BondType::Contributing, &caller, amount) .map_err(|_| Error::::InsufficientBalance)?; - } + }, None => { // If the user has not bonded yet, create a new bond *maybe_bond = Some(ContributingBond { @@ -1468,7 +1509,7 @@ impl Pallet { // Reserve the required PLMC T::NativeCurrency::reserve_named(&BondType::Contributing, &caller, amount) .map_err(|_| Error::::InsufficientBalance)?; - } + }, } Self::deposit_event(Event::::FundsBonded { project_id, @@ -1482,7 +1523,10 @@ impl Pallet { } /// Adds a project to the ProjectsToUpdate storage, so it can be updated at some later point in time. - pub fn add_to_update_store(block_number: T::BlockNumber, store: (&T::ProjectIdentifier, UpdateType)) { + pub fn add_to_update_store( + block_number: T::BlockNumber, + store: (&T::ProjectIdentifier, UpdateType), + ) { // Try to get the project into the earliest possible block to update. // There is a limit for how many projects can update each block, so we need to make sure we don't exceed that limit let mut block_number = block_number; @@ -1492,10 +1536,13 @@ impl Pallet { } } - pub fn remove_from_update_store(project_id: &T::ProjectIdentifier) -> Result<(), DispatchError> { + pub fn remove_from_update_store( + project_id: &T::ProjectIdentifier, + ) -> Result<(), DispatchError> { let (block_position, project_index) = ProjectsToUpdate::::iter() .find_map(|(block, project_vec)| { - let project_index = project_vec.iter().position(|(id, _update_type)| id == project_id)?; + let project_index = + project_vec.iter().position(|(id, _update_type)| id == project_id)?; Some((block, project_index)) }) .ok_or(Error::::ProjectNotInUpdateStore)?; @@ -1510,15 +1557,13 @@ impl Pallet { /// Based on the amount of tokens and price to buy, a desired multiplier, and the type of investor the caller is, /// calculate the amount and vesting periods of bonded PLMC and reward CT tokens. pub fn calculate_vesting_periods( - _caller: T::AccountId, multiplier: MultiplierOf, token_amount: BalanceOf, token_price: BalanceOf, + _caller: T::AccountId, + multiplier: MultiplierOf, + token_amount: BalanceOf, + token_price: BalanceOf, decimals: u8, - ) -> Result< - ( - Vesting>, - Vesting>, - ), - (), - > { + ) -> Result<(Vesting>, Vesting>), ()> + { let plmc_start: T::BlockNumber = 0u32.into(); let ct_start: T::BlockNumber = (T::MaxProjectsToUpdatePerBlock::get() * 7).into(); // TODO: Calculate real vesting periods based on multiplier and caller type @@ -1546,7 +1591,9 @@ impl Pallet { /// Calculates the price of contribution tokens for the Community and Remainder Rounds pub fn calculate_weighted_average_price( - project_id: T::ProjectIdentifier, end_block: T::BlockNumber, total_allocation_size: BalanceOf, + project_id: T::ProjectIdentifier, + end_block: T::BlockNumber, + total_allocation_size: BalanceOf, ) -> Result<(), DispatchError> { // Get all the bids that were made before the end of the candle let mut bids = AuctionsInfo::::iter_values().flatten().collect::>(); @@ -1564,7 +1611,7 @@ impl Pallet { if bid.when > end_block { bid.status = BidStatus::Rejected(RejectionReason::AfterCandleEnd); // TODO: PLMC-147. Unlock funds. We can do this inside the "on_idle" hook, and change the `status` of the `Bid` to "Unreserved" - return bid; + return bid } let buyable_amount = total_allocation_size.saturating_sub(bid_amount_sum); if buyable_amount == 0_u32.into() { @@ -1576,7 +1623,8 @@ impl Pallet { } else { bid_amount_sum.saturating_accrue(buyable_amount); bid_value_sum.saturating_accrue(buyable_amount * bid.price); - bid.status = BidStatus::PartiallyAccepted(buyable_amount, RejectionReason::NoTokensLeft) + bid.status = + BidStatus::PartiallyAccepted(buyable_amount, RejectionReason::NoTokensLeft) // TODO: PLMC-147. Refund remaining amount } @@ -1624,12 +1672,10 @@ impl Pallet { // TODO: PLMC-150. collecting due to previous mut borrow, find a way to not collect and borrow bid on filter_map .into_iter() .filter_map(|bid| match bid.status { - BidStatus::Accepted => { - Some(Perbill::from_rational(bid.amount * bid.price, bid_value_sum) * bid.price) - }, - BidStatus::PartiallyAccepted(amount, _) => { - Some(Perbill::from_rational(amount * bid.price, bid_value_sum) * bid.price) - }, + BidStatus::Accepted => + Some(Perbill::from_rational(bid.amount * bid.price, bid_value_sum) * bid.price), + BidStatus::PartiallyAccepted(amount, _) => + Some(Perbill::from_rational(amount * bid.price, bid_value_sum) * bid.price), _ => None, }) .reduce(|a, b| a.saturating_add(b)) @@ -1639,7 +1685,8 @@ impl Pallet { ProjectsDetails::::mutate(project_id, |maybe_info| -> Result<(), DispatchError> { if let Some(info) = maybe_info { info.weighted_average_price = Some(weighted_token_price); - info.remaining_contribution_tokens = info.remaining_contribution_tokens.saturating_sub(bid_amount_sum); + info.remaining_contribution_tokens = + info.remaining_contribution_tokens.saturating_sub(bid_amount_sum); Ok(()) } else { Err(Error::::ProjectNotFound.into()) @@ -1650,7 +1697,8 @@ impl Pallet { } pub fn select_random_block( - candle_starting_block: T::BlockNumber, candle_ending_block: T::BlockNumber, + candle_starting_block: T::BlockNumber, + candle_ending_block: T::BlockNumber, ) -> T::BlockNumber { let nonce = Self::get_and_increment_nonce(); let (random_value, _known_since) = T::Randomness::random(&nonce); @@ -1671,7 +1719,8 @@ impl Pallet { // This function is kept separate from the `do_claim_contribution_tokens` for easier testing the logic #[inline(always)] pub fn calculate_claimable_tokens( - contribution_amount: BalanceOf, weighted_average_price: BalanceOf, + contribution_amount: BalanceOf, + weighted_average_price: BalanceOf, ) -> FixedU128 { FixedU128::saturating_from_rational(contribution_amount, weighted_average_price) } diff --git a/pallets/funding/src/lib.rs b/pallets/funding/src/lib.rs index 641dd3a33..1729100ea 100644 --- a/pallets/funding/src/lib.rs +++ b/pallets/funding/src/lib.rs @@ -197,9 +197,6 @@ pub mod tests; mod benchmarking; pub mod traits; -#[allow(unused_imports)] -use polimec_traits::{MemberRole, PolimecMembers}; - pub use crate::weights::WeightInfo; use frame_support::{ pallet_prelude::ValueQuery, @@ -221,8 +218,11 @@ use sp_std::prelude::*; type BalanceOf = ::Balance; -type ProjectMetadataOf = - ProjectMetadata::StringLimit>, BalanceOf, ::Hash>; +type ProjectMetadataOf = ProjectMetadata< + BoundedVec::StringLimit>, + BalanceOf, + ::Hash, +>; type ProjectDetailsOf = ProjectDetails<::BlockNumber, BalanceOf>; @@ -396,17 +396,20 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn projects)] /// A StorageMap containing the primary project information of projects - pub type ProjectsMetadata = StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, ProjectMetadataOf>; + pub type ProjectsMetadata = + StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, ProjectMetadataOf>; #[pallet::storage] #[pallet::getter(fn project_issuer)] /// StorageMap to get the issuer of a project - pub type ProjectsIssuers = StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, T::AccountId>; + pub type ProjectsIssuers = + StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, T::AccountId>; #[pallet::storage] #[pallet::getter(fn project_info)] /// StorageMap containing additional information for the projects, relevant for correctness of the protocol - pub type ProjectsDetails = StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, ProjectDetailsOf>; + pub type ProjectsDetails = + StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, ProjectDetailsOf>; #[pallet::storage] #[pallet::getter(fn projects_to_update)] @@ -497,23 +500,13 @@ pub mod pallet { end_block: T::BlockNumber, }, /// The auction round of a project started. - EnglishAuctionStarted { - project_id: T::ProjectIdentifier, - when: T::BlockNumber, - }, + EnglishAuctionStarted { project_id: T::ProjectIdentifier, when: T::BlockNumber }, /// The candle auction part of the auction started for a project - CandleAuctionStarted { - project_id: T::ProjectIdentifier, - when: T::BlockNumber, - }, + CandleAuctionStarted { project_id: T::ProjectIdentifier, when: T::BlockNumber }, /// The auction round of a project ended. AuctionEnded { project_id: T::ProjectIdentifier }, /// A `bonder` bonded an `amount` of PLMC for `project_id`. - FundsBonded { - project_id: T::ProjectIdentifier, - amount: BalanceOf, - bonder: T::AccountId, - }, + FundsBonded { project_id: T::ProjectIdentifier, amount: BalanceOf, bonder: T::AccountId }, /// Someone paid for the release of a user's PLMC bond for a project. BondReleased { project_id: T::ProjectIdentifier, @@ -542,10 +535,7 @@ pub mod pallet { /// A project has now finished funding FundingEnded { project_id: T::ProjectIdentifier }, /// Something was not properly initialized. Most likely due to dev error manually calling do_* functions or updating storage - TransitionError { - project_id: T::ProjectIdentifier, - error: DispatchError, - }, + TransitionError { project_id: T::ProjectIdentifier, error: DispatchError }, /// Something terribly wrong happened where the bond could not be unbonded. Most likely a programming error FailedEvaluationUnbondFailed { error: DispatchError }, /// Contribution tokens were minted to a user @@ -678,7 +668,9 @@ pub mod pallet { /// Change the metadata hash of a project #[pallet::weight(T::WeightInfo::edit_metadata())] pub fn edit_metadata( - origin: OriginFor, project_id: T::ProjectIdParameter, project_metadata_hash: T::Hash, + origin: OriginFor, + project_id: T::ProjectIdParameter, + project_metadata_hash: T::Hash, ) -> DispatchResult { let issuer = ensure_signed(origin)?; let project_id = project_id.into(); @@ -688,7 +680,10 @@ pub mod pallet { /// Starts the evaluation round of a project. It needs to be called by the project issuer. #[pallet::weight(T::WeightInfo::start_evaluation())] - pub fn start_evaluation(origin: OriginFor, project_id: T::ProjectIdParameter) -> DispatchResult { + pub fn start_evaluation( + origin: OriginFor, + project_id: T::ProjectIdParameter, + ) -> DispatchResult { let issuer = ensure_signed(origin)?; let project_id = project_id.into(); @@ -698,10 +693,7 @@ pub mod pallet { // Error::::NotAuthorized // ); - ensure!( - ProjectsIssuers::::get(project_id) == Some(issuer), - Error::::NotAllowed - ); + ensure!(ProjectsIssuers::::get(project_id) == Some(issuer), Error::::NotAllowed); Self::do_evaluation_start(project_id) } @@ -710,7 +702,10 @@ pub mod pallet { /// institutional user can set bids for a token_amount/token_price pair. /// Any bids from this point until the candle_auction starts, will be considered as valid. #[pallet::weight(T::WeightInfo::start_auction())] - pub fn start_auction(origin: OriginFor, project_id: T::ProjectIdParameter) -> DispatchResult { + pub fn start_auction( + origin: OriginFor, + project_id: T::ProjectIdParameter, + ) -> DispatchResult { let issuer = ensure_signed(origin)?; let project_id = project_id.into(); @@ -720,10 +715,7 @@ pub mod pallet { // Error::::NotAuthorized // ); - ensure!( - ProjectsIssuers::::get(project_id) == Some(issuer), - Error::::NotAllowed - ); + ensure!(ProjectsIssuers::::get(project_id) == Some(issuer), Error::::NotAllowed); Self::do_english_auction(project_id) } @@ -731,7 +723,9 @@ pub mod pallet { /// Bond PLMC for a project in the evaluation stage #[pallet::weight(T::WeightInfo::bond())] pub fn bond_evaluation( - origin: OriginFor, project_id: T::ProjectIdParameter, #[pallet::compact] amount: BalanceOf, + origin: OriginFor, + project_id: T::ProjectIdParameter, + #[pallet::compact] amount: BalanceOf, ) -> DispatchResult { let from = ensure_signed(origin)?; let project_id = project_id.into(); @@ -741,10 +735,13 @@ pub mod pallet { /// Release the bonded PLMC for an evaluator if the project assigned to it is in the EvaluationFailed phase #[pallet::weight(T::WeightInfo::failed_evaluation_unbond_for())] pub fn failed_evaluation_unbond_for( - origin: OriginFor, project_id: T::ProjectIdParameter, bonder: T::AccountId, + origin: OriginFor, + project_id: T::ProjectIdParameter, + bonder: T::AccountId, ) -> DispatchResult { let releaser = ensure_signed(origin)?; - let bond = EvaluationBonds::::get(project_id.into(), bonder).ok_or(Error::::BondNotFound)?; + let bond = EvaluationBonds::::get(project_id.into(), bonder) + .ok_or(Error::::BondNotFound)?; Self::do_failed_evaluation_unbond_for(bond, releaser) } @@ -773,7 +770,9 @@ pub mod pallet { /// Buy tokens in the Community or Remainder round at the price set in the Auction Round #[pallet::weight(T::WeightInfo::contribute())] pub fn contribute( - origin: OriginFor, project_id: T::ProjectIdParameter, #[pallet::compact] amount: BalanceOf, + origin: OriginFor, + project_id: T::ProjectIdParameter, + #[pallet::compact] amount: BalanceOf, multiplier: Option>, ) -> DispatchResult { let contributor = ensure_signed(origin)?; @@ -784,7 +783,9 @@ pub mod pallet { /// Unbond some plmc from a contribution, after a step in the vesting period has passed. pub fn vested_plmc_bid_unbond_for( - origin: OriginFor, project_id: T::ProjectIdParameter, bidder: T::AccountId, + origin: OriginFor, + project_id: T::ProjectIdParameter, + bidder: T::AccountId, ) -> DispatchResult { // TODO: PLMC-157. Manage the fact that the CTs may not be claimed by those entitled let claimer = ensure_signed(origin)?; @@ -796,7 +797,9 @@ pub mod pallet { // TODO: PLMC-157. Manage the fact that the CTs may not be claimed by those entitled /// Mint contribution tokens after a step in the vesting period for a successful bid. pub fn vested_contribution_token_bid_mint_for( - origin: OriginFor, project_id: T::ProjectIdParameter, bidder: T::AccountId, + origin: OriginFor, + project_id: T::ProjectIdParameter, + bidder: T::AccountId, ) -> DispatchResult { let claimer = ensure_signed(origin)?; let project_id = project_id.into(); @@ -807,7 +810,9 @@ pub mod pallet { // TODO: PLMC-157. Manage the fact that the CTs may not be claimed by those entitled /// Unbond some plmc from a contribution, after a step in the vesting period has passed. pub fn vested_plmc_purchase_unbond_for( - origin: OriginFor, project_id: T::ProjectIdParameter, purchaser: T::AccountId, + origin: OriginFor, + project_id: T::ProjectIdParameter, + purchaser: T::AccountId, ) -> DispatchResult { let claimer = ensure_signed(origin)?; let project_id = project_id.into(); @@ -818,7 +823,9 @@ pub mod pallet { // TODO: PLMC-157. Manage the fact that the CTs may not be claimed by those entitled /// Mint contribution tokens after a step in the vesting period for a contribution. pub fn vested_contribution_token_purchase_mint_for( - origin: OriginFor, project_id: T::ProjectIdParameter, purchaser: T::AccountId, + origin: OriginFor, + project_id: T::ProjectIdParameter, + purchaser: T::AccountId, ) -> DispatchResult { let claimer = ensure_signed(origin)?; let project_id = project_id.into(); @@ -836,33 +843,33 @@ pub mod pallet { // EvaluationRound -> AuctionInitializePeriod | EvaluationFailed UpdateType::EvaluationEnd => { unwrap_result_or_skip!(Self::do_evaluation_end(project_id), project_id); - } + }, // AuctionInitializePeriod -> AuctionRound(AuctionPhase::English) // Only if it wasn't first handled by user extrinsic UpdateType::EnglishAuctionStart => { unwrap_result_or_skip!(Self::do_english_auction(project_id), project_id); - } + }, // AuctionRound(AuctionPhase::English) -> AuctionRound(AuctionPhase::Candle) UpdateType::CandleAuctionStart => { unwrap_result_or_skip!(Self::do_candle_auction(project_id), project_id); - } + }, // AuctionRound(AuctionPhase::Candle) -> CommunityRound UpdateType::CommunityFundingStart => { unwrap_result_or_skip!(Self::do_community_funding(project_id), project_id); - } + }, // CommunityRound -> RemainderRound UpdateType::RemainderFundingStart => { unwrap_result_or_skip!(Self::do_remainder_funding(project_id), project_id) - } + }, // CommunityRound || RemainderRound -> FundingEnded UpdateType::FundingEnd => { unwrap_result_or_skip!(Self::do_end_funding(project_id), project_id) - } + }, } } // TODO: PLMC-127. Set a proper weight @@ -870,7 +877,8 @@ pub mod pallet { } fn on_idle(_now: T::BlockNumber, max_weight: Weight) -> Weight { - let pallet_account: T::AccountId = ::PalletId::get().into_account_truncating(); + let pallet_account: T::AccountId = + ::PalletId::get().into_account_truncating(); let mut remaining_weight = max_weight; @@ -933,14 +941,8 @@ pub mod pallet { let project: ProjectMetadataOf = ProjectMetadata { total_allocation_size: 1_000_000u64.into(), minimum_price: 1__0_000_000_000_u64.into(), - ticket_size: TicketSize { - minimum: Some(1u8.into()), - maximum: None, - }, - participants_size: ParticipantsSize { - minimum: Some(2), - maximum: None, - }, + ticket_size: TicketSize { minimum: Some(1u8.into()), maximum: None }, + participants_size: ParticipantsSize { minimum: Some(2), maximum: None }, offchain_information_hash: Some(metadata_hash), ..Default::default() }; @@ -962,8 +964,8 @@ pub mod local_macros { project_id: $project_id, error: Error::::FieldIsNone.into(), }); - continue; - } + continue + }, } }; } @@ -979,8 +981,8 @@ pub mod local_macros { project_id: $project_id, error: err, }); - continue; - } + continue + }, } }; } diff --git a/pallets/funding/src/mock.rs b/pallets/funding/src/mock.rs index 602e372a3..6ec9516ee 100644 --- a/pallets/funding/src/mock.rs +++ b/pallets/funding/src/mock.rs @@ -176,16 +176,11 @@ impl pallet_funding::Config for TestRuntime { // Build genesis storage according to the mock runtime. // TODO: PLMC-161. Add some mocks projects at Genesis to simplify the tests pub fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - GenesisConfig { - balances: BalancesConfig { balances: vec![] }, - ..Default::default() - } - .assimilate_storage(&mut t) - .unwrap(); + GenesisConfig { balances: BalancesConfig { balances: vec![] }, ..Default::default() } + .assimilate_storage(&mut t) + .unwrap(); let mut ext = sp_io::TestExternalities::new(t); // In order to emit events the block number must be more than 0 diff --git a/pallets/funding/src/tests.rs b/pallets/funding/src/tests.rs index e9567709d..a62e9b98d 100644 --- a/pallets/funding/src/tests.rs +++ b/pallets/funding/src/tests.rs @@ -38,13 +38,10 @@ type UserToBalance = Vec<(mock::AccountId, BalanceOf)>; // User -> token_amount, price_per_token, multiplier type UserToBid = Vec<( AccountId, - ( - BalanceOf, - BalanceOf, - Option>, - ), + (BalanceOf, BalanceOf, Option>), )>; -type UserToContribution = Vec<(AccountId, (BalanceOf, Option>))>; +type UserToContribution = + Vec<(AccountId, (BalanceOf, Option>))>; const ISSUER: AccountId = 1; const EVALUATOR_1: AccountId = 2; @@ -75,7 +72,10 @@ const METADATA: &str = r#" // } /// Remove accounts from fundings_1 that are not in fundings_2 -fn remove_missing_accounts_from_fundings(fundings_1: UserToBalance, fundings_2: UserToBalance) -> UserToBalance { +fn remove_missing_accounts_from_fundings( + fundings_1: UserToBalance, + fundings_2: UserToBalance, +) -> UserToBalance { let mut fundings_1 = fundings_1; let fundings_2 = fundings_2; fundings_1.retain(|(account, _)| { @@ -93,18 +93,19 @@ trait ProjectInstance { fn get_creator(&self) -> AccountId; fn get_project_id(&self) -> ProjectIdOf; fn get_project(&self) -> ProjectMetadataOf { - self.get_test_environment() - .ext_env - .borrow_mut() - .execute_with(|| FundingModule::projects(self.get_project_id()).expect("Project info should exist")) + self.get_test_environment().ext_env.borrow_mut().execute_with(|| { + FundingModule::projects(self.get_project_id()).expect("Project info should exist") + }) } fn get_project_info(&self) -> ProjectDetailsOf { - self.get_test_environment() - .ext_env - .borrow_mut() - .execute_with(|| FundingModule::project_info(self.get_project_id()).expect("Project info should exist")) + self.get_test_environment().ext_env.borrow_mut().execute_with(|| { + FundingModule::project_info(self.get_project_id()).expect("Project info should exist") + }) } - fn do_project_assertions(&self, project_assertions: impl Fn(ProjectIdOf, &TestEnvironment) -> ()) { + fn do_project_assertions( + &self, + project_assertions: impl Fn(ProjectIdOf, &TestEnvironment) -> (), + ) { let project_id = self.get_project_id(); let test_env = self.get_test_environment(); project_assertions(project_id, test_env); @@ -119,13 +120,12 @@ pub struct TestEnvironment { } impl TestEnvironment { pub fn new() -> Self { - Self { - ext_env: RefCell::new(new_test_ext()), - nonce: RefCell::new(0u64), - } + Self { ext_env: RefCell::new(new_test_ext()), nonce: RefCell::new(0u64) } } fn create_project( - &self, creator: mock::AccountId, project: ProjectMetadataOf, + &self, + creator: mock::AccountId, + project: ProjectMetadataOf, ) -> Result { // Create project in the externalities environment of this struct instance self.ext_env @@ -137,7 +137,8 @@ impl TestEnvironment { frame_system::Pallet::::events() .iter() .filter_map(|event| match event.event { - RuntimeEvent::FundingModule(crate::Event::Created { project_id }) => Some(project_id), + RuntimeEvent::FundingModule(crate::Event::Created { project_id }) => + Some(project_id), _ => None, }) .last() @@ -145,18 +146,15 @@ impl TestEnvironment { .clone() }); - Ok(CreatedProject { - test_env: self, - creator, - project_id, - }) + Ok(CreatedProject { test_env: self, creator, project_id }) } /// Returns the *free* fundings of the Users. #[allow(dead_code)] fn get_free_fundings(&self) -> UserToBalance { self.ext_env.borrow_mut().execute_with(|| { let mut fundings = UserToBalance::new(); - let user_keys: Vec = frame_system::Account::::iter_keys().collect(); + let user_keys: Vec = + frame_system::Account::::iter_keys().collect(); for user in user_keys { let funding = Balances::free_balance(&user); fundings.push((user, funding)); @@ -169,7 +167,8 @@ impl TestEnvironment { fn get_reserved_fundings(&self, reserve_type: BondType) -> UserToBalance { self.ext_env.borrow_mut().execute_with(|| { let mut fundings = UserToBalance::new(); - let user_keys: Vec = frame_system::Account::::iter_keys().collect(); + let user_keys: Vec = + frame_system::Account::::iter_keys().collect(); for user in user_keys { let funding = Balances::reserved_balance_named(&reserve_type, &user); fundings.push((user, funding)); @@ -191,7 +190,10 @@ impl TestEnvironment { self.ext_env.borrow_mut().execute_with(|| { for _block in 0..amount { >::on_finalize(System::block_number()); - >::on_idle(System::block_number(), Weight::MAX); + >::on_idle( + System::block_number(), + Weight::MAX, + ); System::set_block_number(System::block_number() + 1); >::on_initialize(System::block_number()); } @@ -245,11 +247,13 @@ impl<'a> CreatedProject<'a> { } // Move to next project phase - fn start_evaluation(self, caller: mock::AccountId) -> Result, DispatchError> { - self.test_env - .ext_env - .borrow_mut() - .execute_with(|| FundingModule::start_evaluation(RuntimeOrigin::signed(caller), self.project_id))?; + fn start_evaluation( + self, + caller: mock::AccountId, + ) -> Result, DispatchError> { + self.test_env.ext_env.borrow_mut().execute_with(|| { + FundingModule::start_evaluation(RuntimeOrigin::signed(caller), self.project_id) + })?; Ok(EvaluatingProject { test_env: self.test_env, @@ -289,10 +293,9 @@ impl<'a> EvaluatingProject<'a> { fn bond_for_users(&self, bonds: UserToBalance) -> Result<(), DispatchError> { let project_id = self.get_project_id(); for (account, amount) in bonds { - self.test_env - .ext_env - .borrow_mut() - .execute_with(|| FundingModule::bond_evaluation(RuntimeOrigin::signed(account), project_id, amount))?; + self.test_env.ext_env.borrow_mut().execute_with(|| { + FundingModule::bond_evaluation(RuntimeOrigin::signed(account), project_id, amount) + })?; } Ok(()) } @@ -390,16 +393,14 @@ impl<'a> AuctioningProject<'a> { .english_auction .end() .expect("English end point should exist"); - self.test_env - .advance_time(english_end - self.test_env.current_block() + 1); + self.test_env.advance_time(english_end - self.test_env.current_block() + 1); let candle_end = self .get_project_info() .phase_transition_points .candle_auction .end() .expect("Candle end point should exist"); - self.test_env - .advance_time(candle_end - self.test_env.current_block() + 1); + self.test_env.advance_time(candle_end - self.test_env.current_block() + 1); assert_eq!(self.get_project_info().project_status, ProjectStatus::CommunityRound); CommunityFundingProject { test_env: self.test_env, @@ -452,7 +453,12 @@ impl<'a> CommunityFundingProject<'a> { let project_id = self.get_project_id(); for (account, (ct_amount, multiplier)) in buys { self.test_env.ext_env.borrow_mut().execute_with(|| { - FundingModule::contribute(RuntimeOrigin::signed(account), project_id, ct_amount, multiplier) + FundingModule::contribute( + RuntimeOrigin::signed(account), + project_id, + ct_amount, + multiplier, + ) })?; } Ok(()) @@ -498,7 +504,12 @@ impl<'a> RemainderFundingProject<'a> { let project_id = self.get_project_id(); for (account, (ct_amount, multiplier)) in buys { self.test_env.ext_env.borrow_mut().execute_with(|| { - FundingModule::contribute(RuntimeOrigin::signed(account), project_id, ct_amount, multiplier) + FundingModule::contribute( + RuntimeOrigin::signed(account), + project_id, + ct_amount, + multiplier, + ) })?; } Ok(()) @@ -581,21 +592,18 @@ mod defaults { use super::*; use crate::traits::BondingRequirementCalculation; - pub fn default_project(nonce: u64) -> ProjectMetadata>, u128, sp_core::H256> { - let bounded_name = BoundedVec::try_from("Contribution Token TEST".as_bytes().to_vec()).unwrap(); + pub fn default_project( + nonce: u64, + ) -> ProjectMetadata>, u128, sp_core::H256> { + let bounded_name = + BoundedVec::try_from("Contribution Token TEST".as_bytes().to_vec()).unwrap(); let bounded_symbol = BoundedVec::try_from("CTEST".as_bytes().to_vec()).unwrap(); let metadata_hash = hashed(format!("{}-{}", METADATA, nonce)); ProjectMetadata { total_allocation_size: 1_000_000, minimum_price: 1 * PLMC, - ticket_size: TicketSize { - minimum: Some(1), - maximum: None, - }, - participants_size: ParticipantsSize { - minimum: Some(2), - maximum: None, - }, + ticket_size: TicketSize { minimum: Some(1), maximum: None }, + participants_size: ParticipantsSize { minimum: Some(2), maximum: None }, funding_thresholds: Default::default(), conversion_rate: 0, participation_currencies: Default::default(), @@ -687,7 +695,9 @@ mod defaults { .collect() } - pub fn default_community_buys_currency_reserved(price: BalanceOf) -> UserToBalance { + pub fn default_community_buys_currency_reserved( + price: BalanceOf, + ) -> UserToBalance { default_community_buys() .into_iter() .map(|(user, (amount, _multiplier))| (user, (amount * price))) @@ -708,30 +718,46 @@ mod defaults { // vec![(BUYER_1, (100 * PLMC)), (BUYER_2, (6000 * PLMC))] // } - pub fn default_creation_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { + pub fn default_creation_assertions( + project_id: ProjectIdOf, + test_env: &TestEnvironment, + ) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = + FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::Application); }); } - pub fn default_evaluation_start_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { + pub fn default_evaluation_start_assertions( + project_id: ProjectIdOf, + test_env: &TestEnvironment, + ) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = + FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::EvaluationRound); }); } - pub fn default_evaluation_end_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { + pub fn default_evaluation_end_assertions( + project_id: ProjectIdOf, + test_env: &TestEnvironment, + ) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = + FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::AuctionInitializePeriod); }); } - pub fn default_auction_start_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { + pub fn default_auction_start_assertions( + project_id: ProjectIdOf, + test_env: &TestEnvironment, + ) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = + FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!( project_info.project_status, ProjectStatus::AuctionRound(AuctionPhase::English) @@ -739,9 +765,13 @@ mod defaults { }); } - pub fn default_auction_end_assertions(_project_id: ProjectIdOf, test_env: &TestEnvironment) { + pub fn default_auction_end_assertions( + _project_id: ProjectIdOf, + test_env: &TestEnvironment, + ) { // Check that enough PLMC is bonded - test_env.do_reserved_funds_assertions(default_auction_bids_plmc_bondings(), BondType::Bidding); + test_env + .do_reserved_funds_assertions(default_auction_bids_plmc_bondings(), BondType::Bidding); // Check that the bidding currency is reserved test_env.ext_env.borrow_mut().execute_with(|| { @@ -762,7 +792,8 @@ mod defaults { // Check that free funds were reduced let mut free_funds = default_fundings(); // Remove accounts that didnt bond from free_funds - free_funds = remove_missing_accounts_from_fundings(free_funds, default_auction_bids_plmc_bondings()); + free_funds = + remove_missing_accounts_from_fundings(free_funds, default_auction_bids_plmc_bondings()); // Subtract plmc bonded bidding funds free_funds = free_funds .iter() @@ -786,7 +817,8 @@ mod defaults { } pub fn default_community_funding_start_assertions( - project_id: ProjectIdOf, test_env: &TestEnvironment, + project_id: ProjectIdOf, + test_env: &TestEnvironment, ) { // Bids that reserved bidding currency, should have that drained from their account on community round, and transfered to the pallet account test_env.ext_env.borrow_mut().execute_with(|| { @@ -799,15 +831,18 @@ mod defaults { }); // PLMC should still be reserved, since its only a bond - test_env.do_reserved_funds_assertions(default_auction_bids_plmc_bondings(), BondType::Bidding); + test_env + .do_reserved_funds_assertions(default_auction_bids_plmc_bondings(), BondType::Bidding); // Check for correct project information test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = + FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::CommunityRound); // Check correct weighted_average_price - let token_price = project_info.weighted_average_price.expect("Token price should exist"); + let token_price = + project_info.weighted_average_price.expect("Token price should exist"); assert_eq!( token_price, default_token_average_price(), @@ -829,7 +864,8 @@ mod defaults { // Check status of bids test_env.ext_env.borrow_mut().execute_with(|| { - let project_bids = crate::pallet::AuctionsInfo::::iter_prefix(project_id).collect::>(); + let project_bids = crate::pallet::AuctionsInfo::::iter_prefix(project_id) + .collect::>(); let project_info = FundingModule::project_info(project_id).unwrap(); assert!( matches!(project_info.weighted_average_price, Some(_)), @@ -837,26 +873,34 @@ mod defaults { ); assert!(project_bids .into_iter() - .find(|(_bidder, bids)| { !bids.iter().all(|bid| bid.status == BidStatus::Accepted) }) + .find(|(_bidder, bids)| { + !bids.iter().all(|bid| bid.status == BidStatus::Accepted) + }) .is_none()); }); } - pub fn default_community_funding_end_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { + pub fn default_community_funding_end_assertions( + project_id: ProjectIdOf, + test_env: &TestEnvironment, + ) { let token_price = test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = + FundingModule::project_info(project_id).expect("Project info should exist"); project_info.weighted_average_price.expect("Token price should exist") }); let expected_plmc_bondings = default_community_plmc_bondings(token_price); let expected_buys = default_community_buys_currency_reserved(token_price); // Check that enough PLMC is bonded - test_env.do_reserved_funds_assertions(expected_plmc_bondings.clone(), BondType::Contributing); + test_env + .do_reserved_funds_assertions(expected_plmc_bondings.clone(), BondType::Contributing); // Check that free funds were reduced let mut free_funds = default_fundings(); // Remove accounts that didnt bond from free_funds - free_funds = remove_missing_accounts_from_fundings(free_funds, expected_plmc_bondings.clone()); + free_funds = + remove_missing_accounts_from_fundings(free_funds, expected_plmc_bondings.clone()); // Subtract the amount spent on the buys from the free funds free_funds = free_funds .iter() @@ -891,25 +935,33 @@ mod defaults { .sum(); assert_eq!( project.remaining_contribution_tokens, - default_project(0).total_allocation_size - auction_bought_tokens - community_bought_tokens, + default_project(0).total_allocation_size - + auction_bought_tokens - + community_bought_tokens, "Remaining CTs are incorrect" ); }); } pub fn default_remainder_funding_start_assertions( - project_id: ProjectIdOf, test_env: &TestEnvironment, + project_id: ProjectIdOf, + test_env: &TestEnvironment, ) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = + FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::RemainderRound); }); } - pub fn default_project_end_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { + pub fn default_project_end_assertions( + project_id: ProjectIdOf, + test_env: &TestEnvironment, + ) { // Check that project status is correct test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = + FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::FundingEnded); }); @@ -930,10 +982,10 @@ mod defaults { .sum(); assert_eq!( project.remaining_contribution_tokens, - default_project(0).total_allocation_size - - auction_bought_tokens - - community_bought_tokens - - remainder_bought_tokens, + default_project(0).total_allocation_size - + auction_bought_tokens - + community_bought_tokens - + remainder_bought_tokens, "Remaining CTs are incorrect" ); }); @@ -961,11 +1013,7 @@ mod helper_functions { FundingModule::remove_from_update_store(&69u32).unwrap(); let stored = crate::ProjectsToUpdate::::iter_values().collect::>(); - assert_eq!( - stored[2], - vec![], - "Vector should be empty for that block after deletion" - ); + assert_eq!(stored[2], vec![], "Vector should be empty for that block after deletion"); }); } } @@ -1027,14 +1075,8 @@ mod creation_round_failure { fn price_too_low() { let wrong_project: ProjectMetadataOf = ProjectMetadata { minimum_price: 0, - ticket_size: TicketSize { - minimum: Some(1), - maximum: None, - }, - participants_size: ParticipantsSize { - minimum: Some(2), - maximum: None, - }, + ticket_size: TicketSize { minimum: Some(1), maximum: None }, + participants_size: ParticipantsSize { minimum: Some(2), maximum: None }, offchain_information_hash: Some(hashed(METADATA)), ..Default::default() }; @@ -1050,14 +1092,8 @@ mod creation_round_failure { fn participants_size_error() { let wrong_project: ProjectMetadataOf = ProjectMetadata { minimum_price: 1, - ticket_size: TicketSize { - minimum: Some(1), - maximum: None, - }, - participants_size: ParticipantsSize { - minimum: None, - maximum: None, - }, + ticket_size: TicketSize { minimum: Some(1), maximum: None }, + participants_size: ParticipantsSize { minimum: None, maximum: None }, offchain_information_hash: Some(hashed(METADATA)), ..Default::default() }; @@ -1073,14 +1109,8 @@ mod creation_round_failure { fn ticket_size_error() { let wrong_project: ProjectMetadataOf = ProjectMetadata { minimum_price: 1, - ticket_size: TicketSize { - minimum: None, - maximum: None, - }, - participants_size: ParticipantsSize { - minimum: Some(1), - maximum: None, - }, + ticket_size: TicketSize { minimum: None, maximum: None }, + participants_size: ParticipantsSize { minimum: Some(1), maximum: None }, offchain_information_hash: Some(hashed(METADATA)), ..Default::default() }; @@ -1097,14 +1127,8 @@ mod creation_round_failure { fn multiple_field_error() { let wrong_project: ProjectMetadataOf = ProjectMetadata { minimum_price: 0, - ticket_size: TicketSize { - minimum: None, - maximum: None, - }, - participants_size: ParticipantsSize { - minimum: None, - maximum: None, - }, + ticket_size: TicketSize { minimum: None, maximum: None }, + participants_size: ParticipantsSize { minimum: None, maximum: None }, ..Default::default() }; let test_env = TestEnvironment::new(); @@ -1137,7 +1161,8 @@ mod evaluation_round_success { let evaluating_project = EvaluatingProject::new_default(&test_env); evaluating_project.bond_for_users(default_evaluation_bonds()).unwrap(); let project_info = evaluating_project.get_project_info(); - test_env.advance_time(project_info.phase_transition_points.evaluation.end().unwrap() + 1u64); + test_env + .advance_time(project_info.phase_transition_points.evaluation.end().unwrap() + 1u64); let end_block = evaluating_project .get_project_info() .phase_transition_points @@ -1167,13 +1192,15 @@ mod evaluation_round_failure { .expect("Bonding should work"); // Check that enough funds are reserved - test_env.do_reserved_funds_assertions(default_failing_evaluation_bonds(), BondType::Evaluation); + test_env + .do_reserved_funds_assertions(default_failing_evaluation_bonds(), BondType::Evaluation); // Check that free funds were reduced let mut free_funds = default_fundings(); // Remove accounts that didnt bond from free_funds - free_funds = remove_missing_accounts_from_fundings(free_funds, default_failing_evaluation_bonds()); + free_funds = + remove_missing_accounts_from_fundings(free_funds, default_failing_evaluation_bonds()); free_funds = free_funds .iter() .zip(default_failing_evaluation_bonds().iter()) @@ -1251,8 +1278,8 @@ mod auction_round_success { // do one candle bid for each block until the end of candle auction with a new user let mut bidding_account = 1000; let bid_info = default_auction_bids()[0].1; - let necessary_funding = (bid_info.0 * bid_info.1) - + (bid_info + let necessary_funding = (bid_info.0 * bid_info.1) + + (bid_info .2 .unwrap_or_default() .calculate_bonding_requirement(bid_info.0 * bid_info.1) @@ -1298,7 +1325,8 @@ mod auction_round_success { for (bidder, (_amount, _price, _multiplier)) in included_bids { test_env.ext_env.borrow_mut().execute_with(|| { let pid = auctioning_project.project_id; - let stored_bid = FundingModule::auctions_info(pid, bidder).expect("Bid should exist"); + let stored_bid = + FundingModule::auctions_info(pid, bidder).expect("Bid should exist"); assert!( matches!( stored_bid[0], @@ -1320,7 +1348,8 @@ mod auction_round_success { for (bidder, (_amount, _price, _multiplier)) in excluded_bids { test_env.ext_env.borrow_mut().execute_with(|| { let pid = auctioning_project.project_id; - let stored_bid = FundingModule::auctions_info(pid, bidder).expect("Bid should exist"); + let stored_bid = + FundingModule::auctions_info(pid, bidder).expect("Bid should exist"); assert!( matches!( stored_bid[0], @@ -1481,12 +1510,12 @@ mod community_round_success { let community_funding_project = CommunityFundingProject::new_default(&test_env); const BOB: AccountId = 808; test_env.ext_env.borrow_mut().execute_with(|| { - let bob_balance = ::NativeCurrency::reserved_balance(&BOB); + let bob_balance = + ::NativeCurrency::reserved_balance(&BOB); let stop = "here"; }); - let remaining_ct = community_funding_project - .get_project_info() - .remaining_contribution_tokens; + let remaining_ct = + community_funding_project.get_project_info().remaining_contribution_tokens; let ct_price = community_funding_project .get_project_info() .weighted_average_price @@ -1512,12 +1541,7 @@ mod community_round_success { .expect("The Buyer should be able to buy the exact amount of remaining CTs"); test_env.advance_time(2u64); // Check remaining CTs is 0 - assert_eq!( - community_funding_project - .get_project_info() - .remaining_contribution_tokens, - 0 - ); + assert_eq!(community_funding_project.get_project_info().remaining_contribution_tokens, 0); // Check project is in FundingEnded state assert_eq!( @@ -1534,10 +1558,8 @@ mod community_round_success { let community_funding_project = CommunityFundingProject::new_default(&test_env); const BOB: AccountId = 808; - let remaining_ct = community_funding_project - .get_project_info() - .remaining_contribution_tokens - + 40; // Overbuy + let remaining_ct = + community_funding_project.get_project_info().remaining_contribution_tokens + 40; // Overbuy let ct_price = community_funding_project .get_project_info() .weighted_average_price @@ -1556,12 +1578,7 @@ mod community_round_success { test_env.advance_time(2u64); // Check remaining CTs is 0 - assert_eq!( - community_funding_project - .get_project_info() - .remaining_contribution_tokens, - 0 - ); + assert_eq!(community_funding_project.get_project_info().remaining_contribution_tokens, 0); // Check project is in FundingEnded state assert_eq!( @@ -1576,20 +1593,21 @@ mod community_round_success { fn contribution_is_returned_on_limit_reached_same_mult_diff_ct() { let test_env = TestEnvironment::new(); let project = CommunityFundingProject::new_default(&test_env); - let buyer_2_initial_balance = test_env - .ext_env - .borrow_mut() - .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); + let buyer_2_initial_balance = test_env.ext_env.borrow_mut().execute_with(|| { + ::NativeCurrency::free_balance(&BUYER_2) + }); let project_details = project.get_project_info(); // Create a contribution that will reach the limit of contributions for a user-project let multiplier: Option> = None; let token_amount: BalanceOf = 1; let range = 0..::MaxContributionsPerUser::get(); - let contributions: UserToContribution = range.map(|_| (BUYER_2, (token_amount, multiplier))).collect(); + let contributions: UserToContribution = + range.map(|_| (BUYER_2, (token_amount, multiplier))).collect(); // Calculate currencies being transferred and bonded - let contribution_ticket_size = token_amount * project_details.weighted_average_price.unwrap(); + let contribution_ticket_size = + token_amount * project_details.weighted_average_price.unwrap(); let plmc_bond = multiplier .unwrap_or_default() .calculate_bonding_requirement(contribution_ticket_size) @@ -1599,24 +1617,24 @@ mod community_round_success { project.buy_for_retail_users(contributions.clone()).unwrap(); // Check that the right amount of PLMC is bonded, and funding currency is transferred - let buyer_2_post_buy_balance = test_env - .ext_env - .borrow_mut() - .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); + let buyer_2_post_buy_balance = test_env.ext_env.borrow_mut().execute_with(|| { + ::NativeCurrency::free_balance(&BUYER_2) + }); assert_eq!( buyer_2_post_buy_balance, - buyer_2_initial_balance - (contribution_ticket_size + plmc_bond) * contributions.len() as u128 + buyer_2_initial_balance - + (contribution_ticket_size + plmc_bond) * contributions.len() as u128 ); - let plmc_bond_stored = test_env - .ext_env - .borrow_mut() - .execute_with(|| crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap()); + let plmc_bond_stored = test_env.ext_env.borrow_mut().execute_with(|| { + crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap() + }); assert_eq!(plmc_bond_stored.amount, plmc_bond * contributions.len() as u128); // Make a new contribution with a PLMC bond bigger than the lowest bond already in store for that account let new_multiplier: Option> = None; let new_token_amount: BalanceOf = 2; - let new_contribution: UserToContribution = vec![(BUYER_2, (new_token_amount, new_multiplier))]; + let new_contribution: UserToContribution = + vec![(BUYER_2, (new_token_amount, new_multiplier))]; let new_ticket_size = new_token_amount * project_details.weighted_average_price.unwrap(); let new_plmc_bond = new_multiplier .unwrap_or_default() @@ -1626,18 +1644,17 @@ mod community_round_success { project.buy_for_retail_users(new_contribution.clone()).unwrap(); // Check that the previous contribution returned the reserved PLMC and the transferred funding currency - let buyer_2_post_return_balance = test_env - .ext_env - .borrow_mut() - .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); + let buyer_2_post_return_balance = test_env.ext_env.borrow_mut().execute_with(|| { + ::NativeCurrency::free_balance(&BUYER_2) + }); assert_eq!( buyer_2_post_return_balance, - buyer_2_post_buy_balance + (contribution_ticket_size + plmc_bond) - (new_ticket_size + new_plmc_bond) + buyer_2_post_buy_balance + (contribution_ticket_size + plmc_bond) - + (new_ticket_size + new_plmc_bond) ); - let new_plmc_bond_stored = test_env - .ext_env - .borrow_mut() - .execute_with(|| crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap()); + let new_plmc_bond_stored = test_env.ext_env.borrow_mut().execute_with(|| { + crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap() + }); assert_eq!( new_plmc_bond_stored.amount, plmc_bond_stored.amount - plmc_bond + new_plmc_bond @@ -1648,20 +1665,21 @@ mod community_round_success { fn contribution_is_returned_on_limit_reached_diff_mult_same_ct() { let test_env = TestEnvironment::new(); let project = CommunityFundingProject::new_default(&test_env); - let buyer_2_initial_balance = test_env - .ext_env - .borrow_mut() - .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); + let buyer_2_initial_balance = test_env.ext_env.borrow_mut().execute_with(|| { + ::NativeCurrency::free_balance(&BUYER_2) + }); let project_details = project.get_project_info(); // Create a contribution that will reach the limit of contributions for a user-project let multiplier: Option> = Some(Multiplier(2)); let token_amount: BalanceOf = 1; let range = 0..::MaxContributionsPerUser::get(); - let contributions: UserToContribution = range.map(|_| (BUYER_2, (token_amount, multiplier))).collect(); + let contributions: UserToContribution = + range.map(|_| (BUYER_2, (token_amount, multiplier))).collect(); // Calculate currencies being transferred and bonded - let contribution_ticket_size = token_amount * project_details.weighted_average_price.unwrap(); + let contribution_ticket_size = + token_amount * project_details.weighted_average_price.unwrap(); let plmc_bond = multiplier .unwrap_or_default() .calculate_bonding_requirement(contribution_ticket_size) @@ -1671,24 +1689,24 @@ mod community_round_success { project.buy_for_retail_users(contributions.clone()).unwrap(); // Check that the right amount of PLMC is bonded, and funding currency is transferred - let buyer_2_post_buy_balance = test_env - .ext_env - .borrow_mut() - .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); + let buyer_2_post_buy_balance = test_env.ext_env.borrow_mut().execute_with(|| { + ::NativeCurrency::free_balance(&BUYER_2) + }); assert_eq!( buyer_2_post_buy_balance, - buyer_2_initial_balance - (contribution_ticket_size + plmc_bond) * contributions.len() as u128 + buyer_2_initial_balance - + (contribution_ticket_size + plmc_bond) * contributions.len() as u128 ); - let plmc_bond_stored = test_env - .ext_env - .borrow_mut() - .execute_with(|| crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap()); + let plmc_bond_stored = test_env.ext_env.borrow_mut().execute_with(|| { + crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap() + }); assert_eq!(plmc_bond_stored.amount, plmc_bond * contributions.len() as u128); // Make a new contribution with a PLMC bond bigger than the lowest bond already in store for that account let new_multiplier: Option> = Some(Multiplier(1)); let new_token_amount: BalanceOf = 1; - let new_contribution: UserToContribution = vec![(BUYER_2, (new_token_amount, new_multiplier))]; + let new_contribution: UserToContribution = + vec![(BUYER_2, (new_token_amount, new_multiplier))]; let new_ticket_size = new_token_amount * project_details.weighted_average_price.unwrap(); let new_plmc_bond = new_multiplier .unwrap_or_default() @@ -1698,18 +1716,17 @@ mod community_round_success { project.buy_for_retail_users(new_contribution.clone()).unwrap(); // Check that the previous contribution returned the reserved PLMC and the transferred funding currency - let buyer_2_post_return_balance = test_env - .ext_env - .borrow_mut() - .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); + let buyer_2_post_return_balance = test_env.ext_env.borrow_mut().execute_with(|| { + ::NativeCurrency::free_balance(&BUYER_2) + }); assert_eq!( buyer_2_post_return_balance, - buyer_2_post_buy_balance + (contribution_ticket_size + plmc_bond) - (new_ticket_size + new_plmc_bond) + buyer_2_post_buy_balance + (contribution_ticket_size + plmc_bond) - + (new_ticket_size + new_plmc_bond) ); - let new_plmc_bond_stored = test_env - .ext_env - .borrow_mut() - .execute_with(|| crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap()); + let new_plmc_bond_stored = test_env.ext_env.borrow_mut().execute_with(|| { + crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap() + }); assert_eq!( new_plmc_bond_stored.amount, plmc_bond_stored.amount - plmc_bond + new_plmc_bond @@ -1770,14 +1787,16 @@ mod purchased_vesting { .unwrap_or_default() .calculate_bonding_requirement(token_amount * price) .unwrap(); - let actual_bonded_plmc = Balances::reserved_balance_named(&BondType::Contributing, &buyer); + let actual_bonded_plmc = + Balances::reserved_balance_named(&BondType::Contributing, &buyer); assert_eq!(theoretical_bonded_plmc, actual_bonded_plmc); assert_ok!(FundingModule::vested_plmc_purchase_unbond_for( RuntimeOrigin::signed(buyer), project_id, buyer )); - let actual_bonded_plmc = Balances::reserved_balance_named(&BondType::Contributing, &buyer); + let actual_bonded_plmc = + Balances::reserved_balance_named(&BondType::Contributing, &buyer); assert_eq!(actual_bonded_plmc, 0u32.into()); } }); @@ -1826,14 +1845,16 @@ mod bids_vesting { .unwrap_or_default() .calculate_bonding_requirement(amount * price) .unwrap(); - let actual_bonded_plmc = Balances::reserved_balance_named(&BondType::Bidding, &bidder); + let actual_bonded_plmc = + Balances::reserved_balance_named(&BondType::Bidding, &bidder); assert_eq!(theoretical_bonded_plmc, actual_bonded_plmc); assert_ok!(FundingModule::vested_plmc_bid_unbond_for( RuntimeOrigin::signed(bidder), project_id, bidder )); - let actual_bonded_plmc = Balances::reserved_balance_named(&BondType::Bidding, &bidder); + let actual_bonded_plmc = + Balances::reserved_balance_named(&BondType::Bidding, &bidder); assert_eq!(actual_bonded_plmc, 0u32.into()); } }); diff --git a/pallets/funding/src/types.rs b/pallets/funding/src/types.rs index a0fe9ab4a..4c376e256 100644 --- a/pallets/funding/src/types.rs +++ b/pallets/funding/src/types.rs @@ -18,8 +18,7 @@ //! Types for Funding pallet. -use crate::traits::BondingRequirementCalculation; -use crate::BalanceOf; +use crate::{traits::BondingRequirementCalculation, BalanceOf}; use frame_support::{pallet_prelude::*, traits::tokens::Balance as BalanceT}; use sp_arithmetic::traits::Saturating; use sp_runtime::traits::CheckedDiv; @@ -76,7 +75,7 @@ impl ProjectMetadata Result<(), ValidityError> { if self.minimum_price == Balance::zero() { - return Err(ValidityError::PriceTooLow); + return Err(ValidityError::PriceTooLow) } self.ticket_size.is_valid()?; self.participants_size.is_valid()?; @@ -94,13 +93,13 @@ impl TicketSize { fn is_valid(&self) -> Result<(), ValidityError> { if self.minimum.is_some() && self.maximum.is_some() { if self.minimum < self.maximum { - return Ok(()); + return Ok(()) } else { - return Err(ValidityError::TicketSizeError); + return Err(ValidityError::TicketSizeError) } } if self.minimum.is_some() || self.maximum.is_some() { - return Ok(()); + return Ok(()) } Err(ValidityError::TicketSizeError) @@ -116,20 +115,18 @@ pub struct ParticipantsSize { impl ParticipantsSize { fn is_valid(&self) -> Result<(), ValidityError> { match (self.minimum, self.maximum) { - (Some(min), Some(max)) => { + (Some(min), Some(max)) => if min < max && min > 0 && max > 0 { Ok(()) } else { Err(ValidityError::ParticipantsSizeError) - } - } - (Some(elem), None) | (None, Some(elem)) => { + }, + (Some(elem), None) | (None, Some(elem)) => if elem > 0 { Ok(()) } else { Err(ValidityError::ParticipantsSizeError) - } - } + }, (None, None) => Err(ValidityError::ParticipantsSizeError), } } @@ -201,7 +198,15 @@ impl BlockNumberPair { } #[derive(Default, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)] -pub struct BidInfo { +pub struct BidInfo< + BidId, + ProjectId, + Balance: BalanceT, + AccountId, + BlockNumber, + PlmcVesting, + CTVesting, +> { pub bid_id: BidId, pub project: ProjectId, #[codec(compact)] @@ -225,8 +230,14 @@ impl { pub fn new( - bid_id: BidId, project: ProjectId, amount: Balance, price: Balance, when: BlockNumber, bidder: AccountId, - plmc_vesting_period: PlmcVesting, ct_vesting_period: CTVesting, + bid_id: BidId, + project: ProjectId, + amount: Balance, + price: Balance, + when: BlockNumber, + bidder: AccountId, + plmc_vesting_period: PlmcVesting, + ct_vesting_period: CTVesting, ) -> Self { let ticket_size = amount.saturating_mul(price); Self { @@ -246,16 +257,32 @@ impl - sp_std::cmp::Ord for BidInfo +impl< + BidId: Eq, + ProjectId: Eq, + Balance: BalanceT, + AccountId: Eq, + BlockNumber: Eq, + PlmcVesting: Eq, + CTVesting: Eq, + > sp_std::cmp::Ord + for BidInfo { fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering { self.price.cmp(&other.price) } } -impl - sp_std::cmp::PartialOrd for BidInfo +impl< + BidId: Eq, + ProjectId: Eq, + Balance: BalanceT, + AccountId: Eq, + BlockNumber: Eq, + PlmcVesting: Eq, + CTVesting: Eq, + > sp_std::cmp::PartialOrd + for BidInfo { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) @@ -323,7 +350,19 @@ pub enum RejectionReason { } /// Enum used to identify PLMC named reserves -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen, Copy, Ord, PartialOrd)] +#[derive( + Clone, + Encode, + Decode, + Eq, + PartialEq, + RuntimeDebug, + TypeInfo, + MaxEncodedLen, + Copy, + Ord, + PartialOrd, +)] pub enum BondType { Evaluation, Bidding, @@ -389,7 +428,19 @@ impl< } /// Tells on_initialize what to do with the project -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen, Copy, Ord, PartialOrd)] +#[derive( + Clone, + Encode, + Decode, + Eq, + PartialEq, + RuntimeDebug, + TypeInfo, + MaxEncodedLen, + Copy, + Ord, + PartialOrd, +)] pub enum UpdateType { EvaluationEnd, EnglishAuctionStart, @@ -399,7 +450,19 @@ pub enum UpdateType { FundingEnd, } -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen, Copy, Ord, PartialOrd)] +#[derive( + Clone, + Encode, + Decode, + Eq, + PartialEq, + RuntimeDebug, + TypeInfo, + MaxEncodedLen, + Copy, + Ord, + PartialOrd, +)] pub struct Multiplier(pub T::Balance); impl BondingRequirementCalculation for Multiplier { fn calculate_bonding_requirement(&self, ticket_size: BalanceOf) -> Result, ()> { diff --git a/pallets/sandbox/Cargo.toml b/pallets/sandbox/Cargo.toml index 2fbc67cbf..a0cc28996 100644 --- a/pallets/sandbox/Cargo.toml +++ b/pallets/sandbox/Cargo.toml @@ -23,7 +23,6 @@ frame-system.workspace = true sp-std.workspace = true sp-runtime.workspace = true sp-arithmetic.workspace = true -polimec-traits.workspace = true parachains-common.workspace = true pallet-funding.workspace = true @@ -57,7 +56,6 @@ std = [ "sp-runtime/std", "pallet-assets/std", "pallet-balances/std", - "polimec-traits/std", "frame-benchmarking?/std", "parachains-common/std", ] diff --git a/pallets/sandbox/src/lib.rs b/pallets/sandbox/src/lib.rs index 97ec6cbff..a5e2961ec 100644 --- a/pallets/sandbox/src/lib.rs +++ b/pallets/sandbox/src/lib.rs @@ -27,13 +27,15 @@ pub mod pallet { /// Buy tokens for a project in the community round if it achieved at least 500k USDT funding #[pallet::weight(0)] pub fn buy_if_popular( - origin: OriginFor, project_id: ::ProjectIdParameter, + origin: OriginFor, + project_id: ::ProjectIdParameter, amount: ::Balance, ) -> DispatchResult { let retail_user = ensure_signed(origin)?; let project_id: ::ProjectIdentifier = project_id.into(); // Check project is in the community round - let project_info = funding::Pallet::::project_info(project_id).ok_or(Error::::ProjectNotFound)?; + let project_info = funding::Pallet::::project_info(project_id) + .ok_or(Error::::ProjectNotFound)?; ensure!( project_info.project_status == funding::ProjectStatus::CommunityRound, "Project is not in the community round" @@ -41,11 +43,12 @@ pub mod pallet { // Calculate how much funding was done already let project_contributions: ::Balance = - funding::Contributions::::iter_prefix_values(project_id) - .flatten() - .fold(0u64.into(), |total_tokens_bought, contribution| { + funding::Contributions::::iter_prefix_values(project_id).flatten().fold( + 0u64.into(), + |total_tokens_bought, contribution| { total_tokens_bought + contribution.contribution_amount - }); + }, + ); ensure!( project_contributions >= 500_000_0_000_000_000u64.into(), diff --git a/pallets/sandbox/src/mock.rs b/pallets/sandbox/src/mock.rs index f23912681..278414096 100644 --- a/pallets/sandbox/src/mock.rs +++ b/pallets/sandbox/src/mock.rs @@ -173,16 +173,11 @@ impl pallet_funding::Config for TestRuntime { // TODO: PLMC-161. Add some mocks projects at Genesis to simplify the tests #[allow(dead_code)] pub fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - GenesisConfig { - balances: BalancesConfig { balances: vec![] }, - ..Default::default() - } - .assimilate_storage(&mut t) - .unwrap(); + GenesisConfig { balances: BalancesConfig { balances: vec![] }, ..Default::default() } + .assimilate_storage(&mut t) + .unwrap(); let mut ext = sp_io::TestExternalities::new(t); // In order to emit events the block number must be more than 0 diff --git a/pallets/sandbox/src/tests.rs b/pallets/sandbox/src/tests.rs index c6ef58158..52ee116a2 100644 --- a/pallets/sandbox/src/tests.rs +++ b/pallets/sandbox/src/tests.rs @@ -43,18 +43,12 @@ fn test_buy_if_popular() { >::on_initialize(System::block_number()); } - assert_ok!(FundingModule::bid( - RuntimeOrigin::signed(bidder), - 0, - 1000, - 100 * PLMC, - None - )); + assert_ok!(FundingModule::bid(RuntimeOrigin::signed(bidder), 0, 1000, 100 * PLMC, None)); // advance time - for _block in 0..(::EnglishAuctionDuration::get() - + ::CandleAuctionDuration::get() - + 5) + for _block in 0..(::EnglishAuctionDuration::get() + + ::CandleAuctionDuration::get() + + 5) { >::on_finalize(System::block_number()); >::on_idle(System::block_number(), Weight::MAX); @@ -62,21 +56,11 @@ fn test_buy_if_popular() { >::on_initialize(System::block_number()); } - assert_ok!(FundingModule::contribute( - RuntimeOrigin::signed(contributor), - 0, - 1, - None - )); + assert_ok!(FundingModule::contribute(RuntimeOrigin::signed(contributor), 0, 1, None)); assert!(Sandbox::buy_if_popular(RuntimeOrigin::signed(4), 0, 1000).is_err()); - assert_ok!(FundingModule::contribute( - RuntimeOrigin::signed(contributor), - 0, - 10000, - None - )); + assert_ok!(FundingModule::contribute(RuntimeOrigin::signed(contributor), 0, 10000, None)); assert_ok!(Sandbox::buy_if_popular(RuntimeOrigin::signed(4), 0, 1000)); }); @@ -92,21 +76,17 @@ const METADATA: &str = r#" "usage_of_founds":"ipfs_url" }"#; -pub fn default_project(nonce: u64) -> ProjectMetadata>, u128, sp_core::H256> { +pub fn default_project( + nonce: u64, +) -> ProjectMetadata>, u128, sp_core::H256> { let bounded_name = BoundedVec::try_from("Contribution Token TEST".as_bytes().to_vec()).unwrap(); let bounded_symbol = BoundedVec::try_from("CTEST".as_bytes().to_vec()).unwrap(); let metadata_hash = hashed(format!("{}-{}", METADATA, nonce)); ProjectMetadata { total_allocation_size: 1_000_000, minimum_price: 1 * PLMC, - ticket_size: TicketSize { - minimum: Some(1), - maximum: None, - }, - participants_size: ParticipantsSize { - minimum: Some(2), - maximum: None, - }, + ticket_size: TicketSize { minimum: Some(1), maximum: None }, + participants_size: ParticipantsSize { minimum: Some(2), maximum: None }, funding_thresholds: Default::default(), conversion_rate: 0, participation_currencies: Default::default(), @@ -120,9 +100,7 @@ pub fn default_project(nonce: u64) -> ProjectMetadata sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); GenesisConfig { balances: BalancesConfig { diff --git a/polimec-skeleton/pallets/funding/src/mock.rs b/polimec-skeleton/pallets/funding/src/mock.rs index 052274a20..9643e64aa 100644 --- a/polimec-skeleton/pallets/funding/src/mock.rs +++ b/polimec-skeleton/pallets/funding/src/mock.rs @@ -90,7 +90,6 @@ parameter_types! { // https://github.com/paritytech/substrate/blob/069917b/frame/assets/src/lib.rs#L257L271 pub const MetadataDepositBase: Balance = free_deposit(); pub const MetadataDepositPerByte: Balance = free_deposit(); - pub const AssetsPalletId: PalletId = PalletId(*b"assetsid"); pub const ApprovalDeposit: Balance = EXISTENTIAL_DEPOSIT; } diff --git a/primitives/xcm/Cargo.toml b/primitives/xcm/Cargo.toml deleted file mode 100644 index ab131c9e8..000000000 --- a/primitives/xcm/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "xcm-primitives" -version = "0.0.1" -edition = "2021" - -[dependencies] -sp-std.workspace = true - -xcm.workspace = true -xcm-executor.workspace = true - -[features] -default = [ "std" ] -std = [ - "sp-std/std", - "xcm/std", - "xcm-executor/std" -] diff --git a/primitives/xcm/src/lib.rs b/primitives/xcm/src/lib.rs deleted file mode 100644 index e653cdc4d..000000000 --- a/primitives/xcm/src/lib.rs +++ /dev/null @@ -1,63 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -#![cfg_attr(not(feature = "std"), no_std)] - -use sp_std::{borrow::Borrow, marker::PhantomData}; -use xcm::latest::{AssetId::Concrete, Fungibility::Fungible, MultiAsset, MultiLocation}; -use xcm_executor::traits::{Convert, Error as MatchError, MatchesFungibles}; - -pub struct AsAssetMultiLocation(PhantomData<(AssetId, AssetIdInfoGetter)>); -impl xcm_executor::traits::Convert - for AsAssetMultiLocation -where - AssetId: Clone, - AssetIdInfoGetter: AssetMultiLocationGetter, -{ - fn convert_ref(asset_multi_location: impl Borrow) -> Result { - AssetIdInfoGetter::get_asset_id(asset_multi_location.borrow().clone()).ok_or(()) - } - - fn reverse_ref(asset_id: impl Borrow) -> Result { - AssetIdInfoGetter::get_asset_multi_location(asset_id.borrow().clone()).ok_or(()) - } -} - -pub trait AssetMultiLocationGetter { - fn get_asset_multi_location(asset_id: AssetId) -> Option; - fn get_asset_id(asset_multi_location: MultiLocation) -> Option; -} - -pub struct ConvertedRegisteredAssetId( - PhantomData<(AssetId, Balance, ConvertAssetId, ConvertBalance)>, -); -impl< - AssetId: Clone, - Balance: Clone, - ConvertAssetId: Convert, - ConvertBalance: Convert, - > MatchesFungibles for ConvertedRegisteredAssetId -{ - fn matches_fungibles(a: &MultiAsset) -> Result<(AssetId, Balance), MatchError> { - let (amount, id) = match (&a.fun, &a.id) { - (Fungible(ref amount), Concrete(ref id)) => (amount, id), - _ => return Err(MatchError::AssetNotFound), - }; - let what = ConvertAssetId::convert_ref(id).map_err(|_| MatchError::AssetNotFound)?; - let amount = ConvertBalance::convert_ref(amount).map_err(|_| MatchError::AmountToBalanceConversionFailed)?; - Ok((what, amount)) - } -} diff --git a/runtimes/base/Cargo.toml b/runtimes/base/Cargo.toml index 73809d8af..51e0309a4 100644 --- a/runtimes/base/Cargo.toml +++ b/runtimes/base/Cargo.toml @@ -14,7 +14,7 @@ version.workspace = true substrate-wasm-builder.workspace = true [dependencies] -parity-scale-codec = { version = "3.3.0", default-features = false, features = [ +parity-scale-codec = { version = "3.3.0", default-features = false, features = [ "derive", ] } hex-literal = { version = "0.3.4", optional = true } @@ -25,6 +25,8 @@ scale-info = { version = "2.3.1", default-features = false, features = [ smallvec = "1.10.0" # Local +pallet-parachain-staking.workspace = true +shared-configuration.workspace = true # Substrate frame-benchmarking = { workspace = true, optional = true } @@ -43,6 +45,7 @@ pallet-sudo.workspace = true pallet-timestamp.workspace = true pallet-transaction-payment.workspace = true pallet-transaction-payment-rpc-runtime-api.workspace = true +sp-arithmetic.workspace = true sp-api.workspace = true sp-block-builder.workspace = true sp-consensus-aura.workspace = true @@ -99,6 +102,8 @@ std = [ "frame-support/std", "frame-system-rpc-runtime-api/std", "frame-system/std", + "pallet-parachain-staking/std", + "parachains-common/std", "pallet-aura/std", "pallet-authorship/std", "pallet-balances/std", @@ -112,6 +117,7 @@ std = [ "parachain-info/std", "polkadot-parachain/std", "polkadot-runtime-common/std", + "sp-arithmetic/std", "sp-api/std", "sp-block-builder/std", "sp-consensus-aura/std", @@ -122,6 +128,7 @@ std = [ "sp-session/std", "sp-std/std", "sp-transaction-pool/std", + "shared-configuration/std", "sp-version/std", "xcm-builder/std", "xcm-executor/std", diff --git a/runtimes/base/src/currency.rs b/runtimes/base/src/currency.rs deleted file mode 100644 index 3d89c4f25..000000000 --- a/runtimes/base/src/currency.rs +++ /dev/null @@ -1,14 +0,0 @@ -use crate::Balance; - -/// One PLMC -pub const PLMC: Balance = 10u128.pow(10); -/// 0.001 PLMC -pub const MILLI_PLMC: Balance = 10u128.pow(7); -/// 0.000_001 PLMC -pub const MICRO_PLMC: Balance = 10u128.pow(4); - -pub const EXISTENTIAL_DEPOSIT: Balance = MILLI_PLMC; - -pub const fn deposit(items: u32, bytes: u32) -> Balance { - (items as Balance * 20 * PLMC + (bytes as Balance) * 100 * MICRO_PLMC) / 100 -} \ No newline at end of file diff --git a/runtimes/base/src/lib.rs b/runtimes/base/src/lib.rs index 230849198..63fb89b54 100644 --- a/runtimes/base/src/lib.rs +++ b/runtimes/base/src/lib.rs @@ -24,17 +24,11 @@ extern crate frame_benchmarking; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use frame_support::{ - construct_runtime, - dispatch::DispatchClass, - parameter_types, - traits::{ConstU32, ConstU64, Everything}, + construct_runtime, parameter_types, + traits::Everything, weights::{ConstantMultiplier, Weight}, - PalletId, -}; -use frame_system::{ - limits::{BlockLength, BlockWeights}, - EnsureRoot, }; +use frame_system::EnsureRoot; use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; use sp_api::impl_runtime_apis; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -43,7 +37,10 @@ use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; pub use sp_runtime::BuildStorage; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, OpaqueKeys, Verify}, + traits::{ + AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, OpaqueKeys, + Verify, + }, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, MultiSignature, }; @@ -52,22 +49,20 @@ use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; + // XCM Imports -use parachains_common::AVERAGE_ON_INITIALIZE_RATIO; -use parachains_common::HOURS; -use parachains_common::MAXIMUM_BLOCK_WEIGHT; -use parachains_common::NORMAL_DISPATCH_RATIO; -use parachains_common::SLOT_DURATION; -use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; -use xcm::latest::prelude::BodyId; use xcm_config::{XcmConfig, XcmOriginToTransactDispatchOrigin}; use xcm_executor::XcmExecutor; +// Polimec Shared Imports +pub use shared_configuration::{currency::*, fee::*, governance::*, staking::*, weights::*}; + +pub use pallet_parachain_staking; + // Make the WASM binary available. #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -mod weights; pub mod xcm_config; /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. @@ -117,122 +112,20 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = - frame_executive::Executive, Runtime, AllPalletsWithSystem>; - -pub mod fee { - use super::{currency::MICRO_PLMC, Balance, ExtrinsicBaseWeight}; - use frame_support::weights::{Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}; - use smallvec::smallvec; - use sp_arithmetic::traits::{BaseArithmetic, Unsigned}; - use sp_runtime::{Perbill, SaturatedConversion}; - - /// Handles converting a weight scalar to a fee value, based on the scale and granularity of the - /// node's balance type. - /// - /// This should typically create a mapping between the following ranges: - /// - `[0, MAXIMUM_BLOCK_WEIGHT]` - /// - `[Balance::min, Balance::max]` - /// - /// Yet, it can be used for any other sort of change to weight-fee. Some examples being: - /// - Setting it to `0` will essentially disable the weight fee. - /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. - pub struct WeightToFee; - impl frame_support::weights::WeightToFee for WeightToFee { - type Balance = Balance; - - fn weight_to_fee(weight: &Weight) -> Self::Balance { - let ref_time = Balance::saturated_from(weight.ref_time()); - let proof_size = Balance::saturated_from(weight.proof_size()); - - let ref_polynomial = RefTimeToFee::polynomial(); - let proof_polynomial = ProofSizeToFee::polynomial(); - - // Get fee amount from ref_time based on the RefTime polynomial - let ref_fee: Balance = ref_polynomial - .iter() - .fold(0, |acc, term| term.saturating_eval(acc, ref_time)); - - // Get fee amount from proof_size based on the ProofSize polynomial - let proof_fee: Balance = proof_polynomial - .iter() - .fold(0, |acc, term| term.saturating_eval(acc, proof_size)); - - // Take the maximum instead of the sum to charge by the more scarce resource. - ref_fee.max(proof_fee) - } - } - - /// Maps the Ref time component of `Weight` to a fee. - pub struct RefTimeToFee; - impl WeightToFeePolynomial for RefTimeToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 MILLIUNIT: - // in our template, we map to 1/10 of that, or 1/10 MILLIUNIT - let p = MILLIUNIT / 10; - let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); - smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } - } - - /// Maps the proof size component of `Weight` to a fee. - pub struct ProofSizeToFee; - impl WeightToFeePolynomial for ProofSizeToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - // Map 10kb proof to 1 CENT. - let p = MILLIUNIT / 10; - let q = 10_000; - - smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } - } - - // TODO: Refactor out this code to use `FeePolynomial` on versions using polkadot-v0.9.42 and above: - pub trait WeightCoefficientCalc { - fn saturating_eval(&self, result: Balance, x: Balance) -> Balance; - } - - impl WeightCoefficientCalc for WeightToFeeCoefficient - where - Balance: BaseArithmetic + From + Copy + Unsigned + SaturatedConversion, - { - fn saturating_eval(&self, mut result: Balance, x: Balance) -> Balance { - let power = x.saturating_pow(self.degree.into()); - - let frac = self.coeff_frac * power; // Overflow safe since coeff_frac is strictly less than 1. - let integer = self.coeff_integer.saturating_mul(power); - // Do not add them together here to avoid an underflow. - - if self.negative { - result = result.saturating_sub(frac); - result = result.saturating_sub(integer); - } else { - result = result.saturating_add(frac); - result = result.saturating_add(integer); - } - - result - } - } -} +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPalletsWithSystem, +>; /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know /// the specifics of the runtime. They can then be made to be agnostic over specific formats @@ -272,39 +165,11 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { - NativeVersion { - runtime_version: VERSION, - can_author_with: Default::default(), - } + NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } } parameter_types! { pub const Version: RuntimeVersion = VERSION; - - // This part is copied from Substrate's `bin/node/runtime/src/lib.rs`. - // The `RuntimeBlockLength` and `RuntimeBlockWeights` exist here because the - // `DeletionWeightLimit` and `DeletionQueueDepth` depend on those to parameterize - // the lazy contract deletion. - pub RuntimeBlockLength: BlockLength = - BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); - pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder() - .base_block(BlockExecutionWeight::get()) - .for_class(DispatchClass::all(), |weights| { - weights.base_extrinsic = ExtrinsicBaseWeight::get(); - }) - .for_class(DispatchClass::Normal, |weights| { - weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); - }) - .for_class(DispatchClass::Operational, |weights| { - weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); - // Operational transactions have some extra reserved space, so that they - // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. - weights.reserved = Some( - MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT - ); - }) - .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) - .build_or_panic(); pub const SS58Prefix: u16 = 42; } @@ -359,58 +224,39 @@ impl frame_system::Config for Runtime { type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; type MaxConsumers = frame_support::traits::ConstU32<16>; } -parameter_types! { - pub const UncleGenerations: u32 = 0; -} impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; + type MinimumPeriod = MinimumPeriod; type WeightInfo = (); } impl pallet_authorship::Config for Runtime { type FindAuthor = pallet_session::FindAccountFromAuthorIndex; - type EventHandler = (); -} - -parameter_types! { - pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT; + type EventHandler = ParachainStaking; } impl pallet_balances::Config for Runtime { - type MaxLocks = ConstU32<50>; - /// The type for recording an account's balance. type Balance = Balance; - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; - type WeightInfo = pallet_balances::weights::SubstrateWeight; - type MaxReserves = ConstU32<50>; - type ReserveIdentifier = [u8; 8]; -} - -parameter_types! { - /// Relay Chain `TransactionByteFee` / 10 - pub const TransactionByteFee: Balance = 10 * MICRO_PLMC; + type MaxLocks = MaxLocks; + type MaxReserves = MaxReserves; + type ReserveIdentifier = (); + type WeightInfo = (); } impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter>; + type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; + type OperationalFeeMultiplier = frame_support::traits::ConstU8<5>; type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; - type OperationalFeeMultiplier = ConstU8<5>; -} - -parameter_types! { - pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); - pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); } impl cumulus_pallet_parachain_system::Config for Runtime { @@ -447,71 +293,52 @@ impl cumulus_pallet_dmp_queue::Config for Runtime { type ExecuteOverweightOrigin = EnsureRoot; } -parameter_types! { - pub const Period: u32 = 6 * HOURS; - pub const Offset: u32 = 0; -} - impl pallet_session::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ValidatorId = AccountId; type ValidatorIdOf = ConvertInto; - type ShouldEndSession = (); - type NextSessionRotation = (); - type SessionManager = (); + type ShouldEndSession = ParachainStaking; + type NextSessionRotation = ParachainStaking; + type SessionManager = ParachainStaking; type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; - // type WeightInfo = weights::pallet_session::WeightInfo; type WeightInfo = (); } impl pallet_aura::Config for Runtime { type AuthorityId = AuraId; type DisabledValidators = (); - type MaxAuthorities = ConstU32<100_000>; + type MaxAuthorities = MaxAuthorities; } -parameter_types! { - pub const PotId: PalletId = PalletId(*b"PotStake"); - pub const MaxCandidates: u32 = 1000; - pub const MinCandidates: u32 = 5; - pub const SessionLength: BlockNumber = 6 * HOURS; - pub const MaxInvulnerables: u32 = 100; - pub const ExecutiveBody: BodyId = BodyId::Executive; -} - -parameter_types! { - pub const ProposalBond: Permill = Permill::from_percent(5); - pub const ProposalBondMinimum: Balance = 20 * PLMC; - pub const SpendPeriod: BlockNumber = runtime_common::constants::governance::SPEND_PERIOD; - pub const Burn: Permill = Permill::zero(); - pub const MaxApprovals: u32 = 100; - pub const TreasuryId: PalletId = PalletId(*b"plmc/tsy"); -} - -impl pallet_treasury::Config for Runtime { - type PalletId = TreasuryId; - type Currency = Balances; - type ApproveOrigin = EnsureRoot; - type RejectOrigin = EnsureRoot; +impl pallet_sudo::Config for Runtime { + type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; - type OnSlash = Treasury; - type ProposalBond = ProposalBond; - type ProposalBondMinimum = ProposalBondMinimum; - type ProposalBondMaximum = (); - type SpendPeriod = SpendPeriod; - type SpendOrigin = frame_support::traits::NeverEnsureOrigin; - type Burn = Burn; - type BurnDestination = (); - type SpendFunds = (); - // type WeightInfo = weights::pallet_treasury::WeightInfo; - type WeightInfo = (); - type MaxApprovals = MaxApprovals; } -impl pallet_sudo::Config for Runtime { - type RuntimeCall = RuntimeCall; +impl pallet_parachain_staking::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type MonetaryGovernanceOrigin = frame_system::EnsureRoot; + type MinBlocksPerRound = MinBlocksPerRound; + type LeaveCandidatesDelay = LeaveCandidatesDelay; + type CandidateBondLessDelay = CandidateBondLessDelay; + type LeaveDelegatorsDelay = LeaveDelegatorsDelay; + type RevokeDelegationDelay = RevokeDelegationDelay; + type DelegationBondLessDelay = DelegationBondLessDelay; + type RewardPaymentDelay = RewardPaymentDelay; + type MinSelectedCandidates = MinSelectedCandidates; + type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; + type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate; + type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator; + type MinCandidateStk = MinCandidateStk; + type MinDelegatorStk = MinDelegatorStk; + type MinDelegation = MinDelegation; + type OnCollatorPayout = (); + // We use the default implementation, so we leave () here. + type PayoutCollatorReward = (); + type OnNewRound = (); + type WeightInfo = pallet_parachain_staking::weights::SubstrateWeight; } // Create the runtime by composing the FRAME pallets that were previously configured. @@ -531,15 +358,13 @@ construct_runtime!( // Monetary stuff. Balances: pallet_balances = 10, TransactionPayment: pallet_transaction_payment = 11, - Treasury: pallet_treasury = 12, - // Consensus support. - // The following order MUST NOT be changed: Aura -> Session -> Staking -> Authorship -> AuraExt - // Dependencies: AuraExt on Aura, Authorship and Session on ParachainStaking - Aura: pallet_aura = 23, - Session: pallet_session = 22, - Authorship: pallet_authorship = 20, - AuraExt: cumulus_pallet_aura_ext = 24, + // Collator support. the order of these 5 are important and shall not change. + Authorship: pallet_authorship::{Pallet, Storage} = 20, + Session: pallet_session::{Pallet, Call, Storage, Event, Config} = 22, + Aura: pallet_aura::{Pallet, Storage, Config} = 23, + AuraExt: cumulus_pallet_aura_ext::{Pallet, Storage, Config} = 24, + ParachainStaking: pallet_parachain_staking::{Pallet, Call, Storage, Event, Config} = 25, // XCM helpers. XcmpQueue: cumulus_pallet_xcmp_queue = 30, @@ -770,12 +595,13 @@ impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { .read_slot() .expect("Could not read the relay chain slot from the proof"); - let inherent_data = cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( - relay_chain_slot, - sp_std::time::Duration::from_secs(6), - ) - .create_inherent_data() - .expect("Could not create the timestamp inherent data"); + let inherent_data = + cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( + relay_chain_slot, + sp_std::time::Duration::from_secs(6), + ) + .create_inherent_data() + .expect("Could not create the timestamp inherent data"); inherent_data.check_extrinsics(block) } diff --git a/runtimes/base/src/xcm_config.rs b/runtimes/base/src/xcm_config.rs index c8d6ae879..ea8c1a842 100644 --- a/runtimes/base/src/xcm_config.rs +++ b/runtimes/base/src/xcm_config.rs @@ -15,8 +15,8 @@ // along with this program. If not, see . use super::{ - AccountId, AllPalletsWithSystem, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, - RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, + AccountId, AllPalletsWithSystem, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, + Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, }; use frame_support::{ match_types, parameter_types, @@ -29,10 +29,11 @@ use polkadot_parachain::primitives::Sibling; use polkadot_runtime_common::impls::ToAuthor; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, - EnsureXcmOrigin, FixedWeightBounds, IsConcrete, NativeAsset, ParentIsPreset, RelayChainAsNative, - SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, WithComputedOrigin, + AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowTopLevelPaidExecutionFrom, + CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, IsConcrete, NativeAsset, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + UsingComponents, WithComputedOrigin, }; use xcm_executor::XcmExecutor; @@ -133,7 +134,8 @@ impl xcm_executor::Config for XcmConfig { type UniversalLocation = UniversalLocation; type Barrier = Barrier; type Weigher = FixedWeightBounds; - type Trader = UsingComponents, RelayLocation, AccountId, Balances, ToAuthor>; + type Trader = + UsingComponents>; type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; type AssetClaims = PolkadotXcm; diff --git a/runtimes/shared-configuration/Cargo.toml b/runtimes/shared-configuration/Cargo.toml new file mode 100644 index 000000000..f52095e35 --- /dev/null +++ b/runtimes/shared-configuration/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "shared-configuration" +description = "Chain shared configuration Polimec" +authors.workspace = true +documentation.workspace = true +edition.workspace = true +homepage.workspace = true +license-file.workspace = true +readme.workspace = true +repository.workspace = true +version.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +smallvec.workspace = true + +# FRAME +frame-system.workspace = true +frame-support.workspace = true +sp-arithmetic.workspace = true +parachains-common.workspace = true + +[features] +default = ["std"] +fast-gov = [] +std = ["frame-support/std", "sp-arithmetic/std", "parachains-common/std"] +runtime-benchmarks = ["frame-support/runtime-benchmarks"] diff --git a/runtimes/testnet/src/weights/mod.rs b/runtimes/shared-configuration/src/assets.rs similarity index 59% rename from runtimes/testnet/src/weights/mod.rs rename to runtimes/shared-configuration/src/assets.rs index 40ae41d0a..6568a765b 100644 --- a/runtimes/testnet/src/weights/mod.rs +++ b/runtimes/shared-configuration/src/assets.rs @@ -14,15 +14,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -//! Expose the auto generated weight files. +use crate::{ + currency::{deposit, PLMC}, + Balance, +}; +use frame_support::parameter_types; -pub mod block_weights; -pub mod extrinsic_weights; -pub mod pallet_funding; -pub mod paritydb_weights; -pub mod rocksdb_weights; - -pub use block_weights::constants::BlockExecutionWeight; -pub use extrinsic_weights::constants::ExtrinsicBaseWeight; -pub use paritydb_weights::constants::ParityDbWeight; -pub use rocksdb_weights::constants::RocksDbWeight; +parameter_types! { + pub const AssetDeposit: Balance = 10 * PLMC; + pub const AssetsStringLimit: u32 = 50; + /// Key = 32 bytes, Value = 36 bytes (32+1+1+1+1) + // https://github.com/paritytech/substrate/blob/069917b/frame/assets/src/lib.rs#L257L271 + pub const MetadataDepositBase: Balance = deposit(1, 68); + pub const MetadataDepositPerByte: Balance = deposit(0, 1); + pub const AssetAccountDeposit: Balance = deposit(1, 18); +} diff --git a/runtimes/shared-configuration/src/currency.rs b/runtimes/shared-configuration/src/currency.rs new file mode 100644 index 000000000..bc401318a --- /dev/null +++ b/runtimes/shared-configuration/src/currency.rs @@ -0,0 +1,64 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +use crate::Balance; +use frame_support::parameter_types; + +/// One PLMC +pub const PLMC: Balance = 10u128.pow(10); +/// 0.001 PLMC +pub const MILLI_PLMC: Balance = 10u128.pow(7); +/// 0.000_001 PLMC +pub const MICRO_PLMC: Balance = 10u128.pow(4); + +pub const EXISTENTIAL_DEPOSIT: Balance = MILLI_PLMC; + +/// Deposit that must be provided for each occupied storage item. +pub const DEPOSIT_STORAGE_ITEM: Balance = 56 * MILLI_PLMC; +/// Deposit that must be provided for each occupied storage byte. +pub const DEPOSIT_STORAGE_BYTE: Balance = 100 * MICRO_PLMC; + +pub const fn deposit(items: u32, bytes: u32) -> Balance { + (items as Balance * DEPOSIT_STORAGE_ITEM + (bytes as Balance) * DEPOSIT_STORAGE_BYTE) / 100 +} + +#[inline(always)] +pub const fn free_deposit() -> Balance { + deposit(0, 0) +} + +parameter_types! { + /// Relay Chain `TransactionByteFee` / 10 + pub const TransactionByteFee: Balance = 10 * MICRO_PLMC; + pub const DepositBase: Balance = DEPOSIT_STORAGE_ITEM; + pub const DepositFactor: Balance = DEPOSIT_STORAGE_BYTE; + pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT; + pub const MaxSignatories: u32 = 64; + pub const MaxLocks: u32 = 50; + pub const MaxReserves: u32 = 50; +} + +pub mod vesting { + use frame_support::traits::WithdrawReasons; + + use super::*; + + parameter_types! { + pub const MinVestedTransfer: Balance = 10 * PLMC; + pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons = + WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); + } +} diff --git a/runtimes/shared-configuration/src/fee.rs b/runtimes/shared-configuration/src/fee.rs new file mode 100644 index 000000000..2fd88b717 --- /dev/null +++ b/runtimes/shared-configuration/src/fee.rs @@ -0,0 +1,48 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +use crate::{currency::MILLI_PLMC, Balance}; +use frame_support::{ + parameter_types, + weights::{ + constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients, + WeightToFeePolynomial, + }, +}; +use parachains_common::SLOT_DURATION; +use smallvec::smallvec; +use sp_arithmetic::Perbill; + +pub struct WeightToFee; +impl WeightToFeePolynomial for WeightToFee { + type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { + // extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: + let p = 10 * MILLI_PLMC; + let q = Balance::from(ExtrinsicBaseWeight::get().ref_time()); + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } +} + +parameter_types! { + pub const MinimumPeriod: u64 = SLOT_DURATION / 2; + pub const MaxAuthorities: u32 = 100_000; +} diff --git a/runtimes/shared-configuration/src/funding.rs b/runtimes/shared-configuration/src/funding.rs new file mode 100644 index 000000000..a1bf85ad0 --- /dev/null +++ b/runtimes/shared-configuration/src/funding.rs @@ -0,0 +1,64 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +use crate::{BlockNumber, DAYS}; +use frame_support::{parameter_types, PalletId}; + +#[cfg(feature = "fast-gov")] +pub const EVALUATION_DURATION: BlockNumber = 28; +#[cfg(not(feature = "fast-gov"))] +pub const EVALUATION_DURATION: BlockNumber = 28 * DAYS; + +#[cfg(feature = "fast-gov")] +pub const AUCTION_INITIALIZE_PERIOD_DURATION: BlockNumber = 7; +#[cfg(not(feature = "fast-gov"))] +pub const AUCTION_INITIALIZE_PERIOD_DURATION: BlockNumber = 7 * DAYS; + +#[cfg(feature = "fast-gov")] +pub const ENGLISH_AUCTION_DURATION: BlockNumber = 10; +#[cfg(not(feature = "fast-gov"))] +pub const ENGLISH_AUCTION_DURATION: BlockNumber = 2 * DAYS; + +#[cfg(feature = "fast-gov")] +pub const CANDLE_AUCTION_DURATION: BlockNumber = 5; +#[cfg(not(feature = "fast-gov"))] +pub const CANDLE_AUCTION_DURATION: BlockNumber = 3 * DAYS; + +#[cfg(feature = "fast-gov")] +pub const COMMUNITY_FUNDING_DURATION: BlockNumber = 10; +#[cfg(not(feature = "fast-gov"))] +pub const COMMUNITY_FUNDING_DURATION: BlockNumber = 5 * DAYS; + +#[cfg(feature = "fast-gov")] +pub const REMAINDER_FUNDING_DURATION: BlockNumber = 10; +#[cfg(not(feature = "fast-gov"))] +pub const REMAINDER_FUNDING_DURATION: BlockNumber = DAYS; + +#[cfg(feature = "fast-gov")] +pub const CONTRIBUTION_VESTING_DURATION: BlockNumber = 365; +#[cfg(not(feature = "fast-gov"))] +pub const CONTRIBUTION_VESTING_DURATION: BlockNumber = 365 * DAYS; + +parameter_types! { + pub const EvaluationDuration: BlockNumber = EVALUATION_DURATION; + pub const AuctionInitializePeriodDuration: BlockNumber = AUCTION_INITIALIZE_PERIOD_DURATION; + pub const EnglishAuctionDuration: BlockNumber = ENGLISH_AUCTION_DURATION; + pub const CandleAuctionDuration: BlockNumber = CANDLE_AUCTION_DURATION; + pub const CommunityFundingDuration: BlockNumber = COMMUNITY_FUNDING_DURATION; + pub const RemainderFundingDuration: BlockNumber = REMAINDER_FUNDING_DURATION; + pub const ContributionVestingDuration: BlockNumber = CONTRIBUTION_VESTING_DURATION; + pub const FundingPalletId: PalletId = PalletId(*b"py/cfund"); +} diff --git a/runtimes/shared-configuration/src/governance.rs b/runtimes/shared-configuration/src/governance.rs new file mode 100644 index 000000000..654000553 --- /dev/null +++ b/runtimes/shared-configuration/src/governance.rs @@ -0,0 +1,105 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +use crate::{ + currency::{deposit, PLMC}, + Balance, +}; +use frame_support::{parameter_types, PalletId}; +use parachains_common::{BlockNumber, DAYS, HOURS}; +use sp_arithmetic::Permill; + +pub const MIN_DEPOSIT: Balance = PLMC; + +#[cfg(feature = "fast-gov")] +pub const LAUNCH_PERIOD: BlockNumber = 7 * MINUTES; +#[cfg(not(feature = "fast-gov"))] +pub const LAUNCH_PERIOD: BlockNumber = 7 * DAYS; + +#[cfg(feature = "fast-gov")] +pub const VOTING_PERIOD: BlockNumber = 7 * MINUTES; +#[cfg(not(feature = "fast-gov"))] +pub const VOTING_PERIOD: BlockNumber = 7 * DAYS; + +#[cfg(feature = "fast-gov")] +pub const FAST_TRACK_VOTING_PERIOD: BlockNumber = 3 * MINUTES; +#[cfg(not(feature = "fast-gov"))] +pub const FAST_TRACK_VOTING_PERIOD: BlockNumber = 3 * HOURS; + +#[cfg(feature = "fast-gov")] +pub const ENACTMENT_PERIOD: BlockNumber = 8 * MINUTES; +#[cfg(not(feature = "fast-gov"))] +pub const ENACTMENT_PERIOD: BlockNumber = DAYS; + +#[cfg(feature = "fast-gov")] +pub const COOLOFF_PERIOD: BlockNumber = 7 * MINUTES; +#[cfg(not(feature = "fast-gov"))] +pub const COOLOFF_PERIOD: BlockNumber = 7 * DAYS; + +#[cfg(feature = "fast-gov")] +pub const SPEND_PERIOD: BlockNumber = 6 * MINUTES; +#[cfg(not(feature = "fast-gov"))] +pub const SPEND_PERIOD: BlockNumber = 6 * DAYS; + +#[cfg(feature = "fast-gov")] +pub const ROTATION_PERIOD: BlockNumber = 80 * MINUTES; +#[cfg(not(feature = "fast-gov"))] +pub const ROTATION_PERIOD: BlockNumber = 80 * HOURS; + +#[cfg(feature = "fast-gov")] +pub const TERM_DURATION: BlockNumber = 15 * MINUTES; +#[cfg(not(feature = "fast-gov"))] +pub const TERM_DURATION: BlockNumber = DAYS; + +#[cfg(feature = "fast-gov")] +pub const COUNCIL_MOTION_DURATION: BlockNumber = 4 * MINUTES; +#[cfg(not(feature = "fast-gov"))] +pub const COUNCIL_MOTION_DURATION: BlockNumber = 3 * DAYS; + +#[cfg(feature = "fast-gov")] +pub const TECHNICAL_MOTION_DURATION: BlockNumber = 4 * MINUTES; +#[cfg(not(feature = "fast-gov"))] +pub const TECHNICAL_MOTION_DURATION: BlockNumber = 3 * DAYS; + +parameter_types! { + // Democracy Pallet + pub const LaunchPeriod: BlockNumber = LAUNCH_PERIOD; + pub const VotingPeriod: BlockNumber = VOTING_PERIOD; + pub const FastTrackVotingPeriod: BlockNumber = FAST_TRACK_VOTING_PERIOD; + pub const MinimumDeposit: Balance = MIN_DEPOSIT; + pub const EnactmentPeriod: BlockNumber = ENACTMENT_PERIOD; + pub const CooloffPeriod: BlockNumber = COOLOFF_PERIOD; + // Council Pallet + pub const CouncilMotionDuration: BlockNumber = COUNCIL_MOTION_DURATION; + pub const CouncilMaxProposals: u32 = 100; + pub const CouncilMaxMembers: u32 = 100; + // Technical Committee + pub const TechnicalMotionDuration: BlockNumber = TECHNICAL_MOTION_DURATION; + pub const TechnicalMaxProposals: u32 = 100; + pub const TechnicalMaxMembers: u32 = 100; + // Tipper Group + pub const TipperMaxMembers: u32 = 21; + // Extras + pub const PreimageBaseDeposit: Balance = deposit(2, 64); + pub const MaxProposals: u32 = 100; + //Treasury + pub const ProposalBond: Permill = Permill::from_percent(5); + pub const ProposalBondMinimum: Balance = 20 * PLMC; + pub const SpendPeriod: BlockNumber = SPEND_PERIOD; + pub const Burn: Permill = Permill::zero(); + pub const MaxApprovals: u32 = 100; + pub const TreasuryId: PalletId = PalletId(*b"plmc/tsy"); +} diff --git a/runtimes/base/src/weights/mod.rs b/runtimes/shared-configuration/src/lib.rs similarity index 67% rename from runtimes/base/src/weights/mod.rs rename to runtimes/shared-configuration/src/lib.rs index fb04fe6e5..01fd24175 100644 --- a/runtimes/base/src/weights/mod.rs +++ b/runtimes/shared-configuration/src/lib.rs @@ -14,14 +14,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -//! Expose the auto generated weight files. +#![cfg_attr(not(feature = "std"), no_std)] -pub mod block_weights; -pub mod extrinsic_weights; -pub mod paritydb_weights; -pub mod rocksdb_weights; +pub mod assets; +pub mod currency; +pub mod fee; +pub mod funding; +pub mod governance; +pub mod staking; +pub mod weights; -pub use block_weights::constants::BlockExecutionWeight; -pub use extrinsic_weights::constants::ExtrinsicBaseWeight; -pub use paritydb_weights::constants::ParityDbWeight; -pub use rocksdb_weights::constants::RocksDbWeight; +/// Common types +pub use parachains_common::{Balance, BlockNumber, DAYS}; diff --git a/runtimes/shared-configuration/src/staking.rs b/runtimes/shared-configuration/src/staking.rs new file mode 100644 index 000000000..66292b5d4 --- /dev/null +++ b/runtimes/shared-configuration/src/staking.rs @@ -0,0 +1,38 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +use crate::currency::PLMC; +use frame_support::parameter_types; + +// Since a Round is 6 hours, one week, expresses as `RoundIndex` is 4 * 7 +const WEEK_IN_ROUNDS: u32 = 4 * 7; + +parameter_types! { + pub const MinBlocksPerRound: u32 = 10; + pub const LeaveCandidatesDelay: u32 = WEEK_IN_ROUNDS; + pub const CandidateBondLessDelay: u32 = WEEK_IN_ROUNDS; + pub const LeaveDelegatorsDelay: u32 = WEEK_IN_ROUNDS; + pub const RevokeDelegationDelay: u32 = WEEK_IN_ROUNDS; + pub const DelegationBondLessDelay: u32 = WEEK_IN_ROUNDS; + pub const RewardPaymentDelay: u32 = 2; + pub const MinSelectedCandidates: u32 = 5; + pub const MaxTopDelegationsPerCandidate: u32 = 300; + pub const MaxBottomDelegationsPerCandidate: u32 = 50; + pub const MaxDelegationsPerDelegator: u32 = 100; + pub const MinCandidateStk: u128 = 20_000 * PLMC; + pub const MinDelegatorStk: u128 = 50 * PLMC; + pub const MinDelegation: u128 = 50 * PLMC; +} diff --git a/runtimes/base/src/weights/block_weights.rs b/runtimes/shared-configuration/src/weights/block_weights.rs similarity index 94% rename from runtimes/base/src/weights/block_weights.rs rename to runtimes/shared-configuration/src/weights/block_weights.rs index 451c27f95..f24090fb4 100644 --- a/runtimes/base/src/weights/block_weights.rs +++ b/runtimes/shared-configuration/src/weights/block_weights.rs @@ -23,7 +23,7 @@ pub mod constants { parameter_types! { /// Importing a block with 0 Extrinsics. pub const BlockExecutionWeight: Weight = - Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(5_000_000)); + Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(5_000_000), 0); } #[cfg(test)] diff --git a/runtimes/base/src/weights/extrinsic_weights.rs b/runtimes/shared-configuration/src/weights/extrinsic_weights.rs similarity index 94% rename from runtimes/base/src/weights/extrinsic_weights.rs rename to runtimes/shared-configuration/src/weights/extrinsic_weights.rs index 0819bab8a..465a4c5fe 100644 --- a/runtimes/base/src/weights/extrinsic_weights.rs +++ b/runtimes/shared-configuration/src/weights/extrinsic_weights.rs @@ -23,7 +23,7 @@ pub mod constants { parameter_types! { /// Executing a NO-OP `System::remarks` Extrinsic. pub const ExtrinsicBaseWeight: Weight = - Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(125_000)); + Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(125_000), 0); } #[cfg(test)] diff --git a/runtimes/shared-configuration/src/weights/mod.rs b/runtimes/shared-configuration/src/weights/mod.rs new file mode 100644 index 000000000..68cc6b5f3 --- /dev/null +++ b/runtimes/shared-configuration/src/weights/mod.rs @@ -0,0 +1,63 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +//! Expose the auto generated weight files. + +pub mod block_weights; +pub mod extrinsic_weights; +pub mod paritydb_weights; +pub mod rocksdb_weights; + +pub use block_weights::constants::BlockExecutionWeight; +pub use extrinsic_weights::constants::ExtrinsicBaseWeight; +use frame_support::{dispatch::DispatchClass, parameter_types, weights::Weight}; +use parachains_common::{AVERAGE_ON_INITIALIZE_RATIO, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO}; +pub use paritydb_weights::constants::ParityDbWeight; +pub use rocksdb_weights::constants::RocksDbWeight; + +use frame_system::limits::{BlockLength, BlockWeights}; +use sp_arithmetic::Perbill; + +parameter_types! { + // This part is copied from Substrate's `bin/node/runtime/src/lib.rs`. + // The `RuntimeBlockLength` and `RuntimeBlockWeights` exist here because the + // `DeletionWeightLimit` and `DeletionQueueDepth` depend on those to parameterize + // the lazy contract deletion. + pub RuntimeBlockLength: BlockLength = + BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); + pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder() + .base_block(BlockExecutionWeight::get()) + .for_class(DispatchClass::all(), |weights| { + weights.base_extrinsic = ExtrinsicBaseWeight::get(); + }) + .for_class(DispatchClass::Normal, |weights| { + weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + }) + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); + // Operational transactions have some extra reserved space, so that they + // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. + weights.reserved = Some( + MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT + ); + }) + .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) + .build_or_panic(); + pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); + pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); + pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * RuntimeBlockWeights::get().max_block; + pub const MaxScheduledPerBlock: u32 = 50; +} diff --git a/runtimes/base/src/weights/paritydb_weights.rs b/runtimes/shared-configuration/src/weights/paritydb_weights.rs similarity index 100% rename from runtimes/base/src/weights/paritydb_weights.rs rename to runtimes/shared-configuration/src/weights/paritydb_weights.rs diff --git a/runtimes/base/src/weights/rocksdb_weights.rs b/runtimes/shared-configuration/src/weights/rocksdb_weights.rs similarity index 100% rename from runtimes/base/src/weights/rocksdb_weights.rs rename to runtimes/shared-configuration/src/weights/rocksdb_weights.rs diff --git a/runtimes/standalone/Cargo.toml b/runtimes/standalone/Cargo.toml index d2b067ff1..9faf0e20e 100644 --- a/runtimes/standalone/Cargo.toml +++ b/runtimes/standalone/Cargo.toml @@ -66,7 +66,6 @@ hex-literal = { workspace = true, optional = true } # Local Dependencies pallet-funding.workspace = true -polimec-traits.workspace = true [build-dependencies] substrate-wasm-builder.workspace = true @@ -112,7 +111,6 @@ std = [ "pallet-session/std", "pallet-authorship/std", "pallet-insecure-randomness-collective-flip/std", - "polimec-traits/std", "pallet-vesting/std", ] @@ -131,7 +129,6 @@ runtime-benchmarks = [ "pallet-democracy/runtime-benchmarks", "pallet-funding/runtime-benchmarks", "pallet-scheduler/runtime-benchmarks", - "polimec-traits/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", ] try-runtime = [ @@ -153,6 +150,5 @@ try-runtime = [ "pallet-insecure-randomness-collective-flip/try-runtime", "pallet-scheduler/try-runtime", "pallet-session/try-runtime", - "polimec-traits/try-runtime", "pallet-vesting/try-runtime", ] diff --git a/runtimes/standalone/src/lib.rs b/runtimes/standalone/src/lib.rs index 9975c2faa..039fd3a3b 100644 --- a/runtimes/standalone/src/lib.rs +++ b/runtimes/standalone/src/lib.rs @@ -25,11 +25,13 @@ extern crate frame_benchmarking; pub use frame_support::{ construct_runtime, parameter_types, traits::{ - ConstU128, ConstU32, ConstU64, ConstU8, Contains, EitherOfDiverse, EqualPrivilegeOnly, KeyOwnerProofSystem, - Randomness, StorageInfo, + ConstU128, ConstU32, ConstU64, ConstU8, Contains, EitherOfDiverse, EqualPrivilegeOnly, + KeyOwnerProofSystem, Randomness, StorageInfo, WithdrawReasons, }, weights::{ - constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND}, + constants::{ + BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND, + }, IdentityFee, Weight, }, PalletId, StorageValue, @@ -40,7 +42,9 @@ use frame_system::EnsureSigned; pub use frame_system::{Call as SystemCall, EnsureRoot}; pub use pallet_balances::Call as BalancesCall; use pallet_funding::{BondType, Multiplier as FundingMultiplier}; -use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; +use pallet_grandpa::{ + fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, +}; pub use pallet_timestamp::Call as TimestampCall; use pallet_transaction_payment::{ConstFeeMultiplier, CurrencyAdapter, Multiplier}; use sp_api::impl_runtime_apis; @@ -51,7 +55,8 @@ pub use sp_runtime::BuildStorage; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{ - AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, NumberFor, One, OpaqueKeys, Verify, + AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, NumberFor, + One, OpaqueKeys, Verify, }, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, MultiSignature, @@ -167,10 +172,7 @@ pub const MICRO_PLMC: Balance = 10u128.pow(4); /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { - NativeVersion { - runtime_version: VERSION, - can_author_with: Default::default(), - } + NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } } const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); @@ -256,10 +258,13 @@ impl pallet_grandpa::Config for Runtime { type KeyOwnerProofSystem = (); - type KeyOwnerProof = >::Proof; + type KeyOwnerProof = + >::Proof; - type KeyOwnerIdentification = - >::IdentificationTuple; + type KeyOwnerIdentification = >::IdentificationTuple; type HandleEquivocation = (); @@ -375,7 +380,6 @@ impl pallet_funding::Config for Runtime { type ContributionTokenCurrency = Assets; type BidId = u128; type Randomness = Random; - type HandleMembers = Credentials; type StringLimit = ConstU32<64>; type PreImageLimit = ConstU32<1024>; type EvaluationDuration = EvaluationDuration; @@ -394,17 +398,6 @@ impl pallet_funding::Config for Runtime { type WeightInfo = (); } -impl pallet_credentials::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 = (); -} - impl pallet_scheduler::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; @@ -478,20 +471,26 @@ impl pallet_democracy::Config for Runtime { type VoteLockingPeriod = EnactmentPeriod; // Same as EnactmentPeriod type MinimumDeposit = MinimumDeposit; /// A straight majority of the council can decide what their next motion is. - type ExternalOrigin = pallet_collective::EnsureProportionAtLeast; + type ExternalOrigin = + pallet_collective::EnsureProportionAtLeast; /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. - type ExternalMajorityOrigin = pallet_collective::EnsureProportionAtLeast; + type ExternalMajorityOrigin = + pallet_collective::EnsureProportionAtLeast; /// A unanimous council can have the next scheduled referendum be a straight default-carries /// (NTB) vote. - type ExternalDefaultOrigin = pallet_collective::EnsureProportionAtLeast; + type ExternalDefaultOrigin = + pallet_collective::EnsureProportionAtLeast; /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote /// be tabled immediately and with a shorter voting/enactment period. - type FastTrackOrigin = pallet_collective::EnsureProportionAtLeast; - type InstantOrigin = pallet_collective::EnsureProportionAtLeast; + type FastTrackOrigin = + pallet_collective::EnsureProportionAtLeast; + type InstantOrigin = + pallet_collective::EnsureProportionAtLeast; type InstantAllowed = frame_support::traits::ConstBool; type FastTrackVotingPeriod = FastTrackVotingPeriod; // To cancel a proposal which has been passed, 2/3 of the council must agree to it. - type CancellationOrigin = pallet_collective::EnsureProportionAtLeast; + type CancellationOrigin = + pallet_collective::EnsureProportionAtLeast; // To cancel a proposal before it has been passed, the technical committee must be unanimous or // Root must agree. type CancelProposalOrigin = EitherOfDiverse< @@ -566,13 +565,20 @@ impl pallet_utility::Config for Runtime { type WeightInfo = (); } +parameter_types! { + /// Vesting Pallet. Copied from Kusama & Polkadot runtime + pub const MinVestedTransfer: Balance = 100 * MILLI_PLMC; + pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons = + WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); +} + impl pallet_vesting::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; type BlockNumberToBalance = ConvertInto; - type MinVestedTransfer = runtime_common::constants::MinVestedTransfer; + type MinVestedTransfer = MinVestedTransfer; type WeightInfo = pallet_vesting::weights::SubstrateWeight; - type UnvestedFundsAllowedWithdrawReasons = runtime_common::constants::UnvestedFundsAllowedWithdrawReasons; + type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; // `VestingInfo` encode length is 36bytes. 28 schedules gets encoded as 1009 bytes, which is the // highest number of schedules that encodes less than 2^10. const MAX_VESTING_SCHEDULES: u32 = 28; @@ -613,7 +619,6 @@ construct_runtime!( // Include the custom logic PolimecFunding: pallet_funding, - Credentials: pallet_credentials, } ); @@ -636,12 +641,18 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic; /// The payload being signed in transactions. pub type SignedPayload = generic::SignedPayload; /// Executive: handles dispatch to the various modules. -pub type Executive = - frame_executive::Executive, Runtime, AllPalletsWithSystem>; +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPalletsWithSystem, +>; #[cfg(feature = "runtime-benchmarks")] mod benches { @@ -892,14 +903,24 @@ mod tests { .collect(); // Block Number - assert!(whitelist.contains("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac")); + assert!( + whitelist.contains("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac") + ); // Total Issuance - assert!(whitelist.contains("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80")); + assert!( + whitelist.contains("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80") + ); // Execution Phase - assert!(whitelist.contains("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a")); + assert!( + whitelist.contains("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a") + ); // Event Count - assert!(whitelist.contains("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850")); + assert!( + whitelist.contains("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850") + ); // System Events - assert!(whitelist.contains("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7")); + assert!( + whitelist.contains("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7") + ); } } diff --git a/runtimes/testnet/Cargo.toml b/runtimes/testnet/Cargo.toml index 7cb6f4dbc..42a17d71f 100644 --- a/runtimes/testnet/Cargo.toml +++ b/runtimes/testnet/Cargo.toml @@ -25,16 +25,7 @@ smallvec.workspace = true # Polimec specific pallet-funding.workspace = true -polimec-traits.workspace = true - -# KILT specific -pallet-dip-consumer.workspace = true -did.workspace = true -pallet-did-lookup.workspace = true -kilt-dip-support.workspace = true - -# Primitives -xcm-primitives.workspace = true +shared-configuration.workspace = true # FRAME frame-benchmarking = { workspace = true, optional = true } @@ -63,6 +54,7 @@ pallet-multisig.workspace = true pallet-preimage.workspace = true pallet-insecure-randomness-collective-flip.workspace = true pallet-vesting.workspace = true +pallet-parachain-staking.workspace = true # Substrate sp-api.workspace = true @@ -150,7 +142,6 @@ std = [ "parachain-info/std", "polkadot-parachain/std", "polkadot-runtime-common/std", - "polimec-traits/std", "sp-api/std", "sp-block-builder/std", "sp-consensus-aura/std", @@ -166,9 +157,8 @@ std = [ "xcm-builder/std", "xcm-executor/std", "xcm/std", - "did/std", - "pallet-dip-consumer/std", - "pallet-did-lookup/std", + "shared-configuration/std", + "pallet-parachain-staking/std" ] runtime-benchmarks = [ @@ -190,7 +180,7 @@ runtime-benchmarks = [ "pallet-assets/runtime-benchmarks", "pallet-collective/runtime-benchmarks", ] -# + try-runtime = [ "cumulus-pallet-aura-ext/try-runtime", "cumulus-pallet-dmp-queue/try-runtime", diff --git a/runtimes/testnet/src/dip.rs b/runtimes/testnet/src/dip.rs deleted file mode 100644 index 6e9b41ecb..000000000 --- a/runtimes/testnet/src/dip.rs +++ /dev/null @@ -1,169 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -use did::{did_details::DidVerificationKey, DidVerificationKeyRelationship, KeyIdOf}; -use frame_support::traits::Contains; -use kilt_dip_support::{ - did::{DidSignatureAndCallVerifier, MerkleEntriesAndDidSignature, MerkleRevealedDidSignatureVerifier}, - merkle::{DidMerkleProofVerifier, MerkleProof, ProofLeaf}, - traits::{BlockNumberProvider, DidDipOriginFilter, GenesisProvider}, - MerkleProofAndDidSignatureVerifier, -}; -use pallet_dip_consumer::traits::IdentityProofVerifier; -use sp_std::vec::Vec; - -use crate::{AccountId, BlockNumber, Hash, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin}; -use runtime_common::DidIdentifier; -use sp_runtime::traits::BlakeTwo256; -pub type Hasher = BlakeTwo256; - -pub type MerkleProofVerifier = DidMerkleProofVerifier, BlockNumber, u128, 10>; -pub type MerkleProofVerifierOutputOf = - >::VerificationResult; - -pub type MerkleDidSignatureVerifierOf = MerkleRevealedDidSignatureVerifier< - BlockNumber, - Hash, - u128, - AccountId, - MerkleProofVerifierOutputOf, - BlockNumberProvider, - // Signatures are valid for 50 blocks - 50, - GenesisProvider, - Hash, ->; - -impl pallet_dip_consumer::Config for Runtime { - type DipCallOriginFilter = PreliminaryDipOriginFilter; - type Identifier = DidIdentifier; - type IdentityDetails = u128; - type Proof = MerkleEntriesAndDidSignature>, ProofLeaf>, BlockNumber>; - type ProofDigest = Hash; - type ProofVerifier = MerkleProofAndDidSignatureVerifier< - BlockNumber, - MerkleProofVerifier, - DidSignatureAndCallVerifier, DipCallFilter>, - >; - type RuntimeCall = RuntimeCall; - type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; -} - -pub struct PreliminaryDipOriginFilter; - -impl Contains for PreliminaryDipOriginFilter { - fn contains(t: &RuntimeCall) -> bool { - matches!( - t, - RuntimeCall::DidLookup { .. } - | RuntimeCall::Utility(pallet_utility::Call::batch { .. }) - | RuntimeCall::Utility(pallet_utility::Call::batch_all { .. }) - | RuntimeCall::Utility(pallet_utility::Call::force_batch { .. }) - ) - } -} - -fn derive_verification_key_relationship(call: &RuntimeCall) -> Option { - match call { - RuntimeCall::DidLookup { .. } => Some(DidVerificationKeyRelationship::Authentication), - RuntimeCall::Utility(pallet_utility::Call::batch { calls }) => single_key_relationship(calls.iter()).ok(), - RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => single_key_relationship(calls.iter()).ok(), - RuntimeCall::Utility(pallet_utility::Call::force_batch { calls }) => single_key_relationship(calls.iter()).ok(), - _ => None, - } -} - -// Taken and adapted from `impl -// did::DeriveDidCallAuthorizationVerificationKeyRelationship for RuntimeCall` -// in Spiritnet/Peregrine runtime. -fn single_key_relationship<'a>( - calls: impl Iterator, -) -> Result { - let mut calls = calls.peekable(); - let first_call_relationship = calls - .peek() - .and_then(|k| derive_verification_key_relationship(k)) - .ok_or(())?; - calls - .map(derive_verification_key_relationship) - .try_fold(first_call_relationship, |acc, next| { - if next == Some(acc) { - Ok(acc) - } else { - Err(()) - } - }) -} - -pub struct DipCallFilter; - -impl DidDipOriginFilter for DipCallFilter { - type Error = (); - type OriginInfo = (DidVerificationKey, DidVerificationKeyRelationship); - type Success = (); - - // Accepts only a DipOrigin for the DidLookup pallet calls. - fn check_call_origin_info(call: &RuntimeCall, info: &Self::OriginInfo) -> Result { - let key_relationship = single_key_relationship([call].into_iter())?; - if info.1 == key_relationship { - Ok(()) - } else { - Err(()) - } - } -} - -#[cfg(test)] -mod dip_call_origin_filter_tests { - use super::*; - - use frame_support::assert_err; - - #[test] - fn test_key_relationship_derivation() { - // Can call DidLookup functions with an authentication key - let did_lookup_call = RuntimeCall::DidLookup(pallet_did_lookup::Call::associate_sender {}); - assert_eq!( - single_key_relationship(vec![did_lookup_call].iter()), - Ok(DidVerificationKeyRelationship::Authentication) - ); - // Can't call System functions with a DID key (hence a DIP origin) - let system_call = RuntimeCall::System(frame_system::Call::remark { remark: vec![] }); - assert_err!(single_key_relationship(vec![system_call].iter()), ()); - // Can't call empty batch with a DID key - let empty_batch_call = RuntimeCall::Utility(pallet_utility::Call::batch_all { calls: vec![] }); - assert_err!(single_key_relationship(vec![empty_batch_call].iter()), ()); - // Can call batch with a DipLookup with an authentication key - let did_lookup_batch_call = RuntimeCall::Utility(pallet_utility::Call::batch_all { - calls: vec![pallet_did_lookup::Call::associate_sender {}.into()], - }); - assert_eq!( - single_key_relationship(vec![did_lookup_batch_call].iter()), - Ok(DidVerificationKeyRelationship::Authentication) - ); - // Can't call a batch with different required keys - let did_lookup_batch_call = RuntimeCall::Utility(pallet_utility::Call::batch_all { - calls: vec![ - // Authentication key - pallet_did_lookup::Call::associate_sender {}.into(), - // No key - frame_system::Call::remark { remark: vec![] }.into(), - ], - }); - assert_err!(single_key_relationship(vec![did_lookup_batch_call].iter()), ()); - } -} diff --git a/runtimes/testnet/src/lib.rs b/runtimes/testnet/src/lib.rs index a36c0bdb3..7531aa8c2 100644 --- a/runtimes/testnet/src/lib.rs +++ b/runtimes/testnet/src/lib.rs @@ -24,22 +24,19 @@ extern crate frame_benchmarking; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use frame_support::{ - construct_runtime, - pallet_prelude::Get, - parameter_types, + construct_runtime, parameter_types, traits::{ - AsEnsureOriginWithArg, ConstU32, Currency, EitherOfDiverse, EqualPrivilegeOnly, Everything, Imbalance, - OnUnbalanced, + AsEnsureOriginWithArg, ConstU32, Currency, EitherOfDiverse, EqualPrivilegeOnly, Everything, }, weights::{ConstantMultiplier, Weight}, - PalletId, }; use frame_system::{EnsureRoot, EnsureSigned}; pub use parachains_common::{ - impls::DealWithFees, opaque, AccountId, AssetIdForTrustBackedAssets as AssetId, AuraId, Balance, BlockNumber, Hash, - Header, Index, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, MAXIMUM_BLOCK_WEIGHT, MINUTES, - NORMAL_DISPATCH_RATIO, SLOT_DURATION, + impls::DealWithFees, opaque, AccountId, AssetIdForTrustBackedAssets as AssetId, AuraId, + Balance, BlockNumber, Hash, Header, Index, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, + MAXIMUM_BLOCK_WEIGHT, MINUTES, NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; + // Polkadot imports use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; use sp_api::impl_runtime_apis; @@ -50,42 +47,40 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, Perquintill, + ApplyExtrinsicResult, }; pub use sp_runtime::{MultiAddress, Perbill, Permill}; use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; -// XCM Imports -use pallet_funding::{BondType, Multiplier as FundingMultiplier}; -use xcm_executor::XcmExecutor; -use kilt_dip_support::merkle::VerificationResult; -use pallet_dip_consumer::{DipOrigin, EnsureDipOrigin}; -use runtime_common::constants::staking::*; -pub use runtime_common::{ - constants::{ - governance::*, polimec_inflation_config, preimage::PreimageBaseDeposit, treasury::INITIAL_PERIOD_LENGTH, - InflationInfo, BLOCKS_PER_YEAR, EXISTENTIAL_DEPOSIT, MAX_COLLATOR_STAKE, MICRO_PLMC, PLMC, - }, - fees::WeightToFee, - DidIdentifier, RuntimeBlockLength, RuntimeBlockWeights, -}; -use weights::RocksDbWeight; +// XCM Imports use xcm_config::XcmConfig; +use xcm_executor::XcmExecutor; +mod xcm_config; +pub use crate::xcm_config::*; // Make the WASM binary available. #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -mod dip; -mod weights; -mod xcm_config; -pub use crate::{dip::*, xcm_config::*}; +// Polimec Shared Imports +use pallet_funding::{BondType, Multiplier as FundingMultiplier}; +pub use pallet_parachain_staking; +pub use shared_configuration::{ + assets::*, + currency::{vesting::*, *}, + fee::*, + funding::*, + governance::*, + staking::*, + weights::*, +}; -pub type NegativeImbalanceOf = - as Currency<::AccountId>>::NegativeImbalance; +pub type NegativeImbalanceOf = as Currency< + ::AccountId, +>>::NegativeImbalance; /// The address format for describing accounts. pub type Address = MultiAddress; @@ -108,19 +103,24 @@ pub type SignedExtra = ( frame_system::CheckEra, frame_system::CheckNonce, frame_system::CheckWeight, - // pallet_asset_tx_payment::ChargeAssetTxPayment, pallet_transaction_payment::ChargeTransactionPayment, ); /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = - frame_executive::Executive, Runtime, AllPalletsWithSystem>; +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPalletsWithSystem, +>; impl_opaque_keys! { pub struct SessionKeys { @@ -143,10 +143,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { - NativeVersion { - runtime_version: VERSION, - can_author_with: Default::default(), - } + NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } } parameter_types! { @@ -180,7 +177,7 @@ impl frame_system::Config for Runtime { /// The lookup mechanism to get account ID from whatever is passed in dispatchers. type Lookup = AccountIdLookup; /// The header type. - type Header = runtime_common::Header; + type Header = Header; /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; /// Maximum number of block number to block hash mappings to keep (oldest pruned first). @@ -207,10 +204,6 @@ impl frame_system::Config for Runtime { type MaxConsumers = frame_support::traits::ConstU32<16>; } -parameter_types! { - pub const MinimumPeriod: u64 = SLOT_DURATION / 2; -} - impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; @@ -219,119 +212,46 @@ impl pallet_timestamp::Config for Runtime { type WeightInfo = (); } -parameter_types! { - pub const UncleGenerations: u32 = 0; -} - impl pallet_authorship::Config for Runtime { type FindAuthor = pallet_session::FindAccountFromAuthorIndex; - type EventHandler = ParachainStaking; -} - -parameter_types! { - pub const MaxLocks: u32 = 50; - pub const MaxReserves: u32 = 50; - pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT; - + type EventHandler = (ParachainStaking,); } impl pallet_balances::Config for Runtime { - /// The type for recording an account's balance. type Balance = Balance; type DustRemoval = Treasury; - /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; - type WeightInfo = pallet_balances::weights::SubstrateWeight; type MaxLocks = MaxLocks; type MaxReserves = MaxReserves; type ReserveIdentifier = BondType; + type WeightInfo = (); } -/// Logic for the author to get a portion of fees. -pub struct ToAuthor(sp_std::marker::PhantomData); - -impl OnUnbalanced> for ToAuthor -where - R: pallet_balances::Config + pallet_authorship::Config, - ::AccountId: From, - ::AccountId: Into, - ::Balance: Into, -{ - fn on_nonzero_unbalanced(amount: NegativeImbalanceOf) { - if let Some(author) = >::author() { - >::resolve_creating(&author, amount); - } - } -} - -/// Split two Imbalances between two unbalanced handlers. -/// The first Imbalance will be split according to the given ratio. The second -/// Imbalance will be handled by the second beneficiary. -/// -/// In case of transaction payment, the first Imbalance is the fee and the -/// second imbalance the tip. -pub struct SplitFeesByRatio( - sp_std::marker::PhantomData<(R, Ratio, Beneficiary1, Beneficiary2)>, -); -impl OnUnbalanced> - for SplitFeesByRatio -where - R: pallet_balances::Config, - Beneficiary1: OnUnbalanced>, - Beneficiary2: OnUnbalanced>, - Ratio: Get<(u32, u32)>, -{ - fn on_unbalanceds(mut fees_then_tips: impl Iterator>) { - let ratio = Ratio::get(); - if let Some(fees) = fees_then_tips.next() { - let mut split = fees.ration(ratio.0, ratio.1); - if let Some(tips) = fees_then_tips.next() { - // for tips, if any, 100% to author - tips.merge_into(&mut split.1); - } - Beneficiary1::on_unbalanced(split.0); - Beneficiary2::on_unbalanced(split.1); - } - } -} - -parameter_types! { - /// Relay Chain `TransactionByteFee` / 10 - pub const TransactionByteFee: Balance = 10 * MICRO_PLMC; - pub const OperationalFeeMultiplier: u8 = 5; - pub const FeeSplitRatio: (u32, u32) = (50, 50); -} - -/// Split the fees using a preconfigured Ratio -pub type FeeSplit = SplitFeesByRatio; - impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = - pallet_transaction_payment::CurrencyAdapter>>; - type WeightToFee = WeightToFee; + type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; + type OperationalFeeMultiplier = frame_support::traits::ConstU8<5>; + type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; - type OperationalFeeMultiplier = OperationalFeeMultiplier; } impl pallet_asset_tx_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Fungibles = StatemintAssets; type OnChargeAssetTransaction = pallet_asset_tx_payment::FungiblesAdapter< - pallet_assets::BalanceToAssetBalance, + pallet_assets::BalanceToAssetBalance< + Balances, + Runtime, + ConvertInto, + StatemintAssetsInstance, + >, xcm_config::AssetsToBlockAuthor, >; } -parameter_types! { - pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); - pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); -} - -// TODO: On Testnet only impl pallet_sudo::Config for Runtime { type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; @@ -371,12 +291,6 @@ impl cumulus_pallet_dmp_queue::Config for Runtime { type ExecuteOverweightOrigin = EnsureRoot; } -parameter_types! { - pub const Period: BlockNumber = 6 * HOURS; - pub const Offset: BlockNumber = 0; - pub const MaxAuthorities: u32 = 100_000; -} - impl pallet_session::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ValidatorId = ::AccountId; @@ -391,117 +305,12 @@ impl pallet_session::Config for Runtime { impl pallet_aura::Config for Runtime { type AuthorityId = AuraId; - // TODO: handle disabled validators type DisabledValidators = (); type MaxAuthorities = MaxAuthorities; } -parameter_types! { - /// Minimum round length is 1 hour - pub const MinBlocksPerRound: BlockNumber = MIN_BLOCKS_PER_ROUND; - /// Default length of a round/session is 2 hours - pub const DefaultBlocksPerRound: BlockNumber = DEFAULT_BLOCKS_PER_ROUND; - /// Unstaked balance can be unlocked after 7 days - pub const StakeDuration: BlockNumber = STAKE_DURATION; - /// Collator exit requests are delayed by 4 hours (2 rounds/sessions) - pub const ExitQueueDelay: u32 = 2; - /// Minimum 16 collators selected per round, default at genesis and minimum forever after - pub const MinCollators: u32 = MIN_COLLATORS; - /// At least 4 candidates which cannot leave the network if there are no other candidates. - pub const MinRequiredCollators: u32 = 4; - /// We only allow one delegation per round. - pub const MaxDelegationsPerRound: u32 = 1; - /// Maximum 25 delegators per collator at launch, might be increased later - #[derive(Debug, Eq, PartialEq)] - pub const MaxDelegatorsPerCollator: u32 = MAX_DELEGATORS_PER_COLLATOR; - /// Minimum stake required to be reserved to be a collator is 10_000 - pub const MinCollatorStake: Balance = 10_000 * PLMC; - /// Minimum stake required to be reserved to be a delegator is 1000 - pub const MinDelegatorStake: Balance = MIN_DELEGATOR_STAKE; - /// Maximum number of collator candidates - #[derive(Debug, Eq, PartialEq)] - pub const MaxCollatorCandidates: u32 = MAX_CANDIDATES; - /// Maximum number of concurrent requests to unlock unstaked balance - pub const MaxUnstakeRequests: u32 = 10; - /// The starting block number for the network rewards - pub const NetworkRewardStart: BlockNumber = INITIAL_PERIOD_LENGTH; - /// The rate in percent for the network rewards - pub const NetworkRewardRate: Perquintill = NETWORK_REWARD_RATE; -} - -impl parachain_staking::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Currency = Balances; - type CurrencyBalance = Balance; - type MinBlocksPerRound = MinBlocksPerRound; - type DefaultBlocksPerRound = DefaultBlocksPerRound; - type StakeDuration = StakeDuration; - type ExitQueueDelay = ExitQueueDelay; - type MinCollators = MinCollators; - type MinRequiredCollators = MinRequiredCollators; - type MaxDelegationsPerRound = MaxDelegationsPerRound; - type MaxDelegatorsPerCollator = MaxDelegatorsPerCollator; - type MinCollatorStake = MinCollatorStake; - type MinCollatorCandidateStake = MinCollatorStake; - type MaxTopCandidates = MaxCollatorCandidates; - type MinDelegatorStake = MinDelegatorStake; - type MaxUnstakeRequests = MaxUnstakeRequests; - type NetworkRewardRate = NetworkRewardRate; - type NetworkRewardStart = NetworkRewardStart; - type NetworkRewardBeneficiary = Treasury; - type WeightInfo = (); - - const BLOCKS_PER_YEAR: Self::BlockNumber = BLOCKS_PER_YEAR; -} - impl pallet_insecure_randomness_collective_flip::Config for Runtime {} -#[cfg(feature = "fast-gov")] -pub const EVALUATION_DURATION: BlockNumber = 28; -#[cfg(not(feature = "fast-gov"))] -pub const EVALUATION_DURATION: BlockNumber = 28 * DAYS; - -#[cfg(feature = "fast-gov")] -pub const AUCTION_INITIALIZE_PERIOD_DURATION: BlockNumber = 7; -#[cfg(not(feature = "fast-gov"))] -pub const AUCTION_INITIALIZE_PERIOD_DURATION: BlockNumber = 7 * DAYS; - -#[cfg(feature = "fast-gov")] -pub const ENGLISH_AUCTION_DURATION: BlockNumber = 10; -#[cfg(not(feature = "fast-gov"))] -pub const ENGLISH_AUCTION_DURATION: BlockNumber = 2 * DAYS; - -#[cfg(feature = "fast-gov")] -pub const CANDLE_AUCTION_DURATION: BlockNumber = 5; -#[cfg(not(feature = "fast-gov"))] -pub const CANDLE_AUCTION_DURATION: BlockNumber = 3 * DAYS; - -#[cfg(feature = "fast-gov")] -pub const COMMUNITY_FUNDING_DURATION: BlockNumber = 10; -#[cfg(not(feature = "fast-gov"))] -pub const COMMUNITY_FUNDING_DURATION: BlockNumber = 5 * DAYS; - -#[cfg(feature = "fast-gov")] -pub const REMAINDER_FUNDING_DURATION: BlockNumber = 10; -#[cfg(not(feature = "fast-gov"))] -pub const REMAINDER_FUNDING_DURATION: BlockNumber = 1 * DAYS; - -#[cfg(feature = "fast-gov")] -pub const CONTRIBUTION_VESTING_DURATION: BlockNumber = 365; -#[cfg(not(feature = "fast-gov"))] -pub const CONTRIBUTION_VESTING_DURATION: BlockNumber = 365 * DAYS; - -parameter_types! { - pub const EvaluationDuration: BlockNumber = EVALUATION_DURATION; - pub const AuctionInitializePeriodDuration: BlockNumber = AUCTION_INITIALIZE_PERIOD_DURATION; - pub const EnglishAuctionDuration: BlockNumber = ENGLISH_AUCTION_DURATION; - pub const CandleAuctionDuration: BlockNumber = CANDLE_AUCTION_DURATION; - pub const CommunityFundingDuration: BlockNumber = COMMUNITY_FUNDING_DURATION; - pub const RemainderFundingDuration: BlockNumber = REMAINDER_FUNDING_DURATION; - pub const ContributionVestingDuration: BlockNumber = CONTRIBUTION_VESTING_DURATION; - pub const FundingPalletId: PalletId = PalletId(*b"py/cfund"); -} - impl pallet_funding::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ProjectIdentifier = u32; @@ -513,7 +322,6 @@ impl pallet_funding::Config for Runtime { type ContributionTokenCurrency = LocalAssets; type BidId = u128; type Randomness = Random; - type HandleMembers = Credentials; type StringLimit = ConstU32<64>; type PreImageLimit = ConstU32<1024>; type EvaluationDuration = EvaluationDuration; @@ -530,32 +338,7 @@ impl pallet_funding::Config for Runtime { type ContributionVesting = ContributionVestingDuration; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); - type WeightInfo = weights::pallet_funding::WeightInfo; -} - -impl pallet_credentials::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 = (); -} - -#[cfg(feature = "fast-gov")] -pub const SPEND_PERIOD: BlockNumber = 6 * MINUTES; -#[cfg(not(feature = "fast-gov"))] -pub const SPEND_PERIOD: BlockNumber = 6 * DAYS; - -parameter_types! { - pub const ProposalBond: Permill = Permill::from_percent(5); - pub const ProposalBondMinimum: Balance = 20 * PLMC; - pub const SpendPeriod: BlockNumber = SPEND_PERIOD; - pub const Burn: Permill = Permill::zero(); - pub const MaxApprovals: u32 = 100; - pub const TreasuryPalletId: PalletId = PalletId(*b"politrea"); + type WeightInfo = (); } impl pallet_treasury::Config for Runtime { @@ -570,7 +353,7 @@ impl pallet_treasury::Config for Runtime { type ProposalBondMaximum = (); type SpendPeriod = SpendPeriod; type Burn = Burn; - type PalletId = TreasuryPalletId; + type PalletId = TreasuryId; type BurnDestination = (); type WeightInfo = (); type SpendFunds = (); @@ -578,12 +361,6 @@ impl pallet_treasury::Config for Runtime { type SpendOrigin = frame_support::traits::NeverEnsureOrigin; } -parameter_types! { - pub const CouncilMotionDuration: BlockNumber = 5 * DAYS; - pub const CouncilMaxProposals: u32 = 100; - pub const CouncilMaxMembers: u32 = 100; -} - // TODO: VERY BASIC implementation, more work needed type CouncilCollective = pallet_collective::Instance1; impl pallet_collective::Config for Runtime { @@ -598,12 +375,6 @@ impl pallet_collective::Config for Runtime { type SetMembersOrigin = EnsureRoot; } -parameter_types! { - pub const TechnicalMotionDuration: BlockNumber = 5 * DAYS; - pub const TechnicalMaxProposals: u32 = 100; - pub const TechnicalMaxMembers: u32 = 100; -} - type TechnicalCollective = pallet_collective::Instance2; impl pallet_collective::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; @@ -637,18 +408,24 @@ impl pallet_democracy::Config for Runtime { type MaxDeposits = (); type MaxBlacklisted = (); /// A straight majority of the council can decide what their next motion is. - type ExternalOrigin = pallet_collective::EnsureProportionAtLeast; + type ExternalOrigin = + pallet_collective::EnsureProportionAtLeast; /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. - type ExternalMajorityOrigin = pallet_collective::EnsureProportionAtLeast; + type ExternalMajorityOrigin = + pallet_collective::EnsureProportionAtLeast; /// A unanimous council can have the next scheduled referendum be a straight default-carries /// (NTB) vote. - type ExternalDefaultOrigin = pallet_collective::EnsureProportionAtLeast; + type ExternalDefaultOrigin = + pallet_collective::EnsureProportionAtLeast; /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote /// be tabled immediately and with a shorter voting/enactment period. - type FastTrackOrigin = pallet_collective::EnsureProportionAtLeast; - type InstantOrigin = pallet_collective::EnsureProportionAtLeast; + type FastTrackOrigin = + pallet_collective::EnsureProportionAtLeast; + type InstantOrigin = + pallet_collective::EnsureProportionAtLeast; // To cancel a proposal which has been passed, 2/3 of the council must agree to it. - type CancellationOrigin = pallet_collective::EnsureProportionAtLeast; + type CancellationOrigin = + pallet_collective::EnsureProportionAtLeast; type BlacklistOrigin = EnsureRoot; // To cancel a proposal before it has been passed, the technical committee must be unanimous or // Root must agree. @@ -664,11 +441,6 @@ impl pallet_democracy::Config for Runtime { type SubmitOrigin = EnsureSigned; } -parameter_types! { - pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * RuntimeBlockWeights::get().max_block; - pub const MaxScheduledPerBlock: u32 = 50; -} - impl pallet_scheduler::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; @@ -689,22 +461,6 @@ impl pallet_utility::Config for Runtime { type WeightInfo = (); } -pub const fn deposit(items: u32, bytes: u32) -> Balance { - items as Balance * 15 * MICRO_PLMC + (bytes as Balance) * 6 * MICRO_PLMC -} - -pub const fn free_deposit() -> Balance { - 0 * MICRO_PLMC -} - -parameter_types! { - // One storage item; key size is 32; value is size 4+4+16+32 bytes = 56 bytes. - pub const DepositBase: Balance = deposit(1, 88); - // Additional storage item size of 32 bytes. - pub const DepositFactor: Balance = deposit(0, 32); - pub const MaxSignatories: u16 = 100; -} - impl pallet_multisig::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; @@ -724,18 +480,6 @@ impl pallet_preimage::Config for Runtime { type ByteDeposit = (); } -parameter_types! { - pub const AssetDeposit: Balance = PLMC; // 1 UNIT deposit to create asset - pub const ApprovalDeposit: Balance = EXISTENTIAL_DEPOSIT; - pub const AssetAccountDeposit: Balance = deposit(1, 16); - pub const AssetsStringLimit: u32 = 50; - /// Key = 32 bytes, Value = 36 bytes (32+1+1+1+1) - // https://github.com/paritytech/substrate/blob/069917b/frame/assets/src/lib.rs#L257L271 - pub const MetadataDepositBase: Balance = free_deposit(); - pub const MetadataDepositPerByte: Balance = free_deposit(); - pub const AssetsPalletId: PalletId = PalletId(*b"assetsid"); -} - pub type LocalAssetsInstance = pallet_assets::Instance1; pub type StatemintAssetsInstance = pallet_assets::Instance2; @@ -752,7 +496,7 @@ impl pallet_assets::Config for Runtime { type AssetAccountDeposit = AssetAccountDeposit; type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type ApprovalDeposit = ApprovalDeposit; + type ApprovalDeposit = ExistentialDeposit; type StringLimit = AssetsStringLimit; type Freezer = (); type Extra = (); @@ -775,7 +519,7 @@ impl pallet_assets::Config for Runtime { type AssetAccountDeposit = AssetAccountDeposit; type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type ApprovalDeposit = ApprovalDeposit; + type ApprovalDeposit = ExistentialDeposit; type StringLimit = AssetsStringLimit; type Freezer = (); type Extra = (); @@ -785,33 +529,41 @@ impl pallet_assets::Config for Runtime { type BenchmarkHelper = (); } -impl pallet_asset_registry::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type ReserveAssetModifierOrigin = frame_system::EnsureRoot; - type Assets = StatemintAssets; - type WeightInfo = (); -} - impl pallet_vesting::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; type BlockNumberToBalance = ConvertInto; - type MinVestedTransfer = runtime_common::constants::MinVestedTransfer; + type MinVestedTransfer = MinVestedTransfer; type WeightInfo = pallet_vesting::weights::SubstrateWeight; - type UnvestedFundsAllowedWithdrawReasons = runtime_common::constants::UnvestedFundsAllowedWithdrawReasons; + type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; // `VestingInfo` encode length is 36bytes. 28 schedules gets encoded as 1009 bytes, which is the // highest number of schedules that encodes less than 2^10. const MAX_VESTING_SCHEDULES: u32 = 28; } -impl pallet_did_lookup::Config for Runtime { - type Currency = Balances; - type Deposit = DepositBase; - type DidIdentifier = DidIdentifier; - type EnsureOrigin = EnsureDipOrigin>; - type OriginSuccess = DipOrigin>; +impl pallet_parachain_staking::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type WeightInfo = (); + type Currency = Balances; + type MonetaryGovernanceOrigin = frame_system::EnsureRoot; + type MinBlocksPerRound = MinBlocksPerRound; + type LeaveCandidatesDelay = LeaveCandidatesDelay; + type CandidateBondLessDelay = CandidateBondLessDelay; + type LeaveDelegatorsDelay = LeaveDelegatorsDelay; + type RevokeDelegationDelay = RevokeDelegationDelay; + type DelegationBondLessDelay = DelegationBondLessDelay; + type RewardPaymentDelay = RewardPaymentDelay; + type MinSelectedCandidates = MinSelectedCandidates; + type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; + type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate; + type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator; + type MinCandidateStk = MinCandidateStk; + type MinDelegatorStk = MinDelegatorStk; + type MinDelegation = MinDelegation; + type OnCollatorPayout = (); + // We use the default implementation, so we leave () here. + type PayoutCollatorReward = (); + type OnNewRound = (); + type WeightInfo = pallet_parachain_staking::weights::SubstrateWeight; } // Create the runtime by composing the FRAME pallets that were previously configured. @@ -834,17 +586,15 @@ construct_runtime!( AssetTxPayment: pallet_asset_tx_payment::{Pallet, Storage, Event} = 12, LocalAssets: pallet_assets::::{Pallet, Call, Storage, Event} = 13, StatemintAssets: pallet_assets::::{Pallet, Call, Storage, Event} = 14, - AssetRegistry: pallet_asset_registry::{Pallet, Call, Storage, Event} = 15, Vesting: pallet_vesting::{Pallet, Call, Storage, Event, Config} = 16, - // Consensus support. - // The following order MUST NOT be changed: Aura -> Session -> Staking -> Authorship -> AuraExt - // Dependencies: AuraExt on Aura, Authorship and Session on ParachainStaking - Aura: pallet_aura = 23, - Session: pallet_session = 22, - ParachainStaking: parachain_staking = 21, + // Collator support. the order of these 5 are important and shall not change. Authorship: pallet_authorship::{Pallet, Storage} = 20, - AuraExt: cumulus_pallet_aura_ext = 24, + Session: pallet_session::{Pallet, Call, Storage, Event, Config} = 22, + Aura: pallet_aura::{Pallet, Storage, Config} = 23, + AuraExt: cumulus_pallet_aura_ext::{Pallet, Storage, Config} = 24, + ParachainStaking: pallet_parachain_staking::{Pallet, Call, Storage, Event, Config} = 25, + // Governance Treasury: pallet_treasury = 40, @@ -854,10 +604,7 @@ construct_runtime!( Preimage: pallet_preimage::{Pallet, Call, Storage, Event} = 44, // Polimec Core - DipConsumer: pallet_dip_consumer = 50, - DidLookup: pallet_did_lookup = 51, PolimecFunding: pallet_funding::{Pallet, Call, Storage, Event} = 52, - Credentials: pallet_credentials = 53, // Utilities Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event} = 61, @@ -1108,18 +855,20 @@ struct CheckInherents; impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { fn check_inherents( - block: &Block, relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, + block: &Block, + relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, ) -> sp_inherents::CheckInherentsResult { let relay_chain_slot = relay_state_proof .read_slot() .expect("Could not read the relay chain slot from the proof"); - let inherent_data = cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( - relay_chain_slot, - sp_std::time::Duration::from_secs(6), - ) - .create_inherent_data() - .expect("Could not create the timestamp inherent data"); + let inherent_data = + cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( + relay_chain_slot, + sp_std::time::Duration::from_secs(6), + ) + .create_inherent_data() + .expect("Could not create the timestamp inherent data"); inherent_data.check_extrinsics(block) } diff --git a/runtimes/testnet/src/weights/block_weights.rs b/runtimes/testnet/src/weights/block_weights.rs deleted file mode 100644 index f5dcc6ac2..000000000 --- a/runtimes/testnet/src/weights/block_weights.rs +++ /dev/null @@ -1,53 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see .erning permissions and -// limitations under the License. - -pub mod constants { - use frame_support::{ - parameter_types, - weights::{constants, Weight}, - }; - - parameter_types! { - /// Importing a block with 0 Extrinsics. - pub const BlockExecutionWeight: Weight = - Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(5_000_000)); - } - - #[cfg(test)] - mod test_weights { - use frame_support::weights::constants; - - /// Checks that the weight exists and is sane. - // NOTE: If this test fails but you are sure that the generated values are fine, - // you can delete it. - #[test] - fn sane() { - let w = super::constants::BlockExecutionWeight::get(); - - // At least 100 µs. - assert!( - w.ref_time() >= 100u64 * constants::WEIGHT_REF_TIME_PER_MICROS, - "Weight should be at least 100 µs." - ); - // At most 50 ms. - assert!( - w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, - "Weight should be at most 50 ms." - ); - } - } -} diff --git a/runtimes/testnet/src/weights/extrinsic_weights.rs b/runtimes/testnet/src/weights/extrinsic_weights.rs deleted file mode 100644 index 0819bab8a..000000000 --- a/runtimes/testnet/src/weights/extrinsic_weights.rs +++ /dev/null @@ -1,52 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -pub mod constants { - use frame_support::{ - parameter_types, - weights::{constants, Weight}, - }; - - parameter_types! { - /// Executing a NO-OP `System::remarks` Extrinsic. - pub const ExtrinsicBaseWeight: Weight = - Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(125_000)); - } - - #[cfg(test)] - mod test_weights { - use frame_support::weights::constants; - - /// Checks that the weight exists and is sane. - // NOTE: If this test fails but you are sure that the generated values are fine, - // you can delete it. - #[test] - fn sane() { - let w = super::constants::ExtrinsicBaseWeight::get(); - - // At least 10 µs. - assert!( - w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, - "Weight should be at least 10 µs." - ); - // At most 1 ms. - assert!( - w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, - "Weight should be at most 1 ms." - ); - } - } -} diff --git a/runtimes/testnet/src/weights/pallet_funding.rs b/runtimes/testnet/src/weights/pallet_funding.rs deleted file mode 100644 index 50c79d7b7..000000000 --- a/runtimes/testnet/src/weights/pallet_funding.rs +++ /dev/null @@ -1,202 +0,0 @@ - -//! Autogenerated weights for `pallet_funding` -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-03-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `pop-os`, CPU: `13th Gen Intel(R) Core(TM) i9-13900K` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 - -// Executed Command: -// target/release/polimec-standalone-node -// benchmark -// pallet -// --chain=dev -// --steps=50 -// --repeat=20 -// --pallet=pallet_funding -// --extrinsic -// * -// --execution=wasm -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=runtimes/testnet/src/weights/pallet_funding.rs - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{traits::Get, weights::Weight}; -use sp_std::marker::PhantomData; - -/// Weight functions for `pallet_funding`. -pub struct WeightInfo(PhantomData); -impl pallet_funding::WeightInfo for WeightInfo { - /// Storage: PolimecFunding Images (r:0 w:1) - /// Proof Skipped: PolimecFunding Images (max_values: None, max_size: None, mode: Measured) - fn note_image() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 5_860 nanoseconds. - Weight::from_ref_time(6_343_000) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: PolimecFunding Images (r:1 w:0) - /// Proof Skipped: PolimecFunding Images (max_values: None, max_size: None, mode: Measured) - /// Storage: PolimecFunding NextProjectId (r:1 w:1) - /// Proof Skipped: PolimecFunding NextProjectId (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolimecFunding Projects (r:0 w:1) - /// Proof Skipped: PolimecFunding Projects (max_values: None, max_size: None, mode: Measured) - /// Storage: PolimecFunding ProjectsInfo (r:0 w:1) - /// Proof Skipped: PolimecFunding ProjectsInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: PolimecFunding ProjectsIssuers (r:0 w:1) - /// Proof Skipped: PolimecFunding ProjectsIssuers (max_values: None, max_size: None, mode: Measured) - fn create() -> Weight { - // Proof Size summary in bytes: - // Measured: `111` - // Estimated: `3525` - // Minimum execution time: 13_134 nanoseconds. - Weight::from_parts(13_798_000, 3525) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(4)) - } - /// Storage: PolimecFunding ProjectsIssuers (r:1 w:0) - /// Proof Skipped: PolimecFunding ProjectsIssuers (max_values: None, max_size: None, mode: Measured) - /// Storage: PolimecFunding ProjectsInfo (r:1 w:1) - /// Proof Skipped: PolimecFunding ProjectsInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: PolimecFunding ProjectsActive (r:1 w:1) - /// Proof Skipped: PolimecFunding ProjectsActive (max_values: Some(1), max_size: None, mode: Measured) - fn start_evaluation() -> Weight { - // Proof Size summary in bytes: - // Measured: `207` - // Estimated: `6066` - // Minimum execution time: 12_306 nanoseconds. - Weight::from_parts(12_756_000, 6066) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(2)) - } - /// Storage: PolimecFunding ProjectsIssuers (r:1 w:0) - /// Proof Skipped: PolimecFunding ProjectsIssuers (max_values: None, max_size: None, mode: Measured) - /// Storage: PolimecFunding ProjectsInfo (r:1 w:0) - /// Proof Skipped: PolimecFunding ProjectsInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: PolimecFunding Bonds (r:1 w:1) - /// Proof Skipped: PolimecFunding Bonds (max_values: None, max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) - fn bond() -> Weight { - // Proof Size summary in bytes: - // Measured: `370` - // Estimated: `14912` - // Minimum execution time: 19_568 nanoseconds. - Weight::from_parts(19_897_000, 14912) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: PolimecFunding ProjectsIssuers (r:1 w:0) - /// Proof Skipped: PolimecFunding ProjectsIssuers (max_values: None, max_size: None, mode: Measured) - /// Storage: PolimecFunding Images (r:1 w:0) - /// Proof Skipped: PolimecFunding Images (max_values: None, max_size: None, mode: Measured) - /// Storage: PolimecFunding ProjectsInfo (r:1 w:0) - /// Proof Skipped: PolimecFunding ProjectsInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: PolimecFunding Projects (r:1 w:1) - /// Proof Skipped: PolimecFunding Projects (max_values: None, max_size: None, mode: Measured) - fn edit_metadata() -> Weight { - // Proof Size summary in bytes: - // Measured: `454` - // Estimated: `11716` - // Minimum execution time: 14_476 nanoseconds. - Weight::from_parts(15_071_000, 11716) - .saturating_add(T::DbWeight::get().reads(4)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: PolimecFunding ProjectsIssuers (r:1 w:0) - /// Proof Skipped: PolimecFunding ProjectsIssuers (max_values: None, max_size: None, mode: Measured) - /// Storage: PolimecFunding ProjectsInfo (r:1 w:1) - /// Proof Skipped: PolimecFunding ProjectsInfo (max_values: None, max_size: None, mode: Measured) - fn start_auction() -> Weight { - // Proof Size summary in bytes: - // Measured: `268` - // Estimated: `5486` - // Minimum execution time: 13_427 nanoseconds. - Weight::from_parts(13_815_000, 5486) - .saturating_add(T::DbWeight::get().reads(2)) - .saturating_add(T::DbWeight::get().writes(1)) - } - /// Storage: PolimecFunding ProjectsIssuers (r:1 w:0) - /// Proof Skipped: PolimecFunding ProjectsIssuers (max_values: None, max_size: None, mode: Measured) - /// Storage: PolimecFunding ProjectsInfo (r:1 w:0) - /// Proof Skipped: PolimecFunding ProjectsInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: PolimecFunding Projects (r:1 w:0) - /// Proof Skipped: PolimecFunding Projects (max_values: None, max_size: None, mode: Measured) - /// Storage: PolimecFunding AuctionsInfo (r:1 w:1) - /// Proof Skipped: PolimecFunding AuctionsInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - fn bid() -> Weight { - // Proof Size summary in bytes: - // Measured: `633` - // Estimated: `15035` - // Minimum execution time: 25_578 nanoseconds. - Weight::from_parts(26_100_000, 15035) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(2)) - } - /// Storage: PolimecFunding ProjectsIssuers (r:1 w:0) - /// Proof Skipped: PolimecFunding ProjectsIssuers (max_values: None, max_size: None, mode: Measured) - /// Storage: PolimecFunding ProjectsInfo (r:1 w:0) - /// Proof Skipped: PolimecFunding ProjectsInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:2 w:2) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - /// Storage: PolimecFunding Contributions (r:1 w:1) - /// Proof Skipped: PolimecFunding Contributions (max_values: None, max_size: None, mode: Measured) - fn contribute() -> Weight { - // Proof Size summary in bytes: - // Measured: `474` - // Estimated: `14053` - // Minimum execution time: 30_643 nanoseconds. - Weight::from_parts(31_201_000, 14053) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(3)) - } - /// Storage: PolimecFunding ProjectsInfo (r:1 w:0) - /// Proof Skipped: PolimecFunding ProjectsInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: PolimecFunding Contributions (r:1 w:1) - /// Proof Skipped: PolimecFunding Contributions (max_values: None, max_size: None, mode: Measured) - /// Storage: Assets Asset (r:1 w:1) - /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) - /// Storage: Assets Account (r:1 w:1) - /// Proof: Assets Account (max_values: None, max_size: Some(102), added: 2577, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) - fn claim_contribution_tokens() -> Weight { - // Proof Size summary in bytes: - // Measured: `877` - // Estimated: `14569` - // Minimum execution time: 26_228 nanoseconds. - Weight::from_parts(27_498_000, 14569) - .saturating_add(T::DbWeight::get().reads(5)) - .saturating_add(T::DbWeight::get().writes(4)) - } - /// Storage: PolimecFunding ProjectsActive (r:1 w:0) - /// Proof Skipped: PolimecFunding ProjectsActive (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: PolimecFunding ProjectsInfo (r:100 w:100) - /// Proof Skipped: PolimecFunding ProjectsInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: PolimecFunding Bonds (r:200 w:0) - /// Proof Skipped: PolimecFunding Bonds (max_values: None, max_size: None, mode: Measured) - fn on_initialize() -> Weight { - // Proof Size summary in bytes: - // Measured: `15727` - // Estimated: `790176` - // Minimum execution time: 1_279_152 nanoseconds. - Weight::from_parts(1_286_826_000, 790176) - .saturating_add(T::DbWeight::get().reads(301)) - .saturating_add(T::DbWeight::get().writes(100)) - } - - fn failed_evaluation_unbond_for() -> Weight { - Weight::from_ref_time(1_000_000) - } -} diff --git a/runtimes/testnet/src/weights/paritydb_weights.rs b/runtimes/testnet/src/weights/paritydb_weights.rs deleted file mode 100644 index 8f380e07a..000000000 --- a/runtimes/testnet/src/weights/paritydb_weights.rs +++ /dev/null @@ -1,62 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -pub mod constants { - use frame_support::{ - parameter_types, - weights::{constants, RuntimeDbWeight}, - }; - - parameter_types! { - /// `ParityDB` can be enabled with a feature flag, but is still experimental. These weights - /// are available for brave runtime engineers who may want to try this out as default. - pub const ParityDbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 8_000 * constants::WEIGHT_REF_TIME_PER_NANOS, - write: 50_000 * constants::WEIGHT_REF_TIME_PER_NANOS, - }; - } - - #[cfg(test)] - mod test_db_weights { - use super::constants::ParityDbWeight as W; - use frame_support::weights::constants; - - /// Checks that all weights exist and have sane values. - // NOTE: If this test fails but you are sure that the generated values are fine, - // you can delete it. - #[test] - fn sane() { - // At least 1 µs. - assert!( - W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, - "Read weight should be at least 1 µs." - ); - assert!( - W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, - "Write weight should be at least 1 µs." - ); - // At most 1 ms. - assert!( - W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, - "Read weight should be at most 1 ms." - ); - assert!( - W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, - "Write weight should be at most 1 ms." - ); - } - } -} diff --git a/runtimes/testnet/src/weights/rocksdb_weights.rs b/runtimes/testnet/src/weights/rocksdb_weights.rs deleted file mode 100644 index d7e720f64..000000000 --- a/runtimes/testnet/src/weights/rocksdb_weights.rs +++ /dev/null @@ -1,62 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -pub mod constants { - use frame_support::{ - parameter_types, - weights::{constants, RuntimeDbWeight}, - }; - - parameter_types! { - /// By default, Substrate uses `RocksDB`, so this will be the weight used throughout - /// the runtime. - pub const RocksDbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 25_000 * constants::WEIGHT_REF_TIME_PER_NANOS, - write: 100_000 * constants::WEIGHT_REF_TIME_PER_NANOS, - }; - } - - #[cfg(test)] - mod test_db_weights { - use super::constants::RocksDbWeight as W; - use frame_support::weights::constants; - - /// Checks that all weights exist and have sane values. - // NOTE: If this test fails but you are sure that the generated values are fine, - // you can delete it. - #[test] - fn sane() { - // At least 1 µs. - assert!( - W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, - "Read weight should be at least 1 µs." - ); - assert!( - W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, - "Write weight should be at least 1 µs." - ); - // At most 1 ms. - assert!( - W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, - "Read weight should be at most 1 ms." - ); - assert!( - W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, - "Write weight should be at most 1 ms." - ); - } - } -} diff --git a/runtimes/testnet/src/xcm_config.rs b/runtimes/testnet/src/xcm_config.rs index 5aa13b359..b450763d1 100644 --- a/runtimes/testnet/src/xcm_config.rs +++ b/runtimes/testnet/src/xcm_config.rs @@ -39,11 +39,13 @@ use polkadot_runtime_common::impls::ToAuthor; use sp_runtime::traits::Zero; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, - FixedRateOfFungible, FixedWeightBounds, FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, ParentIsPreset, - RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, WithComputedOrigin, + AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, + AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, + ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, + FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, ParentIsPreset, RelayChainAsNative, + SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, + WithComputedOrigin, }; use xcm_executor::{ traits::{Convert, Error, JustTry, MatchesFungibles}, @@ -51,8 +53,9 @@ use xcm_executor::{ }; use super::{ - AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Balance, Balances, ParachainInfo, ParachainSystem, - PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, StatemintAssets, WeightToFee, XcmpQueue, + AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Balance, Balances, + ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, + StatemintAssets, WeightToFee, XcmpQueue, }; const DOT_ASSET_ID: AssetId = Concrete(RelayLocation::get()); @@ -121,19 +124,13 @@ pub struct NativeToFungible; impl Convert for NativeToFungible { fn convert(asset: MultiLocation) -> Result { match asset { - MultiLocation { - parents: 1, - interior: Here, - } => Ok(AssetIdPalletAssets::from(0u32)), + MultiLocation { parents: 1, interior: Here } => Ok(AssetIdPalletAssets::from(0u32)), _ => Err(asset), } } fn reverse(value: AssetIdPalletAssets) -> Result { if value == AssetIdPalletAssets::from(0u32) { - Ok(MultiLocation { - parents: 1, - interior: Here, - }) + Ok(MultiLocation { parents: 1, interior: Here }) } else { Err(value) } @@ -154,8 +151,10 @@ impl< for NonBlockingConvertedConcreteId { fn matches_fungibles(a: &MultiAsset) -> Result<(AssetId, Balance), Error> { - ConvertedConcreteId::::matches_fungibles(a) - .map_err(|_| Error::AssetNotFound) + ConvertedConcreteId::::matches_fungibles( + a, + ) + .map_err(|_| Error::AssetNotFound) } } @@ -176,7 +175,8 @@ pub type StatemintDotTransactor = FungiblesAdapter< >; /// Means for transacting assets on this chain. -pub type AssetTransactors = (CurrencyTransactor, StatemintDotTransactor, StatemintFungiblesTransactor); +pub type AssetTransactors = + (CurrencyTransactor, StatemintDotTransactor, StatemintFungiblesTransactor); /// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, /// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can @@ -228,7 +228,10 @@ pub type Barrier = DenyThenTry< // If the message is one that immediately attemps to pay for execution, then allow it. AllowTopLevelPaidExecutionFrom, // Common Good Assets parachain, parent and its exec plurality get free execution - AllowExplicitUnpaidExecutionFrom<(CommonGoodAssetsParachain, ParentOrParentsExecutivePlurality)>, + AllowExplicitUnpaidExecutionFrom<( + CommonGoodAssetsParachain, + ParentOrParentsExecutivePlurality, + )>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, ), @@ -250,8 +253,8 @@ impl ContainsPair for StatemintAssetsFilter { // location must be the statemint parachain let loc = MultiLocation::new(1, X1(Parachain(1000))); // asset must be either a fungible asset from `pallet_assets` or the native token of the relay chain - &loc == origin - && match asset { + &loc == origin && + match asset { MultiAsset { id: Concrete(MultiLocation { @@ -261,11 +264,7 @@ impl ContainsPair for StatemintAssetsFilter { .. } => true, MultiAsset { - id: Concrete(MultiLocation { - parents: 1, - interior: Here, - }), - .. + id: Concrete(MultiLocation { parents: 1, interior: Here }), .. } => true, _ => false, @@ -276,8 +275,8 @@ impl ContainsPair for StatemintAssetsFilter { impl> ContainsPair for AssetsFrom { fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool { let loc = T::get(); - &loc == origin - && matches!(asset, MultiAsset { id: AssetId::Concrete(asset_loc), fun: Fungible(_a) } + &loc == origin && + matches!(asset, MultiAsset { id: AssetId::Concrete(asset_loc), fun: Fungible(_a) } if asset_loc.match_and_split(&loc).is_some()) } } @@ -343,7 +342,7 @@ impl ContainsPair for MultiNativeAsset { fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool { if let Some(ref reserve) = asset.reserve() { if reserve == origin { - return true; + return true } } false @@ -376,7 +375,7 @@ impl xcm_executor::Config for XcmConfig { type Weigher = FixedWeightBounds; type Trader = ( // TODO: weight to fee has to be carefully considered. For now use default - UsingComponents, HereLocation, AccountId, Balances, ToAuthor>, + UsingComponents>, FixedRateOfFungible, ); type ResponseHandler = PolkadotXcm; diff --git a/rustfmt.toml b/rustfmt.toml index 402b58e25..6df3a1834 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,8 +1,24 @@ -edition = "2021" -fn_params_layout = "Compressed" -use_field_init_shorthand = true -max_width = 120 -use_small_heuristics = "Default" # This modifies `fn_call_width`, `attr_fn_like_width`, `struct_lit_width`, `struct_variant_width`, `array_width`, `chain_width`, `single_line_if_else_max_width` according to the value of `max_width` -use_try_shorthand = true +# Basic +hard_tabs = true +max_width = 100 +use_small_heuristics = "Max" +# Imports +imports_granularity = "Crate" +reorder_imports = true +# Consistency newline_style = "Unix" -hard_tabs = true \ No newline at end of file +# Misc +chain_width = 80 +spaces_around_ranges = false +binop_separator = "Back" +reorder_impl_items = false +match_arm_leading_pipes = "Preserve" +match_arm_blocks = false +match_block_trailing_comma = true +trailing_comma = "Vertical" +trailing_semicolon = false +use_field_init_shorthand = true +ignore = [ + "bridges", +] +edition = "2021" \ No newline at end of file diff --git a/traits/Cargo.toml b/traits/Cargo.toml deleted file mode 100644 index aa5411b7a..000000000 --- a/traits/Cargo.toml +++ /dev/null @@ -1,42 +0,0 @@ -[package] -name = 'polimec-traits' -description = 'Common traits for Polimec pallets' -authors.workspace = true -documentation.workspace = true -edition.workspace = true -homepage.workspace = true -license-file.workspace = true -readme.workspace = true -repository.workspace = true -version.workspace = true - -[dependencies] -parity-scale-codec = { workspace = true, features = [ - "derive", -] } -scale-info = { workspace = true, features = ["derive"] } -serde = { workspace = true, features = ["derive"], default-features = false } -frame-benchmarking = { workspace = true, optional = true } -frame-support.workspace = true -frame-system.workspace = true -sp-std.workspace = true -sp-runtime.workspace = true - -[dev-dependencies] -sp-core.workspace = true -sp-io.workspace = true - -[features] -default = ["std"] -std = [ - "frame-benchmarking?/std", - "parity-scale-codec/std", - "sp-std/std", - "sp-runtime/std", - "frame-support/std", - "frame-system/std", - "scale-info/std", - "serde/std", -] -runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] -try-runtime = ["frame-support/try-runtime"] diff --git a/traits/src/lib.rs b/traits/src/lib.rs deleted file mode 100644 index ab2269e92..000000000 --- a/traits/src/lib.rs +++ /dev/null @@ -1,83 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -#![cfg_attr(not(feature = "std"), no_std)] - -use core::slice::Iter; -use frame_support::{ - pallet_prelude::{Decode, DispatchError, Encode, MaxEncodedLen, TypeInfo}, - BoundedVec, RuntimeDebug, -}; -use serde::{Deserialize, Serialize}; -use sp_std::vec::Vec; - -/// The various roles that a member can hold. -#[derive(Copy, Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen, Serialize, Deserialize)] -pub enum MemberRole { - Issuer, - Retail, - Professional, - Institutional, -} - -impl MemberRole { - pub fn iterator() -> Iter<'static, MemberRole> { - static ROLES: [MemberRole; 4] = [ - MemberRole::Issuer, - MemberRole::Retail, - MemberRole::Professional, - MemberRole::Institutional, - ]; - ROLES.iter() - } -} - -/// The various attesters on KILT. -#[derive(Copy, Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)] -pub enum Issuers { - IssuerOne, - IssuerTwo, - IssuerThree, - IssuerFour, -} - -#[derive(Copy, Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)] -pub enum Country { - Switzerland, - UnitedStates, -} - -// TODO: Set this at runtime -type MaxDomicile = frame_support::traits::ConstU32<255>; - -/// A basic "credential" representation -#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)] -pub struct Credential { - pub issuer: Issuers, - pub role: MemberRole, - pub domicile: BoundedVec, - pub country: Country, - // TODO: Find a way to handle the date of birth - pub date_of_birth: u32, -} - -pub trait PolimecMembers { - fn is_in(role: &MemberRole, who: &AccountId) -> bool; - fn add_member(role: &MemberRole, who: &AccountId) -> Result<(), DispatchError>; - fn initialize_members(role: &MemberRole, members: &[AccountId]); - fn get_members_of(role: &MemberRole) -> Vec; - fn get_roles_of(who: &AccountId) -> Vec; -} From edb84f6c2574c0d8a4964657a18d3b4d959e28ee Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Thu, 13 Jul 2023 17:38:58 +0200 Subject: [PATCH 33/80] make integration tests compile --- integration-tests/src/lib.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs index 09b481930..4a5e6dfde 100644 --- a/integration-tests/src/lib.rs +++ b/integration-tests/src/lib.rs @@ -97,9 +97,6 @@ fn statemint_id() -> u32 { fn penpal_id() -> u32 { _para_ids()[2] } -fn provider_id() -> u32 { - _para_ids()[3] -} // Helper functions to calculate chain accounts struct ParachainAccounts; @@ -124,9 +121,6 @@ impl ParachainAccounts { fn penpal_sibling_account() -> RuntimeAccountId32 { SiblingId::from(penpal_id()).into_account_truncating() } - fn provider_sibling_account() -> RuntimeAccountId32 { - SiblingId::from(provider_id()).into_account_truncating() - } } fn default_parachains_host_configuration( @@ -229,7 +223,6 @@ pub fn polimec_ext(para_id: u32) -> sp_io::TestExternalities { (DISPATCHER_ACCOUNT, INITIAL_BALANCE), (ParachainAccounts::penpal_sibling_account(), INITIAL_BALANCE), (ParachainAccounts::statemint_sibling_account(), INITIAL_BALANCE), - (ParachainAccounts::provider_sibling_account(), INITIAL_BALANCE), ], } .assimilate_storage(&mut t) @@ -243,7 +236,12 @@ pub fn polimec_ext(para_id: u32) -> sp_io::TestExternalities { 12, )], accounts: vec![(RELAY_ASSET_ID, ALICE, INITIAL_BALANCE)], - ..Default::default() + assets: vec![( + RELAY_ASSET_ID, + frame_support::PalletId(*b"assetsid").into_account_truncating(), + false, + 1_0_000_000_000, + )], } .assimilate_storage(&mut t) .unwrap(); From cc1cb23429bb67967110a3738ebd47dc334c7c36 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 14 Jul 2023 11:45:01 +0200 Subject: [PATCH 34/80] feat: update to 0.9.42 --- .maintain/frame-weight-template.hbs | 60 +- Cargo.lock | 1713 ++++++++++------- Cargo.toml | 233 ++- README.md | 4 +- integration-tests/modified-penpal/Cargo.toml | 2 +- integration-tests/modified-penpal/src/lib.rs | 39 +- .../modified-penpal/src/xcm_config.rs | 46 +- integration-tests/src/lib.rs | 501 ++--- nodes/parachain/Cargo.toml | 1 + nodes/parachain/src/chain_spec.rs | 2 +- nodes/parachain/src/command.rs | 3 +- nodes/parachain/src/service.rs | 71 +- nodes/standalone/Cargo.toml | 5 +- nodes/standalone/src/chain_spec.rs | 2 +- nodes/standalone/src/command.rs | 33 +- nodes/standalone/src/service.rs | 86 +- pallets/funding/src/lib.rs | 5 +- pallets/funding/src/mock.rs | 4 + pallets/sandbox/src/mock.rs | 4 + runtimes/base/src/lib.rs | 21 +- runtimes/base/src/xcm_config.rs | 5 +- .../shared-configuration/src/weights/mod.rs | 1 + runtimes/standalone/Cargo.toml | 4 + runtimes/standalone/src/lib.rs | 116 +- runtimes/testnet/src/lib.rs | 63 +- runtimes/testnet/src/xcm_config.rs | 9 +- rust-toolchain.toml | 2 +- 27 files changed, 1695 insertions(+), 1340 deletions(-) diff --git a/.maintain/frame-weight-template.hbs b/.maintain/frame-weight-template.hbs index 09a7fe280..5db697617 100644 --- a/.maintain/frame-weight-template.hbs +++ b/.maintain/frame-weight-template.hbs @@ -20,9 +20,10 @@ //! Autogenerated weights for {{pallet}} //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION {{version}} -//! DATE: {{date}}, STEPS: `{{cmd.steps}}`, REPEAT: {{cmd.repeat}}, LOW RANGE: `{{cmd.lowest_range_values}}`, HIGH RANGE: `{{cmd.highest_range_values}}` +//! DATE: {{date}}, STEPS: `{{cmd.steps}}`, REPEAT: `{{cmd.repeat}}`, LOW RANGE: `{{cmd.lowest_range_values}}`, HIGH RANGE: `{{cmd.highest_range_values}}` +//! WORST CASE MAP SIZE: `{{cmd.worst_case_map_values}}` //! HOSTNAME: `{{hostname}}`, CPU: `{{cpuname}}` -//! EXECUTION: {{cmd.execution}}, WASM-EXECUTION: {{cmd.wasm_execution}}, CHAIN: {{cmd.chain}}, DB CACHE: {{cmd.db_cache}} +//! EXECUTION: `{{cmd.execution}}`, WASM-EXECUTION: `{{cmd.wasm_execution}}`, CHAIN: `{{cmd.chain}}`, DB CACHE: `{{cmd.db_cache}}` // Executed Command: {{#each args as |arg|}} @@ -32,9 +33,10 @@ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] +#![allow(missing_docs)] use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use sp_std::marker::PhantomData; +use core::marker::PhantomData; /// Weight functions needed for {{pallet}}. pub trait WeightInfo { @@ -56,7 +58,7 @@ impl WeightInfo for SubstrateWeight { {{/if}} {{#each benchmarks as |benchmark|}} {{#each benchmark.comments as |comment|}} - // {{comment}} + /// {{comment}} {{/each}} {{#each benchmark.component_ranges as |range|}} /// The range of component `{{range.name}}` is `[{{range.min}}, {{range.max}}]`. @@ -66,59 +68,29 @@ impl WeightInfo for SubstrateWeight { {{~#each benchmark.components as |c| ~}} {{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}} ) -> Weight { - // Minimum execution time: {{underscore benchmark.min_execution_time}} nanoseconds. - Weight::from_ref_time({{underscore benchmark.base_weight}}) + // Proof Size summary in bytes: + // Measured: `{{benchmark.base_recorded_proof_size}}{{#each benchmark.component_recorded_proof_size as |cp|}} + {{cp.name}} * ({{cp.slope}} ±{{underscore cp.error}}){{/each}}` + // Estimated: `{{benchmark.base_calculated_proof_size}}{{#each benchmark.component_calculated_proof_size as |cp|}} + {{cp.name}} * ({{cp.slope}} ±{{underscore cp.error}}){{/each}}` + // Minimum execution time: {{underscore benchmark.min_execution_time}}_000 picoseconds. + Weight::from_parts({{underscore benchmark.base_weight}}, {{benchmark.base_calculated_proof_size}}) {{#each benchmark.component_weight as |cw|}} // Standard Error: {{underscore cw.error}} - .saturating_add(Weight::from_ref_time({{underscore cw.slope}}).saturating_mul({{cw.name}}.into())) + .saturating_add(Weight::from_parts({{underscore cw.slope}}, 0).saturating_mul({{cw.name}}.into())) {{/each}} {{#if (ne benchmark.base_reads "0")}} - .saturating_add(T::DbWeight::get().reads({{benchmark.base_reads}})) + .saturating_add(T::DbWeight::get().reads({{benchmark.base_reads}}_u64)) {{/if}} {{#each benchmark.component_reads as |cr|}} .saturating_add(T::DbWeight::get().reads(({{cr.slope}}_u64).saturating_mul({{cr.name}}.into()))) {{/each}} {{#if (ne benchmark.base_writes "0")}} - .saturating_add(T::DbWeight::get().writes({{benchmark.base_writes}})) + .saturating_add(T::DbWeight::get().writes({{benchmark.base_writes}}_u64)) {{/if}} {{#each benchmark.component_writes as |cw|}} .saturating_add(T::DbWeight::get().writes(({{cw.slope}}_u64).saturating_mul({{cw.name}}.into()))) {{/each}} - } - {{/each}} -} - -// For backwards compatibility and tests -impl WeightInfo for () { - {{#each benchmarks as |benchmark|}} - {{#each benchmark.comments as |comment|}} - // {{comment}} - {{/each}} - {{#each benchmark.component_ranges as |range|}} - /// The range of component `{{range.name}}` is `[{{range.min}}, {{range.max}}]`. - {{/each}} - fn {{benchmark.name~}} - ( - {{~#each benchmark.components as |c| ~}} - {{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}} - ) -> Weight { - // Minimum execution time: {{underscore benchmark.min_execution_time}} nanoseconds. - Weight::from_ref_time({{underscore benchmark.base_weight}}) - {{#each benchmark.component_weight as |cw|}} - // Standard Error: {{underscore cw.error}} - .saturating_add(Weight::from_ref_time({{underscore cw.slope}}).saturating_mul({{cw.name}}.into())) - {{/each}} - {{#if (ne benchmark.base_reads "0")}} - .saturating_add(RocksDbWeight::get().reads({{benchmark.base_reads}})) - {{/if}} - {{#each benchmark.component_reads as |cr|}} - .saturating_add(RocksDbWeight::get().reads(({{cr.slope}}_u64).saturating_mul({{cr.name}}.into()))) - {{/each}} - {{#if (ne benchmark.base_writes "0")}} - .saturating_add(RocksDbWeight::get().writes({{benchmark.base_writes}})) - {{/if}} - {{#each benchmark.component_writes as |cw|}} - .saturating_add(RocksDbWeight::get().writes(({{cw.slope}}_u64).saturating_mul({{cw.name}}.into()))) + {{#each benchmark.component_calculated_proof_size as |cp|}} + .saturating_add(Weight::from_parts(0, {{cp.slope}}).saturating_mul({{cp.name}}.into())) {{/each}} } {{/each}} diff --git a/Cargo.lock b/Cargo.lock index 9949fb987..2faa2f1ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -388,6 +388,37 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" +[[package]] +name = "assets-common" +version = "0.1.0" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +dependencies = [ + "cumulus-primitives-core", + "frame-support", + "log", + "pallet-xcm", + "parachains-common", + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-std", + "substrate-wasm-builder", + "xcm", + "xcm-builder", + "xcm-executor", +] + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + [[package]] name = "async-io" version = "1.13.0" @@ -417,6 +448,17 @@ dependencies = [ "event-listener", ] +[[package]] +name = "async-recursion" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + [[package]] name = "async-trait" version = "0.1.71" @@ -492,10 +534,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" [[package]] -name = "base58" +name = "base16ct" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] name = "base64" @@ -524,63 +566,10 @@ dependencies = [ "serde", ] -[[package]] -name = "beefy-gadget" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" -dependencies = [ - "array-bytes 4.2.0", - "async-trait", - "fnv", - "futures", - "log", - "parity-scale-codec", - "parking_lot 0.12.1", - "sc-client-api", - "sc-consensus", - "sc-keystore", - "sc-network", - "sc-network-common", - "sc-network-gossip", - "sc-utils", - "sp-api", - "sp-application-crypto", - "sp-arithmetic", - "sp-beefy", - "sp-blockchain", - "sp-consensus", - "sp-core", - "sp-keystore", - "sp-mmr-primitives", - "sp-runtime", - "substrate-prometheus-endpoint", - "thiserror", - "wasm-timer", -] - -[[package]] -name = "beefy-gadget-rpc" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" -dependencies = [ - "beefy-gadget", - "futures", - "jsonrpsee", - "log", - "parity-scale-codec", - "parking_lot 0.12.1", - "sc-rpc", - "serde", - "sp-beefy", - "sp-core", - "sp-runtime", - "thiserror", -] - [[package]] name = "binary-merkle-tree" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "hash-db", "log", @@ -843,9 +832,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" dependencies = [ "serde", ] @@ -1104,6 +1093,19 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "console" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.45.0", +] + [[package]] name = "const-oid" version = "0.9.4" @@ -1375,6 +1377,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "crypto-bigint" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15" +dependencies = [ + "generic-array 0.14.7", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -1427,7 +1441,7 @@ dependencies = [ [[package]] name = "cumulus-client-cli" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "clap", "parity-scale-codec", @@ -1442,7 +1456,7 @@ dependencies = [ [[package]] name = "cumulus-client-collator" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "cumulus-client-consensus-common", "cumulus-client-network", @@ -1465,7 +1479,7 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-aura" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "async-trait", "cumulus-client-consensus-common", @@ -1494,7 +1508,7 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-common" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "async-trait", "cumulus-client-pov-recovery", @@ -1518,7 +1532,7 @@ dependencies = [ [[package]] name = "cumulus-client-network" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "async-trait", "cumulus-relay-chain-interface", @@ -1541,7 +1555,7 @@ dependencies = [ [[package]] name = "cumulus-client-pov-recovery" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -1565,7 +1579,7 @@ dependencies = [ [[package]] name = "cumulus-client-service" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "cumulus-client-cli", "cumulus-client-collator", @@ -1577,11 +1591,11 @@ dependencies = [ "cumulus-relay-chain-interface", "cumulus-relay-chain-minimal-node", "futures", - "parking_lot 0.12.1", "polkadot-primitives", "sc-client-api", "sc-consensus", "sc-network", + "sc-network-sync", "sc-network-transactions", "sc-rpc", "sc-service", @@ -1600,7 +1614,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-aura-ext" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "frame-support", "frame-system", @@ -1616,7 +1630,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-dmp-queue" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -1633,7 +1647,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-parachain-system" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "bytes", "cumulus-pallet-parachain-system-proc-macro", @@ -1662,18 +1676,18 @@ dependencies = [ [[package]] name = "cumulus-pallet-parachain-system-proc-macro" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.25", ] [[package]] name = "cumulus-pallet-session-benchmarking" version = "3.0.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "frame-benchmarking", "frame-support", @@ -1687,7 +1701,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcm" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -1703,7 +1717,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcmp-queue" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "cumulus-primitives-core", "frame-benchmarking", @@ -1724,12 +1738,13 @@ dependencies = [ [[package]] name = "cumulus-primitives-core" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "parity-scale-codec", "polkadot-core-primitives", "polkadot-parachain", "polkadot-primitives", + "scale-info", "sp-api", "sp-runtime", "sp-std", @@ -1740,7 +1755,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-parachain-inherent" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -1763,7 +1778,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-timestamp" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "cumulus-primitives-core", "futures", @@ -1776,7 +1791,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-utility" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -1794,7 +1809,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-inprocess-interface" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -1819,7 +1834,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-interface" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -1827,19 +1842,17 @@ dependencies = [ "jsonrpsee-core", "parity-scale-codec", "polkadot-overseer", - "polkadot-service", "sc-client-api", "sp-api", "sp-blockchain", "sp-state-machine", "thiserror", - "tokio", ] [[package]] name = "cumulus-relay-chain-minimal-node" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "array-bytes 6.1.0", "async-trait", @@ -1848,24 +1861,23 @@ dependencies = [ "cumulus-relay-chain-rpc-interface", "futures", "lru 0.9.0", + "polkadot-availability-recovery", + "polkadot-collator-protocol", "polkadot-core-primitives", "polkadot-network-bridge", + "polkadot-node-collation-generation", + "polkadot-node-core-runtime-api", "polkadot-node-network-protocol", "polkadot-node-subsystem-util", "polkadot-overseer", "polkadot-primitives", - "polkadot-service", "sc-authority-discovery", "sc-client-api", - "sc-consensus", - "sc-keystore", "sc-network", "sc-network-common", "sc-service", - "sc-telemetry", "sc-tracing", - "sc-transaction-pool", - "sc-transaction-pool-api", + "sc-utils", "sp-api", "sp-blockchain", "sp-consensus", @@ -1873,13 +1885,12 @@ dependencies = [ "sp-runtime", "tokio", "tracing", - "url", ] [[package]] name = "cumulus-relay-chain-rpc-interface" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -1889,9 +1900,10 @@ dependencies = [ "jsonrpsee", "lru 0.9.0", "parity-scale-codec", - "polkadot-service", + "polkadot-overseer", "sc-client-api", "sc-rpc-api", + "sc-service", "serde", "serde_json", "sp-api", @@ -1908,7 +1920,7 @@ dependencies = [ [[package]] name = "cumulus-test-relay-sproof-builder" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "cumulus-primitives-core", "parity-scale-codec", @@ -2074,6 +2086,16 @@ dependencies = [ "zeroize", ] +[[package]] +name = "der" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946" +dependencies = [ + "const-oid", + "zeroize", +] + [[package]] name = "der-parser" version = "7.0.0" @@ -2199,6 +2221,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", + "const-oid", "crypto-common", "subtle", ] @@ -2306,10 +2329,24 @@ version = "0.14.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" dependencies = [ - "der", - "elliptic-curve", - "rfc6979", - "signature", + "der 0.6.1", + "elliptic-curve 0.12.3", + "rfc6979 0.3.1", + "signature 1.6.4", +] + +[[package]] +name = "ecdsa" +version = "0.16.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428" +dependencies = [ + "der 0.7.7", + "digest 0.10.7", + "elliptic-curve 0.13.5", + "rfc6979 0.4.0", + "signature 2.1.0", + "spki 0.7.2", ] [[package]] @@ -2318,7 +2355,7 @@ version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" dependencies = [ - "signature", + "signature 1.6.4", ] [[package]] @@ -2361,22 +2398,47 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" dependencies = [ - "base16ct", - "crypto-bigint", - "der", + "base16ct 0.1.1", + "crypto-bigint 0.4.9", + "der 0.6.1", "digest 0.10.7", - "ff", + "ff 0.12.1", "generic-array 0.14.7", - "group", + "group 0.12.1", "hkdf", "pem-rfc7468", - "pkcs8", + "pkcs8 0.9.0", "rand_core 0.6.4", - "sec1", + "sec1 0.3.0", "subtle", "zeroize", ] +[[package]] +name = "elliptic-curve" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" +dependencies = [ + "base16ct 0.2.0", + "crypto-bigint 0.5.2", + "digest 0.10.7", + "ff 0.13.0", + "generic-array 0.14.7", + "group 0.13.0", + "pkcs8 0.10.2", + "rand_core 0.6.4", + "sec1 0.7.2", + "subtle", + "zeroize", +] + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "enum-as-inner" version = "0.5.1" @@ -2511,6 +2573,18 @@ name = "expander" version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3774182a5df13c3d1690311ad32fbe913feef26baba609fa2dd5f72042bd2ab6" +dependencies = [ + "blake2", + "fs-err", + "proc-macro2", + "quote", +] + +[[package]] +name = "expander" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f360349150728553f92e4c997a16af8915f418d3a0f21b440d34c5632f16ed84" dependencies = [ "blake2", "fs-err", @@ -2519,6 +2593,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "expander" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f86a749cf851891866c10515ef6c299b5c69661465e9c3bbe7e07a2b77fb0f7" +dependencies = [ + "blake2", + "fs-err", + "proc-macro2", + "quote", + "syn 2.0.25", +] + [[package]] name = "fake-simd" version = "0.1.2" @@ -2584,6 +2671,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "fiat-crypto" version = "0.1.20" @@ -2675,7 +2772,7 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "fork-tree" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", ] @@ -2698,7 +2795,7 @@ checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" [[package]] name = "frame-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-support-procedural", @@ -2723,7 +2820,7 @@ dependencies = [ [[package]] name = "frame-benchmarking-cli" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "Inflector", "array-bytes 4.2.0", @@ -2770,18 +2867,18 @@ dependencies = [ [[package]] name = "frame-election-provider-solution-type" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.25", ] [[package]] name = "frame-election-provider-support" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-election-provider-solution-type", "frame-support", @@ -2798,7 +2895,7 @@ dependencies = [ [[package]] name = "frame-executive" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -2827,15 +2924,19 @@ dependencies = [ [[package]] name = "frame-remote-externalities" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ + "async-recursion", "futures", + "indicatif", + "jsonrpsee", "log", "parity-scale-codec", "serde", "sp-core", "sp-io", "sp-runtime", + "spinners", "substrate-rpc-client", "tokio", ] @@ -2843,9 +2944,10 @@ dependencies = [ [[package]] name = "frame-support" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "bitflags 1.3.2", + "environmental", "frame-metadata", "frame-support-procedural", "impl-trait-for-tuples", @@ -2875,44 +2977,45 @@ dependencies = [ [[package]] name = "frame-support-procedural" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "Inflector", "cfg-expr", "derive-syn-parse", "frame-support-procedural-tools", "itertools", + "proc-macro-warning", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.25", ] [[package]] name = "frame-support-procedural-tools" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support-procedural-tools-derive", "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.25", ] [[package]] name = "frame-support-procedural-tools-derive" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.25", ] [[package]] name = "frame-system" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "log", @@ -2930,7 +3033,7 @@ dependencies = [ [[package]] name = "frame-system-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -2945,7 +3048,7 @@ dependencies = [ [[package]] name = "frame-system-rpc-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "sp-api", @@ -2954,7 +3057,7 @@ dependencies = [ [[package]] name = "frame-try-runtime" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "parity-scale-codec", @@ -2979,6 +3082,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "fs4" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eeb4ed9e12f43b7fa0baae3f9cdda28352770132ef2e09a23760c29cae8bd47" +dependencies = [ + "rustix 0.38.4", + "windows-sys 0.48.0", +] + [[package]] name = "funty" version = "2.0.0" @@ -3133,6 +3246,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum 1.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "version_check", + "zeroize", ] [[package]] @@ -3229,7 +3343,18 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" dependencies = [ - "ff", + "ff 0.12.1", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff 0.13.0", "rand_core 0.6.4", "subtle", ] @@ -3269,9 +3394,9 @@ dependencies = [ [[package]] name = "hash-db" -version = "0.15.2" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" +checksum = "8e7d7786361d7425ae2fe4f9e407eb0efaa0840f5212d109cc018c40c35c6ab4" [[package]] name = "hash256-std-hasher" @@ -3339,6 +3464,12 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + [[package]] name = "hkdf" version = "0.12.3" @@ -3482,6 +3613,7 @@ dependencies = [ "rustls-native-certs", "tokio", "tokio-rustls", + "webpki-roots", ] [[package]] @@ -3613,6 +3745,19 @@ dependencies = [ "hashbrown 0.14.0", ] +[[package]] +name = "indicatif" +version = "0.17.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ff8cc23a7393a397ed1d7f56e6365cba772aba9f9912ab968b03043c395d057" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "unicode-width", +] + [[package]] name = "inout" version = "0.1.3" @@ -3783,6 +3928,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d291e3a5818a2384645fd9756362e6d89cf0541b0b916fa7702ea4a9833608e" dependencies = [ "jsonrpsee-core", + "jsonrpsee-http-client", "jsonrpsee-proc-macros", "jsonrpsee-server", "jsonrpsee-types", @@ -3839,6 +3985,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "jsonrpsee-http-client" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc345b0a43c6bc49b947ebeb936e886a419ee3d894421790c969cc56040542ad" +dependencies = [ + "async-trait", + "hyper", + "hyper-rustls", + "jsonrpsee-core", + "jsonrpsee-types", + "rustc-hash", + "serde", + "serde_json", + "thiserror", + "tokio", + "tracing", +] + [[package]] name = "jsonrpsee-proc-macros" version = "0.16.2" @@ -3902,13 +4067,14 @@ dependencies = [ [[package]] name = "k256" -version = "0.11.6" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" dependencies = [ "cfg-if", - "ecdsa", - "elliptic-curve", + "ecdsa 0.16.7", + "elliptic-curve 0.13.5", + "once_cell", "sha2 0.10.7", ] @@ -3923,8 +4089,8 @@ dependencies = [ [[package]] name = "kusama-runtime" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitvec", "frame-benchmarking", @@ -3935,7 +4101,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal", + "hex-literal 0.4.1", "kusama-runtime-constants", "log", "pallet-authority-discovery", @@ -3997,9 +4163,9 @@ dependencies = [ "sp-api", "sp-arithmetic", "sp-authority-discovery", - "sp-beefy", "sp-block-builder", "sp-consensus-babe", + "sp-consensus-beefy", "sp-core", "sp-inherents", "sp-io", @@ -4021,8 +4187,8 @@ dependencies = [ [[package]] name = "kusama-runtime-constants" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "frame-support", "polkadot-primitives", @@ -4054,9 +4220,9 @@ dependencies = [ [[package]] name = "kvdb-rocksdb" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2182b8219fee6bd83aacaab7344e840179ae079d5216aa4e249b4d704646a844" +checksum = "fe7a749456510c45f795e8b04a6a3e0976d0139213ecbf465843830ad55e2217" dependencies = [ "kvdb", "num_cpus", @@ -4165,7 +4331,7 @@ dependencies = [ "prost-build", "rand 0.8.5", "rw-stream-sink", - "sec1", + "sec1 0.3.0", "sha2 0.10.7", "smallvec", "thiserror", @@ -4561,9 +4727,9 @@ dependencies = [ [[package]] name = "librocksdb-sys" -version = "0.8.3+7.4.4" +version = "0.10.0+7.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "557b255ff04123fcc176162f56ed0c9cd42d8f357cf55b3fabeb60f7413741b3" +checksum = "0fe4d5874f5ff2bc616e55e8c6086d478fcda13faf9495768a4aa1c22042d30b" dependencies = [ "bindgen", "bzip2-sys", @@ -4756,6 +4922,12 @@ dependencies = [ "libc", ] +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + [[package]] name = "match_cfg" version = "0.1.0" @@ -4829,15 +5001,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - [[package]] name = "memoffset" version = "0.9.0" @@ -4849,12 +5012,11 @@ dependencies = [ [[package]] name = "memory-db" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e0c7cba9ce19ac7ffd2053ac9f49843bbd3f4318feedfd74e85c19d5fb0ba66" +checksum = "808b50db46293432a45e63bc15ea51e0ab4c0a1647b8eb114e31a3e698dd6fbe" dependencies = [ "hash-db", - "hashbrown 0.12.3", ] [[package]] @@ -4915,7 +5077,7 @@ dependencies = [ [[package]] name = "mmr-gadget" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "futures", "log", @@ -4923,9 +5085,9 @@ dependencies = [ "sc-client-api", "sc-offchain", "sp-api", - "sp-beefy", "sp-blockchain", "sp-consensus", + "sp-consensus-beefy", "sp-core", "sp-mmr-primitives", "sp-runtime", @@ -4934,7 +5096,7 @@ dependencies = [ [[package]] name = "mmr-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "anyhow", "jsonrpsee", @@ -5204,20 +5366,6 @@ dependencies = [ "memoffset 0.6.5", ] -[[package]] -name = "nix" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset 0.7.1", - "pin-utils", - "static_assertions", -] - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -5311,6 +5459,12 @@ dependencies = [ "libc", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "object" version = "0.29.0" @@ -5376,9 +5530,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "orchestra" -version = "0.0.4" +version = "0.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17e7d5b6bb115db09390bed8842c94180893dd83df3dfce7354f2a2aa090a4ee" +checksum = "227585216d05ba65c7ab0a0450a3cf2cbd81a98862a54c4df8e14d5ac6adb015" dependencies = [ "async-trait", "dyn-clonable", @@ -5393,9 +5547,9 @@ dependencies = [ [[package]] name = "orchestra-proc-macro" -version = "0.0.4" +version = "0.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2af4dabb2286b0be0e9711d2d24e25f6217048b71210cffd3daddc3b5c84e1f" +checksum = "2871aadd82a2c216ee68a69837a526dfe788ecbe74c4c5038a6acdbff6653066" dependencies = [ "expander 0.0.6", "itertools", @@ -5421,8 +5575,8 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" dependencies = [ - "ecdsa", - "elliptic-curve", + "ecdsa 0.14.8", + "elliptic-curve 0.12.3", "sha2 0.10.7", ] @@ -5432,8 +5586,8 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa" dependencies = [ - "ecdsa", - "elliptic-curve", + "ecdsa 0.14.8", + "elliptic-curve 0.12.3", "sha2 0.10.7", ] @@ -5450,7 +5604,7 @@ dependencies = [ [[package]] name = "pallet-asset-tx-payment" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5468,7 +5622,7 @@ dependencies = [ [[package]] name = "pallet-assets" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5483,7 +5637,7 @@ dependencies = [ [[package]] name = "pallet-aura" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -5499,7 +5653,7 @@ dependencies = [ [[package]] name = "pallet-authority-discovery" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -5515,7 +5669,7 @@ dependencies = [ [[package]] name = "pallet-authorship" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -5529,7 +5683,7 @@ dependencies = [ [[package]] name = "pallet-babe" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5542,7 +5696,7 @@ dependencies = [ "scale-info", "sp-application-crypto", "sp-consensus-babe", - "sp-consensus-vrf", + "sp-core", "sp-io", "sp-runtime", "sp-session", @@ -5553,7 +5707,7 @@ dependencies = [ [[package]] name = "pallet-bags-list" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -5573,7 +5727,7 @@ dependencies = [ [[package]] name = "pallet-balances" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5588,7 +5742,7 @@ dependencies = [ [[package]] name = "pallet-beefy" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -5597,7 +5751,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-beefy", + "sp-consensus-beefy", "sp-runtime", "sp-session", "sp-staking", @@ -5607,7 +5761,7 @@ dependencies = [ [[package]] name = "pallet-beefy-mmr" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", "binary-merkle-tree", @@ -5621,7 +5775,7 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-beefy", + "sp-consensus-beefy", "sp-core", "sp-io", "sp-runtime", @@ -5631,7 +5785,7 @@ dependencies = [ [[package]] name = "pallet-bounties" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5649,7 +5803,7 @@ dependencies = [ [[package]] name = "pallet-child-bounties" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5668,7 +5822,7 @@ dependencies = [ [[package]] name = "pallet-collator-selection" version = "3.0.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "frame-benchmarking", "frame-support", @@ -5687,7 +5841,7 @@ dependencies = [ [[package]] name = "pallet-collective" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5704,7 +5858,7 @@ dependencies = [ [[package]] name = "pallet-conviction-voting" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "assert_matches", "frame-benchmarking", @@ -5721,7 +5875,7 @@ dependencies = [ [[package]] name = "pallet-democracy" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5739,7 +5893,7 @@ dependencies = [ [[package]] name = "pallet-election-provider-multi-phase" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -5762,7 +5916,7 @@ dependencies = [ [[package]] name = "pallet-election-provider-support-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -5775,7 +5929,7 @@ dependencies = [ [[package]] name = "pallet-elections-phragmen" version = "5.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5793,7 +5947,7 @@ dependencies = [ [[package]] name = "pallet-fast-unstake" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -5830,7 +5984,7 @@ dependencies = [ [[package]] name = "pallet-grandpa" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5841,8 +5995,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-application-crypto", + "sp-consensus-grandpa", "sp-core", - "sp-finality-grandpa", "sp-io", "sp-runtime", "sp-session", @@ -5853,7 +6007,7 @@ dependencies = [ [[package]] name = "pallet-identity" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "enumflags2", "frame-benchmarking", @@ -5869,7 +6023,7 @@ dependencies = [ [[package]] name = "pallet-im-online" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5889,7 +6043,7 @@ dependencies = [ [[package]] name = "pallet-indices" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5906,7 +6060,7 @@ dependencies = [ [[package]] name = "pallet-insecure-randomness-collective-flip" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -5920,7 +6074,7 @@ dependencies = [ [[package]] name = "pallet-membership" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5937,7 +6091,7 @@ dependencies = [ [[package]] name = "pallet-mmr" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5954,7 +6108,7 @@ dependencies = [ [[package]] name = "pallet-multisig" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5970,7 +6124,7 @@ dependencies = [ [[package]] name = "pallet-nis" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5986,7 +6140,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools" version = "1.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -6003,7 +6157,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-benchmarking" version = "1.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -6023,7 +6177,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-runtime-api" version = "1.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "pallet-nomination-pools", "parity-scale-codec", @@ -6034,7 +6188,7 @@ dependencies = [ [[package]] name = "pallet-offences" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -6051,7 +6205,7 @@ dependencies = [ [[package]] name = "pallet-offences-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -6075,7 +6229,7 @@ dependencies = [ [[package]] name = "pallet-parachain-staking" version = "3.0.0" -source = "git+https://gitlab.com/Omegabit/stake-patch#28a788327c7dbf408060cbe0b1f0109bd8533260" +source = "git+https://gitlab.com/Omegabit/stake-patch?branch=0.9.42#a9b481bf9f658f45db37fa9c8e26f31d41550518" dependencies = [ "frame-benchmarking", "frame-support", @@ -6095,7 +6249,7 @@ dependencies = [ [[package]] name = "pallet-preimage" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6112,7 +6266,7 @@ dependencies = [ [[package]] name = "pallet-proxy" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6127,7 +6281,7 @@ dependencies = [ [[package]] name = "pallet-ranked-collective" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6145,7 +6299,7 @@ dependencies = [ [[package]] name = "pallet-recovery" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6160,7 +6314,7 @@ dependencies = [ [[package]] name = "pallet-referenda" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "assert_matches", "frame-benchmarking", @@ -6201,7 +6355,7 @@ dependencies = [ [[package]] name = "pallet-scheduler" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6218,7 +6372,7 @@ dependencies = [ [[package]] name = "pallet-session" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -6239,7 +6393,7 @@ dependencies = [ [[package]] name = "pallet-session-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6255,7 +6409,7 @@ dependencies = [ [[package]] name = "pallet-society" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -6269,7 +6423,7 @@ dependencies = [ [[package]] name = "pallet-staking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -6292,18 +6446,18 @@ dependencies = [ [[package]] name = "pallet-staking-reward-curve" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.25", ] [[package]] name = "pallet-staking-reward-fn" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "log", "sp-arithmetic", @@ -6312,7 +6466,7 @@ dependencies = [ [[package]] name = "pallet-staking-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "sp-api", @@ -6321,7 +6475,7 @@ dependencies = [ [[package]] name = "pallet-state-trie-migration" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6338,7 +6492,7 @@ dependencies = [ [[package]] name = "pallet-sudo" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -6352,7 +6506,7 @@ dependencies = [ [[package]] name = "pallet-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6370,7 +6524,7 @@ dependencies = [ [[package]] name = "pallet-tips" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6389,7 +6543,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -6405,7 +6559,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "jsonrpsee", "pallet-transaction-payment-rpc-runtime-api", @@ -6421,7 +6575,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "pallet-transaction-payment", "parity-scale-codec", @@ -6433,7 +6587,7 @@ dependencies = [ [[package]] name = "pallet-treasury" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6450,7 +6604,7 @@ dependencies = [ [[package]] name = "pallet-uniques" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6465,7 +6619,7 @@ dependencies = [ [[package]] name = "pallet-utility" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6481,7 +6635,7 @@ dependencies = [ [[package]] name = "pallet-vesting" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6496,7 +6650,7 @@ dependencies = [ [[package]] name = "pallet-whitelist" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6510,8 +6664,8 @@ dependencies = [ [[package]] name = "pallet-xcm" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bounded-collections", "frame-benchmarking", @@ -6531,8 +6685,8 @@ dependencies = [ [[package]] name = "pallet-xcm-benchmarks" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "frame-benchmarking", "frame-support", @@ -6551,7 +6705,7 @@ dependencies = [ [[package]] name = "parachain-info" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -6563,7 +6717,7 @@ dependencies = [ [[package]] name = "parachains-common" version = "1.0.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ "cumulus-primitives-utility", "frame-support", @@ -6768,7 +6922,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal", + "hex-literal 0.3.4", "log", "pallet-asset-tx-payment", "pallet-assets", @@ -6911,8 +7065,18 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" dependencies = [ - "der", - "spki", + "der 0.6.1", + "spki 0.6.0", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der 0.7.7", + "spki 0.7.2", ] [[package]] @@ -6953,7 +7117,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal", + "hex-literal 0.3.4", "log", "pallet-aura", "pallet-authorship", @@ -7010,7 +7174,7 @@ dependencies = [ "cumulus-relay-chain-minimal-node", "frame-benchmarking", "frame-benchmarking-cli", - "hex-literal", + "hex-literal 0.3.4", "jsonrpsee", "log", "pallet-transaction-payment-rpc", @@ -7028,6 +7192,7 @@ dependencies = [ "sc-executor", "sc-network", "sc-network-common", + "sc-network-sync", "sc-rpc", "sc-rpc-api", "sc-service", @@ -7077,7 +7242,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal", + "hex-literal 0.3.4", "log", "pallet-asset-tx-payment", "pallet-assets", @@ -7148,8 +7313,8 @@ dependencies = [ "sc-client-api", "sc-consensus", "sc-consensus-aura", + "sc-consensus-grandpa", "sc-executor", - "sc-finality-grandpa", "sc-keystore", "sc-rpc", "sc-rpc-api", @@ -7163,8 +7328,8 @@ dependencies = [ "sp-blockchain", "sp-consensus", "sp-consensus-aura", + "sp-consensus-grandpa", "sp-core", - "sp-finality-grandpa", "sp-inherents", "sp-keyring", "sp-runtime", @@ -7185,7 +7350,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal", + "hex-literal 0.3.4", "pallet-assets", "pallet-aura", "pallet-authorship", @@ -7207,9 +7372,11 @@ dependencies = [ "pallet-vesting", "parity-scale-codec", "scale-info", + "shared-configuration", "sp-api", "sp-block-builder", "sp-consensus-aura", + "sp-consensus-grandpa", "sp-core", "sp-inherents", "sp-offchain", @@ -7223,10 +7390,11 @@ dependencies = [ [[package]] name = "polkadot-approval-distribution" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "futures", + "polkadot-node-jaeger", "polkadot-node-metrics", "polkadot-node-network-protocol", "polkadot-node-primitives", @@ -7238,8 +7406,8 @@ dependencies = [ [[package]] name = "polkadot-availability-bitfield-distribution" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "futures", "polkadot-node-network-protocol", @@ -7252,8 +7420,8 @@ dependencies = [ [[package]] name = "polkadot-availability-distribution" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "derive_more", "fatality", @@ -7275,8 +7443,8 @@ dependencies = [ [[package]] name = "polkadot-availability-recovery" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "fatality", "futures", @@ -7296,15 +7464,15 @@ dependencies = [ [[package]] name = "polkadot-cli" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "clap", "frame-benchmarking-cli", "futures", "log", "polkadot-client", - "polkadot-node-core-pvf", + "polkadot-node-core-pvf-worker", "polkadot-node-metrics", "polkadot-performance-test", "polkadot-service", @@ -7317,6 +7485,7 @@ dependencies = [ "sp-core", "sp-io", "sp-keyring", + "sp-maybe-compressed-blob", "substrate-build-script-utils", "thiserror", "try-runtime-cli", @@ -7324,8 +7493,8 @@ dependencies = [ [[package]] name = "polkadot-client" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "async-trait", "frame-benchmarking", @@ -7346,13 +7515,13 @@ dependencies = [ "sc-service", "sp-api", "sp-authority-discovery", - "sp-beefy", "sp-block-builder", "sp-blockchain", "sp-consensus", "sp-consensus-babe", + "sp-consensus-beefy", + "sp-consensus-grandpa", "sp-core", - "sp-finality-grandpa", "sp-inherents", "sp-keyring", "sp-mmr-primitives", @@ -7366,8 +7535,8 @@ dependencies = [ [[package]] name = "polkadot-collator-protocol" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "always-assert", "bitvec", @@ -7388,8 +7557,8 @@ dependencies = [ [[package]] name = "polkadot-core-primitives" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "parity-scale-codec", "scale-info", @@ -7400,8 +7569,8 @@ dependencies = [ [[package]] name = "polkadot-dispute-distribution" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "derive_more", "fatality", @@ -7425,8 +7594,8 @@ dependencies = [ [[package]] name = "polkadot-erasure-coding" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "parity-scale-codec", "polkadot-node-primitives", @@ -7439,8 +7608,8 @@ dependencies = [ [[package]] name = "polkadot-gossip-support" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "futures", "futures-timer", @@ -7459,8 +7628,8 @@ dependencies = [ [[package]] name = "polkadot-network-bridge" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "always-assert", "async-trait", @@ -7475,7 +7644,6 @@ dependencies = [ "polkadot-overseer", "polkadot-primitives", "sc-network", - "sc-network-common", "sp-consensus", "thiserror", "tracing-gum", @@ -7483,8 +7651,8 @@ dependencies = [ [[package]] name = "polkadot-node-collation-generation" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "futures", "parity-scale-codec", @@ -7501,8 +7669,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-approval-voting" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitvec", "derive_more", @@ -7530,8 +7698,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-av-store" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitvec", "futures", @@ -7551,8 +7719,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-backing" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitvec", "fatality", @@ -7570,8 +7738,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-bitfield-signing" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "futures", "polkadot-node-subsystem", @@ -7585,8 +7753,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-candidate-validation" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "async-trait", "futures", @@ -7605,8 +7773,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-api" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "futures", "polkadot-node-metrics", @@ -7620,8 +7788,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-selection" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "futures", "futures-timer", @@ -7637,8 +7805,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-dispute-coordinator" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "fatality", "futures", @@ -7656,8 +7824,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-parachains-inherent" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "async-trait", "futures", @@ -7673,8 +7841,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-provisioner" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitvec", "fatality", @@ -7691,12 +7859,10 @@ dependencies = [ [[package]] name = "polkadot-node-core-pvf" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "always-assert", - "assert_matches", - "cpu-time", "futures", "futures-timer", "libc", @@ -7708,27 +7874,20 @@ dependencies = [ "polkadot-parachain", "polkadot-primitives", "rand 0.8.5", - "rayon", - "sc-executor", - "sc-executor-common", - "sc-executor-wasmtime", "slotmap", "sp-core", - "sp-externalities", - "sp-io", "sp-maybe-compressed-blob", "sp-tracing", "sp-wasm-interface", - "tempfile", - "tikv-jemalloc-ctl", + "substrate-build-script-utils", "tokio", "tracing-gum", ] [[package]] name = "polkadot-node-core-pvf-checker" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "futures", "polkadot-node-primitives", @@ -7741,10 +7900,39 @@ dependencies = [ "tracing-gum", ] +[[package]] +name = "polkadot-node-core-pvf-worker" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +dependencies = [ + "assert_matches", + "cpu-time", + "futures", + "libc", + "parity-scale-codec", + "polkadot-node-core-pvf", + "polkadot-parachain", + "polkadot-primitives", + "rayon", + "sc-executor", + "sc-executor-common", + "sc-executor-wasmtime", + "sp-core", + "sp-externalities", + "sp-io", + "sp-maybe-compressed-blob", + "sp-tracing", + "substrate-build-script-utils", + "tempfile", + "tikv-jemalloc-ctl", + "tokio", + "tracing-gum", +] + [[package]] name = "polkadot-node-core-runtime-api" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "futures", "lru 0.9.0", @@ -7758,8 +7946,8 @@ dependencies = [ [[package]] name = "polkadot-node-jaeger" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "lazy_static", "log", @@ -7776,8 +7964,8 @@ dependencies = [ [[package]] name = "polkadot-node-metrics" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bs58", "futures", @@ -7795,8 +7983,8 @@ dependencies = [ [[package]] name = "polkadot-node-network-protocol" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "async-trait", "derive_more", @@ -7810,7 +7998,6 @@ dependencies = [ "rand 0.8.5", "sc-authority-discovery", "sc-network", - "sc-network-common", "strum", "thiserror", "tracing-gum", @@ -7818,8 +8005,8 @@ dependencies = [ [[package]] name = "polkadot-node-primitives" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bounded-vec", "futures", @@ -7830,19 +8017,18 @@ dependencies = [ "serde", "sp-application-crypto", "sp-consensus-babe", - "sp-consensus-vrf", "sp-core", "sp-keystore", "sp-maybe-compressed-blob", "sp-runtime", "thiserror", - "zstd", + "zstd 0.11.2+zstd.1.5.2", ] [[package]] name = "polkadot-node-subsystem" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "polkadot-node-jaeger", "polkadot-node-subsystem-types", @@ -7851,8 +8037,8 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-types" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "async-trait", "derive_more", @@ -7874,8 +8060,8 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-util" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "async-trait", "derive_more", @@ -7907,8 +8093,8 @@ dependencies = [ [[package]] name = "polkadot-overseer" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "async-trait", "futures", @@ -7930,8 +8116,8 @@ dependencies = [ [[package]] name = "polkadot-parachain" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bounded-collections", "derive_more", @@ -7947,27 +8133,29 @@ dependencies = [ [[package]] name = "polkadot-performance-test" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "env_logger 0.9.3", "kusama-runtime", "log", "polkadot-erasure-coding", - "polkadot-node-core-pvf", + "polkadot-node-core-pvf-worker", "polkadot-node-primitives", "polkadot-primitives", "quote", + "sc-executor-common", + "sp-maybe-compressed-blob", "thiserror", ] [[package]] name = "polkadot-primitives" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitvec", - "hex-literal", + "hex-literal 0.4.1", "parity-scale-codec", "polkadot-core-primitives", "polkadot-parachain", @@ -7989,11 +8177,9 @@ dependencies = [ [[package]] name = "polkadot-rpc" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ - "beefy-gadget", - "beefy-gadget-rpc", "jsonrpsee", "mmr-rpc", "pallet-transaction-payment-rpc", @@ -8002,9 +8188,11 @@ dependencies = [ "sc-client-api", "sc-consensus-babe", "sc-consensus-babe-rpc", + "sc-consensus-beefy", + "sc-consensus-beefy-rpc", "sc-consensus-epochs", - "sc-finality-grandpa", - "sc-finality-grandpa-rpc", + "sc-consensus-grandpa", + "sc-consensus-grandpa-rpc", "sc-rpc", "sc-sync-state-rpc", "sc-transaction-pool-api", @@ -8021,8 +8209,8 @@ dependencies = [ [[package]] name = "polkadot-runtime" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitvec", "frame-benchmarking", @@ -8033,7 +8221,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal", + "hex-literal 0.4.1", "log", "pallet-authority-discovery", "pallet-authorship", @@ -8043,6 +8231,7 @@ dependencies = [ "pallet-bounties", "pallet-child-bounties", "pallet-collective", + "pallet-conviction-voting", "pallet-democracy", "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", @@ -8061,6 +8250,7 @@ dependencies = [ "pallet-offences-benchmarking", "pallet-preimage", "pallet-proxy", + "pallet-referenda", "pallet-scheduler", "pallet-session", "pallet-session-benchmarking", @@ -8074,6 +8264,7 @@ dependencies = [ "pallet-treasury", "pallet-utility", "pallet-vesting", + "pallet-whitelist", "pallet-xcm", "parity-scale-codec", "polkadot-primitives", @@ -8086,10 +8277,11 @@ dependencies = [ "serde_derive", "smallvec", "sp-api", + "sp-arithmetic", "sp-authority-discovery", - "sp-beefy", "sp-block-builder", "sp-consensus-babe", + "sp-consensus-beefy", "sp-core", "sp-inherents", "sp-io", @@ -8111,8 +8303,8 @@ dependencies = [ [[package]] name = "polkadot-runtime-common" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitvec", "frame-benchmarking", @@ -8125,7 +8317,6 @@ dependencies = [ "pallet-authorship", "pallet-babe", "pallet-balances", - "pallet-beefy-mmr", "pallet-election-provider-multi-phase", "pallet-fast-unstake", "pallet-session", @@ -8144,7 +8335,6 @@ dependencies = [ "serde_derive", "slot-range-helper", "sp-api", - "sp-beefy", "sp-core", "sp-inherents", "sp-io", @@ -8159,8 +8349,8 @@ dependencies = [ [[package]] name = "polkadot-runtime-constants" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "frame-support", "polkadot-primitives", @@ -8173,8 +8363,8 @@ dependencies = [ [[package]] name = "polkadot-runtime-metrics" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bs58", "parity-scale-codec", @@ -8185,8 +8375,8 @@ dependencies = [ [[package]] name = "polkadot-runtime-parachains" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitflags 1.3.2", "bitvec", @@ -8229,16 +8419,15 @@ dependencies = [ [[package]] name = "polkadot-service" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "async-trait", - "beefy-gadget", "frame-benchmarking-cli", "frame-support", "frame-system-rpc-runtime-api", "futures", - "hex-literal", + "hex-literal 0.4.1", "kusama-runtime", "kvdb", "kvdb-rocksdb", @@ -8294,12 +8483,14 @@ dependencies = [ "sc-client-db", "sc-consensus", "sc-consensus-babe", + "sc-consensus-beefy", + "sc-consensus-grandpa", "sc-consensus-slots", "sc-executor", - "sc-finality-grandpa", "sc-keystore", "sc-network", "sc-network-common", + "sc-network-sync", "sc-offchain", "sc-service", "sc-sync-state-rpc", @@ -8310,13 +8501,13 @@ dependencies = [ "serde_json", "sp-api", "sp-authority-discovery", - "sp-beefy", "sp-block-builder", "sp-blockchain", "sp-consensus", "sp-consensus-babe", + "sp-consensus-beefy", + "sp-consensus-grandpa", "sp-core", - "sp-finality-grandpa", "sp-inherents", "sp-io", "sp-keystore", @@ -8337,8 +8528,8 @@ dependencies = [ [[package]] name = "polkadot-statement-distribution" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "arrayvec 0.5.2", "fatality", @@ -8358,8 +8549,8 @@ dependencies = [ [[package]] name = "polkadot-statement-table" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "parity-scale-codec", "polkadot-primitives", @@ -8417,6 +8608,12 @@ dependencies = [ "universal-hash 0.5.1", ] +[[package]] +name = "portable-atomic" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d220334a184db82b31b83f5ff093e3315280fb2b6bbc032022b2304a509aab7a" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -8526,6 +8723,17 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-warning" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e99670bafb56b9a106419397343bdbc8b8742c3cc449fec6345f86173f47cd4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.25", +] + [[package]] name = "proc-macro2" version = "1.0.64" @@ -8986,11 +9194,21 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" dependencies = [ - "crypto-bigint", + "crypto-bigint 0.4.9", "hmac 0.12.1", "zeroize", ] +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac 0.12.1", + "subtle", +] + [[package]] name = "ring" version = "0.16.20" @@ -9008,9 +9226,9 @@ dependencies = [ [[package]] name = "rocksdb" -version = "0.19.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e9562ea1d70c0cc63a34a22d977753b50cca91cc6b6527750463bd5dd8697bc" +checksum = "015439787fce1e75d55f279078d33ff14b4af5d93d995e8838ee4631301c8a99" dependencies = [ "libc", "librocksdb-sys", @@ -9018,8 +9236,8 @@ dependencies = [ [[package]] name = "rococo-runtime" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "binary-merkle-tree", "frame-benchmarking", @@ -9029,7 +9247,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal", + "hex-literal 0.4.1", "log", "pallet-authority-discovery", "pallet-authorship", @@ -9081,9 +9299,9 @@ dependencies = [ "smallvec", "sp-api", "sp-authority-discovery", - "sp-beefy", "sp-block-builder", "sp-consensus-babe", + "sp-consensus-beefy", "sp-core", "sp-inherents", "sp-io", @@ -9104,8 +9322,8 @@ dependencies = [ [[package]] name = "rococo-runtime-constants" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "frame-support", "polkadot-primitives", @@ -9148,7 +9366,7 @@ dependencies = [ "log", "netlink-packet-route", "netlink-proto", - "nix 0.24.3", + "nix", "thiserror", "tokio", ] @@ -9362,7 +9580,7 @@ dependencies = [ [[package]] name = "sc-allocator" version = "4.1.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "log", "sp-core", @@ -9373,7 +9591,7 @@ dependencies = [ [[package]] name = "sc-authority-discovery" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "futures", @@ -9386,6 +9604,7 @@ dependencies = [ "prost-build", "rand 0.8.5", "sc-client-api", + "sc-network", "sc-network-common", "sp-api", "sp-authority-discovery", @@ -9400,7 +9619,7 @@ dependencies = [ [[package]] name = "sc-basic-authorship" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "futures", "futures-timer", @@ -9423,7 +9642,7 @@ dependencies = [ [[package]] name = "sc-block-builder" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "sc-client-api", @@ -9433,39 +9652,42 @@ dependencies = [ "sp-core", "sp-inherents", "sp-runtime", - "sp-state-machine", ] [[package]] name = "sc-chain-spec" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "memmap2", "sc-chain-spec-derive", - "sc-network-common", + "sc-client-api", + "sc-executor", + "sc-network", "sc-telemetry", "serde", "serde_json", + "sp-blockchain", "sp-core", "sp-runtime", + "sp-state-machine", ] [[package]] name = "sc-chain-spec-derive" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.25", ] [[package]] name = "sc-cli" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", "chrono", @@ -9505,7 +9727,7 @@ dependencies = [ [[package]] name = "sc-client-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "fnv", "futures", @@ -9531,7 +9753,7 @@ dependencies = [ [[package]] name = "sc-client-db" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "hash-db", "kvdb", @@ -9557,7 +9779,7 @@ dependencies = [ [[package]] name = "sc-consensus" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "futures", @@ -9582,7 +9804,7 @@ dependencies = [ [[package]] name = "sc-consensus-aura" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "futures", @@ -9611,13 +9833,12 @@ dependencies = [ [[package]] name = "sc-consensus-babe" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "fork-tree", "futures", "log", - "merlin", "num-bigint", "num-rational", "num-traits", @@ -9630,7 +9851,6 @@ dependencies = [ "sc-keystore", "sc-telemetry", "scale-info", - "schnorrkel", "sp-api", "sp-application-crypto", "sp-block-builder", @@ -9638,7 +9858,6 @@ dependencies = [ "sp-consensus", "sp-consensus-babe", "sp-consensus-slots", - "sp-consensus-vrf", "sp-core", "sp-inherents", "sp-keystore", @@ -9650,7 +9869,7 @@ dependencies = [ [[package]] name = "sc-consensus-babe-rpc" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "futures", "jsonrpsee", @@ -9669,10 +9888,64 @@ dependencies = [ "thiserror", ] +[[package]] +name = "sc-consensus-beefy" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "array-bytes 4.2.0", + "async-trait", + "fnv", + "futures", + "log", + "parity-scale-codec", + "parking_lot 0.12.1", + "sc-client-api", + "sc-consensus", + "sc-keystore", + "sc-network", + "sc-network-common", + "sc-network-gossip", + "sc-network-sync", + "sc-utils", + "sp-api", + "sp-application-crypto", + "sp-arithmetic", + "sp-blockchain", + "sp-consensus", + "sp-consensus-beefy", + "sp-core", + "sp-keystore", + "sp-mmr-primitives", + "sp-runtime", + "substrate-prometheus-endpoint", + "thiserror", + "wasm-timer", +] + +[[package]] +name = "sc-consensus-beefy-rpc" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "futures", + "jsonrpsee", + "log", + "parity-scale-codec", + "parking_lot 0.12.1", + "sc-consensus-beefy", + "sc-rpc", + "serde", + "sp-consensus-beefy", + "sp-core", + "sp-runtime", + "thiserror", +] + [[package]] name = "sc-consensus-epochs" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "fork-tree", "parity-scale-codec", @@ -9682,10 +9955,70 @@ dependencies = [ "sp-runtime", ] +[[package]] +name = "sc-consensus-grandpa" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "ahash 0.8.3", + "array-bytes 4.2.0", + "async-trait", + "dyn-clone", + "finality-grandpa", + "fork-tree", + "futures", + "futures-timer", + "log", + "parity-scale-codec", + "parking_lot 0.12.1", + "rand 0.8.5", + "sc-block-builder", + "sc-chain-spec", + "sc-client-api", + "sc-consensus", + "sc-network", + "sc-network-common", + "sc-network-gossip", + "sc-telemetry", + "sc-utils", + "serde_json", + "sp-api", + "sp-application-crypto", + "sp-arithmetic", + "sp-blockchain", + "sp-consensus", + "sp-consensus-grandpa", + "sp-core", + "sp-keystore", + "sp-runtime", + "substrate-prometheus-endpoint", + "thiserror", +] + +[[package]] +name = "sc-consensus-grandpa-rpc" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "finality-grandpa", + "futures", + "jsonrpsee", + "log", + "parity-scale-codec", + "sc-client-api", + "sc-consensus-grandpa", + "sc-rpc", + "serde", + "sp-blockchain", + "sp-core", + "sp-runtime", + "thiserror", +] + [[package]] name = "sc-consensus-slots" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "futures", @@ -9708,7 +10041,7 @@ dependencies = [ [[package]] name = "sc-executor" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "lru 0.8.1", "parity-scale-codec", @@ -9732,7 +10065,7 @@ dependencies = [ [[package]] name = "sc-executor-common" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "sc-allocator", "sp-maybe-compressed-blob", @@ -9745,7 +10078,7 @@ dependencies = [ [[package]] name = "sc-executor-wasmi" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "log", "sc-allocator", @@ -9758,7 +10091,7 @@ dependencies = [ [[package]] name = "sc-executor-wasmtime" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "anyhow", "cfg-if", @@ -9773,76 +10106,17 @@ dependencies = [ "wasmtime", ] -[[package]] -name = "sc-finality-grandpa" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" -dependencies = [ - "ahash 0.8.3", - "array-bytes 4.2.0", - "async-trait", - "dyn-clone", - "finality-grandpa", - "fork-tree", - "futures", - "futures-timer", - "log", - "parity-scale-codec", - "parking_lot 0.12.1", - "rand 0.8.5", - "sc-block-builder", - "sc-chain-spec", - "sc-client-api", - "sc-consensus", - "sc-network", - "sc-network-common", - "sc-network-gossip", - "sc-telemetry", - "sc-utils", - "serde_json", - "sp-api", - "sp-application-crypto", - "sp-arithmetic", - "sp-blockchain", - "sp-consensus", - "sp-core", - "sp-finality-grandpa", - "sp-keystore", - "sp-runtime", - "substrate-prometheus-endpoint", - "thiserror", -] - -[[package]] -name = "sc-finality-grandpa-rpc" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" -dependencies = [ - "finality-grandpa", - "futures", - "jsonrpsee", - "log", - "parity-scale-codec", - "sc-client-api", - "sc-finality-grandpa", - "sc-rpc", - "serde", - "sp-blockchain", - "sp-core", - "sp-runtime", - "thiserror", -] - [[package]] name = "sc-informant" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "ansi_term", "futures", "futures-timer", "log", "sc-client-api", + "sc-network", "sc-network-common", "sp-blockchain", "sp-runtime", @@ -9851,7 +10125,7 @@ dependencies = [ [[package]] name = "sc-keystore" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", "async-trait", @@ -9866,12 +10140,12 @@ dependencies = [ [[package]] name = "sc-network" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", + "async-channel", "async-trait", "asynchronous-codec", - "backtrace", "bytes", "either", "fnv", @@ -9879,6 +10153,7 @@ dependencies = [ "futures-timer", "ip_network", "libp2p", + "linked_hash_set", "log", "lru 0.8.1", "mockall", @@ -9895,6 +10170,7 @@ dependencies = [ "serde", "serde_json", "smallvec", + "snow", "sp-arithmetic", "sp-blockchain", "sp-consensus", @@ -9909,7 +10185,7 @@ dependencies = [ [[package]] name = "sc-network-bitswap" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "cid", "futures", @@ -9918,6 +10194,7 @@ dependencies = [ "prost", "prost-build", "sc-client-api", + "sc-network", "sc-network-common", "sp-blockchain", "sp-runtime", @@ -9928,33 +10205,35 @@ dependencies = [ [[package]] name = "sc-network-common" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ + "array-bytes 4.2.0", "async-trait", "bitflags 1.3.2", "bytes", "futures", "futures-timer", "libp2p", - "linked_hash_set", "parity-scale-codec", "prost-build", "sc-consensus", "sc-peerset", + "sc-utils", "serde", "smallvec", "sp-blockchain", "sp-consensus", - "sp-finality-grandpa", + "sp-consensus-grandpa", "sp-runtime", "substrate-prometheus-endpoint", "thiserror", + "zeroize", ] [[package]] name = "sc-network-gossip" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "ahash 0.8.3", "futures", @@ -9962,6 +10241,7 @@ dependencies = [ "libp2p", "log", "lru 0.8.1", + "sc-network", "sc-network-common", "sc-peerset", "sp-runtime", @@ -9972,7 +10252,7 @@ dependencies = [ [[package]] name = "sc-network-light" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", "futures", @@ -9982,6 +10262,7 @@ dependencies = [ "prost", "prost-build", "sc-client-api", + "sc-network", "sc-network-common", "sc-peerset", "sp-blockchain", @@ -9993,12 +10274,13 @@ dependencies = [ [[package]] name = "sc-network-sync" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", "async-trait", "fork-tree", "futures", + "futures-timer", "libp2p", "log", "lru 0.8.1", @@ -10008,6 +10290,7 @@ dependencies = [ "prost-build", "sc-client-api", "sc-consensus", + "sc-network", "sc-network-common", "sc-peerset", "sc-utils", @@ -10015,8 +10298,8 @@ dependencies = [ "sp-arithmetic", "sp-blockchain", "sp-consensus", + "sp-consensus-grandpa", "sp-core", - "sp-finality-grandpa", "sp-runtime", "substrate-prometheus-endpoint", "thiserror", @@ -10025,7 +10308,7 @@ dependencies = [ [[package]] name = "sc-network-transactions" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", "futures", @@ -10033,6 +10316,7 @@ dependencies = [ "log", "parity-scale-codec", "pin-project", + "sc-network", "sc-network-common", "sc-peerset", "sc-utils", @@ -10044,7 +10328,7 @@ dependencies = [ [[package]] name = "sc-offchain" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", "bytes", @@ -10060,6 +10344,7 @@ dependencies = [ "parking_lot 0.12.1", "rand 0.8.5", "sc-client-api", + "sc-network", "sc-network-common", "sc-peerset", "sc-utils", @@ -10074,7 +10359,7 @@ dependencies = [ [[package]] name = "sc-peerset" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "futures", "libp2p", @@ -10087,7 +10372,7 @@ dependencies = [ [[package]] name = "sc-proposer-metrics" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "log", "substrate-prometheus-endpoint", @@ -10096,7 +10381,7 @@ dependencies = [ [[package]] name = "sc-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "futures", "jsonrpsee", @@ -10126,7 +10411,7 @@ dependencies = [ [[package]] name = "sc-rpc-api" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -10145,7 +10430,7 @@ dependencies = [ [[package]] name = "sc-rpc-server" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "http", "jsonrpsee", @@ -10160,7 +10445,7 @@ dependencies = [ [[package]] name = "sc-rpc-spec-v2" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", "futures", @@ -10186,7 +10471,7 @@ dependencies = [ [[package]] name = "sc-service" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "directories", @@ -10252,7 +10537,7 @@ dependencies = [ [[package]] name = "sc-state-db" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "log", "parity-scale-codec", @@ -10263,12 +10548,12 @@ dependencies = [ [[package]] name = "sc-storage-monitor" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "clap", + "fs4", "futures", "log", - "nix 0.26.2", "sc-client-db", "sc-utils", "sp-core", @@ -10279,7 +10564,7 @@ dependencies = [ [[package]] name = "sc-sync-state-rpc" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -10287,7 +10572,7 @@ dependencies = [ "sc-client-api", "sc-consensus-babe", "sc-consensus-epochs", - "sc-finality-grandpa", + "sc-consensus-grandpa", "serde", "serde_json", "sp-blockchain", @@ -10298,7 +10583,7 @@ dependencies = [ [[package]] name = "sc-sysinfo" version = "6.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "futures", "libc", @@ -10317,7 +10602,7 @@ dependencies = [ [[package]] name = "sc-telemetry" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "chrono", "futures", @@ -10336,7 +10621,7 @@ dependencies = [ [[package]] name = "sc-tracing" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "ansi_term", "atty", @@ -10367,18 +10652,18 @@ dependencies = [ [[package]] name = "sc-tracing-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.25", ] [[package]] name = "sc-transaction-pool" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "futures", @@ -10405,7 +10690,7 @@ dependencies = [ [[package]] name = "sc-transaction-pool-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "futures", @@ -10419,15 +10704,16 @@ dependencies = [ [[package]] name = "sc-utils" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "backtrace", + "async-channel", "futures", "futures-timer", "lazy_static", "log", "parking_lot 0.12.1", "prometheus", + "sp-arithmetic", ] [[package]] @@ -10544,10 +10830,24 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" dependencies = [ - "base16ct", - "der", + "base16ct 0.1.1", + "der 0.6.1", "generic-array 0.14.7", - "pkcs8", + "pkcs8 0.9.0", + "subtle", + "zeroize", +] + +[[package]] +name = "sec1" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e" +dependencies = [ + "base16ct 0.2.0", + "der 0.7.7", + "generic-array 0.14.7", + "pkcs8 0.10.2", "subtle", "zeroize", ] @@ -10666,6 +10966,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" +dependencies = [ + "serde", +] + [[package]] name = "sha-1" version = "0.9.8" @@ -10781,6 +11090,16 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "signature" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + [[package]] name = "simba" version = "0.8.1" @@ -10817,8 +11136,8 @@ checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" [[package]] name = "slot-range-helper" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "enumn", "parity-scale-codec", @@ -10905,13 +11224,15 @@ dependencies = [ [[package]] name = "sp-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "hash-db", "log", "parity-scale-codec", + "scale-info", "sp-api-proc-macro", "sp-core", + "sp-metadata-ir", "sp-runtime", "sp-state-machine", "sp-std", @@ -10923,19 +11244,21 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ + "Inflector", "blake2", + "expander 1.0.0", "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.25", ] [[package]] name = "sp-application-crypto" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", @@ -10948,7 +11271,7 @@ dependencies = [ [[package]] name = "sp-arithmetic" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "integer-sqrt", "num-traits", @@ -10962,7 +11285,7 @@ dependencies = [ [[package]] name = "sp-authority-discovery" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", @@ -10972,29 +11295,10 @@ dependencies = [ "sp-std", ] -[[package]] -name = "sp-beefy" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" -dependencies = [ - "lazy_static", - "parity-scale-codec", - "scale-info", - "serde", - "sp-api", - "sp-application-crypto", - "sp-core", - "sp-io", - "sp-mmr-primitives", - "sp-runtime", - "sp-std", - "strum", -] - [[package]] name = "sp-block-builder" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "sp-api", @@ -11006,7 +11310,7 @@ dependencies = [ [[package]] name = "sp-blockchain" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "futures", "log", @@ -11024,25 +11328,22 @@ dependencies = [ [[package]] name = "sp-consensus" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "futures", "log", - "parity-scale-codec", "sp-core", "sp-inherents", "sp-runtime", "sp-state-machine", - "sp-std", - "sp-version", "thiserror", ] [[package]] name = "sp-consensus-aura" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "parity-scale-codec", @@ -11060,10 +11361,9 @@ dependencies = [ [[package]] name = "sp-consensus-babe" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", - "merlin", "parity-scale-codec", "scale-info", "serde", @@ -11071,7 +11371,6 @@ dependencies = [ "sp-application-crypto", "sp-consensus", "sp-consensus-slots", - "sp-consensus-vrf", "sp-core", "sp-inherents", "sp-keystore", @@ -11081,40 +11380,64 @@ dependencies = [ ] [[package]] -name = "sp-consensus-slots" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +name = "sp-consensus-beefy" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ + "lazy_static", "parity-scale-codec", "scale-info", "serde", + "sp-api", + "sp-application-crypto", + "sp-core", + "sp-io", + "sp-mmr-primitives", + "sp-runtime", "sp-std", - "sp-timestamp", + "strum", ] [[package]] -name = "sp-consensus-vrf" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +name = "sp-consensus-grandpa" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ + "finality-grandpa", + "log", "parity-scale-codec", "scale-info", - "schnorrkel", + "serde", + "sp-api", + "sp-application-crypto", "sp-core", + "sp-keystore", "sp-runtime", "sp-std", ] +[[package]] +name = "sp-consensus-slots" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", + "sp-std", + "sp-timestamp", +] + [[package]] name = "sp-core" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", - "base58", "bitflags 1.3.2", "blake2", "bounded-collections", + "bs58", "dyn-clonable", "ed25519-zebra", "futures", @@ -11127,6 +11450,7 @@ dependencies = [ "merlin", "parity-scale-codec", "parking_lot 0.12.1", + "paste", "primitive-types", "rand 0.8.5", "regex", @@ -11151,9 +11475,9 @@ dependencies = [ [[package]] name = "sp-core-hashing" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "blake2", + "blake2b_simd", "byteorder", "digest 0.10.7", "sha2 0.10.7", @@ -11165,18 +11489,18 @@ dependencies = [ [[package]] name = "sp-core-hashing-proc-macro" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "proc-macro2", "quote", "sp-core-hashing", - "syn 1.0.109", + "syn 2.0.25", ] [[package]] name = "sp-database" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "kvdb", "parking_lot 0.12.1", @@ -11185,17 +11509,17 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.25", ] [[package]] name = "sp-externalities" version = "0.13.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "environmental", "parity-scale-codec", @@ -11203,28 +11527,10 @@ dependencies = [ "sp-storage", ] -[[package]] -name = "sp-finality-grandpa" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" -dependencies = [ - "finality-grandpa", - "log", - "parity-scale-codec", - "scale-info", - "serde", - "sp-api", - "sp-application-crypto", - "sp-core", - "sp-keystore", - "sp-runtime", - "sp-std", -] - [[package]] name = "sp-inherents" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "impl-trait-for-tuples", @@ -11239,7 +11545,7 @@ dependencies = [ [[package]] name = "sp-io" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "bytes", "ed25519", @@ -11248,6 +11554,7 @@ dependencies = [ "libsecp256k1", "log", "parity-scale-codec", + "rustversion", "secp256k1", "sp-core", "sp-externalities", @@ -11264,7 +11571,7 @@ dependencies = [ [[package]] name = "sp-keyring" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "lazy_static", "sp-core", @@ -11275,14 +11582,11 @@ dependencies = [ [[package]] name = "sp-keystore" version = "0.13.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "async-trait", "futures", - "merlin", "parity-scale-codec", "parking_lot 0.12.1", - "schnorrkel", "serde", "sp-core", "sp-externalities", @@ -11292,16 +11596,27 @@ dependencies = [ [[package]] name = "sp-maybe-compressed-blob" version = "4.1.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "thiserror", - "zstd", + "zstd 0.12.3+zstd.1.5.2", +] + +[[package]] +name = "sp-metadata-ir" +version = "0.1.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "frame-metadata", + "parity-scale-codec", + "scale-info", + "sp-std", ] [[package]] name = "sp-mmr-primitives" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "ckb-merkle-mountain-range", "log", @@ -11319,7 +11634,7 @@ dependencies = [ [[package]] name = "sp-npos-elections" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", @@ -11333,7 +11648,7 @@ dependencies = [ [[package]] name = "sp-offchain" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "sp-api", "sp-core", @@ -11343,7 +11658,7 @@ dependencies = [ [[package]] name = "sp-panic-handler" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "backtrace", "lazy_static", @@ -11353,7 +11668,7 @@ dependencies = [ [[package]] name = "sp-rpc" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "rustc-hash", "serde", @@ -11363,7 +11678,7 @@ dependencies = [ [[package]] name = "sp-runtime" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "either", "hash256-std-hasher", @@ -11385,7 +11700,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -11403,19 +11718,19 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "Inflector", "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.25", ] [[package]] name = "sp-serializer" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "serde", "serde_json", @@ -11424,7 +11739,7 @@ dependencies = [ [[package]] name = "sp-session" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", @@ -11438,10 +11753,11 @@ dependencies = [ [[package]] name = "sp-staking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", + "serde", "sp-core", "sp-runtime", "sp-std", @@ -11450,7 +11766,7 @@ dependencies = [ [[package]] name = "sp-state-machine" version = "0.13.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "hash-db", "log", @@ -11470,12 +11786,12 @@ dependencies = [ [[package]] name = "sp-std" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" [[package]] name = "sp-storage" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "impl-serde", "parity-scale-codec", @@ -11488,7 +11804,7 @@ dependencies = [ [[package]] name = "sp-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "futures-timer", @@ -11503,7 +11819,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "sp-std", @@ -11515,7 +11831,7 @@ dependencies = [ [[package]] name = "sp-transaction-pool" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "sp-api", "sp-runtime", @@ -11524,7 +11840,7 @@ dependencies = [ [[package]] name = "sp-transaction-storage-proof" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "log", @@ -11540,11 +11856,11 @@ dependencies = [ [[package]] name = "sp-trie" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "ahash 0.8.3", "hash-db", - "hashbrown 0.12.3", + "hashbrown 0.13.2", "lazy_static", "memory-db", "nohash-hasher", @@ -11563,7 +11879,7 @@ dependencies = [ [[package]] name = "sp-version" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "impl-serde", "parity-scale-codec", @@ -11580,18 +11896,18 @@ dependencies = [ [[package]] name = "sp-version-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.25", ] [[package]] name = "sp-wasm-interface" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -11605,7 +11921,7 @@ dependencies = [ [[package]] name = "sp-weights" version = "4.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", @@ -11623,6 +11939,17 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spinners" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08615eea740067d9899969bc2891c68a19c315cb1f66640af9a9ecb91b13bcab" +dependencies = [ + "lazy_static", + "maplit", + "strum", +] + [[package]] name = "spki" version = "0.6.0" @@ -11630,7 +11957,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" dependencies = [ "base64ct", - "der", + "der 0.6.1", +] + +[[package]] +name = "spki" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +dependencies = [ + "base64ct", + "der 0.7.7", ] [[package]] @@ -11657,8 +11994,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "statemint-runtime" version = "1.0.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" dependencies = [ + "assets-common", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -11674,7 +12012,7 @@ dependencies = [ "frame-system", "frame-system-benchmarking", "frame-system-rpc-runtime-api", - "hex-literal", + "hex-literal 0.4.1", "log", "pallet-asset-tx-payment", "pallet-assets", @@ -11712,6 +12050,7 @@ dependencies = [ "sp-std", "sp-transaction-pool", "sp-version", + "sp-weights", "substrate-wasm-builder", "xcm", "xcm-builder", @@ -11840,7 +12179,7 @@ dependencies = [ [[package]] name = "substrate-build-script-utils" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "platforms 2.0.0", ] @@ -11858,7 +12197,7 @@ dependencies = [ [[package]] name = "substrate-frame-rpc-system" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-system-rpc-runtime-api", "futures", @@ -11877,7 +12216,7 @@ dependencies = [ [[package]] name = "substrate-prometheus-endpoint" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "hyper", "log", @@ -11889,7 +12228,7 @@ dependencies = [ [[package]] name = "substrate-rpc-client" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "jsonrpsee", @@ -11902,7 +12241,7 @@ dependencies = [ [[package]] name = "substrate-state-trie-migration-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "jsonrpsee", "log", @@ -11921,7 +12260,7 @@ dependencies = [ [[package]] name = "substrate-wasm-builder" version = "5.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "ansi_term", "build-helper", @@ -11930,7 +12269,7 @@ dependencies = [ "sp-maybe-compressed-blob", "strum", "tempfile", - "toml", + "toml 0.7.6", "walkdir", "wasm-opt", ] @@ -12285,11 +12624,26 @@ dependencies = [ "serde", ] +[[package]] +name = "toml" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + [[package]] name = "toml_datetime" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] [[package]] name = "toml_edit" @@ -12298,6 +12652,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78" dependencies = [ "indexmap 2.0.0", + "serde", + "serde_spanned", "toml_datetime", "winnow", ] @@ -12389,8 +12745,8 @@ dependencies = [ [[package]] name = "tracing-gum" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "polkadot-node-jaeger", "polkadot-primitives", @@ -12400,14 +12756,14 @@ dependencies = [ [[package]] name = "tracing-gum-proc-macro" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ - "expander 0.0.6", + "expander 2.0.0", "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.25", ] [[package]] @@ -12456,9 +12812,9 @@ dependencies = [ [[package]] name = "trie-db" -version = "0.25.1" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3390c0409daaa6027d6681393316f4ccd3ff82e1590a1e4725014e3ae2bf1920" +checksum = "767abe6ffed88a1889671a102c2861ae742726f52e0a5a425b92c9fbfa7e9c85" dependencies = [ "hash-db", "hashbrown 0.13.2", @@ -12469,9 +12825,9 @@ dependencies = [ [[package]] name = "trie-root" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a36c5ca3911ed3c9a5416ee6c679042064b93fc637ded67e25f92e68d783891" +checksum = "d4ed310ef5ab98f5fa467900ed906cb9232dd5376597e00fd4cba2a449d06c0b" dependencies = [ "hash-db", ] @@ -12531,7 +12887,7 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "try-runtime-cli" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "clap", @@ -12562,7 +12918,7 @@ dependencies = [ "sp-version", "sp-weights", "substrate-rpc-client", - "zstd", + "zstd 0.12.3+zstd.1.5.2", ] [[package]] @@ -13035,9 +13391,9 @@ dependencies = [ "rustix 0.36.15", "serde", "sha2 0.10.7", - "toml", + "toml 0.5.11", "windows-sys 0.42.0", - "zstd", + "zstd 0.11.2+zstd.1.5.2", ] [[package]] @@ -13272,7 +13628,7 @@ dependencies = [ "ccm", "curve25519-dalek 3.2.0", "der-parser 8.2.0", - "elliptic-curve", + "elliptic-curve 0.12.3", "hkdf", "hmac 0.12.1", "log", @@ -13284,11 +13640,11 @@ dependencies = [ "rcgen 0.9.3", "ring", "rustls 0.19.1", - "sec1", + "sec1 0.3.0", "serde", "sha1", "sha2 0.10.7", - "signature", + "signature 1.6.4", "subtle", "thiserror", "tokio", @@ -13403,7 +13759,7 @@ dependencies = [ "lazy_static", "libc", "log", - "nix 0.24.3", + "nix", "rand 0.8.5", "thiserror", "tokio", @@ -13412,8 +13768,8 @@ dependencies = [ [[package]] name = "westend-runtime" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitvec", "frame-benchmarking", @@ -13424,7 +13780,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal", + "hex-literal 0.4.1", "log", "pallet-authority-discovery", "pallet-authorship", @@ -13480,9 +13836,9 @@ dependencies = [ "smallvec", "sp-api", "sp-authority-discovery", - "sp-beefy", "sp-block-builder", "sp-consensus-babe", + "sp-consensus-beefy", "sp-core", "sp-inherents", "sp-io", @@ -13504,8 +13860,8 @@ dependencies = [ [[package]] name = "westend-runtime-constants" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "frame-support", "polkadot-primitives", @@ -13862,8 +14218,8 @@ dependencies = [ [[package]] name = "xcm" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bounded-collections", "derivative", @@ -13878,8 +14234,8 @@ dependencies = [ [[package]] name = "xcm-builder" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "frame-support", "frame-system", @@ -13900,7 +14256,7 @@ dependencies = [ [[package]] name = "xcm-emulator" version = "0.1.0" -source = "git+https://github.com/shaunxw/xcm-simulator?rev=aa13dce47596e150806dfc3af99096dae6ffc65e#aa13dce47596e150806dfc3af99096dae6ffc65e" +source = "git+https://github.com/shaunxw/xcm-simulator?rev=d011e5ca62b93e8f688c2042c1f92cdbafc5d1d0#d011e5ca62b93e8f688c2042c1f92cdbafc5d1d0" dependencies = [ "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -13925,8 +14281,8 @@ dependencies = [ [[package]] name = "xcm-executor" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "environmental", "frame-benchmarking", @@ -13945,13 +14301,13 @@ dependencies = [ [[package]] name = "xcm-procedural" -version = "0.9.39-1" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +version = "0.9.42" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.25", ] [[package]] @@ -14003,7 +14359,16 @@ version = "0.11.2+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" dependencies = [ - "zstd-safe", + "zstd-safe 5.0.2+zstd.1.5.2", +] + +[[package]] +name = "zstd" +version = "0.12.3+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76eea132fb024e0e13fd9c2f5d5d595d8a967aa72382ac2f9d39fcc95afd0806" +dependencies = [ + "zstd-safe 6.0.5+zstd.1.5.4", ] [[package]] @@ -14016,6 +14381,16 @@ dependencies = [ "zstd-sys", ] +[[package]] +name = "zstd-safe" +version = "6.0.5+zstd.1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56d9e60b4b1758206c238a10165fbcae3ca37b01744e394c463463f6529d23b" +dependencies = [ + "libc", + "zstd-sys", +] + [[package]] name = "zstd-sys" version = "2.0.8+zstd.1.5.5" diff --git a/Cargo.toml b/Cargo.toml index f71ec117a..f63ca7de0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,12 +41,12 @@ overflow-checks = true [workspace.dependencies] # Build deps -substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } # Internal pallets (with default disabled) pallet-funding = { path = "pallets/funding", default-features = false } pallet-sandbox = { path = "pallets/sandbox", default-features = false } -pallet-parachain-staking = { git = "https://gitlab.com/Omegabit/stake-patch", default-features = false } +pallet-parachain-staking = { git = "https://gitlab.com/Omegabit/stake-patch", default-features = false, branch = "0.9.42"} # Internal support (with default disabled) @@ -76,134 +76,133 @@ smallvec = "1.10.0" log = "0.4.17" # Emulations -xcm-emulator = { git = "https://github.com/shaunxw/xcm-simulator", default-features = false, rev = "aa13dce47596e150806dfc3af99096dae6ffc65e" } -dip-provider-runtime-template = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } -kilt-runtime-common = { package = "runtime-common", default-features = false, git = "https://github.com/KILTprotocol/kilt-node", branch = "aa/dip" } +# TODO: Replace it from the one in the Cumulus Repo +xcm-emulator = { git = "https://github.com/shaunxw/xcm-simulator", default-features = false, rev = "d011e5ca62b93e8f688c2042c1f92cdbafc5d1d0" } # Substrate (with default disabled) -frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -frame-try-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -sp-arithmetic = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -sp-blockchain = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -sp-consensus-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -sp-block-builder = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -sp-offchain = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -sp-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -sp-trie = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -try-runtime-cli = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +frame-try-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-arithmetic = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-consensus-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-block-builder = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-offchain = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-trie = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +try-runtime-cli = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } # FRAME -pallet-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-assets = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-asset-tx-payment = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-collective = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-democracy = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-scheduler = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-treasury = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-utility = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-membership = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-multisig = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-preimage = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-grandpa = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } -pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-assets = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-asset-tx-payment = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-collective = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-democracy = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-scheduler = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-treasury = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-utility = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-membership = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-multisig = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-preimage = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-grandpa = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } # Polkadot (with default disabled) -pallet-xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } -polkadot-parachain = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } -polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } -polkadot-core-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } -xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } -xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } -xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } -xcm-simulator = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } -polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } -polkadot-runtime = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } +pallet-xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } +polkadot-core-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } +xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } +xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } +xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } +xcm-simulator = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } +polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } +polkadot-runtime = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } # Cumulus (with default disabled) -cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } -cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } -cumulus-pallet-solo-to-para = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } -cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } -cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } -cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } -cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } -cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } -cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } -pallet-collator-selection = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } -parachain-info = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } -parachains-common = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } -statemint-runtime = { git = 'https://github.com/paritytech/cumulus', default-features = false, branch = 'polkadot-v0.9.39' } +cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } +cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } +cumulus-pallet-solo-to-para = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } +cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } +cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } +cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } +cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } +cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } +pallet-collator-selection = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } +parachain-info = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } +parachains-common = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } +statemint-runtime = { git = 'https://github.com/paritytech/cumulus', default-features = false, branch = 'polkadot-v0.9.42' } # Client-only (with default enabled) -cumulus-client-cli = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.39" } -cumulus-client-consensus-aura = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.39" } -cumulus-client-consensus-common = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.39" } -cumulus-client-network = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.39" } -cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.39" } -cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.39" } -cumulus-relay-chain-interface = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.39" } -cumulus-relay-chain-inprocess-interface = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.39" } -cumulus-relay-chain-minimal-node = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.39" } -polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.39" } -polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.39" } -sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sc-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sp-serializer = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sc-sysinfo = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -sc-network-common = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } - -substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } -substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +cumulus-client-cli = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } +cumulus-client-consensus-aura = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } +cumulus-client-consensus-common = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } +cumulus-client-network = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } +cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } +cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } +cumulus-relay-chain-interface = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } +cumulus-relay-chain-inprocess-interface = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } +cumulus-relay-chain-minimal-node = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } +polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.42" } +polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.42" } +sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sc-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sc-network-sync = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sp-serializer = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sc-sysinfo = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sc-network-common = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +sc-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } # Benchmarking (with default disabled) -cumulus-pallet-session-benchmarking = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } -frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +cumulus-pallet-session-benchmarking = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } +frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } # Runtimes polimec-parachain-runtime = { path = "runtimes/testnet" } diff --git a/README.md b/README.md index cf6ebf1f6..cb326bbcd 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ ### Step 1: Compile the relay chain and add it to $PATH - Clone the [Polkadot Repository](https://github.com/paritytech/polkadot) -- Checkout the `release-v0.9.39` branch +- Checkout the `release-v0.9.42` branch - Compile it using `cargo b -r -p polkadot` - Add the binary to your $PATH, e.g. `cp target/release/polkadot ~/.local/bin/polkadot` @@ -48,7 +48,7 @@ $ cargo run --release -- --dev You can use [srtool](https://github.com/paritytech/srtool) to compile the runtime and generate the WASM blob. -> TODO: Rust 1.69.0 broke `srtool` and `polkadot-v0.9.39` - we need to wait `polkadot-v0.9.42`. [src](https://github.com/paritytech/srtool/issues/62) +> TODO: Rust 1.69.0 broke `srtool` and `polkadot-v0.9.42` - we need to wait `polkadot-v0.9.42`. [src](https://github.com/paritytech/srtool/issues/62) ``` == Compact diff --git a/integration-tests/modified-penpal/Cargo.toml b/integration-tests/modified-penpal/Cargo.toml index 790852360..ed71efba0 100644 --- a/integration-tests/modified-penpal/Cargo.toml +++ b/integration-tests/modified-penpal/Cargo.toml @@ -12,7 +12,7 @@ edition = "2021" targets = ["x86_64-unknown-linux-gnu"] [build-dependencies] -substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } [dependencies] parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } diff --git a/integration-tests/modified-penpal/src/lib.rs b/integration-tests/modified-penpal/src/lib.rs index e320f5376..0ca13534b 100644 --- a/integration-tests/modified-penpal/src/lib.rs +++ b/integration-tests/modified-penpal/src/lib.rs @@ -123,12 +123,14 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; -pub type Migrations = (pallet_balances::migration::MigrateToTrackInactive,); +pub type Migrations = + (pallet_balances::migration::MigrateToTrackInactive,); /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< @@ -244,10 +246,7 @@ const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts( /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { - NativeVersion { - runtime_version: VERSION, - can_author_with: Default::default(), - } + NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } } parameter_types! { @@ -361,6 +360,10 @@ impl pallet_balances::Config for Runtime { type WeightInfo = pallet_balances::weights::SubstrateWeight; type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; + type HoldIdentifier = (); + type FreezeIdentifier = (); + type MaxHolds = ConstU32<0>; + type MaxFreezes = ConstU32<0>; } parameter_types! { @@ -604,6 +607,14 @@ impl_runtime_apis! { fn metadata() -> OpaqueMetadata { OpaqueMetadata::new(Runtime::metadata().into()) } + + fn metadata_at_version(version: u32) -> Option { + Runtime::metadata_at_version(version) + } + + fn metadata_versions() -> sp_std::vec::Vec { + Runtime::metadata_versions() + } } impl sp_block_builder::BlockBuilder for Runtime { @@ -786,18 +797,20 @@ struct CheckInherents; impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { fn check_inherents( - block: &Block, relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, + block: &Block, + relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, ) -> sp_inherents::CheckInherentsResult { let relay_chain_slot = relay_state_proof .read_slot() .expect("Could not read the relay chain slot from the proof"); - let inherent_data = cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( - relay_chain_slot, - sp_std::time::Duration::from_secs(6), - ) - .create_inherent_data() - .expect("Could not create the timestamp inherent data"); + let inherent_data = + cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( + relay_chain_slot, + sp_std::time::Duration::from_secs(6), + ) + .create_inherent_data() + .expect("Could not create the timestamp inherent data"); inherent_data.check_extrinsics(block) } diff --git a/integration-tests/modified-penpal/src/xcm_config.rs b/integration-tests/modified-penpal/src/xcm_config.rs index 7810eb65b..436ed023b 100644 --- a/integration-tests/modified-penpal/src/xcm_config.rs +++ b/integration-tests/modified-penpal/src/xcm_config.rs @@ -22,14 +22,15 @@ //! with statemine as the reserve. At present no derivative tokens are minted on receipt of a //! ReserveAssetTransferDeposited message but that will but the intension will be to support this soon. use super::{ - AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Assets, Balance, Balances, ParachainInfo, - ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, + AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Assets, Balance, Balances, + EnsureRoot, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, + RuntimeOrigin, WeightToFee, XcmpQueue, }; use core::marker::PhantomData; use frame_support::{ match_types, parameter_types, traits::{ - fungibles::{self, Balanced, CreditOf}, + fungibles::{self, Balanced, Credit}, ConstU32, Contains, ContainsPair, Everything, Get, Nothing, }, weights::Weight, @@ -42,11 +43,13 @@ use polkadot_runtime_common::impls::ToAuthor; use sp_runtime::traits::Zero; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, - FixedWeightBounds, FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, ParentIsPreset, RelayChainAsNative, - SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, WithComputedOrigin, + AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, + AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, + ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, FungiblesAdapter, + IsConcrete, LocalMint, NativeAsset, ParentIsPreset, RelayChainAsNative, + SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, + WithComputedOrigin, }; use xcm_executor::{traits::JustTry, XcmExecutor}; @@ -158,7 +161,10 @@ pub type Barrier = DenyThenTry< // If the message is one that immediately attemps to pay for execution, then allow it. AllowTopLevelPaidExecutionFrom, // Common Good Assets parachain, parent and its exec plurality get free execution - AllowExplicitUnpaidExecutionFrom<(CommonGoodAssetsParachain, ParentOrParentsExecutivePlurality)>, + AllowExplicitUnpaidExecutionFrom<( + CommonGoodAssetsParachain, + ParentOrParentsExecutivePlurality, + )>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, ), @@ -176,8 +182,8 @@ pub struct AssetsFrom(PhantomData); impl> ContainsPair for AssetsFrom { fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool { let loc = T::get(); - &loc == origin - && matches!(asset, MultiAsset { id: AssetId::Concrete(asset_loc), fun: Fungible(_a) } + &loc == origin && + matches!(asset, MultiAsset { id: AssetId::Concrete(asset_loc), fun: Fungible(_a) } if asset_loc.match_and_split(&loc).is_some()) } } @@ -202,7 +208,7 @@ where R: pallet_authorship::Config + pallet_assets::Config, AccountIdOf: From + Into, { - fn handle_credit(credit: CreditOf, pallet_assets::Pallet>) { + fn handle_credit(credit: Credit, pallet_assets::Pallet>) { if let Some(author) = pallet_authorship::Pallet::::author() { // In case of error: Will drop the result triggering the `OnDrop` of the imbalance. let _ = pallet_assets::Pallet::::resolve(&author, credit); @@ -240,7 +246,7 @@ impl ContainsPair for MultiNativeAsset { fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool { if let Some(ref reserve) = asset.reserve() { if reserve == origin { - return true; + return true } } false @@ -262,8 +268,8 @@ impl ContainsPair for StatemintAssets { // location must be the statemint parachain let loc = MultiLocation::new(1, X1(Parachain(1000))); // asset must be either a fungible asset from `pallet_assets` or the native token of the relay chain - &loc == origin - && match asset { + &loc == origin && + match asset { MultiAsset { id: Concrete(MultiLocation { @@ -273,11 +279,7 @@ impl ContainsPair for StatemintAssets { .. } => true, MultiAsset { - id: Concrete(MultiLocation { - parents: 1, - interior: Here, - }), - .. + id: Concrete(MultiLocation { parents: 1, interior: Here }), .. } => true, _ => false, @@ -299,7 +301,8 @@ impl xcm_executor::Config for XcmConfig { type UniversalLocation = UniversalLocation; type Barrier = Barrier; type Weigher = FixedWeightBounds; - type Trader = UsingComponents>; + type Trader = + UsingComponents>; type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; type AssetClaims = PolkadotXcm; @@ -357,6 +360,7 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<8>; type WeightInfo = pallet_xcm::TestWeightInfo; + type AdminOrigin = EnsureRoot; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; } diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs index 4a5e6dfde..fa5b321ee 100644 --- a/integration-tests/src/lib.rs +++ b/integration-tests/src/lib.rs @@ -24,8 +24,8 @@ use sp_core::{ecdsa, ed25519, sr25519, Pair}; use sp_runtime::{traits::AccountIdConversion, AccountId32 as RuntimeAccountId32}; use xcm::{v3::prelude::*, VersionedMultiAssets, VersionedMultiLocation, VersionedXcm}; use xcm_emulator::{ - cumulus_pallet_xcmp_queue, decl_test_network, decl_test_parachain, decl_test_relay_chain, polkadot_primitives, - TestExt, + cumulus_pallet_xcmp_queue, decl_test_network, decl_test_parachain, decl_test_relay_chain, + polkadot_primitives, TestExt, }; const RELAY_ASSET_ID: u32 = 0; @@ -124,8 +124,10 @@ impl ParachainAccounts { } fn default_parachains_host_configuration( -) -> polkadot_runtime_parachains::configuration::HostConfiguration { - use polkadot_primitives::v2::{MAX_CODE_SIZE, MAX_POV_SIZE}; +) -> polkadot_runtime_parachains::configuration::HostConfiguration< + polkadot_primitives::v4::BlockNumber, +> { + use polkadot_primitives::v4::{MAX_CODE_SIZE, MAX_POV_SIZE}; polkadot_runtime_parachains::configuration::HostConfiguration { minimum_validation_upgrade_delay: 5, @@ -167,9 +169,7 @@ fn default_parachains_host_configuration( pub fn polkadot_ext() -> sp_io::TestExternalities { use polkadot_runtime::{Runtime, System}; - let mut t = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); pallet_balances::GenesisConfig:: { balances: vec![ @@ -188,10 +188,12 @@ pub fn polkadot_ext() -> sp_io::TestExternalities { .assimilate_storage(&mut t) .unwrap(); - let xcm_config = pallet_xcm::GenesisConfig { - safe_xcm_version: Some(3), - }; - >::assimilate_storage(&xcm_config, &mut t).unwrap(); + let xcm_config = pallet_xcm::GenesisConfig { safe_xcm_version: Some(3) }; + >::assimilate_storage( + &xcm_config, + &mut t, + ) + .unwrap(); let mut ext = sp_io::TestExternalities::new(t); ext.execute_with(|| System::set_block_number(1)); @@ -201,21 +203,22 @@ pub fn polkadot_ext() -> sp_io::TestExternalities { pub fn polimec_ext(para_id: u32) -> sp_io::TestExternalities { use polimec_runtime::{Runtime, System}; - let mut t = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - let parachain_info_config = parachain_info::GenesisConfig { - parachain_id: para_id.into(), - }; + let parachain_info_config = parachain_info::GenesisConfig { parachain_id: para_id.into() }; - >::assimilate_storage(¶chain_info_config, &mut t) - .unwrap(); + >::assimilate_storage( + ¶chain_info_config, + &mut t, + ) + .unwrap(); - let xcm_config = pallet_xcm::GenesisConfig { - safe_xcm_version: Some(3), - }; - >::assimilate_storage(&xcm_config, &mut t).unwrap(); + let xcm_config = pallet_xcm::GenesisConfig { safe_xcm_version: Some(3) }; + >::assimilate_storage( + &xcm_config, + &mut t, + ) + .unwrap(); pallet_balances::GenesisConfig:: { balances: vec![ @@ -254,21 +257,22 @@ pub fn polimec_ext(para_id: u32) -> sp_io::TestExternalities { pub fn statemint_ext(para_id: u32) -> sp_io::TestExternalities { use statemint_runtime::{Runtime, System}; - let mut t = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - let parachain_info_config = parachain_info::GenesisConfig { - parachain_id: para_id.into(), - }; + let parachain_info_config = parachain_info::GenesisConfig { parachain_id: para_id.into() }; - >::assimilate_storage(¶chain_info_config, &mut t) - .unwrap(); + >::assimilate_storage( + ¶chain_info_config, + &mut t, + ) + .unwrap(); - let xcm_config = pallet_xcm::GenesisConfig { - safe_xcm_version: Some(3), - }; - >::assimilate_storage(&xcm_config, &mut t).unwrap(); + let xcm_config = pallet_xcm::GenesisConfig { safe_xcm_version: Some(3) }; + >::assimilate_storage( + &xcm_config, + &mut t, + ) + .unwrap(); pallet_balances::GenesisConfig:: { balances: vec![ @@ -288,20 +292,21 @@ pub fn statemint_ext(para_id: u32) -> sp_io::TestExternalities { pub fn penpal_ext(para_id: u32) -> sp_io::TestExternalities { use penpal_runtime::{Runtime, System}; - let mut t = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - let parachain_info_config = parachain_info::GenesisConfig { - parachain_id: para_id.into(), - }; - >::assimilate_storage(¶chain_info_config, &mut t) - .unwrap(); + let parachain_info_config = parachain_info::GenesisConfig { parachain_id: para_id.into() }; + >::assimilate_storage( + ¶chain_info_config, + &mut t, + ) + .unwrap(); - let xcm_config = pallet_xcm::GenesisConfig { - safe_xcm_version: Some(3), - }; - >::assimilate_storage(&xcm_config, &mut t).unwrap(); + let xcm_config = pallet_xcm::GenesisConfig { safe_xcm_version: Some(3) }; + >::assimilate_storage( + &xcm_config, + &mut t, + ) + .unwrap(); pallet_balances::GenesisConfig:: { balances: vec![ @@ -338,7 +343,8 @@ pub mod shortcuts { pub type PenpalBalances = pallet_balances::Pallet; pub type PolkadotAssets = pallet_assets::Pallet; - pub type PolimecAssets = pallet_assets::Pallet; + pub type PolimecAssets = + pallet_assets::Pallet; pub type StatemintAssets = pallet_assets::Pallet; pub type PenpalAssets = pallet_assets::Pallet; @@ -375,13 +381,13 @@ mod network_tests { Here, Parachain(polimec_id()), Xcm(vec![ - UnpaidExecution { - weight_limit: WeightLimit::Unlimited, - check_origin: None - }, + UnpaidExecution { weight_limit: WeightLimit::Unlimited, check_origin: None }, Transact { origin_kind: OriginKind::SovereignAccount, - require_weight_at_most: Weight::from_parts(INITIAL_BALANCE as u64, 1024 * 1024), + require_weight_at_most: Weight::from_parts( + INITIAL_BALANCE as u64, + 1024 * 1024 + ), call: remark.encode().into(), } ]), @@ -402,31 +408,29 @@ mod network_tests { fn ump() { Network::reset(); - let burn_transfer = PolkadotCall::Balances(pallet_balances::Call::::transfer { - dest: PolkadotAccountId::from([0u8; 32]).into(), - value: 1_000, - }); + let burn_transfer = + PolkadotCall::Balances(pallet_balances::Call::::transfer { + dest: PolkadotAccountId::from([0u8; 32]).into(), + value: 1_000, + }); let here_asset: MultiAsset = (MultiLocation::here(), INITIAL_BALANCE / 2).into(); PolimecNet::execute_with(|| { - assert_ok!(PolimecXcmPallet::force_default_xcm_version( - PolimecOrigin::root(), - Some(3) - )); + assert_ok!(PolimecXcmPallet::force_default_xcm_version(PolimecOrigin::root(), Some(3))); assert_ok!(PolimecXcmPallet::send_xcm( Here, Parent, Xcm(vec![ WithdrawAsset(vec![here_asset.clone()].into()), - BuyExecution { - fees: here_asset.clone(), - weight_limit: Unlimited - }, + BuyExecution { fees: here_asset.clone(), weight_limit: Unlimited }, Transact { origin_kind: OriginKind::SovereignAccount, - require_weight_at_most: Weight::from_parts(INITIAL_BALANCE as u64, 1024 * 1024), + require_weight_at_most: Weight::from_parts( + INITIAL_BALANCE as u64, + 1024 * 1024 + ), call: burn_transfer.encode().into(), } ]), @@ -450,10 +454,11 @@ mod network_tests { fn xcmp() { Network::reset(); - let burn_transfer = PolimecCall::Balances(pallet_balances::Call::::transfer { - dest: PolimecAccountId::from([0u8; 32]).into(), - value: 1_000, - }); + let burn_transfer = + PolimecCall::Balances(pallet_balances::Call::::transfer { + dest: PolimecAccountId::from([0u8; 32]).into(), + value: 1_000, + }); let here_asset: MultiAsset = (MultiLocation::here(), INITIAL_BALANCE / 2).into(); @@ -463,13 +468,13 @@ mod network_tests { MultiLocation::new(1, X1(Parachain(polimec_id()))), Xcm(vec![ WithdrawAsset(vec![here_asset.clone()].into()), - BuyExecution { - fees: here_asset.clone(), - weight_limit: Unlimited - }, + BuyExecution { fees: here_asset.clone(), weight_limit: Unlimited }, Transact { origin_kind: OriginKind::SovereignAccount, - require_weight_at_most: Weight::from_parts(INITIAL_BALANCE as u64, 1024 * 1024), + require_weight_at_most: Weight::from_parts( + INITIAL_BALANCE as u64, + 1024 * 1024 + ), call: burn_transfer.encode().into(), } ]), @@ -514,14 +519,17 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_polimec_dot_balance, statemint_prev_dot_issuance) = - StatemintNet::execute_with(|| { - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::free_balance(ParachainAccounts::polimec_child_account()), - StatemintBalances::total_issuance(), - ) - }); + let ( + statemint_prev_alice_dot_balance, + statemint_prev_polimec_dot_balance, + statemint_prev_dot_issuance, + ) = StatemintNet::execute_with(|| { + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::free_balance(ParachainAccounts::polimec_child_account()), + StatemintBalances::total_issuance(), + ) + }); // do the transfer StatemintNet::execute_with(|| { @@ -568,25 +576,32 @@ mod reserve_backed_transfers { }); // check Statemint's post transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_polimec_dot_balance, statemint_post_dot_issuance) = - StatemintNet::execute_with(|| { - statemint_runtime::System::reset_events(); - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::free_balance(ParachainAccounts::polimec_child_account()), - StatemintBalances::total_issuance(), - ) - }); + let ( + statemint_post_alice_dot_balance, + statemint_post_polimec_dot_balance, + statemint_post_dot_issuance, + ) = StatemintNet::execute_with(|| { + statemint_runtime::System::reset_events(); + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::free_balance(ParachainAccounts::polimec_child_account()), + StatemintBalances::total_issuance(), + ) + }); - let polimec_delta_alice_dot_balance = polimec_post_alice_dot_balance - polimec_prev_alice_dot_balance; + let polimec_delta_alice_dot_balance = + polimec_post_alice_dot_balance - polimec_prev_alice_dot_balance; let polimec_delta_dot_issuance = polimec_post_dot_issuance - polimec_prev_dot_issuance; - let polimec_delta_alice_plmc_balance = polimec_post_alice_plmc_balance - polimec_prev_alice_plmc_balance; + let polimec_delta_alice_plmc_balance = + polimec_post_alice_plmc_balance - polimec_prev_alice_plmc_balance; let polimec_delta_plmc_issuance = polimec_post_plmc_issuance - polimec_prev_plmc_issuance; - let statemint_delta_alice_dot_balance = statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; + let statemint_delta_alice_dot_balance = + statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; let statemint_delta_polimec_dot_balance = statemint_post_polimec_dot_balance - statemint_prev_polimec_dot_balance; - let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_dot_issuance = + statemint_prev_dot_issuance - statemint_post_dot_issuance; assert!( polimec_delta_alice_dot_balance >= RESERVE_TRANSFER_AMOUNT - polimec_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) && @@ -622,10 +637,7 @@ mod reserve_backed_transfers { "Polimec ALICE PLMC balance should not have changed" ); - assert_eq!( - polimec_delta_plmc_issuance, 0, - "Polimec PLMC issuance should not have changed" - ); + assert_eq!(polimec_delta_plmc_issuance, 0, "Polimec PLMC issuance should not have changed"); } #[test] @@ -652,20 +664,15 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = StatemintNet::execute_with(|| { - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::total_issuance(), - ) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = + StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); // construct the XCM to transfer from Polimec to Statemint's reserve let transfer_xcm: Xcm = Xcm(vec![ WithdrawAsset(vec![dot.clone()].into()), - BuyExecution { - fees: execution_dot.clone(), - weight_limit: Limited(MAX_XCM_WEIGHT), - }, + BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, InitiateReserveWithdraw { assets: All.into(), reserve: MultiLocation::new(1, X1(Parachain(statemint_id()))), @@ -678,10 +685,7 @@ mod reserve_backed_transfers { assets: All.into(), beneficiary: MultiLocation::new( 0, - AccountId32 { - network: None, - id: ALICE.into(), - }, + AccountId32 { network: None, id: ALICE.into() }, ), }, ]), @@ -723,20 +727,22 @@ mod reserve_backed_transfers { }); // check Statemint's post transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = StatemintNet::execute_with(|| { - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::total_issuance(), - ) - }); + let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = + StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); let polimec_delta_dot_issuance = polimec_prev_dot_issuance - polimec_post_dot_issuance; let polimec_delta_plmc_issuance = polimec_prev_plmc_issuance - polimec_post_plmc_issuance; - let polimec_delta_alice_dot_balance = polimec_prev_alice_dot_balance - polimec_post_alice_dot_balance; - let polimec_delta_alice_plmc_balance = polimec_prev_alice_plmc_balance - polimec_post_alice_plmc_balance; + let polimec_delta_alice_dot_balance = + polimec_prev_alice_dot_balance - polimec_post_alice_dot_balance; + let polimec_delta_alice_plmc_balance = + polimec_prev_alice_plmc_balance - polimec_post_alice_plmc_balance; - let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; - let statemint_delta_alice_dot_balance = statemint_post_alice_dot_balance - statemint_prev_alice_dot_balance; + let statemint_delta_dot_issuance = + statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = + statemint_post_alice_dot_balance - statemint_prev_alice_dot_balance; assert_eq!( polimec_delta_alice_dot_balance, RESERVE_TRANSFER_AMOUNT, @@ -749,10 +755,7 @@ mod reserve_backed_transfers { ); assert_eq!(polimec_delta_plmc_issuance, 0, "Polimec's PLMC issuance should not change, since all xcm token transfer are done in DOT, and no fees are burnt since no extrinsics are dispatched"); - assert_eq!( - polimec_delta_alice_plmc_balance, 0, - "Polimec's Alice PLMC should not change" - ); + assert_eq!(polimec_delta_alice_plmc_balance, 0, "Polimec's Alice PLMC should not change"); assert!( statemint_delta_alice_dot_balance @@ -776,17 +779,22 @@ mod reserve_backed_transfers { // check Penpal's pre transfer balances and issuance let (penpal_prev_alice_dot_balance, penpal_prev_dot_issuance) = - PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); + PenpalNet::execute_with(|| { + (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) + }); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_penpal_dot_balance, statemint_prev_dot_issuance) = - StatemintNet::execute_with(|| { - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::free_balance(ParachainAccounts::penpal_child_account()), - StatemintBalances::total_issuance(), - ) - }); + let ( + statemint_prev_alice_dot_balance, + statemint_prev_penpal_dot_balance, + statemint_prev_dot_issuance, + ) = StatemintNet::execute_with(|| { + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::free_balance(ParachainAccounts::penpal_child_account()), + StatemintBalances::total_issuance(), + ) + }); // do the transfer StatemintNet::execute_with(|| { @@ -817,28 +825,36 @@ mod reserve_backed_transfers { }); // check Penpal's post transfer balances and issuance - let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = PenpalNet::execute_with(|| { - penpal_runtime::System::reset_events(); - (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) - }); + let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = + PenpalNet::execute_with(|| { + penpal_runtime::System::reset_events(); + (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) + }); // check Statemint's post transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_penpal_dot_balance, statemint_post_dot_issuance) = - StatemintNet::execute_with(|| { - statemint_runtime::System::reset_events(); - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::free_balance(ParachainAccounts::penpal_child_account()), - StatemintBalances::total_issuance(), - ) - }); + let ( + statemint_post_alice_dot_balance, + statemint_post_penpal_dot_balance, + statemint_post_dot_issuance, + ) = StatemintNet::execute_with(|| { + statemint_runtime::System::reset_events(); + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::free_balance(ParachainAccounts::penpal_child_account()), + StatemintBalances::total_issuance(), + ) + }); - let penpal_delta_alice_dot_balance = penpal_post_alice_dot_balance - penpal_prev_alice_dot_balance; + let penpal_delta_alice_dot_balance = + penpal_post_alice_dot_balance - penpal_prev_alice_dot_balance; let penpal_delta_dot_issuance = penpal_post_dot_issuance - penpal_prev_dot_issuance; - let statemint_delta_alice_dot_balance = statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; - let statemint_delta_penpal_dot_balance = statemint_post_penpal_dot_balance - statemint_prev_penpal_dot_balance; - let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = + statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; + let statemint_delta_penpal_dot_balance = + statemint_post_penpal_dot_balance - statemint_prev_penpal_dot_balance; + let statemint_delta_dot_issuance = + statemint_prev_dot_issuance - statemint_post_dot_issuance; assert!( penpal_delta_alice_dot_balance >= RESERVE_TRANSFER_AMOUNT - penpal_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) && @@ -879,23 +895,20 @@ mod reserve_backed_transfers { // check Penpal's pre transfer balances and issuance let (penpal_prev_alice_dot_balance, penpal_prev_dot_issuance) = - PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); + PenpalNet::execute_with(|| { + (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) + }); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = StatemintNet::execute_with(|| { - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::total_issuance(), - ) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = + StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); // construct the XCM to transfer from Penpal to Statemint's reserve let transfer_xcm: Xcm = Xcm(vec![ WithdrawAsset(vec![dot.clone()].into()), - BuyExecution { - fees: execution_dot.clone(), - weight_limit: Limited(MAX_XCM_WEIGHT), - }, + BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, InitiateReserveWithdraw { assets: All.into(), reserve: MultiLocation::new(1, X1(Parachain(statemint_id()))), @@ -908,10 +921,7 @@ mod reserve_backed_transfers { assets: All.into(), beneficiary: MultiLocation::new( 0, - AccountId32 { - network: None, - id: ALICE.into(), - }, + AccountId32 { network: None, id: ALICE.into() }, ), }, ]), @@ -939,21 +949,24 @@ mod reserve_backed_transfers { // check Penpal's post transfer balances and issuance let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = - PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); + PenpalNet::execute_with(|| { + (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) + }); // check Statemint's post transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = StatemintNet::execute_with(|| { - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::total_issuance(), - ) - }); + let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = + StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); let penpal_delta_dot_issuance = penpal_prev_dot_issuance - penpal_post_dot_issuance; - let penpal_delta_alice_dot_balance = penpal_prev_alice_dot_balance - penpal_post_alice_dot_balance; + let penpal_delta_alice_dot_balance = + penpal_prev_alice_dot_balance - penpal_post_alice_dot_balance; - let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; - let statemint_delta_alice_dot_balance = statemint_post_alice_dot_balance - statemint_prev_alice_dot_balance; + let statemint_delta_dot_issuance = + statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = + statemint_post_alice_dot_balance - statemint_prev_alice_dot_balance; assert_eq!( penpal_delta_alice_dot_balance, RESERVE_TRANSFER_AMOUNT, @@ -988,10 +1001,7 @@ mod reserve_backed_transfers { let transfer_xcm: Xcm = Xcm(vec![ WithdrawAsset(vec![dot.clone()].into()), - BuyExecution { - fees: execution_dot.clone(), - weight_limit: Limited(MAX_XCM_WEIGHT), - }, + BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, InitiateReserveWithdraw { assets: All.into(), reserve: MultiLocation::new(1, X1(Parachain(statemint_id()))), @@ -1010,11 +1020,8 @@ mod reserve_backed_transfers { }, DepositAsset { assets: All.into(), - beneficiary: X1(AccountId32 { - network: None, - id: ALICE.into(), - }) - .into(), + beneficiary: X1(AccountId32 { network: None, id: ALICE.into() }) + .into(), }, ]), }, @@ -1038,16 +1045,16 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = StatemintNet::execute_with(|| { - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::total_issuance(), - ) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = + StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); // check Penpal's pre transfer balances and issuance let (penpal_prev_alice_dot_balance, penpal_prev_dot_issuance) = - PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); + PenpalNet::execute_with(|| { + (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) + }); // send the XCM message PolimecNet::execute_with(|| { @@ -1092,31 +1099,36 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = StatemintNet::execute_with(|| { - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::total_issuance(), - ) - }); + let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = + StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); // check Penpal's pre transfer balances and issuance let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = - PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); + PenpalNet::execute_with(|| { + (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) + }); let penpal_delta_dot_issuance = penpal_post_dot_issuance - penpal_prev_dot_issuance; - let penpal_delta_alice_dot_balance = penpal_post_alice_dot_balance - penpal_prev_alice_dot_balance; + let penpal_delta_alice_dot_balance = + penpal_post_alice_dot_balance - penpal_prev_alice_dot_balance; let polimec_delta_dot_issuance = polimec_prev_dot_issuance - polimec_post_dot_issuance; - let polimec_delta_alice_dot_balance = polimec_prev_alice_dot_balance - polimec_post_alice_dot_balance; + let polimec_delta_alice_dot_balance = + polimec_prev_alice_dot_balance - polimec_post_alice_dot_balance; let polimec_delta_plmc_issuance = polimec_prev_plmc_issuance - polimec_post_plmc_issuance; - let polimec_delta_alice_plmc_balance = polimec_prev_alice_plmc_balance - polimec_post_alice_plmc_balance; + let polimec_delta_alice_plmc_balance = + polimec_prev_alice_plmc_balance - polimec_post_alice_plmc_balance; - let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; - let statemint_delta_alice_dot_balance = statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; + let statemint_delta_dot_issuance = + statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = + statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; assert!( - penpal_delta_alice_dot_balance > RESERVE_TRANSFER_AMOUNT - MAX_XCM_FEE * 3 - && penpal_delta_alice_dot_balance < RESERVE_TRANSFER_AMOUNT, + penpal_delta_alice_dot_balance > RESERVE_TRANSFER_AMOUNT - MAX_XCM_FEE * 3 && + penpal_delta_alice_dot_balance < RESERVE_TRANSFER_AMOUNT, "Expected funds are not received by Alice on Penpal" ); @@ -1150,10 +1162,7 @@ mod reserve_backed_transfers { "Polimec ALICE PLMC balance should not have changed" ); - assert_eq!( - polimec_delta_plmc_issuance, 0, - "Polimec PLMC issuance should not have changed" - ); + assert_eq!(polimec_delta_plmc_issuance, 0, "Polimec PLMC issuance should not have changed"); } #[test] @@ -1165,10 +1174,7 @@ mod reserve_backed_transfers { let transfer_xcm: Xcm = Xcm(vec![ WithdrawAsset(vec![dot.clone()].into()), - BuyExecution { - fees: execution_dot.clone(), - weight_limit: Limited(MAX_XCM_WEIGHT), - }, + BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, InitiateReserveWithdraw { assets: All.into(), reserve: MultiLocation::new(1, X1(Parachain(statemint_id()))), @@ -1187,11 +1193,8 @@ mod reserve_backed_transfers { }, DepositAsset { assets: All.into(), - beneficiary: X1(AccountId32 { - network: None, - id: ALICE.into(), - }) - .into(), + beneficiary: X1(AccountId32 { network: None, id: ALICE.into() }) + .into(), }, ]), }, @@ -1215,16 +1218,16 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = StatemintNet::execute_with(|| { - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::total_issuance(), - ) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = + StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); // check Penpal's pre transfer balances and issuance let (penpal_prev_alice_dot_balance, penpal_prev_dot_issuance) = - PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); + PenpalNet::execute_with(|| { + (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) + }); // send the XCM message PenpalNet::execute_with(|| { @@ -1269,31 +1272,36 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = StatemintNet::execute_with(|| { - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::total_issuance(), - ) - }); + let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = + StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); // check Penpal's pre transfer balances and issuance let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = - PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); + PenpalNet::execute_with(|| { + (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) + }); let penpal_delta_dot_issuance = penpal_prev_dot_issuance - penpal_post_dot_issuance; - let penpal_delta_alice_dot_balance = penpal_prev_alice_dot_balance - penpal_post_alice_dot_balance; + let penpal_delta_alice_dot_balance = + penpal_prev_alice_dot_balance - penpal_post_alice_dot_balance; let polimec_delta_dot_issuance = polimec_post_dot_issuance - polimec_prev_dot_issuance; - let polimec_delta_alice_dot_balance = polimec_post_alice_dot_balance - polimec_prev_alice_dot_balance; + let polimec_delta_alice_dot_balance = + polimec_post_alice_dot_balance - polimec_prev_alice_dot_balance; let polimec_delta_plmc_issuance = polimec_post_plmc_issuance - polimec_prev_plmc_issuance; - let polimec_delta_alice_plmc_balance = polimec_post_alice_plmc_balance - polimec_prev_alice_plmc_balance; + let polimec_delta_alice_plmc_balance = + polimec_post_alice_plmc_balance - polimec_prev_alice_plmc_balance; - let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; - let statemint_delta_alice_dot_balance = statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; + let statemint_delta_dot_issuance = + statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = + statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; assert!( - polimec_delta_alice_dot_balance > RESERVE_TRANSFER_AMOUNT - MAX_XCM_FEE * 3 - && polimec_delta_alice_dot_balance < RESERVE_TRANSFER_AMOUNT, + polimec_delta_alice_dot_balance > RESERVE_TRANSFER_AMOUNT - MAX_XCM_FEE * 3 && + polimec_delta_alice_dot_balance < RESERVE_TRANSFER_AMOUNT, "Expected funds are not received by Alice on Polimec" ); @@ -1327,9 +1335,6 @@ mod reserve_backed_transfers { "Polimec ALICE PLMC balance should not have changed" ); - assert_eq!( - polimec_delta_plmc_issuance, 0, - "Polimec PLMC issuance should not have changed" - ); + assert_eq!(polimec_delta_plmc_issuance, 0, "Polimec PLMC issuance should not have changed"); } -} \ No newline at end of file +} diff --git a/nodes/parachain/Cargo.toml b/nodes/parachain/Cargo.toml index e564a5e40..8a1316d20 100644 --- a/nodes/parachain/Cargo.toml +++ b/nodes/parachain/Cargo.toml @@ -42,6 +42,7 @@ sc-telemetry.workspace = true sc-tracing.workspace = true sc-transaction-pool.workspace = true sc-transaction-pool-api.workspace = true +sc-network-sync.workspace = true sp-api.workspace = true sp-block-builder.workspace = true sp-blockchain.workspace = true diff --git a/nodes/parachain/src/chain_spec.rs b/nodes/parachain/src/chain_spec.rs index c7ff83f19..7c6a1dc99 100644 --- a/nodes/parachain/src/chain_spec.rs +++ b/nodes/parachain/src/chain_spec.rs @@ -18,7 +18,7 @@ use cumulus_primitives_core::ParaId; use polimec_parachain_runtime::{AccountId, Signature}; -use polkadot_primitives::v2::LOWEST_PUBLIC_ID; +use polkadot_primitives::v4::LOWEST_PUBLIC_ID; use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup}; use sc_service::Properties; use serde::{Deserialize, Serialize}; diff --git a/nodes/parachain/src/command.rs b/nodes/parachain/src/command.rs index 3ce35ff93..c46e4a73c 100644 --- a/nodes/parachain/src/command.rs +++ b/nodes/parachain/src/command.rs @@ -363,8 +363,7 @@ pub fn run() -> Result<()> { let id = ParaId::from(para_id); let parachain_account = - AccountIdConversion::::into_account_truncating(&id); - + AccountIdConversion::::into_account_truncating(&id); let state_version = Cli::native_runtime_version(&config.chain_spec).state_version(); let block: Block = generate_genesis_block(&*config.chain_spec, state_version) .map_err(|e| format!("{:?}", e))?; diff --git a/nodes/parachain/src/service.rs b/nodes/parachain/src/service.rs index 352435bc0..d21e7b66c 100644 --- a/nodes/parachain/src/service.rs +++ b/nodes/parachain/src/service.rs @@ -21,7 +21,7 @@ use std::{sync::Arc, time::Duration}; use cumulus_client_cli::CollatorOptions; // Local Runtime Types -use polimec_parachain_runtime::{opaque::Block, Hash, RuntimeApi}; +use polimec_parachain_runtime::{opaque::Block, RuntimeApi}; // Cumulus Imports use cumulus_client_consensus_aura::{AuraConsensus, BuildAuraConsensusParams, SlotProportion}; @@ -33,17 +33,19 @@ use cumulus_client_service::{ start_full_node, BuildNetworkParams, StartCollatorParams, StartFullNodeParams, }; use cumulus_primitives_core::ParaId; -use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface}; +use cumulus_relay_chain_interface::RelayChainInterface; // Substrate Imports use frame_benchmarking_cli::SUBSTRATE_REFERENCE_HARDWARE; use sc_consensus::ImportQueue; -use sc_executor::NativeElseWasmExecutor; -use sc_network::NetworkService; -use sc_network_common::service::NetworkBlock; +use sc_executor::{ + HeapAllocStrategy, NativeElseWasmExecutor, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY, +}; +use sc_network::NetworkBlock; +use sc_network_sync::SyncingService; use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager}; use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle}; -use sp_keystore::SyncCryptoStorePtr; +use sp_keystore::KeystorePtr; use substrate_prometheus_endpoint::Registry; /// Native executor type. @@ -73,6 +75,7 @@ type ParachainBlockImport = TParachainBlockImport, P /// /// Use this macro if you don't actually need the full service, but just the builder in order to /// be able to perform chain operations. +#[allow(clippy::type_complexity)] pub fn new_partial( config: &Configuration, ) -> Result< @@ -97,12 +100,19 @@ pub fn new_partial( }) .transpose()?; - let executor = ParachainExecutor::new( - config.wasm_method, - config.default_heap_pages, - config.max_runtime_instances, - config.runtime_cache_size, - ); + let heap_pages = config + .default_heap_pages + .map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| HeapAllocStrategy::Static { extra_pages: h as _ }); + + let wasm = WasmExecutor::builder() + .with_execution_method(config.wasm_method) + .with_onchain_heap_alloc_strategy(heap_pages) + .with_offchain_heap_alloc_strategy(heap_pages) + .with_max_runtime_instances(config.max_runtime_instances) + .with_runtime_cache_size(config.runtime_cache_size) + .build(); + + let executor = ParachainExecutor::new_with_wasm_executor(wasm); let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( @@ -178,10 +188,7 @@ async fn start_node_impl( hwbench.clone(), ) .await - .map_err(|e| match e { - RelayChainError::ServiceError(polkadot_service::Error::Sub(x)) => x, - s => s.to_string().into(), - })?; + .map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?; let force_authoring = parachain_config.force_authoring; let validator = parachain_config.role.is_authority(); @@ -189,7 +196,7 @@ async fn start_node_impl( let transaction_pool = params.transaction_pool.clone(); let import_queue_service = params.import_queue.service(); - let (network, system_rpc_tx, tx_handler_controller, start_network) = + let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) = build_network(BuildNetworkParams { parachain_config: ¶chain_config, client: client.clone(), @@ -231,9 +238,10 @@ async fn start_node_impl( transaction_pool: transaction_pool.clone(), task_manager: &mut task_manager, config: parachain_config, - keystore: params.keystore_container.sync_keystore(), + keystore: params.keystore_container.keystore(), backend, network: network.clone(), + sync_service: sync_service.clone(), system_rpc_tx, tx_handler_controller, telemetry: telemetry.as_mut(), @@ -261,8 +269,8 @@ async fn start_node_impl( } let announce_block = { - let network = network.clone(); - Arc::new(move |hash, data| network.announce_block(hash, data)) + let sync_service = sync_service.clone(); + Arc::new(move |hash, data| sync_service.announce_block(hash, data)) }; let relay_chain_slot_duration = Duration::from_secs(6); @@ -280,8 +288,8 @@ async fn start_node_impl( &task_manager, relay_chain_interface.clone(), transaction_pool, - network, - params.keystore_container.sync_keystore(), + sync_service.clone(), + params.keystore_container.keystore(), force_authoring, para_id, )?; @@ -300,6 +308,7 @@ async fn start_node_impl( collator_key: collator_key.expect("Command line arguments do not allow this. qed"), relay_chain_slot_duration, recovery_handle: Box::new(overseer_handle), + sync_service, }; start_collator(params).await?; @@ -313,6 +322,7 @@ async fn start_node_impl( relay_chain_slot_duration, import_queue: import_queue_service, recovery_handle: Box::new(overseer_handle), + sync_service, }; start_full_node(params)?; @@ -346,7 +356,8 @@ fn build_import_queue( create_inherent_data_providers: move |_, _| async move { let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, slot_duration, ); @@ -360,6 +371,7 @@ fn build_import_queue( .map_err(Into::into) } +#[allow(clippy::too_many_arguments)] fn build_consensus( client: Arc, block_import: ParachainBlockImport, @@ -368,8 +380,8 @@ fn build_consensus( task_manager: &TaskManager, relay_chain_interface: Arc, transaction_pool: Arc>, - sync_oracle: Arc>, - keystore: SyncCryptoStorePtr, + sync_oracle: Arc>, + keystore: KeystorePtr, force_authoring: bool, para_id: ParaId, ) -> Result>, sc_service::Error> { @@ -398,10 +410,11 @@ fn build_consensus( .await; let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); let parachain_inherent = parachain_inherent.ok_or_else(|| { Box::::from( diff --git a/nodes/standalone/Cargo.toml b/nodes/standalone/Cargo.toml index b31ad7d4e..92b409a30 100644 --- a/nodes/standalone/Cargo.toml +++ b/nodes/standalone/Cargo.toml @@ -26,8 +26,6 @@ sc-consensus-aura.workspace = true sp-consensus-aura.workspace = true sp-consensus.workspace = true sc-consensus.workspace = true -sc-finality-grandpa.workspace = true -sp-finality-grandpa.workspace = true sc-client-api.workspace = true sp-runtime.workspace = true sp-timestamp.workspace = true @@ -36,7 +34,8 @@ sp-keyring.workspace = true frame-system.workspace = true pallet-transaction-payment.workspace = true sc-chain-spec.workspace = true - +sc-consensus-grandpa.workspace = true +sp-consensus-grandpa.workspace = true # These dependencies are used for the node's RPCs jsonrpsee = { workspace = true, features = ["server"] } sc-rpc.workspace = true diff --git a/nodes/standalone/src/chain_spec.rs b/nodes/standalone/src/chain_spec.rs index 6db1a7883..ec044fd58 100644 --- a/nodes/standalone/src/chain_spec.rs +++ b/nodes/standalone/src/chain_spec.rs @@ -20,8 +20,8 @@ use polimec_standalone_runtime::{ }; use sc_service::{ChainType, Properties}; use sp_consensus_aura::sr25519::AuthorityId as AuraId; +use sp_consensus_grandpa::AuthorityId as GrandpaId; use sp_core::{sr25519, Pair, Public}; -use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_runtime::traits::{IdentifyAccount, Verify}; // The URL for the telemetry server. diff --git a/nodes/standalone/src/command.rs b/nodes/standalone/src/command.rs index 7b4d488f6..892c41ce5 100644 --- a/nodes/standalone/src/command.rs +++ b/nodes/standalone/src/command.rs @@ -1,19 +1,3 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - use crate::{ benchmarking::{inherent_benchmark_data, RemarkBuilder, TransferKeepAliveBuilder}, chain_spec, @@ -26,6 +10,9 @@ use sc_cli::{ChainSpec, RuntimeVersion, SubstrateCli}; use sc_service::PartialComponents; use sp_keyring::Sr25519Keyring; +#[cfg(feature = "try-runtime")] +use try_runtime_cli::block_building_info::timestamp_with_aura_info; + impl SubstrateCli for Cli { fn impl_name() -> String { "Substrate Node".into() @@ -115,7 +102,7 @@ pub fn run() -> sc_cli::Result<()> { let PartialComponents { client, task_manager, backend, .. } = service::new_partial(&config)?; let aux_revert = Box::new(|client, _, blocks| { - sc_finality_grandpa::revert(client, blocks)?; + sc_consensus_grandpa::revert(client, blocks)?; Ok(()) }); Ok((cmd.run(client, backend, Some(aux_revert)), task_manager)) @@ -190,6 +177,8 @@ pub fn run() -> sc_cli::Result<()> { }, #[cfg(feature = "try-runtime")] Some(Subcommand::TryRuntime(cmd)) => { + use crate::service::ExecutorDispatch; + use sc_executor::{sp_wasm_interface::ExtendedHostFunctions, NativeExecutionDispatch}; let runner = cli.create_runner(cmd)?; runner.async_run(|config| { // we don't need any of the components of new_partial, just a runtime, or a task @@ -198,7 +187,15 @@ pub fn run() -> sc_cli::Result<()> { let task_manager = sc_service::TaskManager::new(config.tokio_handle.clone(), registry) .map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?; - Ok((cmd.run::(config), task_manager)) + let info_provider = timestamp_with_aura_info(6000); + + Ok(( + cmd.run::::ExtendHostFunctions, + >, _>(Some(info_provider)), + task_manager, + )) }) }, #[cfg(not(feature = "try-runtime"))] diff --git a/nodes/standalone/src/service.rs b/nodes/standalone/src/service.rs index b92c2e81d..0ce896d35 100644 --- a/nodes/standalone/src/service.rs +++ b/nodes/standalone/src/service.rs @@ -19,9 +19,8 @@ use polimec_standalone_runtime::{self, opaque::Block, RuntimeApi}; use sc_client_api::BlockBackend; use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; +use sc_consensus_grandpa::SharedVoterState; pub use sc_executor::NativeElseWasmExecutor; -use sc_finality_grandpa::SharedVoterState; -use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager, WarpSyncParams}; use sc_telemetry::{Telemetry, TelemetryWorker}; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; @@ -62,22 +61,18 @@ pub fn new_partial( sc_consensus::DefaultImportQueue, sc_transaction_pool::FullPool, ( - sc_finality_grandpa::GrandpaBlockImport< + sc_consensus_grandpa::GrandpaBlockImport< FullBackend, Block, FullClient, FullSelectChain, >, - sc_finality_grandpa::LinkHalf, + sc_consensus_grandpa::LinkHalf, Option, ), >, ServiceError, > { - if config.keystore_remote.is_some() { - return Err(ServiceError::Other("Remote Keystores are not supported.".into())) - } - let telemetry = config .telemetry_endpoints .clone() @@ -89,12 +84,7 @@ pub fn new_partial( }) .transpose()?; - let executor = NativeElseWasmExecutor::::new( - config.wasm_method, - config.default_heap_pages, - config.max_runtime_instances, - config.runtime_cache_size, - ); + let executor = sc_service::new_native_or_wasm_executor(&config); let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( @@ -119,7 +109,7 @@ pub fn new_partial( client.clone(), ); - let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import( + let (grandpa_block_import, grandpa_link) = sc_consensus_grandpa::block_import( client.clone(), &(client.clone() as Arc<_>), select_chain.clone(), @@ -136,10 +126,11 @@ pub fn new_partial( create_inherent_data_providers: move |_, ()| async move { let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); Ok((slot, timestamp)) }, @@ -162,13 +153,6 @@ pub fn new_partial( }) } -fn remote_keystore(_url: &String) -> Result, &'static str> { - // FIXME: here would the concrete keystore be built, - // must return a concrete type (NOT `LocalKeystore`) that - // implements `CryptoStore` and `SyncCryptoStore` - Err("Remote Keystore not supported.") -} - /// Builds a new service for a full client. pub fn new_full(mut config: Configuration) -> Result { let sc_service::PartialComponents { @@ -176,23 +160,13 @@ pub fn new_full(mut config: Configuration) -> Result backend, mut task_manager, import_queue, - mut keystore_container, + keystore_container, select_chain, transaction_pool, other: (block_import, grandpa_link, mut telemetry), } = new_partial(&config)?; - if let Some(url) = &config.keystore_remote { - match remote_keystore(url) { - Ok(k) => keystore_container.set_remote_keystore(k), - Err(e) => - return Err(ServiceError::Other(format!( - "Error hooking up remote keystore for {}: {}", - url, e - ))), - }; - } - let grandpa_protocol_name = sc_finality_grandpa::protocol_standard_name( + let grandpa_protocol_name = sc_consensus_grandpa::protocol_standard_name( &client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"), &config.chain_spec, ); @@ -200,14 +174,14 @@ pub fn new_full(mut config: Configuration) -> Result config .network .extra_sets - .push(sc_finality_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone())); - let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( + .push(sc_consensus_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone())); + let warp_sync = Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), Vec::default(), )); - let (network, system_rpc_tx, tx_handler_controller, network_starter) = + let (network, system_rpc_tx, tx_handler_controller, network_starter, sync_service) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, client: client.clone(), @@ -248,13 +222,14 @@ pub fn new_full(mut config: Configuration) -> Result let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { network: network.clone(), client: client.clone(), - keystore: keystore_container.sync_keystore(), + keystore: keystore_container.keystore(), task_manager: &mut task_manager, transaction_pool: transaction_pool.clone(), rpc_builder: rpc_extensions_builder, backend, system_rpc_tx, tx_handler_controller, + sync_service: sync_service.clone(), config, telemetry: telemetry.as_mut(), })?; @@ -280,18 +255,19 @@ pub fn new_full(mut config: Configuration) -> Result create_inherent_data_providers: move |_, ()| async move { let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); Ok((slot, timestamp)) }, force_authoring, backoff_authoring_blocks, - keystore: keystore_container.sync_keystore(), - sync_oracle: network.clone(), - justification_sync_link: network.clone(), + keystore: keystore_container.keystore(), + sync_oracle: sync_service.clone(), + justification_sync_link: sync_service.clone(), block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), max_block_proposal_slot_portion: None, telemetry: telemetry.as_ref().map(|x| x.handle()), @@ -309,10 +285,9 @@ pub fn new_full(mut config: Configuration) -> Result if enable_grandpa { // if the node isn't actively participating in consensus then it doesn't // need a keystore, regardless of which protocol we use below. - let keystore = - if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None }; + let keystore = if role.is_authority() { Some(keystore_container.keystore()) } else { None }; - let grandpa_config = sc_finality_grandpa::Config { + let grandpa_config = sc_consensus_grandpa::Config { // FIXME #1578 make this available through chainspec gossip_duration: Duration::from_millis(333), justification_period: 512, @@ -330,11 +305,12 @@ pub fn new_full(mut config: Configuration) -> Result // and vote data availability than the observer. The observer has not // been tested extensively yet and having most nodes in a network run it // could lead to finality stalls. - let grandpa_config = sc_finality_grandpa::GrandpaParams { + let grandpa_config = sc_consensus_grandpa::GrandpaParams { config: grandpa_config, link: grandpa_link, network, - voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), + sync: Arc::new(sync_service), + voting_rule: sc_consensus_grandpa::VotingRulesBuilder::default().build(), prometheus_registry, shared_voter_state: SharedVoterState::empty(), telemetry: telemetry.as_ref().map(|x| x.handle()), @@ -345,7 +321,7 @@ pub fn new_full(mut config: Configuration) -> Result task_manager.spawn_essential_handle().spawn_blocking( "grandpa-voter", None, - sc_finality_grandpa::run_grandpa_voter(grandpa_config)?, + sc_consensus_grandpa::run_grandpa_voter(grandpa_config)?, ); } diff --git a/pallets/funding/src/lib.rs b/pallets/funding/src/lib.rs index 1729100ea..41202a2dc 100644 --- a/pallets/funding/src/lib.rs +++ b/pallets/funding/src/lib.rs @@ -202,7 +202,7 @@ use frame_support::{ pallet_prelude::ValueQuery, traits::{ tokens::{ - fungibles::{metadata::Mutate as MetadataMutate, Create, InspectMetadata, Mutate}, + fungibles::{metadata::Mutate as MetadataMutate, Create, Mutate}, Balance, }, Currency as CurrencyT, Get, NamedReservableCurrency, Randomness, ReservableCurrency, @@ -298,8 +298,7 @@ pub mod pallet { /// The currency used for minting contribution tokens as fungible assets (i.e pallet-assets) type ContributionTokenCurrency: Create> + Mutate - + MetadataMutate - + InspectMetadata; + + MetadataMutate; /// Unique identifier for any bid in the system. type BidId: Parameter + Copy + Saturating + One + Default; diff --git a/pallets/funding/src/mock.rs b/pallets/funding/src/mock.rs index 6ec9516ee..9459da70c 100644 --- a/pallets/funding/src/mock.rs +++ b/pallets/funding/src/mock.rs @@ -103,6 +103,10 @@ impl pallet_balances::Config for TestRuntime { type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; type WeightInfo = (); + type MaxHolds = ConstU32<1024>; + type MaxFreezes = (); + type HoldIdentifier = BondType; + type FreezeIdentifier = (); } impl pallet_insecure_randomness_collective_flip::Config for TestRuntime {} diff --git a/pallets/sandbox/src/mock.rs b/pallets/sandbox/src/mock.rs index 278414096..4bcc626da 100644 --- a/pallets/sandbox/src/mock.rs +++ b/pallets/sandbox/src/mock.rs @@ -101,6 +101,10 @@ impl pallet_balances::Config for TestRuntime { type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; type WeightInfo = (); + type HoldIdentifier = pallet_funding::BondType; + type FreezeIdentifier = pallet_funding::BondType; + type MaxHolds = (); + type MaxFreezes = (); } impl pallet_insecure_randomness_collective_flip::Config for TestRuntime {} diff --git a/runtimes/base/src/lib.rs b/runtimes/base/src/lib.rs index 63fb89b54..701846e13 100644 --- a/runtimes/base/src/lib.rs +++ b/runtimes/base/src/lib.rs @@ -239,14 +239,18 @@ impl pallet_authorship::Config for Runtime { } impl pallet_balances::Config for Runtime { + type MaxLocks = MaxLocks; type Balance = Balance; - type DustRemoval = (); type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; - type MaxLocks = MaxLocks; type MaxReserves = MaxReserves; - type ReserveIdentifier = (); + type MaxHolds = MaxLocks; + type MaxFreezes = MaxReserves; + type HoldIdentifier = (); + type FreezeIdentifier = (); + type ReserveIdentifier = [u8; 8]; type WeightInfo = (); } @@ -414,6 +418,13 @@ impl_runtime_apis! { fn metadata() -> OpaqueMetadata { OpaqueMetadata::new(Runtime::metadata().into()) } + fn metadata_at_version(version: u32) -> Option { + Runtime::metadata_at_version(version) + } + + fn metadata_versions() -> sp_std::vec::Vec { + Runtime::metadata_versions() + } } impl sp_block_builder::BlockBuilder for Runtime { @@ -484,7 +495,6 @@ impl_runtime_apis! { ) -> pallet_transaction_payment::FeeDetails { TransactionPayment::query_fee_details(uxt, len) } - fn query_weight_to_fee(weight: Weight) -> Balance { TransactionPayment::weight_to_fee(weight) } @@ -508,7 +518,6 @@ impl_runtime_apis! { ) -> pallet_transaction_payment::FeeDetails { TransactionPayment::query_call_fee_details(call, len) } - fn query_weight_to_fee(weight: Weight) -> Balance { TransactionPayment::weight_to_fee(weight) } @@ -536,8 +545,6 @@ impl_runtime_apis! { signature_check: bool, select: frame_try_runtime::TryStateSelect, ) -> Weight { - // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to - // have a backtrace here. Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap() } } diff --git a/runtimes/base/src/xcm_config.rs b/runtimes/base/src/xcm_config.rs index ea8c1a842..ab1307a1b 100644 --- a/runtimes/base/src/xcm_config.rs +++ b/runtimes/base/src/xcm_config.rs @@ -15,8 +15,8 @@ // along with this program. If not, see . use super::{ - AccountId, AllPalletsWithSystem, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, - Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, + AccountId, AllPalletsWithSystem, Balances, EnsureRoot, ParachainInfo, ParachainSystem, + PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, }; use frame_support::{ match_types, parameter_types, @@ -169,6 +169,7 @@ parameter_types! { } impl pallet_xcm::Config for Runtime { + type AdminOrigin = EnsureRoot; type RuntimeEvent = RuntimeEvent; type SendXcmOrigin = EnsureXcmOrigin; type XcmRouter = XcmRouter; diff --git a/runtimes/shared-configuration/src/weights/mod.rs b/runtimes/shared-configuration/src/weights/mod.rs index 68cc6b5f3..ea1fd8720 100644 --- a/runtimes/shared-configuration/src/weights/mod.rs +++ b/runtimes/shared-configuration/src/weights/mod.rs @@ -59,5 +59,6 @@ parameter_types! { pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * RuntimeBlockWeights::get().max_block; + pub MaxCollectivesProposalWeight: Weight = Perbill::from_percent(50) * RuntimeBlockWeights::get().max_block; pub const MaxScheduledPerBlock: u32 = 50; } diff --git a/runtimes/standalone/Cargo.toml b/runtimes/standalone/Cargo.toml index 9faf0e20e..1287744a3 100644 --- a/runtimes/standalone/Cargo.toml +++ b/runtimes/standalone/Cargo.toml @@ -31,6 +31,7 @@ sp-session.workspace = true sp-std.workspace = true sp-transaction-pool.workspace = true sp-version.workspace = true +sp-consensus-grandpa.workspace = true # FRAME pallet-aura.workspace = true @@ -66,6 +67,7 @@ hex-literal = { workspace = true, optional = true } # Local Dependencies pallet-funding.workspace = true +shared-configuration.workspace = true [build-dependencies] substrate-wasm-builder.workspace = true @@ -112,6 +114,8 @@ std = [ "pallet-authorship/std", "pallet-insecure-randomness-collective-flip/std", "pallet-vesting/std", + "shared-configuration/std", + "sp-consensus-grandpa/std" ] runtime-benchmarks = [ diff --git a/runtimes/standalone/src/lib.rs b/runtimes/standalone/src/lib.rs index 039fd3a3b..646c294fe 100644 --- a/runtimes/standalone/src/lib.rs +++ b/runtimes/standalone/src/lib.rs @@ -42,9 +42,7 @@ use frame_system::EnsureSigned; pub use frame_system::{Call as SystemCall, EnsureRoot}; pub use pallet_balances::Call as BalancesCall; use pallet_funding::{BondType, Multiplier as FundingMultiplier}; -use pallet_grandpa::{ - fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, -}; +use pallet_grandpa::AuthorityId as GrandpaId; pub use pallet_timestamp::Call as TimestampCall; use pallet_transaction_payment::{ConstFeeMultiplier, CurrencyAdapter, Multiplier}; use sp_api::impl_runtime_apis; @@ -67,6 +65,16 @@ use sp_std::prelude::*; use sp_version::NativeVersion; use sp_version::RuntimeVersion; +pub use shared_configuration::{ + assets::*, + currency::{vesting::*, *}, + fee::*, + funding::*, + governance::*, + staking::*, + weights::*, +}; + // Make the WASM binary available. #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); @@ -256,46 +264,35 @@ impl pallet_aura::Config for Runtime { impl pallet_grandpa::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type KeyOwnerProofSystem = (); - - type KeyOwnerProof = - >::Proof; - - type KeyOwnerIdentification = >::IdentificationTuple; - - type HandleEquivocation = (); - type WeightInfo = (); type MaxAuthorities = ConstU32<32>; - type MaxSetIdSessionEntries = (); + type MaxSetIdSessionEntries = ConstU64<0>; + + type KeyOwnerProof = sp_core::Void; + type EquivocationReportSystem = (); } impl pallet_timestamp::Config for Runtime { - /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; + type MinimumPeriod = MinimumPeriod; type WeightInfo = (); } -/// Existential deposit. -pub const EXISTENTIAL_DEPOSIT: u128 = 500; - impl pallet_balances::Config for Runtime { - type MaxLocks = ConstU32<50>; - type MaxReserves = ConstU32<50>; - type ReserveIdentifier = BondType; - /// The type for recording an account's balance. + type MaxLocks = MaxLocks; type Balance = Balance; - /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; type DustRemoval = (); - type ExistentialDeposit = ConstU128; + type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; - type WeightInfo = pallet_balances::weights::SubstrateWeight; + type MaxReserves = MaxReserves; + type MaxHolds = MaxLocks; + type MaxFreezes = MaxReserves; + type HoldIdentifier = (); + type FreezeIdentifier = (); + type ReserveIdentifier = BondType; + type WeightInfo = (); } parameter_types! { @@ -316,25 +313,6 @@ impl pallet_sudo::Config for Runtime { type RuntimeCall = RuntimeCall; } -pub const fn deposit(items: u32, bytes: u32) -> Balance { - items as Balance * 15 * MICRO_PLMC + (bytes as Balance) * 6 * MICRO_PLMC -} - -pub const fn free_deposit() -> Balance { - 0 * MICRO_PLMC -} - -parameter_types! { - pub const AssetDeposit: Balance = PLMC; // 1 UNIT deposit to create asset - pub const ApprovalDeposit: Balance = EXISTENTIAL_DEPOSIT; - pub const AssetAccountDeposit: Balance = deposit(1, 16); - pub const AssetsStringLimit: u32 = 50; - /// Key = 32 bytes, Value = 36 bytes (32+1+1+1+1) - // https://github.com/paritytech/substrate/blob/069917b/frame/assets/src/lib.rs#L257L271 - pub const MetadataDepositBase: Balance = free_deposit(); - pub const MetadataDepositPerByte: Balance = free_deposit(); -} - impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; @@ -346,7 +324,7 @@ impl pallet_assets::Config for Runtime { type AssetDeposit = AssetDeposit; type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type ApprovalDeposit = ApprovalDeposit; + type ApprovalDeposit = ExistentialDeposit; type StringLimit = AssetsStringLimit; type Freezer = (); type Extra = (); @@ -428,6 +406,7 @@ impl pallet_collective::Config for Runtime { type DefaultVote = pallet_collective::PrimeDefaultVote; type WeightInfo = pallet_collective::weights::SubstrateWeight; type SetMembersOrigin = EnsureRoot; + type MaxProposalWeight = MaxCollectivesProposalWeight; } parameter_types! { @@ -447,6 +426,7 @@ impl pallet_collective::Config for Runtime { type DefaultVote = pallet_collective::PrimeDefaultVote; type WeightInfo = pallet_collective::weights::SubstrateWeight; type SetMembersOrigin = EnsureRoot; + type MaxProposalWeight = MaxCollectivesProposalWeight; } parameter_types! { @@ -683,6 +663,14 @@ impl_runtime_apis! { fn metadata() -> OpaqueMetadata { OpaqueMetadata::new(Runtime::metadata().into()) } + + fn metadata_at_version(version: u32) -> Option { + Runtime::metadata_at_version(version) + } + + fn metadata_versions() -> sp_std::vec::Vec { + Runtime::metadata_versions() + } } impl sp_block_builder::BlockBuilder for Runtime { @@ -744,29 +732,29 @@ impl_runtime_apis! { } } - impl fg_primitives::GrandpaApi for Runtime { - fn grandpa_authorities() -> GrandpaAuthorityList { + impl sp_consensus_grandpa::GrandpaApi for Runtime { + fn grandpa_authorities() -> sp_consensus_grandpa::AuthorityList { Grandpa::grandpa_authorities() } - fn current_set_id() -> fg_primitives::SetId { + fn current_set_id() -> sp_consensus_grandpa::SetId { Grandpa::current_set_id() } fn submit_report_equivocation_unsigned_extrinsic( - _equivocation_proof: fg_primitives::EquivocationProof< + _equivocation_proof: sp_consensus_grandpa::EquivocationProof< ::Hash, NumberFor, >, - _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof, + _key_owner_proof: sp_consensus_grandpa::OpaqueKeyOwnershipProof, ) -> Option<()> { None } fn generate_key_ownership_proof( - _set_id: fg_primitives::SetId, + _set_id: sp_consensus_grandpa::SetId, _authority_id: GrandpaId, - ) -> Option { + ) -> Option { // NOTE: this is the only implementation possible since we've // defined our key owner proof type as a bottom type (i.e. a type // with no values). @@ -830,9 +818,10 @@ impl_runtime_apis! { Vec, Vec, ) { - use frame_benchmarking::{Benchmarking, BenchmarkList}; + use frame_benchmarking::{baseline, Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; + use baseline::Pallet as BaselineBench; let mut list = Vec::::new(); list_benchmarks!(list, extra); @@ -848,6 +837,7 @@ impl_runtime_apis! { use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch, TrackedStorageKey}; use frame_system_benchmarking::Pallet as SystemBench; + use baseline::Pallet as BaselineBench; impl frame_system_benchmarking::Config for Runtime {} impl baseline::Config for Runtime {} @@ -863,37 +853,35 @@ impl_runtime_apis! { } } - #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { - fn on_runtime_upgrade() -> (Weight, Weight) { + fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to // have a backtrace here. If any of the pre/post migration checks fail, we shall stop // right here and right now. - let weight = Executive::try_runtime_upgrade().unwrap(); + let weight = Executive::try_runtime_upgrade(checks).unwrap(); (weight, BlockWeights::get().max_block) } fn execute_block( block: Block, state_root_check: bool, + signature_check: bool, select: frame_try_runtime::TryStateSelect ) -> Weight { // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to // have a backtrace here. - Executive::try_execute_block(block, state_root_check, select).expect("execute-block failed") + Executive::try_execute_block(block, state_root_check, signature_check, select).expect("execute-block failed") } } } #[cfg(test)] mod tests { - use std::collections::HashSet; - + use super::*; use frame_support::traits::WhitelistedStorageKeys; use sp_core::hexdisplay::HexDisplay; - - use super::*; + use std::collections::HashSet; #[test] fn check_whitelist() { diff --git a/runtimes/testnet/src/lib.rs b/runtimes/testnet/src/lib.rs index 7531aa8c2..d1b240b85 100644 --- a/runtimes/testnet/src/lib.rs +++ b/runtimes/testnet/src/lib.rs @@ -218,13 +218,17 @@ impl pallet_authorship::Config for Runtime { } impl pallet_balances::Config for Runtime { + type MaxLocks = MaxLocks; type Balance = Balance; - type DustRemoval = Treasury; type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; - type MaxLocks = MaxLocks; type MaxReserves = MaxReserves; + type MaxHolds = MaxLocks; + type MaxFreezes = MaxReserves; + type HoldIdentifier = (); + type FreezeIdentifier = (); type ReserveIdentifier = BondType; type WeightInfo = (); } @@ -373,6 +377,7 @@ impl pallet_collective::Config for Runtime { type DefaultVote = pallet_collective::PrimeDefaultVote; type WeightInfo = pallet_collective::weights::SubstrateWeight; type SetMembersOrigin = EnsureRoot; + type MaxProposalWeight = MaxCollectivesProposalWeight; } type TechnicalCollective = pallet_collective::Instance2; @@ -386,6 +391,7 @@ impl pallet_collective::Config for Runtime { type DefaultVote = pallet_collective::PrimeDefaultVote; type WeightInfo = pallet_collective::weights::SubstrateWeight; type SetMembersOrigin = EnsureRoot; + type MaxProposalWeight = MaxCollectivesProposalWeight; } impl pallet_democracy::Config for Runtime { @@ -665,6 +671,13 @@ impl_runtime_apis! { fn metadata() -> OpaqueMetadata { OpaqueMetadata::new(Runtime::metadata().into()) } + fn metadata_at_version(version: u32) -> Option { + Runtime::metadata_at_version(version) + } + + fn metadata_versions() -> sp_std::vec::Vec { + Runtime::metadata_versions() + } } impl sp_block_builder::BlockBuilder for Runtime { @@ -735,11 +748,9 @@ impl_runtime_apis! { ) -> pallet_transaction_payment::FeeDetails { TransactionPayment::query_fee_details(uxt, len) } - fn query_weight_to_fee(weight: Weight) -> Balance { TransactionPayment::weight_to_fee(weight) } - fn query_length_to_fee(length: u32) -> Balance { TransactionPayment::length_to_fee(length) } @@ -760,15 +771,12 @@ impl_runtime_apis! { ) -> pallet_transaction_payment::FeeDetails { TransactionPayment::query_call_fee_details(call, len) } - fn query_weight_to_fee(weight: Weight) -> Balance { TransactionPayment::weight_to_fee(weight) } - fn query_length_to_fee(length: u32) -> Balance { TransactionPayment::length_to_fee(length) } - } impl cumulus_primitives_core::CollectCollationInfo for Runtime { @@ -779,21 +787,18 @@ impl_runtime_apis! { #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { - fn on_runtime_upgrade() -> (Weight, Weight) { - log::info!("try-runtime::on_runtime_upgrade statemine."); - let weight = Executive::try_runtime_upgrade().unwrap(); + fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { + let weight = Executive::try_runtime_upgrade(checks).unwrap(); (weight, RuntimeBlockWeights::get().max_block) } - fn execute_block(block: Block, state_root_check: bool, select: frame_try_runtime::TryStateSelect) -> Weight { - log::info!( - target: "runtime::statemine", "try-runtime: executing block #{} ({:?}) / root checks: {:?} / sanity-checks: {:?}", - block.header.number, - block.header.hash(), - state_root_check, - select, - ); - Executive::try_execute_block(block, state_root_check, select).expect("try_execute_block failed") + fn execute_block( + block: Block, + state_root_check: bool, + signature_check: bool, + select: frame_try_runtime::TryStateSelect, + ) -> Weight { + Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap() } } @@ -803,7 +808,6 @@ impl_runtime_apis! { Vec, Vec, ) { - use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; @@ -819,7 +823,7 @@ impl_runtime_apis! { fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey}; + use frame_benchmarking::{Benchmarking, BenchmarkBatch}; use frame_system_benchmarking::Pallet as SystemBench; impl frame_system_benchmarking::Config for Runtime {} @@ -827,25 +831,14 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} - let whitelist: Vec = vec![ - // Block Number - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), - // Total Issuance - hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(), - // Execution Phase - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(), - // Event Count - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(), - // System Events - hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(), - //TODO: use from relay_well_known_keys::ACTIVE_CONFIG - hex_literal::hex!("06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385").to_vec().into(), - ]; + use frame_support::traits::WhitelistedStorageKeys; + let whitelist = AllPalletsWithSystem::whitelisted_storage_keys(); let mut batches = Vec::::new(); let params = (&config, &whitelist); add_benchmarks!(params, batches); + if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) } } diff --git a/runtimes/testnet/src/xcm_config.rs b/runtimes/testnet/src/xcm_config.rs index b450763d1..75b876ee7 100644 --- a/runtimes/testnet/src/xcm_config.rs +++ b/runtimes/testnet/src/xcm_config.rs @@ -26,7 +26,7 @@ use core::marker::PhantomData; use frame_support::{ match_types, parameter_types, traits::{ - fungibles::{self, Balanced, CreditOf}, + fungibles::{self, Balanced, Credit}, ConstU32, Contains, ContainsPair, Everything, Get, Nothing, }, weights::Weight, @@ -53,7 +53,7 @@ use xcm_executor::{ }; use super::{ - AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Balance, Balances, + AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Balance, Balances, EnsureRoot, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, StatemintAssets, WeightToFee, XcmpQueue, }; @@ -154,7 +154,7 @@ impl< ConvertedConcreteId::::matches_fungibles( a, ) - .map_err(|_| Error::AssetNotFound) + .map_err(|_| Error::AssetNotHandled) } } @@ -303,7 +303,7 @@ where R: pallet_authorship::Config + pallet_assets::Config, AccountIdOf: From + Into, { - fn handle_credit(credit: CreditOf, pallet_assets::Pallet>) { + fn handle_credit(credit: Credit, pallet_assets::Pallet>) { if let Some(author) = pallet_authorship::Pallet::::author() { // In case of error: Will drop the result triggering the `OnDrop` of the imbalance. let _ = pallet_assets::Pallet::::resolve(&author, credit); @@ -437,6 +437,7 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<8>; type WeightInfo = pallet_xcm::TestWeightInfo; + type AdminOrigin = EnsureRoot; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index f805bace5..084fd8d11 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2022-11-15" +channel = "1.69.0" components = [ "rustfmt", "clippy" ] targets = [ "wasm32-unknown-unknown" ] \ No newline at end of file From 272b76014d67ceb95db285788a21de625d9252b2 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 14 Jul 2023 11:55:54 +0200 Subject: [PATCH 35/80] feat: add parachain staking --- Cargo.lock | 47 +- Cargo.toml | 3 +- pallets/parachain-staking/Cargo.toml | 49 + pallets/parachain-staking/README.md | 30 + pallets/parachain-staking/migrations.md | 42 + .../parachain-staking/src/auto_compound.rs | 368 + pallets/parachain-staking/src/benchmarks.rs | 1483 ++++ .../src/delegation_requests.rs | 653 ++ pallets/parachain-staking/src/inflation.rs | 208 + pallets/parachain-staking/src/lib.rs | 2011 +++++ pallets/parachain-staking/src/migrations.rs | 17 + pallets/parachain-staking/src/mock.rs | 1008 +++ pallets/parachain-staking/src/set.rs | 89 + pallets/parachain-staking/src/tests.rs | 6934 +++++++++++++++++ pallets/parachain-staking/src/traits.rs | 66 + pallets/parachain-staking/src/types.rs | 1627 ++++ pallets/parachain-staking/src/weights.rs | 1418 ++++ 17 files changed, 16050 insertions(+), 3 deletions(-) create mode 100644 pallets/parachain-staking/Cargo.toml create mode 100644 pallets/parachain-staking/README.md create mode 100644 pallets/parachain-staking/migrations.md create mode 100644 pallets/parachain-staking/src/auto_compound.rs create mode 100644 pallets/parachain-staking/src/benchmarks.rs create mode 100644 pallets/parachain-staking/src/delegation_requests.rs create mode 100644 pallets/parachain-staking/src/inflation.rs create mode 100644 pallets/parachain-staking/src/lib.rs create mode 100644 pallets/parachain-staking/src/migrations.rs create mode 100644 pallets/parachain-staking/src/mock.rs create mode 100644 pallets/parachain-staking/src/set.rs create mode 100644 pallets/parachain-staking/src/tests.rs create mode 100644 pallets/parachain-staking/src/traits.rs create mode 100644 pallets/parachain-staking/src/types.rs create mode 100644 pallets/parachain-staking/src/weights.rs diff --git a/Cargo.lock b/Cargo.lock index 2faa2f1ea..07b6234cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -755,6 +755,17 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" +[[package]] +name = "bstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "lazy_static", + "memchr", + "regex-automata 0.1.10", +] + [[package]] name = "bstr" version = "1.6.0" @@ -3331,7 +3342,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1391ab1f92ffcc08911957149833e682aa3fe252b9f45f966d2ef972274c97df" dependencies = [ "aho-corasick", - "bstr", + "bstr 1.6.0", "fnv", "log", "regex", @@ -6229,17 +6240,23 @@ dependencies = [ [[package]] name = "pallet-parachain-staking" version = "3.0.0" -source = "git+https://gitlab.com/Omegabit/stake-patch?branch=0.9.42#a9b481bf9f658f45db37fa9c8e26f31d41550518" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", "log", + "pallet-aura", "pallet-authorship", + "pallet-balances", "pallet-session", + "pallet-timestamp", "parity-scale-codec", "scale-info", "serde", + "similar-asserts", + "sp-consensus-aura", + "sp-core", + "sp-io", "sp-runtime", "sp-staking", "sp-std", @@ -11113,6 +11130,26 @@ dependencies = [ "wide", ] +[[package]] +name = "similar" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" +dependencies = [ + "bstr 0.2.17", + "unicode-segmentation", +] + +[[package]] +name = "similar-asserts" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbf644ad016b75129f01a34a355dcb8d66a5bc803e417c7a77cc5d5ee9fa0f18" +dependencies = [ + "console", + "similar", +] + [[package]] name = "siphasher" version = "0.3.10" @@ -13012,6 +13049,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + [[package]] name = "unicode-width" version = "0.1.10" diff --git a/Cargo.toml b/Cargo.toml index f63ca7de0..2bb3e5a8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,13 +46,14 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran # Internal pallets (with default disabled) pallet-funding = { path = "pallets/funding", default-features = false } pallet-sandbox = { path = "pallets/sandbox", default-features = false } -pallet-parachain-staking = { git = "https://gitlab.com/Omegabit/stake-patch", default-features = false, branch = "0.9.42"} +pallet-parachain-staking = { path = "pallets/parachain-staking", default-features = false} # Internal support (with default disabled) shared-configuration = { path = "runtimes/shared-configuration", default-features = false } # External support (with default disabled) +substrate-fixed = { git = "https://github.com/encointer/substrate-fixed", default-features = false } # dip-support = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } # kilt-support = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } # kilt-dip-support = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } diff --git a/pallets/parachain-staking/Cargo.toml b/pallets/parachain-staking/Cargo.toml new file mode 100644 index 000000000..ef13ae5e2 --- /dev/null +++ b/pallets/parachain-staking/Cargo.toml @@ -0,0 +1,49 @@ +[package] +name = "pallet-parachain-staking" +description = "parachain staking pallet for collator selection and reward distribution" +edition = "2021" +version = "3.0.0" + +[dependencies] +serde = { version = "1", default-features = false, optional = true } +log = "0.4" + +# Substrate +frame-benchmarking = { workspace = true, optional = true } +frame-support.workspace = true +frame-system.workspace = true +parity-scale-codec.workspace = true +scale-info.workspace = true +sp-runtime.workspace = true +sp-std.workspace = true +substrate-fixed.workspace = true +sp-staking.workspace = true +pallet-authorship.workspace = true +pallet-session.workspace = true + +[dev-dependencies] +pallet-balances.workspace = true +pallet-aura.workspace = true +pallet-timestamp.workspace = true +similar-asserts = "1.1.0" +sp-core.workspace = true +sp-io.workspace = true +sp-consensus-aura.workspace = true + +[features] +default = ["std"] +std = [ + "frame-benchmarking?/std", + "frame-support/std", + "frame-system/std", + "parity-scale-codec/std", + "scale-info/std", + "serde/std", + "sp-runtime/std", + "sp-std/std", + "sp-staking/std", + "pallet-authorship/std", + "pallet-session/std", +] +runtime-benchmarks = ["frame-benchmarking"] +try-runtime = ["frame-support/try-runtime"] diff --git a/pallets/parachain-staking/README.md b/pallets/parachain-staking/README.md new file mode 100644 index 000000000..78afd35c0 --- /dev/null +++ b/pallets/parachain-staking/README.md @@ -0,0 +1,30 @@ +# DPoS Pallet for Parachain Staking + +## Polimec Changes + + + +## Formatting Rules + +- dependencies in alphabetical order in the `Cargo.toml` and at the top of each file +- prefer explicit imports to glob import syntax i.e. prefer `use::crate::{Ex1, Ex2, ..};` to `use super::*;` + +## Description + +Implements Delegated Proof of Stake to + +1. select the active set of eligible block producers +2. reward block authors +3. enable delegators and collators to participate in inflationary rewards + +Links: + +- [Rust Documentation](https://purestake.github.io/moonbeam/pallet_parachain_staking/index.html) +- [Unofficial Documentation](https://meta5.world/parachain-staking-docs/) +- [(Outdated) Blog Post with Justification](https://meta5.world/posts/parachain-staking) + +## History + +Since January 2021, Moonbeam's team has maintained this Delegated Proof of Stake (DPoS) pallet designed specifically for parachains. + +Since April 2021, the development of this pallet has been supported by [a Web3 Foundation grant](https://github.com/w3f/Grants-Program/pull/389). The [first milestone](https://github.com/w3f/Grant-Milestone-Delivery/pull/218) was approved in June 2021. diff --git a/pallets/parachain-staking/migrations.md b/pallets/parachain-staking/migrations.md new file mode 100644 index 000000000..d2277ffcd --- /dev/null +++ b/pallets/parachain-staking/migrations.md @@ -0,0 +1,42 @@ +# Migration History + +## Calculate outgoing rewards based on pending revoke and decrease changes + +- [Migration PR `#1408`](https://github.com/PureStake/moonbeam/pull/1408) + +## Patch delegations total mismatch + +- [Migration PR `#1291`](https://github.com/PureStake/moonbeam/pull/1291) + +## Split candidate state for PoV optimization + +- [Migration PR `#1117`](https://github.com/PureStake/moonbeam/pull/1117) + +## Increase max delegations per candidate + +- [Migration PR `#1096`](https://github.com/PureStake/moonbeam/pull/1096) +- [Migratio bugfix `#1112`](https://github.com/PureStake/moonbeam/pull/1112) + +## Manual Exits and Patch Lack of Delay for bond\_{more, less} + +- [Migration PR `#810`](https://github.com/PureStake/moonbeam/pull/810) +- [Migration Removal PR `#?`]() + +## Purge Stale Storage + +- [Migration PR `#970`](https://github.com/PureStake/moonbeam/pull/970) + +## Delay nominator exits by changing NominatorState and ExitQueue + +- [Migration PR `#610`](https://github.com/PureStake/moonbeam/pull/610) +- [Migration Removal PR `#662`](https://github.com/PureStake/moonbeam/pull/662) + +## Patch nomination DOS attack vector by changing CollatorState + +- [Migration PR `#505`](https://github.com/PureStake/moonbeam/pull/505) +- [Migration Removal PR `#553`](https://github.com/PureStake/moonbeam/pull/553) + +## Patch underflow bug and correct Total storage item + +- [Migration PR `#502`](https://github.com/PureStake/moonbeam/pull/502) +- [Migration Removal PR `#553`](https://github.com/PureStake/moonbeam/pull/553) diff --git a/pallets/parachain-staking/src/auto_compound.rs b/pallets/parachain-staking/src/auto_compound.rs new file mode 100644 index 000000000..830c4c077 --- /dev/null +++ b/pallets/parachain-staking/src/auto_compound.rs @@ -0,0 +1,368 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Auto-compounding functionality for staking rewards + +use crate::{ + pallet::{ + AddGet, AutoCompoundingDelegations as AutoCompoundingDelegationsStorage, BalanceOf, + CandidateInfo, Config, DelegatorState, Error, Event, Pallet, Total, + }, + types::{Bond, BondAdjust, Delegator}, +}; +use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, traits::Get, RuntimeDebug}; +use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; +use sp_runtime::{traits::Saturating, BoundedVec, Percent}; +use sp_std::prelude::*; + +/// Represents the auto-compounding amount for a delegation. +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, PartialOrd, Ord)] +pub struct AutoCompoundConfig { + pub delegator: AccountId, + pub value: Percent, +} + +/// Represents the auto-compounding [Delegations] for `T: Config` +#[derive(Clone, Eq, PartialEq, RuntimeDebug)] +pub struct AutoCompoundDelegations( + BoundedVec< + AutoCompoundConfig, + AddGet, + >, +); + +impl AutoCompoundDelegations +where + T: Config, +{ + /// Creates a new instance of [AutoCompoundingDelegations] from a vector of sorted_delegations. + /// This is used for testing purposes only. + #[cfg(test)] + pub fn new( + sorted_delegations: BoundedVec< + AutoCompoundConfig, + AddGet, + >, + ) -> Self { + Self(sorted_delegations) + } + + /// Retrieves an instance of [AutoCompoundingDelegations] storage as [AutoCompoundDelegations]. + pub fn get_storage(candidate: &T::AccountId) -> Self { + Self(>::get(candidate)) + } + + /// Inserts the current state to [AutoCompoundingDelegations] storage. + pub fn set_storage(self, candidate: &T::AccountId) { + >::insert(candidate, self.0) + } + + /// Retrieves the auto-compounding value for a delegation. The `delegations_config` must be a + /// sorted vector for binary_search to work. + pub fn get_for_delegator(&self, delegator: &T::AccountId) -> Option { + match self.0.binary_search_by(|d| d.delegator.cmp(delegator)) { + Ok(index) => Some(self.0[index].value), + Err(_) => None, + } + } + + /// Sets the auto-compounding value for a delegation. The `delegations_config` must be a sorted + /// vector for binary_search to work. + pub fn set_for_delegator( + &mut self, + delegator: T::AccountId, + value: Percent, + ) -> Result> { + match self.0.binary_search_by(|d| d.delegator.cmp(&delegator)) { + Ok(index) => + if self.0[index].value == value { + Ok(false) + } else { + self.0[index].value = value; + Ok(true) + }, + Err(index) => { + self.0 + .try_insert(index, AutoCompoundConfig { delegator, value }) + .map_err(|_| Error::::ExceedMaxDelegationsPerDelegator)?; + Ok(true) + }, + } + } + + /// Removes the auto-compounding value for a delegation. + /// Returns `true` if the entry was removed, `false` otherwise. The `delegations_config` must be a + /// sorted vector for binary_search to work. + pub fn remove_for_delegator(&mut self, delegator: &T::AccountId) -> bool { + match self.0.binary_search_by(|d| d.delegator.cmp(delegator)) { + Ok(index) => { + self.0.remove(index); + true + }, + Err(_) => false, + } + } + + /// Returns the length of the inner vector. + pub fn len(&self) -> u32 { + self.0.len() as u32 + } + + /// Returns a reference to the inner vector. + #[cfg(test)] + pub fn inner( + &self, + ) -> &BoundedVec< + AutoCompoundConfig, + AddGet, + > { + &self.0 + } + + /// Converts the [AutoCompoundDelegations] into the inner vector. + #[cfg(test)] + pub fn into_inner( + self, + ) -> BoundedVec< + AutoCompoundConfig, + AddGet, + > { + self.0 + } + + // -- pallet functions -- + + /// Delegates and sets the auto-compounding config. The function skips inserting auto-compound + /// storage and validation, if the auto-compound value is 0%. + pub(crate) fn delegate_with_auto_compound( + candidate: T::AccountId, + delegator: T::AccountId, + amount: BalanceOf, + auto_compound: Percent, + candidate_delegation_count_hint: u32, + candidate_auto_compounding_delegation_count_hint: u32, + delegation_count_hint: u32, + ) -> DispatchResultWithPostInfo { + // check that caller can lock the amount before any changes to storage + ensure!( + >::get_delegator_stakable_free_balance(&delegator) >= amount, + Error::::InsufficientBalance + ); + + let mut delegator_state = if let Some(mut state) = >::get(&delegator) { + // delegation after first + ensure!(amount >= T::MinDelegation::get(), Error::::DelegationBelowMin); + ensure!( + delegation_count_hint >= state.delegations.0.len() as u32, + Error::::TooLowDelegationCountToDelegate + ); + ensure!( + (state.delegations.0.len() as u32) < T::MaxDelegationsPerDelegator::get(), + Error::::ExceedMaxDelegationsPerDelegator + ); + ensure!( + state.add_delegation(Bond { owner: candidate.clone(), amount }), + Error::::AlreadyDelegatedCandidate + ); + state + } else { + // first delegation + ensure!(amount >= T::MinDelegatorStk::get(), Error::::DelegatorBondBelowMin); + ensure!(!>::is_candidate(&delegator), Error::::CandidateExists); + Delegator::new(delegator.clone(), candidate.clone(), amount) + }; + let mut candidate_state = + >::get(&candidate).ok_or(Error::::CandidateDNE)?; + ensure!( + candidate_delegation_count_hint >= candidate_state.delegation_count, + Error::::TooLowCandidateDelegationCountToDelegate + ); + + let auto_compounding_state = if !auto_compound.is_zero() { + let auto_compounding_state = Self::get_storage(&candidate); + ensure!( + auto_compounding_state.len() <= candidate_auto_compounding_delegation_count_hint, + >::TooLowCandidateAutoCompoundingDelegationCountToDelegate, + ); + Some(auto_compounding_state) + } else { + None + }; + + // add delegation to candidate + let (delegator_position, less_total_staked) = candidate_state + .add_delegation::(&candidate, Bond { owner: delegator.clone(), amount })?; + + // lock delegator amount + delegator_state.adjust_bond_lock::(BondAdjust::Increase(amount))?; + + // adjust total locked, + // only is_some if kicked the lowest bottom as a consequence of this new delegation + let net_total_increase = + if let Some(less) = less_total_staked { amount.saturating_sub(less) } else { amount }; + let new_total_locked = >::get().saturating_add(net_total_increase); + + // maybe set auto-compound config, state is Some if the percent is non-zero + if let Some(mut state) = auto_compounding_state { + state.set_for_delegator(delegator.clone(), auto_compound)?; + state.set_storage(&candidate); + } + + >::put(new_total_locked); + >::insert(&candidate, candidate_state); + >::insert(&delegator, delegator_state); + >::deposit_event(Event::Delegation { + delegator, + locked_amount: amount, + candidate, + delegator_position, + auto_compound, + }); + + Ok(().into()) + } + + /// Sets the auto-compounding value for a delegation. The config is removed if value is zero. + pub(crate) fn set_auto_compound( + candidate: T::AccountId, + delegator: T::AccountId, + value: Percent, + candidate_auto_compounding_delegation_count_hint: u32, + delegation_count_hint: u32, + ) -> DispatchResultWithPostInfo { + let delegator_state = + >::get(&delegator).ok_or(>::DelegatorDNE)?; + ensure!( + delegator_state.delegations.0.len() <= delegation_count_hint as usize, + >::TooLowDelegationCountToAutoCompound, + ); + ensure!( + delegator_state.delegations.0.iter().any(|b| b.owner == candidate), + >::DelegationDNE, + ); + + let mut auto_compounding_state = Self::get_storage(&candidate); + ensure!( + auto_compounding_state.len() <= candidate_auto_compounding_delegation_count_hint, + >::TooLowCandidateAutoCompoundingDelegationCountToAutoCompound, + ); + let state_updated = if value.is_zero() { + auto_compounding_state.remove_for_delegator(&delegator) + } else { + auto_compounding_state.set_for_delegator(delegator.clone(), value)? + }; + if state_updated { + auto_compounding_state.set_storage(&candidate); + } + + >::deposit_event(Event::AutoCompoundSet { candidate, delegator, value }); + + Ok(().into()) + } + + /// Removes the auto-compounding value for a delegation. This should be called when the + /// delegation is revoked to cleanup storage. Storage is only written iff the entry existed. + pub(crate) fn remove_auto_compound(candidate: &T::AccountId, delegator: &T::AccountId) { + let mut auto_compounding_state = Self::get_storage(candidate); + if auto_compounding_state.remove_for_delegator(delegator) { + auto_compounding_state.set_storage(candidate); + } + } + + /// Returns the value of auto-compound, if it exists for a given delegation, zero otherwise. + pub(crate) fn auto_compound(candidate: &T::AccountId, delegator: &T::AccountId) -> Percent { + let delegations_config = Self::get_storage(candidate); + delegations_config.get_for_delegator(delegator).unwrap_or_else(Percent::zero) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mock::Test; + + #[test] + fn test_set_for_delegator_inserts_config_and_returns_true_if_entry_missing() { + let mut delegations_config = + AutoCompoundDelegations::::new(vec![].try_into().expect("must succeed")); + assert_eq!( + true, + delegations_config + .set_for_delegator(1, Percent::from_percent(50)) + .expect("must succeed") + ); + assert_eq!( + vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(50) }], + delegations_config.into_inner().into_inner(), + ); + } + + #[test] + fn test_set_for_delegator_updates_config_and_returns_true_if_entry_changed() { + let mut delegations_config = AutoCompoundDelegations::::new( + vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(10) }] + .try_into() + .expect("must succeed"), + ); + assert_eq!( + true, + delegations_config + .set_for_delegator(1, Percent::from_percent(50)) + .expect("must succeed") + ); + assert_eq!( + vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(50) }], + delegations_config.into_inner().into_inner(), + ); + } + + #[test] + fn test_set_for_delegator_updates_config_and_returns_false_if_entry_unchanged() { + let mut delegations_config = AutoCompoundDelegations::::new( + vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(10) }] + .try_into() + .expect("must succeed"), + ); + assert_eq!( + false, + delegations_config + .set_for_delegator(1, Percent::from_percent(10)) + .expect("must succeed") + ); + assert_eq!( + vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(10) }], + delegations_config.into_inner().into_inner(), + ); + } + + #[test] + fn test_remove_for_delegator_returns_false_if_entry_was_missing() { + let mut delegations_config = + AutoCompoundDelegations::::new(vec![].try_into().expect("must succeed")); + assert_eq!(false, delegations_config.remove_for_delegator(&1),); + } + + #[test] + fn test_remove_delegation_config_returns_true_if_entry_existed() { + let mut delegations_config = AutoCompoundDelegations::::new( + vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(10) }] + .try_into() + .expect("must succeed"), + ); + assert_eq!(true, delegations_config.remove_for_delegator(&1)); + } +} diff --git a/pallets/parachain-staking/src/benchmarks.rs b/pallets/parachain-staking/src/benchmarks.rs new file mode 100644 index 000000000..0f8ba8ad6 --- /dev/null +++ b/pallets/parachain-staking/src/benchmarks.rs @@ -0,0 +1,1483 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +#![cfg(feature = "runtime-benchmarks")] + +//! Benchmarking +use crate::{ + AwardedPts, BalanceOf, Call, CandidateBondLessRequest, Config, DelegationAction, Pallet, + ParachainBondConfig, ParachainBondInfo, Points, Range, RewardPayment, Round, ScheduledRequest, + Staked, TopDelegations, +}; +use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, vec}; +use frame_support::traits::{Currency, Get, OnFinalize, OnInitialize}; +use frame_system::RawOrigin; +use sp_runtime::{Perbill, Percent}; +use sp_std::vec::Vec; + +/// Minimum collator candidate stake +fn min_candidate_stk() -> BalanceOf { + <::MinCandidateStk as Get>>::get() +} + +/// Minimum delegator stake +fn min_delegator_stk() -> BalanceOf { + <::MinDelegatorStk as Get>>::get() +} + +/// Create a funded user. +/// Extra + min_candidate_stk is total minted funds +/// Returns tuple (id, balance) +fn create_funded_user( + string: &'static str, + n: u32, + extra: BalanceOf, +) -> (T::AccountId, BalanceOf) { + const SEED: u32 = 0; + let user = account(string, n, SEED); + let min_candidate_stk = min_candidate_stk::(); + let total = min_candidate_stk + extra; + T::Currency::make_free_balance_be(&user, total); + T::Currency::issue(total); + (user, total) +} + +/// Create a funded delegator. +fn create_funded_delegator( + string: &'static str, + n: u32, + extra: BalanceOf, + collator: T::AccountId, + min_bond: bool, + collator_delegator_count: u32, +) -> Result { + let (user, total) = create_funded_user::(string, n, extra); + let bond = if min_bond { min_delegator_stk::() } else { total }; + Pallet::::delegate( + RawOrigin::Signed(user.clone()).into(), + collator, + bond, + collator_delegator_count, + 0u32, // first delegation for all calls + )?; + Ok(user) +} + +/// Create a funded collator. +fn create_funded_collator( + string: &'static str, + n: u32, + extra: BalanceOf, + min_bond: bool, + candidate_count: u32, +) -> Result { + let (user, total) = create_funded_user::(string, n, extra); + let bond = if min_bond { min_candidate_stk::() } else { total }; + Pallet::::join_candidates(RawOrigin::Signed(user.clone()).into(), bond, candidate_count)?; + Ok(user) +} + +// Simulate staking on finalize by manually setting points +fn parachain_staking_on_finalize(author: T::AccountId) { + let now = >::get().current; + let score_plus_20 = >::get(now, &author).saturating_add(20); + >::insert(now, author, score_plus_20); + >::mutate(now, |x| *x = x.saturating_add(20)); +} + +/// Run to end block and author +fn roll_to_and_author(round_delay: u32, author: T::AccountId) { + let total_rounds = round_delay + 1u32; + let round_length: T::BlockNumber = Pallet::::round().length.into(); + let mut now = >::block_number() + 1u32.into(); + let end = Pallet::::round().first + (round_length * total_rounds.into()); + while now < end { + parachain_staking_on_finalize::(author.clone()); + >::on_finalize(>::block_number()); + >::set_block_number( + >::block_number() + 1u32.into(), + ); + >::on_initialize(>::block_number()); + Pallet::::on_initialize(>::block_number()); + now += 1u32.into(); + } +} + +const USER_SEED: u32 = 999666; +struct Seed { + pub inner: u32, +} +impl Seed { + fn new() -> Self { + Seed { inner: USER_SEED } + } + + pub fn take(&mut self) -> u32 { + let v = self.inner; + self.inner += 1; + v + } +} + +benchmarks! { + // MONETARY ORIGIN DISPATCHABLES + set_staking_expectations { + let stake_range: Range> = Range { + min: 100u32.into(), + ideal: 200u32.into(), + max: 300u32.into(), + }; + }: _(RawOrigin::Root, stake_range) + verify { + assert_eq!(Pallet::::inflation_config().expect, stake_range); + } + + set_inflation { + let inflation_range: Range = Range { + min: Perbill::from_perthousand(1), + ideal: Perbill::from_perthousand(2), + max: Perbill::from_perthousand(3), + }; + + }: _(RawOrigin::Root, inflation_range) + verify { + assert_eq!(Pallet::::inflation_config().annual, inflation_range); + } + + set_parachain_bond_account { + let parachain_bond_account: T::AccountId = account("TEST", 0u32, USER_SEED); + }: _(RawOrigin::Root, parachain_bond_account.clone()) + verify { + assert_eq!(Pallet::::parachain_bond_info().account, parachain_bond_account); + } + + set_parachain_bond_reserve_percent { + }: _(RawOrigin::Root, Percent::from_percent(33)) + verify { + assert_eq!(Pallet::::parachain_bond_info().percent, Percent::from_percent(33)); + } + + // ROOT DISPATCHABLES + + set_total_selected { + Pallet::::set_blocks_per_round(RawOrigin::Root.into(), 101u32)?; + }: _(RawOrigin::Root, 100u32) + verify { + assert_eq!(Pallet::::total_selected(), 100u32); + } + + set_collator_commission {}: _(RawOrigin::Root, Perbill::from_percent(33)) + verify { + assert_eq!(Pallet::::collator_commission(), Perbill::from_percent(33)); + } + + set_blocks_per_round {}: _(RawOrigin::Root, 1200u32) + verify { + assert_eq!(Pallet::::round().length, 1200u32); + } + + // USER DISPATCHABLES + + join_candidates { + let x in 3..1_000; + // Worst Case Complexity is insertion into an ordered list so \exists full list before call + let mut candidate_count = 1u32; + for i in 2..x { + let seed = USER_SEED - i; + let collator = create_funded_collator::( + "collator", + seed, + 0u32.into(), + true, + candidate_count + )?; + candidate_count += 1u32; + } + let (caller, min_candidate_stk) = create_funded_user::("caller", USER_SEED, 0u32.into()); + }: _(RawOrigin::Signed(caller.clone()), min_candidate_stk, candidate_count) + verify { + assert!(Pallet::::is_candidate(&caller)); + } + + // This call schedules the collator's exit and removes them from the candidate pool + // -> it retains the self-bond and delegator bonds + schedule_leave_candidates { + let x in 3..1_000; + // Worst Case Complexity is removal from an ordered list so \exists full list before call + let mut candidate_count = 1u32; + for i in 2..x { + let seed = USER_SEED - i; + let collator = create_funded_collator::( + "collator", + seed, + 0u32.into(), + true, + candidate_count + )?; + candidate_count += 1u32; + } + let caller: T::AccountId = create_funded_collator::( + "caller", + USER_SEED, + 0u32.into(), + true, + candidate_count, + )?; + candidate_count += 1u32; + }: _(RawOrigin::Signed(caller.clone()), candidate_count) + verify { + assert!(Pallet::::candidate_info(&caller).expect("must exist").is_leaving()); + } + + execute_leave_candidates { + // x is total number of delegations for the candidate + let x in 2..(<::MaxTopDelegationsPerCandidate as Get>::get() + + <::MaxBottomDelegationsPerCandidate as Get>::get()); + let candidate: T::AccountId = create_funded_collator::( + "unique_caller", + USER_SEED - 100, + 0u32.into(), + true, + 1u32, + )?; + // 2nd delegation required for all delegators to ensure DelegatorState updated not removed + let second_candidate: T::AccountId = create_funded_collator::( + "unique__caller", + USER_SEED - 99, + 0u32.into(), + true, + 2u32, + )?; + let mut delegators: Vec = Vec::new(); + let mut col_del_count = 0u32; + for i in 1..x { + let seed = USER_SEED + i; + let delegator = create_funded_delegator::( + "delegator", + seed, + min_delegator_stk::(), + candidate.clone(), + true, + col_del_count, + )?; + Pallet::::delegate( + RawOrigin::Signed(delegator.clone()).into(), + second_candidate.clone(), + min_delegator_stk::(), + col_del_count, + 1u32, + )?; + Pallet::::schedule_revoke_delegation( + RawOrigin::Signed(delegator.clone()).into(), + candidate.clone() + )?; + delegators.push(delegator); + col_del_count += 1u32; + } + Pallet::::schedule_leave_candidates( + RawOrigin::Signed(candidate.clone()).into(), + 3u32 + )?; + roll_to_and_author::(2, candidate.clone()); + }: _(RawOrigin::Signed(candidate.clone()), candidate.clone(), col_del_count) + verify { + assert!(Pallet::::candidate_info(&candidate).is_none()); + assert!(Pallet::::candidate_info(&second_candidate).is_some()); + for delegator in delegators { + assert!(Pallet::::is_delegator(&delegator)); + } + } + + cancel_leave_candidates { + let x in 3..1_000; + // Worst Case Complexity is removal from an ordered list so \exists full list before call + let mut candidate_count = 1u32; + for i in 2..x { + let seed = USER_SEED - i; + let collator = create_funded_collator::( + "collator", + seed, + 0u32.into(), + true, + candidate_count + )?; + candidate_count += 1u32; + } + let caller: T::AccountId = create_funded_collator::( + "caller", + USER_SEED, + 0u32.into(), + true, + candidate_count, + )?; + candidate_count += 1u32; + Pallet::::schedule_leave_candidates( + RawOrigin::Signed(caller.clone()).into(), + candidate_count + )?; + candidate_count -= 1u32; + }: _(RawOrigin::Signed(caller.clone()), candidate_count) + verify { + assert!(Pallet::::candidate_info(&caller).expect("must exist").is_active()); + } + + go_offline { + let caller: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + }: _(RawOrigin::Signed(caller.clone())) + verify { + assert!(!Pallet::::candidate_info(&caller).expect("must exist").is_active()); + } + + go_online { + let caller: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + Pallet::::go_offline(RawOrigin::Signed(caller.clone()).into())?; + }: _(RawOrigin::Signed(caller.clone())) + verify { + assert!(Pallet::::candidate_info(&caller).expect("must exist").is_active()); + } + + candidate_bond_more { + let more = min_candidate_stk::(); + let caller: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + more, + true, + 1u32, + )?; + }: _(RawOrigin::Signed(caller.clone()), more) + verify { + let expected_bond = more * 2u32.into(); + assert_eq!( + Pallet::::candidate_info(&caller).expect("candidate was created, qed").bond, + expected_bond, + ); + } + + schedule_candidate_bond_less { + let min_candidate_stk = min_candidate_stk::(); + let caller: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + min_candidate_stk, + false, + 1u32, + )?; + }: _(RawOrigin::Signed(caller.clone()), min_candidate_stk) + verify { + let state = Pallet::::candidate_info(&caller).expect("request bonded less so exists"); + assert_eq!( + state.request, + Some(CandidateBondLessRequest { + amount: min_candidate_stk, + when_executable: 3, + }) + ); + } + + execute_candidate_bond_less { + let min_candidate_stk = min_candidate_stk::(); + let caller: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + min_candidate_stk, + false, + 1u32, + )?; + Pallet::::schedule_candidate_bond_less( + RawOrigin::Signed(caller.clone()).into(), + min_candidate_stk + )?; + roll_to_and_author::(2, caller.clone()); + }: { + Pallet::::execute_candidate_bond_less( + RawOrigin::Signed(caller.clone()).into(), + caller.clone() + )?; + } verify { + assert_eq!( + Pallet::::candidate_info(&caller).expect("candidate was created, qed").bond, + min_candidate_stk, + ); + } + + cancel_candidate_bond_less { + let min_candidate_stk = min_candidate_stk::(); + let caller: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + min_candidate_stk, + false, + 1u32, + )?; + Pallet::::schedule_candidate_bond_less( + RawOrigin::Signed(caller.clone()).into(), + min_candidate_stk + )?; + }: { + Pallet::::cancel_candidate_bond_less( + RawOrigin::Signed(caller.clone()).into(), + )?; + } verify { + assert!( + Pallet::::candidate_info(&caller).expect("must exist").request.is_none() + ); + } + + delegate { + let x in 3..<::MaxDelegationsPerDelegator as Get>::get(); + let y in 2..<::MaxTopDelegationsPerCandidate as Get>::get(); + // Worst Case is full of delegations before calling `delegate` + let mut collators: Vec = Vec::new(); + // Initialize MaxDelegationsPerDelegator collator candidates + for i in 2..x { + let seed = USER_SEED - i; + let collator = create_funded_collator::( + "collator", + seed, + 0u32.into(), + true, + collators.len() as u32 + 1u32, + )?; + collators.push(collator.clone()); + } + let bond = <::MinDelegatorStk as Get>>::get(); + let extra = if (bond * (collators.len() as u32 + 1u32).into()) > min_candidate_stk::() { + (bond * (collators.len() as u32 + 1u32).into()) - min_candidate_stk::() + } else { + 0u32.into() + }; + let (caller, _) = create_funded_user::("caller", USER_SEED, extra.into()); + // Delegation count + let mut del_del_count = 0u32; + // Nominate MaxDelegationsPerDelegators collator candidates + for col in collators.clone() { + Pallet::::delegate( + RawOrigin::Signed(caller.clone()).into(), col, bond, 0u32, del_del_count + )?; + del_del_count += 1u32; + } + // Last collator to be delegated + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + collators.len() as u32 + 1u32, + )?; + // Worst Case Complexity is insertion into an almost full collator + let mut col_del_count = 0u32; + for i in 1..y { + let seed = USER_SEED + i; + let _ = create_funded_delegator::( + "delegator", + seed, + 0u32.into(), + collator.clone(), + true, + col_del_count, + )?; + col_del_count += 1u32; + } + }: _(RawOrigin::Signed(caller.clone()), collator, bond, col_del_count, del_del_count) + verify { + assert!(Pallet::::is_delegator(&caller)); + } + + schedule_leave_delegators { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); + let bond = <::MinDelegatorStk as Get>>::get(); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + bond, + 0u32, + 0u32 + )?; + }: _(RawOrigin::Signed(caller.clone())) + verify { + assert!( + Pallet::::delegation_scheduled_requests(&collator) + .iter() + .any(|r| r.delegator == caller && matches!(r.action, DelegationAction::Revoke(_))) + ); + } + + execute_leave_delegators { + let x in 2..<::MaxDelegationsPerDelegator as Get>::get(); + // Worst Case is full of delegations before execute exit + let mut collators: Vec = Vec::new(); + // Initialize MaxDelegationsPerDelegator collator candidates + for i in 1..x { + let seed = USER_SEED - i; + let collator = create_funded_collator::( + "collator", + seed, + 0u32.into(), + true, + collators.len() as u32 + 1u32 + )?; + collators.push(collator.clone()); + } + let bond = <::MinDelegatorStk as Get>>::get(); + let need = bond * (collators.len() as u32).into(); + let default_minted = min_candidate_stk::(); + let need: BalanceOf = if need > default_minted { + need - default_minted + } else { + 0u32.into() + }; + // Fund the delegator + let (caller, _) = create_funded_user::("caller", USER_SEED, need); + // Delegation count + let mut delegation_count = 0u32; + let author = collators[0].clone(); + // Nominate MaxDelegationsPerDelegators collator candidates + for col in collators { + Pallet::::delegate( + RawOrigin::Signed(caller.clone()).into(), + col, + bond, + 0u32, + delegation_count + )?; + delegation_count += 1u32; + } + Pallet::::schedule_leave_delegators(RawOrigin::Signed(caller.clone()).into())?; + roll_to_and_author::(2, author); + }: _(RawOrigin::Signed(caller.clone()), caller.clone(), delegation_count) + verify { + assert!(Pallet::::delegator_state(&caller).is_none()); + } + + cancel_leave_delegators { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); + let bond = <::MinDelegatorStk as Get>>::get(); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + bond, + 0u32, + 0u32 + )?; + Pallet::::schedule_leave_delegators(RawOrigin::Signed(caller.clone()).into())?; + }: _(RawOrigin::Signed(caller.clone())) + verify { + assert!(Pallet::::delegator_state(&caller).expect("must exist").is_active()); + } + + schedule_revoke_delegation { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); + let bond = <::MinDelegatorStk as Get>>::get(); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + bond, + 0u32, + 0u32 + )?; + }: _(RawOrigin::Signed(caller.clone()), collator.clone()) + verify { + assert_eq!( + Pallet::::delegation_scheduled_requests(&collator), + vec![ScheduledRequest { + delegator: caller, + when_executable: 3, + action: DelegationAction::Revoke(bond), + }], + ); + } + + delegator_bond_more { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); + let bond = <::MinDelegatorStk as Get>>::get(); + Pallet::::delegate( + RawOrigin::Signed(caller.clone()).into(), + collator.clone(), + bond, + 0u32, + 0u32 + )?; + }: _(RawOrigin::Signed(caller.clone()), collator.clone(), bond) + verify { + let expected_bond = bond * 2u32.into(); + assert_eq!( + Pallet::::delegator_state(&caller).expect("candidate was created, qed").total, + expected_bond, + ); + } + + schedule_delegator_bond_less { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, total) = create_funded_user::("caller", USER_SEED, 0u32.into()); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + total, + 0u32, + 0u32 + )?; + let bond_less = <::MinDelegatorStk as Get>>::get(); + }: _(RawOrigin::Signed(caller.clone()), collator.clone(), bond_less) + verify { + let state = Pallet::::delegator_state(&caller) + .expect("just request bonded less so exists"); + assert_eq!( + Pallet::::delegation_scheduled_requests(&collator), + vec![ScheduledRequest { + delegator: caller, + when_executable: 3, + action: DelegationAction::Decrease(bond_less), + }], + ); + } + + execute_revoke_delegation { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); + let bond = <::MinDelegatorStk as Get>>::get(); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + bond, + 0u32, + 0u32 + )?; + Pallet::::schedule_revoke_delegation(RawOrigin::Signed( + caller.clone()).into(), + collator.clone() + )?; + roll_to_and_author::(2, collator.clone()); + }: { + Pallet::::execute_delegation_request( + RawOrigin::Signed(caller.clone()).into(), + caller.clone(), + collator.clone() + )?; + } verify { + assert!( + !Pallet::::is_delegator(&caller) + ); + } + + execute_delegator_bond_less { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, total) = create_funded_user::("caller", USER_SEED, 0u32.into()); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + total, + 0u32, + 0u32 + )?; + let bond_less = <::MinDelegatorStk as Get>>::get(); + Pallet::::schedule_delegator_bond_less( + RawOrigin::Signed(caller.clone()).into(), + collator.clone(), + bond_less + )?; + roll_to_and_author::(2, collator.clone()); + }: { + Pallet::::execute_delegation_request( + RawOrigin::Signed(caller.clone()).into(), + caller.clone(), + collator.clone() + )?; + } verify { + let expected = total - bond_less; + assert_eq!( + Pallet::::delegator_state(&caller).expect("candidate was created, qed").total, + expected, + ); + } + + cancel_revoke_delegation { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); + let bond = <::MinDelegatorStk as Get>>::get(); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + bond, + 0u32, + 0u32 + )?; + Pallet::::schedule_revoke_delegation( + RawOrigin::Signed(caller.clone()).into(), + collator.clone() + )?; + }: { + Pallet::::cancel_delegation_request( + RawOrigin::Signed(caller.clone()).into(), + collator.clone() + )?; + } verify { + assert!( + !Pallet::::delegation_scheduled_requests(&collator) + .iter() + .any(|x| &x.delegator == &caller) + ); + } + + cancel_delegator_bond_less { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let (caller, total) = create_funded_user::("caller", USER_SEED, 0u32.into()); + Pallet::::delegate(RawOrigin::Signed( + caller.clone()).into(), + collator.clone(), + total, + 0u32, + 0u32 + )?; + let bond_less = <::MinDelegatorStk as Get>>::get(); + Pallet::::schedule_delegator_bond_less( + RawOrigin::Signed(caller.clone()).into(), + collator.clone(), + bond_less + )?; + roll_to_and_author::(2, collator.clone()); + }: { + Pallet::::cancel_delegation_request( + RawOrigin::Signed(caller.clone()).into(), + collator.clone() + )?; + } verify { + assert!( + !Pallet::::delegation_scheduled_requests(&collator) + .iter() + .any(|x| &x.delegator == &caller) + ); + } + + // ON_INITIALIZE + + prepare_staking_payouts { + let reward_delay = <::RewardPaymentDelay as Get>::get(); + let round = reward_delay + 2u32; + let payout_round = round - reward_delay; + // may need: + // > + // > + // > + // ensure parachain bond account exists so that deposit_into_existing succeeds + >::insert(payout_round, 100); + >::insert(payout_round, min_candidate_stk::()); + + // set an account in the bond config so that we will measure the payout to it + let account = create_funded_user::( + "parachain_bond", + 0, + min_candidate_stk::(), + ).0; + >::put(ParachainBondConfig { + account, + percent: Percent::from_percent(50), + }); + + }: { Pallet::::prepare_staking_payouts(round); } + verify { + } + + get_rewardable_delegators { + let y in 0..<::MaxDelegationsPerDelegator as Get>::get(); // num delegators + + let high_inflation: Range = Range { + min: Perbill::one(), + ideal: Perbill::one(), + max: Perbill::one(), + }; + Pallet::::set_inflation(RawOrigin::Root.into(), high_inflation.clone())?; + Pallet::::set_blocks_per_round(RawOrigin::Root.into(), 101u32)?; + Pallet::::set_total_selected(RawOrigin::Root.into(), 100u32)?; + + let collator = create_funded_collator::( + "collator", + 0, + min_candidate_stk::() * 1_000_000u32.into(), + true, + 1, + )?; + + // create delegators + for i in 0..y { + let seed = USER_SEED + i + 1; + let delegator = create_funded_delegator::( + "delegator", + seed, + min_candidate_stk::() * 1_000_000u32.into(), + collator.clone(), + true, + i, + )?; + } + + let mut _results = None; + + }: { _results = Some(Pallet::::get_rewardable_delegators(&collator)); } + verify { + let counted_delegations = _results.expect("get_rewardable_delegators returned some results"); + assert!(counted_delegations.uncounted_stake == 0u32.into()); + assert!(counted_delegations.rewardable_delegations.len() as u32 == y); + let top_delegations = >::get(collator.clone()) + .expect("delegations were set for collator through delegate() calls"); + assert!(top_delegations.delegations.len() as u32 == y); + } + + select_top_candidates { + let x in 0..50; // num collators + let y in 0..<::MaxDelegationsPerDelegator as Get>::get(); // num delegators + + let high_inflation: Range = Range { + min: Perbill::one(), + ideal: Perbill::one(), + max: Perbill::one(), + }; + Pallet::::set_inflation(RawOrigin::Root.into(), high_inflation.clone())?; + Pallet::::set_blocks_per_round(RawOrigin::Root.into(), 101u32)?; + Pallet::::set_total_selected(RawOrigin::Root.into(), 100u32)?; + + let mut seed = USER_SEED + 1; + + for _ in 0..x { + let collator = create_funded_collator::( + "collator", + seed, + min_candidate_stk::() * 1_000_000u32.into(), + true, + 999999, + )?; + seed += 1; + + // create delegators + for _ in 0..y { + let delegator = create_funded_delegator::( + "delegator", + seed, + min_candidate_stk::() * 1_000_000u32.into(), + collator.clone(), + true, + 9999999, + )?; + seed += 1; + } + } + + }: { Pallet::::select_top_candidates(1); } + verify { + } + + pay_one_collator_reward { + // y controls number of delegations, its maximum per collator is the max top delegations + let y in 0..<::MaxTopDelegationsPerCandidate as Get>::get(); + + // must come after 'let foo in 0..` statements for macro + use crate::{ + DelayedPayout, DelayedPayouts, AtStake, CollatorSnapshot, BondWithAutoCompound, Points, + AwardedPts, + }; + + let before_running_round_index = Pallet::::round().current; + let initial_stake_amount = min_candidate_stk::() * 1_000_000u32.into(); + + let mut total_staked = 0u32.into(); + + // initialize our single collator + let sole_collator = create_funded_collator::( + "collator", + 0, + initial_stake_amount, + true, + 1u32, + )?; + total_staked += initial_stake_amount; + + // generate funded collator accounts + let mut delegators: Vec = Vec::new(); + for i in 0..y { + let seed = USER_SEED + i; + let delegator = create_funded_delegator::( + "delegator", + seed, + initial_stake_amount, + sole_collator.clone(), + true, + delegators.len() as u32, + )?; + delegators.push(delegator); + total_staked += initial_stake_amount; + } + + // rather than roll through rounds in order to initialize the storage we want, we set it + // directly and then call pay_one_collator_reward directly. + + let round_for_payout = 5; + >::insert(&round_for_payout, DelayedPayout { + // NOTE: round_issuance is not correct here, but it doesn't seem to cause problems + round_issuance: 1000u32.into(), + total_staking_reward: total_staked, + collator_commission: Perbill::from_rational(1u32, 100u32), + }); + + let mut delegations: Vec>> = Vec::new(); + for delegator in &delegators { + delegations.push(BondWithAutoCompound { + owner: delegator.clone(), + amount: 100u32.into(), + auto_compound: Percent::zero(), + }); + } + + >::insert(round_for_payout, &sole_collator, CollatorSnapshot { + bond: 1_000u32.into(), + delegations, + total: 1_000_000u32.into(), + }); + + >::insert(round_for_payout, 100); + >::insert(round_for_payout, &sole_collator, 20); + + }: { + let round_for_payout = 5; + // TODO: this is an extra read right here (we should whitelist it?) + let payout_info = Pallet::::delayed_payouts(round_for_payout).expect("payout expected"); + let result = Pallet::::pay_one_collator_reward(round_for_payout, payout_info); + // TODO: how to keep this in scope so it can be done in verify block? + assert!(matches!(result.0, RewardPayment::Paid)); + } + verify { + // collator should have been paid + assert!( + T::Currency::free_balance(&sole_collator) > initial_stake_amount, + "collator should have been paid in pay_one_collator_reward" + ); + // nominators should have been paid + for delegator in &delegators { + assert!( + T::Currency::free_balance(&delegator) > initial_stake_amount, + "delegator should have been paid in pay_one_collator_reward" + ); + } + } + + base_on_initialize { + let collator: T::AccountId = create_funded_collator::( + "collator", + USER_SEED, + 0u32.into(), + true, + 1u32 + )?; + let start = >::block_number(); + parachain_staking_on_finalize::(collator.clone()); + >::on_finalize(start); + >::set_block_number( + start + 1u32.into() + ); + let end = >::block_number(); + >::on_initialize(end); + }: { Pallet::::on_initialize(end); } + verify { + // Round transitions + assert_eq!(start + 1u32.into(), end); + } + + set_auto_compound { + // x controls number of distinct auto-compounding delegations the prime collator will have + // y controls number of distinct delegations the prime delegator will have + let x in 0..<::MaxTopDelegationsPerCandidate as Get>::get(); + let y in 0..<::MaxDelegationsPerDelegator as Get>::get(); + + use crate::auto_compound::AutoCompoundDelegations; + + let min_candidate_stake = min_candidate_stk::(); + let min_delegator_stake = min_delegator_stk::(); + let mut seed = Seed::new(); + + // initialize the prime collator + let prime_candidate = create_funded_collator::( + "collator", + seed.take(), + min_candidate_stake, + true, + 1, + )?; + + // initialize the prime delegator + let prime_delegator = create_funded_delegator::( + "delegator", + seed.take(), + min_delegator_stake * (y+1).into(), + prime_candidate.clone(), + true, + 0, + )?; + + // have x-1 distinct auto-compounding delegators delegate to prime collator + // we directly set the storage, since benchmarks don't work when the same extrinsic is + // called from within the benchmark. + let mut auto_compounding_state = >::get_storage(&prime_candidate); + for i in 1..x { + let delegator = create_funded_delegator::( + "delegator", + seed.take(), + min_delegator_stake, + prime_candidate.clone(), + true, + i, + )?; + auto_compounding_state.set_for_delegator( + delegator, + Percent::from_percent(100), + ).expect("must succeed"); + } + auto_compounding_state.set_storage(&prime_candidate); + + // delegate to y-1 distinct collators from the prime delegator + for i in 1..y { + let collator = create_funded_collator::( + "collator", + seed.take(), + min_candidate_stake, + true, + i+1, + )?; + Pallet::::delegate( + RawOrigin::Signed(prime_delegator.clone()).into(), + collator, + min_delegator_stake, + 0, + i, + )?; + } + }: { + Pallet::::set_auto_compound( + RawOrigin::Signed(prime_delegator.clone()).into(), + prime_candidate.clone(), + Percent::from_percent(50), + x, + y+1, + )?; + } + verify { + let actual_auto_compound = >::get_storage(&prime_candidate) + .get_for_delegator(&prime_delegator); + let expected_auto_compound = Some(Percent::from_percent(50)); + assert_eq!( + expected_auto_compound, + actual_auto_compound, + "delegation must have an auto-compound entry", + ); + } + + delegate_with_auto_compound { + // x controls number of distinct delegations the prime collator will have + // y controls number of distinct auto-compounding delegations the prime collator will have + // z controls number of distinct delegations the prime delegator will have + let x in 0..(<::MaxTopDelegationsPerCandidate as Get>::get() + + <::MaxBottomDelegationsPerCandidate as Get>::get()); + let y in 0..<::MaxTopDelegationsPerCandidate as Get>::get() + + <::MaxBottomDelegationsPerCandidate as Get>::get(); + let z in 0..<::MaxDelegationsPerDelegator as Get>::get(); + + use crate::auto_compound::AutoCompoundDelegations; + + let min_candidate_stake = min_candidate_stk::(); + let min_delegator_stake = min_delegator_stk::(); + let mut seed = Seed::new(); + + // initialize the prime collator + let prime_candidate = create_funded_collator::( + "collator", + seed.take(), + min_candidate_stake, + true, + 1, + )?; + + // initialize the future delegator + let (prime_delegator, _) = create_funded_user::( + "delegator", + seed.take(), + min_delegator_stake * (z+1).into(), + ); + + // have x-1 distinct delegators delegate to prime collator, of which y are auto-compounding. + // we can directly set the storage here. + let auto_compound_z = x * y / 100; + for i in 1..x { + let delegator = create_funded_delegator::( + "delegator", + seed.take(), + min_delegator_stake, + prime_candidate.clone(), + true, + i, + )?; + if i <= y { + Pallet::::set_auto_compound( + RawOrigin::Signed(delegator.clone()).into(), + prime_candidate.clone(), + Percent::from_percent(100), + i+1, + i, + )?; + } + } + + // delegate to z-1 distinct collators from the prime delegator + for i in 1..z { + let collator = create_funded_collator::( + "collator", + seed.take(), + min_candidate_stake, + true, + i+1, + )?; + Pallet::::delegate( + RawOrigin::Signed(prime_delegator.clone()).into(), + collator, + min_delegator_stake, + 0, + i, + )?; + } + }: { + Pallet::::delegate_with_auto_compound( + RawOrigin::Signed(prime_delegator.clone()).into(), + prime_candidate.clone(), + min_delegator_stake, + Percent::from_percent(50), + x, + y, + z, + )?; + } + verify { + assert!(Pallet::::is_delegator(&prime_delegator)); + let actual_auto_compound = >::get_storage(&prime_candidate) + .get_for_delegator(&prime_delegator); + let expected_auto_compound = Some(Percent::from_percent(50)); + assert_eq!( + expected_auto_compound, + actual_auto_compound, + "delegation must have an auto-compound entry", + ); + } + + mint_collator_reward { + let mut seed = Seed::new(); + let collator = create_funded_collator::( + "collator", + seed.take(), + 0u32.into(), + true, + 1, + )?; + let original_free_balance = T::Currency::free_balance(&collator); + }: { + Pallet::::mint_collator_reward(1u32.into(), collator.clone(), 50u32.into()) + } + verify { + assert_eq!(T::Currency::free_balance(&collator), original_free_balance + 50u32.into()); + } +} + +#[cfg(test)] +mod tests { + use crate::{benchmarks::*, mock::Test}; + use frame_support::assert_ok; + use sp_io::TestExternalities; + + pub fn new_test_ext() -> TestExternalities { + let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + TestExternalities::new(t) + } + + #[test] + fn bench_set_staking_expectations() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_staking_expectations()); + }); + } + + #[test] + fn bench_set_inflation() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_inflation()); + }); + } + + #[test] + fn bench_set_parachain_bond_account() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_parachain_bond_account()); + }); + } + + #[test] + fn bench_set_parachain_bond_reserve_percent() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_parachain_bond_reserve_percent()); + }); + } + + #[test] + fn bench_set_total_selected() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_total_selected()); + }); + } + + #[test] + fn bench_set_collator_commission() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_collator_commission()); + }); + } + + #[test] + fn bench_set_blocks_per_round() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_set_blocks_per_round()); + }); + } + + #[test] + fn bench_join_candidates() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_join_candidates()); + }); + } + + #[test] + fn bench_schedule_leave_candidates() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_schedule_leave_candidates()); + }); + } + + #[test] + fn bench_execute_leave_candidates() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_execute_leave_candidates()); + }); + } + + #[test] + fn bench_cancel_leave_candidates() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_cancel_leave_candidates()); + }); + } + + #[test] + fn bench_go_offline() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_go_offline()); + }); + } + + #[test] + fn bench_go_online() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_go_online()); + }); + } + + #[test] + fn bench_candidate_bond_more() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_candidate_bond_more()); + }); + } + + #[test] + fn bench_schedule_candidate_bond_less() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_schedule_candidate_bond_less()); + }); + } + + #[test] + fn bench_execute_candidate_bond_less() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_execute_candidate_bond_less()); + }); + } + + #[test] + fn bench_cancel_candidate_bond_less() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_cancel_candidate_bond_less()); + }); + } + + #[test] + fn bench_delegate() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_delegate()); + }); + } + + #[test] + fn bench_schedule_leave_delegators() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_schedule_leave_delegators()); + }); + } + + #[test] + fn bench_execute_leave_delegators() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_execute_leave_delegators()); + }); + } + + #[test] + fn bench_cancel_leave_delegators() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_cancel_leave_delegators()); + }); + } + + #[test] + fn bench_schedule_revoke_delegation() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_schedule_revoke_delegation()); + }); + } + + #[test] + fn bench_delegator_bond_more() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_delegator_bond_more()); + }); + } + + #[test] + fn bench_schedule_delegator_bond_less() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_schedule_delegator_bond_less()); + }); + } + + #[test] + fn bench_execute_revoke_delegation() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_execute_revoke_delegation()); + }); + } + + #[test] + fn bench_execute_delegator_bond_less() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_execute_delegator_bond_less()); + }); + } + + #[test] + fn bench_cancel_revoke_delegation() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_cancel_revoke_delegation()); + }); + } + + #[test] + fn bench_cancel_delegator_bond_less() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_cancel_delegator_bond_less()); + }); + } + + #[test] + fn bench_base_on_initialize() { + new_test_ext().execute_with(|| { + assert_ok!(Pallet::::test_benchmark_base_on_initialize()); + }); + } +} + +impl_benchmark_test_suite!(Pallet, crate::benchmarks::tests::new_test_ext(), crate::mock::Test); diff --git a/pallets/parachain-staking/src/delegation_requests.rs b/pallets/parachain-staking/src/delegation_requests.rs new file mode 100644 index 000000000..c1beb3d80 --- /dev/null +++ b/pallets/parachain-staking/src/delegation_requests.rs @@ -0,0 +1,653 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Scheduled requests functionality for delegators + +use crate::{ + auto_compound::AutoCompoundDelegations, + pallet::{ + BalanceOf, CandidateInfo, Config, DelegationScheduledRequests, DelegatorState, Error, + Event, Pallet, Round, RoundIndex, Total, + }, + Delegator, DelegatorStatus, +}; +use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, traits::Get, RuntimeDebug}; +use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; +use sp_runtime::traits::Saturating; +use sp_std::{vec, vec::Vec}; + +/// An action that can be performed upon a delegation +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, PartialOrd, Ord)] +pub enum DelegationAction { + Revoke(Balance), + Decrease(Balance), +} + +impl DelegationAction { + /// Returns the wrapped amount value. + pub fn amount(&self) -> Balance { + match self { + DelegationAction::Revoke(amount) => *amount, + DelegationAction::Decrease(amount) => *amount, + } + } +} + +/// Represents a scheduled request that define a [DelegationAction]. The request is executable +/// iff the provided [RoundIndex] is achieved. +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, PartialOrd, Ord)] +pub struct ScheduledRequest { + pub delegator: AccountId, + pub when_executable: RoundIndex, + pub action: DelegationAction, +} + +/// Represents a cancelled scheduled request for emitting an event. +#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct CancelledScheduledRequest { + pub when_executable: RoundIndex, + pub action: DelegationAction, +} + +impl From> for CancelledScheduledRequest { + fn from(request: ScheduledRequest) -> Self { + CancelledScheduledRequest { + when_executable: request.when_executable, + action: request.action, + } + } +} + +impl Pallet { + /// Schedules a [DelegationAction::Revoke] for the delegator, towards a given collator. + pub(crate) fn delegation_schedule_revoke( + collator: T::AccountId, + delegator: T::AccountId, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + let mut scheduled_requests = >::get(&collator); + + ensure!( + !scheduled_requests.iter().any(|req| req.delegator == delegator), + >::PendingDelegationRequestAlreadyExists, + ); + + let bonded_amount = state.get_bond_amount(&collator).ok_or(>::DelegationDNE)?; + let now = >::get().current; + let when = now.saturating_add(T::RevokeDelegationDelay::get()); + scheduled_requests.push(ScheduledRequest { + delegator: delegator.clone(), + action: DelegationAction::Revoke(bonded_amount), + when_executable: when, + }); + state.less_total = state.less_total.saturating_add(bonded_amount); + >::insert(collator.clone(), scheduled_requests); + >::insert(delegator.clone(), state); + + Self::deposit_event(Event::DelegationRevocationScheduled { + round: now, + delegator, + candidate: collator, + scheduled_exit: when, + }); + Ok(().into()) + } + + /// Schedules a [DelegationAction::Decrease] for the delegator, towards a given collator. + pub(crate) fn delegation_schedule_bond_decrease( + collator: T::AccountId, + delegator: T::AccountId, + decrease_amount: BalanceOf, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + let mut scheduled_requests = >::get(&collator); + + ensure!( + !scheduled_requests.iter().any(|req| req.delegator == delegator), + >::PendingDelegationRequestAlreadyExists, + ); + + let bonded_amount = state.get_bond_amount(&collator).ok_or(>::DelegationDNE)?; + ensure!(bonded_amount > decrease_amount, >::DelegatorBondBelowMin); + let new_amount: BalanceOf = bonded_amount - decrease_amount; + ensure!(new_amount >= T::MinDelegation::get(), >::DelegationBelowMin); + + // Net Total is total after pending orders are executed + let net_total = state.total().saturating_sub(state.less_total); + // Net Total is always >= MinDelegatorStk + let max_subtracted_amount = net_total.saturating_sub(T::MinDelegatorStk::get()); + ensure!(decrease_amount <= max_subtracted_amount, >::DelegatorBondBelowMin); + + let now = >::get().current; + let when = now.saturating_add(T::RevokeDelegationDelay::get()); + scheduled_requests.push(ScheduledRequest { + delegator: delegator.clone(), + action: DelegationAction::Decrease(decrease_amount), + when_executable: when, + }); + state.less_total = state.less_total.saturating_add(decrease_amount); + >::insert(collator.clone(), scheduled_requests); + >::insert(delegator.clone(), state); + + Self::deposit_event(Event::DelegationDecreaseScheduled { + delegator, + candidate: collator, + amount_to_decrease: decrease_amount, + execute_round: when, + }); + Ok(().into()) + } + + /// Cancels the delegator's existing [ScheduledRequest] towards a given collator. + pub(crate) fn delegation_cancel_request( + collator: T::AccountId, + delegator: T::AccountId, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + let mut scheduled_requests = >::get(&collator); + + let request = + Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests) + .ok_or(>::PendingDelegationRequestDNE)?; + + >::insert(collator.clone(), scheduled_requests); + >::insert(delegator.clone(), state); + + Self::deposit_event(Event::CancelledDelegationRequest { + delegator, + collator, + cancelled_request: request.into(), + }); + Ok(().into()) + } + + fn cancel_request_with_state( + delegator: &T::AccountId, + state: &mut Delegator>, + scheduled_requests: &mut Vec>>, + ) -> Option>> { + let request_idx = scheduled_requests.iter().position(|req| &req.delegator == delegator)?; + + let request = scheduled_requests.remove(request_idx); + let amount = request.action.amount(); + state.less_total = state.less_total.saturating_sub(amount); + Some(request) + } + + /// Executes the delegator's existing [ScheduledRequest] towards a given collator. + pub(crate) fn delegation_execute_scheduled_request( + collator: T::AccountId, + delegator: T::AccountId, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + let mut scheduled_requests = >::get(&collator); + let request_idx = scheduled_requests + .iter() + .position(|req| req.delegator == delegator) + .ok_or(>::PendingDelegationRequestDNE)?; + let request = &scheduled_requests[request_idx]; + + let now = >::get().current; + ensure!(request.when_executable <= now, >::PendingDelegationRequestNotDueYet); + + match request.action { + DelegationAction::Revoke(amount) => { + // revoking last delegation => leaving set of delegators + let leaving = if state.delegations.0.len() == 1usize { + true + } else { + ensure!( + state.total().saturating_sub(T::MinDelegatorStk::get()) >= amount, + >::DelegatorBondBelowMin + ); + false + }; + + // remove from pending requests + let amount = scheduled_requests.remove(request_idx).action.amount(); + state.less_total = state.less_total.saturating_sub(amount); + + // remove delegation from delegator state + state.rm_delegation::(&collator); + + // remove delegation from auto-compounding info + >::remove_auto_compound(&collator, &delegator); + + // remove delegation from collator state delegations + Self::delegator_leaves_candidate(collator.clone(), delegator.clone(), amount)?; + Self::deposit_event(Event::DelegationRevoked { + delegator: delegator.clone(), + candidate: collator.clone(), + unstaked_amount: amount, + }); + + >::insert(collator, scheduled_requests); + if leaving { + >::remove(&delegator); + Self::deposit_event(Event::DelegatorLeft { + delegator, + unstaked_amount: amount, + }); + } else { + >::insert(&delegator, state); + } + Ok(().into()) + }, + DelegationAction::Decrease(_) => { + // remove from pending requests + let amount = scheduled_requests.remove(request_idx).action.amount(); + state.less_total = state.less_total.saturating_sub(amount); + + // decrease delegation + for bond in &mut state.delegations.0 { + if bond.owner == collator { + return if bond.amount > amount { + let amount_before: BalanceOf = bond.amount; + bond.amount = bond.amount.saturating_sub(amount); + let mut collator_info = >::get(&collator) + .ok_or(>::CandidateDNE)?; + + state.total_sub_if::(amount, |total| { + let new_total: BalanceOf = total; + ensure!( + new_total >= T::MinDelegation::get(), + >::DelegationBelowMin + ); + ensure!( + new_total >= T::MinDelegatorStk::get(), + >::DelegatorBondBelowMin + ); + + Ok(()) + })?; + + // need to go into decrease_delegation + let in_top = collator_info.decrease_delegation::( + &collator, + delegator.clone(), + amount_before, + amount, + )?; + >::insert(&collator, collator_info); + let new_total_staked = >::get().saturating_sub(amount); + >::put(new_total_staked); + + >::insert( + collator.clone(), + scheduled_requests, + ); + >::insert(delegator.clone(), state); + Self::deposit_event(Event::DelegationDecreased { + delegator, + candidate: collator.clone(), + amount, + in_top, + }); + Ok(().into()) + } else { + // must rm entire delegation if bond.amount <= less or cancel request + Err(>::DelegationBelowMin.into()) + } + } + } + Err(>::DelegationDNE.into()) + }, + } + } + + /// Schedules [DelegationAction::Revoke] for the delegator, towards all delegated collator. + /// The last fulfilled request causes the delegator to leave the set of delegators. + pub(crate) fn delegator_schedule_revoke_all( + delegator: T::AccountId, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + let mut updated_scheduled_requests = vec![]; + let now = >::get().current; + let when = now.saturating_add(T::LeaveDelegatorsDelay::get()); + + // lazy migration for DelegatorStatus::Leaving + #[allow(deprecated)] + if matches!(state.status, DelegatorStatus::Leaving(_)) { + state.status = DelegatorStatus::Active; + >::insert(delegator.clone(), state.clone()); + } + + // it is assumed that a multiple delegations to the same collator does not exist, else this + // will cause a bug - the last duplicate delegation update will be the only one applied. + let mut existing_revoke_count = 0; + for bond in state.delegations.0.clone() { + let collator = bond.owner; + let bonded_amount = bond.amount; + let mut scheduled_requests = >::get(&collator); + + // cancel any existing requests + let request = + Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests); + let request = match request { + Some(revoke_req) if matches!(revoke_req.action, DelegationAction::Revoke(_)) => { + existing_revoke_count += 1; + revoke_req // re-insert the same Revoke request + }, + _ => ScheduledRequest { + delegator: delegator.clone(), + action: DelegationAction::Revoke(bonded_amount), + when_executable: when, + }, + }; + + scheduled_requests.push(request); + state.less_total = state.less_total.saturating_add(bonded_amount); + updated_scheduled_requests.push((collator, scheduled_requests)); + } + + if existing_revoke_count == state.delegations.0.len() { + return Err(>::DelegatorAlreadyLeaving.into()) + } + + updated_scheduled_requests + .into_iter() + .for_each(|(collator, scheduled_requests)| { + >::insert(collator, scheduled_requests); + }); + + >::insert(delegator.clone(), state); + Self::deposit_event(Event::DelegatorExitScheduled { + round: now, + delegator, + scheduled_exit: when, + }); + Ok(().into()) + } + + /// Cancels every [DelegationAction::Revoke] request for a delegator towards a collator. + /// Each delegation must have a [DelegationAction::Revoke] scheduled that must be allowed to be + /// executed in the current round, for this function to succeed. + pub(crate) fn delegator_cancel_scheduled_revoke_all( + delegator: T::AccountId, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + let mut updated_scheduled_requests = vec![]; + + // backwards compatible handling for DelegatorStatus::Leaving + #[allow(deprecated)] + if matches!(state.status, DelegatorStatus::Leaving(_)) { + state.status = DelegatorStatus::Active; + >::insert(delegator.clone(), state.clone()); + Self::deposit_event(Event::DelegatorExitCancelled { delegator }); + return Ok(().into()) + } + + // pre-validate that all delegations have a Revoke request. + for bond in &state.delegations.0 { + let collator = bond.owner.clone(); + let scheduled_requests = >::get(&collator); + scheduled_requests + .iter() + .find(|req| { + req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) + }) + .ok_or(>::DelegatorNotLeaving)?; + } + + // cancel all requests + for bond in state.delegations.0.clone() { + let collator = bond.owner.clone(); + let mut scheduled_requests = >::get(&collator); + Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests); + updated_scheduled_requests.push((collator, scheduled_requests)); + } + + updated_scheduled_requests + .into_iter() + .for_each(|(collator, scheduled_requests)| { + >::insert(collator, scheduled_requests); + }); + + >::insert(delegator.clone(), state); + Self::deposit_event(Event::DelegatorExitCancelled { delegator }); + + Ok(().into()) + } + + /// Executes every [DelegationAction::Revoke] request for a delegator towards a collator. + /// Each delegation must have a [DelegationAction::Revoke] scheduled that must be allowed to be + /// executed in the current round, for this function to succeed. + pub(crate) fn delegator_execute_scheduled_revoke_all( + delegator: T::AccountId, + delegation_count: u32, + ) -> DispatchResultWithPostInfo { + let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + ensure!( + delegation_count >= (state.delegations.0.len() as u32), + Error::::TooLowDelegationCountToLeaveDelegators + ); + let now = >::get().current; + + // backwards compatible handling for DelegatorStatus::Leaving + #[allow(deprecated)] + if let DelegatorStatus::Leaving(when) = state.status { + ensure!(>::get().current >= when, Error::::DelegatorCannotLeaveYet); + + for bond in state.delegations.0.clone() { + if let Err(error) = Self::delegator_leaves_candidate( + bond.owner.clone(), + delegator.clone(), + bond.amount, + ) { + log::warn!( + "STORAGE CORRUPTED \nDelegator leaving collator failed with error: {:?}", + error + ); + } + + Self::delegation_remove_request_with_state(&bond.owner, &delegator, &mut state); + >::remove_auto_compound(&bond.owner, &delegator); + } + >::remove(&delegator); + Self::deposit_event(Event::DelegatorLeft { delegator, unstaked_amount: state.total }); + return Ok(().into()) + } + + let mut validated_scheduled_requests = vec![]; + // pre-validate that all delegations have a Revoke request that can be executed now. + for bond in &state.delegations.0 { + let scheduled_requests = >::get(&bond.owner); + let request_idx = scheduled_requests + .iter() + .position(|req| { + req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) + }) + .ok_or(>::DelegatorNotLeaving)?; + let request = &scheduled_requests[request_idx]; + + ensure!(request.when_executable <= now, >::DelegatorCannotLeaveYet); + + validated_scheduled_requests.push((bond.clone(), scheduled_requests, request_idx)) + } + + let mut updated_scheduled_requests = vec![]; + // we do not update the delegator state, since the it will be completely removed + for (bond, mut scheduled_requests, request_idx) in validated_scheduled_requests { + let collator = bond.owner; + + if let Err(error) = + Self::delegator_leaves_candidate(collator.clone(), delegator.clone(), bond.amount) + { + log::warn!( + "STORAGE CORRUPTED \nDelegator {:?} leaving collator failed with error: {:?}", + delegator, + error + ); + } + + // remove the scheduled request, since it is fulfilled + scheduled_requests.remove(request_idx).action.amount(); + updated_scheduled_requests.push((collator.clone(), scheduled_requests)); + + // remove the auto-compounding entry for the delegation + >::remove_auto_compound(&collator, &delegator); + } + + // set state.total so that state.adjust_bond_lock will remove lock + let unstaked_amount = state.total(); + state.total_sub::(unstaked_amount)?; + + updated_scheduled_requests + .into_iter() + .for_each(|(collator, scheduled_requests)| { + >::insert(collator, scheduled_requests); + }); + + Self::deposit_event(Event::DelegatorLeft { delegator: delegator.clone(), unstaked_amount }); + >::remove(&delegator); + + Ok(().into()) + } + + /// Removes the delegator's existing [ScheduledRequest] towards a given collator, if exists. + /// The state needs to be persisted by the caller of this function. + pub(crate) fn delegation_remove_request_with_state( + collator: &T::AccountId, + delegator: &T::AccountId, + state: &mut Delegator>, + ) { + let mut scheduled_requests = >::get(collator); + + let maybe_request_idx = + scheduled_requests.iter().position(|req| &req.delegator == delegator); + + if let Some(request_idx) = maybe_request_idx { + let request = scheduled_requests.remove(request_idx); + let amount = request.action.amount(); + state.less_total = state.less_total.saturating_sub(amount); + >::insert(collator, scheduled_requests); + } + } + + /// Returns true if a [ScheduledRequest] exists for a given delegation + pub fn delegation_request_exists(collator: &T::AccountId, delegator: &T::AccountId) -> bool { + >::get(collator) + .iter() + .any(|req| &req.delegator == delegator) + } + + /// Returns true if a [DelegationAction::Revoke] [ScheduledRequest] exists for a given delegation + pub fn delegation_request_revoke_exists( + collator: &T::AccountId, + delegator: &T::AccountId, + ) -> bool { + >::get(collator).iter().any(|req| { + &req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{mock::Test, set::OrderedSet, Bond}; + + #[test] + fn test_cancel_request_with_state_removes_request_for_correct_delegator_and_updates_state() { + let mut state = Delegator { + id: 1, + delegations: OrderedSet::from(vec![Bond { amount: 100, owner: 2 }]), + total: 100, + less_total: 100, + status: crate::DelegatorStatus::Active, + }; + let mut scheduled_requests = vec![ + ScheduledRequest { + delegator: 1, + when_executable: 1, + action: DelegationAction::Revoke(100), + }, + ScheduledRequest { + delegator: 2, + when_executable: 1, + action: DelegationAction::Decrease(50), + }, + ]; + let removed_request = + >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); + + assert_eq!( + removed_request, + Some(ScheduledRequest { + delegator: 1, + when_executable: 1, + action: DelegationAction::Revoke(100), + }) + ); + assert_eq!( + scheduled_requests, + vec![ScheduledRequest { + delegator: 2, + when_executable: 1, + action: DelegationAction::Decrease(50), + },] + ); + assert_eq!( + state, + Delegator { + id: 1, + delegations: OrderedSet::from(vec![Bond { amount: 100, owner: 2 }]), + total: 100, + less_total: 0, + status: crate::DelegatorStatus::Active, + } + ); + } + + #[test] + fn test_cancel_request_with_state_does_nothing_when_request_does_not_exist() { + let mut state = Delegator { + id: 1, + delegations: OrderedSet::from(vec![Bond { amount: 100, owner: 2 }]), + total: 100, + less_total: 100, + status: crate::DelegatorStatus::Active, + }; + let mut scheduled_requests = vec![ScheduledRequest { + delegator: 2, + when_executable: 1, + action: DelegationAction::Decrease(50), + }]; + let removed_request = + >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); + + assert_eq!(removed_request, None,); + assert_eq!( + scheduled_requests, + vec![ScheduledRequest { + delegator: 2, + when_executable: 1, + action: DelegationAction::Decrease(50), + },] + ); + assert_eq!( + state, + Delegator { + id: 1, + delegations: OrderedSet::from(vec![Bond { amount: 100, owner: 2 }]), + total: 100, + less_total: 100, + status: crate::DelegatorStatus::Active, + } + ); + } +} diff --git a/pallets/parachain-staking/src/inflation.rs b/pallets/parachain-staking/src/inflation.rs new file mode 100644 index 000000000..e6c6778d7 --- /dev/null +++ b/pallets/parachain-staking/src/inflation.rs @@ -0,0 +1,208 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Helper methods for computing issuance based on inflation +use crate::pallet::{BalanceOf, Config, Pallet}; +use frame_support::traits::Currency; +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; +use sp_runtime::{PerThing, Perbill, RuntimeDebug}; +use substrate_fixed::{transcendental::pow as floatpow, types::I64F64}; + +const SECONDS_PER_YEAR: u32 = 31557600; +const SECONDS_PER_BLOCK: u32 = 12; +pub const BLOCKS_PER_YEAR: u32 = SECONDS_PER_YEAR / SECONDS_PER_BLOCK; + +fn rounds_per_year() -> u32 { + let blocks_per_round = >::round().length; + BLOCKS_PER_YEAR / blocks_per_round +} + +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive( + Eq, PartialEq, Clone, Copy, Encode, Decode, Default, RuntimeDebug, MaxEncodedLen, TypeInfo, +)] +pub struct Range { + pub min: T, + pub ideal: T, + pub max: T, +} + +impl Range { + pub fn is_valid(&self) -> bool { + self.max >= self.ideal && self.ideal >= self.min + } +} + +impl From for Range { + fn from(other: T) -> Range { + Range { min: other, ideal: other, max: other } + } +} +/// Convert an annual inflation to a round inflation +/// round = (1+annual)^(1/rounds_per_year) - 1 +pub fn perbill_annual_to_perbill_round( + annual: Range, + rounds_per_year: u32, +) -> Range { + let exponent = I64F64::from_num(1) / I64F64::from_num(rounds_per_year); + let annual_to_round = |annual: Perbill| -> Perbill { + let x = I64F64::from_num(annual.deconstruct()) / I64F64::from_num(Perbill::ACCURACY); + let y: I64F64 = floatpow(I64F64::from_num(1) + x, exponent) + .expect("Cannot overflow since rounds_per_year is u32 so worst case 0; QED"); + Perbill::from_parts( + ((y - I64F64::from_num(1)) * I64F64::from_num(Perbill::ACCURACY)) + .ceil() + .to_num::(), + ) + }; + Range { + min: annual_to_round(annual.min), + ideal: annual_to_round(annual.ideal), + max: annual_to_round(annual.max), + } +} +/// Convert annual inflation rate range to round inflation range +pub fn annual_to_round(annual: Range) -> Range { + let periods = rounds_per_year::(); + perbill_annual_to_perbill_round(annual, periods) +} + +/// Compute round issuance range from round inflation range and current total issuance +pub fn round_issuance_range(round: Range) -> Range> { + let circulating = T::Currency::total_issuance(); + Range { + min: round.min * circulating, + ideal: round.ideal * circulating, + max: round.max * circulating, + } +} + +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Eq, PartialEq, Clone, Encode, Decode, Default, RuntimeDebug, TypeInfo)] +pub struct InflationInfo { + /// Staking expectations + pub expect: Range, + /// Annual inflation range + pub annual: Range, + /// Round inflation range + pub round: Range, +} + +impl InflationInfo { + pub fn new( + annual: Range, + expect: Range, + ) -> InflationInfo { + InflationInfo { expect, annual, round: annual_to_round::(annual) } + } + /// Set round inflation range according to input annual inflation range + pub fn set_round_from_annual(&mut self, new: Range) { + self.round = annual_to_round::(new); + } + /// Reset round inflation rate based on changes to round length + pub fn reset_round(&mut self, new_length: u32) { + let periods = BLOCKS_PER_YEAR / new_length; + self.round = perbill_annual_to_perbill_round(self.annual, periods); + } + /// Set staking expectations + pub fn set_expectations(&mut self, expect: Range) { + self.expect = expect; + } +} + +#[cfg(test)] +mod tests { + use super::*; + fn mock_annual_to_round(annual: Range, rounds_per_year: u32) -> Range { + perbill_annual_to_perbill_round(annual, rounds_per_year) + } + fn mock_round_issuance_range( + // Total circulating before minting + circulating: u128, + // Round inflation range + round: Range, + ) -> Range { + Range { + min: round.min * circulating, + ideal: round.ideal * circulating, + max: round.max * circulating, + } + } + #[test] + fn simple_issuance_conversion() { + // 5% inflation for 10_000_0000 = 500,000 minted over the year + // let's assume there are 10 periods in a year + // => mint 500_000 over 10 periods => 50_000 minted per period + let expected_round_issuance_range: Range = + Range { min: 48_909, ideal: 48_909, max: 48_909 }; + let schedule = Range { + min: Perbill::from_percent(5), + ideal: Perbill::from_percent(5), + max: Perbill::from_percent(5), + }; + assert_eq!( + expected_round_issuance_range, + mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 10)) + ); + } + #[test] + fn range_issuance_conversion() { + // 3-5% inflation for 10_000_0000 = 300_000-500,000 minted over the year + // let's assume there are 10 periods in a year + // => mint 300_000-500_000 over 10 periods => 30_000-50_000 minted per period + let expected_round_issuance_range: Range = + Range { min: 29_603, ideal: 39298, max: 48_909 }; + let schedule = Range { + min: Perbill::from_percent(3), + ideal: Perbill::from_percent(4), + max: Perbill::from_percent(5), + }; + assert_eq!( + expected_round_issuance_range, + mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 10)) + ); + } + #[test] + fn expected_parameterization() { + let expected_round_schedule: Range = Range { min: 45, ideal: 56, max: 56 }; + let schedule = Range { + min: Perbill::from_percent(4), + ideal: Perbill::from_percent(5), + max: Perbill::from_percent(5), + }; + assert_eq!( + expected_round_schedule, + mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 8766)) + ); + } + #[test] + fn inflation_does_not_panic_at_round_number_limit() { + let schedule = Range { + min: Perbill::from_percent(100), + ideal: Perbill::from_percent(100), + max: Perbill::from_percent(100), + }; + mock_round_issuance_range(u32::MAX.into(), mock_annual_to_round(schedule, u32::MAX)); + mock_round_issuance_range(u64::MAX.into(), mock_annual_to_round(schedule, u32::MAX)); + mock_round_issuance_range(u128::MAX.into(), mock_annual_to_round(schedule, u32::MAX)); + mock_round_issuance_range(u32::MAX.into(), mock_annual_to_round(schedule, 1)); + mock_round_issuance_range(u64::MAX.into(), mock_annual_to_round(schedule, 1)); + mock_round_issuance_range(u128::MAX.into(), mock_annual_to_round(schedule, 1)); + } +} diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs new file mode 100644 index 000000000..0ed5d4e24 --- /dev/null +++ b/pallets/parachain-staking/src/lib.rs @@ -0,0 +1,2011 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! # Parachain Staking +//! Minimal staking pallet that implements collator selection by total backed stake. +//! The main difference between this pallet and `frame/pallet-staking` is that this pallet +//! uses direct delegation. Delegators choose exactly who they delegate and with what stake. +//! This is different from `frame/pallet-staking` where delegators approval vote and run Phragmen. +//! +//! ### Rules +//! There is a new round every `>::get().length` blocks. +//! +//! At the start of every round, +//! * issuance is calculated for collators (and their delegators) for block authoring +//! `T::RewardPaymentDelay` rounds ago +//! * a new set of collators is chosen from the candidates +//! +//! Immediately following a round change, payments are made once-per-block until all payments have +//! been made. In each such block, one collator is chosen for a rewards payment and is paid along +//! with each of its top `T::MaxTopDelegationsPerCandidate` delegators. +//! +//! To join the set of candidates, call `join_candidates` with `bond >= MinCandidateStk`. +//! To leave the set of candidates, call `schedule_leave_candidates`. If the call succeeds, +//! the collator is removed from the pool of candidates so they cannot be selected for future +//! collator sets, but they are not unbonded until their exit request is executed. Any signed +//! account may trigger the exit `T::LeaveCandidatesDelay` rounds after the round in which the +//! original request was made. +//! +//! To join the set of delegators, call `delegate` and pass in an account that is +//! already a collator candidate and `bond >= MinDelegatorStk`. Each delegator can delegate up to +//! `T::MaxDelegationsPerDelegator` collator candidates by calling `delegate`. +//! +//! To revoke a delegation, call `revoke_delegation` with the collator candidate's account. +//! To leave the set of delegators and revoke all delegations, call `leave_delegators`. + +#![cfg_attr(not(feature = "std"), no_std)] + +mod auto_compound; +mod delegation_requests; +pub mod inflation; +pub mod migrations; +pub mod traits; +pub mod types; +pub mod weights; + +#[cfg(any(test, feature = "runtime-benchmarks"))] +mod benchmarks; +#[cfg(test)] +mod mock; +mod set; +#[cfg(test)] +mod tests; + +use frame_support::pallet; +pub use inflation::{InflationInfo, Range}; +use weights::WeightInfo; + +pub use auto_compound::{AutoCompoundConfig, AutoCompoundDelegations}; +pub use delegation_requests::{CancelledScheduledRequest, DelegationAction, ScheduledRequest}; +pub use pallet::*; +pub use traits::*; +pub use types::*; +pub use RoundIndex; + +#[pallet] +pub mod pallet { + use crate::{ + delegation_requests::{CancelledScheduledRequest, DelegationAction, ScheduledRequest}, + set::OrderedSet, + traits::*, + types::*, + AutoCompoundConfig, AutoCompoundDelegations, InflationInfo, Range, WeightInfo, + }; + use frame_support::{ + pallet_prelude::*, + traits::{ + tokens::WithdrawReasons, Currency, EstimateNextSessionRotation, Get, Imbalance, + LockIdentifier, LockableCurrency, ReservableCurrency, + }, + }; + use frame_system::pallet_prelude::*; + use sp_runtime::{ + traits::{Saturating, Zero}, + Perbill, Percent, Permill, + }; + use sp_staking::SessionIndex; + use sp_std::{collections::btree_map::BTreeMap, prelude::*}; + + /// Pallet for parachain staking + #[pallet::pallet] + #[pallet::without_storage_info] + pub struct Pallet(PhantomData); + + pub type RoundIndex = u32; + type RewardPoint = u32; + pub type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; + + pub type AccountIdOf = ::AccountId; + + pub const COLLATOR_LOCK_ID: LockIdentifier = *b"stkngcol"; + pub const DELEGATOR_LOCK_ID: LockIdentifier = *b"stkngdel"; + + /// Configuration trait of this pallet. + #[pallet::config] + pub trait Config: frame_system::Config { + /// Overarching event type + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + /// The currency type + type Currency: Currency + + ReservableCurrency + + LockableCurrency; + /// The origin for monetary governance + type MonetaryGovernanceOrigin: EnsureOrigin; + /// Minimum number of blocks per round + #[pallet::constant] + type MinBlocksPerRound: Get; + /// Number of rounds that candidates remain bonded before exit request is executable + #[pallet::constant] + type LeaveCandidatesDelay: Get; + /// Number of rounds candidate requests to decrease self-bond must wait to be executable + #[pallet::constant] + type CandidateBondLessDelay: Get; + /// Number of rounds that delegators remain bonded before exit request is executable + #[pallet::constant] + type LeaveDelegatorsDelay: Get; + /// Number of rounds that delegations remain bonded before revocation request is executable + #[pallet::constant] + type RevokeDelegationDelay: Get; + /// Number of rounds that delegation less requests must wait before executable + #[pallet::constant] + type DelegationBondLessDelay: Get; + /// Number of rounds after which block authors are rewarded + #[pallet::constant] + type RewardPaymentDelay: Get; + /// Minimum number of selected candidates every round + #[pallet::constant] + type MinSelectedCandidates: Get; + /// Maximum top delegations counted per candidate + #[pallet::constant] + type MaxTopDelegationsPerCandidate: Get; + /// Maximum bottom delegations (not counted) per candidate + #[pallet::constant] + type MaxBottomDelegationsPerCandidate: Get; + /// Maximum delegations per delegator + #[pallet::constant] + type MaxDelegationsPerDelegator: Get; + /// Minimum stake required for any account to be a collator candidate + #[pallet::constant] + type MinCandidateStk: Get>; + /// Minimum stake for any registered on-chain account to delegate + #[pallet::constant] + type MinDelegation: Get>; + /// Minimum stake for any registered on-chain account to be a delegator + #[pallet::constant] + type MinDelegatorStk: Get>; + /// Get the current block author + // type BlockAuthor: Get; + /// Handler to notify the runtime when a collator is paid. + /// If you don't need it, you can specify the type `()`. + type OnCollatorPayout: OnCollatorPayout>; + /// Handler to distribute a collator's reward. + /// To use the default implementation of minting rewards, specify the type `()`. + type PayoutCollatorReward: PayoutCollatorReward; + /// Handler to notify the runtime when a new round begin. + /// If you don't need it, you can specify the type `()`. + type OnNewRound: OnNewRound; + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; + } + + #[pallet::error] + pub enum Error { + DelegatorDNE, + DelegatorDNEinTopNorBottom, + DelegatorDNEInDelegatorSet, + CandidateDNE, + DelegationDNE, + DelegatorExists, + CandidateExists, + CandidateBondBelowMin, + InsufficientBalance, + DelegatorBondBelowMin, + DelegationBelowMin, + AlreadyOffline, + AlreadyActive, + DelegatorAlreadyLeaving, + DelegatorNotLeaving, + DelegatorCannotLeaveYet, + CannotDelegateIfLeaving, + CandidateAlreadyLeaving, + CandidateNotLeaving, + CandidateCannotLeaveYet, + CannotGoOnlineIfLeaving, + ExceedMaxDelegationsPerDelegator, + AlreadyDelegatedCandidate, + InvalidSchedule, + CannotSetBelowMin, + RoundLengthMustBeGreaterThanTotalSelectedCollators, + NoWritingSameValue, + TooLowCandidateCountWeightHintJoinCandidates, + TooLowCandidateCountWeightHintCancelLeaveCandidates, + TooLowCandidateCountToLeaveCandidates, + TooLowDelegationCountToDelegate, + TooLowCandidateDelegationCountToDelegate, + TooLowCandidateDelegationCountToLeaveCandidates, + TooLowDelegationCountToLeaveDelegators, + PendingCandidateRequestsDNE, + PendingCandidateRequestAlreadyExists, + PendingCandidateRequestNotDueYet, + PendingDelegationRequestDNE, + PendingDelegationRequestAlreadyExists, + PendingDelegationRequestNotDueYet, + CannotDelegateLessThanOrEqualToLowestBottomWhenFull, + PendingDelegationRevoke, + TooLowDelegationCountToAutoCompound, + TooLowCandidateAutoCompoundingDelegationCountToAutoCompound, + TooLowCandidateAutoCompoundingDelegationCountToDelegate, + } + + #[pallet::event] + #[pallet::generate_deposit(pub(crate) fn deposit_event)] + pub enum Event { + /// Started new round. + NewRound { + starting_block: T::BlockNumber, + round: RoundIndex, + selected_collators_number: u32, + total_balance: BalanceOf, + }, + /// Account joined the set of collator candidates. + JoinedCollatorCandidates { + account: T::AccountId, + amount_locked: BalanceOf, + new_total_amt_locked: BalanceOf, + }, + /// Candidate selected for collators. Total Exposed Amount includes all delegations. + CollatorChosen { + round: RoundIndex, + collator_account: T::AccountId, + total_exposed_amount: BalanceOf, + }, + /// Candidate requested to decrease a self bond. + CandidateBondLessRequested { + candidate: T::AccountId, + amount_to_decrease: BalanceOf, + execute_round: RoundIndex, + }, + /// Candidate has increased a self bond. + CandidateBondedMore { + candidate: T::AccountId, + amount: BalanceOf, + new_total_bond: BalanceOf, + }, + /// Candidate has decreased a self bond. + CandidateBondedLess { + candidate: T::AccountId, + amount: BalanceOf, + new_bond: BalanceOf, + }, + /// Candidate temporarily leave the set of collator candidates without unbonding. + CandidateWentOffline { candidate: T::AccountId }, + /// Candidate rejoins the set of collator candidates. + CandidateBackOnline { candidate: T::AccountId }, + /// Candidate has requested to leave the set of candidates. + CandidateScheduledExit { + exit_allowed_round: RoundIndex, + candidate: T::AccountId, + scheduled_exit: RoundIndex, + }, + /// Cancelled request to leave the set of candidates. + CancelledCandidateExit { candidate: T::AccountId }, + /// Cancelled request to decrease candidate's bond. + CancelledCandidateBondLess { + candidate: T::AccountId, + amount: BalanceOf, + execute_round: RoundIndex, + }, + /// Candidate has left the set of candidates. + CandidateLeft { + ex_candidate: T::AccountId, + unlocked_amount: BalanceOf, + new_total_amt_locked: BalanceOf, + }, + /// Delegator requested to decrease a bond for the collator candidate. + DelegationDecreaseScheduled { + delegator: T::AccountId, + candidate: T::AccountId, + amount_to_decrease: BalanceOf, + execute_round: RoundIndex, + }, + // Delegation increased. + DelegationIncreased { + delegator: T::AccountId, + candidate: T::AccountId, + amount: BalanceOf, + in_top: bool, + }, + // Delegation decreased. + DelegationDecreased { + delegator: T::AccountId, + candidate: T::AccountId, + amount: BalanceOf, + in_top: bool, + }, + /// Delegator requested to leave the set of delegators. + DelegatorExitScheduled { + round: RoundIndex, + delegator: T::AccountId, + scheduled_exit: RoundIndex, + }, + /// Delegator requested to revoke delegation. + DelegationRevocationScheduled { + round: RoundIndex, + delegator: T::AccountId, + candidate: T::AccountId, + scheduled_exit: RoundIndex, + }, + /// Delegator has left the set of delegators. + DelegatorLeft { delegator: T::AccountId, unstaked_amount: BalanceOf }, + /// Delegation revoked. + DelegationRevoked { + delegator: T::AccountId, + candidate: T::AccountId, + unstaked_amount: BalanceOf, + }, + /// Delegation kicked. + DelegationKicked { + delegator: T::AccountId, + candidate: T::AccountId, + unstaked_amount: BalanceOf, + }, + /// Cancelled a pending request to exit the set of delegators. + DelegatorExitCancelled { delegator: T::AccountId }, + /// Cancelled request to change an existing delegation. + CancelledDelegationRequest { + delegator: T::AccountId, + cancelled_request: CancelledScheduledRequest>, + collator: T::AccountId, + }, + /// New delegation (increase of the existing one). + Delegation { + delegator: T::AccountId, + locked_amount: BalanceOf, + candidate: T::AccountId, + delegator_position: DelegatorAdded>, + auto_compound: Percent, + }, + /// Delegation from candidate state has been remove. + DelegatorLeftCandidate { + delegator: T::AccountId, + candidate: T::AccountId, + unstaked_amount: BalanceOf, + total_candidate_staked: BalanceOf, + }, + /// Paid the account (delegator or collator) the balance as liquid rewards. + Rewarded { account: T::AccountId, rewards: BalanceOf }, + /// Transferred to account which holds funds reserved for parachain bond. + ReservedForParachainBond { account: T::AccountId, value: BalanceOf }, + /// Account (re)set for parachain bond treasury. + ParachainBondAccountSet { old: T::AccountId, new: T::AccountId }, + /// Percent of inflation reserved for parachain bond (re)set. + ParachainBondReservePercentSet { old: Percent, new: Percent }, + /// Annual inflation input (first 3) was used to derive new per-round inflation (last 3) + InflationSet { + annual_min: Perbill, + annual_ideal: Perbill, + annual_max: Perbill, + round_min: Perbill, + round_ideal: Perbill, + round_max: Perbill, + }, + /// Staking expectations set. + StakeExpectationsSet { + expect_min: BalanceOf, + expect_ideal: BalanceOf, + expect_max: BalanceOf, + }, + /// Set total selected candidates to this value. + TotalSelectedSet { old: u32, new: u32 }, + /// Set collator commission to this value. + CollatorCommissionSet { old: Perbill, new: Perbill }, + /// Set blocks per round + BlocksPerRoundSet { + current_round: RoundIndex, + first_block: T::BlockNumber, + old: u32, + new: u32, + new_per_round_inflation_min: Perbill, + new_per_round_inflation_ideal: Perbill, + new_per_round_inflation_max: Perbill, + }, + /// Auto-compounding reward percent was set for a delegation. + AutoCompoundSet { candidate: T::AccountId, delegator: T::AccountId, value: Percent }, + /// Compounded a portion of rewards towards the delegation. + Compounded { candidate: T::AccountId, delegator: T::AccountId, amount: BalanceOf }, + } + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_initialize(n: T::BlockNumber) -> Weight { + let mut weight = T::WeightInfo::base_on_initialize(); + + let mut round = >::get(); + + if round.should_update(n) { + // mutate round + round.update(n); + // notify that new round begin + weight = weight.saturating_add(T::OnNewRound::on_new_round(round.current)); + // pay all stakers for T::RewardPaymentDelay rounds ago + weight = weight.saturating_add(Self::prepare_staking_payouts(round.current)); + // select top collator candidates for next round + let (extra_weight, collator_count, _delegation_count, total_staked) = + Self::select_top_candidates(round.current); + weight = weight.saturating_add(extra_weight); + // start next round + >::put(round); + // snapshot total stake + >::insert(round.current, >::get()); + Self::deposit_event(Event::NewRound { + starting_block: round.first, + round: round.current, + selected_collators_number: collator_count, + total_balance: total_staked, + }); + // account for Round and Staked writes + weight = weight.saturating_add(T::DbWeight::get().reads_writes(0, 2)); + } else { + weight = weight.saturating_add(Self::handle_delayed_payouts(round.current)); + } + + // add on_finalize weight + // read: Author, Points, AwardedPts + // write: Points, AwardedPts + weight = weight.saturating_add(T::DbWeight::get().reads_writes(3, 2)); + weight + } + } + + #[pallet::storage] + #[pallet::getter(fn collator_commission)] + /// Commission percent taken off of rewards for all collators + type CollatorCommission = StorageValue<_, Perbill, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn total_selected)] + /// The total candidates selected every round + pub(crate) type TotalSelected = StorageValue<_, u32, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn parachain_bond_info)] + /// Parachain bond config info { account, percent_of_inflation } + pub(crate) type ParachainBondInfo = + StorageValue<_, ParachainBondConfig, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn round)] + /// Current round index and next round scheduled transition + pub(crate) type Round = StorageValue<_, RoundInfo, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn delegator_state)] + /// Get delegator state associated with an account if account is delegating else None + pub(crate) type DelegatorState = StorageMap< + _, + Twox64Concat, + T::AccountId, + Delegator>, + OptionQuery, + >; + + #[pallet::storage] + #[pallet::getter(fn candidate_info)] + /// Get collator candidate info associated with an account if account is candidate else None + pub(crate) type CandidateInfo = + StorageMap<_, Twox64Concat, T::AccountId, CandidateMetadata>, OptionQuery>; + + /// Stores outstanding delegation requests per collator. + #[pallet::storage] + #[pallet::getter(fn delegation_scheduled_requests)] + pub(crate) type DelegationScheduledRequests = StorageMap< + _, + Blake2_128Concat, + T::AccountId, + Vec>>, + ValueQuery, + >; + + pub struct AddGet { + _phantom: PhantomData<(T, R)>, + } + impl Get for AddGet + where + T: Get, + R: Get, + { + fn get() -> u32 { + T::get() + R::get() + } + } + + /// Stores auto-compounding configuration per collator. + #[pallet::storage] + #[pallet::getter(fn auto_compounding_delegations)] + pub(crate) type AutoCompoundingDelegations = StorageMap< + _, + Blake2_128Concat, + T::AccountId, + BoundedVec< + AutoCompoundConfig, + AddGet, + >, + ValueQuery, + >; + + #[pallet::storage] + #[pallet::getter(fn top_delegations)] + /// Top delegations for collator candidate + pub(crate) type TopDelegations = StorageMap< + _, + Twox64Concat, + T::AccountId, + Delegations>, + OptionQuery, + >; + + #[pallet::storage] + #[pallet::getter(fn bottom_delegations)] + /// Bottom delegations for collator candidate + pub(crate) type BottomDelegations = StorageMap< + _, + Twox64Concat, + T::AccountId, + Delegations>, + OptionQuery, + >; + + #[pallet::storage] + #[pallet::getter(fn selected_candidates)] + /// The collator candidates selected for the current round + type SelectedCandidates = StorageValue<_, Vec, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn total)] + /// Total capital locked by this staking pallet + pub(crate) type Total = StorageValue<_, BalanceOf, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn candidate_pool)] + /// The pool of collator candidates, each with their total backing stake + pub(crate) type CandidatePool = + StorageValue<_, OrderedSet>>, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn at_stake)] + /// Snapshot of collator delegation stake at the start of the round + pub type AtStake = StorageDoubleMap< + _, + Twox64Concat, + RoundIndex, + Twox64Concat, + T::AccountId, + CollatorSnapshot>, + ValueQuery, + >; + + #[pallet::storage] + #[pallet::getter(fn delayed_payouts)] + /// Delayed payouts + pub type DelayedPayouts = + StorageMap<_, Twox64Concat, RoundIndex, DelayedPayout>, OptionQuery>; + + #[pallet::storage] + #[pallet::getter(fn staked)] + /// Total counted stake for selected candidates in the round + pub type Staked = StorageMap<_, Twox64Concat, RoundIndex, BalanceOf, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn inflation_config)] + /// Inflation configuration + pub type InflationConfig = StorageValue<_, InflationInfo>, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn points)] + /// Total points awarded to collators for block production in the round + pub type Points = StorageMap<_, Twox64Concat, RoundIndex, RewardPoint, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn awarded_pts)] + /// Points for each collator per round + pub type AwardedPts = StorageDoubleMap< + _, + Twox64Concat, + RoundIndex, + Twox64Concat, + T::AccountId, + RewardPoint, + ValueQuery, + >; + + #[pallet::genesis_config] + pub struct GenesisConfig { + /// Initialize balance and register all as collators: `(collator AccountId, balance Amount)` + pub candidates: Vec<(T::AccountId, BalanceOf)>, + /// Initialize balance and make delegations: + /// `(delegator AccountId, collator AccountId, delegation Amount, auto-compounding Percent)` + pub delegations: Vec<(T::AccountId, T::AccountId, BalanceOf, Percent)>, + /// Inflation configuration + pub inflation_config: InflationInfo>, + /// Default fixed percent a collator takes off the top of due rewards + pub collator_commission: Perbill, + /// Default percent of inflation set aside for parachain bond every round + pub parachain_bond_reserve_percent: Percent, + /// Default number of blocks in a round + pub blocks_per_round: u32, + /// Number of selected candidates every round. Cannot be lower than MinSelectedCandidates + pub num_selected_candidates: u32, + } + + #[cfg(feature = "std")] + impl Default for GenesisConfig { + fn default() -> Self { + Self { + candidates: vec![], + delegations: vec![], + inflation_config: Default::default(), + collator_commission: Default::default(), + parachain_bond_reserve_percent: Default::default(), + blocks_per_round: 1u32, + num_selected_candidates: T::MinSelectedCandidates::get(), + } + } + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + assert!(self.blocks_per_round > 0, "Blocks per round must be > 0"); + >::put(self.inflation_config.clone()); + let mut candidate_count = 0u32; + // Initialize the candidates + for &(ref candidate, balance) in &self.candidates { + assert!( + >::get_collator_stakable_free_balance(candidate) >= balance, + "Account does not have enough balance to bond as a candidate." + ); + if let Err(error) = >::join_candidates( + T::RuntimeOrigin::from(Some(candidate.clone()).into()), + balance, + candidate_count, + ) { + log::warn!("Join candidates failed in genesis with error {:?}", error); + } else { + candidate_count = candidate_count.saturating_add(1u32); + } + } + + let mut col_delegator_count: BTreeMap = BTreeMap::new(); + let mut col_auto_compound_delegator_count: BTreeMap = + BTreeMap::new(); + let mut del_delegation_count: BTreeMap = BTreeMap::new(); + // Initialize the delegations + for &(ref delegator, ref target, balance, auto_compound) in &self.delegations { + assert!( + >::get_delegator_stakable_free_balance(delegator) >= balance, + "Account does not have enough balance to place delegation." + ); + let cd_count = + if let Some(x) = col_delegator_count.get(target) { *x } else { 0u32 }; + let dd_count = + if let Some(x) = del_delegation_count.get(delegator) { *x } else { 0u32 }; + let cd_auto_compound_count = + col_auto_compound_delegator_count.get(target).cloned().unwrap_or_default(); + if let Err(error) = >::delegate_with_auto_compound( + T::RuntimeOrigin::from(Some(delegator.clone()).into()), + target.clone(), + balance, + auto_compound, + cd_count, + cd_auto_compound_count, + dd_count, + ) { + log::warn!("Delegate failed in genesis with error {:?}", error); + } else { + if let Some(x) = col_delegator_count.get_mut(target) { + *x = x.saturating_add(1u32); + } else { + col_delegator_count.insert(target.clone(), 1u32); + }; + if let Some(x) = del_delegation_count.get_mut(delegator) { + *x = x.saturating_add(1u32); + } else { + del_delegation_count.insert(delegator.clone(), 1u32); + }; + if !auto_compound.is_zero() { + col_auto_compound_delegator_count + .entry(target.clone()) + .and_modify(|x| *x = x.saturating_add(1)) + .or_insert(1); + } + } + } + // Set collator commission to default config + >::put(self.collator_commission); + // Set parachain bond config to default config + >::put(ParachainBondConfig { + // must be set soon; if not => due inflation will be sent to collators/delegators + account: T::AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) + .expect("infinite length input; no invalid inputs for type; qed"), + percent: self.parachain_bond_reserve_percent, + }); + // Set total selected candidates to value from config + assert!( + self.num_selected_candidates >= T::MinSelectedCandidates::get(), + "{:?}", + Error::::CannotSetBelowMin + ); + >::put(self.num_selected_candidates); + // Choose top TotalSelected collator candidates + let (_, v_count, _, total_staked) = >::select_top_candidates(1u32); + // Start Round 1 at Block 0 + let round: RoundInfo = + RoundInfo::new(1u32, 0u32.into(), self.blocks_per_round); + >::put(round); + // Snapshot total stake + >::insert(1u32, >::get()); + >::deposit_event(Event::NewRound { + starting_block: T::BlockNumber::zero(), + round: 1u32, + selected_collators_number: v_count, + total_balance: total_staked, + }); + } + } + + #[pallet::call] + impl Pallet { + /// Set the expectations for total staked. These expectations determine the issuance for + /// the round according to logic in `fn compute_issuance` + #[pallet::call_index(0)] + #[pallet::weight(::WeightInfo::set_staking_expectations())] + pub fn set_staking_expectations( + origin: OriginFor, + expectations: Range>, + ) -> DispatchResultWithPostInfo { + T::MonetaryGovernanceOrigin::ensure_origin(origin)?; + ensure!(expectations.is_valid(), Error::::InvalidSchedule); + let mut config = >::get(); + ensure!(config.expect != expectations, Error::::NoWritingSameValue); + config.set_expectations(expectations); + Self::deposit_event(Event::StakeExpectationsSet { + expect_min: config.expect.min, + expect_ideal: config.expect.ideal, + expect_max: config.expect.max, + }); + >::put(config); + Ok(().into()) + } + + /// Set the annual inflation rate to derive per-round inflation + #[pallet::call_index(1)] + #[pallet::weight(::WeightInfo::set_inflation())] + pub fn set_inflation( + origin: OriginFor, + schedule: Range, + ) -> DispatchResultWithPostInfo { + T::MonetaryGovernanceOrigin::ensure_origin(origin)?; + ensure!(schedule.is_valid(), Error::::InvalidSchedule); + let mut config = >::get(); + ensure!(config.annual != schedule, Error::::NoWritingSameValue); + config.annual = schedule; + config.set_round_from_annual::(schedule); + Self::deposit_event(Event::InflationSet { + annual_min: config.annual.min, + annual_ideal: config.annual.ideal, + annual_max: config.annual.max, + round_min: config.round.min, + round_ideal: config.round.ideal, + round_max: config.round.max, + }); + >::put(config); + Ok(().into()) + } + + /// Set the account that will hold funds set aside for parachain bond + #[pallet::call_index(2)] + #[pallet::weight(::WeightInfo::set_parachain_bond_account())] + pub fn set_parachain_bond_account( + origin: OriginFor, + new: T::AccountId, + ) -> DispatchResultWithPostInfo { + T::MonetaryGovernanceOrigin::ensure_origin(origin)?; + let ParachainBondConfig { account: old, percent } = >::get(); + ensure!(old != new, Error::::NoWritingSameValue); + >::put(ParachainBondConfig { account: new.clone(), percent }); + Self::deposit_event(Event::ParachainBondAccountSet { old, new }); + Ok(().into()) + } + + /// Set the percent of inflation set aside for parachain bond + #[pallet::call_index(3)] + #[pallet::weight(::WeightInfo::set_parachain_bond_reserve_percent())] + pub fn set_parachain_bond_reserve_percent( + origin: OriginFor, + new: Percent, + ) -> DispatchResultWithPostInfo { + T::MonetaryGovernanceOrigin::ensure_origin(origin)?; + let ParachainBondConfig { account, percent: old } = >::get(); + ensure!(old != new, Error::::NoWritingSameValue); + >::put(ParachainBondConfig { account, percent: new }); + Self::deposit_event(Event::ParachainBondReservePercentSet { old, new }); + Ok(().into()) + } + + /// Set the total number of collator candidates selected per round + /// - changes are not applied until the start of the next round + #[pallet::call_index(4)] + #[pallet::weight(::WeightInfo::set_total_selected())] + pub fn set_total_selected(origin: OriginFor, new: u32) -> DispatchResultWithPostInfo { + frame_system::ensure_root(origin)?; + ensure!(new >= T::MinSelectedCandidates::get(), Error::::CannotSetBelowMin); + let old = >::get(); + ensure!(old != new, Error::::NoWritingSameValue); + ensure!( + new < >::get().length, + Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, + ); + >::put(new); + Self::deposit_event(Event::TotalSelectedSet { old, new }); + Ok(().into()) + } + + /// Set the commission for all collators + #[pallet::call_index(5)] + #[pallet::weight(::WeightInfo::set_collator_commission())] + pub fn set_collator_commission( + origin: OriginFor, + new: Perbill, + ) -> DispatchResultWithPostInfo { + frame_system::ensure_root(origin)?; + let old = >::get(); + ensure!(old != new, Error::::NoWritingSameValue); + >::put(new); + Self::deposit_event(Event::CollatorCommissionSet { old, new }); + Ok(().into()) + } + + /// Set blocks per round + /// - if called with `new` less than length of current round, will transition immediately + /// in the next block + /// - also updates per-round inflation config + #[pallet::call_index(6)] + #[pallet::weight(::WeightInfo::set_blocks_per_round())] + pub fn set_blocks_per_round(origin: OriginFor, new: u32) -> DispatchResultWithPostInfo { + frame_system::ensure_root(origin)?; + ensure!(new >= T::MinBlocksPerRound::get(), Error::::CannotSetBelowMin); + let mut round = >::get(); + let (now, first, old) = (round.current, round.first, round.length); + ensure!(old != new, Error::::NoWritingSameValue); + ensure!( + new > >::get(), + Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, + ); + round.length = new; + // update per-round inflation given new rounds per year + let mut inflation_config = >::get(); + inflation_config.reset_round(new); + >::put(round); + Self::deposit_event(Event::BlocksPerRoundSet { + current_round: now, + first_block: first, + old, + new, + new_per_round_inflation_min: inflation_config.round.min, + new_per_round_inflation_ideal: inflation_config.round.ideal, + new_per_round_inflation_max: inflation_config.round.max, + }); + >::put(inflation_config); + Ok(().into()) + } + + /// Join the set of collator candidates + #[pallet::call_index(7)] + #[pallet::weight(::WeightInfo::join_candidates(*candidate_count))] + pub fn join_candidates( + origin: OriginFor, + bond: BalanceOf, + candidate_count: u32, + ) -> DispatchResultWithPostInfo { + let acc = ensure_signed(origin)?; + ensure!(!Self::is_candidate(&acc), Error::::CandidateExists); + ensure!(!Self::is_delegator(&acc), Error::::DelegatorExists); + ensure!(bond >= T::MinCandidateStk::get(), Error::::CandidateBondBelowMin); + let mut candidates = >::get(); + let old_count = candidates.0.len() as u32; + ensure!( + candidate_count >= old_count, + Error::::TooLowCandidateCountWeightHintJoinCandidates + ); + ensure!( + candidates.insert(Bond { owner: acc.clone(), amount: bond }), + Error::::CandidateExists + ); + ensure!( + Self::get_collator_stakable_free_balance(&acc) >= bond, + Error::::InsufficientBalance, + ); + T::Currency::set_lock(COLLATOR_LOCK_ID, &acc, bond, WithdrawReasons::all()); + let candidate = CandidateMetadata::new(bond); + >::insert(&acc, candidate); + let empty_delegations: Delegations> = Default::default(); + // insert empty top delegations + >::insert(&acc, empty_delegations.clone()); + // insert empty bottom delegations + >::insert(&acc, empty_delegations); + >::put(candidates); + let new_total = >::get().saturating_add(bond); + >::put(new_total); + Self::deposit_event(Event::JoinedCollatorCandidates { + account: acc, + amount_locked: bond, + new_total_amt_locked: new_total, + }); + Ok(().into()) + } + + /// Request to leave the set of candidates. If successful, the account is immediately + /// removed from the candidate pool to prevent selection as a collator. + #[pallet::call_index(8)] + #[pallet::weight(::WeightInfo::schedule_leave_candidates(*candidate_count))] + pub fn schedule_leave_candidates( + origin: OriginFor, + candidate_count: u32, + ) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + let (now, when) = state.schedule_leave::()?; + let mut candidates = >::get(); + ensure!( + candidate_count >= candidates.0.len() as u32, + Error::::TooLowCandidateCountToLeaveCandidates + ); + if candidates.remove(&Bond::from_owner(collator.clone())) { + >::put(candidates); + } + >::insert(&collator, state); + Self::deposit_event(Event::CandidateScheduledExit { + exit_allowed_round: now, + candidate: collator, + scheduled_exit: when, + }); + Ok(().into()) + } + + /// Execute leave candidates request + #[pallet::call_index(9)] + #[pallet::weight( + ::WeightInfo::execute_leave_candidates(*candidate_delegation_count) + )] + pub fn execute_leave_candidates( + origin: OriginFor, + candidate: T::AccountId, + candidate_delegation_count: u32, + ) -> DispatchResultWithPostInfo { + ensure_signed(origin)?; + let state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; + ensure!( + state.delegation_count <= candidate_delegation_count, + Error::::TooLowCandidateDelegationCountToLeaveCandidates + ); + state.can_leave::()?; + let return_stake = |bond: Bond>| -> DispatchResult { + // remove delegation from delegator state + let mut delegator = DelegatorState::::get(&bond.owner).expect( + "Collator state and delegator state are consistent. + Collator state has a record of this delegation. Therefore, + Delegator state also has a record. qed.", + ); + + if let Some(remaining) = delegator.rm_delegation::(&candidate) { + Self::delegation_remove_request_with_state( + &candidate, + &bond.owner, + &mut delegator, + ); + >::remove_auto_compound(&candidate, &bond.owner); + + if remaining.is_zero() { + // we do not remove the scheduled delegation requests from other collators + // since it is assumed that they were removed incrementally before only the + // last delegation was left. + >::remove(&bond.owner); + T::Currency::remove_lock(DELEGATOR_LOCK_ID, &bond.owner); + } else { + >::insert(&bond.owner, delegator); + } + } else { + // TODO: review. we assume here that this delegator has no remaining staked + // balance, so we ensure the lock is cleared + T::Currency::remove_lock(DELEGATOR_LOCK_ID, &bond.owner); + } + Ok(()) + }; + // total backing stake is at least the candidate self bond + let mut total_backing = state.bond; + // return all top delegations + let top_delegations = + >::take(&candidate).expect("CandidateInfo existence checked"); + for bond in top_delegations.delegations { + return_stake(bond)?; + } + total_backing = total_backing.saturating_add(top_delegations.total); + // return all bottom delegations + let bottom_delegations = + >::take(&candidate).expect("CandidateInfo existence checked"); + for bond in bottom_delegations.delegations { + return_stake(bond)?; + } + total_backing = total_backing.saturating_add(bottom_delegations.total); + // return stake to collator + T::Currency::remove_lock(COLLATOR_LOCK_ID, &candidate); + >::remove(&candidate); + >::remove(&candidate); + >::remove(&candidate); + >::remove(&candidate); + >::remove(&candidate); + let new_total_staked = >::get().saturating_sub(total_backing); + >::put(new_total_staked); + Self::deposit_event(Event::CandidateLeft { + ex_candidate: candidate, + unlocked_amount: total_backing, + new_total_amt_locked: new_total_staked, + }); + Ok(().into()) + } + + /// Cancel open request to leave candidates + /// - only callable by collator account + /// - result upon successful call is the candidate is active in the candidate pool + #[pallet::call_index(10)] + #[pallet::weight(::WeightInfo::cancel_leave_candidates(*candidate_count))] + pub fn cancel_leave_candidates( + origin: OriginFor, + candidate_count: u32, + ) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + ensure!(state.is_leaving(), Error::::CandidateNotLeaving); + state.go_online(); + let mut candidates = >::get(); + ensure!( + candidates.0.len() as u32 <= candidate_count, + Error::::TooLowCandidateCountWeightHintCancelLeaveCandidates + ); + ensure!( + candidates.insert(Bond { owner: collator.clone(), amount: state.total_counted }), + Error::::AlreadyActive + ); + >::put(candidates); + >::insert(&collator, state); + Self::deposit_event(Event::CancelledCandidateExit { candidate: collator }); + Ok(().into()) + } + + /// Temporarily leave the set of collator candidates without unbonding + #[pallet::call_index(11)] + #[pallet::weight(::WeightInfo::go_offline())] + pub fn go_offline(origin: OriginFor) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + ensure!(state.is_active(), Error::::AlreadyOffline); + state.go_offline(); + let mut candidates = >::get(); + if candidates.remove(&Bond::from_owner(collator.clone())) { + >::put(candidates); + } + >::insert(&collator, state); + Self::deposit_event(Event::CandidateWentOffline { candidate: collator }); + Ok(().into()) + } + + /// Rejoin the set of collator candidates if previously had called `go_offline` + #[pallet::call_index(12)] + #[pallet::weight(::WeightInfo::go_online())] + pub fn go_online(origin: OriginFor) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + ensure!(!state.is_active(), Error::::AlreadyActive); + ensure!(!state.is_leaving(), Error::::CannotGoOnlineIfLeaving); + state.go_online(); + let mut candidates = >::get(); + ensure!( + candidates.insert(Bond { owner: collator.clone(), amount: state.total_counted }), + Error::::AlreadyActive + ); + >::put(candidates); + >::insert(&collator, state); + Self::deposit_event(Event::CandidateBackOnline { candidate: collator }); + Ok(().into()) + } + + /// Increase collator candidate self bond by `more` + #[pallet::call_index(13)] + #[pallet::weight(::WeightInfo::candidate_bond_more())] + pub fn candidate_bond_more( + origin: OriginFor, + more: BalanceOf, + ) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + state.bond_more::(collator.clone(), more)?; + let (is_active, total_counted) = (state.is_active(), state.total_counted); + >::insert(&collator, state); + if is_active { + Self::update_active(collator, total_counted); + } + Ok(().into()) + } + + /// Request by collator candidate to decrease self bond by `less` + #[pallet::call_index(14)] + #[pallet::weight(::WeightInfo::schedule_candidate_bond_less())] + pub fn schedule_candidate_bond_less( + origin: OriginFor, + less: BalanceOf, + ) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + let when = state.schedule_bond_less::(less)?; + >::insert(&collator, state); + Self::deposit_event(Event::CandidateBondLessRequested { + candidate: collator, + amount_to_decrease: less, + execute_round: when, + }); + Ok(().into()) + } + + /// Execute pending request to adjust the collator candidate self bond + #[pallet::call_index(15)] + #[pallet::weight(::WeightInfo::execute_candidate_bond_less())] + pub fn execute_candidate_bond_less( + origin: OriginFor, + candidate: T::AccountId, + ) -> DispatchResultWithPostInfo { + ensure_signed(origin)?; // we may want to reward this if caller != candidate + let mut state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; + state.execute_bond_less::(candidate.clone())?; + >::insert(&candidate, state); + Ok(().into()) + } + + /// Cancel pending request to adjust the collator candidate self bond + #[pallet::call_index(16)] + #[pallet::weight(::WeightInfo::cancel_candidate_bond_less())] + pub fn cancel_candidate_bond_less(origin: OriginFor) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; + state.cancel_bond_less::(collator.clone())?; + >::insert(&collator, state); + Ok(().into()) + } + + /// If caller is not a delegator and not a collator, then join the set of delegators + /// If caller is a delegator, then makes delegation to change their delegation state + #[pallet::call_index(17)] + #[pallet::weight( + ::WeightInfo::delegate( + *candidate_delegation_count, + *delegation_count + ) + )] + pub fn delegate( + origin: OriginFor, + candidate: T::AccountId, + amount: BalanceOf, + candidate_delegation_count: u32, + delegation_count: u32, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + >::delegate_with_auto_compound( + candidate, + delegator, + amount, + Percent::zero(), + candidate_delegation_count, + 0, + delegation_count, + ) + } + + /// If caller is not a delegator and not a collator, then join the set of delegators + /// If caller is a delegator, then makes delegation to change their delegation state + /// Sets the auto-compound config for the delegation + #[pallet::call_index(18)] + #[pallet::weight( + ::WeightInfo::delegate_with_auto_compound( + *candidate_delegation_count, + *candidate_auto_compounding_delegation_count, + *delegation_count, + ) + )] + pub fn delegate_with_auto_compound( + origin: OriginFor, + candidate: T::AccountId, + amount: BalanceOf, + auto_compound: Percent, + candidate_delegation_count: u32, + candidate_auto_compounding_delegation_count: u32, + delegation_count: u32, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + >::delegate_with_auto_compound( + candidate, + delegator, + amount, + auto_compound, + candidate_delegation_count, + candidate_auto_compounding_delegation_count, + delegation_count, + ) + } + + /// DEPRECATED use batch util with schedule_revoke_delegation for all delegations + /// Request to leave the set of delegators. If successful, the caller is scheduled to be + /// allowed to exit via a [DelegationAction::Revoke] towards all existing delegations. + /// Success forbids future delegation requests until the request is invoked or cancelled. + #[pallet::call_index(19)] + #[pallet::weight(::WeightInfo::schedule_leave_delegators())] + pub fn schedule_leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + Self::delegator_schedule_revoke_all(delegator) + } + + /// DEPRECATED use batch util with execute_delegation_request for all delegations + /// Execute the right to exit the set of delegators and revoke all ongoing delegations. + #[pallet::call_index(20)] + #[pallet::weight(::WeightInfo::execute_leave_delegators(*delegation_count))] + pub fn execute_leave_delegators( + origin: OriginFor, + delegator: T::AccountId, + delegation_count: u32, + ) -> DispatchResultWithPostInfo { + ensure_signed(origin)?; + Self::delegator_execute_scheduled_revoke_all(delegator, delegation_count) + } + + /// DEPRECATED use batch util with cancel_delegation_request for all delegations + /// Cancel a pending request to exit the set of delegators. Success clears the pending exit + /// request (thereby resetting the delay upon another `leave_delegators` call). + #[pallet::call_index(21)] + #[pallet::weight(::WeightInfo::cancel_leave_delegators())] + pub fn cancel_leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + Self::delegator_cancel_scheduled_revoke_all(delegator) + } + + /// Request to revoke an existing delegation. If successful, the delegation is scheduled + /// to be allowed to be revoked via the `execute_delegation_request` extrinsic. + /// The delegation receives no rewards for the rounds while a revoke is pending. + /// A revoke may not be performed if any other scheduled request is pending. + #[pallet::call_index(22)] + #[pallet::weight(::WeightInfo::schedule_revoke_delegation())] + pub fn schedule_revoke_delegation( + origin: OriginFor, + collator: T::AccountId, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + Self::delegation_schedule_revoke(collator, delegator) + } + + /// Bond more for delegators wrt a specific collator candidate. + #[pallet::call_index(23)] + #[pallet::weight(::WeightInfo::delegator_bond_more())] + pub fn delegator_bond_more( + origin: OriginFor, + candidate: T::AccountId, + more: BalanceOf, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + let in_top = Self::delegation_bond_more_without_event( + delegator.clone(), + candidate.clone(), + more, + )?; + Pallet::::deposit_event(Event::DelegationIncreased { + delegator, + candidate, + amount: more, + in_top, + }); + + Ok(().into()) + } + + /// Request bond less for delegators wrt a specific collator candidate. The delegation's + /// rewards for rounds while the request is pending use the reduced bonded amount. + /// A bond less may not be performed if any other scheduled request is pending. + #[pallet::call_index(24)] + #[pallet::weight(::WeightInfo::schedule_delegator_bond_less())] + pub fn schedule_delegator_bond_less( + origin: OriginFor, + candidate: T::AccountId, + less: BalanceOf, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + Self::delegation_schedule_bond_decrease(candidate, delegator, less) + } + + /// Execute pending request to change an existing delegation + #[pallet::call_index(25)] + #[pallet::weight(::WeightInfo::execute_delegator_bond_less())] + pub fn execute_delegation_request( + origin: OriginFor, + delegator: T::AccountId, + candidate: T::AccountId, + ) -> DispatchResultWithPostInfo { + ensure_signed(origin)?; // we may want to reward caller if caller != delegator + Self::delegation_execute_scheduled_request(candidate, delegator) + } + + /// Cancel request to change an existing delegation. + #[pallet::call_index(26)] + #[pallet::weight(::WeightInfo::cancel_delegator_bond_less())] + pub fn cancel_delegation_request( + origin: OriginFor, + candidate: T::AccountId, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + Self::delegation_cancel_request(candidate, delegator) + } + + /// Sets the auto-compounding reward percentage for a delegation. + #[pallet::call_index(27)] + #[pallet::weight(::WeightInfo::set_auto_compound( + *candidate_auto_compounding_delegation_count_hint, + *delegation_count_hint, + ))] + pub fn set_auto_compound( + origin: OriginFor, + candidate: T::AccountId, + value: Percent, + candidate_auto_compounding_delegation_count_hint: u32, + delegation_count_hint: u32, + ) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + >::set_auto_compound( + candidate, + delegator, + value, + candidate_auto_compounding_delegation_count_hint, + delegation_count_hint, + ) + } + + /// Hotfix to remove existing empty entries for candidates that have left. + #[pallet::call_index(28)] + #[pallet::weight( + T::DbWeight::get().reads_writes(2 * candidates.len() as u64, candidates.len() as u64) + )] + pub fn hotfix_remove_delegation_requests_exited_candidates( + origin: OriginFor, + candidates: Vec, + ) -> DispatchResult { + ensure_signed(origin)?; + ensure!(candidates.len() < 100, >::InsufficientBalance); + for candidate in &candidates { + ensure!( + >::get(candidate).is_none(), + >::CandidateNotLeaving + ); + ensure!( + >::get(candidate).is_empty(), + >::CandidateNotLeaving + ); + } + + for candidate in candidates { + >::remove(candidate); + } + + Ok(()) + } + } + + /// Represents a payout made via `pay_one_collator_reward`. + pub(crate) enum RewardPayment { + /// A collator was paid + Paid, + /// A collator was skipped for payment. This can happen if they haven't been awarded any + /// points, that is, they did not produce any blocks. + Skipped, + /// All collator payments have been processed. + Finished, + } + + impl Pallet { + pub fn is_delegator(acc: &T::AccountId) -> bool { + >::get(acc).is_some() + } + pub fn is_candidate(acc: &T::AccountId) -> bool { + >::get(acc).is_some() + } + pub fn is_selected_candidate(acc: &T::AccountId) -> bool { + >::get().binary_search(acc).is_ok() + } + /// Returns an account's free balance which is not locked in delegation staking + pub fn get_delegator_stakable_free_balance(acc: &T::AccountId) -> BalanceOf { + let mut balance = T::Currency::free_balance(acc); + if let Some(state) = >::get(acc) { + balance = balance.saturating_sub(state.total()); + } + balance + } + /// Returns an account's free balance which is not locked in collator staking + pub fn get_collator_stakable_free_balance(acc: &T::AccountId) -> BalanceOf { + let mut balance = T::Currency::free_balance(acc); + if let Some(info) = >::get(acc) { + balance = balance.saturating_sub(info.bond); + } + balance + } + /// Returns a delegations auto-compound value. + pub fn delegation_auto_compound( + candidate: &T::AccountId, + delegator: &T::AccountId, + ) -> Percent { + >::auto_compound(candidate, delegator) + } + /// Caller must ensure candidate is active before calling + pub(crate) fn update_active(candidate: T::AccountId, total: BalanceOf) { + let mut candidates = >::get(); + candidates.remove(&Bond::from_owner(candidate.clone())); + candidates.insert(Bond { owner: candidate, amount: total }); + >::put(candidates); + } + /// Compute round issuance based on total staked for the given round + fn compute_issuance(staked: BalanceOf) -> BalanceOf { + let config = >::get(); + let round_issuance = crate::inflation::round_issuance_range::(config.round); + // TODO: consider interpolation instead of bounded range + if staked < config.expect.min { + round_issuance.min + } else if staked > config.expect.max { + round_issuance.max + } else { + round_issuance.ideal + } + } + /// Remove delegation from candidate state + /// Amount input should be retrieved from delegator and it informs the storage lookups + pub(crate) fn delegator_leaves_candidate( + candidate: T::AccountId, + delegator: T::AccountId, + amount: BalanceOf, + ) -> DispatchResult { + let mut state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; + state.rm_delegation_if_exists::(&candidate, delegator.clone(), amount)?; + let new_total_locked = >::get().saturating_sub(amount); + >::put(new_total_locked); + let new_total = state.total_counted; + >::insert(&candidate, state); + Self::deposit_event(Event::DelegatorLeftCandidate { + delegator, + candidate, + unstaked_amount: amount, + total_candidate_staked: new_total, + }); + Ok(()) + } + pub(crate) fn prepare_staking_payouts(now: RoundIndex) -> Weight { + // payout is now - delay rounds ago => now - delay > 0 else return early + let delay = T::RewardPaymentDelay::get(); + if now <= delay { + return Weight::zero() + } + let round_to_payout = now.saturating_sub(delay); + let total_points = >::get(round_to_payout); + if total_points.is_zero() { + return Weight::zero() + } + let total_staked = >::take(round_to_payout); + let total_issuance = Self::compute_issuance(total_staked); + let mut left_issuance = total_issuance; + // reserve portion of issuance for parachain bond account + let bond_config = >::get(); + let parachain_bond_reserve = bond_config.percent * total_issuance; + if let Ok(imb) = + T::Currency::deposit_into_existing(&bond_config.account, parachain_bond_reserve) + { + // update round issuance iff transfer succeeds + left_issuance = left_issuance.saturating_sub(imb.peek()); + Self::deposit_event(Event::ReservedForParachainBond { + account: bond_config.account, + value: imb.peek(), + }); + } + + let payout = DelayedPayout { + round_issuance: total_issuance, + total_staking_reward: left_issuance, + collator_commission: >::get(), + }; + + >::insert(round_to_payout, payout); + T::WeightInfo::prepare_staking_payouts() + } + + /// Wrapper around pay_one_collator_reward which handles the following logic: + /// * whether or not a payout needs to be made + /// * cleaning up when payouts are done + /// * returns the weight consumed by pay_one_collator_reward if applicable + fn handle_delayed_payouts(now: RoundIndex) -> Weight { + let delay = T::RewardPaymentDelay::get(); + + // don't underflow uint + if now < delay { + return Weight::from_parts(0u64, 0) + } + + let paid_for_round = now.saturating_sub(delay); + + if let Some(payout_info) = >::get(paid_for_round) { + let result = Self::pay_one_collator_reward(paid_for_round, payout_info); + + // clean up storage items that we no longer need + if matches!(result.0, RewardPayment::Finished) { + >::remove(paid_for_round); + >::remove(paid_for_round); + } + result.1 // weight consumed by pay_one_collator_reward + } else { + Weight::from_parts(0u64, 0) + } + } + + /// Payout a single collator from the given round. + /// + /// Returns an optional tuple of (Collator's AccountId, total paid) + /// or None if there were no more payouts to be made for the round. + pub(crate) fn pay_one_collator_reward( + paid_for_round: RoundIndex, + payout_info: DelayedPayout>, + ) -> (RewardPayment, Weight) { + // 'early_weight' tracks weight used for reads/writes done early in this fn before its + // early-exit codepaths. + let mut early_weight = Weight::zero(); + + // TODO: it would probably be optimal to roll Points into the DelayedPayouts storage + // item so that we do fewer reads each block + let total_points = >::get(paid_for_round); + early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 0)); + + if total_points.is_zero() { + // TODO: this case is obnoxious... it's a value query, so it could mean one of two + // different logic errors: + // 1. we removed it before we should have + // 2. we called pay_one_collator_reward when we were actually done with deferred + // payouts + log::warn!("pay_one_collator_reward called with no > for the round!"); + return (RewardPayment::Finished, early_weight) + } + + let collator_fee = payout_info.collator_commission; + let collator_issuance = collator_fee * payout_info.round_issuance; + + if let Some((collator, state)) = + >::iter_prefix(paid_for_round).drain().next() + { + // read and kill AtStake + early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); + + // Take the awarded points for the collator + let pts = >::take(paid_for_round, &collator); + // read and kill AwardedPts + early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); + if pts == 0 { + return (RewardPayment::Skipped, early_weight) + } + + // 'extra_weight' tracks weight returned from fns that we delegate to which can't be + // known ahead of time. + let mut extra_weight = Weight::zero(); + let pct_due = Perbill::from_rational(pts, total_points); + let total_paid = pct_due * payout_info.total_staking_reward; + let mut amt_due = total_paid; + + let num_delegators = state.delegations.len(); + if state.delegations.is_empty() { + // solo collator with no delegators + extra_weight = extra_weight + .saturating_add(T::PayoutCollatorReward::payout_collator_reward( + paid_for_round, + collator.clone(), + amt_due, + )) + .saturating_add(T::OnCollatorPayout::on_collator_payout( + paid_for_round, + collator, + amt_due, + )); + log::warn!("💵 Solo collator reward: {:?}", amt_due); + } else { + // pay collator first; commission + due_portion + let collator_pct = Perbill::from_rational(state.bond, state.total); + let commission = pct_due * collator_issuance; + amt_due = amt_due.saturating_sub(commission); + let collator_reward = (collator_pct * amt_due).saturating_add(commission); + extra_weight = extra_weight + .saturating_add(T::PayoutCollatorReward::payout_collator_reward( + paid_for_round, + collator.clone(), + collator_reward, + )) + .saturating_add(T::OnCollatorPayout::on_collator_payout( + paid_for_round, + collator.clone(), + collator_reward, + )); + + // pay delegators due portion + for BondWithAutoCompound { owner, amount, auto_compound } in state.delegations { + let percent = Perbill::from_rational(amount, state.total); + let due = percent * amt_due; + if !due.is_zero() { + extra_weight = extra_weight.saturating_add(Self::mint_and_compound( + due, + auto_compound, + collator.clone(), + owner.clone(), + )); + } + } + } + + ( + RewardPayment::Paid, + T::WeightInfo::pay_one_collator_reward(num_delegators as u32) + .saturating_add(extra_weight), + ) + } else { + // Note that we don't clean up storage here; it is cleaned up in + // handle_delayed_payouts() + (RewardPayment::Finished, Weight::from_parts(0u64, 0)) + } + } + + /// Compute the top `TotalSelected` candidates in the CandidatePool and return + /// a vec of their AccountIds (sorted by AccountId). + /// + /// If the returned vec is empty, the previous candidates should be used. + pub fn compute_top_candidates() -> Vec { + let top_n = >::get() as usize; + if top_n == 0 { + return vec![] + } + + let mut candidates = >::get().0; + + // If the number of candidates is greater than top_n, select the candidates with higher + // amount. Otherwise, return all the candidates. + if candidates.len() > top_n { + // Partially sort candidates such that element at index `top_n - 1` is sorted, and + // all the elements in the range 0..top_n are the top n elements. + candidates.select_nth_unstable_by(top_n - 1, |a, b| { + // Order by amount, then owner. The owner is needed to ensure a stable order + // when two accounts have the same amount. + a.amount.cmp(&b.amount).then_with(|| a.owner.cmp(&b.owner)).reverse() + }); + + let mut collators = candidates + .into_iter() + .take(top_n) + .map(|x| x.owner) + .collect::>(); + + // Sort collators by AccountId + collators.sort(); + + collators + } else { + // Return all candidates + // The candidates are already sorted by AccountId, so no need to sort again + candidates.into_iter().map(|x| x.owner).collect::>() + } + } + /// Best as in most cumulatively supported in terms of stake + /// Returns [collator_count, delegation_count, total staked] + pub(crate) fn select_top_candidates(now: RoundIndex) -> (Weight, u32, u32, BalanceOf) { + let (mut collator_count, mut delegation_count, mut total) = + (0u32, 0u32, BalanceOf::::zero()); + // choose the top TotalSelected qualified candidates, ordered by stake + let collators = Self::compute_top_candidates(); + if collators.is_empty() { + // SELECTION FAILED TO SELECT >=1 COLLATOR => select collators from previous round + let last_round = now.saturating_sub(1u32); + let mut total_per_candidate: BTreeMap> = BTreeMap::new(); + // set this round AtStake to last round AtStake + for (account, snapshot) in >::iter_prefix(last_round) { + collator_count = collator_count.saturating_add(1u32); + delegation_count = + delegation_count.saturating_add(snapshot.delegations.len() as u32); + total = total.saturating_add(snapshot.total); + total_per_candidate.insert(account.clone(), snapshot.total); + >::insert(now, account, snapshot); + } + // `SelectedCandidates` remains unchanged from last round + // emit CollatorChosen event for tools that use this event + for candidate in >::get() { + let snapshot_total = total_per_candidate + .get(&candidate) + .expect("all selected candidates have snapshots"); + Self::deposit_event(Event::CollatorChosen { + round: now, + collator_account: candidate, + total_exposed_amount: *snapshot_total, + }) + } + let weight = T::WeightInfo::select_top_candidates(0, 0); + return (weight, collator_count, delegation_count, total) + } + + // snapshot exposure for round for weighting reward distribution + for account in collators.iter() { + let state = >::get(account) + .expect("all members of CandidateQ must be candidates"); + + collator_count = collator_count.saturating_add(1u32); + delegation_count = delegation_count.saturating_add(state.delegation_count); + total = total.saturating_add(state.total_counted); + let CountedDelegations { uncounted_stake, rewardable_delegations } = + Self::get_rewardable_delegators(account); + let total_counted = state.total_counted.saturating_sub(uncounted_stake); + + let auto_compounding_delegations = >::get(account) + .into_iter() + .map(|x| (x.delegator, x.value)) + .collect::>(); + let rewardable_delegations = rewardable_delegations + .into_iter() + .map(|d| BondWithAutoCompound { + owner: d.owner.clone(), + amount: d.amount, + auto_compound: auto_compounding_delegations + .get(&d.owner) + .cloned() + .unwrap_or_else(Percent::zero), + }) + .collect(); + + let snapshot = CollatorSnapshot { + bond: state.bond, + delegations: rewardable_delegations, + total: total_counted, + }; + >::insert(now, account, snapshot); + Self::deposit_event(Event::CollatorChosen { + round: now, + collator_account: account.clone(), + total_exposed_amount: state.total_counted, + }); + } + // insert canonical collator set + >::put(collators); + + let avg_delegator_count = delegation_count.checked_div(collator_count).unwrap_or(0); + let weight = T::WeightInfo::select_top_candidates(collator_count, avg_delegator_count); + (weight, collator_count, delegation_count, total) + } + + /// Apply the delegator intent for revoke and decrease in order to build the + /// effective list of delegators with their intended bond amount. + /// + /// This will: + /// - if [DelegationChange::Revoke] is outstanding, set the bond amount to 0. + /// - if [DelegationChange::Decrease] is outstanding, subtract the bond by specified amount. + /// - else, do nothing + /// + /// The intended bond amounts will be used while calculating rewards. + pub(crate) fn get_rewardable_delegators(collator: &T::AccountId) -> CountedDelegations { + let requests = >::get(collator) + .into_iter() + .map(|x| (x.delegator, x.action)) + .collect::>(); + let mut uncounted_stake = BalanceOf::::zero(); + let rewardable_delegations = >::get(collator) + .expect("all members of CandidateQ must be candidates") + .delegations + .into_iter() + .map(|mut bond| { + bond.amount = match requests.get(&bond.owner) { + None => bond.amount, + Some(DelegationAction::Revoke(_)) => { + uncounted_stake = uncounted_stake.saturating_add(bond.amount); + BalanceOf::::zero() + }, + Some(DelegationAction::Decrease(amount)) => { + uncounted_stake = uncounted_stake.saturating_add(*amount); + bond.amount.saturating_sub(*amount) + }, + }; + + bond + }) + .collect(); + CountedDelegations { uncounted_stake, rewardable_delegations } + } + + /// This function exists as a helper to delegator_bond_more & auto_compound functionality. + /// Any changes to this function must align with both user-initiated bond increases and + /// auto-compounding bond increases. + /// Any feature-specific preconditions should be validated before this function is invoked. + /// Any feature-specific events must be emitted after this function is invoked. + pub fn delegation_bond_more_without_event( + delegator: T::AccountId, + candidate: T::AccountId, + more: BalanceOf, + ) -> Result { + ensure!( + !Self::delegation_request_revoke_exists(&candidate, &delegator), + Error::::PendingDelegationRevoke + ); + let mut state = >::get(&delegator).ok_or(Error::::DelegatorDNE)?; + state.increase_delegation::(candidate, more) + } + + /// Mint a specified reward amount to the beneficiary account. Emits the [Rewarded] event. + pub fn mint(amt: BalanceOf, to: T::AccountId) { + if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&to, amt) { + Self::deposit_event(Event::Rewarded { + account: to.clone(), + rewards: amount_transferred.peek(), + }); + } + } + + /// Mint a specified reward amount to the collator's account. Emits the [Rewarded] event. + pub fn mint_collator_reward( + _paid_for_round: RoundIndex, + collator_id: T::AccountId, + amt: BalanceOf, + ) -> Weight { + if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&collator_id, amt) { + Self::deposit_event(Event::Rewarded { + account: collator_id.clone(), + rewards: amount_transferred.peek(), + }); + } + T::WeightInfo::mint_collator_reward() + } + + /// Mint and compound delegation rewards. The function mints the amount towards the + /// delegator and tries to compound a specified percent of it back towards the delegation. + /// If a scheduled delegation revoke exists, then the amount is only minted, and nothing is + /// compounded. Emits the [Compounded] event. + pub fn mint_and_compound( + amt: BalanceOf, + compound_percent: Percent, + candidate: T::AccountId, + delegator: T::AccountId, + ) -> Weight { + let mut weight = T::WeightInfo::mint_collator_reward(); + if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&delegator, amt) { + Self::deposit_event(Event::Rewarded { + account: delegator.clone(), + rewards: amount_transferred.peek(), + }); + + let compound_amount = compound_percent.mul_ceil(amount_transferred.peek()); + if compound_amount.is_zero() { + return weight + } + + if let Err(err) = Self::delegation_bond_more_without_event( + delegator.clone(), + candidate.clone(), + compound_amount, + ) { + log::warn!( + "skipped compounding staking reward towards candidate '{:?}' for delegator '{:?}': {:?}", + candidate, + delegator, + err + ); + return weight + }; + weight = weight.saturating_add(T::WeightInfo::delegator_bond_more()); + + Pallet::::deposit_event(Event::Compounded { + delegator, + candidate, + amount: compound_amount, + }); + }; + + weight + } + } + + /// Add reward points to block authors: + /// * 20 points to the block producer for producing a block in the chain + impl Pallet { + fn award_points_to_block_author(author: AccountIdOf) { + let now = >::get().current; + let score_plus_20 = >::get(now, &author).saturating_add(20); + >::insert(now, author, score_plus_20); + >::mutate(now, |x| *x = x.saturating_add(20)); + } + } + + impl Get> for Pallet { + fn get() -> Vec { + Self::selected_candidates() + } + } + impl pallet_authorship::EventHandler, T::BlockNumber> for Pallet + where + T: Config + pallet_authorship::Config + pallet_session::Config, + { + /// Add reward points to block authors: + /// * 20 points to the block producer for producing a block in the chain + fn note_author(author: AccountIdOf) { + Pallet::::award_points_to_block_author(author); + } + } + + impl pallet_session::SessionManager> for Pallet { + /// 1. A new session starts. + /// 2. In hook new_session: Read the current top n candidates from the + /// TopCandidates and assign this set to author blocks for the next + /// session. + /// 3. AuRa queries the authorities from the session pallet for + /// this session and picks authors on round-robin-basis from list of + /// authorities. + fn new_session(new_index: SessionIndex) -> Option>> { + log::warn!( + "assembling new collators for new session {} at #{:?}", + new_index, + >::block_number(), + ); + + let collators = Pallet::::selected_candidates().to_vec(); + if collators.is_empty() { + // we never want to pass an empty set of collators. This would brick the chain. + log::error!("💥 keeping old session because of empty collator set!"); + None + } else { + Some(collators) + } + } + + fn end_session(_end_index: SessionIndex) { + // we too are not caring. + } + + fn start_session(_start_index: SessionIndex) { + // we too are not caring. + } + } + + impl pallet_session::ShouldEndSession for Pallet { + fn should_end_session(now: T::BlockNumber) -> bool { + let round = >::get(); + // always update when a new round should start + round.should_update(now) + } + } + + impl EstimateNextSessionRotation for Pallet { + fn average_session_length() -> T::BlockNumber { + T::BlockNumber::from(>::get().length) + } + + fn estimate_current_session_progress(now: T::BlockNumber) -> (Option, Weight) { + let round = >::get(); + let passed_blocks = now.saturating_sub(round.first); + + ( + Some(Permill::from_rational(passed_blocks, T::BlockNumber::from(round.length))), + // One read for the round info, blocknumber is read free + T::DbWeight::get().reads(1), + ) + } + + fn estimate_next_session_rotation( + _now: T::BlockNumber, + ) -> (Option, Weight) { + let round = >::get(); + + ( + Some(round.first + round.length.into()), + // One read for the round info, blocknumber is read free + T::DbWeight::get().reads(1), + ) + } + } +} diff --git a/pallets/parachain-staking/src/migrations.rs b/pallets/parachain-staking/src/migrations.rs new file mode 100644 index 000000000..de1629368 --- /dev/null +++ b/pallets/parachain-staking/src/migrations.rs @@ -0,0 +1,17 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! # Migrations diff --git a/pallets/parachain-staking/src/mock.rs b/pallets/parachain-staking/src/mock.rs new file mode 100644 index 000000000..09f6906fc --- /dev/null +++ b/pallets/parachain-staking/src/mock.rs @@ -0,0 +1,1008 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Test utilities +use crate as pallet_parachain_staking; +use crate::{ + pallet, AwardedPts, Config, Event as ParachainStakingEvent, InflationInfo, Points, Range, + COLLATOR_LOCK_ID, DELEGATOR_LOCK_ID, +}; +use frame_support::{ + construct_runtime, parameter_types, + traits::{Everything, GenesisBuild, LockIdentifier, OnFinalize, OnInitialize}, + weights::{constants::RocksDbWeight, Weight}, +}; +use sp_core::H256; +use sp_io; +use sp_runtime::{ + traits::{BlakeTwo256, IdentityLookup}, + Perbill, Percent, +}; + +pub type AccountId = u64; +pub type Balance = u128; +pub type BlockNumber = u32; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +// Configure a mock runtime to test the pallet. +construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + Aura: pallet_aura::{Pallet, Storage}, + Session: pallet_session::{Pallet, Call, Storage, Event, Config}, + ParachainStaking: pallet_parachain_staking::{Pallet, Call, Storage, Config, Event}, + Authorship: pallet_authorship::{Pallet, Storage}, + } +); + +parameter_types! { + pub const BlockHashCount: u32 = 250; + pub const MaximumBlockWeight: Weight = Weight::from_parts(1024, 1); + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + pub const SS58Prefix: u8 = 42; +} +impl frame_system::Config for Test { + type BaseCallFilter = Everything; + type DbWeight = RocksDbWeight; + type RuntimeOrigin = RuntimeOrigin; + type Index = u64; + type BlockNumber = BlockNumber; + type RuntimeCall = RuntimeCall; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = sp_runtime::generic::Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type BlockWeights = (); + type BlockLength = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} +parameter_types! { + pub const ExistentialDeposit: u128 = 1; +} +impl pallet_balances::Config for Test { + type MaxReserves = (); + type ReserveIdentifier = [u8; 4]; + type MaxLocks = (); + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); + type HoldIdentifier = (); + type FreezeIdentifier = (); + type MaxHolds = (); + type MaxFreezes = (); +} +parameter_types! { + #[derive(Debug, Eq, PartialEq)] + pub const MaxCollatorCandidates: u32 = 10; +} +use sp_consensus_aura::sr25519::AuthorityId; +impl pallet_aura::Config for Test { + type AuthorityId = AuthorityId; + type DisabledValidators = (); + type MaxAuthorities = MaxCollatorCandidates; +} + +impl pallet_authorship::Config for Test { + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; + type EventHandler = ParachainStaking; +} +parameter_types! { + pub const MinimumPeriod: u64 = 1; +} + +impl pallet_timestamp::Config for Test { + type Moment = u64; + type OnTimestampSet = Aura; + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +const GENESIS_BLOCKS_PER_ROUND: u32 = 5; +const GENESIS_COLLATOR_COMMISSION: Perbill = Perbill::from_percent(20); +const GENESIS_PARACHAIN_BOND_RESERVE_PERCENT: Percent = Percent::from_percent(30); +const GENESIS_NUM_SELECTED_CANDIDATES: u32 = 5; +parameter_types! { + pub const MinBlocksPerRound: u32 = 3; + pub const LeaveCandidatesDelay: u32 = 2; + pub const CandidateBondLessDelay: u32 = 2; + pub const LeaveDelegatorsDelay: u32 = 2; + pub const RevokeDelegationDelay: u32 = 2; + pub const DelegationBondLessDelay: u32 = 2; + pub const RewardPaymentDelay: u32 = 2; + pub const MinSelectedCandidates: u32 = GENESIS_NUM_SELECTED_CANDIDATES; + pub const MaxTopDelegationsPerCandidate: u32 = 4; + pub const MaxBottomDelegationsPerCandidate: u32 = 4; + pub const MaxDelegationsPerDelegator: u32 = 4; + pub const MinCandidateStk: u128 = 10; + pub const MinDelegatorStk: u128 = 5; + pub const MinDelegation: u128 = 3; +} +impl_opaque_keys! { + pub struct MockSessionKeys { + pub aura: Aura, + } +} + +parameter_types! { + pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17); +} +use sp_runtime::{ + impl_opaque_keys, + traits::{ConvertInto, OpaqueKeys}, +}; + +impl pallet_session::Config for Test { + type RuntimeEvent = RuntimeEvent; + type ValidatorId = AccountId; + type ValidatorIdOf = ConvertInto; + type ShouldEndSession = ParachainStaking; + type NextSessionRotation = ParachainStaking; + type SessionManager = ParachainStaking; + type SessionHandler = ::KeyTypeIdProviders; + type Keys = MockSessionKeys; + type WeightInfo = (); +} +impl Config for Test { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type MonetaryGovernanceOrigin = frame_system::EnsureRoot; + type MinBlocksPerRound = MinBlocksPerRound; + type LeaveCandidatesDelay = LeaveCandidatesDelay; + type CandidateBondLessDelay = CandidateBondLessDelay; + type LeaveDelegatorsDelay = LeaveDelegatorsDelay; + type RevokeDelegationDelay = RevokeDelegationDelay; + type DelegationBondLessDelay = DelegationBondLessDelay; + type RewardPaymentDelay = RewardPaymentDelay; + type MinSelectedCandidates = MinSelectedCandidates; + type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; + type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate; + type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator; + type MinCandidateStk = MinCandidateStk; + type MinDelegatorStk = MinDelegatorStk; + type MinDelegation = MinDelegation; + type OnCollatorPayout = (); + type PayoutCollatorReward = (); + type OnNewRound = (); + type WeightInfo = (); +} + +pub(crate) struct ExtBuilder { + // endowed accounts with balances + balances: Vec<(AccountId, Balance)>, + // [collator, amount] + collators: Vec<(AccountId, Balance)>, + // [delegator, collator, delegation_amount, auto_compound_percent] + delegations: Vec<(AccountId, AccountId, Balance, Percent)>, + // inflation config + inflation: InflationInfo, +} + +impl Default for ExtBuilder { + fn default() -> ExtBuilder { + ExtBuilder { + balances: vec![], + delegations: vec![], + collators: vec![], + inflation: InflationInfo { + expect: Range { min: 700, ideal: 700, max: 700 }, + // not used + annual: Range { + min: Perbill::from_percent(50), + ideal: Perbill::from_percent(50), + max: Perbill::from_percent(50), + }, + // unrealistically high parameterization, only for testing + round: Range { + min: Perbill::from_percent(5), + ideal: Perbill::from_percent(5), + max: Perbill::from_percent(5), + }, + }, + } + } +} + +impl ExtBuilder { + pub(crate) fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self { + self.balances = balances; + self + } + + pub(crate) fn with_candidates(mut self, collators: Vec<(AccountId, Balance)>) -> Self { + self.collators = collators; + self + } + + pub(crate) fn with_delegations( + mut self, + delegations: Vec<(AccountId, AccountId, Balance)>, + ) -> Self { + self.delegations = + delegations.into_iter().map(|d| (d.0, d.1, d.2, Percent::zero())).collect(); + self + } + + pub(crate) fn with_auto_compounding_delegations( + mut self, + delegations: Vec<(AccountId, AccountId, Balance, Percent)>, + ) -> Self { + self.delegations = delegations; + self + } + + #[allow(dead_code)] + pub(crate) fn with_inflation(mut self, inflation: InflationInfo) -> Self { + self.inflation = inflation; + self + } + + pub(crate) fn build(self) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default() + .build_storage::() + .expect("Frame system builds valid default genesis config"); + + pallet_balances::GenesisConfig:: { balances: self.balances } + .assimilate_storage(&mut t) + .expect("Pallet balances storage can be assimilated"); + pallet_parachain_staking::GenesisConfig:: { + candidates: self.collators, + delegations: self.delegations, + inflation_config: self.inflation, + collator_commission: GENESIS_COLLATOR_COMMISSION, + parachain_bond_reserve_percent: GENESIS_PARACHAIN_BOND_RESERVE_PERCENT, + blocks_per_round: GENESIS_BLOCKS_PER_ROUND, + num_selected_candidates: GENESIS_NUM_SELECTED_CANDIDATES, + } + .assimilate_storage(&mut t) + .expect("Parachain Staking's storage can be assimilated"); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext + } +} + +/// Rolls forward one block. Returns the new block number. +fn roll_one_block() -> BlockNumber { + Balances::on_finalize(System::block_number()); + System::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + System::reset_events(); + System::on_initialize(System::block_number()); + Balances::on_initialize(System::block_number()); + ParachainStaking::on_initialize(System::block_number()); + System::block_number() +} + +/// Rolls to the desired block. Returns the number of blocks played. +pub(crate) fn roll_to(n: BlockNumber) -> u32 { + let mut num_blocks = 0; + let mut block = System::block_number(); + while block < n { + block = roll_one_block(); + num_blocks += 1; + } + num_blocks +} + +/// Rolls desired number of blocks. Returns the final block. +pub(crate) fn roll_blocks(num_blocks: u32) -> BlockNumber { + let mut block = System::block_number(); + for _ in 0..num_blocks { + block = roll_one_block(); + } + block +} + +/// Rolls block-by-block to the beginning of the specified round. +/// This will complete the block in which the round change occurs. +/// Returns the number of blocks played. +pub(crate) fn roll_to_round_begin(round: BlockNumber) -> BlockNumber { + let block = (round - 1) * GENESIS_BLOCKS_PER_ROUND; + roll_to(block) +} + +/// Rolls block-by-block to the end of the specified round. +/// The block following will be the one in which the specified round change occurs. +pub(crate) fn roll_to_round_end(round: BlockNumber) -> BlockNumber { + let block = round * GENESIS_BLOCKS_PER_ROUND - 1; + roll_to(block) +} + +pub(crate) fn events() -> Vec> { + System::events() + .into_iter() + .map(|r| r.event) + .filter_map( + |e| { + if let RuntimeEvent::ParachainStaking(inner) = e { + Some(inner) + } else { + None + } + }, + ) + .collect::>() +} + +/// Asserts that some events were never emitted. +/// +/// # Example +/// +/// ``` +/// assert_no_events!(); +/// ``` +#[macro_export] +macro_rules! assert_no_events { + () => { + similar_asserts::assert_eq!(Vec::>::new(), crate::mock::events()) + }; +} + +/// Asserts that emitted events match exactly the given input. +/// +/// # Example +/// +/// ``` +/// assert_events_eq!( +/// Foo { x: 1, y: 2 }, +/// Bar { value: "test" }, +/// Baz { a: 10, b: 20 }, +/// ); +/// ``` +#[macro_export] +macro_rules! assert_events_eq { + ($event:expr) => { + similar_asserts::assert_eq!(vec![$event], crate::mock::events()); + }; + ($($events:expr,)+) => { + similar_asserts::assert_eq!(vec![$($events,)+], crate::mock::events()); + }; +} + +/// Asserts that some emitted events match the given input. +/// +/// # Example +/// +/// ``` +/// assert_events_emitted!( +/// Foo { x: 1, y: 2 }, +/// Baz { a: 10, b: 20 }, +/// ); +/// ``` +#[macro_export] +macro_rules! assert_events_emitted { + ($event:expr) => { + [$event].into_iter().for_each(|e| assert!( + crate::mock::events().into_iter().find(|x| x == &e).is_some(), + "Event {:?} was not found in events: \n{:#?}", + e, + crate::mock::events() + )); + }; + ($($events:expr,)+) => { + [$($events,)+].into_iter().for_each(|e| assert!( + crate::mock::events().into_iter().find(|x| x == &e).is_some(), + "Event {:?} was not found in events: \n{:#?}", + e, + crate::mock::events() + )); + }; +} + +/// Asserts that some events were never emitted. +/// +/// # Example +/// +/// ``` +/// assert_events_not_emitted!( +/// Foo { x: 1, y: 2 }, +/// Bar { value: "test" }, +/// ); +/// ``` +#[macro_export] +macro_rules! assert_events_not_emitted { + ($event:expr) => { + [$event].into_iter().for_each(|e| assert!( + crate::mock::events().into_iter().find(|x| x != &e).is_some(), + "Event {:?} was unexpectedly found in events: \n{:#?}", + e, + crate::mock::events() + )); + }; + ($($events:expr,)+) => { + [$($events,)+].into_iter().for_each(|e| assert!( + crate::mock::events().into_iter().find(|x| x != &e).is_some(), + "Event {:?} was unexpectedly found in events: \n{:#?}", + e, + crate::mock::events() + )); + }; +} + +/// Asserts that the emitted events are exactly equal to the input patterns. +/// +/// # Example +/// +/// ``` +/// assert_events_eq_match!( +/// Foo { x: 1, .. }, +/// Bar { .. }, +/// Baz { a: 10, b: 20 }, +/// ); +/// ``` +#[macro_export] +macro_rules! assert_events_eq_match { + ($index:expr;) => { + assert_eq!( + $index, + crate::mock::events().len(), + "Found {} extra event(s): \n{:#?}", + crate::mock::events().len()-$index, + crate::mock::events() + ); + }; + ($index:expr; $event:pat_param, $($events:pat_param,)*) => { + assert!( + matches!( + crate::mock::events().get($index), + Some($event), + ), + "Event {:#?} was not found at index {}: \n{:#?}", + stringify!($event), + $index, + crate::mock::events() + ); + assert_events_eq_match!($index+1; $($events,)*); + }; + ($event:pat_param) => { + assert_events_eq_match!(0; $event,); + }; + ($($events:pat_param,)+) => { + assert_events_eq_match!(0; $($events,)+); + }; +} + +/// Asserts that some emitted events match the input patterns. +/// +/// # Example +/// +/// ``` +/// assert_events_emitted_match!( +/// Foo { x: 1, .. }, +/// Baz { a: 10, b: 20 }, +/// ); +/// ``` +#[macro_export] +macro_rules! assert_events_emitted_match { + ($event:pat_param) => { + assert!( + crate::mock::events().into_iter().any(|x| matches!(x, $event)), + "Event {:?} was not found in events: \n{:#?}", + stringify!($event), + crate::mock::events() + ); + }; + ($event:pat_param, $($events:pat_param,)+) => { + assert_events_emitted_match!($event); + $( + assert_events_emitted_match!($events); + )+ + }; +} + +/// Asserts that the input patterns match none of the emitted events. +/// +/// # Example +/// +/// ``` +/// assert_events_not_emitted_match!( +/// Foo { x: 1, .. }, +/// Baz { a: 10, b: 20 }, +/// ); +/// ``` +#[macro_export] +macro_rules! assert_events_not_emitted_match { + ($event:pat_param) => { + assert!( + crate::mock::events().into_iter().any(|x| !matches!(x, $event)), + "Event {:?} was unexpectedly found in events: \n{:#?}", + stringify!($event), + crate::mock::events() + ); + }; + ($event:pat_param, $($events:pat_param,)+) => { + assert_events_not_emitted_match!($event); + $( + assert_events_not_emitted_match!($events); + )+ + }; +} + +// Same storage changes as ParachainStaking::on_finalize +pub(crate) fn set_author(round: BlockNumber, acc: u64, pts: u32) { + >::mutate(round, |p| *p += pts); + >::mutate(round, acc, |p| *p += pts); +} + +/// fn to query the lock amount +pub(crate) fn query_lock_amount(account_id: u64, id: LockIdentifier) -> Option { + for lock in Balances::locks(&account_id) { + if lock.id == id { + return Some(lock.amount) + } + } + None +} + +#[test] +fn geneses() { + ExtBuilder::default() + .with_balances(vec![ + (1, 1000), + (2, 300), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 9), + (9, 4), + ]) + .with_candidates(vec![(1, 500), (2, 200)]) + .with_delegations(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) + .build() + .execute_with(|| { + assert!(System::events().is_empty()); + // collators + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 500); + assert_eq!(query_lock_amount(1, COLLATOR_LOCK_ID), Some(500)); + assert!(ParachainStaking::is_candidate(&1)); + assert_eq!(query_lock_amount(2, COLLATOR_LOCK_ID), Some(200)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&2), 100); + assert!(ParachainStaking::is_candidate(&2)); + // delegators + for x in 3..7 { + assert!(ParachainStaking::is_delegator(&x)); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&x), 0); + assert_eq!(query_lock_amount(x, DELEGATOR_LOCK_ID), Some(100)); + } + // uninvolved + for x in 7..10 { + assert!(!ParachainStaking::is_delegator(&x)); + } + // no delegator staking locks + assert_eq!(query_lock_amount(7, DELEGATOR_LOCK_ID), None); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&7), 100); + assert_eq!(query_lock_amount(8, DELEGATOR_LOCK_ID), None); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&8), 9); + assert_eq!(query_lock_amount(9, DELEGATOR_LOCK_ID), None); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&9), 4); + // no collator staking locks + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&7), 100); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&8), 9); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&9), 4); + }); + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + ]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) + .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) + .build() + .execute_with(|| { + assert!(System::events().is_empty()); + // collators + for x in 1..5 { + assert!(ParachainStaking::is_candidate(&x)); + assert_eq!(query_lock_amount(x, COLLATOR_LOCK_ID), Some(20)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&x), 80); + } + assert!(ParachainStaking::is_candidate(&5)); + assert_eq!(query_lock_amount(5, COLLATOR_LOCK_ID), Some(10)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&5), 90); + // delegators + for x in 6..11 { + assert!(ParachainStaking::is_delegator(&x)); + assert_eq!(query_lock_amount(x, DELEGATOR_LOCK_ID), Some(10)); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&x), 90); + } + }); +} + +#[test] +fn roll_to_round_begin_works() { + ExtBuilder::default().build().execute_with(|| { + // these tests assume blocks-per-round of 5, as established by GENESIS_BLOCKS_PER_ROUND + assert_eq!(System::block_number(), 1); // we start on block 1 + + let num_blocks = roll_to_round_begin(1); + assert_eq!(System::block_number(), 1); // no-op, we're already on this round + assert_eq!(num_blocks, 0); + + let num_blocks = roll_to_round_begin(2); + assert_eq!(System::block_number(), 5); + assert_eq!(num_blocks, 4); + + let num_blocks = roll_to_round_begin(3); + assert_eq!(System::block_number(), 10); + assert_eq!(num_blocks, 5); + }); +} + +#[test] +fn roll_to_round_end_works() { + ExtBuilder::default().build().execute_with(|| { + // these tests assume blocks-per-round of 5, as established by GENESIS_BLOCKS_PER_ROUND + assert_eq!(System::block_number(), 1); // we start on block 1 + + let num_blocks = roll_to_round_end(1); + assert_eq!(System::block_number(), 4); + assert_eq!(num_blocks, 3); + + let num_blocks = roll_to_round_end(2); + assert_eq!(System::block_number(), 9); + assert_eq!(num_blocks, 5); + + let num_blocks = roll_to_round_end(3); + assert_eq!(System::block_number(), 14); + assert_eq!(num_blocks, 5); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_eq_fails_if_event_missing() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq!( + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 10, + }, + ); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_eq_fails_if_event_extra() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq!( + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 10, + }, + ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, + ParachainStakingEvent::Rewarded { account: 1, rewards: 200 }, + ); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_eq_fails_if_event_wrong_order() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq!( + ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 10, + }, + ); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_eq_fails_if_event_wrong_value() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq!( + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 10, + }, + ParachainStakingEvent::Rewarded { account: 1, rewards: 50 }, + ); + }); +} + +#[test] +fn test_assert_events_eq_passes_if_all_events_present_single() { + ExtBuilder::default().build().execute_with(|| { + System::deposit_event(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); + + assert_events_eq!(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); + }); +} + +#[test] +fn test_assert_events_eq_passes_if_all_events_present_multiple() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq!( + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 10, + }, + ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, + ); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_emitted_fails_if_event_missing() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_emitted!(ParachainStakingEvent::DelegatorExitScheduled { + round: 2, + delegator: 3, + scheduled_exit: 4, + }); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_emitted_fails_if_event_wrong_value() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_emitted!(ParachainStakingEvent::Rewarded { account: 1, rewards: 50 }); + }); +} + +#[test] +fn test_assert_events_emitted_passes_if_all_events_present_single() { + ExtBuilder::default().build().execute_with(|| { + System::deposit_event(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); + + assert_events_emitted!(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); + }); +} + +#[test] +fn test_assert_events_emitted_passes_if_all_events_present_multiple() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_emitted!( + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, + ); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_eq_match_fails_if_event_missing() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq_match!( + ParachainStakingEvent::CollatorChosen { .. }, + ParachainStakingEvent::NewRound { .. }, + ); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_eq_match_fails_if_event_extra() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq_match!( + ParachainStakingEvent::CollatorChosen { .. }, + ParachainStakingEvent::NewRound { .. }, + ParachainStakingEvent::Rewarded { .. }, + ParachainStakingEvent::Rewarded { .. }, + ); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_eq_match_fails_if_event_wrong_order() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq_match!( + ParachainStakingEvent::Rewarded { .. }, + ParachainStakingEvent::CollatorChosen { .. }, + ParachainStakingEvent::NewRound { .. }, + ); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_eq_match_fails_if_event_wrong_value() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq_match!( + ParachainStakingEvent::CollatorChosen { .. }, + ParachainStakingEvent::NewRound { .. }, + ParachainStakingEvent::Rewarded { rewards: 50, .. }, + ); + }); +} + +#[test] +fn test_assert_events_eq_match_passes_if_all_events_present_single() { + ExtBuilder::default().build().execute_with(|| { + System::deposit_event(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); + + assert_events_eq_match!(ParachainStakingEvent::Rewarded { account: 1, .. }); + }); +} + +#[test] +fn test_assert_events_eq_match_passes_if_all_events_present_multiple() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_eq_match!( + ParachainStakingEvent::CollatorChosen { round: 2, collator_account: 1, .. }, + ParachainStakingEvent::NewRound { starting_block: 10, .. }, + ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, + ); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_emitted_match_fails_if_event_missing() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_emitted_match!(ParachainStakingEvent::DelegatorExitScheduled { + round: 2, + .. + }); + }); +} + +#[test] +#[should_panic] +fn test_assert_events_emitted_match_fails_if_event_wrong_value() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_emitted_match!(ParachainStakingEvent::Rewarded { rewards: 50, .. }); + }); +} + +#[test] +fn test_assert_events_emitted_match_passes_if_all_events_present_single() { + ExtBuilder::default().build().execute_with(|| { + System::deposit_event(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); + + assert_events_emitted_match!(ParachainStakingEvent::Rewarded { rewards: 100, .. }); + }); +} + +#[test] +fn test_assert_events_emitted_match_passes_if_all_events_present_multiple() { + ExtBuilder::default().build().execute_with(|| { + inject_test_events(); + + assert_events_emitted_match!( + ParachainStakingEvent::CollatorChosen { total_exposed_amount: 10, .. }, + ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, + ); + }); +} + +fn inject_test_events() { + [ + ParachainStakingEvent::CollatorChosen { + round: 2, + collator_account: 1, + total_exposed_amount: 10, + }, + ParachainStakingEvent::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 10, + }, + ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, + ] + .into_iter() + .for_each(System::deposit_event); +} diff --git a/pallets/parachain-staking/src/set.rs b/pallets/parachain-staking/src/set.rs new file mode 100644 index 000000000..1f15d68ae --- /dev/null +++ b/pallets/parachain-staking/src/set.rs @@ -0,0 +1,89 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +/* TODO: use orml_utilities::OrderedSet without leaking substrate v2.0 dependencies*/ +use parity_scale_codec::{Decode, Encode}; +use scale_info::TypeInfo; +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; +use sp_runtime::RuntimeDebug; +use sp_std::prelude::*; + +/// An ordered set backed by `Vec` +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(RuntimeDebug, PartialEq, Eq, Encode, Decode, Default, Clone, TypeInfo)] +pub struct OrderedSet(pub Vec); + +impl OrderedSet { + /// Create a new empty set + pub fn new() -> Self { + Self(Vec::new()) + } + + /// Create a set from a `Vec`. + /// `v` will be sorted and dedup first. + pub fn from(mut v: Vec) -> Self { + v.sort(); + v.dedup(); + Self::from_sorted_set(v) + } + + /// Create a set from a `Vec`. + /// Assume `v` is sorted and contain unique elements. + pub fn from_sorted_set(v: Vec) -> Self { + Self(v) + } + + /// Insert an element. + /// Return true if insertion happened. + pub fn insert(&mut self, value: T) -> bool { + match self.0.binary_search(&value) { + Ok(_) => false, + Err(loc) => { + self.0.insert(loc, value); + true + }, + } + } + + /// Remove an element. + /// Return true if removal happened. + pub fn remove(&mut self, value: &T) -> bool { + match self.0.binary_search(value) { + Ok(loc) => { + self.0.remove(loc); + true + }, + Err(_) => false, + } + } + + /// Return if the set contains `value` + pub fn contains(&self, value: &T) -> bool { + self.0.binary_search(value).is_ok() + } + + /// Clear the set + pub fn clear(&mut self) { + self.0.clear(); + } +} + +impl From> for OrderedSet { + fn from(v: Vec) -> Self { + Self::from(v) + } +} diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs new file mode 100644 index 000000000..f35fd0b91 --- /dev/null +++ b/pallets/parachain-staking/src/tests.rs @@ -0,0 +1,6934 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! # Staking Pallet Unit Tests +//! The unit tests are organized by the call they test. The order matches the order +//! of the calls in the `lib.rs`. +//! 1. Root +//! 2. Monetary Governance +//! 3. Public (Collator, Nominator) +//! 4. Miscellaneous Property-Based Tests + +use crate::{ + assert_events_emitted, assert_events_emitted_match, assert_events_eq, assert_no_events, + auto_compound::{AutoCompoundConfig, AutoCompoundDelegations}, + delegation_requests::{CancelledScheduledRequest, DelegationAction, ScheduledRequest}, + mock::{ + roll_blocks, roll_to, roll_to_round_begin, roll_to_round_end, set_author, Balances, + BlockNumber, ExtBuilder, ParachainStaking, RuntimeOrigin, Test, + }, + AtStake, Bond, CollatorStatus, DelegationScheduledRequests, DelegatorAdded, DelegatorState, + DelegatorStatus, Error, Event, Range, DELEGATOR_LOCK_ID, +}; +use frame_support::{assert_noop, assert_ok}; +use sp_runtime::{traits::Zero, Perbill, Percent}; + +// ~~ ROOT ~~ + +#[test] +fn invalid_root_origin_fails() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_total_selected(RuntimeOrigin::signed(45), 6u32), + sp_runtime::DispatchError::BadOrigin + ); + assert_noop!( + ParachainStaking::set_collator_commission( + RuntimeOrigin::signed(45), + Perbill::from_percent(5) + ), + sp_runtime::DispatchError::BadOrigin + ); + assert_noop!( + ParachainStaking::set_blocks_per_round(RuntimeOrigin::signed(45), 3u32), + sp_runtime::DispatchError::BadOrigin + ); + }); +} + +// SET TOTAL SELECTED + +#[test] +fn set_total_selected_event_emits_correctly() { + ExtBuilder::default().build().execute_with(|| { + // before we can bump total_selected we must bump the blocks per round + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 7u32)); + roll_blocks(1); + assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 6u32)); + assert_events_eq!(Event::TotalSelectedSet { old: 5u32, new: 6u32 }); + }); +} + +#[test] +fn set_total_selected_fails_if_above_blocks_per_round() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(ParachainStaking::round().length, 5); // test relies on this + assert_noop!( + ParachainStaking::set_total_selected(RuntimeOrigin::root(), 6u32), + Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, + ); + }); +} + +#[test] +fn set_total_selected_fails_if_equal_to_blocks_per_round() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); + assert_noop!( + ParachainStaking::set_total_selected(RuntimeOrigin::root(), 10u32), + Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, + ); + }); +} + +#[test] +fn set_total_selected_passes_if_below_blocks_per_round() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); + assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 9u32)); + }); +} + +#[test] +fn set_blocks_per_round_fails_if_below_total_selected() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 20u32)); + assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 15u32)); + assert_noop!( + ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 14u32), + Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, + ); + }); +} + +#[test] +fn set_blocks_per_round_fails_if_equal_to_total_selected() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); + assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 9u32)); + assert_noop!( + ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 9u32), + Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, + ); + }); +} + +#[test] +fn set_blocks_per_round_passes_if_above_total_selected() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(ParachainStaking::round().length, 5); // test relies on this + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); + }); +} + +#[test] +fn set_total_selected_storage_updates_correctly() { + ExtBuilder::default().build().execute_with(|| { + // round length must be >= total_selected, so update that first + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); + + assert_eq!(ParachainStaking::total_selected(), 5u32); + assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 6u32)); + assert_eq!(ParachainStaking::total_selected(), 6u32); + }); +} + +#[test] +fn cannot_set_total_selected_to_current_total_selected() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_total_selected(RuntimeOrigin::root(), 5u32), + Error::::NoWritingSameValue + ); + }); +} + +#[test] +fn cannot_set_total_selected_below_module_min() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_total_selected(RuntimeOrigin::root(), 4u32), + Error::::CannotSetBelowMin + ); + }); +} + +// SET COLLATOR COMMISSION + +#[test] +fn set_collator_commission_event_emits_correctly() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_collator_commission( + RuntimeOrigin::root(), + Perbill::from_percent(5) + )); + assert_events_eq!(Event::CollatorCommissionSet { + old: Perbill::from_percent(20), + new: Perbill::from_percent(5), + }); + }); +} + +#[test] +fn set_collator_commission_storage_updates_correctly() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(ParachainStaking::collator_commission(), Perbill::from_percent(20)); + assert_ok!(ParachainStaking::set_collator_commission( + RuntimeOrigin::root(), + Perbill::from_percent(5) + )); + assert_eq!(ParachainStaking::collator_commission(), Perbill::from_percent(5)); + }); +} + +#[test] +fn cannot_set_collator_commission_to_current_collator_commission() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_collator_commission( + RuntimeOrigin::root(), + Perbill::from_percent(20) + ), + Error::::NoWritingSameValue + ); + }); +} + +// SET BLOCKS PER ROUND + +#[test] +fn set_blocks_per_round_event_emits_correctly() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); + assert_events_eq!(Event::BlocksPerRoundSet { + current_round: 1, + first_block: 0, + old: 5, + new: 6, + new_per_round_inflation_min: Perbill::from_parts(926), + new_per_round_inflation_ideal: Perbill::from_parts(926), + new_per_round_inflation_max: Perbill::from_parts(926), + }); + }); +} + +#[test] +fn set_blocks_per_round_storage_updates_correctly() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(ParachainStaking::round().length, 5); + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); + assert_eq!(ParachainStaking::round().length, 6); + }); +} + +#[test] +fn cannot_set_blocks_per_round_below_module_min() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 2u32), + Error::::CannotSetBelowMin + ); + }); +} + +#[test] +fn cannot_set_blocks_per_round_to_current_blocks_per_round() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 5u32), + Error::::NoWritingSameValue + ); + }); +} + +#[test] +fn round_immediately_jumps_if_current_duration_exceeds_new_blocks_per_round() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // we can't lower the blocks per round because it must be above the number of collators, + // and we can't lower the number of collators because it must be above + // MinSelectedCandidates. so we first raise blocks per round, then lower it. + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); + + roll_to(10); + assert_events_emitted!(Event::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 20 + },); + roll_to(17); + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); + roll_to(18); + assert_events_emitted!(Event::NewRound { + starting_block: 18, + round: 3, + selected_collators_number: 1, + total_balance: 20 + }); + }); +} + +// ~~ MONETARY GOVERNANCE ~~ + +#[test] +fn invalid_monetary_origin_fails() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_staking_expectations( + RuntimeOrigin::signed(45), + Range { min: 3u32.into(), ideal: 4u32.into(), max: 5u32.into() } + ), + sp_runtime::DispatchError::BadOrigin + ); + assert_noop!( + ParachainStaking::set_inflation( + RuntimeOrigin::signed(45), + Range { + min: Perbill::from_percent(3), + ideal: Perbill::from_percent(4), + max: Perbill::from_percent(5) + } + ), + sp_runtime::DispatchError::BadOrigin + ); + assert_noop!( + ParachainStaking::set_inflation( + RuntimeOrigin::signed(45), + Range { + min: Perbill::from_percent(3), + ideal: Perbill::from_percent(4), + max: Perbill::from_percent(5) + } + ), + sp_runtime::DispatchError::BadOrigin + ); + assert_noop!( + ParachainStaking::set_parachain_bond_account(RuntimeOrigin::signed(45), 11), + sp_runtime::DispatchError::BadOrigin + ); + assert_noop!( + ParachainStaking::set_parachain_bond_reserve_percent( + RuntimeOrigin::signed(45), + Percent::from_percent(2) + ), + sp_runtime::DispatchError::BadOrigin + ); + }); +} + +// SET STAKING EXPECTATIONS + +#[test] +fn set_staking_event_emits_event_correctly() { + ExtBuilder::default().build().execute_with(|| { + // valid call succeeds + assert_ok!(ParachainStaking::set_staking_expectations( + RuntimeOrigin::root(), + Range { min: 3u128, ideal: 4u128, max: 5u128 } + )); + assert_events_eq!(Event::StakeExpectationsSet { + expect_min: 3u128, + expect_ideal: 4u128, + expect_max: 5u128, + }); + }); +} + +#[test] +fn set_staking_updates_storage_correctly() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!( + ParachainStaking::inflation_config().expect, + Range { min: 700, ideal: 700, max: 700 } + ); + assert_ok!(ParachainStaking::set_staking_expectations( + RuntimeOrigin::root(), + Range { min: 3u128, ideal: 4u128, max: 5u128 } + )); + assert_eq!( + ParachainStaking::inflation_config().expect, + Range { min: 3u128, ideal: 4u128, max: 5u128 } + ); + }); +} + +#[test] +fn cannot_set_invalid_staking_expectations() { + ExtBuilder::default().build().execute_with(|| { + // invalid call fails + assert_noop!( + ParachainStaking::set_staking_expectations( + RuntimeOrigin::root(), + Range { min: 5u128, ideal: 4u128, max: 3u128 } + ), + Error::::InvalidSchedule + ); + }); +} + +#[test] +fn cannot_set_same_staking_expectations() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_staking_expectations( + RuntimeOrigin::root(), + Range { min: 3u128, ideal: 4u128, max: 5u128 } + )); + assert_noop!( + ParachainStaking::set_staking_expectations( + RuntimeOrigin::root(), + Range { min: 3u128, ideal: 4u128, max: 5u128 } + ), + Error::::NoWritingSameValue + ); + }); +} + +// SET INFLATION + +#[test] +fn set_inflation_event_emits_correctly() { + ExtBuilder::default().build().execute_with(|| { + let (min, ideal, max): (Perbill, Perbill, Perbill) = + (Perbill::from_percent(3), Perbill::from_percent(4), Perbill::from_percent(5)); + assert_ok!(ParachainStaking::set_inflation( + RuntimeOrigin::root(), + Range { min, ideal, max } + )); + assert_events_eq!(Event::InflationSet { + annual_min: min, + annual_ideal: ideal, + annual_max: max, + round_min: Perbill::from_parts(57), + round_ideal: Perbill::from_parts(75), + round_max: Perbill::from_parts(93), + }); + }); +} + +#[test] +fn set_inflation_storage_updates_correctly() { + ExtBuilder::default().build().execute_with(|| { + let (min, ideal, max): (Perbill, Perbill, Perbill) = + (Perbill::from_percent(3), Perbill::from_percent(4), Perbill::from_percent(5)); + assert_eq!( + ParachainStaking::inflation_config().annual, + Range { + min: Perbill::from_percent(50), + ideal: Perbill::from_percent(50), + max: Perbill::from_percent(50) + } + ); + assert_eq!( + ParachainStaking::inflation_config().round, + Range { + min: Perbill::from_percent(5), + ideal: Perbill::from_percent(5), + max: Perbill::from_percent(5) + } + ); + assert_ok!(ParachainStaking::set_inflation( + RuntimeOrigin::root(), + Range { min, ideal, max } + ),); + assert_eq!(ParachainStaking::inflation_config().annual, Range { min, ideal, max }); + assert_eq!( + ParachainStaking::inflation_config().round, + Range { + min: Perbill::from_parts(57), + ideal: Perbill::from_parts(75), + max: Perbill::from_parts(93) + } + ); + }); +} + +#[test] +fn cannot_set_invalid_inflation() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_inflation( + RuntimeOrigin::root(), + Range { + min: Perbill::from_percent(5), + ideal: Perbill::from_percent(4), + max: Perbill::from_percent(3) + } + ), + Error::::InvalidSchedule + ); + }); +} + +#[test] +fn cannot_set_same_inflation() { + ExtBuilder::default().build().execute_with(|| { + let (min, ideal, max): (Perbill, Perbill, Perbill) = + (Perbill::from_percent(3), Perbill::from_percent(4), Perbill::from_percent(5)); + assert_ok!(ParachainStaking::set_inflation( + RuntimeOrigin::root(), + Range { min, ideal, max } + ),); + assert_noop!( + ParachainStaking::set_inflation(RuntimeOrigin::root(), Range { min, ideal, max }), + Error::::NoWritingSameValue + ); + }); +} + +// SET PARACHAIN BOND ACCOUNT + +#[test] +fn set_parachain_bond_account_event_emits_correctly() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_parachain_bond_account(RuntimeOrigin::root(), 11)); + assert_events_eq!(Event::ParachainBondAccountSet { old: 0, new: 11 }); + }); +} + +#[test] +fn set_parachain_bond_account_storage_updates_correctly() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(ParachainStaking::parachain_bond_info().account, 0); + assert_ok!(ParachainStaking::set_parachain_bond_account(RuntimeOrigin::root(), 11)); + assert_eq!(ParachainStaking::parachain_bond_info().account, 11); + }); +} + +// SET PARACHAIN BOND RESERVE PERCENT + +#[test] +fn set_parachain_bond_reserve_percent_event_emits_correctly() { + ExtBuilder::default().build().execute_with(|| { + assert_ok!(ParachainStaking::set_parachain_bond_reserve_percent( + RuntimeOrigin::root(), + Percent::from_percent(50) + )); + assert_events_eq!(Event::ParachainBondReservePercentSet { + old: Percent::from_percent(30), + new: Percent::from_percent(50), + }); + }); +} + +#[test] +fn set_parachain_bond_reserve_percent_storage_updates_correctly() { + ExtBuilder::default().build().execute_with(|| { + assert_eq!(ParachainStaking::parachain_bond_info().percent, Percent::from_percent(30)); + assert_ok!(ParachainStaking::set_parachain_bond_reserve_percent( + RuntimeOrigin::root(), + Percent::from_percent(50) + )); + assert_eq!(ParachainStaking::parachain_bond_info().percent, Percent::from_percent(50)); + }); +} + +#[test] +fn cannot_set_same_parachain_bond_reserve_percent() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::set_parachain_bond_reserve_percent( + RuntimeOrigin::root(), + Percent::from_percent(30) + ), + Error::::NoWritingSameValue + ); + }); +} + +// ~~ PUBLIC ~~ + +// JOIN CANDIDATES + +#[test] +fn join_candidates_event_emits_correctly() { + ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); + assert_events_eq!(Event::JoinedCollatorCandidates { + account: 1, + amount_locked: 10u128, + new_total_amt_locked: 10u128, + }); + }); +} + +#[test] +fn join_candidates_reserves_balance() { + ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); + }); +} + +#[test] +fn join_candidates_increases_total_staked() { + ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { + assert_eq!(ParachainStaking::total(), 0); + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); + assert_eq!(ParachainStaking::total(), 10); + }); +} + +#[test] +fn join_candidates_creates_candidate_state() { + ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { + assert!(ParachainStaking::candidate_info(1).is_none()); + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); + let candidate_state = ParachainStaking::candidate_info(1).expect("just joined => exists"); + assert_eq!(candidate_state.bond, 10u128); + }); +} + +#[test] +fn join_candidates_adds_to_candidate_pool() { + ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { + assert!(ParachainStaking::candidate_pool().0.is_empty()); + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); + let candidate_pool = ParachainStaking::candidate_pool(); + assert_eq!(candidate_pool.0[0].owner, 1); + assert_eq!(candidate_pool.0[0].amount, 10); + }); +} + +#[test] +fn cannot_join_candidates_if_candidate() { + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_candidates(vec![(1, 500)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 11u128, 100u32), + Error::::CandidateExists + ); + }); +} + +#[test] +fn cannot_join_candidates_if_delegator() { + ExtBuilder::default() + .with_balances(vec![(1, 50), (2, 20)]) + .with_candidates(vec![(1, 50)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::join_candidates(RuntimeOrigin::signed(2), 10u128, 1u32), + Error::::DelegatorExists + ); + }); +} + +#[test] +fn cannot_join_candidates_without_min_bond() { + ExtBuilder::default().with_balances(vec![(1, 1000)]).build().execute_with(|| { + assert_noop!( + ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 9u128, 100u32), + Error::::CandidateBondBelowMin + ); + }); +} + +#[test] +fn cannot_join_candidates_with_more_than_available_balance() { + ExtBuilder::default().with_balances(vec![(1, 500)]).build().execute_with(|| { + assert_noop!( + ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 501u128, 100u32), + Error::::InsufficientBalance + ); + }); +} + +#[test] +fn insufficient_join_candidates_weight_hint_fails() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) + .build() + .execute_with(|| { + for i in 0..5 { + assert_noop!( + ParachainStaking::join_candidates(RuntimeOrigin::signed(6), 20, i), + Error::::TooLowCandidateCountWeightHintJoinCandidates + ); + } + }); +} + +#[test] +fn sufficient_join_candidates_weight_hint_succeeds() { + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 20), + (3, 20), + (4, 20), + (5, 20), + (6, 20), + (7, 20), + (8, 20), + (9, 20), + ]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) + .build() + .execute_with(|| { + let mut count = 5u32; + for i in 6..10 { + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(i), 20, count)); + count += 1u32; + } + }); +} + +// SCHEDULE LEAVE CANDIDATES + +#[test] +fn leave_candidates_event_emits_correctly() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_events_eq!(Event::CandidateScheduledExit { + exit_allowed_round: 1, + candidate: 1, + scheduled_exit: 3 + }); + }); +} + +#[test] +fn leave_candidates_removes_candidate_from_candidate_pool() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert!(ParachainStaking::candidate_pool().0.is_empty()); + }); +} + +#[test] +fn cannot_leave_candidates_if_not_candidate() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32), + Error::::CandidateDNE + ); + }); +} + +#[test] +fn cannot_leave_candidates_if_already_leaving_candidates() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_noop!( + ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32), + Error::::CandidateAlreadyLeaving + ); + }); +} + +#[test] +fn insufficient_leave_candidates_weight_hint_fails() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) + .build() + .execute_with(|| { + for i in 1..6 { + assert_noop!( + ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(i), 4u32), + Error::::TooLowCandidateCountToLeaveCandidates + ); + } + }); +} + +#[test] +fn sufficient_leave_candidates_weight_hint_succeeds() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) + .build() + .execute_with(|| { + let mut count = 5u32; + for i in 1..6 { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(i), + count + )); + count -= 1u32; + } + }); +} + +// EXECUTE LEAVE CANDIDATES + +#[test] +fn execute_leave_candidates_emits_event() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert_events_emitted!(Event::CandidateLeft { + ex_candidate: 1, + unlocked_amount: 10, + new_total_amt_locked: 0 + }); + }); +} + +#[test] +fn execute_leave_candidates_callable_by_any_signed() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 1, 0)); + }); +} + +#[test] +fn execute_leave_candidates_requires_correct_weight_hint() { + ExtBuilder::default() + .with_balances(vec![(1, 10), (2, 10), (3, 10), (4, 10)]) + .with_candidates(vec![(1, 10)]) + .with_delegations(vec![(2, 1, 10), (3, 1, 10), (4, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + roll_to(10); + for i in 0..3 { + assert_noop!( + ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, i), + Error::::TooLowCandidateDelegationCountToLeaveCandidates + ); + } + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 1, 3)); + }); +} + +#[test] +fn execute_leave_candidates_unreserves_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); + }); +} + +#[test] +fn execute_leave_candidates_decreases_total_staked() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 10); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert_eq!(ParachainStaking::total(), 0); + }); +} + +#[test] +fn execute_leave_candidates_removes_candidate_state() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + // candidate state is not immediately removed + let candidate_state = + ParachainStaking::candidate_info(1).expect("just left => still exists"); + assert_eq!(candidate_state.bond, 10u128); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert!(ParachainStaking::candidate_info(1).is_none()); + }); +} + +#[test] +fn execute_leave_candidates_removes_pending_delegation_requests() { + ExtBuilder::default() + .with_balances(vec![(1, 10), (2, 15)]) + .with_candidates(vec![(1, 10)]) + .with_delegations(vec![(2, 1, 15)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + let state = ParachainStaking::delegation_scheduled_requests(&1); + assert_eq!( + state, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], + ); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + // candidate state is not immediately removed + let candidate_state = + ParachainStaking::candidate_info(1).expect("just left => still exists"); + assert_eq!(candidate_state.bond, 10u128); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 1)); + assert!(ParachainStaking::candidate_info(1).is_none()); + assert!( + !ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation request not removed" + ); + assert!( + !>::contains_key(&1), + "the key was not removed from storage" + ); + }); +} + +#[test] +fn cannot_execute_leave_candidates_before_delay() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_noop!( + ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), + Error::::CandidateCannotLeaveYet + ); + roll_to(9); + assert_noop!( + ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), + Error::::CandidateCannotLeaveYet + ); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0)); + }); +} + +// CANCEL LEAVE CANDIDATES + +#[test] +fn cancel_leave_candidates_emits_event() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_events_emitted!(Event::CancelledCandidateExit { candidate: 1 }); + }); +} + +#[test] +fn cancel_leave_candidates_updates_candidate_state() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); + let candidate = + ParachainStaking::candidate_info(&1).expect("just cancelled leave so exists"); + assert!(candidate.is_active()); + }); +} + +#[test] +fn cancel_leave_candidates_adds_to_candidate_pool() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 10); + }); +} + +// GO OFFLINE + +#[test] +fn go_offline_event_emits_correctly() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert_events_eq!(Event::CandidateWentOffline { candidate: 1 }); + }); +} + +#[test] +fn go_offline_removes_candidate_from_candidate_pool() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert!(ParachainStaking::candidate_pool().0.is_empty()); + }); +} + +#[test] +fn go_offline_updates_candidate_state_to_idle() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + let candidate_state = ParachainStaking::candidate_info(1).expect("is active candidate"); + assert_eq!(candidate_state.status, CollatorStatus::Active); + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + let candidate_state = + ParachainStaking::candidate_info(1).expect("is candidate, just offline"); + assert_eq!(candidate_state.status, CollatorStatus::Idle); + }); +} + +#[test] +fn cannot_go_offline_if_not_candidate() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::go_offline(RuntimeOrigin::signed(3)), + Error::::CandidateDNE + ); + }); +} + +#[test] +fn cannot_go_offline_if_already_offline() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert_noop!( + ParachainStaking::go_offline(RuntimeOrigin::signed(1)), + Error::::AlreadyOffline + ); + }); +} + +// GO ONLINE + +#[test] +fn go_online_event_emits_correctly() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + roll_blocks(1); + assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); + assert_events_eq!(Event::CandidateBackOnline { candidate: 1 }); + }); +} + +#[test] +fn go_online_adds_to_candidate_pool() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert!(ParachainStaking::candidate_pool().0.is_empty()); + assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); + }); +} + +#[test] +fn go_online_storage_updates_candidate_state() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + let candidate_state = + ParachainStaking::candidate_info(1).expect("offline still exists"); + assert_eq!(candidate_state.status, CollatorStatus::Idle); + assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); + let candidate_state = ParachainStaking::candidate_info(1).expect("online so exists"); + assert_eq!(candidate_state.status, CollatorStatus::Active); + }); +} + +#[test] +fn cannot_go_online_if_not_candidate() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::go_online(RuntimeOrigin::signed(3)), + Error::::CandidateDNE + ); + }); +} + +#[test] +fn cannot_go_online_if_already_online() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::go_online(RuntimeOrigin::signed(1)), + Error::::AlreadyActive + ); + }); +} + +#[test] +fn cannot_go_online_if_leaving() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_noop!( + ParachainStaking::go_online(RuntimeOrigin::signed(1)), + Error::::CannotGoOnlineIfLeaving + ); + }); +} + +// CANDIDATE BOND MORE + +#[test] +fn candidate_bond_more_emits_correct_event() { + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + assert_events_eq!(Event::CandidateBondedMore { + candidate: 1, + amount: 30, + new_total_bond: 50 + }); + }); +} + +#[test] +fn candidate_bond_more_reserves_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 30); + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); + }); +} + +#[test] +fn candidate_bond_more_increases_total() { + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + let mut total = ParachainStaking::total(); + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + total += 30; + assert_eq!(ParachainStaking::total(), total); + }); +} + +#[test] +fn candidate_bond_more_updates_candidate_state() { + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 20); + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 50); + }); +} + +#[test] +fn candidate_bond_more_updates_candidate_pool() { + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 50); + }); +} + +// SCHEDULE CANDIDATE BOND LESS + +#[test] +fn schedule_candidate_bond_less_event_emits_correctly() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + assert_events_eq!(Event::CandidateBondLessRequested { + candidate: 1, + amount_to_decrease: 10, + execute_round: 3, + }); + }); +} + +#[test] +fn cannot_schedule_candidate_bond_less_if_request_exists() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 5)); + assert_noop!( + ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 5), + Error::::PendingCandidateRequestAlreadyExists + ); + }); +} + +#[test] +fn cannot_schedule_candidate_bond_less_if_not_candidate() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(6), 50), + Error::::CandidateDNE + ); + }); +} + +#[test] +fn cannot_schedule_candidate_bond_less_if_new_total_below_min_candidate_stk() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 21), + Error::::CandidateBondBelowMin + ); + }); +} + +#[test] +fn can_schedule_candidate_bond_less_if_leaving_candidates() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + }); +} + +#[test] +fn cannot_schedule_candidate_bond_less_if_exited_candidates() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert_noop!( + ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10), + Error::::CandidateDNE + ); + }); +} + +// 2. EXECUTE BOND LESS REQUEST + +#[test] +fn execute_candidate_bond_less_emits_correct_event() { + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 50)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 30 + )); + roll_to(10); + roll_blocks(1); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + assert_events_eq!(Event::CandidateBondedLess { + candidate: 1, + amount: 30, + new_bond: 20 + }); + }); +} + +#[test] +fn execute_candidate_bond_less_unreserves_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); + }); +} + +#[test] +fn execute_candidate_bond_less_decreases_total() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + let mut total = ParachainStaking::total(); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + total -= 10; + assert_eq!(ParachainStaking::total(), total); + }); +} + +#[test] +fn execute_candidate_bond_less_updates_candidate_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 30); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 20); + }); +} + +#[test] +fn execute_candidate_bond_less_updates_candidate_pool() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 30); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); + }); +} + +// CANCEL CANDIDATE BOND LESS REQUEST + +#[test] +fn cancel_candidate_bond_less_emits_event() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + assert_ok!(ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(1))); + assert_events_emitted!(Event::CancelledCandidateBondLess { + candidate: 1, + amount: 10, + execute_round: 3, + }); + }); +} + +#[test] +fn cancel_candidate_bond_less_updates_candidate_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + assert_ok!(ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(1))); + assert!(ParachainStaking::candidate_info(&1).unwrap().request.is_none()); + }); +} + +#[test] +fn only_candidate_can_cancel_candidate_bond_less_request() { + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + assert_noop!( + ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(2)), + Error::::CandidateDNE + ); + }); +} + +// DELEGATE + +#[test] +fn delegate_event_emits_correctly() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); + assert_events_eq!(Event::Delegation { + delegator: 2, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, + auto_compound: Percent::zero(), + }); + }); +} + +#[test] +fn delegate_reserves_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); + }); +} + +#[test] +fn delegate_updates_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert!(ParachainStaking::delegator_state(2).is_none()); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); + let delegator_state = + ParachainStaking::delegator_state(2).expect("just delegated => exists"); + assert_eq!(delegator_state.total(), 10); + assert_eq!(delegator_state.delegations.0[0].owner, 1); + assert_eq!(delegator_state.delegations.0[0].amount, 10); + }); +} + +#[test] +fn delegate_updates_collator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + let candidate_state = + ParachainStaking::candidate_info(1).expect("registered in genesis"); + assert_eq!(candidate_state.total_counted, 30); + let top_delegations = + ParachainStaking::top_delegations(1).expect("registered in genesis"); + assert!(top_delegations.delegations.is_empty()); + assert!(top_delegations.total.is_zero()); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); + let candidate_state = + ParachainStaking::candidate_info(1).expect("just delegated => exists"); + assert_eq!(candidate_state.total_counted, 40); + let top_delegations = + ParachainStaking::top_delegations(1).expect("just delegated => exists"); + assert_eq!(top_delegations.delegations[0].owner, 2); + assert_eq!(top_delegations.delegations[0].amount, 10); + assert_eq!(top_delegations.total, 10); + }); +} + +#[test] +fn can_delegate_immediately_after_other_join_candidates() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 20, 0)); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 20, 0, 0)); + }); +} + +#[test] +fn can_delegate_if_revoking() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 30), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 4, 10, 0, 2)); + }); +} + +#[test] +fn cannot_delegate_if_full_and_new_delegation_less_than_or_equal_lowest_bottom() { + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 10), + (3, 10), + (4, 10), + (5, 10), + (6, 10), + (7, 10), + (8, 10), + (9, 10), + (10, 10), + (11, 10), + ]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (2, 1, 10), + (3, 1, 10), + (4, 1, 10), + (5, 1, 10), + (6, 1, 10), + (8, 1, 10), + (9, 1, 10), + (10, 1, 10), + ]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate(RuntimeOrigin::signed(11), 1, 10, 8, 0), + Error::::CannotDelegateLessThanOrEqualToLowestBottomWhenFull + ); + }); +} + +#[test] +fn can_delegate_if_full_and_new_delegation_greater_than_lowest_bottom() { + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 10), + (3, 10), + (4, 10), + (5, 10), + (6, 10), + (7, 10), + (8, 10), + (9, 10), + (10, 10), + (11, 11), + ]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (2, 1, 10), + (3, 1, 10), + (4, 1, 10), + (5, 1, 10), + (6, 1, 10), + (8, 1, 10), + (9, 1, 10), + (10, 1, 10), + ]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(11), 1, 11, 8, 0)); + assert_events_emitted!(Event::DelegationKicked { + delegator: 10, + candidate: 1, + unstaked_amount: 10 + }); + assert_events_emitted!(Event::DelegatorLeft { delegator: 10, unstaked_amount: 10 }); + }); +} + +#[test] +fn can_still_delegate_if_leaving() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 20), (3, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 3, 10, 0, 1),); + }); +} + +#[test] +fn cannot_delegate_if_candidate() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 30)]) + .with_candidates(vec![(1, 20), (2, 20)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0), + Error::::CandidateExists + ); + }); +} + +#[test] +fn cannot_delegate_if_already_delegated() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 30)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 20)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 1, 1), + Error::::AlreadyDelegatedCandidate + ); + }); +} + +#[test] +fn cannot_delegate_more_than_max_delegations() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 50), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10), (2, 4, 10), (2, 5, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate(RuntimeOrigin::signed(2), 6, 10, 0, 4), + Error::::ExceedMaxDelegationsPerDelegator, + ); + }); +} + +#[test] +fn sufficient_delegate_weight_hint_succeeds() { + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 20), + (3, 20), + (4, 20), + (5, 20), + (6, 20), + (7, 20), + (8, 20), + (9, 20), + (10, 20), + ]) + .with_candidates(vec![(1, 20), (2, 20)]) + .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) + .build() + .execute_with(|| { + let mut count = 4u32; + for i in 7..11 { + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(i), + 1, + 10, + count, + 0u32 + )); + count += 1u32; + } + let mut count = 0u32; + for i in 3..11 { + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(i), + 2, + 10, + count, + 1u32 + )); + count += 1u32; + } + }); +} + +#[test] +fn insufficient_delegate_weight_hint_fails() { + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 20), + (3, 20), + (4, 20), + (5, 20), + (6, 20), + (7, 20), + (8, 20), + (9, 20), + (10, 20), + ]) + .with_candidates(vec![(1, 20), (2, 20)]) + .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) + .build() + .execute_with(|| { + let mut count = 3u32; + for i in 7..11 { + assert_noop!( + ParachainStaking::delegate(RuntimeOrigin::signed(i), 1, 10, count, 0u32), + Error::::TooLowCandidateDelegationCountToDelegate + ); + } + // to set up for next error test + count = 4u32; + for i in 7..11 { + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(i), + 1, + 10, + count, + 0u32 + )); + count += 1u32; + } + count = 0u32; + for i in 3..11 { + assert_noop!( + ParachainStaking::delegate(RuntimeOrigin::signed(i), 2, 10, count, 0u32), + Error::::TooLowDelegationCountToDelegate + ); + count += 1u32; + } + }); +} + +// SCHEDULE LEAVE DELEGATORS + +#[test] +fn schedule_leave_delegators_event_emits_correctly() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 1, + delegator: 2, + scheduled_exit: 3 + }); + }); +} + +#[test] +fn cannot_schedule_leave_delegators_if_already_leaving() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_noop!( + ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2)), + Error::::DelegatorAlreadyLeaving + ); + }); +} + +#[test] +fn cannot_schedule_leave_delegators_if_not_delegator() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2)), + Error::::DelegatorDNE + ); + }); +} + +// EXECUTE LEAVE DELEGATORS + +#[test] +fn execute_leave_delegators_event_emits_correctly() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); + assert_events_emitted!(Event::DelegatorLeft { delegator: 2, unstaked_amount: 10 }); + }); +} + +#[test] +fn execute_leave_delegators_unreserves_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 00); + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); + assert_eq!(crate::mock::query_lock_amount(2, DELEGATOR_LOCK_ID), None); + }); +} + +#[test] +fn execute_leave_delegators_decreases_total_staked() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 40); + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); + assert_eq!(ParachainStaking::total(), 30); + }); +} + +#[test] +fn execute_leave_delegators_removes_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert!(ParachainStaking::delegator_state(2).is_some()); + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); + assert!(ParachainStaking::delegator_state(2).is_none()); + }); +} + +#[test] +fn execute_leave_delegators_removes_pending_delegation_requests() { + ExtBuilder::default() + .with_balances(vec![(1, 10), (2, 15)]) + .with_candidates(vec![(1, 10)]) + .with_delegations(vec![(2, 1, 15)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + let state = ParachainStaking::delegation_scheduled_requests(&1); + assert_eq!( + state, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], + ); + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); + assert!(ParachainStaking::delegator_state(2).is_none()); + assert!( + !ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation request not removed" + ) + }); +} + +#[test] +fn execute_leave_delegators_removes_delegations_from_collator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 20), (3, 20), (4, 20), (5, 20)]) + .with_candidates(vec![(2, 20), (3, 20), (4, 20), (5, 20)]) + .with_delegations(vec![(1, 2, 10), (1, 3, 10), (1, 4, 10), (1, 5, 10)]) + .build() + .execute_with(|| { + for i in 2..6 { + let candidate_state = + ParachainStaking::candidate_info(i).expect("initialized in ext builder"); + assert_eq!(candidate_state.total_counted, 30); + let top_delegations = + ParachainStaking::top_delegations(i).expect("initialized in ext builder"); + assert_eq!(top_delegations.delegations[0].owner, 1); + assert_eq!(top_delegations.delegations[0].amount, 10); + assert_eq!(top_delegations.total, 10); + } + assert_eq!(ParachainStaking::delegator_state(1).unwrap().delegations.0.len(), 4usize); + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(1))); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(1), 1, 10)); + for i in 2..6 { + let candidate_state = + ParachainStaking::candidate_info(i).expect("initialized in ext builder"); + assert_eq!(candidate_state.total_counted, 20); + let top_delegations = + ParachainStaking::top_delegations(i).expect("initialized in ext builder"); + assert!(top_delegations.delegations.is_empty()); + } + }); +} + +#[test] +fn cannot_execute_leave_delegators_before_delay() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_noop!( + ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1), + Error::::DelegatorCannotLeaveYet + ); + // can execute after delay + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); + }); +} + +#[test] +fn cannot_execute_leave_delegators_if_single_delegation_revoke_manually_cancelled() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 3)); + roll_to(10); + assert_noop!( + ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2), + Error::::DelegatorNotLeaving + ); + // can execute after manually scheduling revoke, and the round delay after which + // all revokes can be executed + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3)); + roll_to(20); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2)); + }); +} + +#[test] +fn insufficient_execute_leave_delegators_weight_hint_fails() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) + .build() + .execute_with(|| { + for i in 3..7 { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(i))); + } + roll_to(10); + for i in 3..7 { + assert_noop!( + ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(i), i, 0), + Error::::TooLowDelegationCountToLeaveDelegators + ); + } + }); +} + +#[test] +fn sufficient_execute_leave_delegators_weight_hint_succeeds() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) + .build() + .execute_with(|| { + for i in 3..7 { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(i))); + } + roll_to(10); + for i in 3..7 { + assert_ok!(ParachainStaking::execute_leave_delegators( + RuntimeOrigin::signed(i), + i, + 1 + )); + } + }); +} + +// CANCEL LEAVE DELEGATORS + +#[test] +fn cancel_leave_delegators_emits_correct_event() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); + assert_events_emitted!(Event::DelegatorExitCancelled { delegator: 2 }); + }); +} + +#[test] +fn cancel_leave_delegators_updates_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); + let delegator = + ParachainStaking::delegator_state(&2).expect("just cancelled exit so exists"); + assert!(delegator.is_active()); + }); +} + +#[test] +fn cannot_cancel_leave_delegators_if_single_delegation_revoke_manually_cancelled() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 3)); + roll_to(10); + assert_noop!( + ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2)), + Error::::DelegatorNotLeaving + ); + // can execute after manually scheduling revoke, without waiting for round delay after + // which all revokes can be executed + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3)); + assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); + }); +} + +// SCHEDULE REVOKE DELEGATION + +#[test] +fn revoke_delegation_event_emits_correctly() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_events_eq!(Event::DelegationRevocationScheduled { + round: 1, + delegator: 2, + candidate: 1, + scheduled_exit: 3, + }); + roll_to_round_begin(3); + roll_blocks(1); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_events_eq!( + Event::DelegatorLeftCandidate { + delegator: 2, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 30 + }, + Event::DelegationRevoked { delegator: 2, candidate: 1, unstaked_amount: 10 }, + ); + }); +} + +#[test] +fn can_revoke_delegation_if_revoking_another_delegation() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + // this is an exit implicitly because last delegation revoked + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3)); + }); +} + +#[test] +fn delegator_not_allowed_revoke_if_already_leaving() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_noop!( + ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3), + >::PendingDelegationRequestAlreadyExists, + ); + }); +} + +#[test] +fn cannot_revoke_delegation_if_not_delegator() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1), + Error::::DelegatorDNE + ); + }); +} + +#[test] +fn cannot_revoke_delegation_that_dne() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3), + Error::::DelegationDNE + ); + }); +} + +#[test] +// See `cannot_execute_revoke_delegation_below_min_delegator_stake` for where the "must be above +// MinDelegatorStk" rule is now enforced. +fn can_schedule_revoke_delegation_below_min_delegator_stake() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 8), (3, 20)]) + .with_candidates(vec![(1, 20), (3, 20)]) + .with_delegations(vec![(2, 1, 5), (2, 3, 3)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + }); +} + +// DELEGATOR BOND MORE + +#[test] +fn delegator_bond_more_reserves_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 5); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); + }); +} + +#[test] +fn delegator_bond_more_increases_total_staked() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 40); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); + assert_eq!(ParachainStaking::total(), 45); + }); +} + +#[test] +fn delegator_bond_more_updates_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 10); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); + assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 15); + }); +} + +#[test] +fn delegator_bond_more_updates_candidate_state_top_delegations() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); + assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 10); + assert_eq!(ParachainStaking::top_delegations(1).unwrap().total, 10); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); + assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); + assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 15); + assert_eq!(ParachainStaking::top_delegations(1).unwrap().total, 15); + }); +} + +#[test] +fn delegator_bond_more_updates_candidate_state_bottom_delegations() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10), (3, 1, 20), (4, 1, 20), (5, 1, 20), (6, 1, 20)]) + .build() + .execute_with(|| { + assert_eq!( + ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].owner, + 2 + ); + assert_eq!( + ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].amount, + 10 + ); + assert_eq!(ParachainStaking::bottom_delegations(1).unwrap().total, 10); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); + assert_events_eq!(Event::DelegationIncreased { + delegator: 2, + candidate: 1, + amount: 5, + in_top: false + }); + assert_eq!( + ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].owner, + 2 + ); + assert_eq!( + ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].amount, + 15 + ); + assert_eq!(ParachainStaking::bottom_delegations(1).unwrap().total, 15); + }); +} + +#[test] +fn delegator_bond_more_increases_total() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 40); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); + assert_eq!(ParachainStaking::total(), 45); + }); +} + +#[test] +fn can_delegator_bond_more_for_leaving_candidate() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); + }); +} + +#[test] +fn delegator_bond_more_disallowed_when_revoke_scheduled() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_noop!( + ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5), + >::PendingDelegationRevoke + ); + }); +} + +#[test] +fn delegator_bond_more_allowed_when_bond_decrease_scheduled() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 15)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5, + )); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); + }); +} + +// DELEGATOR BOND LESS + +#[test] +fn delegator_bond_less_event_emits_correctly() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + assert_events_eq!(Event::DelegationDecreaseScheduled { + delegator: 2, + candidate: 1, + amount_to_decrease: 5, + execute_round: 3, + }); + }); +} + +#[test] +fn delegator_bond_less_updates_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + let state = ParachainStaking::delegation_scheduled_requests(&1); + assert_eq!( + state, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], + ); + }); +} + +#[test] +fn delegator_not_allowed_bond_less_if_leaving() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 1), + >::PendingDelegationRequestAlreadyExists, + ); + }); +} + +#[test] +fn cannot_delegator_bond_less_if_revoking() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 1), + Error::::PendingDelegationRequestAlreadyExists + ); + }); +} + +#[test] +fn cannot_delegator_bond_less_if_not_delegator() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5), + Error::::DelegatorDNE + ); + }); +} + +#[test] +fn cannot_delegator_bond_less_if_candidate_dne() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 3, 5), + Error::::DelegationDNE + ); + }); +} + +#[test] +fn cannot_delegator_bond_less_if_delegation_dne() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 3, 5), + Error::::DelegationDNE + ); + }); +} + +#[test] +fn cannot_delegator_bond_less_below_min_collator_stk() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 6), + Error::::DelegatorBondBelowMin + ); + }); +} + +#[test] +fn cannot_delegator_bond_less_more_than_total_delegation() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 11), + Error::::DelegatorBondBelowMin + ); + }); +} + +#[test] +fn cannot_delegator_bond_less_below_min_delegation() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 8), + Error::::DelegationBelowMin + ); + }); +} + +// EXECUTE PENDING DELEGATION REQUEST + +// 1. REVOKE DELEGATION + +#[test] +fn execute_revoke_delegation_emits_exit_event_if_exit_happens() { + // last delegation is revocation + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_events_emitted!(Event::DelegatorLeftCandidate { + delegator: 2, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 30 + }); + assert_events_emitted!(Event::DelegatorLeft { delegator: 2, unstaked_amount: 10 }); + }); +} + +#[test] +fn cannot_execute_revoke_delegation_below_min_delegator_stake() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 8), (3, 20)]) + .with_candidates(vec![(1, 20), (3, 20)]) + .with_delegations(vec![(2, 1, 5), (2, 3, 3)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_noop!( + ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1), + Error::::DelegatorBondBelowMin + ); + // but delegator can cancel the request and request to leave instead: + assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + roll_to(20); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2)); + }); +} + +#[test] +fn revoke_delegation_executes_exit_if_last_delegation() { + // last delegation is revocation + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_events_emitted!(Event::DelegatorLeftCandidate { + delegator: 2, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 30 + }); + assert_events_emitted!(Event::DelegatorLeft { delegator: 2, unstaked_amount: 10 }); + }); +} + +#[test] +fn execute_revoke_delegation_emits_correct_event() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_events_emitted!(Event::DelegatorLeftCandidate { + delegator: 2, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 30 + }); + }); +} + +#[test] +fn execute_revoke_delegation_unreserves_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); + }); +} + +#[test] +fn execute_revoke_delegation_adds_revocation_to_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert!(!ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2)); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert!(ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2)); + }); +} + +#[test] +fn execute_revoke_delegation_removes_revocation_from_delegator_state_upon_execution() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!(!ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2)); + }); +} + +#[test] +fn execute_revoke_delegation_removes_revocation_from_state_for_single_delegation_leave() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!( + !ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation was not removed" + ); + }); +} + +#[test] +fn execute_revoke_delegation_decreases_total_staked() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 40); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!(ParachainStaking::total(), 30); + }); +} + +#[test] +fn execute_revoke_delegation_for_last_delegation_removes_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert!(ParachainStaking::delegator_state(2).is_some()); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + // this will be confusing for people + // if status is leaving, then execute_delegation_request works if last delegation + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!(ParachainStaking::delegator_state(2).is_none()); + }); +} + +#[test] +fn execute_revoke_delegation_removes_delegation_from_candidate_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::candidate_info(1).expect("exists").delegation_count, 1u32); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!(ParachainStaking::candidate_info(1) + .expect("exists") + .delegation_count + .is_zero()); + }); +} + +#[test] +fn can_execute_revoke_delegation_for_leaving_candidate() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + // can execute delegation request for leaving candidate + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + }); +} + +#[test] +fn can_execute_leave_candidates_if_revoking_candidate() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + // revocation executes during execute leave candidates (callable by anyone) + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 1)); + assert!(!ParachainStaking::is_delegator(&2)); + assert_eq!(Balances::reserved_balance(&2), 0); + assert_eq!(Balances::free_balance(&2), 10); + }); +} + +#[test] +fn delegator_bond_more_after_revoke_delegation_does_not_effect_exit() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 30), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 3, 10)); + roll_to(100); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!(ParachainStaking::is_delegator(&2)); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); + }); +} + +#[test] +fn delegator_bond_less_after_revoke_delegation_does_not_effect_exit() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 30), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_events_eq!(Event::DelegationRevocationScheduled { + round: 1, + delegator: 2, + candidate: 1, + scheduled_exit: 3, + }); + assert_noop!( + ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 2), + Error::::PendingDelegationRequestAlreadyExists + ); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 3, + 2 + )); + roll_to(10); + roll_blocks(1); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 3 + )); + assert_events_eq!( + Event::DelegatorLeftCandidate { + delegator: 2, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 30, + }, + Event::DelegationRevoked { delegator: 2, candidate: 1, unstaked_amount: 10 }, + Event::DelegationDecreased { delegator: 2, candidate: 3, amount: 2, in_top: true }, + ); + assert!(ParachainStaking::is_delegator(&2)); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 22); + }); +} + +// 2. EXECUTE BOND LESS + +#[test] +fn execute_delegator_bond_less_unreserves_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 5); + }); +} + +#[test] +fn execute_delegator_bond_less_decreases_total_staked() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 40); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!(ParachainStaking::total(), 35); + }); +} + +#[test] +fn execute_delegator_bond_less_updates_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 10); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 5); + }); +} + +#[test] +fn execute_delegator_bond_less_updates_candidate_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); + assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 10); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); + assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 5); + }); +} + +#[test] +fn execute_delegator_bond_less_decreases_total() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 40); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!(ParachainStaking::total(), 35); + }); +} + +#[test] +fn execute_delegator_bond_less_updates_just_bottom_delegations() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 10), (3, 11), (4, 12), (5, 14), (6, 15)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 10), (3, 1, 11), (4, 1, 12), (5, 1, 14), (6, 1, 15)]) + .build() + .execute_with(|| { + let pre_call_candidate_info = + ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let pre_call_top_delegations = + ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + let pre_call_bottom_delegations = + ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 2 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + let post_call_candidate_info = + ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let post_call_top_delegations = + ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + let post_call_bottom_delegations = + ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); + let mut not_equal = false; + for Bond { owner, amount } in pre_call_bottom_delegations.delegations { + for Bond { owner: post_owner, amount: post_amount } in + &post_call_bottom_delegations.delegations + { + if &owner == post_owner { + if &amount != post_amount { + not_equal = true; + break + } + } + } + } + assert!(not_equal); + let mut equal = true; + for Bond { owner, amount } in pre_call_top_delegations.delegations { + for Bond { owner: post_owner, amount: post_amount } in + &post_call_top_delegations.delegations + { + if &owner == post_owner { + if &amount != post_amount { + equal = false; + break + } + } + } + } + assert!(equal); + assert_eq!( + pre_call_candidate_info.total_counted, + post_call_candidate_info.total_counted + ); + }); +} + +#[test] +fn execute_delegator_bond_less_does_not_delete_bottom_delegations() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 10), (3, 11), (4, 12), (5, 14), (6, 15)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 10), (3, 1, 11), (4, 1, 12), (5, 1, 14), (6, 1, 15)]) + .build() + .execute_with(|| { + let pre_call_candidate_info = + ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let pre_call_top_delegations = + ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + let pre_call_bottom_delegations = + ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(6), + 1, + 4 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(6), + 6, + 1 + )); + let post_call_candidate_info = + ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let post_call_top_delegations = + ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + let post_call_bottom_delegations = + ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); + let mut equal = true; + for Bond { owner, amount } in pre_call_bottom_delegations.delegations { + for Bond { owner: post_owner, amount: post_amount } in + &post_call_bottom_delegations.delegations + { + if &owner == post_owner { + if &amount != post_amount { + equal = false; + break + } + } + } + } + assert!(equal); + let mut not_equal = false; + for Bond { owner, amount } in pre_call_top_delegations.delegations { + for Bond { owner: post_owner, amount: post_amount } in + &post_call_top_delegations.delegations + { + if &owner == post_owner { + if &amount != post_amount { + not_equal = true; + break + } + } + } + } + assert!(not_equal); + assert_eq!( + pre_call_candidate_info.total_counted - 4, + post_call_candidate_info.total_counted + ); + }); +} + +#[test] +fn can_execute_delegator_bond_less_for_leaving_candidate() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 15)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + roll_to(10); + // can execute bond more delegation request for leaving candidate + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + }); +} + +// CANCEL PENDING DELEGATION REQUEST +// 1. CANCEL REVOKE DELEGATION + +#[test] +fn cancel_revoke_delegation_emits_correct_event() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); + assert_events_emitted!(Event::CancelledDelegationRequest { + delegator: 2, + collator: 1, + cancelled_request: CancelledScheduledRequest { + when_executable: 3, + action: DelegationAction::Revoke(10), + }, + }); + }); +} + +#[test] +fn cancel_revoke_delegation_updates_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + let state = ParachainStaking::delegation_scheduled_requests(&1); + assert_eq!( + state, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Revoke(10), + }], + ); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 10 + ); + assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); + assert!(!ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2)); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 0 + ); + }); +} + +// 2. CANCEL DELEGATOR BOND LESS + +#[test] +fn cancel_delegator_bond_less_correct_event() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 15)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); + assert_events_emitted!(Event::CancelledDelegationRequest { + delegator: 2, + collator: 1, + cancelled_request: CancelledScheduledRequest { + when_executable: 3, + action: DelegationAction::Decrease(5), + }, + }); + }); +} + +#[test] +fn cancel_delegator_bond_less_updates_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 15)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 15)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); + let state = ParachainStaking::delegation_scheduled_requests(&1); + assert_eq!( + state, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], + ); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 5 + ); + assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); + assert!(!ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2)); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 0 + ); + }); +} + +// ~~ PROPERTY-BASED TESTS ~~ + +#[test] +fn delegator_schedule_revocation_total() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20), (5, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20), (5, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10), (2, 4, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 10 + ); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 0 + ); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 5, 10, 0, 2)); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3)); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 4)); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 20, + ); + roll_to(20); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 3 + )); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 10, + ); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 4 + )); + assert_eq!( + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), + 0 + ); + }); +} + +#[ignore] +#[test] +fn parachain_bond_inflation_reserve_matches_config() { + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + (11, 1), + ]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) + .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!(Balances::free_balance(&11), 1); + // set parachain bond account so DefaultParachainBondReservePercent = 30% of inflation + // is allocated to this account hereafter + assert_ok!(ParachainStaking::set_parachain_bond_account(RuntimeOrigin::root(), 11)); + assert_events_eq!(Event::ParachainBondAccountSet { old: 0, new: 11 }); + roll_to_round_begin(2); + // chooses top TotalSelectedCandidates (5), in order + assert_events_eq!( + Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 2, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 5, + total_balance: 140, + }, + ); + assert_eq!(Balances::free_balance(&11), 1); + // ~ set block author as 1 for all blocks this round + set_author(2, 1, 100); + roll_to_round_begin(4); + // distribute total issuance to collator 1 and its delegators 6, 7, 19 + assert_eq!(Balances::free_balance(&11), 16); + // ~ set block author as 1 for all blocks this round + set_author(3, 1, 100); + set_author(4, 1, 100); + set_author(5, 1, 100); + // 1. ensure delegators are paid for 2 rounds after they leave + assert_noop!( + ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(66)), + Error::::DelegatorDNE + ); + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(6))); + assert_events_eq!( + Event::ReservedForParachainBond { account: 11, value: 15 }, + Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 4, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 4, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 4, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 5, + total_balance: 140, + }, + Event::DelegatorExitScheduled { round: 4, delegator: 6, scheduled_exit: 6 }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 20 }, + Event::Rewarded { account: 6, rewards: 5 }, + Event::Rewarded { account: 7, rewards: 5 }, + Event::Rewarded { account: 10, rewards: 5 }, + ); + // fast forward to block in which delegator 6 exit executes + roll_to_round_begin(5); + assert_events_eq!( + Event::ReservedForParachainBond { account: 11, value: 16 }, + Event::CollatorChosen { round: 5, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 5, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 5, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 5, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 5, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 20, + round: 5, + selected_collators_number: 5, + total_balance: 140, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 21 }, + Event::Rewarded { account: 6, rewards: 5 }, + Event::Rewarded { account: 7, rewards: 5 }, + Event::Rewarded { account: 10, rewards: 5 }, + ); + roll_to_round_begin(6); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(6), 6, 10)); + assert_events_eq!( + Event::ReservedForParachainBond { account: 11, value: 16 }, + Event::CollatorChosen { round: 6, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 6, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 25, + round: 6, + selected_collators_number: 5, + total_balance: 140, + }, + Event::DelegatorLeftCandidate { + delegator: 6, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 40, + }, + Event::DelegatorLeft { delegator: 6, unstaked_amount: 10 }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 22 }, + Event::Rewarded { account: 6, rewards: 6 }, + Event::Rewarded { account: 7, rewards: 6 }, + Event::Rewarded { account: 10, rewards: 6 }, + ); + roll_to_round_begin(7); + assert_events_eq!( + Event::ReservedForParachainBond { account: 11, value: 17 }, + Event::CollatorChosen { round: 7, collator_account: 1, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 7, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 7, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 7, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 7, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 30, + round: 7, + selected_collators_number: 5, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 26 }, + Event::Rewarded { account: 7, rewards: 7 }, + Event::Rewarded { account: 10, rewards: 7 }, + ); + assert_eq!(Balances::free_balance(&11), 65); + roll_blocks(1); + assert_ok!(ParachainStaking::set_parachain_bond_reserve_percent( + RuntimeOrigin::root(), + Percent::from_percent(50) + )); + assert_events_eq!(Event::ParachainBondReservePercentSet { + old: Percent::from_percent(30), + new: Percent::from_percent(50), + }); + // 6 won't be paid for this round because they left already + set_author(6, 1, 100); + roll_to_round_begin(8); + // keep paying 6 + assert_events_eq!( + Event::ReservedForParachainBond { account: 11, value: 30 }, + Event::CollatorChosen { round: 8, collator_account: 1, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 8, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 8, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 8, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 8, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 35, + round: 8, + selected_collators_number: 5, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 21 }, + Event::Rewarded { account: 7, rewards: 5 }, + Event::Rewarded { account: 10, rewards: 5 }, + ); + assert_eq!(Balances::free_balance(&11), 95); + set_author(7, 1, 100); + roll_to_round_begin(9); + // no more paying 6 + assert_events_eq!( + Event::ReservedForParachainBond { account: 11, value: 32 }, + Event::CollatorChosen { round: 9, collator_account: 1, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 9, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 9, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 9, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 9, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 40, + round: 9, + selected_collators_number: 5, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 22 }, + Event::Rewarded { account: 7, rewards: 5 }, + Event::Rewarded { account: 10, rewards: 5 }, + ); + assert_eq!(Balances::free_balance(&11), 127); + set_author(8, 1, 100); + roll_blocks(1); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(8), 1, 10, 10, 10)); + assert_events_eq!(Event::Delegation { + delegator: 8, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, + auto_compound: Percent::zero(), + }); + roll_to_round_begin(10); + // new delegation is not rewarded yet + assert_events_eq!( + Event::ReservedForParachainBond { account: 11, value: 33 }, + Event::CollatorChosen { round: 10, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 10, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 10, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 10, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 10, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 45, + round: 10, + selected_collators_number: 5, + total_balance: 140, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 23 }, + Event::Rewarded { account: 7, rewards: 5 }, + Event::Rewarded { account: 10, rewards: 5 }, + ); + assert_eq!(Balances::free_balance(&11), 160); + set_author(9, 1, 100); + set_author(10, 1, 100); + roll_to_round_begin(11); + // new delegation is still not rewarded yet + assert_events_eq!( + Event::ReservedForParachainBond { account: 11, value: 35 }, + Event::CollatorChosen { round: 11, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 11, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 11, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 11, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 11, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 50, + round: 11, + selected_collators_number: 5, + total_balance: 140, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 24 }, + Event::Rewarded { account: 7, rewards: 5 }, + Event::Rewarded { account: 10, rewards: 5 }, + ); + assert_eq!(Balances::free_balance(&11), 195); + roll_to_round_begin(12); + // new delegation is rewarded, 2 rounds after joining (`RewardPaymentDelay` is 2) + assert_events_eq!( + Event::ReservedForParachainBond { account: 11, value: 37 }, + Event::CollatorChosen { round: 12, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 12, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 12, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 12, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 12, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 55, + round: 12, + selected_collators_number: 5, + total_balance: 140, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 24 }, + Event::Rewarded { account: 7, rewards: 4 }, + Event::Rewarded { account: 10, rewards: 4 }, + Event::Rewarded { account: 8, rewards: 4 }, + ); + assert_eq!(Balances::free_balance(&11), 232); + }); +} + +#[test] +fn paid_collator_commission_matches_config() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (6, 100)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 10), (3, 1, 10)]) + .build() + .execute_with(|| { + roll_to_round_begin(2); + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(4), 20u128, 100u32)); + assert_events_eq!( + Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 40 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 1, + total_balance: 40, + }, + Event::JoinedCollatorCandidates { + account: 4, + amount_locked: 20, + new_total_amt_locked: 60, + }, + ); + + roll_blocks(1); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(5), 4, 10, 10, 10)); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(6), 4, 10, 10, 10)); + assert_events_eq!( + Event::Delegation { + delegator: 5, + locked_amount: 10, + candidate: 4, + delegator_position: DelegatorAdded::AddedToTop { new_total: 30 }, + auto_compound: Percent::zero(), + }, + Event::Delegation { + delegator: 6, + locked_amount: 10, + candidate: 4, + delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, + auto_compound: Percent::zero(), + }, + ); + + roll_to_round_begin(3); + assert_events_eq!( + Event::CollatorChosen { round: 3, collator_account: 1, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 3, collator_account: 4, total_exposed_amount: 40 }, + Event::NewRound { + starting_block: 10, + round: 3, + selected_collators_number: 2, + total_balance: 80, + }, + ); + // only reward author with id 4 + set_author(3, 4, 100); + roll_to_round_begin(5); + // 20% of 10 is commission + due_portion (0) = 2 + 4 = 6 + // all delegator payouts are 10-2 = 8 * stake_pct + assert_events_eq!( + Event::CollatorChosen { round: 5, collator_account: 1, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 5, collator_account: 4, total_exposed_amount: 40 }, + Event::NewRound { + starting_block: 20, + round: 5, + selected_collators_number: 2, + total_balance: 80, + }, + ); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { account: 4, rewards: 18 }, + Event::Rewarded { account: 5, rewards: 6 }, + Event::Rewarded { account: 6, rewards: 6 }, + ); + }); +} + +#[test] +fn collator_exit_executes_after_delay() { + ExtBuilder::default() + .with_balances(vec![ + (1, 1000), + (2, 300), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 9), + (9, 4), + ]) + .with_candidates(vec![(1, 500), (2, 200)]) + .with_delegations(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) + .build() + .execute_with(|| { + roll_to(11); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(2), 2)); + assert_events_eq!(Event::CandidateScheduledExit { + exit_allowed_round: 3, + candidate: 2, + scheduled_exit: 5, + }); + let info = ParachainStaking::candidate_info(&2).unwrap(); + assert_eq!(info.status, CollatorStatus::Leaving(5)); + roll_to(21); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 2, 2)); + // we must exclude leaving collators from rewards while + // holding them retroactively accountable for previous faults + // (within the last T::SlashingWindow blocks) + assert_events_eq!(Event::CandidateLeft { + ex_candidate: 2, + unlocked_amount: 400, + new_total_amt_locked: 700, + },); + }); +} + +#[test] +fn collator_selection_chooses_top_candidates() { + ExtBuilder::default() + .with_balances(vec![ + (1, 1000), + (2, 1000), + (3, 1000), + (4, 1000), + (5, 1000), + (6, 1000), + (7, 33), + (8, 33), + (9, 33), + ]) + .with_candidates(vec![(1, 100), (2, 90), (3, 80), (4, 70), (5, 60), (6, 50)]) + .build() + .execute_with(|| { + roll_to_round_begin(2); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(6), 6)); + // should choose top TotalSelectedCandidates (5), in order + assert_events_eq!( + Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 100 }, + Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 90 }, + Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 80 }, + Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 70 }, + Event::CollatorChosen { round: 2, collator_account: 5, total_exposed_amount: 60 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 5, + total_balance: 400, + }, + Event::CandidateScheduledExit { + exit_allowed_round: 2, + candidate: 6, + scheduled_exit: 4 + }, + ); + roll_to_round_begin(4); + roll_blocks(1); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(6), 6, 0)); + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(6), 69u128, 100u32)); + assert_events_eq!( + Event::CandidateLeft { + ex_candidate: 6, + unlocked_amount: 50, + new_total_amt_locked: 400, + }, + Event::JoinedCollatorCandidates { + account: 6, + amount_locked: 69u128, + new_total_amt_locked: 469u128, + }, + ); + roll_to_round_begin(6); + // should choose top TotalSelectedCandidates (5), in order + assert_events_eq!( + Event::CollatorChosen { round: 6, collator_account: 1, total_exposed_amount: 100 }, + Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 90 }, + Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 80 }, + Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 70 }, + Event::CollatorChosen { round: 6, collator_account: 6, total_exposed_amount: 69 }, + Event::NewRound { + starting_block: 25, + round: 6, + selected_collators_number: 5, + total_balance: 409, + }, + ); + }); +} + +#[test] +fn payout_distribution_to_solo_collators() { + ExtBuilder::default() + .with_balances(vec![(1, 1000), (2, 1000), (3, 1000), (4, 1000), (7, 33), (8, 33), (9, 33)]) + .with_candidates(vec![(1, 100), (2, 90), (3, 80), (4, 70)]) + .build() + .execute_with(|| { + roll_to_round_begin(2); + // should choose top TotalCandidatesSelected (5), in order + assert_events_eq!( + Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 100 }, + Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 90 }, + Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 80 }, + Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 70 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 4, + total_balance: 340, + }, + ); + // ~ set block author as 1 for all blocks this round + set_author(2, 1, 100); + roll_to_round_begin(4); + assert_events_eq!( + Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 100 }, + Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 90 }, + Event::CollatorChosen { round: 4, collator_account: 3, total_exposed_amount: 80 }, + Event::CollatorChosen { round: 4, collator_account: 4, total_exposed_amount: 70 }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 4, + total_balance: 340, + }, + ); + // pay total issuance to 1 at 2nd block + roll_blocks(3); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 205 }); + // ~ set block author as 1 for 3 blocks this round + set_author(4, 1, 60); + // ~ set block author as 2 for 2 blocks this round + set_author(4, 2, 40); + roll_to_round_begin(6); + // pay 60% total issuance to 1 and 40% total issuance to 2 + assert_events_eq!( + Event::CollatorChosen { round: 6, collator_account: 1, total_exposed_amount: 100 }, + Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 90 }, + Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 80 }, + Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 70 }, + Event::NewRound { + starting_block: 25, + round: 6, + selected_collators_number: 4, + total_balance: 340, + }, + ); + roll_blocks(3); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 129 }); + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 2, rewards: 86 },); + // ~ each collator produces 1 block this round + set_author(6, 1, 20); + set_author(6, 2, 20); + set_author(6, 3, 20); + set_author(6, 4, 20); + roll_to_round_begin(8); + // pay 20% issuance for all collators + assert_events_eq!( + Event::CollatorChosen { round: 8, collator_account: 1, total_exposed_amount: 100 }, + Event::CollatorChosen { round: 8, collator_account: 2, total_exposed_amount: 90 }, + Event::CollatorChosen { round: 8, collator_account: 3, total_exposed_amount: 80 }, + Event::CollatorChosen { round: 8, collator_account: 4, total_exposed_amount: 70 }, + Event::NewRound { + starting_block: 35, + round: 8, + selected_collators_number: 4, + total_balance: 340, + }, + ); + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 3, rewards: 56 }); + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 4, rewards: 56 }); + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 56 }); + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 2, rewards: 56 }); + // check that distributing rewards clears awarded pts + assert!(ParachainStaking::awarded_pts(1, 1).is_zero()); + assert!(ParachainStaking::awarded_pts(4, 1).is_zero()); + assert!(ParachainStaking::awarded_pts(4, 2).is_zero()); + assert!(ParachainStaking::awarded_pts(6, 1).is_zero()); + assert!(ParachainStaking::awarded_pts(6, 2).is_zero()); + assert!(ParachainStaking::awarded_pts(6, 3).is_zero()); + assert!(ParachainStaking::awarded_pts(6, 4).is_zero()); + }); +} + +#[test] +fn multiple_delegations() { + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + ]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) + .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) + .build() + .execute_with(|| { + roll_to_round_begin(2); + // chooses top TotalSelectedCandidates (5), in order + assert_events_eq!( + Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 2, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 5, + total_balance: 140, + }, + ); + roll_blocks(1); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(6), 2, 10, 10, 10)); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(6), 3, 10, 10, 10)); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(6), 4, 10, 10, 10)); + assert_events_eq!( + Event::Delegation { + delegator: 6, + locked_amount: 10, + candidate: 2, + delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, + auto_compound: Percent::zero(), + }, + Event::Delegation { + delegator: 6, + locked_amount: 10, + candidate: 3, + delegator_position: DelegatorAdded::AddedToTop { new_total: 30 }, + auto_compound: Percent::zero(), + }, + Event::Delegation { + delegator: 6, + locked_amount: 10, + candidate: 4, + delegator_position: DelegatorAdded::AddedToTop { new_total: 30 }, + auto_compound: Percent::zero(), + }, + ); + roll_to_round_begin(6); + roll_blocks(1); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(7), 2, 80, 10, 10)); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(10), 2, 10, 10, 10)); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(2), 5)); + assert_events_eq!( + Event::Delegation { + delegator: 7, + locked_amount: 80, + candidate: 2, + delegator_position: DelegatorAdded::AddedToTop { new_total: 130 }, + auto_compound: Percent::zero(), + }, + Event::Delegation { + delegator: 10, + locked_amount: 10, + candidate: 2, + delegator_position: DelegatorAdded::AddedToBottom, + auto_compound: Percent::zero(), + }, + Event::CandidateScheduledExit { + exit_allowed_round: 6, + candidate: 2, + scheduled_exit: 8 + }, + ); + roll_to_round_begin(7); + assert_events_eq!( + Event::CollatorChosen { round: 7, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 7, collator_account: 3, total_exposed_amount: 30 }, + Event::CollatorChosen { round: 7, collator_account: 4, total_exposed_amount: 30 }, + Event::CollatorChosen { round: 7, collator_account: 5, total_exposed_amount: 10 }, + Event::NewRound { + starting_block: 30, + round: 7, + selected_collators_number: 4, + total_balance: 120, + }, + ); + // verify that delegations are removed after collator leaves, not before + assert_eq!(ParachainStaking::delegator_state(7).unwrap().total(), 90); + assert_eq!(ParachainStaking::delegator_state(7).unwrap().delegations.0.len(), 2usize); + assert_eq!(ParachainStaking::delegator_state(6).unwrap().total(), 40); + assert_eq!(ParachainStaking::delegator_state(6).unwrap().delegations.0.len(), 4usize); + assert_eq!(Balances::locks(&6)[0].amount, 40); + assert_eq!(Balances::locks(&7)[0].amount, 90); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&6), 60); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&7), 10); + roll_to_round_begin(8); + roll_blocks(1); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 2, 5)); + assert_events_eq!(Event::CandidateLeft { + ex_candidate: 2, + unlocked_amount: 140, + new_total_amt_locked: 120, + }); + assert_eq!(ParachainStaking::delegator_state(7).unwrap().total(), 10); + assert_eq!(ParachainStaking::delegator_state(6).unwrap().total(), 30); + assert_eq!(ParachainStaking::delegator_state(7).unwrap().delegations.0.len(), 1usize); + assert_eq!(ParachainStaking::delegator_state(6).unwrap().delegations.0.len(), 3usize); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&6), 70); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&7), 90); + }); +} + +#[test] +// The test verifies that the pending revoke request is removed by 2's exit so there is no dangling +// revoke request after 2 exits +fn execute_leave_candidate_removes_delegations() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100)]) + .with_candidates(vec![(1, 20), (2, 20)]) + .with_delegations(vec![(3, 1, 10), (3, 2, 10), (4, 1, 10), (4, 2, 10)]) + .build() + .execute_with(|| { + // Verifies the revocation request is initially empty + assert!(!ParachainStaking::delegation_scheduled_requests(&2) + .iter() + .any(|x| x.delegator == 3)); + + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(2), 2)); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(3), 2)); + // Verifies the revocation request is present + assert!(ParachainStaking::delegation_scheduled_requests(&2) + .iter() + .any(|x| x.delegator == 3)); + + roll_to(16); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 2, 2)); + // Verifies the revocation request is again empty + assert!(!ParachainStaking::delegation_scheduled_requests(&2) + .iter() + .any(|x| x.delegator == 3)); + }); +} + +#[test] +fn payouts_follow_delegation_changes() { + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + ]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) + .build() + .execute_with(|| { + roll_to_round_begin(2); + // chooses top TotalSelectedCandidates (5), in order + assert_events_eq!( + Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 4, + total_balance: 130, + }, + ); + // ~ set block author as 1 for all blocks this round + set_author(2, 1, 100); + roll_to_round_begin(4); + // distribute total issuance to collator 1 and its delegators 6, 7, 19 + assert_events_eq!( + Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 4, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 4, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 4, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 23 }, + Event::Rewarded { account: 6, rewards: 7 }, + Event::Rewarded { account: 7, rewards: 7 }, + Event::Rewarded { account: 10, rewards: 7 }, + ); + // ~ set block author as 1 for all blocks this round + set_author(3, 1, 100); + set_author(4, 1, 100); + set_author(5, 1, 100); + set_author(6, 1, 100); + + roll_blocks(1); + // 1. ensure delegators are paid for 2 rounds after they leave + assert_noop!( + ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(66)), + Error::::DelegatorDNE + ); + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(6))); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 4, + delegator: 6, + scheduled_exit: 6, + }); + // fast forward to block in which delegator 6 exit executes + roll_to_round_begin(5); + assert_events_eq!( + Event::CollatorChosen { round: 5, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 5, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 5, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 5, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 20, + round: 5, + selected_collators_number: 4, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 24 }, + Event::Rewarded { account: 6, rewards: 8 }, + Event::Rewarded { account: 7, rewards: 8 }, + Event::Rewarded { account: 10, rewards: 8 }, + ); + // keep paying 6 (note: inflation is in terms of total issuance so that's why 1 is 21) + roll_to_round_begin(6); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(6), 6, 10)); + assert_events_eq!( + Event::CollatorChosen { round: 6, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 25, + round: 6, + selected_collators_number: 4, + total_balance: 130, + }, + Event::DelegatorLeftCandidate { + delegator: 6, + candidate: 1, + unstaked_amount: 10, + total_candidate_staked: 40, + }, + Event::DelegatorLeft { delegator: 6, unstaked_amount: 10 }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 26 }, + Event::Rewarded { account: 6, rewards: 8 }, + Event::Rewarded { account: 7, rewards: 8 }, + Event::Rewarded { account: 10, rewards: 8 }, + ); + // 6 won't be paid for this round because they left already + set_author(7, 1, 100); + roll_to_round_begin(7); + // keep paying 6 + assert_events_eq!( + Event::CollatorChosen { round: 7, collator_account: 1, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 7, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 7, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 7, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 30, + round: 7, + selected_collators_number: 4, + total_balance: 120, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 31 }, + Event::Rewarded { account: 7, rewards: 10 }, + Event::Rewarded { account: 10, rewards: 10 }, + ); + roll_to_round_begin(8); + assert_events_eq!( + Event::CollatorChosen { round: 8, collator_account: 1, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 8, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 8, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 8, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 35, + round: 8, + selected_collators_number: 4, + total_balance: 120, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 33 }, + Event::Rewarded { account: 7, rewards: 11 }, + Event::Rewarded { account: 10, rewards: 11 }, + ); + set_author(8, 1, 100); + roll_to_round_begin(9); + // no more paying 6 + assert_events_eq!( + Event::CollatorChosen { round: 9, collator_account: 1, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 9, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 9, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 9, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 40, + round: 9, + selected_collators_number: 4, + total_balance: 120, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 34 }, + Event::Rewarded { account: 7, rewards: 11 }, + Event::Rewarded { account: 10, rewards: 11 }, + ); + roll_blocks(1); + set_author(9, 1, 100); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(8), 1, 10, 10, 10)); + assert_events_eq!(Event::Delegation { + delegator: 8, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, + auto_compound: Percent::zero(), + }); + + roll_to_round_begin(10); + // new delegation is not rewarded yet + assert_events_eq!( + Event::CollatorChosen { round: 10, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 10, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 10, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 10, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 45, + round: 10, + selected_collators_number: 4, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 36 }, + Event::Rewarded { account: 7, rewards: 12 }, + Event::Rewarded { account: 10, rewards: 12 }, + ); + set_author(10, 1, 100); + roll_to_round_begin(11); + // new delegation not rewarded yet + assert_events_eq!( + Event::CollatorChosen { round: 11, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 11, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 11, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 11, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 50, + round: 11, + selected_collators_number: 4, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 38 }, + Event::Rewarded { account: 7, rewards: 12 }, + Event::Rewarded { account: 10, rewards: 12 }, + ); + roll_to_round_begin(12); + // new delegation is rewarded for first time + // 2 rounds after joining (`RewardPaymentDelay` = 2) + assert_events_eq!( + Event::CollatorChosen { round: 12, collator_account: 1, total_exposed_amount: 50 }, + Event::CollatorChosen { round: 12, collator_account: 2, total_exposed_amount: 40 }, + Event::CollatorChosen { round: 12, collator_account: 3, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 12, collator_account: 4, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 55, + round: 12, + selected_collators_number: 4, + total_balance: 130, + }, + ); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 34 }, + Event::Rewarded { account: 7, rewards: 11 }, + Event::Rewarded { account: 10, rewards: 11 }, + Event::Rewarded { account: 8, rewards: 11 }, + ); + }); +} + +#[test] +fn bottom_delegations_are_empty_when_top_delegations_not_full() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 10), (3, 10), (4, 10), (5, 10)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // no top delegators => no bottom delegators + let top_delegations = ParachainStaking::top_delegations(1).unwrap(); + let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); + assert!(top_delegations.delegations.is_empty()); + assert!(bottom_delegations.delegations.is_empty()); + // 1 delegator => 1 top delegator, 0 bottom delegators + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 10, 10)); + let top_delegations = ParachainStaking::top_delegations(1).unwrap(); + let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); + assert_eq!(top_delegations.delegations.len(), 1usize); + assert!(bottom_delegations.delegations.is_empty()); + // 2 delegators => 2 top delegators, 0 bottom delegators + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(3), 1, 10, 10, 10)); + let top_delegations = ParachainStaking::top_delegations(1).unwrap(); + let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); + assert_eq!(top_delegations.delegations.len(), 2usize); + assert!(bottom_delegations.delegations.is_empty()); + // 3 delegators => 3 top delegators, 0 bottom delegators + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(4), 1, 10, 10, 10)); + let top_delegations = ParachainStaking::top_delegations(1).unwrap(); + let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); + assert_eq!(top_delegations.delegations.len(), 3usize); + assert!(bottom_delegations.delegations.is_empty()); + // 4 delegators => 4 top delegators, 0 bottom delegators + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(5), 1, 10, 10, 10)); + let top_delegations = ParachainStaking::top_delegations(1).unwrap(); + let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); + assert_eq!(top_delegations.delegations.len(), 4usize); + assert!(bottom_delegations.delegations.is_empty()); + }); +} + +#[test] +fn candidate_pool_updates_when_total_counted_changes() { + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (3, 19), + (4, 20), + (5, 21), + (6, 22), + (7, 15), + (8, 16), + (9, 17), + (10, 18), + ]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (3, 1, 11), + (4, 1, 12), + (5, 1, 13), + (6, 1, 14), + (7, 1, 15), + (8, 1, 16), + (9, 1, 17), + (10, 1, 18), + ]) + .build() + .execute_with(|| { + fn is_candidate_pool_bond(account: u64, bond: u128) { + let pool = ParachainStaking::candidate_pool(); + for candidate in pool.0 { + if candidate.owner == account { + assert_eq!( + candidate.amount, bond, + "Candidate Bond {:?} is Not Equal to Expected: {:?}", + candidate.amount, bond + ); + } + } + } + // 15 + 16 + 17 + 18 + 20 = 86 (top 4 + self bond) + is_candidate_pool_bond(1, 86); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(3), 1, 8)); + // 3: 11 -> 19 => 3 is in top, bumps out 7 + // 16 + 17 + 18 + 19 + 20 = 90 (top 4 + self bond) + is_candidate_pool_bond(1, 90); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(4), 1, 8)); + // 4: 12 -> 20 => 4 is in top, bumps out 8 + // 17 + 18 + 19 + 20 + 20 = 94 (top 4 + self bond) + is_candidate_pool_bond(1, 94); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(10), + 1, + 3 + )); + roll_to(30); + // 10: 18 -> 15 => 10 bumped to bottom, 8 bumped to top (- 18 + 16 = -2 for count) + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(10), + 10, + 1 + )); + // 16 + 17 + 19 + 20 + 20 = 92 (top 4 + self bond) + is_candidate_pool_bond(1, 92); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(9), + 1, + 4 + )); + roll_to(40); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(9), + 9, + 1 + )); + // 15 + 16 + 19 + 20 + 20 = 90 (top 4 + self bond) + is_candidate_pool_bond(1, 90); + }); +} + +#[test] +fn only_top_collators_are_counted() { + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (3, 19), + (4, 20), + (5, 21), + (6, 22), + (7, 15), + (8, 16), + (9, 17), + (10, 18), + ]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (3, 1, 11), + (4, 1, 12), + (5, 1, 13), + (6, 1, 14), + (7, 1, 15), + (8, 1, 16), + (9, 1, 17), + (10, 1, 18), + ]) + .build() + .execute_with(|| { + // sanity check that 3-10 are delegators immediately + for i in 3..11 { + assert!(ParachainStaking::is_delegator(&i)); + } + let collator_state = ParachainStaking::candidate_info(1).unwrap(); + // 15 + 16 + 17 + 18 + 20 = 86 (top 4 + self bond) + assert_eq!(collator_state.total_counted, 86); + // bump bottom to the top + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(3), 1, 8)); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 3, + candidate: 1, + amount: 8, + in_top: true, + }); + let collator_state = ParachainStaking::candidate_info(1).unwrap(); + // 16 + 17 + 18 + 19 + 20 = 90 (top 4 + self bond) + assert_eq!(collator_state.total_counted, 90); + // bump bottom to the top + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(4), 1, 8)); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 4, + candidate: 1, + amount: 8, + in_top: true, + }); + let collator_state = ParachainStaking::candidate_info(1).unwrap(); + // 17 + 18 + 19 + 20 + 20 = 94 (top 4 + self bond) + assert_eq!(collator_state.total_counted, 94); + // bump bottom to the top + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(5), 1, 8)); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 5, + candidate: 1, + amount: 8, + in_top: true, + }); + let collator_state = ParachainStaking::candidate_info(1).unwrap(); + // 18 + 19 + 20 + 21 + 20 = 98 (top 4 + self bond) + assert_eq!(collator_state.total_counted, 98); + // bump bottom to the top + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(6), 1, 8)); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 6, + candidate: 1, + amount: 8, + in_top: true, + }); + let collator_state = ParachainStaking::candidate_info(1).unwrap(); + // 19 + 20 + 21 + 22 + 20 = 102 (top 4 + self bond) + assert_eq!(collator_state.total_counted, 102); + }); +} + +#[test] +fn delegation_events_convey_correct_position() { + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + ]) + .with_candidates(vec![(1, 20), (2, 20)]) + .with_delegations(vec![(3, 1, 11), (4, 1, 12), (5, 1, 13), (6, 1, 14)]) + .build() + .execute_with(|| { + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 11 + 12 + 13 + 14 + 20 = 70 (top 4 + self bond) + assert_eq!(collator1_state.total_counted, 70); + // Top delegations are full, new highest delegation is made + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(7), 1, 15, 10, 10)); + assert_events_emitted!(Event::Delegation { + delegator: 7, + locked_amount: 15, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 74 }, + auto_compound: Percent::zero(), + }); + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 12 + 13 + 14 + 15 + 20 = 70 (top 4 + self bond) + assert_eq!(collator1_state.total_counted, 74); + // New delegation is added to the bottom + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(8), 1, 10, 10, 10)); + assert_events_emitted!(Event::Delegation { + delegator: 8, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToBottom, + auto_compound: Percent::zero(), + }); + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 12 + 13 + 14 + 15 + 20 = 70 (top 4 + self bond) + assert_eq!(collator1_state.total_counted, 74); + // 8 increases delegation to the top + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(8), 1, 3)); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 8, + candidate: 1, + amount: 3, + in_top: true, + }); + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 13 + 13 + 14 + 15 + 20 = 75 (top 4 + self bond) + assert_eq!(collator1_state.total_counted, 75); + // 3 increases delegation but stays in bottom + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(3), 1, 1)); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 3, + candidate: 1, + amount: 1, + in_top: false, + }); + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 13 + 13 + 14 + 15 + 20 = 75 (top 4 + self bond) + assert_eq!(collator1_state.total_counted, 75); + // 6 decreases delegation but stays in top + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(6), + 1, + 2 + )); + assert_events_emitted!(Event::DelegationDecreaseScheduled { + delegator: 6, + candidate: 1, + amount_to_decrease: 2, + execute_round: 3, + }); + roll_to(30); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(6), + 6, + 1 + )); + assert_events_emitted!(Event::DelegationDecreased { + delegator: 6, + candidate: 1, + amount: 2, + in_top: true, + }); + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 12 + 13 + 13 + 15 + 20 = 73 (top 4 + self bond)ƒ + assert_eq!(collator1_state.total_counted, 73); + // 6 decreases delegation and is bumped to bottom + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(6), + 1, + 1 + )); + assert_events_emitted!(Event::DelegationDecreaseScheduled { + delegator: 6, + candidate: 1, + amount_to_decrease: 1, + execute_round: 9, + }); + roll_to(40); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(6), + 6, + 1 + )); + assert_events_emitted!(Event::DelegationDecreased { + delegator: 6, + candidate: 1, + amount: 1, + in_top: false, + }); + let collator1_state = ParachainStaking::candidate_info(1).unwrap(); + // 12 + 13 + 13 + 15 + 20 = 73 (top 4 + self bond) + assert_eq!(collator1_state.total_counted, 73); + }); +} + +#[test] +fn no_rewards_paid_until_after_reward_payment_delay() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20)]) + .build() + .execute_with(|| { + roll_to_round_begin(2); + // payouts for round 1 + set_author(1, 1, 1); + set_author(1, 2, 1); + set_author(1, 2, 1); + set_author(1, 3, 1); + set_author(1, 3, 1); + assert_events_eq!( + Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 3, + total_balance: 60, + }, + ); + + roll_to_round_begin(3); + assert_events_eq!( + Event::CollatorChosen { round: 3, collator_account: 1, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 3, collator_account: 2, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 3, collator_account: 3, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 10, + round: 3, + selected_collators_number: 3, + total_balance: 60, + }, + ); + + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 3, rewards: 1 }); + + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 1 }); + + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 2, rewards: 1 }); + + // there should be no more payments in this round... + let num_blocks_rolled = roll_to_round_end(3); + assert_no_events!(); + assert_eq!(num_blocks_rolled, 1); + }); +} + +#[test] +fn deferred_payment_storage_items_are_cleaned_up() { + use crate::*; + + // this test sets up two collators, gives them points in round one, and focuses on the + // storage over the next several blocks to show that it is properly cleaned up + + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20)]) + .with_candidates(vec![(1, 20), (2, 20)]) + .build() + .execute_with(|| { + set_author(1, 1, 1); + set_author(1, 2, 1); + + // reflects genesis? + assert!(>::contains_key(1, 1)); + assert!(>::contains_key(1, 2)); + + roll_to_round_begin(2); + assert_events_eq!( + Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 2, + total_balance: 40, + }, + ); + + // we should have AtStake snapshots as soon as we start a round... + assert!(>::contains_key(2, 1)); + assert!(>::contains_key(2, 2)); + // ...and it should persist until the round is fully paid out + assert!(>::contains_key(1, 1)); + assert!(>::contains_key(1, 2)); + + assert!( + !>::contains_key(1), + "DelayedPayouts shouldn't be populated until after RewardPaymentDelay" + ); + assert!( + >::contains_key(1), + "Points should be populated during current round" + ); + assert!( + >::contains_key(1), + "Staked should be populated when round changes" + ); + + assert!( + !>::contains_key(2), + "Points should not be populated until author noted" + ); + assert!( + >::contains_key(2), + "Staked should be populated when round changes" + ); + + // first payout occurs in round 3 + roll_to_round_begin(3); + assert_events_eq!( + Event::CollatorChosen { round: 3, collator_account: 1, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 3, collator_account: 2, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 10, + round: 3, + selected_collators_number: 2, + total_balance: 40, + }, + ); + + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 1 },); + + // payouts should exist for past rounds that haven't been paid out yet.. + assert!(>::contains_key(3, 1)); + assert!(>::contains_key(3, 2)); + assert!(>::contains_key(2, 1)); + assert!(>::contains_key(2, 2)); + + assert!( + >::contains_key(1), + "DelayedPayouts should be populated after RewardPaymentDelay" + ); + assert!(>::contains_key(1)); + assert!( + !>::contains_key(1), + "Staked should be cleaned up after round change" + ); + + assert!(!>::contains_key(2)); + assert!(!>::contains_key(2), "We never rewarded points for round 2"); + assert!(>::contains_key(2)); + + assert!(!>::contains_key(3)); + assert!(!>::contains_key(3), "We never awarded points for round 3"); + assert!(>::contains_key(3)); + + // collator 1 has been paid in this last block and associated storage cleaned up + assert!(!>::contains_key(1, 1)); + assert!(!>::contains_key(1, 1)); + + // but collator 2 hasn't been paid + assert!(>::contains_key(1, 2)); + assert!(>::contains_key(1, 2)); + + // second payout occurs in next block + roll_blocks(1); + assert_events_eq!(Event::Rewarded { account: 2, rewards: 1 },); + + roll_to_round_begin(4); + assert_events_eq!( + Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 20 }, + Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 20 }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 2, + total_balance: 40, + }, + ); + + // collators have both been paid and storage fully cleaned up for round 1 + assert!(!>::contains_key(1, 2)); + assert!(!>::contains_key(1, 2)); + assert!(!>::contains_key(1)); + assert!(!>::contains_key(1)); // points should be cleaned up + assert!(!>::contains_key(1)); + + roll_to_round_end(4); + + // no more events expected + assert_no_events!(); + }); +} + +#[test] +fn deferred_payment_and_at_stake_storage_items_cleaned_up_for_candidates_not_producing_blocks() { + use crate::*; + + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 20), (2, 20), (3, 20)]) + .build() + .execute_with(|| { + // candidate 3 will not produce blocks + set_author(1, 1, 1); + set_author(1, 2, 1); + + // reflects genesis? + assert!(>::contains_key(1, 1)); + assert!(>::contains_key(1, 2)); + + roll_to_round_begin(2); + assert!(>::contains_key(1, 1)); + assert!(>::contains_key(1, 2)); + assert!(>::contains_key(1, 3)); + assert!(>::contains_key(1, 1)); + assert!(>::contains_key(1, 2)); + assert!(!>::contains_key(1, 3)); + assert!(>::contains_key(1)); + assert!(>::contains_key(1)); + roll_to_round_begin(3); + assert!(>::contains_key(1)); + + // all storage items must be cleaned up + roll_to_round_begin(4); + assert!(!>::contains_key(1, 1)); + assert!(!>::contains_key(1, 2)); + assert!(!>::contains_key(1, 3)); + assert!(!>::contains_key(1, 1)); + assert!(!>::contains_key(1, 2)); + assert!(!>::contains_key(1, 3)); + assert!(!>::contains_key(1)); + assert!(!>::contains_key(1)); + assert!(!>::contains_key(1)); + }); +} + +#[test] +fn deferred_payment_steady_state_event_flow() { + use frame_support::traits::{Currency, ExistenceRequirement, WithdrawReasons}; + + // this test "flows" through a number of rounds, asserting that certain things do/don't happen + // once the staking pallet is in a "steady state" (specifically, once we are past the first few + // rounds to clear RewardPaymentDelay) + + ExtBuilder::default() + .with_balances(vec![ + // collators + (1, 200), + (2, 200), + (3, 200), + (4, 200), + // delegators + (11, 200), + (22, 200), + (33, 200), + (44, 200), + // burn account, see `reset_issuance()` + (111, 1000), + ]) + .with_candidates(vec![(1, 200), (2, 200), (3, 200), (4, 200)]) + .with_delegations(vec![ + // delegator 11 delegates 100 to 1 and 2 + (11, 1, 100), + (11, 2, 100), + // delegator 22 delegates 100 to 2 and 3 + (22, 2, 100), + (22, 3, 100), + // delegator 33 delegates 100 to 3 and 4 + (33, 3, 100), + (33, 4, 100), + // delegator 44 delegates 100 to 4 and 1 + (44, 4, 100), + (44, 1, 100), + ]) + .build() + .execute_with(|| { + // convenience to set the round points consistently + let set_round_points = |round: BlockNumber| { + set_author(round as BlockNumber, 1, 1); + set_author(round as BlockNumber, 2, 1); + set_author(round as BlockNumber, 3, 1); + set_author(round as BlockNumber, 4, 1); + }; + + // grab initial issuance -- we will reset it before round issuance is calculated so that + // it is consistent every round + let initial_issuance = Balances::total_issuance(); + let reset_issuance = || { + let new_issuance = Balances::total_issuance(); + let diff = new_issuance - initial_issuance; + let burned = Balances::burn(diff); + Balances::settle( + &111, + burned, + WithdrawReasons::FEE, + ExistenceRequirement::AllowDeath, + ) + .expect("Account can absorb burn"); + }; + + // fn to roll through the first RewardPaymentDelay rounds. returns new round index + let roll_through_initial_rounds = |mut round: BlockNumber| -> BlockNumber { + while round < crate::mock::RewardPaymentDelay::get() + 1 { + set_round_points(round); + + roll_to_round_end(round); + round += 1; + } + + reset_issuance(); + + round + }; + + // roll through a "steady state" round and make all of our assertions + // returns new round index + let roll_through_steady_state_round = |round: BlockNumber| -> BlockNumber { + let num_rounds_rolled = roll_to_round_begin(round); + assert!(num_rounds_rolled <= 1, "expected to be at round begin already"); + + assert_events_eq!( + Event::CollatorChosen { + round: round as u32, + collator_account: 1, + total_exposed_amount: 400, + }, + Event::CollatorChosen { + round: round as u32, + collator_account: 2, + total_exposed_amount: 400, + }, + Event::CollatorChosen { + round: round as u32, + collator_account: 3, + total_exposed_amount: 400, + }, + Event::CollatorChosen { + round: round as u32, + collator_account: 4, + total_exposed_amount: 400, + }, + Event::NewRound { + starting_block: (round - 1) * 5, + round: round as u32, + selected_collators_number: 4, + total_balance: 1600, + }, + ); + + set_round_points(round); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { account: 3, rewards: 19 }, + Event::Rewarded { account: 22, rewards: 6 }, + Event::Rewarded { account: 33, rewards: 6 }, + ); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { account: 4, rewards: 19 }, + Event::Rewarded { account: 33, rewards: 6 }, + Event::Rewarded { account: 44, rewards: 6 }, + ); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 19 }, + Event::Rewarded { account: 11, rewards: 6 }, + Event::Rewarded { account: 44, rewards: 6 }, + ); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { account: 2, rewards: 19 }, + Event::Rewarded { account: 11, rewards: 6 }, + Event::Rewarded { account: 22, rewards: 6 }, + ); + + roll_blocks(1); + // Since we defer first deferred staking payout, this test have the maximum amout of + // supported collators. This eman that the next round is trigerred one block after + // the last reward. + //assert_no_events!(); + + let num_rounds_rolled = roll_to_round_end(round); + assert_eq!(num_rounds_rolled, 0, "expected to be at round end already"); + + reset_issuance(); + + round + 1 + }; + + let mut round = 1; + round = roll_through_initial_rounds(round); // we should be at RewardPaymentDelay + for _ in 1..2 { + round = roll_through_steady_state_round(round); + } + }); +} + +#[test] +fn delegation_kicked_from_bottom_removes_pending_request() { + ExtBuilder::default() + .with_balances(vec![ + (1, 30), + (2, 29), + (3, 20), + (4, 20), + (5, 20), + (6, 20), + (7, 20), + (8, 20), + (9, 20), + (10, 20), + (11, 30), + ]) + .with_candidates(vec![(1, 30), (11, 30)]) + .with_delegations(vec![ + (2, 1, 19), + (2, 11, 10), // second delegation so not left after first is kicked + (3, 1, 20), + (4, 1, 20), + (5, 1, 20), + (6, 1, 20), + (7, 1, 20), + (8, 1, 20), + (9, 1, 20), + ]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + // 10 delegates to full 1 => kicks lowest delegation (2, 19) + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(10), 1, 20, 8, 0)); + // check the event + assert_events_emitted!(Event::DelegationKicked { + delegator: 2, + candidate: 1, + unstaked_amount: 19, + }); + // ensure request DNE + assert!(!ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2)); + }); +} + +#[test] +fn no_selected_candidates_defaults_to_last_round_collators() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 30), (3, 30), (4, 30), (5, 30)]) + .with_candidates(vec![(1, 30), (2, 30), (3, 30), (4, 30), (5, 30)]) + .build() + .execute_with(|| { + roll_to_round_begin(1); + // schedule to leave + for i in 1..6 { + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(i), + 5 + )); + } + let old_round = ParachainStaking::round().current; + let old_selected_candidates = ParachainStaking::selected_candidates(); + let mut old_at_stake_snapshots = Vec::new(); + for account in old_selected_candidates.clone() { + old_at_stake_snapshots.push(>::get(old_round, account)); + } + roll_to_round_begin(3); + // execute leave + for i in 1..6 { + assert_ok!(ParachainStaking::execute_leave_candidates( + RuntimeOrigin::signed(i), + i, + 0, + )); + } + // next round + roll_to_round_begin(4); + let new_round = ParachainStaking::round().current; + // check AtStake matches previous + let new_selected_candidates = ParachainStaking::selected_candidates(); + assert_eq!(old_selected_candidates, new_selected_candidates); + let mut index = 0usize; + for account in new_selected_candidates { + assert_eq!(old_at_stake_snapshots[index], >::get(new_round, account)); + index += 1usize; + } + }); +} + +#[test] +fn test_delegator_scheduled_for_revoke_is_rewarded_for_previous_rounds_but_not_for_future() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + // preset rewards for rounds 1, 2 and 3 + (1..=3).for_each(|round| set_author(round, 1, 1)); + + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_events_eq!(Event::DelegationRevocationScheduled { + round: 1, + delegator: 2, + candidate: 1, + scheduled_exit: 3, + }); + let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); + assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); + + roll_to_round_begin(3); + assert_events_emitted_match!(Event::NewRound { round: 3, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 4 }, + Event::Rewarded { account: 2, rewards: 1 }, + ); + + roll_to_round_begin(4); + assert_events_emitted_match!(Event::NewRound { round: 4, .. }); + roll_blocks(3); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_eq!( + 1, + collator_snapshot.delegations.len(), + "collator snapshot's delegator count was reduced unexpectedly" + ); + assert_eq!( + 20, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); + }); +} + +#[test] +fn test_delegator_scheduled_for_revoke_is_rewarded_when_request_cancelled() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + // preset rewards for rounds 2, 3 and 4 + (2..=4).for_each(|round| set_author(round, 1, 1)); + + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_events_eq!(Event::DelegationRevocationScheduled { + round: 1, + delegator: 2, + candidate: 1, + scheduled_exit: 3, + }); + let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); + assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); + + roll_to_round_begin(2); + assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); + + roll_to_round_begin(4); + assert_events_emitted_match!(Event::NewRound { round: 4, .. }); + roll_blocks(3); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_eq!( + 1, + collator_snapshot.delegations.len(), + "collator snapshot's delegator count was reduced unexpectedly" + ); + assert_eq!( + 30, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); + + roll_to_round_begin(5); + assert_events_emitted_match!(Event::NewRound { round: 5, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 4 }, + Event::Rewarded { account: 2, rewards: 1 }, + ); + }); +} + +#[test] +fn test_delegator_scheduled_for_bond_decrease_is_rewarded_for_previous_rounds_but_less_for_future() +{ + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 20), (2, 3, 10)]) + .build() + .execute_with(|| { + // preset rewards for rounds 1, 2 and 3 + (1..=3).for_each(|round| set_author(round, 1, 1)); + + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 10, + )); + assert_events_eq!(Event::DelegationDecreaseScheduled { + execute_round: 3, + delegator: 2, + candidate: 1, + amount_to_decrease: 10, + }); + let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); + assert_eq!(40, collator.total_counted, "collator's total was reduced unexpectedly"); + + roll_to_round_begin(3); + assert_events_emitted_match!(Event::NewRound { round: 3, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 3 }, + Event::Rewarded { account: 2, rewards: 2 }, + ); + + roll_to_round_begin(4); + assert_events_emitted_match!(Event::NewRound { round: 4, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 4 }, + Event::Rewarded { account: 2, rewards: 1 }, + ); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_eq!( + 1, + collator_snapshot.delegations.len(), + "collator snapshot's delegator count was reduced unexpectedly" + ); + assert_eq!( + 30, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); + }); +} + +#[test] +fn test_delegator_scheduled_for_bond_decrease_is_rewarded_when_request_cancelled() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 20), (2, 3, 10)]) + .build() + .execute_with(|| { + // preset rewards for rounds 2, 3 and 4 + (2..=4).for_each(|round| set_author(round, 1, 1)); + + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 10, + )); + assert_events_eq!(Event::DelegationDecreaseScheduled { + execute_round: 3, + delegator: 2, + candidate: 1, + amount_to_decrease: 10, + }); + let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); + assert_eq!(40, collator.total_counted, "collator's total was reduced unexpectedly"); + + roll_to_round_begin(2); + assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); + + roll_to_round_begin(4); + assert_events_emitted_match!(Event::NewRound { round: 4, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 4 }, + Event::Rewarded { account: 2, rewards: 1 }, + ); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_eq!( + 1, + collator_snapshot.delegations.len(), + "collator snapshot's delegator count was reduced unexpectedly" + ); + assert_eq!( + 40, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); + + roll_to_round_begin(5); + assert_events_emitted_match!(Event::NewRound { round: 5, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 3 }, + Event::Rewarded { account: 2, rewards: 2 }, + ); + }); +} + +#[test] +fn test_delegator_scheduled_for_leave_is_rewarded_for_previous_rounds_but_not_for_future() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + // preset rewards for rounds 1, 2 and 3 + (1..=3).for_each(|round| set_author(round, 1, 1)); + + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2),)); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 1, + delegator: 2, + scheduled_exit: 3, + }); + let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); + assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); + + roll_to_round_begin(3); + assert_events_emitted_match!(Event::NewRound { round: 3, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 4 }, + Event::Rewarded { account: 2, rewards: 1 }, + ); + + roll_to_round_begin(4); + assert_events_emitted_match!(Event::NewRound { round: 4, .. }); + roll_blocks(3); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_eq!( + 1, + collator_snapshot.delegations.len(), + "collator snapshot's delegator count was reduced unexpectedly" + ); + assert_eq!( + 20, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); + }); +} + +#[test] +fn test_delegator_scheduled_for_leave_is_rewarded_when_request_cancelled() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + // preset rewards for rounds 2, 3 and 4 + (2..=4).for_each(|round| set_author(round, 1, 1)); + + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 1, + delegator: 2, + scheduled_exit: 3, + }); + let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); + assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); + + roll_to_round_begin(2); + assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); + + roll_to_round_begin(4); + assert_events_emitted_match!(Event::NewRound { round: 4, .. }); + roll_blocks(3); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_eq!( + 1, + collator_snapshot.delegations.len(), + "collator snapshot's delegator count was reduced unexpectedly" + ); + assert_eq!( + 30, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); + + roll_to_round_begin(5); + assert_events_emitted_match!(Event::NewRound { round: 5, .. }); + roll_blocks(3); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 4 }, + Event::Rewarded { account: 2, rewards: 1 }, + ); + }); +} + +#[test] +fn test_delegation_request_exists_returns_false_when_nothing_exists() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert!(!ParachainStaking::delegation_request_exists(&1, &2)); + }); +} + +#[test] +fn test_delegation_request_exists_returns_true_when_decrease_exists() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::insert( + 1, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], + ); + assert!(ParachainStaking::delegation_request_exists(&1, &2)); + }); +} + +#[test] +fn test_delegation_request_exists_returns_true_when_revoke_exists() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::insert( + 1, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Revoke(5), + }], + ); + assert!(ParachainStaking::delegation_request_exists(&1, &2)); + }); +} + +#[test] +fn test_delegation_request_revoke_exists_returns_false_when_nothing_exists() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert!(!ParachainStaking::delegation_request_revoke_exists(&1, &2)); + }); +} + +#[test] +fn test_delegation_request_revoke_exists_returns_false_when_decrease_exists() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::insert( + 1, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], + ); + assert!(!ParachainStaking::delegation_request_revoke_exists(&1, &2)); + }); +} + +#[test] +fn test_delegation_request_revoke_exists_returns_true_when_revoke_exists() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::insert( + 1, + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Revoke(5), + }], + ); + assert!(ParachainStaking::delegation_request_revoke_exists(&1, &2)); + }); +} + +#[test] +fn test_hotfix_remove_delegation_requests_exited_candidates_cleans_up() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // invalid state + >::insert( + 2, + Vec::>::new(), + ); + >::insert( + 3, + Vec::>::new(), + ); + assert_ok!(ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( + RuntimeOrigin::signed(1), + vec![2, 3, 4] // 4 does not exist, but is OK for idempotency + )); + + assert!(!>::contains_key(2)); + assert!(!>::contains_key(3)); + }); +} + +#[test] +fn test_hotfix_remove_delegation_requests_exited_candidates_cleans_up_only_specified_keys() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // invalid state + >::insert( + 2, + Vec::>::new(), + ); + >::insert( + 3, + Vec::>::new(), + ); + assert_ok!(ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( + RuntimeOrigin::signed(1), + vec![2] + )); + + assert!(!>::contains_key(2)); + assert!(>::contains_key(3)); + }); +} + +#[test] +fn test_hotfix_remove_delegation_requests_exited_candidates_errors_when_requests_not_empty() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // invalid state + >::insert( + 2, + Vec::>::new(), + ); + >::insert( + 3, + vec![ScheduledRequest { + delegator: 10, + when_executable: 1, + action: DelegationAction::Revoke(10), + }], + ); + + assert_noop!( + ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( + RuntimeOrigin::signed(1), + vec![2, 3] + ), + >::CandidateNotLeaving, + ); + }); +} + +#[test] +fn test_hotfix_remove_delegation_requests_exited_candidates_errors_when_candidate_not_exited() { + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // invalid state + >::insert( + 1, + Vec::>::new(), + ); + assert_noop!( + ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( + RuntimeOrigin::signed(1), + vec![1] + ), + >::CandidateNotLeaving, + ); + }); +} + +#[test] +fn locking_zero_amount_is_ignored() { + use frame_support::traits::{LockableCurrency, WithdrawReasons}; + + // this test demonstrates the behavior of pallet Balance's `LockableCurrency` implementation of + // `set_locks()` when an amount of 0 is provided: it is a no-op + + ExtBuilder::default().with_balances(vec![(1, 100)]).build().execute_with(|| { + assert_eq!(crate::mock::query_lock_amount(1, DELEGATOR_LOCK_ID), None); + + Balances::set_lock(DELEGATOR_LOCK_ID, &1, 1, WithdrawReasons::all()); + assert_eq!(crate::mock::query_lock_amount(1, DELEGATOR_LOCK_ID), Some(1)); + + Balances::set_lock(DELEGATOR_LOCK_ID, &1, 0, WithdrawReasons::all()); + // Note that we tried to call `set_lock(0)` and it ignored it, we still have our lock + assert_eq!(crate::mock::query_lock_amount(1, DELEGATOR_LOCK_ID), Some(1)); + }); +} + +#[test] +fn revoke_last_removes_lock() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100), (3, 100)]) + .with_candidates(vec![(1, 25), (2, 25)]) + .with_delegations(vec![(3, 1, 30), (3, 2, 25)]) + .build() + .execute_with(|| { + assert_eq!(crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), Some(55)); + + // schedule and remove one... + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(3), 1)); + roll_to_round_begin(3); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(3), + 3, + 1 + )); + assert_eq!(crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), Some(25)); + + // schedule and remove the other... + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(3), 2)); + roll_to_round_begin(5); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(3), + 3, + 2 + )); + assert_eq!(crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), None); + }); +} + +#[allow(deprecated)] +#[test] +fn test_delegator_with_deprecated_status_leaving_can_schedule_leave_delegators_as_fix() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::mutate(2, |value| { + value.as_mut().map(|mut state| { + state.status = DelegatorStatus::Leaving(2); + }) + }); + let state = >::get(2); + assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); + + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert!(>::get(1) + .iter() + .any(|r| r.delegator == 2 && matches!(r.action, DelegationAction::Revoke(_)))); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 1, + delegator: 2, + scheduled_exit: 3 + }); + + let state = >::get(2); + assert!(matches!(state.unwrap().status, DelegatorStatus::Active)); + }); +} + +#[allow(deprecated)] +#[test] +fn test_delegator_with_deprecated_status_leaving_can_cancel_leave_delegators_as_fix() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::mutate(2, |value| { + value.as_mut().map(|mut state| { + state.status = DelegatorStatus::Leaving(2); + }) + }); + let state = >::get(2); + assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); + + assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); + assert_events_eq!(Event::DelegatorExitCancelled { delegator: 2 }); + + let state = >::get(2); + assert!(matches!(state.unwrap().status, DelegatorStatus::Active)); + }); +} + +#[allow(deprecated)] +#[test] +fn test_delegator_with_deprecated_status_leaving_can_execute_leave_delegators_as_fix() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::mutate(2, |value| { + value.as_mut().map(|mut state| { + state.status = DelegatorStatus::Leaving(2); + }) + }); + let state = >::get(2); + assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); + + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); + assert_events_emitted!(Event::DelegatorLeft { delegator: 2, unstaked_amount: 10 }); + + let state = >::get(2); + assert!(state.is_none()); + }); +} + +#[allow(deprecated)] +#[test] +fn test_delegator_with_deprecated_status_leaving_cannot_execute_leave_delegators_early_no_fix() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 40)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::mutate(2, |value| { + value.as_mut().map(|mut state| { + state.status = DelegatorStatus::Leaving(2); + }) + }); + let state = >::get(2); + assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); + + assert_noop!( + ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1), + Error::::DelegatorCannotLeaveYet + ); + }); +} + +#[test] +fn test_set_auto_compound_fails_if_invalid_delegation_hint() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + let candidate_auto_compounding_delegation_count_hint = 0; + let delegation_hint = 0; // is however, 1 + + assert_noop!( + ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + candidate_auto_compounding_delegation_count_hint, + delegation_hint, + ), + >::TooLowDelegationCountToAutoCompound, + ); + }); +} + +#[test] +fn test_set_auto_compound_fails_if_invalid_candidate_auto_compounding_hint() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::new( + vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(10) }] + .try_into() + .expect("must succeed"), + ) + .set_storage(&1); + let candidate_auto_compounding_delegation_count_hint = 0; // is however, 1 + let delegation_hint = 1; + + assert_noop!( + ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + candidate_auto_compounding_delegation_count_hint, + delegation_hint, + ), + >::TooLowCandidateAutoCompoundingDelegationCountToAutoCompound, + ); + }); +} + +#[test] +fn test_set_auto_compound_inserts_if_not_exists() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 1, + )); + assert_events_emitted!(Event::AutoCompoundSet { + candidate: 1, + delegator: 2, + value: Percent::from_percent(50), + }); + assert_eq!( + vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(50) }], + ParachainStaking::auto_compounding_delegations(&1).into_inner(), + ); + }); +} + +#[test] +fn test_set_auto_compound_updates_if_existing() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::new( + vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(10) }] + .try_into() + .expect("must succeed"), + ) + .set_storage(&1); + + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 1, + 1, + )); + assert_events_emitted!(Event::AutoCompoundSet { + candidate: 1, + delegator: 2, + value: Percent::from_percent(50), + }); + assert_eq!( + vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(50) }], + ParachainStaking::auto_compounding_delegations(&1).into_inner(), + ); + }); +} + +#[test] +fn test_set_auto_compound_removes_if_auto_compound_zero_percent() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + >::new( + vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(10) }] + .try_into() + .expect("must succeed"), + ) + .set_storage(&1); + + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::zero(), + 1, + 1, + )); + assert_events_emitted!(Event::AutoCompoundSet { + candidate: 1, + delegator: 2, + value: Percent::zero(), + }); + assert_eq!(0, ParachainStaking::auto_compounding_delegations(&1).len(),); + }); +} + +#[test] +fn test_execute_revoke_delegation_removes_auto_compounding_from_state_for_delegation_revoke() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 30), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 2, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 3, + Percent::from_percent(50), + 0, + 2, + )); + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!( + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + assert!( + ParachainStaking::auto_compounding_delegations(&3) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was erroneously removed" + ); + }); +} + +#[test] +fn test_execute_leave_delegators_removes_auto_compounding_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 2, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 3, + Percent::from_percent(50), + 0, + 2, + )); + + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2,)); + + assert!( + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + assert!( + !ParachainStaking::auto_compounding_delegations(&3) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + }); +} + +#[allow(deprecated)] +#[test] +fn test_execute_leave_delegators_with_deprecated_status_leaving_removes_auto_compounding_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 2, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 3, + Percent::from_percent(50), + 0, + 2, + )); + + >::mutate(2, |value| { + value.as_mut().map(|mut state| { + state.status = DelegatorStatus::Leaving(2); + }) + }); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2,)); + + assert!( + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + assert!( + !ParachainStaking::auto_compounding_delegations(&3) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + }); +} + +#[test] +fn test_execute_leave_candidates_removes_auto_compounding_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 30), (3, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 2, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 3, + Percent::from_percent(50), + 0, + 2, + )); + + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 2)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 1,)); + + assert!( + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + assert!( + ParachainStaking::auto_compounding_delegations(&3) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was erroneously removed" + ); + }); +} + +#[test] +fn test_delegation_kicked_from_bottom_delegation_removes_auto_compounding_state() { + ExtBuilder::default() + .with_balances(vec![ + (1, 30), + (2, 29), + (3, 20), + (4, 20), + (5, 20), + (6, 20), + (7, 20), + (8, 20), + (9, 20), + (10, 20), + (11, 30), + ]) + .with_candidates(vec![(1, 30), (11, 30)]) + .with_delegations(vec![ + (2, 11, 10), // extra delegation to avoid leaving the delegator set + (2, 1, 19), + (3, 1, 20), + (4, 1, 20), + (5, 1, 20), + (6, 1, 20), + (7, 1, 20), + (8, 1, 20), + (9, 1, 20), + ]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 2, + )); + + // kicks lowest delegation (2, 19) + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(10), 1, 20, 8, 0)); + + assert!( + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), + "delegation auto-compound config was not removed" + ); + }); +} + +#[test] +fn test_rewards_do_not_auto_compound_on_payment_if_delegation_scheduled_revoke_exists() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 200), (3, 200)]) + .with_candidates(vec![(1, 100)]) + .with_delegations(vec![(2, 1, 200), (3, 1, 200)]) + .build() + .execute_with(|| { + (2..=5).for_each(|round| set_author(round, 1, 1)); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(50), + 0, + 1, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(3), + 1, + Percent::from_percent(50), + 1, + 1, + )); + roll_to_round_begin(3); + + // schedule revoke for delegator 2; no rewards should be compounded + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + roll_to_round_begin(4); + + assert_events_eq!( + Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 500 }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 1, + total_balance: 500, + }, + ); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 9 }, + // no compound since revoke request exists + Event::Rewarded { account: 2, rewards: 8 }, + // 50% + Event::Rewarded { account: 3, rewards: 8 }, + Event::Compounded { candidate: 1, delegator: 3, amount: 4 }, + ); + }); +} + +#[test] +fn test_rewards_auto_compound_on_payment_as_per_auto_compound_config() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 200), (3, 200), (4, 200), (5, 200)]) + .with_candidates(vec![(1, 100)]) + .with_delegations(vec![(2, 1, 200), (3, 1, 200), (4, 1, 200), (5, 1, 200)]) + .build() + .execute_with(|| { + (2..=6).for_each(|round| set_author(round, 1, 1)); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::from_percent(0), + 0, + 1, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(3), + 1, + Percent::from_percent(50), + 1, + 1, + )); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(4), + 1, + Percent::from_percent(100), + 2, + 1, + )); + roll_to_round_begin(4); + + assert_events_eq!( + Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 900 }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 1, + total_balance: 900, + }, + ); + + roll_blocks(1); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 13 }, + // 0% + Event::Rewarded { account: 2, rewards: 8 }, + // 50% + Event::Rewarded { account: 3, rewards: 8 }, + Event::Compounded { candidate: 1, delegator: 3, amount: 4 }, + // 100% + Event::Rewarded { account: 4, rewards: 8 }, + Event::Compounded { candidate: 1, delegator: 4, amount: 8 }, + // no-config + Event::Rewarded { account: 5, rewards: 8 }, + ); + }); +} + +#[test] +fn test_delegate_with_auto_compound_fails_if_invalid_delegation_hint() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25), (3, 30)]) + .with_candidates(vec![(1, 30), (3, 30)]) + .with_delegations(vec![(2, 3, 10)]) + .build() + .execute_with(|| { + let candidate_delegation_count_hint = 0; + let candidate_auto_compounding_delegation_count_hint = 0; + let delegation_hint = 0; // is however, 1 + + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + candidate_delegation_count_hint, + candidate_auto_compounding_delegation_count_hint, + delegation_hint, + ), + >::TooLowDelegationCountToDelegate, + ); + }); +} + +#[test] +fn test_delegate_with_auto_compound_fails_if_invalid_candidate_delegation_count_hint() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25), (3, 30)]) + .with_candidates(vec![(1, 30)]) + .with_delegations(vec![(3, 1, 10)]) + .build() + .execute_with(|| { + let candidate_delegation_count_hint = 0; // is however, 1 + let candidate_auto_compounding_delegation_count_hint = 0; + let delegation_hint = 0; + + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + candidate_delegation_count_hint, + candidate_auto_compounding_delegation_count_hint, + delegation_hint, + ), + >::TooLowCandidateDelegationCountToDelegate, + ); + }); +} + +#[test] +fn test_delegate_with_auto_compound_fails_if_invalid_candidate_auto_compounding_delegations_hint() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25), (3, 30)]) + .with_candidates(vec![(1, 30)]) + .with_auto_compounding_delegations(vec![(3, 1, 10, Percent::from_percent(10))]) + .build() + .execute_with(|| { + let candidate_delegation_count_hint = 1; + let candidate_auto_compounding_delegation_count_hint = 0; // is however, 1 + let delegation_hint = 0; + + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + candidate_delegation_count_hint, + candidate_auto_compounding_delegation_count_hint, + delegation_hint, + ), + >::TooLowCandidateAutoCompoundingDelegationCountToDelegate, + ); + }); +} + +#[test] +fn test_delegate_with_auto_compound_sets_auto_compound_config() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + 0, + 0, + 0, + )); + assert_events_emitted!(Event::Delegation { + delegator: 2, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, + auto_compound: Percent::from_percent(50), + }); + assert_eq!( + vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(50) }], + ParachainStaking::auto_compounding_delegations(&1).into_inner(), + ); + }); +} + +#[test] +fn test_delegate_with_auto_compound_skips_storage_but_emits_event_for_zero_auto_compound() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::zero(), + 0, + 0, + 0, + )); + assert_eq!(0, ParachainStaking::auto_compounding_delegations(&1).len(),); + assert_events_eq!(Event::Delegation { + delegator: 2, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, + auto_compound: Percent::zero(), + }); + }); +} + +#[test] +fn test_delegate_with_auto_compound_reserves_balance() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + 0, + 0, + 0, + )); + assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); + }); +} + +#[test] +fn test_delegate_with_auto_compound_updates_delegator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert!(ParachainStaking::delegator_state(2).is_none()); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + 0, + 0, + 0 + )); + let delegator_state = + ParachainStaking::delegator_state(2).expect("just delegated => exists"); + assert_eq!(delegator_state.total(), 10); + assert_eq!(delegator_state.delegations.0[0].owner, 1); + assert_eq!(delegator_state.delegations.0[0].amount, 10); + }); +} + +#[test] +fn test_delegate_with_auto_compound_updates_collator_state() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + let candidate_state = + ParachainStaking::candidate_info(1).expect("registered in genesis"); + assert_eq!(candidate_state.total_counted, 30); + let top_delegations = + ParachainStaking::top_delegations(1).expect("registered in genesis"); + assert!(top_delegations.delegations.is_empty()); + assert!(top_delegations.total.is_zero()); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + 0, + 0, + 0 + )); + let candidate_state = + ParachainStaking::candidate_info(1).expect("just delegated => exists"); + assert_eq!(candidate_state.total_counted, 40); + let top_delegations = + ParachainStaking::top_delegations(1).expect("just delegated => exists"); + assert_eq!(top_delegations.delegations[0].owner, 2); + assert_eq!(top_delegations.delegations[0].amount, 10); + assert_eq!(top_delegations.total, 10); + }); +} + +#[test] +fn test_delegate_with_auto_compound_can_delegate_immediately_after_other_join_candidates() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 20, 0)); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 20, + Percent::from_percent(50), + 0, + 0, + 0 + )); + }); +} + +#[test] +fn test_delegate_with_auto_compound_can_delegate_to_other_if_revoking() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 30), (3, 20), (4, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 4, + 10, + Percent::from_percent(50), + 0, + 0, + 2 + )); + }); +} + +#[test] +fn test_delegate_with_auto_compound_cannot_delegate_if_less_than_or_equal_lowest_bottom() { + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 10), + (3, 10), + (4, 10), + (5, 10), + (6, 10), + (7, 10), + (8, 10), + (9, 10), + (10, 10), + (11, 10), + ]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (2, 1, 10), + (3, 1, 10), + (4, 1, 10), + (5, 1, 10), + (6, 1, 10), + (8, 1, 10), + (9, 1, 10), + (10, 1, 10), + ]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(11), + 1, + 10, + Percent::from_percent(50), + 8, + 0, + 0 + ), + Error::::CannotDelegateLessThanOrEqualToLowestBottomWhenFull + ); + }); +} + +#[test] +fn test_delegate_with_auto_compound_can_delegate_if_greater_than_lowest_bottom() { + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 10), + (3, 10), + (4, 10), + (5, 10), + (6, 10), + (7, 10), + (8, 10), + (9, 10), + (10, 10), + (11, 11), + ]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![ + (2, 1, 10), + (3, 1, 10), + (4, 1, 10), + (5, 1, 10), + (6, 1, 10), + (8, 1, 10), + (9, 1, 10), + (10, 1, 10), + ]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(11), + 1, + 11, + Percent::from_percent(50), + 8, + 0, + 0 + )); + assert_events_emitted!(Event::DelegationKicked { + delegator: 10, + candidate: 1, + unstaked_amount: 10 + }); + assert_events_emitted!(Event::DelegatorLeft { delegator: 10, unstaked_amount: 10 }); + }); +} + +#[test] +fn test_delegate_with_auto_compound_can_still_delegate_to_other_if_leaving() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20), (3, 20)]) + .with_candidates(vec![(1, 20), (3, 20)]) + .with_delegations(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 3, + 10, + Percent::from_percent(50), + 0, + 0, + 1 + ),); + }); +} + +#[test] +fn test_delegate_with_auto_compound_cannot_delegate_if_candidate() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 30)]) + .with_candidates(vec![(1, 20), (2, 20)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + 0, + 0, + 0 + ), + Error::::CandidateExists + ); + }); +} + +#[test] +fn test_delegate_with_auto_compound_cannot_delegate_if_already_delegated() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 30)]) + .with_candidates(vec![(1, 20)]) + .with_delegations(vec![(2, 1, 20)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 10, + Percent::from_percent(50), + 0, + 1, + 1 + ), + Error::::AlreadyDelegatedCandidate + ); + }); +} + +#[test] +fn test_delegate_with_auto_compound_cannot_delegate_more_than_max_delegations() { + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 50), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_candidates(vec![(1, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) + .with_delegations(vec![(2, 1, 10), (2, 3, 10), (2, 4, 10), (2, 5, 10)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 6, + 10, + Percent::from_percent(50), + 0, + 0, + 4 + ), + Error::::ExceedMaxDelegationsPerDelegator, + ); + }); +} + +#[test] +fn test_delegate_skips_auto_compound_storage_but_emits_event_for_zero_auto_compound() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 20), (3, 30)]) + .with_candidates(vec![(1, 30)]) + .with_auto_compounding_delegations(vec![(3, 1, 10, Percent::from_percent(50))]) + .build() + .execute_with(|| { + // We already have an auto-compounding delegation from 3 -> 1, so the hint validation + // would cause a failure if the auto-compounding isn't skipped properly. + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 1, 0,)); + assert_eq!(1, ParachainStaking::auto_compounding_delegations(&1).len(),); + assert_events_eq!(Event::Delegation { + delegator: 2, + locked_amount: 10, + candidate: 1, + delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, + auto_compound: Percent::zero(), + }); + }); +} + +#[test] +fn test_on_initialize_weights() { + use crate::{ + mock::System, + weights::{SubstrateWeight as PalletWeights, WeightInfo}, + *, + }; + use frame_support::{pallet_prelude::*, weights::constants::RocksDbWeight}; + + // generate balance, candidate, and delegation vecs to "fill" out delegations + let mut balances = Vec::new(); + let mut candidates = Vec::new(); + let mut delegations = Vec::new(); + + for collator in 1..30 { + balances.push((collator, 100)); + candidates.push((collator, 10)); + let starting_delegator = collator * 1000; + for delegator in starting_delegator..starting_delegator + 300 { + balances.push((delegator, 100)); + delegations.push((delegator, collator, 10)); + } + } + + ExtBuilder::default() + .with_balances(balances) + .with_candidates(candidates) + .with_delegations(delegations) + .build() + .execute_with(|| { + let weight = ParachainStaking::on_initialize(1); + + // TODO: build this with proper db reads/writes + assert_eq!(Weight::from_parts(277065000, 0), weight); + + // roll to the end of the round, then run on_init again, we should see round change... + roll_to_round_end(3); + set_author(2, 1, 100); // must set some points for prepare_staking_payouts + let block = System::block_number() + 1; + let weight = ParachainStaking::on_initialize(block); + + // the total on_init weight during our round change. this number is taken from running + // the fn with a given weights.rs benchmark, so will need to be updated as benchmarks + // change. + // + // following this assertion, we add individual weights together to show that we can + // derive this number independently. + let expected_on_init = 2479994997; + assert_eq!(Weight::from_parts(expected_on_init, 186592), weight); + + // assemble weight manually to ensure it is well understood + let mut expected_weight = 0u64; + expected_weight += PalletWeights::::base_on_initialize().ref_time(); + expected_weight += PalletWeights::::prepare_staking_payouts().ref_time(); + + // TODO: this should be the same as >. I believe this relates to + // genesis building + let num_avg_delegations = 8; + expected_weight += PalletWeights::::select_top_candidates( + >::get(), + num_avg_delegations, + ) + .ref_time(); + // Round and Staked writes, done in on-round-change code block inside on_initialize() + expected_weight += RocksDbWeight::get().reads_writes(0, 2).ref_time(); + // more reads/writes manually accounted for for on_finalize + expected_weight += RocksDbWeight::get().reads_writes(3, 2).ref_time(); + + assert_eq!(Weight::from_parts(expected_weight, 186592), weight); + assert_eq!(expected_on_init, expected_weight); // magic number == independent accounting + }); +} + +#[test] +fn test_compute_top_candidates_is_stable() { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 30), (3, 30), (4, 30), (5, 30), (6, 30)]) + .with_candidates(vec![(1, 30), (2, 30), (3, 30), (4, 30), (5, 30), (6, 30)]) + .build() + .execute_with(|| { + // There are 6 candidates with equal amount, but only 5 can be selected + assert_eq!(ParachainStaking::candidate_pool().0.len(), 6); + assert_eq!(ParachainStaking::total_selected(), 5); + // Returns the 5 candidates with greater AccountId, because they are iterated in reverse + assert_eq!(ParachainStaking::compute_top_candidates(), vec![2, 3, 4, 5, 6]); + }); +} diff --git a/pallets/parachain-staking/src/traits.rs b/pallets/parachain-staking/src/traits.rs new file mode 100644 index 000000000..2b30b04cc --- /dev/null +++ b/pallets/parachain-staking/src/traits.rs @@ -0,0 +1,66 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! traits for parachain-staking + +use frame_support::pallet_prelude::Weight; + +pub trait OnCollatorPayout { + fn on_collator_payout( + for_round: crate::RoundIndex, + collator_id: AccountId, + amount: Balance, + ) -> Weight; +} +impl OnCollatorPayout for () { + fn on_collator_payout( + _for_round: crate::RoundIndex, + _collator_id: AccountId, + _amount: Balance, + ) -> Weight { + Weight::zero() + } +} + +pub trait OnNewRound { + fn on_new_round(round_index: crate::RoundIndex) -> Weight; +} +impl OnNewRound for () { + fn on_new_round(_round_index: crate::RoundIndex) -> Weight { + Weight::zero() + } +} + +/// Defines the behavior to payout the collator's reward. +pub trait PayoutCollatorReward { + fn payout_collator_reward( + round_index: crate::RoundIndex, + collator_id: Runtime::AccountId, + amount: crate::BalanceOf, + ) -> Weight; +} + +/// Defines the default behavior for paying out the collator's reward. The amount is directly +/// deposited into the collator's account. +impl PayoutCollatorReward for () { + fn payout_collator_reward( + for_round: crate::RoundIndex, + collator_id: Runtime::AccountId, + amount: crate::BalanceOf, + ) -> Weight { + crate::Pallet::::mint_collator_reward(for_round, collator_id, amount) + } +} diff --git a/pallets/parachain-staking/src/types.rs b/pallets/parachain-staking/src/types.rs new file mode 100644 index 000000000..1ef686b2f --- /dev/null +++ b/pallets/parachain-staking/src/types.rs @@ -0,0 +1,1627 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + +//! Types for parachain-staking + +use crate::{ + auto_compound::AutoCompoundDelegations, set::OrderedSet, BalanceOf, BottomDelegations, + CandidateInfo, Config, DelegatorState, Error, Event, Pallet, Round, RoundIndex, TopDelegations, + Total, COLLATOR_LOCK_ID, DELEGATOR_LOCK_ID, +}; +use frame_support::{ + pallet_prelude::*, + traits::{tokens::WithdrawReasons, LockableCurrency}, +}; +use parity_scale_codec::{Decode, Encode}; +use sp_runtime::{ + traits::{AtLeast32BitUnsigned, Saturating, Zero}, + Perbill, Percent, RuntimeDebug, +}; +use sp_std::{cmp::Ordering, collections::btree_map::BTreeMap, prelude::*}; + +pub struct CountedDelegations { + pub uncounted_stake: BalanceOf, + pub rewardable_delegations: Vec>>, +} + +#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct Bond { + pub owner: AccountId, + pub amount: Balance, +} + +impl Default for Bond { + fn default() -> Bond { + Bond { + owner: A::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) + .expect("infinite length input; no invalid inputs for type; qed"), + amount: B::default(), + } + } +} + +impl Bond { + pub fn from_owner(owner: A) -> Self { + Bond { owner, amount: B::default() } + } +} + +impl Eq for Bond {} + +impl Ord for Bond { + fn cmp(&self, other: &Self) -> Ordering { + self.owner.cmp(&other.owner) + } +} + +impl PartialOrd for Bond { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl PartialEq for Bond { + fn eq(&self, other: &Self) -> bool { + self.owner == other.owner + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] +/// The activity status of the collator +#[derive(Default)] +pub enum CollatorStatus { + /// Committed to be online and producing valid blocks (not equivocating) + #[default] + Active, + /// Temporarily inactive and excused for inactivity + Idle, + /// Bonded until the inner round + Leaving(RoundIndex), +} + +#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +pub struct BondWithAutoCompound { + pub owner: AccountId, + pub amount: Balance, + pub auto_compound: Percent, +} + +impl Default for BondWithAutoCompound { + fn default() -> BondWithAutoCompound { + BondWithAutoCompound { + owner: A::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) + .expect("infinite length input; no invalid inputs for type; qed"), + amount: B::default(), + auto_compound: Percent::zero(), + } + } +} + +#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] +/// Snapshot of collator state at the start of the round for which they are selected +pub struct CollatorSnapshot { + /// The total value locked by the collator. + pub bond: Balance, + + /// The rewardable delegations. This list is a subset of total delegators, where certain + /// delegators are adjusted based on their scheduled + /// [DelegationChange::Revoke] or [DelegationChange::Decrease] action. + pub delegations: Vec>, + + /// The total counted value locked for the collator, including the self bond + total staked by + /// top delegators. + pub total: Balance, +} + +impl PartialEq for CollatorSnapshot { + fn eq(&self, other: &Self) -> bool { + let must_be_true = self.bond == other.bond && self.total == other.total; + if !must_be_true { + return false + } + for ( + BondWithAutoCompound { owner: o1, amount: a1, auto_compound: c1 }, + BondWithAutoCompound { owner: o2, amount: a2, auto_compound: c2 }, + ) in self.delegations.iter().zip(other.delegations.iter()) + { + if o1 != o2 || a1 != a2 || c1 != c2 { + return false + } + } + true + } +} + +impl Default for CollatorSnapshot { + fn default() -> CollatorSnapshot { + CollatorSnapshot { bond: B::default(), delegations: Vec::new(), total: B::default() } + } +} + +#[derive(Default, Encode, Decode, RuntimeDebug, TypeInfo)] +/// Info needed to make delayed payments to stakers after round end +pub struct DelayedPayout { + /// Total round reward (result of compute_issuance() at round end) + pub round_issuance: Balance, + /// The total inflation paid this round to stakers (e.g. less parachain bond fund) + pub total_staking_reward: Balance, + /// Snapshot of collator commission rate at the end of the round + pub collator_commission: Perbill, +} + +#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] +/// DEPRECATED +/// Collator state with commission fee, bonded stake, and delegations +pub struct Collator2 { + /// The account of this collator + pub id: AccountId, + /// This collator's self stake. + pub bond: Balance, + /// Set of all nominator AccountIds (to prevent >1 nomination per AccountId) + pub nominators: OrderedSet, + /// Top T::MaxDelegatorsPerCollator::get() nominators, ordered greatest to least + pub top_nominators: Vec>, + /// Bottom nominators (unbounded), ordered least to greatest + pub bottom_nominators: Vec>, + /// Sum of top delegations + self.bond + pub total_counted: Balance, + /// Sum of all delegations + self.bond = (total_counted + uncounted) + pub total_backing: Balance, + /// Current status of the collator + pub state: CollatorStatus, +} + +impl From> for CollatorCandidate { + fn from(other: Collator2) -> CollatorCandidate { + CollatorCandidate { + id: other.id, + bond: other.bond, + delegators: other.nominators, + top_delegations: other.top_nominators, + bottom_delegations: other.bottom_nominators, + total_counted: other.total_counted, + total_backing: other.total_backing, + request: None, + state: other.state, + } + } +} + +#[derive(PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug, TypeInfo)] +/// Request scheduled to change the collator candidate self-bond +pub struct CandidateBondLessRequest { + pub amount: Balance, + pub when_executable: RoundIndex, +} + +#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] +/// DEPRECATED, replaced by `CandidateMetadata` and two storage instances of `Delegations` +/// Collator candidate state with self bond + delegations +pub struct CollatorCandidate { + /// The account of this collator + pub id: AccountId, + /// This collator's self stake. + pub bond: Balance, + /// Set of all delegator AccountIds (to prevent >1 delegation per AccountId) + pub delegators: OrderedSet, + /// Top T::MaxDelegatorsPerCollator::get() delegations, ordered greatest to least + pub top_delegations: Vec>, + /// Bottom delegations (unbounded), ordered least to greatest + pub bottom_delegations: Vec>, + /// Sum of top delegations + self.bond + pub total_counted: Balance, + /// Sum of all delegations + self.bond = (total_counted + uncounted) + pub total_backing: Balance, + /// Maximum 1 pending request to decrease candidate self bond at any given time + pub request: Option>, + /// Current status of the collator + pub state: CollatorStatus, +} + +#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +/// Type for top and bottom delegation storage item +pub struct Delegations { + pub delegations: Vec>, + pub total: Balance, +} + +impl Default for Delegations { + fn default() -> Delegations { + Delegations { delegations: Vec::new(), total: B::default() } + } +} + +impl + Delegations +{ + pub fn sort_greatest_to_least(&mut self) { + self.delegations.sort_by(|a, b| b.amount.cmp(&a.amount)); + } + /// Insert sorted greatest to least and increase .total accordingly + /// Insertion respects first come first serve so new delegations are pushed after existing + /// delegations if the amount is the same + pub fn insert_sorted_greatest_to_least(&mut self, delegation: Bond) { + self.total = self.total.saturating_add(delegation.amount); + // if delegations nonempty && last_element == delegation.amount => push input and return + if !self.delegations.is_empty() { + // if last_element == delegation.amount => push the delegation and return early + if self.delegations[self.delegations.len() - 1].amount == delegation.amount { + self.delegations.push(delegation); + // early return + return + } + } + // else binary search insertion + match self.delegations.binary_search_by(|x| delegation.amount.cmp(&x.amount)) { + // sorted insertion on sorted vec + // enforces first come first serve for equal bond amounts + Ok(i) => { + let mut new_index = i + 1; + while new_index <= (self.delegations.len() - 1) { + if self.delegations[new_index].amount == delegation.amount { + new_index = new_index.saturating_add(1); + } else { + self.delegations.insert(new_index, delegation); + return + } + } + self.delegations.push(delegation) + }, + Err(i) => self.delegations.insert(i, delegation), + } + } + /// Return the capacity status for top delegations + pub fn top_capacity(&self) -> CapacityStatus { + match &self.delegations { + x if x.len() as u32 >= T::MaxTopDelegationsPerCandidate::get() => CapacityStatus::Full, + x if x.is_empty() => CapacityStatus::Empty, + _ => CapacityStatus::Partial, + } + } + /// Return the capacity status for bottom delegations + pub fn bottom_capacity(&self) -> CapacityStatus { + match &self.delegations { + x if x.len() as u32 >= T::MaxBottomDelegationsPerCandidate::get() => + CapacityStatus::Full, + x if x.is_empty() => CapacityStatus::Empty, + _ => CapacityStatus::Partial, + } + } + /// Return last delegation amount without popping the delegation + pub fn lowest_delegation_amount(&self) -> Balance { + self.delegations.last().map(|x| x.amount).unwrap_or(Balance::zero()) + } + /// Return highest delegation amount + pub fn highest_delegation_amount(&self) -> Balance { + self.delegations.first().map(|x| x.amount).unwrap_or(Balance::zero()) + } +} + +#[derive(PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] +/// Capacity status for top or bottom delegations +pub enum CapacityStatus { + /// Reached capacity + Full, + /// Empty aka contains no delegations + Empty, + /// Partially full (nonempty and not full) + Partial, +} + +#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] +/// All candidate info except the top and bottom delegations +pub struct CandidateMetadata { + /// This candidate's self bond amount + pub bond: Balance, + /// Total number of delegations to this candidate + pub delegation_count: u32, + /// Self bond + sum of top delegations + pub total_counted: Balance, + /// The smallest top delegation amount + pub lowest_top_delegation_amount: Balance, + /// The highest bottom delegation amount + pub highest_bottom_delegation_amount: Balance, + /// The smallest bottom delegation amount + pub lowest_bottom_delegation_amount: Balance, + /// Capacity status for top delegations + pub top_capacity: CapacityStatus, + /// Capacity status for bottom delegations + pub bottom_capacity: CapacityStatus, + /// Maximum 1 pending request to decrease candidate self bond at any given time + pub request: Option>, + /// Current status of the collator + pub status: CollatorStatus, +} + +impl< + Balance: Copy + + Zero + + PartialOrd + + sp_std::ops::AddAssign + + sp_std::ops::SubAssign + + sp_std::ops::Sub + + sp_std::fmt::Debug + + Saturating, + > CandidateMetadata +{ + pub fn new(bond: Balance) -> Self { + CandidateMetadata { + bond, + delegation_count: 0u32, + total_counted: bond, + lowest_top_delegation_amount: Zero::zero(), + highest_bottom_delegation_amount: Zero::zero(), + lowest_bottom_delegation_amount: Zero::zero(), + top_capacity: CapacityStatus::Empty, + bottom_capacity: CapacityStatus::Empty, + request: None, + status: CollatorStatus::Active, + } + } + pub fn is_active(&self) -> bool { + matches!(self.status, CollatorStatus::Active) + } + pub fn is_leaving(&self) -> bool { + matches!(self.status, CollatorStatus::Leaving(_)) + } + pub fn schedule_leave(&mut self) -> Result<(RoundIndex, RoundIndex), DispatchError> { + ensure!(!self.is_leaving(), Error::::CandidateAlreadyLeaving); + let now = >::get().current; + let when = now + T::LeaveCandidatesDelay::get(); + self.status = CollatorStatus::Leaving(when); + Ok((now, when)) + } + pub fn can_leave(&self) -> DispatchResult { + if let CollatorStatus::Leaving(when) = self.status { + ensure!(>::get().current >= when, Error::::CandidateCannotLeaveYet); + Ok(()) + } else { + Err(Error::::CandidateNotLeaving.into()) + } + } + pub fn go_offline(&mut self) { + self.status = CollatorStatus::Idle; + } + pub fn go_online(&mut self) { + self.status = CollatorStatus::Active; + } + pub fn bond_more(&mut self, who: T::AccountId, more: Balance) -> DispatchResult + where + BalanceOf: From, + { + ensure!( + >::get_collator_stakable_free_balance(&who) >= more.into(), + Error::::InsufficientBalance + ); + let new_total = >::get().saturating_add(more.into()); + >::put(new_total); + self.bond = self.bond.saturating_add(more); + T::Currency::set_lock(COLLATOR_LOCK_ID, &who, self.bond.into(), WithdrawReasons::all()); + self.total_counted = self.total_counted.saturating_add(more); + >::deposit_event(Event::CandidateBondedMore { + candidate: who, + amount: more.into(), + new_total_bond: self.bond.into(), + }); + Ok(()) + } + /// Schedule executable decrease of collator candidate self bond + /// Returns the round at which the collator can execute the pending request + pub fn schedule_bond_less( + &mut self, + less: Balance, + ) -> Result + where + BalanceOf: Into, + { + // ensure no pending request + ensure!(self.request.is_none(), Error::::PendingCandidateRequestAlreadyExists); + // ensure bond above min after decrease + ensure!(self.bond > less, Error::::CandidateBondBelowMin); + ensure!( + self.bond - less >= T::MinCandidateStk::get().into(), + Error::::CandidateBondBelowMin + ); + let when_executable = >::get().current + T::CandidateBondLessDelay::get(); + self.request = Some(CandidateBondLessRequest { amount: less, when_executable }); + Ok(when_executable) + } + /// Execute pending request to decrease the collator self bond + /// Returns the event to be emitted + pub fn execute_bond_less(&mut self, who: T::AccountId) -> DispatchResult + where + BalanceOf: From, + { + let request = self.request.ok_or(Error::::PendingCandidateRequestsDNE)?; + ensure!( + request.when_executable <= >::get().current, + Error::::PendingCandidateRequestNotDueYet + ); + let new_total_staked = >::get().saturating_sub(request.amount.into()); + >::put(new_total_staked); + // Arithmetic assumptions are self.bond > less && self.bond - less > CollatorMinBond + // (assumptions enforced by `schedule_bond_less`; if storage corrupts, must re-verify) + self.bond = self.bond.saturating_sub(request.amount); + T::Currency::set_lock(COLLATOR_LOCK_ID, &who, self.bond.into(), WithdrawReasons::all()); + self.total_counted = self.total_counted.saturating_sub(request.amount); + let event = Event::CandidateBondedLess { + candidate: who.clone(), + amount: request.amount.into(), + new_bond: self.bond.into(), + }; + // reset s.t. no pending request + self.request = None; + // update candidate pool value because it must change if self bond changes + if self.is_active() { + Pallet::::update_active(who, self.total_counted.into()); + } + Pallet::::deposit_event(event); + Ok(()) + } + /// Cancel candidate bond less request + pub fn cancel_bond_less(&mut self, who: T::AccountId) -> DispatchResult + where + BalanceOf: From, + { + let request = self.request.ok_or(Error::::PendingCandidateRequestsDNE)?; + let event = Event::CancelledCandidateBondLess { + candidate: who, + amount: request.amount.into(), + execute_round: request.when_executable, + }; + self.request = None; + Pallet::::deposit_event(event); + Ok(()) + } + /// Reset top delegations metadata + pub fn reset_top_data( + &mut self, + candidate: T::AccountId, + top_delegations: &Delegations>, + ) where + BalanceOf: Into + From, + { + self.lowest_top_delegation_amount = top_delegations.lowest_delegation_amount().into(); + self.top_capacity = top_delegations.top_capacity::(); + let old_total_counted = self.total_counted; + self.total_counted = self.bond.saturating_add(top_delegations.total.into()); + // CandidatePool value for candidate always changes if top delegations total changes + // so we moved the update into this function to deduplicate code and patch a bug that + // forgot to apply the update when increasing top delegation + if old_total_counted != self.total_counted && self.is_active() { + Pallet::::update_active(candidate, self.total_counted.into()); + } + } + /// Reset bottom delegations metadata + pub fn reset_bottom_data( + &mut self, + bottom_delegations: &Delegations>, + ) where + BalanceOf: Into, + { + self.lowest_bottom_delegation_amount = bottom_delegations.lowest_delegation_amount().into(); + self.highest_bottom_delegation_amount = + bottom_delegations.highest_delegation_amount().into(); + self.bottom_capacity = bottom_delegations.bottom_capacity::(); + } + /// Add delegation + /// Returns whether delegator was added and an optional negative total counted remainder + /// for if a bottom delegation was kicked + /// MUST ensure no delegation exists for this candidate in the `DelegatorState` before call + pub fn add_delegation( + &mut self, + candidate: &T::AccountId, + delegation: Bond>, + ) -> Result<(DelegatorAdded, Option), DispatchError> + where + BalanceOf: Into + From, + { + let mut less_total_staked = None; + let delegator_added = match self.top_capacity { + CapacityStatus::Full => { + // top is full, insert into top iff the lowest_top < amount + if self.lowest_top_delegation_amount < delegation.amount.into() { + // bumps lowest top to the bottom inside this function call + less_total_staked = self.add_top_delegation::(candidate, delegation); + DelegatorAdded::AddedToTop { new_total: self.total_counted } + } else { + // if bottom is full, only insert if greater than lowest bottom (which will + // be bumped out) + if matches!(self.bottom_capacity, CapacityStatus::Full) { + ensure!( + delegation.amount.into() > self.lowest_bottom_delegation_amount, + Error::::CannotDelegateLessThanOrEqualToLowestBottomWhenFull + ); + // need to subtract from total staked + less_total_staked = Some(self.lowest_bottom_delegation_amount); + } + // insert into bottom + self.add_bottom_delegation::(false, candidate, delegation); + DelegatorAdded::AddedToBottom + } + }, + // top is either empty or partially full + _ => { + self.add_top_delegation::(candidate, delegation); + DelegatorAdded::AddedToTop { new_total: self.total_counted } + }, + }; + Ok((delegator_added, less_total_staked)) + } + /// Add delegation to top delegation + /// Returns Option + /// Only call if lowest top delegation is less than delegation.amount || !top_full + pub fn add_top_delegation( + &mut self, + candidate: &T::AccountId, + delegation: Bond>, + ) -> Option + where + BalanceOf: Into + From, + { + let mut less_total_staked = None; + let mut top_delegations = >::get(candidate) + .expect("CandidateInfo existence => TopDelegations existence"); + let max_top_delegations_per_candidate = T::MaxTopDelegationsPerCandidate::get(); + if top_delegations.delegations.len() as u32 == max_top_delegations_per_candidate { + // pop lowest top delegation + let new_bottom_delegation = top_delegations.delegations.pop().expect(""); + top_delegations.total = + top_delegations.total.saturating_sub(new_bottom_delegation.amount); + if matches!(self.bottom_capacity, CapacityStatus::Full) { + less_total_staked = Some(self.lowest_bottom_delegation_amount); + } + self.add_bottom_delegation::(true, candidate, new_bottom_delegation); + } + // insert into top + top_delegations.insert_sorted_greatest_to_least(delegation); + // update candidate info + self.reset_top_data::(candidate.clone(), &top_delegations); + if less_total_staked.is_none() { + // only increment delegation count if we are not kicking a bottom delegation + self.delegation_count = self.delegation_count.saturating_add(1u32); + } + >::insert(candidate, top_delegations); + less_total_staked + } + /// Add delegation to bottom delegations + /// Check before call that if capacity is full, inserted delegation is higher than lowest + /// bottom delegation (and if so, need to adjust the total storage item) + /// CALLER MUST ensure(lowest_bottom_to_be_kicked.amount < delegation.amount) + pub fn add_bottom_delegation( + &mut self, + bumped_from_top: bool, + candidate: &T::AccountId, + delegation: Bond>, + ) where + BalanceOf: Into + From, + { + let mut bottom_delegations = >::get(candidate) + .expect("CandidateInfo existence => BottomDelegations existence"); + // if bottom is full, kick the lowest bottom (which is expected to be lower than input + // as per check) + let increase_delegation_count = if bottom_delegations.delegations.len() as u32 == + T::MaxBottomDelegationsPerCandidate::get() + { + let lowest_bottom_to_be_kicked = bottom_delegations + .delegations + .pop() + .expect("if at full capacity (>0), then >0 bottom delegations exist; qed"); + // EXPECT lowest_bottom_to_be_kicked.amount < delegation.amount enforced by caller + // if lowest_bottom_to_be_kicked.amount == delegation.amount, we will still kick + // the lowest bottom to enforce first come first served + bottom_delegations.total = + bottom_delegations.total.saturating_sub(lowest_bottom_to_be_kicked.amount); + // update delegator state + // total staked is updated via propagation of lowest bottom delegation amount prior + // to call + let mut delegator_state = >::get(&lowest_bottom_to_be_kicked.owner) + .expect("Delegation existence => DelegatorState existence"); + let leaving = delegator_state.delegations.0.len() == 1usize; + delegator_state.rm_delegation::(candidate); + >::delegation_remove_request_with_state( + candidate, + &lowest_bottom_to_be_kicked.owner, + &mut delegator_state, + ); + >::remove_auto_compound( + candidate, + &lowest_bottom_to_be_kicked.owner, + ); + + Pallet::::deposit_event(Event::DelegationKicked { + delegator: lowest_bottom_to_be_kicked.owner.clone(), + candidate: candidate.clone(), + unstaked_amount: lowest_bottom_to_be_kicked.amount, + }); + if leaving { + >::remove(&lowest_bottom_to_be_kicked.owner); + Pallet::::deposit_event(Event::DelegatorLeft { + delegator: lowest_bottom_to_be_kicked.owner, + unstaked_amount: lowest_bottom_to_be_kicked.amount, + }); + } else { + >::insert(&lowest_bottom_to_be_kicked.owner, delegator_state); + } + false + } else { + !bumped_from_top + }; + // only increase delegation count if new bottom delegation (1) doesn't come from top && + // (2) doesn't pop the lowest delegation from the bottom + if increase_delegation_count { + self.delegation_count = self.delegation_count.saturating_add(1u32); + } + bottom_delegations.insert_sorted_greatest_to_least(delegation); + self.reset_bottom_data::(&bottom_delegations); + >::insert(candidate, bottom_delegations); + } + /// Remove delegation + /// Removes from top if amount is above lowest top or top is not full + /// Return Ok(if_total_counted_changed) + pub fn rm_delegation_if_exists( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + amount: Balance, + ) -> Result + where + BalanceOf: Into + From, + { + let amount_geq_lowest_top = amount >= self.lowest_top_delegation_amount; + let top_is_not_full = !matches!(self.top_capacity, CapacityStatus::Full); + let lowest_top_eq_highest_bottom = + self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; + let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); + if top_is_not_full || (amount_geq_lowest_top && !lowest_top_eq_highest_bottom) { + self.rm_top_delegation::(candidate, delegator) + } else if amount_geq_lowest_top && lowest_top_eq_highest_bottom { + let result = self.rm_top_delegation::(candidate, delegator.clone()); + if result == Err(delegation_dne_err) { + // worst case removal + self.rm_bottom_delegation::(candidate, delegator) + } else { + result + } + } else { + self.rm_bottom_delegation::(candidate, delegator) + } + } + /// Remove top delegation, bumps top bottom delegation if exists + pub fn rm_top_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + ) -> Result + where + BalanceOf: Into + From, + { + let old_total_counted = self.total_counted; + // remove top delegation + let mut top_delegations = >::get(candidate) + .expect("CandidateInfo exists => TopDelegations exists"); + let mut actual_amount_option: Option> = None; + top_delegations.delegations = top_delegations + .delegations + .clone() + .into_iter() + .filter(|d| { + if d.owner != delegator { + true + } else { + actual_amount_option = Some(d.amount); + false + } + }) + .collect(); + let actual_amount = actual_amount_option.ok_or(Error::::DelegationDNE)?; + top_delegations.total = top_delegations.total.saturating_sub(actual_amount); + // if bottom nonempty => bump top bottom to top + if !matches!(self.bottom_capacity, CapacityStatus::Empty) { + let mut bottom_delegations = + >::get(candidate).expect("bottom is nonempty as just checked"); + // expect already stored greatest to least by bond amount + let highest_bottom_delegation = bottom_delegations.delegations.remove(0); + bottom_delegations.total = + bottom_delegations.total.saturating_sub(highest_bottom_delegation.amount); + self.reset_bottom_data::(&bottom_delegations); + >::insert(candidate, bottom_delegations); + // insert highest bottom into top delegations + top_delegations.insert_sorted_greatest_to_least(highest_bottom_delegation); + } + // update candidate info + self.reset_top_data::(candidate.clone(), &top_delegations); + self.delegation_count = self.delegation_count.saturating_sub(1u32); + >::insert(candidate, top_delegations); + // return whether total counted changed + Ok(old_total_counted == self.total_counted) + } + /// Remove bottom delegation + /// Returns if_total_counted_changed: bool + pub fn rm_bottom_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + ) -> Result + where + BalanceOf: Into, + { + // remove bottom delegation + let mut bottom_delegations = >::get(candidate) + .expect("CandidateInfo exists => BottomDelegations exists"); + let mut actual_amount_option: Option> = None; + bottom_delegations.delegations = bottom_delegations + .delegations + .clone() + .into_iter() + .filter(|d| { + if d.owner != delegator { + true + } else { + actual_amount_option = Some(d.amount); + false + } + }) + .collect(); + let actual_amount = actual_amount_option.ok_or(Error::::DelegationDNE)?; + bottom_delegations.total = bottom_delegations.total.saturating_sub(actual_amount); + // update candidate info + self.reset_bottom_data::(&bottom_delegations); + self.delegation_count = self.delegation_count.saturating_sub(1u32); + >::insert(candidate, bottom_delegations); + Ok(false) + } + /// Increase delegation amount + pub fn increase_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + bond: BalanceOf, + more: BalanceOf, + ) -> Result + where + BalanceOf: Into + From, + { + let lowest_top_eq_highest_bottom = + self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; + let bond_geq_lowest_top = bond.into() >= self.lowest_top_delegation_amount; + let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); + if bond_geq_lowest_top && !lowest_top_eq_highest_bottom { + // definitely in top + self.increase_top_delegation::(candidate, delegator, more) + } else if bond_geq_lowest_top && lowest_top_eq_highest_bottom { + // update top but if error then update bottom (because could be in bottom because + // lowest_top_eq_highest_bottom) + let result = self.increase_top_delegation::(candidate, delegator.clone(), more); + if result == Err(delegation_dne_err) { + self.increase_bottom_delegation::(candidate, delegator, bond, more) + } else { + result + } + } else { + self.increase_bottom_delegation::(candidate, delegator, bond, more) + } + } + /// Increase top delegation + pub fn increase_top_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + more: BalanceOf, + ) -> Result + where + BalanceOf: Into + From, + { + let mut top_delegations = >::get(candidate) + .expect("CandidateInfo exists => TopDelegations exists"); + let mut in_top = false; + top_delegations.delegations = top_delegations + .delegations + .clone() + .into_iter() + .map(|d| { + if d.owner != delegator { + d + } else { + in_top = true; + let new_amount = d.amount.saturating_add(more); + Bond { owner: d.owner, amount: new_amount } + } + }) + .collect(); + ensure!(in_top, Error::::DelegationDNE); + top_delegations.total = top_delegations.total.saturating_add(more); + top_delegations.sort_greatest_to_least(); + self.reset_top_data::(candidate.clone(), &top_delegations); + >::insert(candidate, top_delegations); + Ok(true) + } + /// Increase bottom delegation + pub fn increase_bottom_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + bond: BalanceOf, + more: BalanceOf, + ) -> Result + where + BalanceOf: Into + From, + { + let mut bottom_delegations = + >::get(candidate).ok_or(Error::::CandidateDNE)?; + let mut delegation_option: Option>> = None; + let in_top_after = if (bond.saturating_add(more)).into() > self.lowest_top_delegation_amount + { + // bump it from bottom + bottom_delegations.delegations = bottom_delegations + .delegations + .clone() + .into_iter() + .filter(|d| { + if d.owner != delegator { + true + } else { + delegation_option = Some(Bond { + owner: d.owner.clone(), + amount: d.amount.saturating_add(more), + }); + false + } + }) + .collect(); + let delegation = delegation_option.ok_or(Error::::DelegationDNE)?; + bottom_delegations.total = bottom_delegations.total.saturating_sub(bond); + // add it to top + let mut top_delegations = >::get(candidate) + .expect("CandidateInfo existence => TopDelegations existence"); + // if top is full, pop lowest top + if matches!(top_delegations.top_capacity::(), CapacityStatus::Full) { + // pop lowest top delegation + let new_bottom_delegation = top_delegations + .delegations + .pop() + .expect("Top capacity full => Exists at least 1 top delegation"); + top_delegations.total = + top_delegations.total.saturating_sub(new_bottom_delegation.amount); + bottom_delegations.insert_sorted_greatest_to_least(new_bottom_delegation); + } + // insert into top + top_delegations.insert_sorted_greatest_to_least(delegation); + self.reset_top_data::(candidate.clone(), &top_delegations); + >::insert(candidate, top_delegations); + true + } else { + let mut in_bottom = false; + // just increase the delegation + bottom_delegations.delegations = bottom_delegations + .delegations + .clone() + .into_iter() + .map(|d| { + if d.owner != delegator { + d + } else { + in_bottom = true; + Bond { owner: d.owner, amount: d.amount.saturating_add(more) } + } + }) + .collect(); + ensure!(in_bottom, Error::::DelegationDNE); + bottom_delegations.total = bottom_delegations.total.saturating_add(more); + bottom_delegations.sort_greatest_to_least(); + false + }; + self.reset_bottom_data::(&bottom_delegations); + >::insert(candidate, bottom_delegations); + Ok(in_top_after) + } + /// Decrease delegation + pub fn decrease_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + bond: Balance, + less: BalanceOf, + ) -> Result + where + BalanceOf: Into + From, + { + let lowest_top_eq_highest_bottom = + self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; + let bond_geq_lowest_top = bond >= self.lowest_top_delegation_amount; + let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); + if bond_geq_lowest_top && !lowest_top_eq_highest_bottom { + // definitely in top + self.decrease_top_delegation::(candidate, delegator, bond.into(), less) + } else if bond_geq_lowest_top && lowest_top_eq_highest_bottom { + // update top but if error then update bottom (because could be in bottom because + // lowest_top_eq_highest_bottom) + let result = + self.decrease_top_delegation::(candidate, delegator.clone(), bond.into(), less); + if result == Err(delegation_dne_err) { + self.decrease_bottom_delegation::(candidate, delegator, less) + } else { + result + } + } else { + self.decrease_bottom_delegation::(candidate, delegator, less) + } + } + /// Decrease top delegation + pub fn decrease_top_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + bond: BalanceOf, + less: BalanceOf, + ) -> Result + where + BalanceOf: Into + From, + { + // The delegation after the `decrease-delegation` will be strictly less than the + // highest bottom delegation + let bond_after_less_than_highest_bottom = + bond.saturating_sub(less).into() < self.highest_bottom_delegation_amount; + // The top delegations is full and the bottom delegations has at least one delegation + let full_top_and_nonempty_bottom = matches!(self.top_capacity, CapacityStatus::Full) && + !matches!(self.bottom_capacity, CapacityStatus::Empty); + let mut top_delegations = + >::get(candidate).ok_or(Error::::CandidateDNE)?; + let in_top_after = if bond_after_less_than_highest_bottom && full_top_and_nonempty_bottom { + let mut delegation_option: Option>> = None; + // take delegation from top + top_delegations.delegations = top_delegations + .delegations + .clone() + .into_iter() + .filter(|d| { + if d.owner != delegator { + true + } else { + top_delegations.total = top_delegations.total.saturating_sub(d.amount); + delegation_option = Some(Bond { + owner: d.owner.clone(), + amount: d.amount.saturating_sub(less), + }); + false + } + }) + .collect(); + let delegation = delegation_option.ok_or(Error::::DelegationDNE)?; + // pop highest bottom by reverse and popping + let mut bottom_delegations = >::get(candidate) + .expect("CandidateInfo existence => BottomDelegations existence"); + let highest_bottom_delegation = bottom_delegations.delegations.remove(0); + bottom_delegations.total = + bottom_delegations.total.saturating_sub(highest_bottom_delegation.amount); + // insert highest bottom into top + top_delegations.insert_sorted_greatest_to_least(highest_bottom_delegation); + // insert previous top into bottom + bottom_delegations.insert_sorted_greatest_to_least(delegation); + self.reset_bottom_data::(&bottom_delegations); + >::insert(candidate, bottom_delegations); + false + } else { + // keep it in the top + let mut is_in_top = false; + top_delegations.delegations = top_delegations + .delegations + .clone() + .into_iter() + .map(|d| { + if d.owner != delegator { + d + } else { + is_in_top = true; + Bond { owner: d.owner, amount: d.amount.saturating_sub(less) } + } + }) + .collect(); + ensure!(is_in_top, Error::::DelegationDNE); + top_delegations.total = top_delegations.total.saturating_sub(less); + top_delegations.sort_greatest_to_least(); + true + }; + self.reset_top_data::(candidate.clone(), &top_delegations); + >::insert(candidate, top_delegations); + Ok(in_top_after) + } + /// Decrease bottom delegation + pub fn decrease_bottom_delegation( + &mut self, + candidate: &T::AccountId, + delegator: T::AccountId, + less: BalanceOf, + ) -> Result + where + BalanceOf: Into, + { + let mut bottom_delegations = >::get(candidate) + .expect("CandidateInfo exists => BottomDelegations exists"); + let mut in_bottom = false; + bottom_delegations.delegations = bottom_delegations + .delegations + .clone() + .into_iter() + .map(|d| { + if d.owner != delegator { + d + } else { + in_bottom = true; + Bond { owner: d.owner, amount: d.amount.saturating_sub(less) } + } + }) + .collect(); + ensure!(in_bottom, Error::::DelegationDNE); + bottom_delegations.sort_greatest_to_least(); + self.reset_bottom_data::(&bottom_delegations); + >::insert(candidate, bottom_delegations); + Ok(false) + } +} + +// Temporary manual implementation for migration testing purposes +impl PartialEq for CollatorCandidate { + fn eq(&self, other: &Self) -> bool { + let must_be_true = self.id == other.id && + self.bond == other.bond && + self.total_counted == other.total_counted && + self.total_backing == other.total_backing && + self.request == other.request && + self.state == other.state; + if !must_be_true { + return false + } + for (x, y) in self.delegators.0.iter().zip(other.delegators.0.iter()) { + if x != y { + return false + } + } + for (Bond { owner: o1, amount: a1 }, Bond { owner: o2, amount: a2 }) in + self.top_delegations.iter().zip(other.top_delegations.iter()) + { + if o1 != o2 || a1 != a2 { + return false + } + } + for (Bond { owner: o1, amount: a1 }, Bond { owner: o2, amount: a2 }) in + self.bottom_delegations.iter().zip(other.bottom_delegations.iter()) + { + if o1 != o2 || a1 != a2 { + return false + } + } + true + } +} + +/// Convey relevant information describing if a delegator was added to the top or bottom +/// Delegations added to the top yield a new total +#[derive(Clone, Copy, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub enum DelegatorAdded { + AddedToTop { new_total: B }, + AddedToBottom, +} + +impl< + A: Ord + Clone + sp_std::fmt::Debug, + B: AtLeast32BitUnsigned + + Ord + + Copy + + sp_std::ops::AddAssign + + sp_std::ops::SubAssign + + sp_std::fmt::Debug, + > CollatorCandidate +{ + pub fn is_active(&self) -> bool { + self.state == CollatorStatus::Active + } +} + +impl From> for CollatorSnapshot { + fn from(other: CollatorCandidate) -> CollatorSnapshot { + CollatorSnapshot { + bond: other.bond, + delegations: other + .top_delegations + .into_iter() + .map(|d| BondWithAutoCompound { + owner: d.owner, + amount: d.amount, + auto_compound: Percent::zero(), + }) + .collect(), + total: other.total_counted, + } + } +} + +#[allow(deprecated)] +#[derive(Clone, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] +pub enum DelegatorStatus { + /// Active with no scheduled exit + Active, + /// Schedule exit to revoke all ongoing delegations + #[deprecated(note = "must only be used for backwards compatibility reasons")] + Leaving(RoundIndex), +} + +#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +/// Delegator state +pub struct Delegator { + /// Delegator account + pub id: AccountId, + /// All current delegations + pub delegations: OrderedSet>, + /// Total balance locked for this delegator + pub total: Balance, + /// Sum of pending revocation amounts + bond less amounts + pub less_total: Balance, + /// Status for this delegator + pub status: DelegatorStatus, +} + +// Temporary manual implementation for migration testing purposes +impl PartialEq for Delegator { + fn eq(&self, other: &Self) -> bool { + let must_be_true = self.id == other.id && + self.total == other.total && + self.less_total == other.less_total && + self.status == other.status; + if !must_be_true { + return false + } + for (Bond { owner: o1, amount: a1 }, Bond { owner: o2, amount: a2 }) in + self.delegations.0.iter().zip(other.delegations.0.iter()) + { + if o1 != o2 || a1 != a2 { + return false + } + } + true + } +} + +impl< + AccountId: Ord + Clone, + Balance: Copy + + sp_std::ops::AddAssign + + sp_std::ops::Add + + sp_std::ops::SubAssign + + sp_std::ops::Sub + + Ord + + Zero + + Default + + Saturating, + > Delegator +{ + pub fn new(id: AccountId, collator: AccountId, amount: Balance) -> Self { + Delegator { + id, + delegations: OrderedSet::from(vec![Bond { owner: collator, amount }]), + total: amount, + less_total: Balance::zero(), + status: DelegatorStatus::Active, + } + } + + pub fn default_with_total(id: AccountId, amount: Balance) -> Self { + Delegator { + id, + total: amount, + delegations: OrderedSet::from(vec![]), + less_total: Balance::zero(), + status: DelegatorStatus::Active, + } + } + + pub fn total(&self) -> Balance { + self.total + } + + pub fn total_sub_if(&mut self, amount: Balance, check: F) -> DispatchResult + where + T: Config, + T::AccountId: From, + BalanceOf: From, + F: Fn(Balance) -> DispatchResult, + { + let total = self.total.saturating_sub(amount); + check(total)?; + self.total = total; + self.adjust_bond_lock::(BondAdjust::Decrease)?; + Ok(()) + } + + pub fn total_add(&mut self, amount: Balance) -> DispatchResult + where + T: Config, + T::AccountId: From, + BalanceOf: From, + { + self.total = self.total.saturating_add(amount); + self.adjust_bond_lock::(BondAdjust::Increase(amount))?; + Ok(()) + } + + pub fn total_sub(&mut self, amount: Balance) -> DispatchResult + where + T: Config, + T::AccountId: From, + BalanceOf: From, + { + self.total = self.total.saturating_sub(amount); + self.adjust_bond_lock::(BondAdjust::Decrease)?; + Ok(()) + } + + pub fn is_active(&self) -> bool { + matches!(self.status, DelegatorStatus::Active) + } + + pub fn add_delegation(&mut self, bond: Bond) -> bool { + let amt = bond.amount; + if self.delegations.insert(bond) { + self.total = self.total.saturating_add(amt); + true + } else { + false + } + } + // Return Some(remaining balance), must be more than MinDelegatorStk + // Return None if delegation not found + pub fn rm_delegation(&mut self, collator: &AccountId) -> Option + where + BalanceOf: From, + T::AccountId: From, + { + let mut amt: Option = None; + let delegations = self + .delegations + .0 + .iter() + .filter_map(|x| { + if &x.owner == collator { + amt = Some(x.amount); + None + } else { + Some(x.clone()) + } + }) + .collect(); + if let Some(balance) = amt { + self.delegations = OrderedSet::from(delegations); + self.total_sub::(balance).expect("Decreasing lock cannot fail, qed"); + Some(self.total) + } else { + None + } + } + + /// Increases the delegation amount and returns `true` if the delegation is part of the + /// TopDelegations set, `false` otherwise. + pub fn increase_delegation( + &mut self, + candidate: AccountId, + amount: Balance, + ) -> Result + where + BalanceOf: From, + T::AccountId: From, + Delegator>: From>, + { + let delegator_id: T::AccountId = self.id.clone().into(); + let candidate_id: T::AccountId = candidate.clone().into(); + let balance_amt: BalanceOf = amount.into(); + // increase delegation + for x in &mut self.delegations.0 { + if x.owner == candidate { + let before_amount: BalanceOf = x.amount.into(); + x.amount = x.amount.saturating_add(amount); + self.total = self.total.saturating_add(amount); + self.adjust_bond_lock::(BondAdjust::Increase(amount))?; + + // update collator state delegation + let mut collator_state = + >::get(&candidate_id).ok_or(Error::::CandidateDNE)?; + let before = collator_state.total_counted; + let in_top = collator_state.increase_delegation::( + &candidate_id, + delegator_id.clone(), + before_amount, + balance_amt, + )?; + let after = collator_state.total_counted; + if collator_state.is_active() && (before != after) { + Pallet::::update_active(candidate_id.clone(), after); + } + >::insert(&candidate_id, collator_state); + let new_total_staked = >::get().saturating_add(balance_amt); + >::put(new_total_staked); + let nom_st: Delegator> = self.clone().into(); + >::insert(&delegator_id, nom_st); + return Ok(in_top) + } + } + Err(Error::::DelegationDNE.into()) + } + + /// Updates the bond locks for this delegator. + /// + /// This will take the current self.total and ensure that a lock of the same amount is applied + /// and when increasing the bond lock will also ensure that the account has enough free balance. + /// + /// `additional_required_balance` should reflect the change to the amount that should be locked if + /// positive, 0 otherwise (e.g. `min(0, change_in_total_bond)`). This is necessary because it is + /// not possible to query the amount that is locked for a given lock id. + pub fn adjust_bond_lock( + &mut self, + additional_required_balance: BondAdjust, + ) -> DispatchResult + where + BalanceOf: From, + T::AccountId: From, + { + match additional_required_balance { + BondAdjust::Increase(amount) => { + ensure!( + >::get_delegator_stakable_free_balance(&self.id.clone().into()) >= + amount.into(), + Error::::InsufficientBalance, + ); + + // additional sanity check: shouldn't ever want to lock more than total + if amount > self.total { + log::warn!("LOGIC ERROR: request to reserve more than bond total"); + return Err(DispatchError::Other("Invalid additional_required_balance")) + } + }, + BondAdjust::Decrease => (), // do nothing on decrease + }; + + if self.total.is_zero() { + T::Currency::remove_lock(DELEGATOR_LOCK_ID, &self.id.clone().into()); + } else { + T::Currency::set_lock( + DELEGATOR_LOCK_ID, + &self.id.clone().into(), + self.total.into(), + WithdrawReasons::all(), + ); + } + Ok(()) + } + + /// Retrieves the bond amount that a delegator has provided towards a collator. + /// Returns `None` if missing. + pub fn get_bond_amount(&self, collator: &AccountId) -> Option { + self.delegations.0.iter().find(|b| &b.owner == collator).map(|b| b.amount) + } +} + +pub mod deprecated { + #![allow(deprecated)] + + use super::*; + + #[deprecated(note = "use DelegationAction")] + #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] + /// Changes requested by the delegator + /// - limit of 1 ongoing change per delegation + pub enum DelegationChange { + Revoke, + Decrease, + } + + #[deprecated(note = "use ScheduledRequest")] + #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] + pub struct DelegationRequest { + pub collator: AccountId, + pub amount: Balance, + pub when_executable: RoundIndex, + pub action: DelegationChange, + } + + #[deprecated(note = "use DelegationScheduledRequests storage item")] + #[derive(Clone, Encode, PartialEq, Decode, RuntimeDebug, TypeInfo)] + /// Pending requests to mutate delegations for each delegator + pub struct PendingDelegationRequests { + /// Number of pending revocations (necessary for determining whether revoke is exit) + pub revocations_count: u32, + /// Map from collator -> Request (enforces at most 1 pending request per delegation) + pub requests: BTreeMap>, + /// Sum of pending revocation amounts + bond less amounts + pub less_total: Balance, + } + + impl Default for PendingDelegationRequests { + fn default() -> PendingDelegationRequests { + PendingDelegationRequests { + revocations_count: 0u32, + requests: BTreeMap::new(), + less_total: B::zero(), + } + } + } + + impl< + A: Ord + Clone, + B: Zero + + Ord + + Copy + + Clone + + sp_std::ops::AddAssign + + sp_std::ops::Add + + sp_std::ops::SubAssign + + sp_std::ops::Sub + + Saturating, + > PendingDelegationRequests + { + /// New default (empty) pending requests + pub fn new() -> Self { + Self::default() + } + } + + #[deprecated(note = "use new crate::types::Delegator struct")] + #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] + /// Delegator state + pub struct Delegator { + /// Delegator account + pub id: AccountId, + /// All current delegations + pub delegations: OrderedSet>, + /// Total balance locked for this delegator + pub total: Balance, + /// Requests to change delegations, relevant iff active + pub requests: PendingDelegationRequests, + /// Status for this delegator + pub status: DelegatorStatus, + } + + // CollatorSnapshot + + #[deprecated(note = "use CollatorSnapshot with BondWithAutoCompound delegations")] + #[derive(Encode, Decode, RuntimeDebug, TypeInfo)] + /// Snapshot of collator state at the start of the round for which they are selected + pub struct CollatorSnapshot { + /// The total value locked by the collator. + pub bond: Balance, + + /// The rewardable delegations. This list is a subset of total delegators, where certain + /// delegators are adjusted based on their scheduled + /// [DelegationChange::Revoke] or [DelegationChange::Decrease] action. + pub delegations: Vec>, + + /// The total counted value locked for the collator, including the self bond + total staked by + /// top delegators. + pub total: Balance, + } + + impl PartialEq for CollatorSnapshot { + fn eq(&self, other: &Self) -> bool { + let must_be_true = self.bond == other.bond && self.total == other.total; + if !must_be_true { + return false + } + for (Bond { owner: o1, amount: a1 }, Bond { owner: o2, amount: a2 }) in + self.delegations.iter().zip(other.delegations.iter()) + { + if o1 != o2 || a1 != a2 { + return false + } + } + true + } + } + + impl Default for CollatorSnapshot { + fn default() -> CollatorSnapshot { + CollatorSnapshot { bond: B::default(), delegations: Vec::new(), total: B::default() } + } + } +} + +#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] +/// DEPRECATED in favor of Delegator +/// Nominator state +pub struct Nominator2 { + /// All current delegations + pub delegations: OrderedSet>, + /// Delegations scheduled to be revoked + pub revocations: OrderedSet, + /// Total balance locked for this nominator + pub total: Balance, + /// Total number of revocations scheduled to be executed + pub scheduled_revocations_count: u32, + /// Total amount to be unbonded once revocations are executed + pub scheduled_revocations_total: Balance, + /// Status for this nominator + pub status: DelegatorStatus, +} + +// /// Temporary function to migrate state +// pub(crate) fn migrate_nominator_to_delegator_state( +// id: T::AccountId, +// nominator: Nominator2>, +// ) -> Delegator> { +// Delegator { +// id, +// delegations: nominator.delegations, +// total: nominator.total, +// requests: PendingDelegationRequests::new(), +// status: nominator.status, +// } +// } + +#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] +/// The current round index and transition information +pub struct RoundInfo { + /// Current round index + pub current: RoundIndex, + /// The first block of the current round + pub first: BlockNumber, + /// The length of the current round in number of blocks + pub length: u32, +} +impl< + B: Copy + sp_std::ops::Add + sp_std::ops::Sub + From + PartialOrd, + > RoundInfo +{ + pub fn new(current: RoundIndex, first: B, length: u32) -> RoundInfo { + RoundInfo { current, first, length } + } + /// Check if the round should be updated + pub fn should_update(&self, now: B) -> bool { + now - self.first >= self.length.into() + } + /// New round + pub fn update(&mut self, now: B) { + self.current = self.current.saturating_add(1u32); + self.first = now; + } +} +impl< + B: Copy + sp_std::ops::Add + sp_std::ops::Sub + From + PartialOrd, + > Default for RoundInfo +{ + fn default() -> RoundInfo { + RoundInfo::new(1u32, 1u32.into(), 20u32) + } +} + +#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] +/// Reserve information { account, percent_of_inflation } +pub struct ParachainBondConfig { + /// Account which receives funds intended for parachain bond + pub account: AccountId, + /// Percent of inflation set aside for parachain bond account + pub percent: Percent, +} +impl Default for ParachainBondConfig { + fn default() -> ParachainBondConfig { + ParachainBondConfig { + account: A::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) + .expect("infinite length input; no invalid inputs for type; qed"), + percent: Percent::zero(), + } + } +} + +pub enum BondAdjust { + Increase(Balance), + Decrease, +} diff --git a/pallets/parachain-staking/src/weights.rs b/pallets/parachain-staking/src/weights.rs new file mode 100644 index 000000000..ac72c2bb6 --- /dev/null +++ b/pallets/parachain-staking/src/weights.rs @@ -0,0 +1,1418 @@ +// Copyright 2019-2022 PureStake Inc. +// This file is part of Moonbeam. + +// Moonbeam 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. + +// Moonbeam 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 Moonbeam. If not, see . + + +//! Autogenerated weights for parachain_staking +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-04-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `benchmarker`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 + +// Executed Command: +// ./target/release/moonbeam +// benchmark +// pallet +// --execution=wasm +// --wasm-execution=compiled +// --pallet +// * +// --extrinsic +// * +// --steps +// 50 +// --repeat +// 20 +// --template=./benchmarking/frame-weight-template.hbs +// --json-file +// raw.json +// --output +// weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for parachain_staking. +pub trait WeightInfo { + fn set_staking_expectations() -> Weight; + fn set_inflation() -> Weight; + fn set_parachain_bond_account() -> Weight; + fn set_parachain_bond_reserve_percent() -> Weight; + fn set_total_selected() -> Weight; + fn set_collator_commission() -> Weight; + fn set_blocks_per_round() -> Weight; + fn join_candidates(x: u32, ) -> Weight; + fn schedule_leave_candidates(x: u32, ) -> Weight; + fn execute_leave_candidates(x: u32, ) -> Weight; + fn cancel_leave_candidates(x: u32, ) -> Weight; + fn go_offline() -> Weight; + fn go_online() -> Weight; + fn candidate_bond_more() -> Weight; + fn schedule_candidate_bond_less() -> Weight; + fn execute_candidate_bond_less() -> Weight; + fn cancel_candidate_bond_less() -> Weight; + fn delegate(x: u32, y: u32, ) -> Weight; + fn schedule_leave_delegators() -> Weight; + fn execute_leave_delegators(x: u32, ) -> Weight; + fn cancel_leave_delegators() -> Weight; + fn schedule_revoke_delegation() -> Weight; + fn delegator_bond_more() -> Weight; + fn schedule_delegator_bond_less() -> Weight; + fn execute_revoke_delegation() -> Weight; + fn execute_delegator_bond_less() -> Weight; + fn cancel_revoke_delegation() -> Weight; + fn cancel_delegator_bond_less() -> Weight; + fn prepare_staking_payouts() -> Weight; + fn get_rewardable_delegators(y: u32, ) -> Weight; + fn select_top_candidates(x: u32, y: u32, ) -> Weight; + fn pay_one_collator_reward(y: u32, ) -> Weight; + fn base_on_initialize() -> Weight; + fn set_auto_compound(x: u32, y: u32, ) -> Weight; + fn delegate_with_auto_compound(x: u32, y: u32, z: u32, ) -> Weight; + fn mint_collator_reward() -> Weight; +} + +/// Weights for parachain_staking using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: ParachainStaking InflationConfig (r:1 w:1) + /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) + fn set_staking_expectations() -> Weight { + // Proof Size summary in bytes: + // Measured: `88` + // Estimated: `1573` + // Minimum execution time: 18_070_000 picoseconds. + Weight::from_parts(18_325_000, 1573) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: ParachainStaking InflationConfig (r:1 w:1) + /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) + fn set_inflation() -> Weight { + // Proof Size summary in bytes: + // Measured: `88` + // Estimated: `1573` + // Minimum execution time: 47_600_000 picoseconds. + Weight::from_parts(48_094_000, 1573) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: ParachainStaking ParachainBondInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking ParachainBondInfo (max_values: Some(1), max_size: None, mode: Measured) + fn set_parachain_bond_account() -> Weight { + // Proof Size summary in bytes: + // Measured: `6` + // Estimated: `1491` + // Minimum execution time: 15_818_000 picoseconds. + Weight::from_parts(16_256_000, 1491) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: ParachainStaking ParachainBondInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking ParachainBondInfo (max_values: Some(1), max_size: None, mode: Measured) + fn set_parachain_bond_reserve_percent() -> Weight { + // Proof Size summary in bytes: + // Measured: `6` + // Estimated: `1491` + // Minimum execution time: 15_327_000 picoseconds. + Weight::from_parts(15_488_000, 1491) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: ParachainStaking TotalSelected (r:1 w:1) + /// Proof Skipped: ParachainStaking TotalSelected (max_values: Some(1), max_size: None, mode: Measured) + fn set_total_selected() -> Weight { + // Proof Size summary in bytes: + // Measured: `28` + // Estimated: `1513` + // Minimum execution time: 16_629_000 picoseconds. + Weight::from_parts(17_245_000, 1513) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: ParachainStaking CollatorCommission (r:1 w:1) + /// Proof Skipped: ParachainStaking CollatorCommission (max_values: Some(1), max_size: None, mode: Measured) + fn set_collator_commission() -> Weight { + // Proof Size summary in bytes: + // Measured: `27` + // Estimated: `1512` + // Minimum execution time: 15_586_000 picoseconds. + Weight::from_parts(16_060_000, 1512) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: ParachainStaking TotalSelected (r:1 w:0) + /// Proof Skipped: ParachainStaking TotalSelected (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking InflationConfig (r:1 w:1) + /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) + fn set_blocks_per_round() -> Weight { + // Proof Size summary in bytes: + // Measured: `116` + // Estimated: `3202` + // Minimum execution time: 52_085_000 picoseconds. + Weight::from_parts(52_439_000, 3202) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegatorState (r:1 w:0) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:0 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking BottomDelegations (r:0 w:1) + /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[3, 1000]`. + fn join_candidates(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1821 + x * (37 ±0)` + // Estimated: `27743 + x * (228 ±0)` + // Minimum execution time: 62_721_000 picoseconds. + Weight::from_parts(59_951_661, 27743) + // Standard Error: 1_080 + .saturating_add(Weight::from_parts(83_856, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + .saturating_add(Weight::from_parts(0, 228).saturating_mul(x.into())) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `x` is `[3, 1000]`. + fn schedule_leave_candidates(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `865 + x * (36 ±0)` + // Estimated: `6542 + x * (74 ±0)` + // Minimum execution time: 29_088_000 picoseconds. + Weight::from_parts(23_948_090, 6542) + // Standard Error: 1_107 + .saturating_add(Weight::from_parts(72_705, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(Weight::from_parts(0, 74).saturating_mul(x.into())) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegatorState (r:349 w:349) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:350 w:350) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: System Account (r:350 w:350) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking BottomDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `x` is `[2, 350]`. + fn execute_leave_candidates(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `979 + x * (431 ±0)` + // Estimated: `30725 + x * (11823 ±0)` + // Minimum execution time: 102_273_000 picoseconds. + Weight::from_parts(102_546_000, 30725) + // Standard Error: 76_720 + .saturating_add(Weight::from_parts(33_831_394, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(x.into()))) + .saturating_add(T::DbWeight::get().writes(5_u64)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(x.into()))) + .saturating_add(Weight::from_parts(0, 11823).saturating_mul(x.into())) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `x` is `[3, 1000]`. + fn cancel_leave_candidates(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `833 + x * (36 ±0)` + // Estimated: `6478 + x * (74 ±0)` + // Minimum execution time: 28_142_000 picoseconds. + Weight::from_parts(22_767_262, 6478) + // Standard Error: 1_102 + .saturating_add(Weight::from_parts(73_806, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(Weight::from_parts(0, 74).saturating_mul(x.into())) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + fn go_offline() -> Weight { + // Proof Size summary in bytes: + // Measured: `271` + // Estimated: `5492` + // Minimum execution time: 27_523_000 picoseconds. + Weight::from_parts(27_792_000, 5492) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + fn go_online() -> Weight { + // Proof Size summary in bytes: + // Measured: `234` + // Estimated: `5418` + // Minimum execution time: 27_667_000 picoseconds. + Weight::from_parts(27_972_000, 5418) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + fn candidate_bond_more() -> Weight { + // Proof Size summary in bytes: + // Measured: `527` + // Estimated: `16349` + // Minimum execution time: 56_424_000 picoseconds. + Weight::from_parts(57_028_000, 16349) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + fn schedule_candidate_bond_less() -> Weight { + // Proof Size summary in bytes: + // Measured: `171` + // Estimated: `3636` + // Minimum execution time: 22_764_000 picoseconds. + Weight::from_parts(23_511_000, 3636) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + fn execute_candidate_bond_less() -> Weight { + // Proof Size summary in bytes: + // Measured: `547` + // Estimated: `16409` + // Minimum execution time: 55_133_000 picoseconds. + Weight::from_parts(55_704_000, 16409) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(5_u64)) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + fn cancel_candidate_bond_less() -> Weight { + // Proof Size summary in bytes: + // Measured: `191` + // Estimated: `3656` + // Minimum execution time: 20_773_000 picoseconds. + Weight::from_parts(21_485_000, 3656) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `x` is `[3, 100]`. + /// The range of component `y` is `[2, 300]`. + fn delegate(x: u32, y: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `2479 + x * (79 ±0) + y * (38 ±0)` + // Estimated: `32988 + x * (405 ±0) + y * (195 ±0)` + // Minimum execution time: 94_976_000 picoseconds. + Weight::from_parts(83_764_148, 32988) + // Standard Error: 1_433 + .saturating_add(Weight::from_parts(154_670, 0).saturating_mul(x.into())) + // Standard Error: 470 + .saturating_add(Weight::from_parts(48_242, 0).saturating_mul(y.into())) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + .saturating_add(Weight::from_parts(0, 405).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 195).saturating_mul(y.into())) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + fn schedule_leave_delegators() -> Weight { + // Proof Size summary in bytes: + // Measured: `107` + // Estimated: `7144` + // Minimum execution time: 28_255_000 picoseconds. + Weight::from_parts(28_539_000, 7144) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:99 w:99) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:99 w:99) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:99 w:99) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:99 w:0) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// The range of component `x` is `[2, 100]`. + fn execute_leave_delegators(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `824 + x * (376 ±0)` + // Estimated: `34626 + x * (12238 ±1)` + // Minimum execution time: 88_582_000 picoseconds. + Weight::from_parts(88_972_000, 34626) + // Standard Error: 40_214 + .saturating_add(Weight::from_parts(30_393_572, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(x.into()))) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(x.into()))) + .saturating_add(Weight::from_parts(0, 12238).saturating_mul(x.into())) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + fn cancel_leave_delegators() -> Weight { + // Proof Size summary in bytes: + // Measured: `173` + // Estimated: `7276` + // Minimum execution time: 30_396_000 picoseconds. + Weight::from_parts(30_758_000, 7276) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + fn schedule_revoke_delegation() -> Weight { + // Proof Size summary in bytes: + // Measured: `107` + // Estimated: `7144` + // Minimum execution time: 27_434_000 picoseconds. + Weight::from_parts(27_725_000, 7144) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + fn delegator_bond_more() -> Weight { + // Proof Size summary in bytes: + // Measured: `843` + // Estimated: `30221` + // Minimum execution time: 76_944_000 picoseconds. + Weight::from_parts(77_695_000, 30221) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(7_u64)) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + fn schedule_delegator_bond_less() -> Weight { + // Proof Size summary in bytes: + // Measured: `107` + // Estimated: `7144` + // Minimum execution time: 27_633_000 picoseconds. + Weight::from_parts(27_950_000, 7144) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + fn execute_revoke_delegation() -> Weight { + // Proof Size summary in bytes: + // Measured: `964` + // Estimated: `35376` + // Minimum execution time: 92_054_000 picoseconds. + Weight::from_parts(93_161_000, 35376) + .saturating_add(T::DbWeight::get().reads(9_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + fn execute_delegator_bond_less() -> Weight { + // Proof Size summary in bytes: + // Measured: `909` + // Estimated: `30617` + // Minimum execution time: 77_509_000 picoseconds. + Weight::from_parts(78_070_000, 30617) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + fn cancel_revoke_delegation() -> Weight { + // Proof Size summary in bytes: + // Measured: `173` + // Estimated: `7276` + // Minimum execution time: 27_469_000 picoseconds. + Weight::from_parts(28_047_000, 7276) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + fn cancel_delegator_bond_less() -> Weight { + // Proof Size summary in bytes: + // Measured: `173` + // Estimated: `7276` + // Minimum execution time: 28_572_000 picoseconds. + Weight::from_parts(28_806_000, 7276) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(2_u64)) + } + /// Storage: ParachainStaking Points (r:1 w:0) + /// Proof Skipped: ParachainStaking Points (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking Staked (r:1 w:1) + /// Proof Skipped: ParachainStaking Staked (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking InflationConfig (r:1 w:0) + /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking ParachainBondInfo (r:1 w:0) + /// Proof Skipped: ParachainStaking ParachainBondInfo (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking CollatorCommission (r:1 w:0) + /// Proof Skipped: ParachainStaking CollatorCommission (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking DelayedPayouts (r:0 w:1) + /// Proof Skipped: ParachainStaking DelayedPayouts (max_values: None, max_size: None, mode: Measured) + fn prepare_staking_payouts() -> Weight { + // Proof Size summary in bytes: + // Measured: `380` + // Estimated: `17246` + // Minimum execution time: 43_338_000 picoseconds. + Weight::from_parts(43_786_000, 17246) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().writes(3_u64)) + } + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:0) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// The range of component `y` is `[0, 100]`. + fn get_rewardable_delegators(y: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `73 + y * (36 ±0)` + // Estimated: `7074 + y * (72 ±0)` + // Minimum execution time: 8_392_000 picoseconds. + Weight::from_parts(9_785_180, 7074) + // Standard Error: 388 + .saturating_add(Weight::from_parts(24_123, 0).saturating_mul(y.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(Weight::from_parts(0, 72).saturating_mul(y.into())) + } + /// Storage: ParachainStaking TotalSelected (r:1 w:0) + /// Proof Skipped: ParachainStaking TotalSelected (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:0) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:51 w:0) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:51 w:0) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:51 w:0) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:51 w:0) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking SelectedCandidates (r:0 w:1) + /// Proof Skipped: ParachainStaking SelectedCandidates (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking AtStake (r:0 w:51) + /// Proof Skipped: ParachainStaking AtStake (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[0, 50]`. + /// The range of component `y` is `[0, 100]`. + fn select_top_candidates(x: u32, y: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0 + x * (3816 ±0) + y * (1800 ±0)` + // Estimated: `18950 + x * (21900 ±39) + y * (5112 ±19)` + // Minimum execution time: 32_303_000 picoseconds. + Weight::from_parts(32_680_000, 18950) + // Standard Error: 82_316 + .saturating_add(Weight::from_parts(23_158_353, 0).saturating_mul(x.into())) + // Standard Error: 41_048 + .saturating_add(Weight::from_parts(1_334_029, 0).saturating_mul(y.into())) + .saturating_add(T::DbWeight::get().reads(6_u64)) + .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(x.into()))) + .saturating_add(T::DbWeight::get().writes(2_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(x.into()))) + .saturating_add(Weight::from_parts(0, 21900).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 5112).saturating_mul(y.into())) + } + /// Storage: ParachainStaking DelayedPayouts (r:1 w:0) + /// Proof Skipped: ParachainStaking DelayedPayouts (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking Points (r:1 w:0) + /// Proof Skipped: ParachainStaking Points (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AtStake (r:2 w:1) + /// Proof Skipped: ParachainStaking AtStake (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AwardedPts (r:1 w:1) + /// Proof Skipped: ParachainStaking AwardedPts (max_values: None, max_size: None, mode: Measured) + /// Storage: MoonbeamOrbiters OrbiterPerRound (r:1 w:0) + /// Proof Skipped: MoonbeamOrbiters OrbiterPerRound (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:301 w:301) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// The range of component `y` is `[0, 300]`. + fn pay_one_collator_reward(y: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1132 + y * (160 ±0)` + // Estimated: `28331 + y * (3396 ±0)` + // Minimum execution time: 58_105_000 picoseconds. + Weight::from_parts(53_052_308, 28331) + // Standard Error: 6_526 + .saturating_add(Weight::from_parts(19_017_961, 0).saturating_mul(y.into())) + .saturating_add(T::DbWeight::get().reads(7_u64)) + .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(y.into()))) + .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(y.into()))) + .saturating_add(Weight::from_parts(0, 3396).saturating_mul(y.into())) + } + fn base_on_initialize() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_008_000 picoseconds. + Weight::from_parts(2_065_000, 0) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:0) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[0, 300]`. + /// The range of component `y` is `[0, 100]`. + fn set_auto_compound(x: u32, y: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `671 + x * (22 ±0) + y * (36 ±0)` + // Estimated: `8054 + x * (46 ±0) + y * (72 ±0)` + // Minimum execution time: 29_102_000 picoseconds. + Weight::from_parts(26_155_259, 8054) + // Standard Error: 278 + .saturating_add(Weight::from_parts(49_717, 0).saturating_mul(x.into())) + // Standard Error: 833 + .saturating_add(Weight::from_parts(48_123, 0).saturating_mul(y.into())) + .saturating_add(T::DbWeight::get().reads(2_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + .saturating_add(Weight::from_parts(0, 46).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 72).saturating_mul(y.into())) + } + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking BottomDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `x` is `[0, 350]`. + /// The range of component `y` is `[0, 350]`. + /// The range of component `z` is `[0, 100]`. + fn delegate_with_auto_compound(x: u32, y: u32, z: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0 + x * (58 ±0) + y * (21 ±0) + z * (41 ±0)` + // Estimated: `59323 + x * (145 ±0) + y * (132 ±0) + z * (873144491150315 ±3)` + // Minimum execution time: 100_647_000 picoseconds. + Weight::from_parts(84_809_337, 59323) + // Standard Error: 1_211 + .saturating_add(Weight::from_parts(15_186, 0).saturating_mul(x.into())) + // Standard Error: 1_211 + .saturating_add(Weight::from_parts(30_270, 0).saturating_mul(y.into())) + // Standard Error: 4_227 + .saturating_add(Weight::from_parts(173_069, 0).saturating_mul(z.into())) + .saturating_add(T::DbWeight::get().reads(8_u64)) + .saturating_add(T::DbWeight::get().writes(8_u64)) + .saturating_add(Weight::from_parts(0, 145).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 132).saturating_mul(y.into())) + .saturating_add(Weight::from_parts(0, 307).saturating_mul(z.into())) + } + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn mint_collator_reward() -> Weight { + // Proof Size summary in bytes: + // Measured: `128` + // Estimated: `3581` + // Minimum execution time: 24_224_000 picoseconds. + Weight::from_parts(24_514_000, 3581) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + /// Storage: ParachainStaking InflationConfig (r:1 w:1) + /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) + fn set_staking_expectations() -> Weight { + // Proof Size summary in bytes: + // Measured: `88` + // Estimated: `1573` + // Minimum execution time: 18_070_000 picoseconds. + Weight::from_parts(18_325_000, 1573) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: ParachainStaking InflationConfig (r:1 w:1) + /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) + fn set_inflation() -> Weight { + // Proof Size summary in bytes: + // Measured: `88` + // Estimated: `1573` + // Minimum execution time: 47_600_000 picoseconds. + Weight::from_parts(48_094_000, 1573) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: ParachainStaking ParachainBondInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking ParachainBondInfo (max_values: Some(1), max_size: None, mode: Measured) + fn set_parachain_bond_account() -> Weight { + // Proof Size summary in bytes: + // Measured: `6` + // Estimated: `1491` + // Minimum execution time: 15_818_000 picoseconds. + Weight::from_parts(16_256_000, 1491) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: ParachainStaking ParachainBondInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking ParachainBondInfo (max_values: Some(1), max_size: None, mode: Measured) + fn set_parachain_bond_reserve_percent() -> Weight { + // Proof Size summary in bytes: + // Measured: `6` + // Estimated: `1491` + // Minimum execution time: 15_327_000 picoseconds. + Weight::from_parts(15_488_000, 1491) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: ParachainStaking TotalSelected (r:1 w:1) + /// Proof Skipped: ParachainStaking TotalSelected (max_values: Some(1), max_size: None, mode: Measured) + fn set_total_selected() -> Weight { + // Proof Size summary in bytes: + // Measured: `28` + // Estimated: `1513` + // Minimum execution time: 16_629_000 picoseconds. + Weight::from_parts(17_245_000, 1513) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: ParachainStaking CollatorCommission (r:1 w:1) + /// Proof Skipped: ParachainStaking CollatorCommission (max_values: Some(1), max_size: None, mode: Measured) + fn set_collator_commission() -> Weight { + // Proof Size summary in bytes: + // Measured: `27` + // Estimated: `1512` + // Minimum execution time: 15_586_000 picoseconds. + Weight::from_parts(16_060_000, 1512) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: ParachainStaking TotalSelected (r:1 w:0) + /// Proof Skipped: ParachainStaking TotalSelected (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking InflationConfig (r:1 w:1) + /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) + fn set_blocks_per_round() -> Weight { + // Proof Size summary in bytes: + // Measured: `116` + // Estimated: `3202` + // Minimum execution time: 52_085_000 picoseconds. + Weight::from_parts(52_439_000, 3202) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegatorState (r:1 w:0) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:0 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking BottomDelegations (r:0 w:1) + /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[3, 1000]`. + fn join_candidates(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1821 + x * (37 ±0)` + // Estimated: `27743 + x * (228 ±0)` + // Minimum execution time: 62_721_000 picoseconds. + Weight::from_parts(59_951_661, 27743) + // Standard Error: 1_080 + .saturating_add(Weight::from_parts(83_856, 0).saturating_mul(x.into())) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) + .saturating_add(Weight::from_parts(0, 228).saturating_mul(x.into())) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `x` is `[3, 1000]`. + fn schedule_leave_candidates(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `865 + x * (36 ±0)` + // Estimated: `6542 + x * (74 ±0)` + // Minimum execution time: 29_088_000 picoseconds. + Weight::from_parts(23_948_090, 6542) + // Standard Error: 1_107 + .saturating_add(Weight::from_parts(72_705, 0).saturating_mul(x.into())) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(Weight::from_parts(0, 74).saturating_mul(x.into())) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegatorState (r:349 w:349) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:350 w:350) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: System Account (r:350 w:350) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking BottomDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `x` is `[2, 350]`. + fn execute_leave_candidates(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `979 + x * (431 ±0)` + // Estimated: `30725 + x * (11823 ±0)` + // Minimum execution time: 102_273_000 picoseconds. + Weight::from_parts(102_546_000, 30725) + // Standard Error: 76_720 + .saturating_add(Weight::from_parts(33_831_394, 0).saturating_mul(x.into())) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(x.into()))) + .saturating_add(RocksDbWeight::get().writes(5_u64)) + .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(x.into()))) + .saturating_add(Weight::from_parts(0, 11823).saturating_mul(x.into())) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `x` is `[3, 1000]`. + fn cancel_leave_candidates(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `833 + x * (36 ±0)` + // Estimated: `6478 + x * (74 ±0)` + // Minimum execution time: 28_142_000 picoseconds. + Weight::from_parts(22_767_262, 6478) + // Standard Error: 1_102 + .saturating_add(Weight::from_parts(73_806, 0).saturating_mul(x.into())) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(Weight::from_parts(0, 74).saturating_mul(x.into())) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + fn go_offline() -> Weight { + // Proof Size summary in bytes: + // Measured: `271` + // Estimated: `5492` + // Minimum execution time: 27_523_000 picoseconds. + Weight::from_parts(27_792_000, 5492) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + fn go_online() -> Weight { + // Proof Size summary in bytes: + // Measured: `234` + // Estimated: `5418` + // Minimum execution time: 27_667_000 picoseconds. + Weight::from_parts(27_972_000, 5418) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + fn candidate_bond_more() -> Weight { + // Proof Size summary in bytes: + // Measured: `527` + // Estimated: `16349` + // Minimum execution time: 56_424_000 picoseconds. + Weight::from_parts(57_028_000, 16349) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + fn schedule_candidate_bond_less() -> Weight { + // Proof Size summary in bytes: + // Measured: `171` + // Estimated: `3636` + // Minimum execution time: 22_764_000 picoseconds. + Weight::from_parts(23_511_000, 3636) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + fn execute_candidate_bond_less() -> Weight { + // Proof Size summary in bytes: + // Measured: `547` + // Estimated: `16409` + // Minimum execution time: 55_133_000 picoseconds. + Weight::from_parts(55_704_000, 16409) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(5_u64)) + } + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + fn cancel_candidate_bond_less() -> Weight { + // Proof Size summary in bytes: + // Measured: `191` + // Estimated: `3656` + // Minimum execution time: 20_773_000 picoseconds. + Weight::from_parts(21_485_000, 3656) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `x` is `[3, 100]`. + /// The range of component `y` is `[2, 300]`. + fn delegate(x: u32, y: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `2479 + x * (79 ±0) + y * (38 ±0)` + // Estimated: `32988 + x * (405 ±0) + y * (195 ±0)` + // Minimum execution time: 94_976_000 picoseconds. + Weight::from_parts(83_764_148, 32988) + // Standard Error: 1_433 + .saturating_add(Weight::from_parts(154_670, 0).saturating_mul(x.into())) + // Standard Error: 470 + .saturating_add(Weight::from_parts(48_242, 0).saturating_mul(y.into())) + .saturating_add(RocksDbWeight::get().reads(7_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) + .saturating_add(Weight::from_parts(0, 405).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 195).saturating_mul(y.into())) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + fn schedule_leave_delegators() -> Weight { + // Proof Size summary in bytes: + // Measured: `107` + // Estimated: `7144` + // Minimum execution time: 28_255_000 picoseconds. + Weight::from_parts(28_539_000, 7144) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:99 w:99) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:99 w:99) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:99 w:99) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:99 w:0) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// The range of component `x` is `[2, 100]`. + fn execute_leave_delegators(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `824 + x * (376 ±0)` + // Estimated: `34626 + x * (12238 ±1)` + // Minimum execution time: 88_582_000 picoseconds. + Weight::from_parts(88_972_000, 34626) + // Standard Error: 40_214 + .saturating_add(Weight::from_parts(30_393_572, 0).saturating_mul(x.into())) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(x.into()))) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(x.into()))) + .saturating_add(Weight::from_parts(0, 12238).saturating_mul(x.into())) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + fn cancel_leave_delegators() -> Weight { + // Proof Size summary in bytes: + // Measured: `173` + // Estimated: `7276` + // Minimum execution time: 30_396_000 picoseconds. + Weight::from_parts(30_758_000, 7276) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + fn schedule_revoke_delegation() -> Weight { + // Proof Size summary in bytes: + // Measured: `107` + // Estimated: `7144` + // Minimum execution time: 27_434_000 picoseconds. + Weight::from_parts(27_725_000, 7144) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + fn delegator_bond_more() -> Weight { + // Proof Size summary in bytes: + // Measured: `843` + // Estimated: `30221` + // Minimum execution time: 76_944_000 picoseconds. + Weight::from_parts(77_695_000, 30221) + .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(RocksDbWeight::get().writes(7_u64)) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + fn schedule_delegator_bond_less() -> Weight { + // Proof Size summary in bytes: + // Measured: `107` + // Estimated: `7144` + // Minimum execution time: 27_633_000 picoseconds. + Weight::from_parts(27_950_000, 7144) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + fn execute_revoke_delegation() -> Weight { + // Proof Size summary in bytes: + // Measured: `964` + // Estimated: `35376` + // Minimum execution time: 92_054_000 picoseconds. + Weight::from_parts(93_161_000, 35376) + .saturating_add(RocksDbWeight::get().reads(9_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + fn execute_delegator_bond_less() -> Weight { + // Proof Size summary in bytes: + // Measured: `909` + // Estimated: `30617` + // Minimum execution time: 77_509_000 picoseconds. + Weight::from_parts(78_070_000, 30617) + .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + fn cancel_revoke_delegation() -> Weight { + // Proof Size summary in bytes: + // Measured: `173` + // Estimated: `7276` + // Minimum execution time: 27_469_000 picoseconds. + Weight::from_parts(28_047_000, 7276) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + fn cancel_delegator_bond_less() -> Weight { + // Proof Size summary in bytes: + // Measured: `173` + // Estimated: `7276` + // Minimum execution time: 28_572_000 picoseconds. + Weight::from_parts(28_806_000, 7276) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + } + /// Storage: ParachainStaking Points (r:1 w:0) + /// Proof Skipped: ParachainStaking Points (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking Staked (r:1 w:1) + /// Proof Skipped: ParachainStaking Staked (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking InflationConfig (r:1 w:0) + /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking ParachainBondInfo (r:1 w:0) + /// Proof Skipped: ParachainStaking ParachainBondInfo (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking CollatorCommission (r:1 w:0) + /// Proof Skipped: ParachainStaking CollatorCommission (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking DelayedPayouts (r:0 w:1) + /// Proof Skipped: ParachainStaking DelayedPayouts (max_values: None, max_size: None, mode: Measured) + fn prepare_staking_payouts() -> Weight { + // Proof Size summary in bytes: + // Measured: `380` + // Estimated: `17246` + // Minimum execution time: 43_338_000 picoseconds. + Weight::from_parts(43_786_000, 17246) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().writes(3_u64)) + } + /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:0) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// The range of component `y` is `[0, 100]`. + fn get_rewardable_delegators(y: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `73 + y * (36 ±0)` + // Estimated: `7074 + y * (72 ±0)` + // Minimum execution time: 8_392_000 picoseconds. + Weight::from_parts(9_785_180, 7074) + // Standard Error: 388 + .saturating_add(Weight::from_parts(24_123, 0).saturating_mul(y.into())) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(Weight::from_parts(0, 72).saturating_mul(y.into())) + } + /// Storage: ParachainStaking TotalSelected (r:1 w:0) + /// Proof Skipped: ParachainStaking TotalSelected (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:0) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:51 w:0) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking DelegationScheduledRequests (r:51 w:0) + /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:51 w:0) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:51 w:0) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking SelectedCandidates (r:0 w:1) + /// Proof Skipped: ParachainStaking SelectedCandidates (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking AtStake (r:0 w:51) + /// Proof Skipped: ParachainStaking AtStake (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[0, 50]`. + /// The range of component `y` is `[0, 100]`. + fn select_top_candidates(x: u32, y: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0 + x * (3816 ±0) + y * (1800 ±0)` + // Estimated: `18950 + x * (21900 ±39) + y * (5112 ±19)` + // Minimum execution time: 32_303_000 picoseconds. + Weight::from_parts(32_680_000, 18950) + // Standard Error: 82_316 + .saturating_add(Weight::from_parts(23_158_353, 0).saturating_mul(x.into())) + // Standard Error: 41_048 + .saturating_add(Weight::from_parts(1_334_029, 0).saturating_mul(y.into())) + .saturating_add(RocksDbWeight::get().reads(6_u64)) + .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(x.into()))) + .saturating_add(RocksDbWeight::get().writes(2_u64)) + .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(x.into()))) + .saturating_add(Weight::from_parts(0, 21900).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 5112).saturating_mul(y.into())) + } + /// Storage: ParachainStaking DelayedPayouts (r:1 w:0) + /// Proof Skipped: ParachainStaking DelayedPayouts (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking Points (r:1 w:0) + /// Proof Skipped: ParachainStaking Points (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AtStake (r:2 w:1) + /// Proof Skipped: ParachainStaking AtStake (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AwardedPts (r:1 w:1) + /// Proof Skipped: ParachainStaking AwardedPts (max_values: None, max_size: None, mode: Measured) + /// Storage: MoonbeamOrbiters OrbiterPerRound (r:1 w:0) + /// Proof Skipped: MoonbeamOrbiters OrbiterPerRound (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:301 w:301) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// The range of component `y` is `[0, 300]`. + fn pay_one_collator_reward(y: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1132 + y * (160 ±0)` + // Estimated: `28331 + y * (3396 ±0)` + // Minimum execution time: 58_105_000 picoseconds. + Weight::from_parts(53_052_308, 28331) + // Standard Error: 6_526 + .saturating_add(Weight::from_parts(19_017_961, 0).saturating_mul(y.into())) + .saturating_add(RocksDbWeight::get().reads(7_u64)) + .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(y.into()))) + .saturating_add(RocksDbWeight::get().writes(3_u64)) + .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(y.into()))) + .saturating_add(Weight::from_parts(0, 3396).saturating_mul(y.into())) + } + fn base_on_initialize() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 2_008_000 picoseconds. + Weight::from_parts(2_065_000, 0) + } + /// Storage: ParachainStaking DelegatorState (r:1 w:0) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// The range of component `x` is `[0, 300]`. + /// The range of component `y` is `[0, 100]`. + fn set_auto_compound(x: u32, y: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `671 + x * (22 ±0) + y * (36 ±0)` + // Estimated: `8054 + x * (46 ±0) + y * (72 ±0)` + // Minimum execution time: 29_102_000 picoseconds. + Weight::from_parts(26_155_259, 8054) + // Standard Error: 278 + .saturating_add(Weight::from_parts(49_717, 0).saturating_mul(x.into())) + // Standard Error: 833 + .saturating_add(Weight::from_parts(48_123, 0).saturating_mul(y.into())) + .saturating_add(RocksDbWeight::get().reads(2_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + .saturating_add(Weight::from_parts(0, 46).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 72).saturating_mul(y.into())) + } + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + /// Storage: ParachainStaking DelegatorState (r:1 w:1) + /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidateInfo (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking BottomDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) + /// Storage: ParachainStaking Total (r:1 w:1) + /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainStaking TopDelegations (r:1 w:1) + /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) + /// Storage: ParachainStaking CandidatePool (r:1 w:1) + /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) + /// The range of component `x` is `[0, 350]`. + /// The range of component `y` is `[0, 350]`. + /// The range of component `z` is `[0, 100]`. + fn delegate_with_auto_compound(x: u32, y: u32, z: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `0 + x * (58 ±0) + y * (21 ±0) + z * (41 ±0)` + // Estimated: `59323 + x * (145 ±0) + y * (132 ±0) + z * (873144491150315 ±3)` + // Minimum execution time: 100_647_000 picoseconds. + Weight::from_parts(84_809_337, 59323) + // Standard Error: 1_211 + .saturating_add(Weight::from_parts(15_186, 0).saturating_mul(x.into())) + // Standard Error: 1_211 + .saturating_add(Weight::from_parts(30_270, 0).saturating_mul(y.into())) + // Standard Error: 4_227 + .saturating_add(Weight::from_parts(173_069, 0).saturating_mul(z.into())) + .saturating_add(RocksDbWeight::get().reads(8_u64)) + .saturating_add(RocksDbWeight::get().writes(8_u64)) + .saturating_add(Weight::from_parts(0, 145).saturating_mul(x.into())) + .saturating_add(Weight::from_parts(0, 132).saturating_mul(y.into())) + .saturating_add(Weight::from_parts(0, 307).saturating_mul(z.into())) + } + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) + fn mint_collator_reward() -> Weight { + // Proof Size summary in bytes: + // Measured: `128` + // Estimated: `3581` + // Minimum execution time: 24_224_000 picoseconds. + Weight::from_parts(24_514_000, 3581) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } +} \ No newline at end of file From 4489e8c65001cfee53c035a76376af786d8456ab Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 14 Jul 2023 12:12:57 +0200 Subject: [PATCH 36/80] fix: building using workspace inheritance --- Cargo.lock | 10 +++++----- pallets/parachain-staking/Cargo.toml | 23 +++++++++++++++++------ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 07b6234cd..59c63407c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6239,7 +6239,7 @@ dependencies = [ [[package]] name = "pallet-parachain-staking" -version = "3.0.0" +version = "0.1.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -12684,9 +12684,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.19.12" +version = "0.19.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78" +checksum = "5f8751d9c1b03c6500c387e96f81f815a4f8e72d142d2d4a9ffa6fedd51ddee7" dependencies = [ "indexmap 2.0.0", "serde", @@ -14174,9 +14174,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.4.9" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a2094c43cc94775293eaa0e499fbc30048a6d824ac82c0351a8c0bf9112529" +checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7" dependencies = [ "memchr", ] diff --git a/pallets/parachain-staking/Cargo.toml b/pallets/parachain-staking/Cargo.toml index ef13ae5e2..7b964271a 100644 --- a/pallets/parachain-staking/Cargo.toml +++ b/pallets/parachain-staking/Cargo.toml @@ -1,19 +1,28 @@ [package] name = "pallet-parachain-staking" -description = "parachain staking pallet for collator selection and reward distribution" -edition = "2021" -version = "3.0.0" +description = "prachain staking pallet for collator selection and reward distribution" +authors.workspace = true +documentation.workspace = true +edition.workspace = true +homepage.workspace = true +license-file.workspace = true +readme.workspace = true +repository.workspace = true +version.workspace = true [dependencies] serde = { version = "1", default-features = false, optional = true } log = "0.4" -# Substrate +parity-scale-codec = { workspace = true, features = [ + "derive", +] } +scale-info = { workspace = true, features = ["derive"] } + +# FRAME frame-benchmarking = { workspace = true, optional = true } frame-support.workspace = true frame-system.workspace = true -parity-scale-codec.workspace = true -scale-info.workspace = true sp-runtime.workspace = true sp-std.workspace = true substrate-fixed.workspace = true @@ -44,6 +53,8 @@ std = [ "sp-staking/std", "pallet-authorship/std", "pallet-session/std", + "pallet-balances/std", + "sp-consensus-aura/std" ] runtime-benchmarks = ["frame-benchmarking"] try-runtime = ["frame-support/try-runtime"] From 79a616c7fbf3fe61d30404a4f69d9fecd41aeb34 Mon Sep 17 00:00:00 2001 From: Juan Ignacio RIos Date: Fri, 14 Jul 2023 14:35:47 +0200 Subject: [PATCH 37/80] chore: fmt --- integration-tests/modified-penpal/build.rs | 6 +- integration-tests/modified-penpal/src/lib.rs | 195 +- .../src/weights/block_weights.rs | 5 +- .../src/weights/extrinsic_weights.rs | 10 +- .../modified-penpal/src/xcm_config.rs | 104 +- integration-tests/src/lib.rs | 525 ++-- nodes/parachain/src/chain_spec.rs | 8 +- nodes/parachain/src/chain_spec/base.rs | 54 +- nodes/parachain/src/chain_spec/testnet.rs | 63 +- nodes/parachain/src/cli.rs | 6 +- nodes/parachain/src/command.rs | 48 +- nodes/parachain/src/rpc.rs | 4 +- nodes/parachain/src/service.rs | 98 +- nodes/standalone/src/benchmarking.rs | 32 +- nodes/standalone/src/chain_spec.rs | 17 +- nodes/standalone/src/command.rs | 48 +- nodes/standalone/src/rpc.rs | 4 +- nodes/standalone/src/service.rs | 133 +- pallets/funding/src/benchmarking.rs | 21 +- pallets/funding/src/functions.rs | 376 +-- pallets/funding/src/lib.rs | 49 +- pallets/funding/src/mock.rs | 112 +- pallets/funding/src/tests.rs | 627 ++-- pallets/funding/src/types.rs | 77 +- .../parachain-staking/src/auto_compound.rs | 55 +- pallets/parachain-staking/src/benchmarks.rs | 15 +- .../src/delegation_requests.rs | 164 +- pallets/parachain-staking/src/inflation.rs | 68 +- pallets/parachain-staking/src/lib.rs | 347 +-- pallets/parachain-staking/src/mock.rs | 172 +- pallets/parachain-staking/src/tests.rs | 2542 +++++------------ pallets/parachain-staking/src/traits.rs | 12 +- pallets/parachain-staking/src/types.rs | 282 +- pallets/sandbox/src/lib.rs | 12 +- pallets/sandbox/src/mock.rs | 112 +- pallets/sandbox/src/tests.rs | 23 +- runtimes/base/build.rs | 6 +- runtimes/base/src/lib.rs | 177 +- runtimes/base/src/xcm_config.rs | 84 +- runtimes/shared-configuration/src/fee.rs | 6 +- .../src/weights/block_weights.rs | 5 +- .../src/weights/extrinsic_weights.rs | 10 +- runtimes/standalone/build.rs | 6 +- runtimes/standalone/src/lib.rs | 339 +-- runtimes/testnet/build.rs | 6 +- runtimes/testnet/src/lib.rs | 440 ++- runtimes/testnet/src/xcm_config.rs | 115 +- rustfmt.toml | 9 +- 48 files changed, 2538 insertions(+), 5091 deletions(-) diff --git a/integration-tests/modified-penpal/build.rs b/integration-tests/modified-penpal/build.rs index fe1a2ea91..e02e83524 100644 --- a/integration-tests/modified-penpal/build.rs +++ b/integration-tests/modified-penpal/build.rs @@ -17,9 +17,5 @@ use substrate_wasm_builder::WasmBuilder; fn main() { - WasmBuilder::new() - .with_current_project() - .export_heap_base() - .import_memory() - .build() + WasmBuilder::new().with_current_project().export_heap_base().import_memory().build() } diff --git a/integration-tests/modified-penpal/src/lib.rs b/integration-tests/modified-penpal/src/lib.rs index 0ca13534b..781bfb980 100644 --- a/integration-tests/modified-penpal/src/lib.rs +++ b/integration-tests/modified-penpal/src/lib.rs @@ -123,14 +123,12 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; -pub type Migrations = - (pallet_balances::migration::MigrateToTrackInactive,); +pub type Migrations = (pallet_balances::migration::MigrateToTrackInactive,); /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< @@ -155,6 +153,7 @@ pub type Executive = frame_executive::Executive< pub struct WeightToFee; impl WeightToFeePolynomial for WeightToFee { type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 MILLIUNIT: // in our template, we map to 1/10 of that, or 1/10 MILLIUNIT @@ -282,66 +281,66 @@ parameter_types! { // Configure FRAME pallets to include in runtime. impl frame_system::Config for Runtime { + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; /// The identifier used to distinguish between accounts. type AccountId = AccountId; - /// The aggregated dispatch type that is available for extrinsics. - type RuntimeCall = RuntimeCall; - /// The lookup mechanism to get account ID from whatever is passed in dispatchers. - type Lookup = AccountIdLookup; - /// The index type for storing how many extrinsics an account has signed. - type Index = Index; + /// The basic call filter to use in dispatchable. + type BaseCallFilter = Everything; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + /// The maximum length of a block (in bytes). + type BlockLength = RuntimeBlockLength; /// The index type for blocks. type BlockNumber = BlockNumber; + /// Block & extrinsics weights: base values and limits. + type BlockWeights = RuntimeBlockWeights; + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; /// The type for hashing blocks and tries. type Hash = Hash; /// The hashing algorithm used. type Hashing = BlakeTwo256; /// The header type. type Header = generic::Header; + /// The index type for storing how many extrinsics an account has signed. + type Index = Index; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = AccountIdLookup; + type MaxConsumers = frame_support::traits::ConstU32<16>; + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); + /// What to do if a new account is created. + type OnNewAccount = (); + /// The action to take on a Runtime Upgrade + type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; + /// Converts a module to an index of this module in the runtime. + type PalletInfo = PalletInfo; + /// The aggregated dispatch type that is available for extrinsics. + type RuntimeCall = RuntimeCall; /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; /// The ubiquitous origin type. type RuntimeOrigin = RuntimeOrigin; - /// Maximum number of block number to block hash mappings to keep (oldest pruned first). - type BlockHashCount = BlockHashCount; - /// Runtime version. - type Version = Version; - /// Converts a module to an index of this module in the runtime. - type PalletInfo = PalletInfo; - /// The data to be stored in an account. - type AccountData = pallet_balances::AccountData; - /// What to do if a new account is created. - type OnNewAccount = (); - /// What to do if an account is fully reaped from the system. - type OnKilledAccount = (); - /// The weight of database operations that the runtime can invoke. - type DbWeight = RocksDbWeight; - /// The basic call filter to use in dispatchable. - type BaseCallFilter = Everything; - /// Weight information for the extrinsics of this pallet. - type SystemWeightInfo = (); - /// Block & extrinsics weights: base values and limits. - type BlockWeights = RuntimeBlockWeights; - /// The maximum length of a block (in bytes). - type BlockLength = RuntimeBlockLength; /// This is used as an identifier of the chain. 42 is the generic substrate prefix. type SS58Prefix = SS58Prefix; - /// The action to take on a Runtime Upgrade - type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; - type MaxConsumers = frame_support::traits::ConstU32<16>; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = (); + /// Runtime version. + type Version = Version; } impl pallet_timestamp::Config for Runtime { + type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; type WeightInfo = (); } impl pallet_authorship::Config for Runtime { - type FindAuthor = pallet_session::FindAccountFromAuthorIndex; type EventHandler = (CollatorSelection,); + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; } parameter_types! { @@ -349,21 +348,21 @@ parameter_types! { } impl pallet_balances::Config for Runtime { - type MaxLocks = ConstU32<50>; + type AccountStore = System; /// The type for recording an account's balance. type Balance = Balance; - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = pallet_balances::weights::SubstrateWeight; - type MaxReserves = ConstU32<50>; - type ReserveIdentifier = [u8; 8]; - type HoldIdentifier = (); type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; + type HoldIdentifier = (); type MaxFreezes = ConstU32<0>; + type MaxHolds = ConstU32<0>; + type MaxLocks = ConstU32<50>; + type MaxReserves = ConstU32<50>; + type ReserveIdentifier = [u8; 8]; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_balances::weights::SubstrateWeight; } parameter_types! { @@ -372,12 +371,12 @@ parameter_types! { } impl pallet_transaction_payment::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; - type WeightToFee = WeightToFee; - type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type LengthToFee = ConstantMultiplier; + type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type OperationalFeeMultiplier = ConstU8<5>; + type RuntimeEvent = RuntimeEvent; + type WeightToFee = WeightToFee; } parameter_types! { @@ -394,26 +393,26 @@ parameter_types! { // EnsureOneOf, EnsureXcm>>; impl pallet_assets::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Balance = Balance; + type ApprovalDeposit = ApprovalDeposit; + type AssetAccountDeposit = AssetAccountDeposit; + type AssetDeposit = AssetDeposit; type AssetId = AssetId; type AssetIdParameter = parity_scale_codec::Compact; - type Currency = Balances; + type Balance = Balance; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); + type CallbackHandle = (); type CreateOrigin = AsEnsureOriginWithArg>; + type Currency = Balances; + type Extra = (); type ForceOrigin = EnsureRoot; - type AssetDeposit = AssetDeposit; + type Freezer = (); type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type ApprovalDeposit = ApprovalDeposit; + type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; + type RuntimeEvent = RuntimeEvent; type StringLimit = AssetsStringLimit; - type Freezer = (); - type Extra = (); type WeightInfo = pallet_assets::weights::SubstrateWeight; - type CallbackHandle = (); - type AssetAccountDeposit = AssetAccountDeposit; - type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); } parameter_types! { @@ -422,15 +421,15 @@ parameter_types! { } impl cumulus_pallet_parachain_system::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type OnSystemEvent = (); - type SelfParaId = parachain_info::Pallet; + type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; type DmpMessageHandler = DmpQueue; - type ReservedDmpWeight = ReservedDmpWeight; + type OnSystemEvent = (); type OutboundXcmpMessageSource = XcmpQueue; - type XcmpMessageHandler = XcmpQueue; + type ReservedDmpWeight = ReservedDmpWeight; type ReservedXcmpWeight = ReservedXcmpWeight; - type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; + type RuntimeEvent = RuntimeEvent; + type SelfParaId = parachain_info::Pallet; + type XcmpMessageHandler = XcmpQueue; } impl parachain_info::Config for Runtime {} @@ -438,21 +437,21 @@ impl parachain_info::Config for Runtime {} impl cumulus_pallet_aura_ext::Config for Runtime {} impl cumulus_pallet_xcmp_queue::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; type ChannelInfo = ParachainSystem; - type VersionWrapper = PolkadotXcm; - type ExecuteOverweightOrigin = EnsureRoot; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; - type WeightInfo = (); + type ExecuteOverweightOrigin = EnsureRoot; type PriceForSiblingDelivery = (); + type RuntimeEvent = RuntimeEvent; + type VersionWrapper = PolkadotXcm; + type WeightInfo = (); + type XcmExecutor = XcmExecutor; } impl cumulus_pallet_dmp_queue::Config for Runtime { + type ExecuteOverweightOrigin = EnsureRoot; type RuntimeEvent = RuntimeEvent; type XcmExecutor = XcmExecutor; - type ExecuteOverweightOrigin = EnsureRoot; } parameter_types! { @@ -461,16 +460,16 @@ parameter_types! { } impl pallet_session::Config for Runtime { + type Keys = SessionKeys; + type NextSessionRotation = pallet_session::PeriodicSessions; type RuntimeEvent = RuntimeEvent; + // Essentially just Aura, but let's be pedantic. + type SessionHandler = ::KeyTypeIdProviders; + type SessionManager = CollatorSelection; + type ShouldEndSession = pallet_session::PeriodicSessions; type ValidatorId = ::AccountId; // we don't have stash and controller, thus we don't need the convert as well. type ValidatorIdOf = pallet_collator_selection::IdentityCollator; - type ShouldEndSession = pallet_session::PeriodicSessions; - type NextSessionRotation = pallet_session::PeriodicSessions; - type SessionManager = CollatorSelection; - // Essentially just Aura, but let's be pedantic. - type SessionHandler = ::KeyTypeIdProviders; - type Keys = SessionKeys; type WeightInfo = (); } @@ -493,15 +492,15 @@ parameter_types! { pub type CollatorSelectionUpdateOrigin = EnsureRoot; impl pallet_collator_selection::Config for Runtime { - type RuntimeEvent = RuntimeEvent; type Currency = Balances; - type UpdateOrigin = CollatorSelectionUpdateOrigin; - type PotId = PotId; - type MaxCandidates = MaxCandidates; - type MinCandidates = MinCandidates; - type MaxInvulnerables = MaxInvulnerables; // should be a multiple of session or things will get inconsistent type KickThreshold = Period; + type MaxCandidates = MaxCandidates; + type MaxInvulnerables = MaxInvulnerables; + type MinCandidates = MinCandidates; + type PotId = PotId; + type RuntimeEvent = RuntimeEvent; + type UpdateOrigin = CollatorSelectionUpdateOrigin; type ValidatorId = ::AccountId; type ValidatorIdOf = pallet_collator_selection::IdentityCollator; type ValidatorRegistration = Session; @@ -509,17 +508,17 @@ impl pallet_collator_selection::Config for Runtime { } impl pallet_asset_tx_payment::Config for Runtime { - type RuntimeEvent = RuntimeEvent; type Fungibles = Assets; type OnChargeAssetTransaction = pallet_asset_tx_payment::FungiblesAdapter< pallet_assets::BalanceToAssetBalance, AssetsToBlockAuthor, >; + type RuntimeEvent = RuntimeEvent; } impl pallet_sudo::Config for Runtime { - type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; } // Create the runtime by composing the FRAME pallets that were previously configured. @@ -800,17 +799,15 @@ impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { block: &Block, relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, ) -> sp_inherents::CheckInherentsResult { - let relay_chain_slot = relay_state_proof - .read_slot() - .expect("Could not read the relay chain slot from the proof"); - - let inherent_data = - cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( - relay_chain_slot, - sp_std::time::Duration::from_secs(6), - ) - .create_inherent_data() - .expect("Could not create the timestamp inherent data"); + let relay_chain_slot = + relay_state_proof.read_slot().expect("Could not read the relay chain slot from the proof"); + + let inherent_data = cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( + relay_chain_slot, + sp_std::time::Duration::from_secs(6), + ) + .create_inherent_data() + .expect("Could not create the timestamp inherent data"); inherent_data.check_extrinsics(block) } diff --git a/integration-tests/modified-penpal/src/weights/block_weights.rs b/integration-tests/modified-penpal/src/weights/block_weights.rs index ea8a341b5..4aee7fb93 100644 --- a/integration-tests/modified-penpal/src/weights/block_weights.rs +++ b/integration-tests/modified-penpal/src/weights/block_weights.rs @@ -44,10 +44,7 @@ pub mod constants { "Weight should be at least 100 µs." ); // At most 50 ms. - assert!( - w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, - "Weight should be at most 50 ms." - ); + assert!(w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 50 ms."); } } } diff --git a/integration-tests/modified-penpal/src/weights/extrinsic_weights.rs b/integration-tests/modified-penpal/src/weights/extrinsic_weights.rs index 0512efb60..f7008216c 100644 --- a/integration-tests/modified-penpal/src/weights/extrinsic_weights.rs +++ b/integration-tests/modified-penpal/src/weights/extrinsic_weights.rs @@ -39,15 +39,9 @@ pub mod constants { let w = super::constants::ExtrinsicBaseWeight::get(); // At least 10 µs. - assert!( - w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, - "Weight should be at least 10 µs." - ); + assert!(w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, "Weight should be at least 10 µs."); // At most 1 ms. - assert!( - w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, - "Weight should be at most 1 ms." - ); + assert!(w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 1 ms."); } } } diff --git a/integration-tests/modified-penpal/src/xcm_config.rs b/integration-tests/modified-penpal/src/xcm_config.rs index 436ed023b..c6ee42a9e 100644 --- a/integration-tests/modified-penpal/src/xcm_config.rs +++ b/integration-tests/modified-penpal/src/xcm_config.rs @@ -22,9 +22,9 @@ //! with statemine as the reserve. At present no derivative tokens are minted on receipt of a //! ReserveAssetTransferDeposited message but that will but the intension will be to support this soon. use super::{ - AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Assets, Balance, Balances, - EnsureRoot, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, - RuntimeOrigin, WeightToFee, XcmpQueue, + AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Assets, Balance, Balances, EnsureRoot, + ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, + XcmpQueue, }; use core::marker::PhantomData; use frame_support::{ @@ -43,13 +43,11 @@ use polkadot_runtime_common::impls::ToAuthor; use sp_runtime::traits::Zero; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, - AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, - ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, FungiblesAdapter, - IsConcrete, LocalMint, NativeAsset, ParentIsPreset, RelayChainAsNative, - SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, - WithComputedOrigin, + AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, + FixedWeightBounds, FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, ParentIsPreset, RelayChainAsNative, + SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, WithComputedOrigin, }; use xcm_executor::{traits::JustTry, XcmExecutor}; @@ -161,10 +159,7 @@ pub type Barrier = DenyThenTry< // If the message is one that immediately attemps to pay for execution, then allow it. AllowTopLevelPaidExecutionFrom, // Common Good Assets parachain, parent and its exec plurality get free execution - AllowExplicitUnpaidExecutionFrom<( - CommonGoodAssetsParachain, - ParentOrParentsExecutivePlurality, - )>, + AllowExplicitUnpaidExecutionFrom<(CommonGoodAssetsParachain, ParentOrParentsExecutivePlurality)>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, ), @@ -271,16 +266,10 @@ impl ContainsPair for StatemintAssets { &loc == origin && match asset { MultiAsset { - id: - Concrete(MultiLocation { - parents: 0, - interior: X2(PalletInstance(50), GeneralIndex(_)), - }), + id: Concrete(MultiLocation { parents: 0, interior: X2(PalletInstance(50), GeneralIndex(_)) }), .. } => true, - MultiAsset { - id: Concrete(MultiLocation { parents: 1, interior: Here }), .. - } => true, + MultiAsset { id: Concrete(MultiLocation { parents: 1, interior: Here }), .. } => true, _ => false, } @@ -291,31 +280,30 @@ pub type Reserves = (NativeAsset, StatemintAssets); pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { - type RuntimeCall = RuntimeCall; - type XcmSender = XcmRouter; + type AssetClaims = PolkadotXcm; + type AssetExchanger = (); + type AssetLocker = (); // How to withdraw and deposit an asset. type AssetTransactor = AssetTransactors; - type OriginConverter = XcmOriginToTransactDispatchOrigin; + type AssetTrap = PolkadotXcm; + type Barrier = Barrier; + type CallDispatcher = RuntimeCall; + type FeeManager = (); type IsReserve = Reserves; type IsTeleporter = NativeAsset; - type UniversalLocation = UniversalLocation; - type Barrier = Barrier; - type Weigher = FixedWeightBounds; - type Trader = - UsingComponents>; - type ResponseHandler = PolkadotXcm; - type AssetTrap = PolkadotXcm; - type AssetClaims = PolkadotXcm; - type SubscriptionService = PolkadotXcm; - type PalletInstancesInfo = AllPalletsWithSystem; type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type AssetLocker = (); - type AssetExchanger = (); - type FeeManager = (); type MessageExporter = (); - type UniversalAliases = Nothing; - type CallDispatcher = RuntimeCall; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type PalletInstancesInfo = AllPalletsWithSystem; + type ResponseHandler = PolkadotXcm; + type RuntimeCall = RuntimeCall; type SafeCallFilter = Everything; + type SubscriptionService = PolkadotXcm; + type Trader = UsingComponents>; + type UniversalAliases = Nothing; + type UniversalLocation = UniversalLocation; + type Weigher = FixedWeightBounds; + type XcmSender = XcmRouter; } /// No local origins on this chain are allowed to dispatch XCM sends/executions. @@ -336,33 +324,33 @@ parameter_types! { } impl pallet_xcm::Config for Runtime { + type AdminOrigin = EnsureRoot; + // ^ Override for AdvertisedXcmVersion default + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; + type Currency = Balances; + type CurrencyMatcher = (); + type ExecuteXcmOrigin = EnsureXcmOrigin; + type MaxLockers = ConstU32<8>; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; type SendXcmOrigin = EnsureXcmOrigin; - type XcmRouter = XcmRouter; - type ExecuteXcmOrigin = EnsureXcmOrigin; + type SovereignAccountOf = LocationToAccountId; + type TrustedLockers = (); + type UniversalLocation = UniversalLocation; + type Weigher = FixedWeightBounds; + type WeightInfo = pallet_xcm::TestWeightInfo; type XcmExecuteFilter = Everything; // ^ Disable dispatchable execute on the XCM pallet. // Needs to be `Everything` for local testing. type XcmExecutor = XcmExecutor; - type XcmTeleportFilter = Everything; type XcmReserveTransferFilter = Everything; - type Weigher = FixedWeightBounds; - type UniversalLocation = UniversalLocation; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; + type XcmRouter = XcmRouter; + type XcmTeleportFilter = Everything; const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; - // ^ Override for AdvertisedXcmVersion default - type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; - type Currency = Balances; - type CurrencyMatcher = (); - type TrustedLockers = (); - type SovereignAccountOf = LocationToAccountId; - type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; - type AdminOrigin = EnsureRoot; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs index fa5b321ee..7ea151ac7 100644 --- a/integration-tests/src/lib.rs +++ b/integration-tests/src/lib.rs @@ -24,8 +24,8 @@ use sp_core::{ecdsa, ed25519, sr25519, Pair}; use sp_runtime::{traits::AccountIdConversion, AccountId32 as RuntimeAccountId32}; use xcm::{v3::prelude::*, VersionedMultiAssets, VersionedMultiLocation, VersionedXcm}; use xcm_emulator::{ - cumulus_pallet_xcmp_queue, decl_test_network, decl_test_parachain, decl_test_relay_chain, - polkadot_primitives, TestExt, + cumulus_pallet_xcmp_queue, decl_test_network, decl_test_parachain, decl_test_relay_chain, polkadot_primitives, + TestExt, }; const RELAY_ASSET_ID: u32 = 0; @@ -104,6 +104,7 @@ impl ParachainAccounts { fn polimec_child_account() -> RuntimeAccountId32 { ParaId::new(polimec_id()).into_account_truncating() } + fn polimec_sibling_account() -> RuntimeAccountId32 { SiblingId::from(polimec_id()).into_account_truncating() } @@ -111,6 +112,7 @@ impl ParachainAccounts { fn statemint_child_account() -> RuntimeAccountId32 { ParaId::from(statemint_id()).into_account_truncating() } + fn statemint_sibling_account() -> RuntimeAccountId32 { SiblingId::from(statemint_id()).into_account_truncating() } @@ -118,15 +120,14 @@ impl ParachainAccounts { fn penpal_child_account() -> RuntimeAccountId32 { ParaId::from(penpal_id()).into_account_truncating() } + fn penpal_sibling_account() -> RuntimeAccountId32 { SiblingId::from(penpal_id()).into_account_truncating() } } fn default_parachains_host_configuration( -) -> polkadot_runtime_parachains::configuration::HostConfiguration< - polkadot_primitives::v4::BlockNumber, -> { +) -> polkadot_runtime_parachains::configuration::HostConfiguration { use polkadot_primitives::v4::{MAX_CODE_SIZE, MAX_POV_SIZE}; polkadot_runtime_parachains::configuration::HostConfiguration { @@ -189,11 +190,7 @@ pub fn polkadot_ext() -> sp_io::TestExternalities { .unwrap(); let xcm_config = pallet_xcm::GenesisConfig { safe_xcm_version: Some(3) }; - >::assimilate_storage( - &xcm_config, - &mut t, - ) - .unwrap(); + >::assimilate_storage(&xcm_config, &mut t).unwrap(); let mut ext = sp_io::TestExternalities::new(t); ext.execute_with(|| System::set_block_number(1)); @@ -207,18 +204,11 @@ pub fn polimec_ext(para_id: u32) -> sp_io::TestExternalities { let parachain_info_config = parachain_info::GenesisConfig { parachain_id: para_id.into() }; - >::assimilate_storage( - ¶chain_info_config, - &mut t, - ) - .unwrap(); + >::assimilate_storage(¶chain_info_config, &mut t) + .unwrap(); let xcm_config = pallet_xcm::GenesisConfig { safe_xcm_version: Some(3) }; - >::assimilate_storage( - &xcm_config, - &mut t, - ) - .unwrap(); + >::assimilate_storage(&xcm_config, &mut t).unwrap(); pallet_balances::GenesisConfig:: { balances: vec![ @@ -232,12 +222,7 @@ pub fn polimec_ext(para_id: u32) -> sp_io::TestExternalities { .unwrap(); pallet_assets::GenesisConfig:: { - metadata: vec![( - RELAY_ASSET_ID, - "Local DOT".as_bytes().to_vec(), - "DOT".as_bytes().to_vec(), - 12, - )], + metadata: vec![(RELAY_ASSET_ID, "Local DOT".as_bytes().to_vec(), "DOT".as_bytes().to_vec(), 12)], accounts: vec![(RELAY_ASSET_ID, ALICE, INITIAL_BALANCE)], assets: vec![( RELAY_ASSET_ID, @@ -261,18 +246,11 @@ pub fn statemint_ext(para_id: u32) -> sp_io::TestExternalities { let parachain_info_config = parachain_info::GenesisConfig { parachain_id: para_id.into() }; - >::assimilate_storage( - ¶chain_info_config, - &mut t, - ) - .unwrap(); + >::assimilate_storage(¶chain_info_config, &mut t) + .unwrap(); let xcm_config = pallet_xcm::GenesisConfig { safe_xcm_version: Some(3) }; - >::assimilate_storage( - &xcm_config, - &mut t, - ) - .unwrap(); + >::assimilate_storage(&xcm_config, &mut t).unwrap(); pallet_balances::GenesisConfig:: { balances: vec![ @@ -295,18 +273,11 @@ pub fn penpal_ext(para_id: u32) -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); let parachain_info_config = parachain_info::GenesisConfig { parachain_id: para_id.into() }; - >::assimilate_storage( - ¶chain_info_config, - &mut t, - ) - .unwrap(); + >::assimilate_storage(¶chain_info_config, &mut t) + .unwrap(); let xcm_config = pallet_xcm::GenesisConfig { safe_xcm_version: Some(3) }; - >::assimilate_storage( - &xcm_config, - &mut t, - ) - .unwrap(); + >::assimilate_storage(&xcm_config, &mut t).unwrap(); pallet_balances::GenesisConfig:: { balances: vec![ @@ -343,8 +314,7 @@ pub mod shortcuts { pub type PenpalBalances = pallet_balances::Pallet; pub type PolkadotAssets = pallet_assets::Pallet; - pub type PolimecAssets = - pallet_assets::Pallet; + pub type PolimecAssets = pallet_assets::Pallet; pub type StatemintAssets = pallet_assets::Pallet; pub type PenpalAssets = pallet_assets::Pallet; @@ -384,10 +354,7 @@ mod network_tests { UnpaidExecution { weight_limit: WeightLimit::Unlimited, check_origin: None }, Transact { origin_kind: OriginKind::SovereignAccount, - require_weight_at_most: Weight::from_parts( - INITIAL_BALANCE as u64, - 1024 * 1024 - ), + require_weight_at_most: Weight::from_parts(INITIAL_BALANCE as u64, 1024 * 1024), call: remark.encode().into(), } ]), @@ -408,11 +375,10 @@ mod network_tests { fn ump() { Network::reset(); - let burn_transfer = - PolkadotCall::Balances(pallet_balances::Call::::transfer { - dest: PolkadotAccountId::from([0u8; 32]).into(), - value: 1_000, - }); + let burn_transfer = PolkadotCall::Balances(pallet_balances::Call::::transfer { + dest: PolkadotAccountId::from([0u8; 32]).into(), + value: 1_000, + }); let here_asset: MultiAsset = (MultiLocation::here(), INITIAL_BALANCE / 2).into(); @@ -427,10 +393,7 @@ mod network_tests { BuyExecution { fees: here_asset.clone(), weight_limit: Unlimited }, Transact { origin_kind: OriginKind::SovereignAccount, - require_weight_at_most: Weight::from_parts( - INITIAL_BALANCE as u64, - 1024 * 1024 - ), + require_weight_at_most: Weight::from_parts(INITIAL_BALANCE as u64, 1024 * 1024), call: burn_transfer.encode().into(), } ]), @@ -442,10 +405,7 @@ mod network_tests { let events = System::events(); assert!(events.iter().any(|r| matches!( r.event, - RuntimeEvent::Ump(polkadot_runtime_parachains::ump::Event::ExecutedUpward( - _, - Outcome::Complete(_), - )) + RuntimeEvent::Ump(polkadot_runtime_parachains::ump::Event::ExecutedUpward(_, Outcome::Complete(_),)) ))); }); } @@ -454,11 +414,10 @@ mod network_tests { fn xcmp() { Network::reset(); - let burn_transfer = - PolimecCall::Balances(pallet_balances::Call::::transfer { - dest: PolimecAccountId::from([0u8; 32]).into(), - value: 1_000, - }); + let burn_transfer = PolimecCall::Balances(pallet_balances::Call::::transfer { + dest: PolimecAccountId::from([0u8; 32]).into(), + value: 1_000, + }); let here_asset: MultiAsset = (MultiLocation::here(), INITIAL_BALANCE / 2).into(); @@ -471,10 +430,7 @@ mod network_tests { BuyExecution { fees: here_asset.clone(), weight_limit: Unlimited }, Transact { origin_kind: OriginKind::SovereignAccount, - require_weight_at_most: Weight::from_parts( - INITIAL_BALANCE as u64, - 1024 * 1024 - ), + require_weight_at_most: Weight::from_parts(INITIAL_BALANCE as u64, 1024 * 1024), call: burn_transfer.encode().into(), } ]), @@ -484,10 +440,9 @@ mod network_tests { PolimecNet::execute_with(|| { use polimec_runtime::{RuntimeEvent, System}; let events = System::events(); - assert!(events.iter().any(|r| matches!( - r.event, - RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) - ))); + assert!(events + .iter() + .any(|r| matches!(r.event, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. })))); }); } } @@ -519,26 +474,20 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let ( - statemint_prev_alice_dot_balance, - statemint_prev_polimec_dot_balance, - statemint_prev_dot_issuance, - ) = StatemintNet::execute_with(|| { - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::free_balance(ParachainAccounts::polimec_child_account()), - StatemintBalances::total_issuance(), - ) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_polimec_dot_balance, statemint_prev_dot_issuance) = + StatemintNet::execute_with(|| { + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::free_balance(ParachainAccounts::polimec_child_account()), + StatemintBalances::total_issuance(), + ) + }); // do the transfer StatemintNet::execute_with(|| { assert_ok!(StatemintXcmPallet::limited_reserve_transfer_assets( StatemintOrigin::signed(ALICE), - Box::new(VersionedMultiLocation::V3(MultiLocation::new( - 1, - X1(Parachain(polimec_id())), - ))), + Box::new(VersionedMultiLocation::V3(MultiLocation::new(1, X1(Parachain(polimec_id())),))), Box::new(VersionedMultiLocation::V3(MultiLocation::from(AccountId32 { network: None, id: ALICE.into(), @@ -553,10 +502,9 @@ mod reserve_backed_transfers { PolimecNet::execute_with(|| { use polimec_runtime::{RuntimeEvent, System}; let events = System::events(); - assert!(events.iter().any(|r| matches!( - r.event, - RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) - ))); + assert!(events + .iter() + .any(|r| matches!(r.event, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. })))); }); // check Polimec's post transfer balances and issuance @@ -576,32 +524,25 @@ mod reserve_backed_transfers { }); // check Statemint's post transfer balances and issuance - let ( - statemint_post_alice_dot_balance, - statemint_post_polimec_dot_balance, - statemint_post_dot_issuance, - ) = StatemintNet::execute_with(|| { - statemint_runtime::System::reset_events(); - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::free_balance(ParachainAccounts::polimec_child_account()), - StatemintBalances::total_issuance(), - ) - }); + let (statemint_post_alice_dot_balance, statemint_post_polimec_dot_balance, statemint_post_dot_issuance) = + StatemintNet::execute_with(|| { + statemint_runtime::System::reset_events(); + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::free_balance(ParachainAccounts::polimec_child_account()), + StatemintBalances::total_issuance(), + ) + }); - let polimec_delta_alice_dot_balance = - polimec_post_alice_dot_balance - polimec_prev_alice_dot_balance; + let polimec_delta_alice_dot_balance = polimec_post_alice_dot_balance - polimec_prev_alice_dot_balance; let polimec_delta_dot_issuance = polimec_post_dot_issuance - polimec_prev_dot_issuance; - let polimec_delta_alice_plmc_balance = - polimec_post_alice_plmc_balance - polimec_prev_alice_plmc_balance; + let polimec_delta_alice_plmc_balance = polimec_post_alice_plmc_balance - polimec_prev_alice_plmc_balance; let polimec_delta_plmc_issuance = polimec_post_plmc_issuance - polimec_prev_plmc_issuance; - let statemint_delta_alice_dot_balance = - statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; + let statemint_delta_alice_dot_balance = statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; let statemint_delta_polimec_dot_balance = statemint_post_polimec_dot_balance - statemint_prev_polimec_dot_balance; - let statemint_delta_dot_issuance = - statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; assert!( polimec_delta_alice_dot_balance >= RESERVE_TRANSFER_AMOUNT - polimec_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) && @@ -610,10 +551,9 @@ mod reserve_backed_transfers { ); assert!( - polimec_delta_dot_issuance - >= RESERVE_TRANSFER_AMOUNT - - polimec_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) - && polimec_delta_dot_issuance <= RESERVE_TRANSFER_AMOUNT, + polimec_delta_dot_issuance >= + RESERVE_TRANSFER_AMOUNT - polimec_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) && + polimec_delta_dot_issuance <= RESERVE_TRANSFER_AMOUNT, "Polimec DOT issuance should have increased by at least the transfer amount minus the XCM execution fee" ); @@ -632,10 +572,7 @@ mod reserve_backed_transfers { "Statemint's DOT issuance should not change, since it acts as a reserve for that asset (except for fees which are burnt)" ); - assert_eq!( - polimec_delta_alice_plmc_balance, 0, - "Polimec ALICE PLMC balance should not have changed" - ); + assert_eq!(polimec_delta_alice_plmc_balance, 0, "Polimec ALICE PLMC balance should not have changed"); assert_eq!(polimec_delta_plmc_issuance, 0, "Polimec PLMC issuance should not have changed"); } @@ -664,10 +601,9 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = - StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); // construct the XCM to transfer from Polimec to Statemint's reserve let transfer_xcm: Xcm = Xcm(vec![ @@ -677,16 +613,10 @@ mod reserve_backed_transfers { assets: All.into(), reserve: MultiLocation::new(1, X1(Parachain(statemint_id()))), xcm: Xcm(vec![ - BuyExecution { - fees: execution_dot.clone(), - weight_limit: Limited(MAX_XCM_WEIGHT), - }, + BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, DepositAsset { assets: All.into(), - beneficiary: MultiLocation::new( - 0, - AccountId32 { network: None, id: ALICE.into() }, - ), + beneficiary: MultiLocation::new(0, AccountId32 { network: None, id: ALICE.into() }), }, ]), }, @@ -705,10 +635,9 @@ mod reserve_backed_transfers { StatemintNet::execute_with(|| { use statemint_runtime::{RuntimeEvent, System}; let events = System::events(); - assert!(events.iter().any(|r| matches!( - r.event, - RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) - ))); + assert!(events + .iter() + .any(|r| matches!(r.event, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. })))); }); // check Polimec's post transfer balances and issuance @@ -727,22 +656,17 @@ mod reserve_backed_transfers { }); // check Statemint's post transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = - StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); let polimec_delta_dot_issuance = polimec_prev_dot_issuance - polimec_post_dot_issuance; let polimec_delta_plmc_issuance = polimec_prev_plmc_issuance - polimec_post_plmc_issuance; - let polimec_delta_alice_dot_balance = - polimec_prev_alice_dot_balance - polimec_post_alice_dot_balance; - let polimec_delta_alice_plmc_balance = - polimec_prev_alice_plmc_balance - polimec_post_alice_plmc_balance; + let polimec_delta_alice_dot_balance = polimec_prev_alice_dot_balance - polimec_post_alice_dot_balance; + let polimec_delta_alice_plmc_balance = polimec_prev_alice_plmc_balance - polimec_post_alice_plmc_balance; - let statemint_delta_dot_issuance = - statemint_prev_dot_issuance - statemint_post_dot_issuance; - let statemint_delta_alice_dot_balance = - statemint_post_alice_dot_balance - statemint_prev_alice_dot_balance; + let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = statemint_post_alice_dot_balance - statemint_prev_alice_dot_balance; assert_eq!( polimec_delta_alice_dot_balance, RESERVE_TRANSFER_AMOUNT, @@ -758,10 +682,10 @@ mod reserve_backed_transfers { assert_eq!(polimec_delta_alice_plmc_balance, 0, "Polimec's Alice PLMC should not change"); assert!( - statemint_delta_alice_dot_balance - >= RESERVE_TRANSFER_AMOUNT - - statemint_runtime::constants::fee::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) - && statemint_delta_alice_dot_balance <= RESERVE_TRANSFER_AMOUNT, + statemint_delta_alice_dot_balance >= + RESERVE_TRANSFER_AMOUNT - + statemint_runtime::constants::fee::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) && + statemint_delta_alice_dot_balance <= RESERVE_TRANSFER_AMOUNT, "Statemint's ALICE DOT balance should increase by at least the transfer amount minus the max allowed fees" ); @@ -779,31 +703,23 @@ mod reserve_backed_transfers { // check Penpal's pre transfer balances and issuance let (penpal_prev_alice_dot_balance, penpal_prev_dot_issuance) = - PenpalNet::execute_with(|| { - (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) - }); + PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); // check Statemint's pre transfer balances and issuance - let ( - statemint_prev_alice_dot_balance, - statemint_prev_penpal_dot_balance, - statemint_prev_dot_issuance, - ) = StatemintNet::execute_with(|| { - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::free_balance(ParachainAccounts::penpal_child_account()), - StatemintBalances::total_issuance(), - ) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_penpal_dot_balance, statemint_prev_dot_issuance) = + StatemintNet::execute_with(|| { + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::free_balance(ParachainAccounts::penpal_child_account()), + StatemintBalances::total_issuance(), + ) + }); // do the transfer StatemintNet::execute_with(|| { assert_ok!(StatemintXcmPallet::limited_reserve_transfer_assets( StatemintOrigin::signed(ALICE), - Box::new(VersionedMultiLocation::V3(MultiLocation::new( - 1, - X1(Parachain(penpal_id())), - ))), + Box::new(VersionedMultiLocation::V3(MultiLocation::new(1, X1(Parachain(penpal_id())),))), Box::new(VersionedMultiLocation::V3(MultiLocation::from(AccountId32 { network: None, id: ALICE.into(), @@ -818,43 +734,34 @@ mod reserve_backed_transfers { PenpalNet::execute_with(|| { use penpal_runtime::{RuntimeEvent, System}; let events = System::events(); - assert!(events.iter().any(|r| matches!( - r.event, - RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) - ))); + assert!(events + .iter() + .any(|r| matches!(r.event, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. })))); }); // check Penpal's post transfer balances and issuance - let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = - PenpalNet::execute_with(|| { - penpal_runtime::System::reset_events(); - (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) - }); + let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = PenpalNet::execute_with(|| { + penpal_runtime::System::reset_events(); + (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) + }); // check Statemint's post transfer balances and issuance - let ( - statemint_post_alice_dot_balance, - statemint_post_penpal_dot_balance, - statemint_post_dot_issuance, - ) = StatemintNet::execute_with(|| { - statemint_runtime::System::reset_events(); - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::free_balance(ParachainAccounts::penpal_child_account()), - StatemintBalances::total_issuance(), - ) - }); + let (statemint_post_alice_dot_balance, statemint_post_penpal_dot_balance, statemint_post_dot_issuance) = + StatemintNet::execute_with(|| { + statemint_runtime::System::reset_events(); + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::free_balance(ParachainAccounts::penpal_child_account()), + StatemintBalances::total_issuance(), + ) + }); - let penpal_delta_alice_dot_balance = - penpal_post_alice_dot_balance - penpal_prev_alice_dot_balance; + let penpal_delta_alice_dot_balance = penpal_post_alice_dot_balance - penpal_prev_alice_dot_balance; let penpal_delta_dot_issuance = penpal_post_dot_issuance - penpal_prev_dot_issuance; - let statemint_delta_alice_dot_balance = - statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; - let statemint_delta_penpal_dot_balance = - statemint_post_penpal_dot_balance - statemint_prev_penpal_dot_balance; - let statemint_delta_dot_issuance = - statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; + let statemint_delta_penpal_dot_balance = statemint_post_penpal_dot_balance - statemint_prev_penpal_dot_balance; + let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; assert!( penpal_delta_alice_dot_balance >= RESERVE_TRANSFER_AMOUNT - penpal_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) && @@ -863,9 +770,9 @@ mod reserve_backed_transfers { ); assert!( - penpal_delta_dot_issuance - >= RESERVE_TRANSFER_AMOUNT - penpal_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) - && penpal_delta_dot_issuance <= RESERVE_TRANSFER_AMOUNT, + penpal_delta_dot_issuance >= + RESERVE_TRANSFER_AMOUNT - penpal_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) && + penpal_delta_dot_issuance <= RESERVE_TRANSFER_AMOUNT, "Penpal DOT issuance should have increased by at least the transfer amount minus the XCM execution fee" ); @@ -895,15 +802,12 @@ mod reserve_backed_transfers { // check Penpal's pre transfer balances and issuance let (penpal_prev_alice_dot_balance, penpal_prev_dot_issuance) = - PenpalNet::execute_with(|| { - (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) - }); + PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = - StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); // construct the XCM to transfer from Penpal to Statemint's reserve let transfer_xcm: Xcm = Xcm(vec![ @@ -913,16 +817,10 @@ mod reserve_backed_transfers { assets: All.into(), reserve: MultiLocation::new(1, X1(Parachain(statemint_id()))), xcm: Xcm(vec![ - BuyExecution { - fees: execution_dot.clone(), - weight_limit: Limited(MAX_XCM_WEIGHT), - }, + BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, DepositAsset { assets: All.into(), - beneficiary: MultiLocation::new( - 0, - AccountId32 { network: None, id: ALICE.into() }, - ), + beneficiary: MultiLocation::new(0, AccountId32 { network: None, id: ALICE.into() }), }, ]), }, @@ -941,32 +839,25 @@ mod reserve_backed_transfers { StatemintNet::execute_with(|| { use statemint_runtime::{RuntimeEvent, System}; let events = System::events(); - assert!(events.iter().any(|r| matches!( - r.event, - RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) - ))); + assert!(events + .iter() + .any(|r| matches!(r.event, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. })))); }); // check Penpal's post transfer balances and issuance let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = - PenpalNet::execute_with(|| { - (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) - }); + PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); // check Statemint's post transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = - StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); let penpal_delta_dot_issuance = penpal_prev_dot_issuance - penpal_post_dot_issuance; - let penpal_delta_alice_dot_balance = - penpal_prev_alice_dot_balance - penpal_post_alice_dot_balance; + let penpal_delta_alice_dot_balance = penpal_prev_alice_dot_balance - penpal_post_alice_dot_balance; - let statemint_delta_dot_issuance = - statemint_prev_dot_issuance - statemint_post_dot_issuance; - let statemint_delta_alice_dot_balance = - statemint_post_alice_dot_balance - statemint_prev_alice_dot_balance; + let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = statemint_post_alice_dot_balance - statemint_prev_alice_dot_balance; assert_eq!( penpal_delta_alice_dot_balance, RESERVE_TRANSFER_AMOUNT, @@ -979,10 +870,10 @@ mod reserve_backed_transfers { ); assert!( - statemint_delta_alice_dot_balance - >= RESERVE_TRANSFER_AMOUNT - - statemint_runtime::constants::fee::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) - && statemint_delta_alice_dot_balance <= RESERVE_TRANSFER_AMOUNT, + statemint_delta_alice_dot_balance >= + RESERVE_TRANSFER_AMOUNT - + statemint_runtime::constants::fee::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) && + statemint_delta_alice_dot_balance <= RESERVE_TRANSFER_AMOUNT, "Statemint's ALICE DOT balance should increase by at least the transfer amount minus the max allowed fees" ); @@ -1006,22 +897,15 @@ mod reserve_backed_transfers { assets: All.into(), reserve: MultiLocation::new(1, X1(Parachain(statemint_id()))), xcm: Xcm::<()>(vec![ - BuyExecution { - fees: execution_dot.clone(), - weight_limit: Limited(MAX_XCM_WEIGHT), - }, + BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, DepositReserveAsset { assets: All.into(), dest: MultiLocation::new(1, X1(Parachain(penpal_id()))), xcm: Xcm::<()>(vec![ - BuyExecution { - fees: execution_dot.clone(), - weight_limit: Limited(MAX_XCM_WEIGHT), - }, + BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, DepositAsset { assets: All.into(), - beneficiary: X1(AccountId32 { network: None, id: ALICE.into() }) - .into(), + beneficiary: X1(AccountId32 { network: None, id: ALICE.into() }).into(), }, ]), }, @@ -1045,16 +929,13 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = - StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); // check Penpal's pre transfer balances and issuance let (penpal_prev_alice_dot_balance, penpal_prev_dot_issuance) = - PenpalNet::execute_with(|| { - (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) - }); + PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); // send the XCM message PolimecNet::execute_with(|| { @@ -1068,19 +949,17 @@ mod reserve_backed_transfers { StatemintNet::execute_with(|| { use statemint_runtime::{RuntimeEvent, System}; let events = System::events(); - assert!(events.iter().any(|r| matches!( - r.event, - RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) - ))); + assert!(events + .iter() + .any(|r| matches!(r.event, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. })))); }); PenpalNet::execute_with(|| { use penpal_runtime::{RuntimeEvent, System}; let events = System::events(); - assert!(events.iter().any(|r| matches!( - r.event, - RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) - ))); + assert!(events + .iter() + .any(|r| matches!(r.event, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. })))); }); // check Polimec's pre transfer balances and issuance @@ -1099,32 +978,24 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = - StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); // check Penpal's pre transfer balances and issuance let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = - PenpalNet::execute_with(|| { - (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) - }); + PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); let penpal_delta_dot_issuance = penpal_post_dot_issuance - penpal_prev_dot_issuance; - let penpal_delta_alice_dot_balance = - penpal_post_alice_dot_balance - penpal_prev_alice_dot_balance; + let penpal_delta_alice_dot_balance = penpal_post_alice_dot_balance - penpal_prev_alice_dot_balance; let polimec_delta_dot_issuance = polimec_prev_dot_issuance - polimec_post_dot_issuance; - let polimec_delta_alice_dot_balance = - polimec_prev_alice_dot_balance - polimec_post_alice_dot_balance; + let polimec_delta_alice_dot_balance = polimec_prev_alice_dot_balance - polimec_post_alice_dot_balance; let polimec_delta_plmc_issuance = polimec_prev_plmc_issuance - polimec_post_plmc_issuance; - let polimec_delta_alice_plmc_balance = - polimec_prev_alice_plmc_balance - polimec_post_alice_plmc_balance; + let polimec_delta_alice_plmc_balance = polimec_prev_alice_plmc_balance - polimec_post_alice_plmc_balance; - let statemint_delta_dot_issuance = - statemint_prev_dot_issuance - statemint_post_dot_issuance; - let statemint_delta_alice_dot_balance = - statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; + let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; assert!( penpal_delta_alice_dot_balance > RESERVE_TRANSFER_AMOUNT - MAX_XCM_FEE * 3 && @@ -1152,15 +1023,9 @@ mod reserve_backed_transfers { "Statemint's DOT issuance should not change, since it acts as a reserve for that asset (except for fees which are burnt)" ); - assert_eq!( - statemint_delta_alice_dot_balance, 0, - "ALICE account on Statemint should not have changed" - ); + assert_eq!(statemint_delta_alice_dot_balance, 0, "ALICE account on Statemint should not have changed"); - assert_eq!( - polimec_delta_alice_plmc_balance, 0, - "Polimec ALICE PLMC balance should not have changed" - ); + assert_eq!(polimec_delta_alice_plmc_balance, 0, "Polimec ALICE PLMC balance should not have changed"); assert_eq!(polimec_delta_plmc_issuance, 0, "Polimec PLMC issuance should not have changed"); } @@ -1179,22 +1044,15 @@ mod reserve_backed_transfers { assets: All.into(), reserve: MultiLocation::new(1, X1(Parachain(statemint_id()))), xcm: Xcm::<()>(vec![ - BuyExecution { - fees: execution_dot.clone(), - weight_limit: Limited(MAX_XCM_WEIGHT), - }, + BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, DepositReserveAsset { assets: All.into(), dest: MultiLocation::new(1, X1(Parachain(polimec_id()))), xcm: Xcm::<()>(vec![ - BuyExecution { - fees: execution_dot.clone(), - weight_limit: Limited(MAX_XCM_WEIGHT), - }, + BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, DepositAsset { assets: All.into(), - beneficiary: X1(AccountId32 { network: None, id: ALICE.into() }) - .into(), + beneficiary: X1(AccountId32 { network: None, id: ALICE.into() }).into(), }, ]), }, @@ -1218,16 +1076,13 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = - StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); // check Penpal's pre transfer balances and issuance let (penpal_prev_alice_dot_balance, penpal_prev_dot_issuance) = - PenpalNet::execute_with(|| { - (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) - }); + PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); // send the XCM message PenpalNet::execute_with(|| { @@ -1241,19 +1096,17 @@ mod reserve_backed_transfers { StatemintNet::execute_with(|| { use statemint_runtime::{RuntimeEvent, System}; let events = System::events(); - assert!(events.iter().any(|r| matches!( - r.event, - RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) - ))); + assert!(events + .iter() + .any(|r| matches!(r.event, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. })))); }); PolimecNet::execute_with(|| { use polimec_runtime::{RuntimeEvent, System}; let events = System::events(); - assert!(events.iter().any(|r| matches!( - r.event, - RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) - ))); + assert!(events + .iter() + .any(|r| matches!(r.event, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. })))); }); // check Polimec's pre transfer balances and issuance @@ -1272,32 +1125,24 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = - StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); // check Penpal's pre transfer balances and issuance let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = - PenpalNet::execute_with(|| { - (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) - }); + PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); let penpal_delta_dot_issuance = penpal_prev_dot_issuance - penpal_post_dot_issuance; - let penpal_delta_alice_dot_balance = - penpal_prev_alice_dot_balance - penpal_post_alice_dot_balance; + let penpal_delta_alice_dot_balance = penpal_prev_alice_dot_balance - penpal_post_alice_dot_balance; let polimec_delta_dot_issuance = polimec_post_dot_issuance - polimec_prev_dot_issuance; - let polimec_delta_alice_dot_balance = - polimec_post_alice_dot_balance - polimec_prev_alice_dot_balance; + let polimec_delta_alice_dot_balance = polimec_post_alice_dot_balance - polimec_prev_alice_dot_balance; let polimec_delta_plmc_issuance = polimec_post_plmc_issuance - polimec_prev_plmc_issuance; - let polimec_delta_alice_plmc_balance = - polimec_post_alice_plmc_balance - polimec_prev_alice_plmc_balance; + let polimec_delta_alice_plmc_balance = polimec_post_alice_plmc_balance - polimec_prev_alice_plmc_balance; - let statemint_delta_dot_issuance = - statemint_prev_dot_issuance - statemint_post_dot_issuance; - let statemint_delta_alice_dot_balance = - statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; + let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; assert!( polimec_delta_alice_dot_balance > RESERVE_TRANSFER_AMOUNT - MAX_XCM_FEE * 3 && @@ -1325,15 +1170,9 @@ mod reserve_backed_transfers { "Statemint's DOT issuance should not change, since it acts as a reserve for that asset (except for fees which are burnt)" ); - assert_eq!( - statemint_delta_alice_dot_balance, 0, - "ALICE account on Statemint should not have changed" - ); + assert_eq!(statemint_delta_alice_dot_balance, 0, "ALICE account on Statemint should not have changed"); - assert_eq!( - polimec_delta_alice_plmc_balance, 0, - "Polimec ALICE PLMC balance should not have changed" - ); + assert_eq!(polimec_delta_alice_plmc_balance, 0, "Polimec ALICE PLMC balance should not have changed"); assert_eq!(polimec_delta_plmc_issuance, 0, "Polimec PLMC issuance should not have changed"); } diff --git a/nodes/parachain/src/chain_spec.rs b/nodes/parachain/src/chain_spec.rs index 7c6a1dc99..920f71dbd 100644 --- a/nodes/parachain/src/chain_spec.rs +++ b/nodes/parachain/src/chain_spec.rs @@ -32,15 +32,11 @@ const DEFAULT_PARA_ID: ParaId = LOWEST_PUBLIC_ID; /// Helper function to generate a crypto pair from seed pub fn get_from_seed(seed: &str) -> ::Public { - TPublic::Pair::from_string(&format!("//{seed}"), None) - .expect("static values are valid; qed") - .public() + TPublic::Pair::from_string(&format!("//{seed}"), None).expect("static values are valid; qed").public() } /// The extensions for the [`ChainSpec`]. -#[derive( - Debug, Clone, Eq, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension, -)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)] #[serde(deny_unknown_fields)] pub struct Extensions { /// The relay chain of the Parachain. diff --git a/nodes/parachain/src/chain_spec/base.rs b/nodes/parachain/src/chain_spec/base.rs index 48fa084bc..c1e167fa7 100644 --- a/nodes/parachain/src/chain_spec/base.rs +++ b/nodes/parachain/src/chain_spec/base.rs @@ -31,9 +31,8 @@ use base_runtime::{ inflation::{perbill_annual_to_perbill_round, BLOCKS_PER_YEAR}, InflationInfo, Range, }, - AccountId, AuraId as AuthorityId, Balance, BalancesConfig, GenesisConfig, MinCandidateStk, - ParachainInfoConfig, ParachainStakingConfig, PolkadotXcmConfig, SessionConfig, SudoConfig, - SystemConfig, PLMC, + AccountId, AuraId as AuthorityId, Balance, BalancesConfig, GenesisConfig, MinCandidateStk, ParachainInfoConfig, + ParachainStakingConfig, PolkadotXcmConfig, SessionConfig, SudoConfig, SystemConfig, PLMC, }; /// The default XCM version to set in genesis config. @@ -55,11 +54,8 @@ pub fn polimec_inflation_config() -> InflationInfo { ) } - let annual = Range { - min: Perbill::from_percent(2), - ideal: Perbill::from_percent(3), - max: Perbill::from_percent(3), - }; + let annual = + Range { min: Perbill::from_percent(2), ideal: Perbill::from_percent(3), max: Perbill::from_percent(3) }; InflationInfo { // staking expectations @@ -86,16 +82,8 @@ pub fn get_local_base_chain_spec() -> Result { base_testnet_genesis( wasm, vec![ - ( - get_account_id_from_seed::("Alice"), - None, - 2 * MinCandidateStk::get(), - ), - ( - get_account_id_from_seed::("Bob"), - None, - 2 * MinCandidateStk::get(), - ), + (get_account_id_from_seed::("Alice"), None, 2 * MinCandidateStk::get()), + (get_account_id_from_seed::("Bob"), None, 2 * MinCandidateStk::get()), ], polimec_inflation_config(), vec![ @@ -103,30 +91,12 @@ pub fn get_local_base_chain_spec() -> Result { get_account_id_from_seed::("Bob"), ], vec![ - ( - get_account_id_from_seed::("Alice"), - 5 * MinCandidateStk::get(), - ), - ( - get_account_id_from_seed::("Bob"), - 5 * MinCandidateStk::get(), - ), - ( - get_account_id_from_seed::("Charlie"), - 5 * MinCandidateStk::get(), - ), - ( - get_account_id_from_seed::("Dave"), - 5 * MinCandidateStk::get(), - ), - ( - get_account_id_from_seed::("Eve"), - 5 * MinCandidateStk::get(), - ), - ( - get_account_id_from_seed::("Ferdie"), - 5 * MinCandidateStk::get(), - ), + (get_account_id_from_seed::("Alice"), 5 * MinCandidateStk::get()), + (get_account_id_from_seed::("Bob"), 5 * MinCandidateStk::get()), + (get_account_id_from_seed::("Charlie"), 5 * MinCandidateStk::get()), + (get_account_id_from_seed::("Dave"), 5 * MinCandidateStk::get()), + (get_account_id_from_seed::("Eve"), 5 * MinCandidateStk::get()), + (get_account_id_from_seed::("Ferdie"), 5 * MinCandidateStk::get()), ], get_account_id_from_seed::("Alice"), DEFAULT_PARA_ID, diff --git a/nodes/parachain/src/chain_spec/testnet.rs b/nodes/parachain/src/chain_spec/testnet.rs index d71f3cb6a..e32191cf0 100644 --- a/nodes/parachain/src/chain_spec/testnet.rs +++ b/nodes/parachain/src/chain_spec/testnet.rs @@ -28,9 +28,8 @@ use polimec_parachain_runtime::{ }; use polimec_parachain_runtime::{ - AccountId, Balance, BalancesConfig, CouncilConfig, GenesisConfig, ParachainInfoConfig, - PolkadotXcmConfig, SessionConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig, - VestingConfig, + AccountId, Balance, BalancesConfig, CouncilConfig, GenesisConfig, ParachainInfoConfig, PolkadotXcmConfig, + SessionConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig, VestingConfig, }; use sc_service::ChainType; use sp_core::{crypto::UncheckedInto, sr25519}; @@ -58,11 +57,8 @@ pub fn polimec_inflation_config() -> InflationInfo { ) } - let annual = Range { - min: Perbill::from_percent(2), - ideal: Perbill::from_percent(3), - max: Perbill::from_percent(3), - }; + let annual = + Range { min: Perbill::from_percent(2), ideal: Perbill::from_percent(3), max: Perbill::from_percent(3) }; InflationInfo { // staking expectations @@ -89,16 +85,8 @@ pub fn get_chain_spec_dev() -> Result { testnet_genesis( wasm, vec![ - ( - get_account_id_from_seed::("Alice"), - None, - 2 * MinCandidateStk::get(), - ), - ( - get_account_id_from_seed::("Bob"), - None, - 2 * MinCandidateStk::get(), - ), + (get_account_id_from_seed::("Alice"), None, 2 * MinCandidateStk::get()), + (get_account_id_from_seed::("Bob"), None, 2 * MinCandidateStk::get()), ], polimec_inflation_config(), vec![ @@ -106,30 +94,12 @@ pub fn get_chain_spec_dev() -> Result { get_account_id_from_seed::("Bob"), ], vec![ - ( - get_account_id_from_seed::("Alice"), - 5 * MinCandidateStk::get(), - ), - ( - get_account_id_from_seed::("Bob"), - 5 * MinCandidateStk::get(), - ), - ( - get_account_id_from_seed::("Charlie"), - 5 * MinCandidateStk::get(), - ), - ( - get_account_id_from_seed::("Dave"), - 5 * MinCandidateStk::get(), - ), - ( - get_account_id_from_seed::("Eve"), - 5 * MinCandidateStk::get(), - ), - ( - get_account_id_from_seed::("Ferdie"), - 5 * MinCandidateStk::get(), - ), + (get_account_id_from_seed::("Alice"), 5 * MinCandidateStk::get()), + (get_account_id_from_seed::("Bob"), 5 * MinCandidateStk::get()), + (get_account_id_from_seed::("Charlie"), 5 * MinCandidateStk::get()), + (get_account_id_from_seed::("Dave"), 5 * MinCandidateStk::get()), + (get_account_id_from_seed::("Eve"), 5 * MinCandidateStk::get()), + (get_account_id_from_seed::("Ferdie"), 5 * MinCandidateStk::get()), ], get_account_id_from_seed::("Alice"), DEFAULT_PARA_ID, @@ -228,9 +198,7 @@ fn testnet_genesis( ( acc.clone(), acc.clone(), - get_testnet_session_keys( - Into::<[u8; 32]>::into(acc.clone()).unchecked_into(), - ), + get_testnet_session_keys(Into::<[u8; 32]>::into(acc.clone()).unchecked_into()), ) }) .collect::>(), @@ -239,10 +207,7 @@ fn testnet_genesis( treasury: Default::default(), sudo: SudoConfig { key: Some(sudo_account) }, council: CouncilConfig { members: accounts.clone(), phantom: Default::default() }, - technical_committee: TechnicalCommitteeConfig { - members: accounts.clone(), - phantom: Default::default(), - }, + technical_committee: TechnicalCommitteeConfig { members: accounts.clone(), phantom: Default::default() }, democracy: Default::default(), vesting: VestingConfig { vesting: vec![] }, } diff --git a/nodes/parachain/src/cli.rs b/nodes/parachain/src/cli.rs index e99d6dc94..4a184008b 100644 --- a/nodes/parachain/src/cli.rs +++ b/nodes/parachain/src/cli.rs @@ -61,11 +61,7 @@ pub enum Subcommand { } #[derive(Debug, clap::Parser)] -#[command( - propagate_version = true, - args_conflicts_with_subcommands = true, - subcommand_negates_reqs = true -)] +#[command(propagate_version = true, args_conflicts_with_subcommands = true, subcommand_negates_reqs = true)] pub struct Cli { #[command(subcommand)] pub subcommand: Option, diff --git a/nodes/parachain/src/command.rs b/nodes/parachain/src/command.rs index c46e4a73c..82b0ce4f6 100644 --- a/nodes/parachain/src/command.rs +++ b/nodes/parachain/src/command.rs @@ -23,8 +23,8 @@ use log::{info, warn}; use parity_scale_codec::Encode; use polimec_parachain_runtime::Block; use sc_cli::{ - ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, - NetworkParams, Result, RuntimeVersion, SharedParams, SubstrateCli, + ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, NetworkParams, Result, + RuntimeVersion, SharedParams, SubstrateCli, }; use sc_service::config::{BasePath, PrometheusConfig}; use sp_core::hexdisplay::HexDisplay; @@ -65,8 +65,8 @@ impl RuntimeResolver for PathBuf { let file = std::fs::File::open(self).expect("Failed to open file"); let reader = std::io::BufReader::new(file); - let chain_spec: EmptyChainSpecWithId = sp_serializer::from_reader(reader) - .expect("Failed to read 'json' file with ChainSpec configuration"); + let chain_spec: EmptyChainSpecWithId = + sp_serializer::from_reader(reader).expect("Failed to read 'json' file with ChainSpec configuration"); runtime(&chain_spec.id) } } @@ -98,9 +98,7 @@ fn load_spec(id: &str) -> std::result::Result, String> { "polimec-polkadot" => Box::new(chain_spec::testnet::get_prod_chain_spec()?), // -- Fallback (generic chainspec) "" => { - log::warn!( - "No ChainSpec.id specified, so using default one, based on polimec-rococo-local" - ); + log::warn!("No ChainSpec.id specified, so using default one, based on polimec-rococo-local"); Box::new(chain_spec::testnet::get_chain_spec_dev()?) }, // A custom chainspec path @@ -221,14 +219,10 @@ pub fn run() -> Result<()> { }) }, Some(Subcommand::ExportBlocks(cmd)) => { - construct_async_run!(|components, cli, cmd, config| Ok( - cmd.run(components.client, config.database) - )) + construct_async_run!(|components, cli, cmd, config| Ok(cmd.run(components.client, config.database))) }, Some(Subcommand::ExportState(cmd)) => { - construct_async_run!(|components, cli, cmd, config| Ok( - cmd.run(components.client, config.chain_spec) - )) + construct_async_run!(|components, cli, cmd, config| Ok(cmd.run(components.client, config.chain_spec))) }, Some(Subcommand::ImportBlocks(cmd)) => { construct_async_run!(|components, cli, cmd, config| { @@ -249,12 +243,9 @@ pub fn run() -> Result<()> { [RelayChainCli::executable_name()].iter().chain(cli.relay_chain_args.iter()), ); - let polkadot_config = SubstrateCli::create_configuration( - &polkadot_cli, - &polkadot_cli, - config.tokio_handle.clone(), - ) - .map_err(|err| format!("Relay chain argument error: {}", err))?; + let polkadot_config = + SubstrateCli::create_configuration(&polkadot_cli, &polkadot_cli, config.tokio_handle.clone()) + .map_err(|err| format!("Relay chain argument error: {}", err))?; cmd.run(config, polkadot_config) }) @@ -325,13 +316,10 @@ pub fn run() -> Result<()> { // grab the task manager. let registry = &runner.config().prometheus_config.as_ref().map(|cfg| &cfg.registry); - let task_manager = - sc_service::TaskManager::new(runner.config().tokio_handle.clone(), *registry) - .map_err(|e| format!("Error: {:?}", e))?; + let task_manager = sc_service::TaskManager::new(runner.config().tokio_handle.clone(), *registry) + .map_err(|e| format!("Error: {:?}", e))?; - runner.async_run(|_| { - Ok((cmd.run::>(), task_manager)) - }) + runner.async_run(|_| Ok((cmd.run::>(), task_manager))) }, #[cfg(not(feature = "try-runtime"))] Some(Subcommand::TryRuntime) => Err("Try-runtime was not enabled when building the node. \ @@ -434,10 +422,7 @@ impl CliConfiguration for RelayChainCli { } fn base_path(&self) -> Result> { - Ok(self - .shared_params() - .base_path()? - .or_else(|| self.base_path.clone().map(Into::into))) + Ok(self.shared_params().base_path()?.or_else(|| self.base_path.clone().map(Into::into))) } fn rpc_http(&self, default_listen_port: u16) -> Result> { @@ -523,10 +508,7 @@ impl CliConfiguration for RelayChainCli { self.base.base.announce_block() } - fn telemetry_endpoints( - &self, - chain_spec: &Box, - ) -> Result> { + fn telemetry_endpoints(&self, chain_spec: &Box) -> Result> { self.base.base.telemetry_endpoints(chain_spec) } diff --git a/nodes/parachain/src/rpc.rs b/nodes/parachain/src/rpc.rs index 6cff4195a..44a745abe 100644 --- a/nodes/parachain/src/rpc.rs +++ b/nodes/parachain/src/rpc.rs @@ -43,9 +43,7 @@ pub struct FullDeps { } /// Instantiate all RPC extensions. -pub fn create_full( - deps: FullDeps, -) -> Result> +pub fn create_full(deps: FullDeps) -> Result> where C: ProvideRuntimeApi + HeaderBackend diff --git a/nodes/parachain/src/service.rs b/nodes/parachain/src/service.rs index d21e7b66c..ea54c0fa9 100644 --- a/nodes/parachain/src/service.rs +++ b/nodes/parachain/src/service.rs @@ -25,12 +25,10 @@ use polimec_parachain_runtime::{opaque::Block, RuntimeApi}; // Cumulus Imports use cumulus_client_consensus_aura::{AuraConsensus, BuildAuraConsensusParams, SlotProportion}; -use cumulus_client_consensus_common::{ - ParachainBlockImport as TParachainBlockImport, ParachainConsensus, -}; +use cumulus_client_consensus_common::{ParachainBlockImport as TParachainBlockImport, ParachainConsensus}; use cumulus_client_service::{ - build_network, build_relay_chain_interface, prepare_node_config, start_collator, - start_full_node, BuildNetworkParams, StartCollatorParams, StartFullNodeParams, + build_network, build_relay_chain_interface, prepare_node_config, start_collator, start_full_node, + BuildNetworkParams, StartCollatorParams, StartFullNodeParams, }; use cumulus_primitives_core::ParaId; use cumulus_relay_chain_interface::RelayChainInterface; @@ -38,9 +36,7 @@ use cumulus_relay_chain_interface::RelayChainInterface; // Substrate Imports use frame_benchmarking_cli::SUBSTRATE_REFERENCE_HARDWARE; use sc_consensus::ImportQueue; -use sc_executor::{ - HeapAllocStrategy, NativeElseWasmExecutor, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY, -}; +use sc_executor::{HeapAllocStrategy, NativeElseWasmExecutor, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY}; use sc_network::NetworkBlock; use sc_network_sync::SyncingService; use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager}; @@ -114,12 +110,11 @@ pub fn new_partial( let executor = ParachainExecutor::new_with_wasm_executor(wasm); - let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( - config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; + let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( + config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, + )?; let client = Arc::new(client); let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle()); @@ -222,11 +217,7 @@ async fn start_node_impl( let transaction_pool = transaction_pool.clone(); Box::new(move |deny_unsafe, _| { - let deps = crate::rpc::FullDeps { - client: client.clone(), - pool: transaction_pool.clone(), - deny_unsafe, - }; + let deps = crate::rpc::FullDeps { client: client.clone(), pool: transaction_pool.clone(), deny_unsafe }; crate::rpc::create_full(deps).map_err(Into::into) }) @@ -253,9 +244,7 @@ async fn start_node_impl( // in there and swapping out the requirements for your own are probably a good idea. The // requirements for a para-chain are dictated by its relay-chain. if !SUBSTRATE_REFERENCE_HARDWARE.check_hardware(&hwbench) && validator { - log::warn!( - "⚠️ The hardware does not meet the minimal requirements for role 'Authority'." - ); + log::warn!("⚠️ The hardware does not meet the minimal requirements for role 'Authority'."); } if let Some(ref mut telemetry) = telemetry { @@ -275,9 +264,8 @@ async fn start_node_impl( let relay_chain_slot_duration = Duration::from_secs(6); - let overseer_handle = relay_chain_interface - .overseer_handle() - .map_err(|e| sc_service::Error::Application(Box::new(e)))?; + let overseer_handle = + relay_chain_interface.overseer_handle().map_err(|e| sc_service::Error::Application(Box::new(e)))?; if validator { let parachain_consensus = build_consensus( @@ -343,31 +331,25 @@ fn build_import_queue( ) -> Result, sc_service::Error> { let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; - cumulus_client_consensus_aura::import_queue::< - sp_consensus_aura::sr25519::AuthorityPair, - _, - _, - _, - _, - _, - >(cumulus_client_consensus_aura::ImportQueueParams { - block_import, - client, - create_inherent_data_providers: move |_, _| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + cumulus_client_consensus_aura::import_queue::( + cumulus_client_consensus_aura::ImportQueueParams { + block_import, + client, + create_inherent_data_providers: move |_, _| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, slot_duration, ); - Ok((slot, timestamp)) + Ok((slot, timestamp)) + }, + registry: config.prometheus_registry(), + spawner: &task_manager.spawn_essential_handle(), + telemetry, }, - registry: config.prometheus_registry(), - spawner: &task_manager.spawn_essential_handle(), - telemetry, - }) + ) .map_err(Into::into) } @@ -400,26 +382,22 @@ fn build_consensus( create_inherent_data_providers: move |_, (relay_parent, validation_data)| { let relay_chain_interface = relay_chain_interface.clone(); async move { - let parachain_inherent = - cumulus_primitives_parachain_inherent::ParachainInherentData::create_at( - relay_parent, - &relay_chain_interface, - &validation_data, - para_id, - ) - .await; + let parachain_inherent = cumulus_primitives_parachain_inherent::ParachainInherentData::create_at( + relay_parent, + &relay_chain_interface, + &validation_data, + para_id, + ) + .await; let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); let parachain_inherent = parachain_inherent.ok_or_else(|| { - Box::::from( - "Failed to create parachain inherent", - ) + Box::::from("Failed to create parachain inherent") })?; Ok((slot, timestamp, parachain_inherent)) } diff --git a/nodes/standalone/src/benchmarking.rs b/nodes/standalone/src/benchmarking.rs index 9ecb50ae6..cf1c1c51c 100644 --- a/nodes/standalone/src/benchmarking.rs +++ b/nodes/standalone/src/benchmarking.rs @@ -56,13 +56,9 @@ impl frame_benchmarking_cli::ExtrinsicBuilder for RemarkBuilder { fn build(&self, nonce: u32) -> std::result::Result { let acc = Sr25519Keyring::Bob.pair(); - let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic( - self.client.as_ref(), - acc, - SystemCall::remark { remark: vec![] }.into(), - nonce, - ) - .into(); + let extrinsic: OpaqueExtrinsic = + create_benchmark_extrinsic(self.client.as_ref(), acc, SystemCall::remark { remark: vec![] }.into(), nonce) + .into(); Ok(extrinsic) } @@ -98,11 +94,7 @@ impl frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder { let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic( self.client.as_ref(), acc, - BalancesCall::transfer_keep_alive { - dest: self.dest.clone().into(), - value: self.value.into(), - } - .into(), + BalancesCall::transfer_keep_alive { dest: self.dest.clone().into(), value: self.value.into() }.into(), nonce, ) .into(); @@ -124,10 +116,7 @@ pub fn create_benchmark_extrinsic( let best_hash = client.chain_info().best_hash; let best_block = client.chain_info().best_number; - let period = runtime::BlockHashCount::get() - .checked_next_power_of_two() - .map(|c| c / 2) - .unwrap_or(2) as u64; + let period = runtime::BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2) as u64; let extra: runtime::SignedExtra = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), @@ -145,16 +134,7 @@ pub fn create_benchmark_extrinsic( let raw_payload = runtime::SignedPayload::from_raw( call.clone(), extra.clone(), - ( - (), - runtime::VERSION.spec_version, - runtime::VERSION.transaction_version, - genesis_hash, - best_hash, - (), - (), - (), - ), + ((), runtime::VERSION.spec_version, runtime::VERSION.transaction_version, genesis_hash, best_hash, (), (), ()), ); let signature = raw_payload.using_encoded(|e| sender.sign(e)); diff --git a/nodes/standalone/src/chain_spec.rs b/nodes/standalone/src/chain_spec.rs index ec044fd58..8d7e956c7 100644 --- a/nodes/standalone/src/chain_spec.rs +++ b/nodes/standalone/src/chain_spec.rs @@ -15,8 +15,7 @@ // along with this program. If not, see . use polimec_standalone_runtime::{ - AccountId, BalancesConfig, GenesisConfig, SessionConfig, Signature, SudoConfig, SystemConfig, - WASM_BINARY, + AccountId, BalancesConfig, GenesisConfig, SessionConfig, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use sc_service::{ChainType, Properties}; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -39,9 +38,7 @@ fn polimec_properties() -> Properties { /// Helper function to generate a crypto pair from seed fn get_from_secret(seed: &str) -> ::Public { - TPublic::Pair::from_string(seed, None) - .unwrap_or_else(|_| panic!("Invalid string '{seed}'")) - .public() + TPublic::Pair::from_string(seed, None).unwrap_or_else(|_| panic!("Invalid string '{seed}'")).public() } /// Helper function to generate an account ID from seed @@ -120,10 +117,7 @@ pub fn local_testnet_config() -> Result { testnet_genesis( wasm_binary, // Initial PoA authorities - vec![ - get_authority_keys_from_secret("//Alice"), - get_authority_keys_from_secret("//Bob"), - ], + vec![get_authority_keys_from_secret("//Alice"), get_authority_keys_from_secret("//Bob")], // Sudo account get_account_id_from_secret::("//Alice"), // Pre-funded accounts @@ -184,10 +178,7 @@ fn testnet_genesis( ( x.0.clone(), x.0.clone(), - polimec_standalone_runtime::opaque::SessionKeys { - aura: x.1.clone(), - grandpa: x.2.clone(), - }, + polimec_standalone_runtime::opaque::SessionKeys { aura: x.1.clone(), grandpa: x.2.clone() }, ) }) .collect::>(), diff --git a/nodes/standalone/src/command.rs b/nodes/standalone/src/command.rs index 892c41ce5..8f07f6943 100644 --- a/nodes/standalone/src/command.rs +++ b/nodes/standalone/src/command.rs @@ -42,8 +42,7 @@ impl SubstrateCli for Cli { Ok(match id { "dev" => Box::new(chain_spec::development_config()?), "" | "local" => Box::new(chain_spec::local_testnet_config()?), - path => - Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?), + path => Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?), }) } @@ -65,8 +64,7 @@ pub fn run() -> sc_cli::Result<()> { Some(Subcommand::CheckBlock(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { client, task_manager, import_queue, .. } = - service::new_partial(&config)?; + let PartialComponents { client, task_manager, import_queue, .. } = service::new_partial(&config)?; Ok((cmd.run(client, import_queue), task_manager)) }) }, @@ -87,8 +85,7 @@ pub fn run() -> sc_cli::Result<()> { Some(Subcommand::ImportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { client, task_manager, import_queue, .. } = - service::new_partial(&config)?; + let PartialComponents { client, task_manager, import_queue, .. } = service::new_partial(&config)?; Ok((cmd.run(client, import_queue), task_manager)) }) }, @@ -99,8 +96,7 @@ pub fn run() -> sc_cli::Result<()> { Some(Subcommand::Revert(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { client, task_manager, backend, .. } = - service::new_partial(&config)?; + let PartialComponents { client, task_manager, backend, .. } = service::new_partial(&config)?; let aux_revert = Box::new(|client, _, blocks| { sc_consensus_grandpa::revert(client, blocks)?; Ok(()) @@ -117,11 +113,9 @@ pub fn run() -> sc_cli::Result<()> { match cmd { BenchmarkCmd::Pallet(cmd) => { if !cfg!(feature = "runtime-benchmarks") { - return Err( - "Runtime benchmarking wasn't enabled when building the node. \ + return Err("Runtime benchmarking wasn't enabled when building the node. \ You can enable it with `--features runtime-benchmarks`." - .into(), - ) + .into()) } cmd.run::(config) @@ -131,14 +125,11 @@ pub fn run() -> sc_cli::Result<()> { cmd.run(client) }, #[cfg(not(feature = "runtime-benchmarks"))] - BenchmarkCmd::Storage(_) => Err( - "Storage benchmarking can be enabled with `--features runtime-benchmarks`." - .into(), - ), + BenchmarkCmd::Storage(_) => + Err("Storage benchmarking can be enabled with `--features runtime-benchmarks`.".into()), #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => { - let PartialComponents { client, backend, .. } = - service::new_partial(&config)?; + let PartialComponents { client, backend, .. } = service::new_partial(&config)?; let db = backend.expose_db(); let storage = backend.expose_storage(); @@ -148,13 +139,7 @@ pub fn run() -> sc_cli::Result<()> { let PartialComponents { client, .. } = service::new_partial(&config)?; let ext_builder = RemarkBuilder::new(client.clone()); - cmd.run( - config, - client, - inherent_benchmark_data()?, - Vec::new(), - &ext_builder, - ) + cmd.run(config, client, inherent_benchmark_data()?, Vec::new(), &ext_builder) }, BenchmarkCmd::Extrinsic(cmd) => { let PartialComponents { client, .. } = service::new_partial(&config)?; @@ -170,8 +155,7 @@ pub fn run() -> sc_cli::Result<()> { cmd.run(client, inherent_benchmark_data()?, Vec::new(), &ext_factory) }, - BenchmarkCmd::Machine(cmd) => - cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone()), + BenchmarkCmd::Machine(cmd) => cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone()), } }) }, @@ -184,9 +168,8 @@ pub fn run() -> sc_cli::Result<()> { // we don't need any of the components of new_partial, just a runtime, or a task // manager to do `async_run`. let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); - let task_manager = - sc_service::TaskManager::new(config.tokio_handle.clone(), registry) - .map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?; + let task_manager = sc_service::TaskManager::new(config.tokio_handle.clone(), registry) + .map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?; let info_provider = timestamp_with_aura_info(6000); Ok(( @@ -208,9 +191,8 @@ pub fn run() -> sc_cli::Result<()> { }, None => { let runner = cli.create_runner(&cli.run)?; - runner.run_node_until_exit(|config| async move { - service::new_full(config).map_err(sc_cli::Error::Service) - }) + runner + .run_node_until_exit(|config| async move { service::new_full(config).map_err(sc_cli::Error::Service) }) }, } } diff --git a/nodes/standalone/src/rpc.rs b/nodes/standalone/src/rpc.rs index d1cd753fd..495ce1991 100644 --- a/nodes/standalone/src/rpc.rs +++ b/nodes/standalone/src/rpc.rs @@ -43,9 +43,7 @@ pub struct FullDeps { } /// Instantiate all full RPC extensions. -pub fn create_full( - deps: FullDeps, -) -> Result, Box> +pub fn create_full(deps: FullDeps) -> Result, Box> where C: ProvideRuntimeApi, C: HeaderBackend + HeaderMetadata + 'static, diff --git a/nodes/standalone/src/service.rs b/nodes/standalone/src/service.rs index 0ce896d35..56ac2c958 100644 --- a/nodes/standalone/src/service.rs +++ b/nodes/standalone/src/service.rs @@ -46,8 +46,7 @@ impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { } } -pub(crate) type FullClient = - sc_service::TFullClient>; +pub(crate) type FullClient = sc_service::TFullClient>; type FullBackend = sc_service::TFullBackend; type FullSelectChain = sc_consensus::LongestChain; @@ -61,12 +60,7 @@ pub fn new_partial( sc_consensus::DefaultImportQueue, sc_transaction_pool::FullPool, ( - sc_consensus_grandpa::GrandpaBlockImport< - FullBackend, - Block, - FullClient, - FullSelectChain, - >, + sc_consensus_grandpa::GrandpaBlockImport, sc_consensus_grandpa::LinkHalf, Option, ), @@ -86,12 +80,11 @@ pub fn new_partial( let executor = sc_service::new_native_or_wasm_executor(&config); - let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( - config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; + let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( + config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, + )?; let client = Arc::new(client); let telemetry = telemetry.map(|(worker, telemetry)| { @@ -118,28 +111,26 @@ pub fn new_partial( let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - let import_queue = - sc_consensus_aura::import_queue::(ImportQueueParams { - block_import: grandpa_block_import.clone(), - justification_import: Some(Box::new(grandpa_block_import.clone())), - client: client.clone(), - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); + let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { + block_import: grandpa_block_import.clone(), + justification_import: Some(Box::new(grandpa_block_import.clone())), + client: client.clone(), + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - Ok((slot, timestamp)) - }, - spawner: &task_manager.spawn_essential_handle(), - registry: config.prometheus_registry(), - check_for_equivocation: Default::default(), - telemetry: telemetry.as_ref().map(|x| x.handle()), - compatibility_mode: Default::default(), - })?; + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); + + Ok((slot, timestamp)) + }, + spawner: &task_manager.spawn_essential_handle(), + registry: config.prometheus_registry(), + check_for_equivocation: Default::default(), + telemetry: telemetry.as_ref().map(|x| x.handle()), + compatibility_mode: Default::default(), + })?; Ok(sc_service::PartialComponents { client, @@ -171,10 +162,7 @@ pub fn new_full(mut config: Configuration) -> Result &config.chain_spec, ); - config - .network - .extra_sets - .push(sc_consensus_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone())); + config.network.extra_sets.push(sc_consensus_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone())); let warp_sync = Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), @@ -193,12 +181,7 @@ pub fn new_full(mut config: Configuration) -> Result })?; if config.offchain_worker.enabled { - sc_service::build_offchain_workers( - &config, - task_manager.spawn_handle(), - client.clone(), - network.clone(), - ); + sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); } let role = config.role.clone(); @@ -213,8 +196,7 @@ pub fn new_full(mut config: Configuration) -> Result let pool = transaction_pool.clone(); Box::new(move |deny_unsafe, _| { - let deps = - crate::rpc::FullDeps { client: client.clone(), pool: pool.clone(), deny_unsafe }; + let deps = crate::rpc::FullDeps { client: client.clone(), pool: pool.clone(), deny_unsafe }; crate::rpc::create_full(deps).map_err(Into::into) }) }; @@ -245,41 +227,36 @@ pub fn new_full(mut config: Configuration) -> Result let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - let aura = sc_consensus_aura::start_aura::( - StartAuraParams { - slot_duration, - client, - select_chain, - block_import, - proposer_factory, - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); - - Ok((slot, timestamp)) - }, - force_authoring, - backoff_authoring_blocks, - keystore: keystore_container.keystore(), - sync_oracle: sync_service.clone(), - justification_sync_link: sync_service.clone(), - block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), - max_block_proposal_slot_portion: None, - telemetry: telemetry.as_ref().map(|x| x.handle()), - compatibility_mode: Default::default(), + let aura = sc_consensus_aura::start_aura::(StartAuraParams { + slot_duration, + client, + select_chain, + block_import, + proposer_factory, + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); + + Ok((slot, timestamp)) }, - )?; + force_authoring, + backoff_authoring_blocks, + keystore: keystore_container.keystore(), + sync_oracle: sync_service.clone(), + justification_sync_link: sync_service.clone(), + block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), + max_block_proposal_slot_portion: None, + telemetry: telemetry.as_ref().map(|x| x.handle()), + compatibility_mode: Default::default(), + })?; // the AURA authoring task is considered essential, i.e. if it // fails we take down the service with it. - task_manager - .spawn_essential_handle() - .spawn_blocking("aura", Some("block-authoring"), aura); + task_manager.spawn_essential_handle().spawn_blocking("aura", Some("block-authoring"), aura); } if enable_grandpa { diff --git a/pallets/funding/src/benchmarking.rs b/pallets/funding/src/benchmarking.rs index e443e7cb3..359096b49 100644 --- a/pallets/funding/src/benchmarking.rs +++ b/pallets/funding/src/benchmarking.rs @@ -62,15 +62,10 @@ fn assert_last_event(generic_event: ::RuntimeEvent) { #[allow(unused)] fn get_events() -> frame_benchmarking::Vec<::RuntimeEvent> { - frame_system::Pallet::::events() - .into_iter() - .map(|r| r.event) - .collect::>() + frame_system::Pallet::::events().into_iter().map(|r| r.event).collect::>() } -fn create_default_project( - id: Option, -) -> (T::ProjectIdParameter, T::AccountId, ProjectMetadataOf) { +fn create_default_project(id: Option) -> (T::ProjectIdParameter, T::AccountId, ProjectMetadataOf) { let issuer: T::AccountId = account::("Alice", 1, 1); let project_id_parameter = id.unwrap_or(0); let project_id = T::BenchmarkHelper::create_project_id_parameter(project_id_parameter); @@ -79,13 +74,9 @@ fn create_default_project( (project_id, issuer, project) } -fn create_default_minted_project( - id: Option, -) -> (T::ProjectIdParameter, T::AccountId) { +fn create_default_minted_project(id: Option) -> (T::ProjectIdParameter, T::AccountId) { let (project_id, issuer, project) = create_default_project::(id); - assert!( - PolimecFunding::::create(SystemOrigin::Signed(issuer.clone()).into(), project).is_ok() - ); + assert!(PolimecFunding::::create(SystemOrigin::Signed(issuer.clone()).into(), project).is_ok()); (project_id, issuer) } @@ -95,9 +86,7 @@ pub fn run_to_block(n: T::BlockNumber) { crate::Pallet::::on_finalize(frame_system::Pallet::::block_number()); frame_system::Pallet::::on_finalize(frame_system::Pallet::::block_number()); crate::Pallet::::on_idle(frame_system::Pallet::::block_number(), max_weight); - frame_system::Pallet::::set_block_number( - frame_system::Pallet::::block_number() + One::one(), - ); + frame_system::Pallet::::set_block_number(frame_system::Pallet::::block_number() + One::one()); frame_system::Pallet::::on_initialize(frame_system::Pallet::::block_number()); crate::Pallet::::on_initialize(frame_system::Pallet::::block_number()); crate::Pallet::::on_idle(frame_system::Pallet::::block_number(), max_weight); diff --git a/pallets/funding/src/functions.rs b/pallets/funding/src/functions.rs index 9c2e4e839..0a32ddea2 100644 --- a/pallets/funding/src/functions.rs +++ b/pallets/funding/src/functions.rs @@ -48,10 +48,7 @@ impl Pallet { /// # Next step /// The issuer will call an extrinsic to start the evaluation round of the project. /// [`do_evaluation_start`](Self::do_evaluation_start) will be executed. - pub fn do_create( - issuer: T::AccountId, - project: ProjectMetadataOf, - ) -> Result<(), DispatchError> { + pub fn do_create(issuer: T::AccountId, project: ProjectMetadataOf) -> Result<(), DispatchError> { // TODO: Probably the issuers don't want to sell all of their tokens. Is there some logic for this? // also even if an issuer wants to sell all their tokens, they could target a lower amount than that to consider it a success // * Get variables * @@ -66,8 +63,7 @@ impl Pallet { if let Err(error) = project.validity_check() { return match error { ValidityError::PriceTooLow => Err(Error::::PriceTooLow.into()), - ValidityError::ParticipantsSizeError => - Err(Error::::ParticipantsSizeError.into()), + ValidityError::ParticipantsSizeError => Err(Error::::ParticipantsSizeError.into()), ValidityError::TicketSizeError => Err(Error::::TicketSizeError.into()), } } @@ -79,10 +75,7 @@ impl Pallet { fundraising_target, project_status: ProjectStatus::Application, phase_transition_points: PhaseTransitionPoints { - application: BlockNumberPair::new( - Some(>::block_number()), - None, - ), + application: BlockNumberPair::new(Some(>::block_number()), None), evaluation: BlockNumberPair::new(None, None), auction_initialize_period: BlockNumberPair::new(None, None), english_auction: BlockNumberPair::new(None, None), @@ -128,26 +121,19 @@ impl Pallet { /// to the next round by `on_initialize` using [`do_evaluation_end`](Self::do_evaluation_end) pub fn do_evaluation_start(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; let now = >::block_number(); // * Validity checks * - ensure!( - project_info.project_status == ProjectStatus::Application, - Error::::ProjectNotInApplicationRound - ); + ensure!(project_info.project_status == ProjectStatus::Application, Error::::ProjectNotInApplicationRound); ensure!(!project_info.is_frozen, Error::::ProjectAlreadyFrozen); ensure!(project.offchain_information_hash.is_some(), Error::::MetadataNotProvided); // * Calculate new variables * let evaluation_end_block = now + T::EvaluationDuration::get(); project_info.phase_transition_points.application.update(None, Some(now)); - project_info - .phase_transition_points - .evaluation - .update(Some(now + 1u32.into()), Some(evaluation_end_block)); + project_info.phase_transition_points.evaluation.update(Some(now + 1u32.into()), Some(evaluation_end_block)); project_info.is_frozen = true; project_info.project_status = ProjectStatus::EvaluationRound; @@ -155,10 +141,7 @@ impl Pallet { // TODO: Should we make it possible to end an application, and schedule for a later point the evaluation? // Or should we just make it so that the evaluation starts immediately after the application ends? ProjectsDetails::::insert(project_id, project_info); - Self::add_to_update_store( - evaluation_end_block + 1u32.into(), - (&project_id, UpdateType::EvaluationEnd), - ); + Self::add_to_update_store(evaluation_end_block + 1u32.into(), (&project_id, UpdateType::EvaluationEnd)); // * Emit events * Self::deposit_event(Event::::EvaluationStarted { project_id }); @@ -196,21 +179,14 @@ impl Pallet { /// unbonds the evaluators funds. pub fn do_evaluation_end(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); - let evaluation_end_block = project_info - .phase_transition_points - .evaluation - .end() - .ok_or(Error::::FieldIsNone)?; + let evaluation_end_block = + project_info.phase_transition_points.evaluation.end().ok_or(Error::::FieldIsNone)?; let fundraising_target = project_info.fundraising_target; // * Validity checks * - ensure!( - project_info.project_status == ProjectStatus::EvaluationRound, - Error::::ProjectNotInEvaluationRound - ); + ensure!(project_info.project_status == ProjectStatus::EvaluationRound, Error::::ProjectNotInEvaluationRound); ensure!(now > evaluation_end_block, Error::::EvaluationPeriodNotEnded); // * Calculate new variables * @@ -232,10 +208,10 @@ impl Pallet { // Successful path if is_funded { // * Update storage * - project_info.phase_transition_points.auction_initialize_period.update( - Some(auction_initialize_period_start_block), - Some(auction_initialize_period_end_block), - ); + project_info + .phase_transition_points + .auction_initialize_period + .update(Some(auction_initialize_period_start_block), Some(auction_initialize_period_end_block)); project_info.project_status = ProjectStatus::AuctionInitializePeriod; ProjectsDetails::::insert(project_id, project_info); Self::add_to_update_store( @@ -291,8 +267,7 @@ impl Pallet { /// [`do_candle_auction`](Self::do_candle_auction). pub fn do_english_auction(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); let auction_initialize_period_start_block = project_info .phase_transition_points @@ -306,10 +281,7 @@ impl Pallet { .ok_or(Error::::EvaluationPeriodNotEnded)?; // * Validity checks * - ensure!( - now >= auction_initialize_period_start_block, - Error::::TooEarlyForEnglishAuctionStart - ); + ensure!(now >= auction_initialize_period_start_block, Error::::TooEarlyForEnglishAuctionStart); ensure!( project_info.project_status == ProjectStatus::AuctionInitializePeriod, Error::::ProjectNotInAuctionInitializePeriodRound @@ -320,10 +292,7 @@ impl Pallet { let english_end_block = now + T::EnglishAuctionDuration::get(); // * Update Storage * - project_info - .phase_transition_points - .english_auction - .update(Some(english_start_block), Some(english_end_block)); + project_info.phase_transition_points.english_auction.update(Some(english_start_block), Some(english_end_block)); project_info.project_status = ProjectStatus::AuctionRound(AuctionPhase::English); ProjectsDetails::::insert(project_id, project_info); @@ -333,10 +302,7 @@ impl Pallet { Self::remove_from_update_store(&project_id)?; } // Schedule for automatic transition to candle auction round - Self::add_to_update_store( - english_end_block + 1u32.into(), - (&project_id, UpdateType::CandleAuctionStart), - ); + Self::add_to_update_store(english_end_block + 1u32.into(), (&project_id, UpdateType::CandleAuctionStart)); // * Emit events * Self::deposit_event(Event::::EnglishAuctionStarted { project_id, when: now }); @@ -369,14 +335,10 @@ impl Pallet { /// by calling [`do_community_funding`](Self::do_community_funding). pub fn do_candle_auction(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); - let english_end_block = project_info - .phase_transition_points - .english_auction - .end() - .ok_or(Error::::FieldIsNone)?; + let english_end_block = + project_info.phase_transition_points.english_auction.end().ok_or(Error::::FieldIsNone)?; // * Validity checks * ensure!(now > english_end_block, Error::::TooEarlyForCandleAuctionStart); @@ -390,17 +352,11 @@ impl Pallet { let candle_end_block = now + T::CandleAuctionDuration::get(); // * Update Storage * - project_info - .phase_transition_points - .candle_auction - .update(Some(candle_start_block), Some(candle_end_block)); + project_info.phase_transition_points.candle_auction.update(Some(candle_start_block), Some(candle_end_block)); project_info.project_status = ProjectStatus::AuctionRound(AuctionPhase::Candle); ProjectsDetails::::insert(project_id, project_info); // Schedule for automatic check by on_initialize. Success depending on enough funding reached - Self::add_to_update_store( - candle_end_block + 1u32.into(), - (&project_id, UpdateType::CommunityFundingStart), - ); + Self::add_to_update_store(candle_end_block + 1u32.into(), (&project_id, UpdateType::CommunityFundingStart)); // * Emit events * Self::deposit_event(Event::::CandleAuctionStarted { project_id, when: now }); @@ -432,19 +388,12 @@ impl Pallet { /// starts the remainder round, where anyone can buy at that price point. pub fn do_community_funding(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); - let auction_candle_start_block = project_info - .phase_transition_points - .candle_auction - .start() - .ok_or(Error::::FieldIsNone)?; - let auction_candle_end_block = project_info - .phase_transition_points - .candle_auction - .end() - .ok_or(Error::::FieldIsNone)?; + let auction_candle_start_block = + project_info.phase_transition_points.candle_auction.start().ok_or(Error::::FieldIsNone)?; + let auction_candle_end_block = + project_info.phase_transition_points.candle_auction.end().ok_or(Error::::FieldIsNone)?; // * Validity checks * ensure!(now > auction_candle_end_block, Error::::TooEarlyForCommunityRoundStart); @@ -454,32 +403,20 @@ impl Pallet { ); // * Calculate new variables * - let end_block = - Self::select_random_block(auction_candle_start_block, auction_candle_end_block); + let end_block = Self::select_random_block(auction_candle_start_block, auction_candle_end_block); let community_start_block = now + 1u32.into(); let community_end_block = now + T::CommunityFundingDuration::get(); // * Update Storage * - Self::calculate_weighted_average_price( - project_id, - end_block, - project_info.fundraising_target, - )?; + Self::calculate_weighted_average_price(project_id, end_block, project_info.fundraising_target)?; // Get info again after updating it with new price. - let mut project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; project_info.phase_transition_points.random_candle_ending = Some(end_block); - project_info - .phase_transition_points - .community - .update(Some(community_start_block), Some(community_end_block)); + project_info.phase_transition_points.community.update(Some(community_start_block), Some(community_end_block)); project_info.project_status = ProjectStatus::CommunityRound; ProjectsDetails::::insert(project_id, project_info); // Schedule for automatic transition by `on_initialize` - Self::add_to_update_store( - community_end_block + 1u32.into(), - (&project_id, UpdateType::RemainderFundingStart), - ); + Self::add_to_update_store(community_end_block + 1u32.into(), (&project_id, UpdateType::RemainderFundingStart)); // * Emit events * Self::deposit_event(Event::::CommunityFundingStarted { project_id }); @@ -509,38 +446,25 @@ impl Pallet { /// [`do_end_funding`](Self::do_end_funding). pub fn do_remainder_funding(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); - let community_end_block = project_info - .phase_transition_points - .community - .end() - .ok_or(Error::::FieldIsNone)?; + let community_end_block = + project_info.phase_transition_points.community.end().ok_or(Error::::FieldIsNone)?; // * Validity checks * ensure!(now > community_end_block, Error::::TooEarlyForRemainderRoundStart); - ensure!( - project_info.project_status == ProjectStatus::CommunityRound, - Error::::ProjectNotInCommunityRound - ); + ensure!(project_info.project_status == ProjectStatus::CommunityRound, Error::::ProjectNotInCommunityRound); // * Calculate new variables * let remainder_start_block = now + 1u32.into(); let remainder_end_block = now + T::RemainderFundingDuration::get(); // * Update Storage * - project_info - .phase_transition_points - .remainder - .update(Some(remainder_start_block), Some(remainder_end_block)); + project_info.phase_transition_points.remainder.update(Some(remainder_start_block), Some(remainder_end_block)); project_info.project_status = ProjectStatus::RemainderRound; ProjectsDetails::::insert(project_id, project_info); // Schedule for automatic transition by `on_initialize` - Self::add_to_update_store( - remainder_end_block + 1u32.into(), - (&project_id, UpdateType::FundingEnd), - ); + Self::add_to_update_store(remainder_end_block + 1u32.into(), (&project_id, UpdateType::FundingEnd)); // * Emit events * Self::deposit_event(Event::::RemainderFundingStarted { project_id }); @@ -580,12 +504,10 @@ impl Pallet { /// If **unsuccessful**, users every user should have their PLMC vesting unbonded. pub fn do_end_funding(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); // TODO: PLMC-149 Check if make sense to set the admin as T::fund_account_id(project_id) - let issuer = - ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; + let issuer = ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; let project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; let token_information = project.token_information; let remaining_cts = project_info.remaining_contribution_tokens; @@ -640,14 +562,10 @@ impl Pallet { /// WIP pub fn do_ready_to_launch(project_id: &T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; // * Validity checks * - ensure!( - project_info.project_status == ProjectStatus::FundingEnded, - Error::::ProjectNotInFundingEndedRound - ); + ensure!(project_info.project_status == ProjectStatus::FundingEnded, Error::::ProjectNotInFundingEndedRound); // Update project Info project_info.project_status = ProjectStatus::ReadyToLaunch; @@ -677,18 +595,13 @@ impl Pallet { project_metadata_hash: T::Hash, ) -> Result<(), DispatchError> { // * Get variables * - let mut project = - ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; - let project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; + let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; // * Validity checks * ensure!(ProjectsIssuers::::get(project_id) == Some(issuer), Error::::NotAllowed); ensure!(!project_info.is_frozen, Error::::Frozen); - ensure!( - !Images::::contains_key(project_metadata_hash), - Error::::MetadataAlreadyExists - ); + ensure!(!Images::::contains_key(project_metadata_hash), Error::::MetadataAlreadyExists); // TODO: PLMC-133. Replace this when this PR is merged: https://github.com/KILTprotocol/kilt-node/pull/448 // ensure!( @@ -726,10 +639,8 @@ impl Pallet { amount: BalanceOf, ) -> Result<(), DispatchError> { // * Get variables * - let project_issuer = - ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; - let project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let project_issuer = ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; + let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; // * Validity checks * // TODO: PLMC-133. Replace this when this PR is merged: https://github.com/KILTprotocol/kilt-node/pull/448 @@ -738,10 +649,7 @@ impl Pallet { // Error::::NotAuthorized // ); ensure!(evaluator != project_issuer, Error::::ContributionToThemselves); - ensure!( - project_info.project_status == ProjectStatus::EvaluationRound, - Error::::EvaluationNotStarted - ); + ensure!(project_info.project_status == ProjectStatus::EvaluationRound, Error::::EvaluationNotStarted); // * Calculate new variables * @@ -769,11 +677,7 @@ impl Pallet { .map_err(|_| Error::::InsufficientBalance)?; }, } - Self::deposit_event(Event::::FundsBonded { - project_id, - amount, - bonder: evaluator.clone(), - }); + Self::deposit_event(Event::::FundsBonded { project_id, amount, bonder: evaluator.clone() }); Result::<(), Error>::Ok(()) })?; @@ -796,14 +700,10 @@ impl Pallet { releaser: T::AccountId, ) -> Result<(), DispatchError> { // * Get variables * - let project_info = - ProjectsDetails::::get(bond.project).ok_or(Error::::ProjectInfoNotFound)?; + let project_info = ProjectsDetails::::get(bond.project).ok_or(Error::::ProjectInfoNotFound)?; // * Validity checks * - ensure!( - project_info.project_status == ProjectStatus::EvaluationFailed, - Error::::EvaluationNotFailed - ); + ensure!(project_info.project_status == ProjectStatus::EvaluationFailed, Error::::EvaluationNotFailed); // * Calculate new variables * @@ -844,10 +744,8 @@ impl Pallet { multiplier: Option>, ) -> Result<(), DispatchError> { // * Get variables * - let project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; - let project_issuer = - ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; + let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let project_issuer = ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; let project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; let project_ticket_size = amount.saturating_mul(price); let now = >::block_number(); @@ -856,10 +754,7 @@ impl Pallet { // * Validity checks * ensure!(bidder != project_issuer, Error::::ContributionToThemselves); - ensure!( - matches!(project_info.project_status, ProjectStatus::AuctionRound(_)), - Error::::AuctionNotStarted - ); + ensure!(matches!(project_info.project_status, ProjectStatus::AuctionRound(_)), Error::::AuctionNotStarted); ensure!(price >= project.minimum_price, Error::::BidTooLow); if let Some(minimum_ticket_size) = project.ticket_size.minimum { // Make sure the bid amount is greater than the minimum specified by the issuer @@ -871,14 +766,9 @@ impl Pallet { }; // * Calculate new variables * - let (plmc_vesting_period, ct_vesting_period) = Self::calculate_vesting_periods( - bidder.clone(), - multiplier.clone(), - amount, - price, - decimals, - ) - .map_err(|_| Error::::BadMath)?; + let (plmc_vesting_period, ct_vesting_period) = + Self::calculate_vesting_periods(bidder.clone(), multiplier.clone(), amount, price, decimals) + .map_err(|_| Error::::BadMath)?; let bid_id = Self::next_bid_id(); let required_plmc_bond = plmc_vesting_period.amount; let bid = BidInfo::new( @@ -922,9 +812,8 @@ impl Pallet { }, Err(_) => { // Since the bids are sorted by price, and in this branch the Vec is full, the last element is the lowest bid - let lowest_bid_index: usize = (T::MaximumBidsPerUser::get() - 1) - .try_into() - .map_err(|_| Error::::BadMath)?; + let lowest_bid_index: usize = + (T::MaximumBidsPerUser::get() - 1).try_into().map_err(|_| Error::::BadMath)?; let lowest_bid = user_bids.swap_remove(lowest_bid_index); ensure!(bid > lowest_bid, Error::::BidTooLow); // Unreserve the lowest bid first @@ -932,9 +821,7 @@ impl Pallet { // Reserve the new bid T::FundingCurrency::reserve(&bidder, bid.ticket_size)?; // Add the new bid to the AuctionsInfo, this should never fail since we just removed an element - user_bids - .try_push(bid) - .expect("We removed an element, so there is always space"); + user_bids.try_push(bid).expect("We removed an element, so there is always space"); user_bids.sort_by_key(|bid| Reverse(bid.price)); AuctionsInfo::::set(project_id, bidder, Some(user_bids)); // TODO: PLMC-159. Send an XCM message to Statemine to transfer amount * multiplier USDT to the PalletId Account @@ -968,15 +855,12 @@ impl Pallet { multiplier: Option>, ) -> Result<(), DispatchError> { // * Get variables * - let project_issuer = - ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; - let project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let project_issuer = ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; + let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; // Default should normally be multiplier of 1 let multiplier = multiplier.unwrap_or_default(); - let weighted_average_price = - project_info.weighted_average_price.ok_or(Error::::AuctionNotStarted)?; + let weighted_average_price = project_info.weighted_average_price.ok_or(Error::::AuctionNotStarted)?; let decimals = project.token_information.decimals; let fund_account = Self::fund_account_id(project_id); @@ -1013,11 +897,8 @@ impl Pallet { decimals, ) .map_err(|_| Error::::BadMath)?; - let contribution = ContributionInfo { - contribution_amount: ticket_size, - plmc_vesting: plmc_vesting.clone(), - ct_vesting, - }; + let contribution = + ContributionInfo { contribution_amount: ticket_size, plmc_vesting: plmc_vesting.clone(), ct_vesting }; // Calculate how much plmc is required to be bonded for this contribution, // based on existing unused PLMC bonds for the project @@ -1025,15 +906,13 @@ impl Pallet { let bonded_plmc = ContributingBonds::::get(project_id, contributor.clone()) .map(|bond| bond.amount) .unwrap_or_else(Zero::zero); - let mut user_contributions = - Contributions::::get(project_id, contributor.clone()).unwrap_or_default(); + let mut user_contributions = Contributions::::get(project_id, contributor.clone()).unwrap_or_default(); for contribution in user_contributions.iter() { bonded_plmc.saturating_sub(contribution.plmc_vesting.amount); } required_plmc_bond.saturating_sub(bonded_plmc); - let remaining_cts_after_purchase = - project_info.remaining_contribution_tokens.saturating_sub(buyable_tokens); + let remaining_cts_after_purchase = project_info.remaining_contribution_tokens.saturating_sub(buyable_tokens); let now = >::block_number(); // * Update storage * @@ -1045,15 +924,13 @@ impl Pallet { Ok(_) => { // TODO: PLMC-159. Send an XCM message to Statemint/e to transfer a `bid.market_cap` amount of USDC (or the Currency specified by the issuer) to the PalletId Account // Alternative TODO: PLMC-159. The user should have the specified currency (e.g: USDC) already on Polimec - user_contributions - .sort_by_key(|contribution| Reverse(contribution.plmc_vesting.amount)); + user_contributions.sort_by_key(|contribution| Reverse(contribution.plmc_vesting.amount)); Contributions::::set(project_id, contributor.clone(), Some(user_contributions)); }, Err(_) => { // The contributions are sorted by highest PLMC bond. If the contribution vector for the user is full, we drop the lowest/last item - let lowest_contribution_index: usize = (T::MaxContributionsPerUser::get() - 1) - .try_into() - .map_err(|_| Error::::BadMath)?; + let lowest_contribution_index: usize = + (T::MaxContributionsPerUser::get() - 1).try_into().map_err(|_| Error::::BadMath)?; let lowest_contribution = user_contributions.swap_remove(lowest_contribution_index); ensure!( contribution.plmc_vesting.amount > lowest_contribution.plmc_vesting.amount, @@ -1077,8 +954,7 @@ impl Pallet { // Update the ContributingBonds storage ContributingBonds::::mutate(project_id, contributor.clone(), |maybe_bond| { if let Some(bond) = maybe_bond { - bond.amount = - bond.amount.saturating_sub(lowest_contribution.plmc_vesting.amount); + bond.amount = bond.amount.saturating_sub(lowest_contribution.plmc_vesting.amount); } }); @@ -1086,8 +962,7 @@ impl Pallet { user_contributions .try_push(contribution) .expect("We removed an element, so there is always space; qed"); - user_contributions - .sort_by_key(|contribution| Reverse(contribution.plmc_vesting.amount)); + user_contributions.sort_by_key(|contribution| Reverse(contribution.plmc_vesting.amount)); Contributions::::set(project_id, contributor.clone(), Some(user_contributions)); // TODO: PLMC-159. Send an XCM message to Statemine to transfer amount * multiplier USDT to the PalletId Account }, @@ -1115,12 +990,7 @@ impl Pallet { } // * Emit events * - Self::deposit_event(Event::::Contribution { - project_id, - contributor, - amount: token_amount, - multiplier, - }); + Self::deposit_event(Event::::Contribution { project_id, contributor, amount: token_amount, multiplier }); Ok(()) } @@ -1170,8 +1040,7 @@ impl Pallet { // Update the new vector that will go in AuctionInfo with the updated vesting period struct new_bids.push(bid.clone()); // Update the BiddingBonds map with the reduced amount for that project-user - let mut bond = BiddingBonds::::get(bid.project, bid.bidder.clone()) - .ok_or(Error::::FieldIsNone)?; + let mut bond = BiddingBonds::::get(bid.project, bid.bidder.clone()).ok_or(Error::::FieldIsNone)?; bond.amount = bond.amount.saturating_sub(unbond_amount); // TODO: maybe the BiddingBonds map is redundant, since we can iterate over the Bids vec and calculate it ourselves BiddingBonds::::insert(bid.project, bid.bidder.clone(), bond); @@ -1271,10 +1140,8 @@ impl Pallet { claimer: T::AccountId, ) -> Result<(), DispatchError> { // * Get variables * - let project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; - let contributions = - Contributions::::get(project_id, &claimer).ok_or(Error::::BidNotFound)?; + let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; + let contributions = Contributions::::get(project_id, &claimer).ok_or(Error::::BidNotFound)?; let now = >::block_number(); let mut updated_contributions = vec![]; @@ -1284,10 +1151,7 @@ impl Pallet { // T::HandleMembers::is_in(&MemberRole::Issuer, &issuer), // Error::::NotAuthorized // ); - ensure!( - project_info.project_status == ProjectStatus::FundingEnded, - Error::::CannotClaimYet - ); + ensure!(project_info.project_status == ProjectStatus::FundingEnded, Error::::CannotClaimYet); // TODO: PLMC-160. Check the flow of the final_price if the final price discovery during the Auction Round fails for mut contribution in contributions { @@ -1352,10 +1216,8 @@ impl Pallet { claimer: T::AccountId, ) -> Result<(), DispatchError> { // * Get variables * - let project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; - let contributions = - Contributions::::get(project_id, &claimer).ok_or(Error::::BidNotFound)?; + let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; + let contributions = Contributions::::get(project_id, &claimer).ok_or(Error::::BidNotFound)?; let now = >::block_number(); let mut updated_contributions = vec![]; @@ -1365,10 +1227,7 @@ impl Pallet { // T::HandleMembers::is_in(&MemberRole::Issuer, &issuer), // Error::::NotAuthorized // ); - ensure!( - project_info.project_status == ProjectStatus::FundingEnded, - Error::::CannotClaimYet - ); + ensure!(project_info.project_status == ProjectStatus::FundingEnded, Error::::CannotClaimYet); // TODO: PLMC-160. Check the flow of the final_price if the final price discovery during the Auction Round fails for mut contribution in contributions { @@ -1435,9 +1294,7 @@ impl Pallet { amount: BalanceOf, ) -> Result<(), DispatchError> { let now = >::block_number(); - let project_info = ProjectsDetails::::get(project_id) - .ok_or(Error::::ProjectInfoNotFound) - .unwrap(); + let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound).unwrap(); if let Some(bidding_end_block) = project_info.phase_transition_points.candle_auction.end() { ensure!(now < bidding_end_block, Error::::TooLateForBidBonding); @@ -1465,11 +1322,7 @@ impl Pallet { .map_err(|_| Error::::InsufficientBalance)?; }, } - Self::deposit_event(Event::::FundsBonded { - project_id, - amount, - bonder: caller.clone(), - }); + Self::deposit_event(Event::::FundsBonded { project_id, amount, bonder: caller.clone() }); Result::<(), Error>::Ok(()) })?; @@ -1482,9 +1335,7 @@ impl Pallet { amount: BalanceOf, ) -> Result<(), DispatchError> { let now = >::block_number(); - let project_info = ProjectsDetails::::get(project_id) - .ok_or(Error::::ProjectInfoNotFound) - .unwrap(); + let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound).unwrap(); if let Some(remainder_end_block) = project_info.phase_transition_points.remainder.end() { ensure!(now < remainder_end_block, Error::::TooLateForContributingBonding); @@ -1500,22 +1351,14 @@ impl Pallet { }, None => { // If the user has not bonded yet, create a new bond - *maybe_bond = Some(ContributingBond { - project: project_id, - account: caller.clone(), - amount, - }); + *maybe_bond = Some(ContributingBond { project: project_id, account: caller.clone(), amount }); // Reserve the required PLMC T::NativeCurrency::reserve_named(&BondType::Contributing, &caller, amount) .map_err(|_| Error::::InsufficientBalance)?; }, } - Self::deposit_event(Event::::FundsBonded { - project_id, - amount, - bonder: caller.clone(), - }); + Self::deposit_event(Event::::FundsBonded { project_id, amount, bonder: caller.clone() }); Result::<(), Error>::Ok(()) })?; @@ -1523,10 +1366,7 @@ impl Pallet { } /// Adds a project to the ProjectsToUpdate storage, so it can be updated at some later point in time. - pub fn add_to_update_store( - block_number: T::BlockNumber, - store: (&T::ProjectIdentifier, UpdateType), - ) { + pub fn add_to_update_store(block_number: T::BlockNumber, store: (&T::ProjectIdentifier, UpdateType)) { // Try to get the project into the earliest possible block to update. // There is a limit for how many projects can update each block, so we need to make sure we don't exceed that limit let mut block_number = block_number; @@ -1536,13 +1376,10 @@ impl Pallet { } } - pub fn remove_from_update_store( - project_id: &T::ProjectIdentifier, - ) -> Result<(), DispatchError> { + pub fn remove_from_update_store(project_id: &T::ProjectIdentifier) -> Result<(), DispatchError> { let (block_position, project_index) = ProjectsToUpdate::::iter() .find_map(|(block, project_vec)| { - let project_index = - project_vec.iter().position(|(id, _update_type)| id == project_id)?; + let project_index = project_vec.iter().position(|(id, _update_type)| id == project_id)?; Some((block, project_index)) }) .ok_or(Error::::ProjectNotInUpdateStore)?; @@ -1562,8 +1399,7 @@ impl Pallet { token_amount: BalanceOf, token_price: BalanceOf, decimals: u8, - ) -> Result<(Vesting>, Vesting>), ()> - { + ) -> Result<(Vesting>, Vesting>), ()> { let plmc_start: T::BlockNumber = 0u32.into(); let ct_start: T::BlockNumber = (T::MaxProjectsToUpdatePerBlock::get() * 7).into(); // TODO: Calculate real vesting periods based on multiplier and caller type @@ -1623,8 +1459,7 @@ impl Pallet { } else { bid_amount_sum.saturating_accrue(buyable_amount); bid_value_sum.saturating_accrue(buyable_amount * bid.price); - bid.status = - BidStatus::PartiallyAccepted(buyable_amount, RejectionReason::NoTokensLeft) + bid.status = BidStatus::PartiallyAccepted(buyable_amount, RejectionReason::NoTokensLeft) // TODO: PLMC-147. Refund remaining amount } @@ -1634,20 +1469,13 @@ impl Pallet { // Update the bid in the storage for bid in bids.iter() { - AuctionsInfo::::mutate( - project_id, - bid.bidder.clone(), - |maybe_bids| -> Result<(), DispatchError> { - let mut bids = maybe_bids.clone().ok_or(Error::::ImpossibleState)?; - let bid_index = bids - .iter() - .position(|b| b.bid_id == bid.bid_id) - .ok_or(Error::::ImpossibleState)?; - bids[bid_index] = bid.clone(); - *maybe_bids = Some(bids); - Ok(()) - }, - )?; + AuctionsInfo::::mutate(project_id, bid.bidder.clone(), |maybe_bids| -> Result<(), DispatchError> { + let mut bids = maybe_bids.clone().ok_or(Error::::ImpossibleState)?; + let bid_index = bids.iter().position(|b| b.bid_id == bid.bid_id).ok_or(Error::::ImpossibleState)?; + bids[bid_index] = bid.clone(); + *maybe_bids = Some(bids); + Ok(()) + })?; } // Calculate the weighted price of the token for the next funding rounds, using winning bids. @@ -1672,8 +1500,7 @@ impl Pallet { // TODO: PLMC-150. collecting due to previous mut borrow, find a way to not collect and borrow bid on filter_map .into_iter() .filter_map(|bid| match bid.status { - BidStatus::Accepted => - Some(Perbill::from_rational(bid.amount * bid.price, bid_value_sum) * bid.price), + BidStatus::Accepted => Some(Perbill::from_rational(bid.amount * bid.price, bid_value_sum) * bid.price), BidStatus::PartiallyAccepted(amount, _) => Some(Perbill::from_rational(amount * bid.price, bid_value_sum) * bid.price), _ => None, @@ -1685,8 +1512,7 @@ impl Pallet { ProjectsDetails::::mutate(project_id, |maybe_info| -> Result<(), DispatchError> { if let Some(info) = maybe_info { info.weighted_average_price = Some(weighted_token_price); - info.remaining_contribution_tokens = - info.remaining_contribution_tokens.saturating_sub(bid_amount_sum); + info.remaining_contribution_tokens = info.remaining_contribution_tokens.saturating_sub(bid_amount_sum); Ok(()) } else { Err(Error::::ProjectNotFound.into()) diff --git a/pallets/funding/src/lib.rs b/pallets/funding/src/lib.rs index 41202a2dc..3f5d77c30 100644 --- a/pallets/funding/src/lib.rs +++ b/pallets/funding/src/lib.rs @@ -218,11 +218,8 @@ use sp_std::prelude::*; type BalanceOf = ::Balance; -type ProjectMetadataOf = ProjectMetadata< - BoundedVec::StringLimit>, - BalanceOf, - ::Hash, ->; +type ProjectMetadataOf = + ProjectMetadata::StringLimit>, BalanceOf, ::Hash>; type ProjectDetailsOf = ProjectDetails<::BlockNumber, BalanceOf>; @@ -395,20 +392,17 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn projects)] /// A StorageMap containing the primary project information of projects - pub type ProjectsMetadata = - StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, ProjectMetadataOf>; + pub type ProjectsMetadata = StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, ProjectMetadataOf>; #[pallet::storage] #[pallet::getter(fn project_issuer)] /// StorageMap to get the issuer of a project - pub type ProjectsIssuers = - StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, T::AccountId>; + pub type ProjectsIssuers = StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, T::AccountId>; #[pallet::storage] #[pallet::getter(fn project_info)] /// StorageMap containing additional information for the projects, relevant for correctness of the protocol - pub type ProjectsDetails = - StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, ProjectDetailsOf>; + pub type ProjectsDetails = StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, ProjectDetailsOf>; #[pallet::storage] #[pallet::getter(fn projects_to_update)] @@ -514,12 +508,7 @@ pub mod pallet { releaser: T::AccountId, }, /// A bid was made for a project - Bid { - project_id: T::ProjectIdentifier, - amount: BalanceOf, - price: BalanceOf, - multiplier: MultiplierOf, - }, + Bid { project_id: T::ProjectIdentifier, amount: BalanceOf, price: BalanceOf, multiplier: MultiplierOf }, /// A contribution was made for a project. i.e token purchase Contribution { project_id: T::ProjectIdentifier, @@ -679,10 +668,7 @@ pub mod pallet { /// Starts the evaluation round of a project. It needs to be called by the project issuer. #[pallet::weight(T::WeightInfo::start_evaluation())] - pub fn start_evaluation( - origin: OriginFor, - project_id: T::ProjectIdParameter, - ) -> DispatchResult { + pub fn start_evaluation(origin: OriginFor, project_id: T::ProjectIdParameter) -> DispatchResult { let issuer = ensure_signed(origin)?; let project_id = project_id.into(); @@ -701,10 +687,7 @@ pub mod pallet { /// institutional user can set bids for a token_amount/token_price pair. /// Any bids from this point until the candle_auction starts, will be considered as valid. #[pallet::weight(T::WeightInfo::start_auction())] - pub fn start_auction( - origin: OriginFor, - project_id: T::ProjectIdParameter, - ) -> DispatchResult { + pub fn start_auction(origin: OriginFor, project_id: T::ProjectIdParameter) -> DispatchResult { let issuer = ensure_signed(origin)?; let project_id = project_id.into(); @@ -739,8 +722,7 @@ pub mod pallet { bonder: T::AccountId, ) -> DispatchResult { let releaser = ensure_signed(origin)?; - let bond = EvaluationBonds::::get(project_id.into(), bonder) - .ok_or(Error::::BondNotFound)?; + let bond = EvaluationBonds::::get(project_id.into(), bonder).ok_or(Error::::BondNotFound)?; Self::do_failed_evaluation_unbond_for(bond, releaser) } @@ -876,8 +858,7 @@ pub mod pallet { } fn on_idle(_now: T::BlockNumber, max_weight: Weight) -> Weight { - let pallet_account: T::AccountId = - ::PalletId::get().into_account_truncating(); + let pallet_account: T::AccountId = ::PalletId::get().into_account_truncating(); let mut remaining_weight = max_weight; @@ -894,9 +875,7 @@ pub mod pallet { // Get a flat list of bonds .flat_map(|project_id| { // get all the bonds for projects with a failed evaluation phase - EvaluationBonds::::iter_prefix(project_id) - .map(|(_bonder, bond)| bond) - .collect::>() + EvaluationBonds::::iter_prefix(project_id).map(|(_bonder, bond)| bond).collect::>() }) // Retrieve as many as possible for the given weight .take_while(|_| { @@ -936,6 +915,7 @@ pub mod pallet { fn create_project_id_parameter(id: u32) -> T::ProjectIdParameter { id.into() } + fn create_dummy_project(metadata_hash: T::Hash) -> ProjectMetadataOf { let project: ProjectMetadataOf = ProjectMetadata { total_allocation_size: 1_000_000u64.into(), @@ -976,10 +956,7 @@ pub mod local_macros { match $option { Ok(val) => val, Err(err) => { - Self::deposit_event(Event::::TransitionError { - project_id: $project_id, - error: err, - }); + Self::deposit_event(Event::::TransitionError { project_id: $project_id, error: err }); continue }, } diff --git a/pallets/funding/src/mock.rs b/pallets/funding/src/mock.rs index 9459da70c..9814c651e 100644 --- a/pallets/funding/src/mock.rs +++ b/pallets/funding/src/mock.rs @@ -63,30 +63,30 @@ parameter_types! { } impl system::Config for TestRuntime { + type AccountData = pallet_balances::AccountData; + type AccountId = AccountId; type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); + type BlockHashCount = BlockHashCount; type BlockLength = (); - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Index = u64; type BlockNumber = BlockNumber; + type BlockWeights = (); + type DbWeight = (); type Hash = H256; type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; type Header = Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type DbWeight = (); - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); + type Index = u64; + type Lookup = IdentityLookup; + type MaxConsumers = frame_support::traits::ConstU32<16>; type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = ConstU16<42>; + type OnNewAccount = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type PalletInfo = PalletInfo; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type SS58Prefix = ConstU16<42>; + type SystemWeightInfo = (); + type Version = (); } parameter_types! { @@ -94,44 +94,44 @@ parameter_types! { } impl pallet_balances::Config for TestRuntime { + type AccountStore = System; + type Balance = Balance; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type FreezeIdentifier = (); + type HoldIdentifier = BondType; + type MaxFreezes = (); + type MaxHolds = ConstU32<1024>; type MaxLocks = frame_support::traits::ConstU32<1024>; type MaxReserves = frame_support::traits::ConstU32<1024>; type ReserveIdentifier = BondType; - type Balance = Balance; type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; type WeightInfo = (); - type MaxHolds = ConstU32<1024>; - type MaxFreezes = (); - type HoldIdentifier = BondType; - type FreezeIdentifier = (); } impl pallet_insecure_randomness_collective_flip::Config for TestRuntime {} impl pallet_assets::Config for TestRuntime { - type RuntimeEvent = RuntimeEvent; - type Balance = Balance; + type ApprovalDeposit = ConstU128<1>; + type AssetAccountDeposit = ConstU128<10>; + type AssetDeposit = ConstU128<1>; type AssetId = Identifier; + type AssetIdParameter = Identifier; + type Balance = Balance; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); + type CallbackHandle = (); + type CreateOrigin = AsEnsureOriginWithArg>; type Currency = Balances; + type Extra = (); type ForceOrigin = frame_system::EnsureRoot; - type AssetDeposit = ConstU128<1>; - type AssetAccountDeposit = ConstU128<10>; + type Freezer = (); type MetadataDepositBase = ConstU128<1>; type MetadataDepositPerByte = ConstU128<1>; - type ApprovalDeposit = ConstU128<1>; + type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; + type RuntimeEvent = RuntimeEvent; type StringLimit = ConstU32<50>; - type Freezer = (); type WeightInfo = (); - type Extra = (); - type AssetIdParameter = Identifier; - type CreateOrigin = AsEnsureOriginWithArg>; - type CallbackHandle = (); - type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); } pub const HOURS: BlockNumber = 300u64; @@ -148,33 +148,33 @@ parameter_types! { } impl pallet_funding::Config for TestRuntime { - type RuntimeEvent = RuntimeEvent; - type StringLimit = ConstU32<64>; - type ProjectIdentifier = Identifier; - type ProjectIdParameter = Identifier; + type AuctionInitializePeriodDuration = AuctionInitializePeriodDuration; + type Balance = Balance; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); type BidId = u128; + type CandleAuctionDuration = CandleAuctionDuration; + type CommunityFundingDuration = CommunityRoundDuration; type ContributionTokenCurrency = Assets; - type EvaluationDuration = EvaluationDuration; - type AuctionInitializePeriodDuration = AuctionInitializePeriodDuration; + type ContributionVesting = ConstU32<4>; type EnglishAuctionDuration = EnglishAuctionDuration; - type CandleAuctionDuration = CandleAuctionDuration; - type RemainderFundingDuration = RemainderFundingDuration; - type PalletId = FundingPalletId; + type EvaluationDuration = EvaluationDuration; + type FundingCurrency = Balances; + type MaxContributionsPerUser = ConstU32<4>; type MaxProjectsToUpdatePerBlock = ConstU32<100>; - type CommunityFundingDuration = CommunityRoundDuration; - type Randomness = RandomnessCollectiveFlip; - type PreImageLimit = ConstU32<1024>; // Low value to simplify the tests type MaximumBidsPerUser = ConstU32<4>; - type MaxContributionsPerUser = ConstU32<4>; - type ContributionVesting = ConstU32<4>; - type WeightInfo = (); - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); type Multiplier = types::Multiplier; - type Balance = Balance; type NativeCurrency = Balances; - type FundingCurrency = Balances; + type PalletId = FundingPalletId; + type PreImageLimit = ConstU32<1024>; + type ProjectIdParameter = Identifier; + type ProjectIdentifier = Identifier; + type Randomness = RandomnessCollectiveFlip; + type RemainderFundingDuration = RemainderFundingDuration; + type RuntimeEvent = RuntimeEvent; + type StringLimit = ConstU32<64>; + type WeightInfo = (); } // Build genesis storage according to the mock runtime. diff --git a/pallets/funding/src/tests.rs b/pallets/funding/src/tests.rs index a62e9b98d..2f1f3f87e 100644 --- a/pallets/funding/src/tests.rs +++ b/pallets/funding/src/tests.rs @@ -36,12 +36,8 @@ use std::cell::RefCell; type ProjectIdOf = ::ProjectIdentifier; type UserToBalance = Vec<(mock::AccountId, BalanceOf)>; // User -> token_amount, price_per_token, multiplier -type UserToBid = Vec<( - AccountId, - (BalanceOf, BalanceOf, Option>), -)>; -type UserToContribution = - Vec<(AccountId, (BalanceOf, Option>))>; +type UserToBid = Vec<(AccountId, (BalanceOf, BalanceOf, Option>))>; +type UserToContribution = Vec<(AccountId, (BalanceOf, Option>))>; const ISSUER: AccountId = 1; const EVALUATOR_1: AccountId = 2; @@ -72,17 +68,11 @@ const METADATA: &str = r#" // } /// Remove accounts from fundings_1 that are not in fundings_2 -fn remove_missing_accounts_from_fundings( - fundings_1: UserToBalance, - fundings_2: UserToBalance, -) -> UserToBalance { +fn remove_missing_accounts_from_fundings(fundings_1: UserToBalance, fundings_2: UserToBalance) -> UserToBalance { let mut fundings_1 = fundings_1; let fundings_2 = fundings_2; fundings_1.retain(|(account, _)| { - fundings_2 - .iter() - .find_map(|(account_2, _)| if account == account_2 { Some(()) } else { None }) - .is_some() + fundings_2.iter().find_map(|(account_2, _)| if account == account_2 { Some(()) } else { None }).is_some() }); fundings_1 } @@ -93,19 +83,18 @@ trait ProjectInstance { fn get_creator(&self) -> AccountId; fn get_project_id(&self) -> ProjectIdOf; fn get_project(&self) -> ProjectMetadataOf { - self.get_test_environment().ext_env.borrow_mut().execute_with(|| { - FundingModule::projects(self.get_project_id()).expect("Project info should exist") - }) + self.get_test_environment() + .ext_env + .borrow_mut() + .execute_with(|| FundingModule::projects(self.get_project_id()).expect("Project info should exist")) } fn get_project_info(&self) -> ProjectDetailsOf { - self.get_test_environment().ext_env.borrow_mut().execute_with(|| { - FundingModule::project_info(self.get_project_id()).expect("Project info should exist") - }) + self.get_test_environment() + .ext_env + .borrow_mut() + .execute_with(|| FundingModule::project_info(self.get_project_id()).expect("Project info should exist")) } - fn do_project_assertions( - &self, - project_assertions: impl Fn(ProjectIdOf, &TestEnvironment) -> (), - ) { + fn do_project_assertions(&self, project_assertions: impl Fn(ProjectIdOf, &TestEnvironment) -> ()) { let project_id = self.get_project_id(); let test_env = self.get_test_environment(); project_assertions(project_id, test_env); @@ -122,23 +111,21 @@ impl TestEnvironment { pub fn new() -> Self { Self { ext_env: RefCell::new(new_test_ext()), nonce: RefCell::new(0u64) } } + fn create_project( &self, creator: mock::AccountId, project: ProjectMetadataOf, ) -> Result { // Create project in the externalities environment of this struct instance - self.ext_env - .borrow_mut() - .execute_with(|| FundingModule::create(RuntimeOrigin::signed(creator), project))?; + self.ext_env.borrow_mut().execute_with(|| FundingModule::create(RuntimeOrigin::signed(creator), project))?; // Retrieve the project_id from the events let project_id = self.ext_env.borrow_mut().execute_with(|| { frame_system::Pallet::::events() .iter() .filter_map(|event| match event.event { - RuntimeEvent::FundingModule(crate::Event::Created { project_id }) => - Some(project_id), + RuntimeEvent::FundingModule(crate::Event::Created { project_id }) => Some(project_id), _ => None, }) .last() @@ -148,13 +135,13 @@ impl TestEnvironment { Ok(CreatedProject { test_env: self, creator, project_id }) } + /// Returns the *free* fundings of the Users. #[allow(dead_code)] fn get_free_fundings(&self) -> UserToBalance { self.ext_env.borrow_mut().execute_with(|| { let mut fundings = UserToBalance::new(); - let user_keys: Vec = - frame_system::Account::::iter_keys().collect(); + let user_keys: Vec = frame_system::Account::::iter_keys().collect(); for user in user_keys { let funding = Balances::free_balance(&user); fundings.push((user, funding)); @@ -162,13 +149,13 @@ impl TestEnvironment { fundings }) } + /// Returns the *reserved* fundings of the Users. #[allow(dead_code)] fn get_reserved_fundings(&self, reserve_type: BondType) -> UserToBalance { self.ext_env.borrow_mut().execute_with(|| { let mut fundings = UserToBalance::new(); - let user_keys: Vec = - frame_system::Account::::iter_keys().collect(); + let user_keys: Vec = frame_system::Account::::iter_keys().collect(); for user in user_keys { let funding = Balances::reserved_balance_named(&reserve_type, &user); fundings.push((user, funding)); @@ -176,6 +163,7 @@ impl TestEnvironment { fundings }) } + fn fund_accounts(&self, fundings: UserToBalance) { self.ext_env.borrow_mut().execute_with(|| { for (account, amount) in fundings { @@ -183,22 +171,22 @@ impl TestEnvironment { } }); } + fn current_block(&self) -> BlockNumber { self.ext_env.borrow_mut().execute_with(|| System::block_number()) } + fn advance_time(&self, amount: BlockNumber) { self.ext_env.borrow_mut().execute_with(|| { for _block in 0..amount { >::on_finalize(System::block_number()); - >::on_idle( - System::block_number(), - Weight::MAX, - ); + >::on_idle(System::block_number(), Weight::MAX); System::set_block_number(System::block_number() + 1); >::on_initialize(System::block_number()); } }); } + fn do_free_funds_assertions(&self, correct_funds: UserToBalance) { for (user, balance) in correct_funds { self.ext_env.borrow_mut().execute_with(|| { @@ -207,6 +195,7 @@ impl TestEnvironment { }); } } + fn do_reserved_funds_assertions(&self, correct_funds: UserToBalance, reserve_type: BondType) { for (user, balance) in correct_funds { self.ext_env.borrow_mut().execute_with(|| { @@ -227,9 +216,11 @@ impl<'a> ProjectInstance for CreatedProject<'a> { fn get_test_environment(&self) -> &TestEnvironment { self.test_env } + fn get_creator(&self) -> AccountId { self.creator.clone() } + fn get_project_id(&self) -> ProjectIdOf { self.project_id.clone() } @@ -238,28 +229,20 @@ impl<'a> CreatedProject<'a> { fn new_default(test_env: &'a TestEnvironment) -> Self { test_env.fund_accounts(default_fundings()); let creator = default_fundings()[0].0; - let project = test_env - .create_project(creator, default_project(test_env.nonce.borrow().clone())) - .unwrap(); + let project = test_env.create_project(creator, default_project(test_env.nonce.borrow().clone())).unwrap(); project.do_project_assertions(default_creation_assertions); *test_env.nonce.borrow_mut() += 1; project } // Move to next project phase - fn start_evaluation( - self, - caller: mock::AccountId, - ) -> Result, DispatchError> { - self.test_env.ext_env.borrow_mut().execute_with(|| { - FundingModule::start_evaluation(RuntimeOrigin::signed(caller), self.project_id) - })?; + fn start_evaluation(self, caller: mock::AccountId) -> Result, DispatchError> { + self.test_env + .ext_env + .borrow_mut() + .execute_with(|| FundingModule::start_evaluation(RuntimeOrigin::signed(caller), self.project_id))?; - Ok(EvaluatingProject { - test_env: self.test_env, - creator: self.creator, - project_id: self.project_id, - }) + Ok(EvaluatingProject { test_env: self.test_env, creator: self.creator, project_id: self.project_id }) } } @@ -273,9 +256,11 @@ impl<'a> ProjectInstance for EvaluatingProject<'a> { fn get_test_environment(&self) -> &TestEnvironment { self.test_env } + fn get_creator(&self) -> AccountId { self.creator.clone() } + fn get_project_id(&self) -> ProjectIdOf { self.project_id.clone() } @@ -293,9 +278,10 @@ impl<'a> EvaluatingProject<'a> { fn bond_for_users(&self, bonds: UserToBalance) -> Result<(), DispatchError> { let project_id = self.get_project_id(); for (account, amount) in bonds { - self.test_env.ext_env.borrow_mut().execute_with(|| { - FundingModule::bond_evaluation(RuntimeOrigin::signed(account), project_id, amount) - })?; + self.test_env + .ext_env + .borrow_mut() + .execute_with(|| FundingModule::bond_evaluation(RuntimeOrigin::signed(account), project_id, amount))?; } Ok(()) } @@ -303,11 +289,7 @@ impl<'a> EvaluatingProject<'a> { fn start_auction(self, caller: AccountId) -> Result, DispatchError> { self.test_env.ext_env.borrow_mut().execute_with(|| { FundingModule::start_auction(RuntimeOrigin::signed(caller), self.project_id)?; - Ok(AuctioningProject { - test_env: self.test_env, - creator: self.creator, - project_id: self.project_id, - }) + Ok(AuctioningProject { test_env: self.test_env, creator: self.creator, project_id: self.project_id }) }) } } @@ -322,9 +304,11 @@ impl<'a> ProjectInstance for AuctioningProject<'a> { fn get_test_environment(&self) -> &TestEnvironment { self.test_env } + fn get_creator(&self) -> AccountId { self.creator.clone() } + fn get_project_id(&self) -> ProjectIdOf { self.project_id.clone() } @@ -335,9 +319,7 @@ impl<'a> AuctioningProject<'a> { let creator = evaluating_project.get_creator(); // Do Evaluation bonding - evaluating_project - .bond_for_users(default_evaluation_bonds()) - .expect("Bonding should work"); + evaluating_project.bond_for_users(default_evaluation_bonds()).expect("Bonding should work"); // Check that enough funds are reserved test_env.do_reserved_funds_assertions(default_evaluation_bonds(), BondType::Evaluation); @@ -402,11 +384,7 @@ impl<'a> AuctioningProject<'a> { .expect("Candle end point should exist"); self.test_env.advance_time(candle_end - self.test_env.current_block() + 1); assert_eq!(self.get_project_info().project_status, ProjectStatus::CommunityRound); - CommunityFundingProject { - test_env: self.test_env, - creator: self.creator, - project_id: self.project_id, - } + CommunityFundingProject { test_env: self.test_env, creator: self.creator, project_id: self.project_id } } } @@ -420,9 +398,11 @@ impl<'a> ProjectInstance for CommunityFundingProject<'a> { fn get_test_environment(&self) -> &TestEnvironment { self.test_env } + fn get_creator(&self) -> AccountId { self.creator.clone() } + fn get_project_id(&self) -> ProjectIdOf { self.project_id.clone() } @@ -432,9 +412,7 @@ impl<'a> CommunityFundingProject<'a> { let auctioning_project = AuctioningProject::new_default(test_env); // Do Auction bidding - auctioning_project - .bid_for_users(default_auction_bids()) - .expect("Bidding should work"); + auctioning_project.bid_for_users(default_auction_bids()).expect("Bidding should work"); // Check our auction was properly interpreted test_env.advance_time(1); @@ -453,12 +431,7 @@ impl<'a> CommunityFundingProject<'a> { let project_id = self.get_project_id(); for (account, (ct_amount, multiplier)) in buys { self.test_env.ext_env.borrow_mut().execute_with(|| { - FundingModule::contribute( - RuntimeOrigin::signed(account), - project_id, - ct_amount, - multiplier, - ) + FundingModule::contribute(RuntimeOrigin::signed(account), project_id, ct_amount, multiplier) })?; } Ok(()) @@ -471,14 +444,9 @@ impl<'a> CommunityFundingProject<'a> { .community .end() .expect("Community funding end point should exist"); - self.test_env - .advance_time(community_funding_end - self.test_env.current_block() + 1); + self.test_env.advance_time(community_funding_end - self.test_env.current_block() + 1); assert_eq!(self.get_project_info().project_status, ProjectStatus::RemainderRound); - RemainderFundingProject { - test_env: self.test_env, - creator: self.creator, - project_id: self.project_id, - } + RemainderFundingProject { test_env: self.test_env, creator: self.creator, project_id: self.project_id } } } @@ -492,9 +460,11 @@ impl<'a> ProjectInstance for RemainderFundingProject<'a> { fn get_test_environment(&self) -> &TestEnvironment { self.test_env } + fn get_creator(&self) -> AccountId { self.creator.clone() } + fn get_project_id(&self) -> ProjectIdOf { self.project_id.clone() } @@ -504,12 +474,7 @@ impl<'a> RemainderFundingProject<'a> { let project_id = self.get_project_id(); for (account, (ct_amount, multiplier)) in buys { self.test_env.ext_env.borrow_mut().execute_with(|| { - FundingModule::contribute( - RuntimeOrigin::signed(account), - project_id, - ct_amount, - multiplier, - ) + FundingModule::contribute(RuntimeOrigin::signed(account), project_id, ct_amount, multiplier) })?; } Ok(()) @@ -519,9 +484,7 @@ impl<'a> RemainderFundingProject<'a> { let community_funding_project = CommunityFundingProject::new_default(test_env); // Do community buying - community_funding_project - .buy_for_retail_users(default_community_buys()) - .expect("Community buying should work"); + community_funding_project.buy_for_retail_users(default_community_buys()).expect("Community buying should work"); // Check our buys were properly interpreted test_env.advance_time(1); @@ -543,14 +506,9 @@ impl<'a> RemainderFundingProject<'a> { .remainder .end() .expect("Remainder funding end point should exist"); - self.test_env - .advance_time(remainder_funding_end - self.test_env.current_block() + 1); + self.test_env.advance_time(remainder_funding_end - self.test_env.current_block() + 1); assert_eq!(self.get_project_info().project_status, ProjectStatus::FundingEnded); - FinishedProject { - test_env: self.test_env, - creator: self.creator, - project_id: self.project_id, - } + FinishedProject { test_env: self.test_env, creator: self.creator, project_id: self.project_id } } } @@ -564,9 +522,11 @@ impl<'a> ProjectInstance for FinishedProject<'a> { fn get_test_environment(&self) -> &TestEnvironment { self.test_env } + fn get_creator(&self) -> AccountId { self.creator.clone() } + fn get_project_id(&self) -> ProjectIdOf { self.project_id.clone() } @@ -574,9 +534,7 @@ impl<'a> ProjectInstance for FinishedProject<'a> { impl<'a> FinishedProject<'a> { fn new_default(test_env: &'a TestEnvironment) -> Self { let remainder_funding_project = RemainderFundingProject::new_default(test_env); - remainder_funding_project - .buy_for_any_user(default_remainder_buys()) - .expect("Buying should work"); + remainder_funding_project.buy_for_any_user(default_remainder_buys()).expect("Buying should work"); // End project funding by moving block to after the end of remainder round let finished_project = remainder_funding_project.finish_project(); @@ -592,11 +550,8 @@ mod defaults { use super::*; use crate::traits::BondingRequirementCalculation; - pub fn default_project( - nonce: u64, - ) -> ProjectMetadata>, u128, sp_core::H256> { - let bounded_name = - BoundedVec::try_from("Contribution Token TEST".as_bytes().to_vec()).unwrap(); + pub fn default_project(nonce: u64) -> ProjectMetadata>, u128, sp_core::H256> { + let bounded_name = BoundedVec::try_from("Contribution Token TEST".as_bytes().to_vec()).unwrap(); let bounded_symbol = BoundedVec::try_from("CTEST".as_bytes().to_vec()).unwrap(); let metadata_hash = hashed(format!("{}-{}", METADATA, nonce)); ProjectMetadata { @@ -635,18 +590,11 @@ mod defaults { pub fn default_evaluation_bonds() -> UserToBalance { // currently the default project needs 100_000 PLMC to be successful in the evaluation round // we assume we will use this bond twice - vec![ - (EVALUATOR_1, 20_000 * PLMC), - (EVALUATOR_2, 30_000 * PLMC), - (EVALUATOR_3, 60_000 * PLMC), - ] + vec![(EVALUATOR_1, 20_000 * PLMC), (EVALUATOR_2, 30_000 * PLMC), (EVALUATOR_3, 60_000 * PLMC)] } pub fn default_failing_evaluation_bonds() -> UserToBalance { - default_evaluation_bonds() - .into_iter() - .map(|(user, balance)| (user, balance / 2)) - .collect::() + default_evaluation_bonds().into_iter().map(|(user, balance)| (user, balance / 2)).collect::() } pub fn default_auction_bids() -> UserToBid { @@ -662,46 +610,26 @@ mod defaults { default_auction_bids() .into_iter() .map(|(user, (amount, price, mult))| { - ( - user, - (mult - .unwrap_or_default() - .calculate_bonding_requirement(amount * price) - .unwrap()), - ) + (user, (mult.unwrap_or_default().calculate_bonding_requirement(amount * price).unwrap())) }) .collect() } pub fn default_auction_bids_currency_reserved() -> UserToBalance { - default_auction_bids() - .into_iter() - .map(|(user, (amount, price, _mult))| (user, (amount * price))) - .collect() + default_auction_bids().into_iter().map(|(user, (amount, price, _mult))| (user, (amount * price))).collect() } pub fn default_community_plmc_bondings(price: BalanceOf) -> UserToBalance { default_community_buys() .into_iter() .map(|(user, (amount, multiplier))| { - ( - user, - (multiplier - .unwrap_or_default() - .calculate_bonding_requirement(amount * price) - .unwrap()), - ) + (user, (multiplier.unwrap_or_default().calculate_bonding_requirement(amount * price).unwrap())) }) .collect() } - pub fn default_community_buys_currency_reserved( - price: BalanceOf, - ) -> UserToBalance { - default_community_buys() - .into_iter() - .map(|(user, (amount, _multiplier))| (user, (amount * price))) - .collect() + pub fn default_community_buys_currency_reserved(price: BalanceOf) -> UserToBalance { + default_community_buys().into_iter().map(|(user, (amount, _multiplier))| (user, (amount * price))).collect() } pub fn default_community_buys() -> UserToContribution { @@ -718,60 +646,37 @@ mod defaults { // vec![(BUYER_1, (100 * PLMC)), (BUYER_2, (6000 * PLMC))] // } - pub fn default_creation_assertions( - project_id: ProjectIdOf, - test_env: &TestEnvironment, - ) { + pub fn default_creation_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = - FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::Application); }); } - pub fn default_evaluation_start_assertions( - project_id: ProjectIdOf, - test_env: &TestEnvironment, - ) { + pub fn default_evaluation_start_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = - FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::EvaluationRound); }); } - pub fn default_evaluation_end_assertions( - project_id: ProjectIdOf, - test_env: &TestEnvironment, - ) { + pub fn default_evaluation_end_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = - FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::AuctionInitializePeriod); }); } - pub fn default_auction_start_assertions( - project_id: ProjectIdOf, - test_env: &TestEnvironment, - ) { + pub fn default_auction_start_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = - FundingModule::project_info(project_id).expect("Project info should exist"); - assert_eq!( - project_info.project_status, - ProjectStatus::AuctionRound(AuctionPhase::English) - ); + let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); + assert_eq!(project_info.project_status, ProjectStatus::AuctionRound(AuctionPhase::English)); }); } - pub fn default_auction_end_assertions( - _project_id: ProjectIdOf, - test_env: &TestEnvironment, - ) { + pub fn default_auction_end_assertions(_project_id: ProjectIdOf, test_env: &TestEnvironment) { // Check that enough PLMC is bonded - test_env - .do_reserved_funds_assertions(default_auction_bids_plmc_bondings(), BondType::Bidding); + test_env.do_reserved_funds_assertions(default_auction_bids_plmc_bondings(), BondType::Bidding); // Check that the bidding currency is reserved test_env.ext_env.borrow_mut().execute_with(|| { @@ -792,8 +697,7 @@ mod defaults { // Check that free funds were reduced let mut free_funds = default_fundings(); // Remove accounts that didnt bond from free_funds - free_funds = - remove_missing_accounts_from_fundings(free_funds, default_auction_bids_plmc_bondings()); + free_funds = remove_missing_accounts_from_fundings(free_funds, default_auction_bids_plmc_bondings()); // Subtract plmc bonded bidding funds free_funds = free_funds .iter() @@ -831,30 +735,21 @@ mod defaults { }); // PLMC should still be reserved, since its only a bond - test_env - .do_reserved_funds_assertions(default_auction_bids_plmc_bondings(), BondType::Bidding); + test_env.do_reserved_funds_assertions(default_auction_bids_plmc_bondings(), BondType::Bidding); // Check for correct project information test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = - FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::CommunityRound); // Check correct weighted_average_price - let token_price = - project_info.weighted_average_price.expect("Token price should exist"); - assert_eq!( - token_price, - default_token_average_price(), - "Weighted average token price is incorrect" - ); + let token_price = project_info.weighted_average_price.expect("Token price should exist"); + assert_eq!(token_price, default_token_average_price(), "Weighted average token price is incorrect"); // Check that remaining CTs are updated let project = FundingModule::project_info(project_id).expect("Project should exist"); - let bought_tokens: u128 = default_auction_bids() - .iter() - .map(|(_account, (amount, _price, _multiplier))| amount) - .sum(); + let bought_tokens: u128 = + default_auction_bids().iter().map(|(_account, (amount, _price, _multiplier))| amount).sum(); assert_eq!( project.remaining_contribution_tokens, default_project(0).total_allocation_size - bought_tokens, @@ -864,43 +759,31 @@ mod defaults { // Check status of bids test_env.ext_env.borrow_mut().execute_with(|| { - let project_bids = crate::pallet::AuctionsInfo::::iter_prefix(project_id) - .collect::>(); + let project_bids = crate::pallet::AuctionsInfo::::iter_prefix(project_id).collect::>(); let project_info = FundingModule::project_info(project_id).unwrap(); - assert!( - matches!(project_info.weighted_average_price, Some(_)), - "Weighted average price should exist" - ); + assert!(matches!(project_info.weighted_average_price, Some(_)), "Weighted average price should exist"); assert!(project_bids .into_iter() - .find(|(_bidder, bids)| { - !bids.iter().all(|bid| bid.status == BidStatus::Accepted) - }) + .find(|(_bidder, bids)| { !bids.iter().all(|bid| bid.status == BidStatus::Accepted) }) .is_none()); }); } - pub fn default_community_funding_end_assertions( - project_id: ProjectIdOf, - test_env: &TestEnvironment, - ) { + pub fn default_community_funding_end_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { let token_price = test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = - FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); project_info.weighted_average_price.expect("Token price should exist") }); let expected_plmc_bondings = default_community_plmc_bondings(token_price); let expected_buys = default_community_buys_currency_reserved(token_price); // Check that enough PLMC is bonded - test_env - .do_reserved_funds_assertions(expected_plmc_bondings.clone(), BondType::Contributing); + test_env.do_reserved_funds_assertions(expected_plmc_bondings.clone(), BondType::Contributing); // Check that free funds were reduced let mut free_funds = default_fundings(); // Remove accounts that didnt bond from free_funds - free_funds = - remove_missing_accounts_from_fundings(free_funds, expected_plmc_bondings.clone()); + free_funds = remove_missing_accounts_from_fundings(free_funds, expected_plmc_bondings.clone()); // Subtract the amount spent on the buys from the free funds free_funds = free_funds .iter() @@ -925,19 +808,13 @@ mod defaults { // Check that remaining CTs are updated test_env.ext_env.borrow_mut().execute_with(|| { let project = FundingModule::project_info(project_id).expect("Project should exist"); - let auction_bought_tokens: u128 = default_auction_bids() - .iter() - .map(|(_account, (amount, _price, _multiplier))| amount) - .sum(); - let community_bought_tokens: u128 = default_community_buys() - .iter() - .map(|(_account, (amount, _multiplier))| amount) - .sum(); + let auction_bought_tokens: u128 = + default_auction_bids().iter().map(|(_account, (amount, _price, _multiplier))| amount).sum(); + let community_bought_tokens: u128 = + default_community_buys().iter().map(|(_account, (amount, _multiplier))| amount).sum(); assert_eq!( project.remaining_contribution_tokens, - default_project(0).total_allocation_size - - auction_bought_tokens - - community_bought_tokens, + default_project(0).total_allocation_size - auction_bought_tokens - community_bought_tokens, "Remaining CTs are incorrect" ); }); @@ -948,38 +825,27 @@ mod defaults { test_env: &TestEnvironment, ) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = - FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::RemainderRound); }); } - pub fn default_project_end_assertions( - project_id: ProjectIdOf, - test_env: &TestEnvironment, - ) { + pub fn default_project_end_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { // Check that project status is correct test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = - FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::FundingEnded); }); // Check that remaining CTs are updated test_env.ext_env.borrow_mut().execute_with(|| { let project = FundingModule::project_info(project_id).expect("Project should exist"); - let auction_bought_tokens: u128 = default_auction_bids() - .iter() - .map(|(_account, (amount, _price, _multiplier))| amount) - .sum(); - let community_bought_tokens: u128 = default_community_buys() - .iter() - .map(|(_account, (amount, _multiplier))| amount) - .sum(); - let remainder_bought_tokens: u128 = default_remainder_buys() - .iter() - .map(|(_account, (amount, _multiplier))| amount) - .sum(); + let auction_bought_tokens: u128 = + default_auction_bids().iter().map(|(_account, (amount, _price, _multiplier))| amount).sum(); + let community_bought_tokens: u128 = + default_community_buys().iter().map(|(_account, (amount, _multiplier))| amount).sum(); + let remainder_bought_tokens: u128 = + default_remainder_buys().iter().map(|(_account, (amount, _multiplier))| amount).sum(); assert_eq!( project.remaining_contribution_tokens, default_project(0).total_allocation_size - @@ -1027,11 +893,7 @@ mod creation_round_success { let test_env = TestEnvironment::new(); test_env.fund_accounts(default_fundings()); test_env.ext_env.borrow_mut().execute_with(|| { - assert_ok!(Balances::transfer( - RuntimeOrigin::signed(EVALUATOR_1), - EVALUATOR_2, - 1 * PLMC - )); + assert_ok!(Balances::transfer(RuntimeOrigin::signed(EVALUATOR_1), EVALUATOR_2, 1 * PLMC)); }); } @@ -1161,19 +1023,11 @@ mod evaluation_round_success { let evaluating_project = EvaluatingProject::new_default(&test_env); evaluating_project.bond_for_users(default_evaluation_bonds()).unwrap(); let project_info = evaluating_project.get_project_info(); - test_env - .advance_time(project_info.phase_transition_points.evaluation.end().unwrap() + 1u64); - let end_block = evaluating_project - .get_project_info() - .phase_transition_points - .auction_initialize_period - .end() - .unwrap(); + test_env.advance_time(project_info.phase_transition_points.evaluation.end().unwrap() + 1u64); + let end_block = + evaluating_project.get_project_info().phase_transition_points.auction_initialize_period.end().unwrap(); test_env.advance_time(end_block - test_env.current_block() + 1); - assert_eq!( - evaluating_project.get_project_info().project_status, - ProjectStatus::AuctionRound(English) - ); + assert_eq!(evaluating_project.get_project_info().project_status, ProjectStatus::AuctionRound(English)); } } @@ -1187,20 +1041,16 @@ mod evaluation_round_failure { let evaluating_project = EvaluatingProject::new_default(&test_env); // Partially bond for evaluation - evaluating_project - .bond_for_users(default_failing_evaluation_bonds()) - .expect("Bonding should work"); + evaluating_project.bond_for_users(default_failing_evaluation_bonds()).expect("Bonding should work"); // Check that enough funds are reserved - test_env - .do_reserved_funds_assertions(default_failing_evaluation_bonds(), BondType::Evaluation); + test_env.do_reserved_funds_assertions(default_failing_evaluation_bonds(), BondType::Evaluation); // Check that free funds were reduced let mut free_funds = default_fundings(); // Remove accounts that didnt bond from free_funds - free_funds = - remove_missing_accounts_from_fundings(free_funds, default_failing_evaluation_bonds()); + free_funds = remove_missing_accounts_from_fundings(free_funds, default_failing_evaluation_bonds()); free_funds = free_funds .iter() .zip(default_failing_evaluation_bonds().iter()) @@ -1279,11 +1129,7 @@ mod auction_round_success { let mut bidding_account = 1000; let bid_info = default_auction_bids()[0].1; let necessary_funding = (bid_info.0 * bid_info.1) + - (bid_info - .2 - .unwrap_or_default() - .calculate_bonding_requirement(bid_info.0 * bid_info.1) - .unwrap()); + (bid_info.2.unwrap_or_default().calculate_bonding_requirement(bid_info.0 * bid_info.1).unwrap()); let mut bids_made: UserToBid = vec![]; let starting_bid_block = test_env.current_block(); assert_eq!(test_env.current_block(), starting_bid_block); @@ -1295,9 +1141,7 @@ mod auction_round_success { ); test_env.fund_accounts(vec![(bidding_account, necessary_funding)]); let bids: UserToBid = vec![(bidding_account, bid_info)]; - auctioning_project - .bid_for_users(bids.clone()) - .expect("Candle Bidding should not fail"); + auctioning_project.bid_for_users(bids.clone()).expect("Candle Bidding should not fail"); bids_made.push(bids[0]); bidding_account += 1; test_env.advance_time(1); @@ -1313,10 +1157,8 @@ mod auction_round_success { let split = (random_end - starting_bid_block + 1) as usize; let excluded_bids = bids_made.split_off(split); let included_bids = bids_made; - let _weighted_price = auctioning_project - .get_project_info() - .weighted_average_price - .expect("Weighted price should exist"); + let _weighted_price = + auctioning_project.get_project_info().weighted_average_price.expect("Weighted price should exist"); // let all_bids = test_env.ext_env.borrow_mut().execute_with(|| { // AuctionsInfo::::iter_prefix_values(auctioning_project.project_id) // .map(|bids| bids[0].clone()) @@ -1325,19 +1167,11 @@ mod auction_round_success { for (bidder, (_amount, _price, _multiplier)) in included_bids { test_env.ext_env.borrow_mut().execute_with(|| { let pid = auctioning_project.project_id; - let stored_bid = - FundingModule::auctions_info(pid, bidder).expect("Bid should exist"); + let stored_bid = FundingModule::auctions_info(pid, bidder).expect("Bid should exist"); assert!( matches!( stored_bid[0], - BidInfo { - project: _pid, - amount: _, - price: _, - ticket_size: _, - bidder: _, - .. - } + BidInfo { project: _pid, amount: _, price: _, ticket_size: _, bidder: _, .. } ), "Stored bid does not match the bid that was made" ); @@ -1348,19 +1182,11 @@ mod auction_round_success { for (bidder, (_amount, _price, _multiplier)) in excluded_bids { test_env.ext_env.borrow_mut().execute_with(|| { let pid = auctioning_project.project_id; - let stored_bid = - FundingModule::auctions_info(pid, bidder).expect("Bid should exist"); + let stored_bid = FundingModule::auctions_info(pid, bidder).expect("Bid should exist"); assert!( matches!( stored_bid[0], - BidInfo { - project: _pid, - amount: _, - price: _, - ticket_size: _, - bidder: _, - .. - } + BidInfo { project: _pid, amount: _, price: _, ticket_size: _, bidder: _, .. } ), "Stored bid does not match the bid that was made" ); @@ -1431,10 +1257,8 @@ mod auction_round_failure { (DAVE, (20_000, 8 * PLMC, None)), ]; - let mut fundings: UserToBalance = bids - .iter() - .map(|(user, (amount, price, _))| (*user, *amount * *price)) - .collect::>(); + let mut fundings: UserToBalance = + bids.iter().map(|(user, (amount, price, _))| (*user, *amount * *price)).collect::>(); // Existential deposit on DAVE fundings.push((DAVE, 100 * PLMC)); @@ -1510,16 +1334,12 @@ mod community_round_success { let community_funding_project = CommunityFundingProject::new_default(&test_env); const BOB: AccountId = 808; test_env.ext_env.borrow_mut().execute_with(|| { - let bob_balance = - ::NativeCurrency::reserved_balance(&BOB); + let bob_balance = ::NativeCurrency::reserved_balance(&BOB); let stop = "here"; }); - let remaining_ct = - community_funding_project.get_project_info().remaining_contribution_tokens; - let ct_price = community_funding_project - .get_project_info() - .weighted_average_price - .expect("CT Price should exist"); + let remaining_ct = community_funding_project.get_project_info().remaining_contribution_tokens; + let ct_price = + community_funding_project.get_project_info().weighted_average_price.expect("CT Price should exist"); // Necessary funds to buy remaining CTs, plus some extra for keeping it account alive let buyers: UserToBalance = vec![(BOB, remaining_ct * ct_price), (BOB, 50 * PLMC)]; @@ -1544,10 +1364,7 @@ mod community_round_success { assert_eq!(community_funding_project.get_project_info().remaining_contribution_tokens, 0); // Check project is in FundingEnded state - assert_eq!( - community_funding_project.get_project_info().project_status, - ProjectStatus::FundingEnded - ); + assert_eq!(community_funding_project.get_project_info().project_status, ProjectStatus::FundingEnded); test_env.do_free_funds_assertions(vec![(BOB, (50 * PLMC) * 2)]); } @@ -1558,12 +1375,9 @@ mod community_round_success { let community_funding_project = CommunityFundingProject::new_default(&test_env); const BOB: AccountId = 808; - let remaining_ct = - community_funding_project.get_project_info().remaining_contribution_tokens + 40; // Overbuy - let ct_price = community_funding_project - .get_project_info() - .weighted_average_price - .expect("CT Price should exist"); + let remaining_ct = community_funding_project.get_project_info().remaining_contribution_tokens + 40; // Overbuy + let ct_price = + community_funding_project.get_project_info().weighted_average_price.expect("CT Price should exist"); // Necessary funds to buy remaining CTs, plus some extra for keeping it account alive let buyers: UserToBalance = vec![(BOB, remaining_ct * ct_price), (BOB, 50 * PLMC)]; @@ -1581,10 +1395,7 @@ mod community_round_success { assert_eq!(community_funding_project.get_project_info().remaining_contribution_tokens, 0); // Check project is in FundingEnded state - assert_eq!( - community_funding_project.get_project_info().project_status, - ProjectStatus::FundingEnded - ); + assert_eq!(community_funding_project.get_project_info().project_status, ProjectStatus::FundingEnded); test_env.do_free_funds_assertions(vec![(BOB, (40 * ct_price) * 2 + (50 * PLMC) * 2)]); } @@ -1593,144 +1404,126 @@ mod community_round_success { fn contribution_is_returned_on_limit_reached_same_mult_diff_ct() { let test_env = TestEnvironment::new(); let project = CommunityFundingProject::new_default(&test_env); - let buyer_2_initial_balance = test_env.ext_env.borrow_mut().execute_with(|| { - ::NativeCurrency::free_balance(&BUYER_2) - }); + let buyer_2_initial_balance = test_env + .ext_env + .borrow_mut() + .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); let project_details = project.get_project_info(); // Create a contribution that will reach the limit of contributions for a user-project let multiplier: Option> = None; let token_amount: BalanceOf = 1; let range = 0..::MaxContributionsPerUser::get(); - let contributions: UserToContribution = - range.map(|_| (BUYER_2, (token_amount, multiplier))).collect(); + let contributions: UserToContribution = range.map(|_| (BUYER_2, (token_amount, multiplier))).collect(); // Calculate currencies being transferred and bonded - let contribution_ticket_size = - token_amount * project_details.weighted_average_price.unwrap(); - let plmc_bond = multiplier - .unwrap_or_default() - .calculate_bonding_requirement(contribution_ticket_size) - .unwrap(); + let contribution_ticket_size = token_amount * project_details.weighted_average_price.unwrap(); + let plmc_bond = multiplier.unwrap_or_default().calculate_bonding_requirement(contribution_ticket_size).unwrap(); // Reach the limit of contributions for a user-project project.buy_for_retail_users(contributions.clone()).unwrap(); // Check that the right amount of PLMC is bonded, and funding currency is transferred - let buyer_2_post_buy_balance = test_env.ext_env.borrow_mut().execute_with(|| { - ::NativeCurrency::free_balance(&BUYER_2) - }); + let buyer_2_post_buy_balance = test_env + .ext_env + .borrow_mut() + .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); assert_eq!( buyer_2_post_buy_balance, - buyer_2_initial_balance - - (contribution_ticket_size + plmc_bond) * contributions.len() as u128 + buyer_2_initial_balance - (contribution_ticket_size + plmc_bond) * contributions.len() as u128 ); - let plmc_bond_stored = test_env.ext_env.borrow_mut().execute_with(|| { - crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap() - }); + let plmc_bond_stored = test_env + .ext_env + .borrow_mut() + .execute_with(|| crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap()); assert_eq!(plmc_bond_stored.amount, plmc_bond * contributions.len() as u128); // Make a new contribution with a PLMC bond bigger than the lowest bond already in store for that account let new_multiplier: Option> = None; let new_token_amount: BalanceOf = 2; - let new_contribution: UserToContribution = - vec![(BUYER_2, (new_token_amount, new_multiplier))]; + let new_contribution: UserToContribution = vec![(BUYER_2, (new_token_amount, new_multiplier))]; let new_ticket_size = new_token_amount * project_details.weighted_average_price.unwrap(); - let new_plmc_bond = new_multiplier - .unwrap_or_default() - .calculate_bonding_requirement(new_ticket_size) - .unwrap(); + let new_plmc_bond = new_multiplier.unwrap_or_default().calculate_bonding_requirement(new_ticket_size).unwrap(); project.buy_for_retail_users(new_contribution.clone()).unwrap(); // Check that the previous contribution returned the reserved PLMC and the transferred funding currency - let buyer_2_post_return_balance = test_env.ext_env.borrow_mut().execute_with(|| { - ::NativeCurrency::free_balance(&BUYER_2) - }); + let buyer_2_post_return_balance = test_env + .ext_env + .borrow_mut() + .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); assert_eq!( buyer_2_post_return_balance, - buyer_2_post_buy_balance + (contribution_ticket_size + plmc_bond) - - (new_ticket_size + new_plmc_bond) - ); - let new_plmc_bond_stored = test_env.ext_env.borrow_mut().execute_with(|| { - crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap() - }); - assert_eq!( - new_plmc_bond_stored.amount, - plmc_bond_stored.amount - plmc_bond + new_plmc_bond + buyer_2_post_buy_balance + (contribution_ticket_size + plmc_bond) - (new_ticket_size + new_plmc_bond) ); + let new_plmc_bond_stored = test_env + .ext_env + .borrow_mut() + .execute_with(|| crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap()); + assert_eq!(new_plmc_bond_stored.amount, plmc_bond_stored.amount - plmc_bond + new_plmc_bond); } #[test] fn contribution_is_returned_on_limit_reached_diff_mult_same_ct() { let test_env = TestEnvironment::new(); let project = CommunityFundingProject::new_default(&test_env); - let buyer_2_initial_balance = test_env.ext_env.borrow_mut().execute_with(|| { - ::NativeCurrency::free_balance(&BUYER_2) - }); + let buyer_2_initial_balance = test_env + .ext_env + .borrow_mut() + .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); let project_details = project.get_project_info(); // Create a contribution that will reach the limit of contributions for a user-project let multiplier: Option> = Some(Multiplier(2)); let token_amount: BalanceOf = 1; let range = 0..::MaxContributionsPerUser::get(); - let contributions: UserToContribution = - range.map(|_| (BUYER_2, (token_amount, multiplier))).collect(); + let contributions: UserToContribution = range.map(|_| (BUYER_2, (token_amount, multiplier))).collect(); // Calculate currencies being transferred and bonded - let contribution_ticket_size = - token_amount * project_details.weighted_average_price.unwrap(); - let plmc_bond = multiplier - .unwrap_or_default() - .calculate_bonding_requirement(contribution_ticket_size) - .unwrap(); + let contribution_ticket_size = token_amount * project_details.weighted_average_price.unwrap(); + let plmc_bond = multiplier.unwrap_or_default().calculate_bonding_requirement(contribution_ticket_size).unwrap(); // Reach the limit of contributions for a user-project project.buy_for_retail_users(contributions.clone()).unwrap(); // Check that the right amount of PLMC is bonded, and funding currency is transferred - let buyer_2_post_buy_balance = test_env.ext_env.borrow_mut().execute_with(|| { - ::NativeCurrency::free_balance(&BUYER_2) - }); + let buyer_2_post_buy_balance = test_env + .ext_env + .borrow_mut() + .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); assert_eq!( buyer_2_post_buy_balance, - buyer_2_initial_balance - - (contribution_ticket_size + plmc_bond) * contributions.len() as u128 + buyer_2_initial_balance - (contribution_ticket_size + plmc_bond) * contributions.len() as u128 ); - let plmc_bond_stored = test_env.ext_env.borrow_mut().execute_with(|| { - crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap() - }); + let plmc_bond_stored = test_env + .ext_env + .borrow_mut() + .execute_with(|| crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap()); assert_eq!(plmc_bond_stored.amount, plmc_bond * contributions.len() as u128); // Make a new contribution with a PLMC bond bigger than the lowest bond already in store for that account let new_multiplier: Option> = Some(Multiplier(1)); let new_token_amount: BalanceOf = 1; - let new_contribution: UserToContribution = - vec![(BUYER_2, (new_token_amount, new_multiplier))]; + let new_contribution: UserToContribution = vec![(BUYER_2, (new_token_amount, new_multiplier))]; let new_ticket_size = new_token_amount * project_details.weighted_average_price.unwrap(); - let new_plmc_bond = new_multiplier - .unwrap_or_default() - .calculate_bonding_requirement(new_ticket_size) - .unwrap(); + let new_plmc_bond = new_multiplier.unwrap_or_default().calculate_bonding_requirement(new_ticket_size).unwrap(); project.buy_for_retail_users(new_contribution.clone()).unwrap(); // Check that the previous contribution returned the reserved PLMC and the transferred funding currency - let buyer_2_post_return_balance = test_env.ext_env.borrow_mut().execute_with(|| { - ::NativeCurrency::free_balance(&BUYER_2) - }); + let buyer_2_post_return_balance = test_env + .ext_env + .borrow_mut() + .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); assert_eq!( buyer_2_post_return_balance, - buyer_2_post_buy_balance + (contribution_ticket_size + plmc_bond) - - (new_ticket_size + new_plmc_bond) - ); - let new_plmc_bond_stored = test_env.ext_env.borrow_mut().execute_with(|| { - crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap() - }); - assert_eq!( - new_plmc_bond_stored.amount, - plmc_bond_stored.amount - plmc_bond + new_plmc_bond + buyer_2_post_buy_balance + (contribution_ticket_size + plmc_bond) - (new_ticket_size + new_plmc_bond) ); + let new_plmc_bond_stored = test_env + .ext_env + .borrow_mut() + .execute_with(|| crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap()); + assert_eq!(new_plmc_bond_stored.amount, plmc_bond_stored.amount - plmc_bond + new_plmc_bond); } } @@ -1750,10 +1543,8 @@ mod purchased_vesting { let test_env = TestEnvironment::new(); let finished_project = FinishedProject::new_default(&test_env); let project_id = finished_project.project_id; - let token_price = finished_project - .get_project_info() - .weighted_average_price - .expect("CT price should exist at this point"); + let token_price = + finished_project.get_project_info().weighted_average_price.expect("CT price should exist at this point"); let project = finished_project.get_project(); let decimals = project.token_information.decimals; @@ -1777,26 +1568,20 @@ mod purchased_vesting { let test_env = TestEnvironment::new(); let finished_project = FinishedProject::new_default(&test_env); let project_id = finished_project.project_id; - let price = finished_project - .get_project_info() - .weighted_average_price - .expect("CT price should exist at this point"); + let price = + finished_project.get_project_info().weighted_average_price.expect("CT price should exist at this point"); test_env.ext_env.borrow_mut().execute_with(|| { for (buyer, (token_amount, multiplier)) in default_community_buys() { - let theoretical_bonded_plmc = multiplier - .unwrap_or_default() - .calculate_bonding_requirement(token_amount * price) - .unwrap(); - let actual_bonded_plmc = - Balances::reserved_balance_named(&BondType::Contributing, &buyer); + let theoretical_bonded_plmc = + multiplier.unwrap_or_default().calculate_bonding_requirement(token_amount * price).unwrap(); + let actual_bonded_plmc = Balances::reserved_balance_named(&BondType::Contributing, &buyer); assert_eq!(theoretical_bonded_plmc, actual_bonded_plmc); assert_ok!(FundingModule::vested_plmc_purchase_unbond_for( RuntimeOrigin::signed(buyer), project_id, buyer )); - let actual_bonded_plmc = - Balances::reserved_balance_named(&BondType::Contributing, &buyer); + let actual_bonded_plmc = Balances::reserved_balance_named(&BondType::Contributing, &buyer); assert_eq!(actual_bonded_plmc, 0u32.into()); } }); @@ -1841,20 +1626,16 @@ mod bids_vesting { let _decimals = project.token_information.decimals; test_env.ext_env.borrow_mut().execute_with(|| { for (bidder, (amount, price, multiplier)) in bidders { - let theoretical_bonded_plmc = multiplier - .unwrap_or_default() - .calculate_bonding_requirement(amount * price) - .unwrap(); - let actual_bonded_plmc = - Balances::reserved_balance_named(&BondType::Bidding, &bidder); + let theoretical_bonded_plmc = + multiplier.unwrap_or_default().calculate_bonding_requirement(amount * price).unwrap(); + let actual_bonded_plmc = Balances::reserved_balance_named(&BondType::Bidding, &bidder); assert_eq!(theoretical_bonded_plmc, actual_bonded_plmc); assert_ok!(FundingModule::vested_plmc_bid_unbond_for( RuntimeOrigin::signed(bidder), project_id, bidder )); - let actual_bonded_plmc = - Balances::reserved_balance_named(&BondType::Bidding, &bidder); + let actual_bonded_plmc = Balances::reserved_balance_named(&BondType::Bidding, &bidder); assert_eq!(actual_bonded_plmc, 0u32.into()); } }); diff --git a/pallets/funding/src/types.rs b/pallets/funding/src/types.rs index 4c376e256..ca82b4770 100644 --- a/pallets/funding/src/types.rs +++ b/pallets/funding/src/types.rs @@ -174,6 +174,7 @@ impl BlockNumberPair { pub fn new(start: Option, end: Option) -> Self { Self { start, end } } + pub fn start(&self) -> Option { self.start } @@ -198,15 +199,7 @@ impl BlockNumberPair { } #[derive(Default, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)] -pub struct BidInfo< - BidId, - ProjectId, - Balance: BalanceT, - AccountId, - BlockNumber, - PlmcVesting, - CTVesting, -> { +pub struct BidInfo { pub bid_id: BidId, pub project: ProjectId, #[codec(compact)] @@ -257,32 +250,16 @@ impl sp_std::cmp::Ord - for BidInfo +impl + sp_std::cmp::Ord for BidInfo { fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering { self.price.cmp(&other.price) } } -impl< - BidId: Eq, - ProjectId: Eq, - Balance: BalanceT, - AccountId: Eq, - BlockNumber: Eq, - PlmcVesting: Eq, - CTVesting: Eq, - > sp_std::cmp::PartialOrd - for BidInfo +impl + sp_std::cmp::PartialOrd for BidInfo { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) @@ -350,19 +327,7 @@ pub enum RejectionReason { } /// Enum used to identify PLMC named reserves -#[derive( - Clone, - Encode, - Decode, - Eq, - PartialEq, - RuntimeDebug, - TypeInfo, - MaxEncodedLen, - Copy, - Ord, - PartialOrd, -)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen, Copy, Ord, PartialOrd)] pub enum BondType { Evaluation, Bidding, @@ -428,19 +393,7 @@ impl< } /// Tells on_initialize what to do with the project -#[derive( - Clone, - Encode, - Decode, - Eq, - PartialEq, - RuntimeDebug, - TypeInfo, - MaxEncodedLen, - Copy, - Ord, - PartialOrd, -)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen, Copy, Ord, PartialOrd)] pub enum UpdateType { EvaluationEnd, EnglishAuctionStart, @@ -450,19 +403,7 @@ pub enum UpdateType { FundingEnd, } -#[derive( - Clone, - Encode, - Decode, - Eq, - PartialEq, - RuntimeDebug, - TypeInfo, - MaxEncodedLen, - Copy, - Ord, - PartialOrd, -)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen, Copy, Ord, PartialOrd)] pub struct Multiplier(pub T::Balance); impl BondingRequirementCalculation for Multiplier { fn calculate_bonding_requirement(&self, ticket_size: BalanceOf) -> Result, ()> { diff --git a/pallets/parachain-staking/src/auto_compound.rs b/pallets/parachain-staking/src/auto_compound.rs index 830c4c077..214b212c0 100644 --- a/pallets/parachain-staking/src/auto_compound.rs +++ b/pallets/parachain-staking/src/auto_compound.rs @@ -18,8 +18,8 @@ use crate::{ pallet::{ - AddGet, AutoCompoundingDelegations as AutoCompoundingDelegationsStorage, BalanceOf, - CandidateInfo, Config, DelegatorState, Error, Event, Pallet, Total, + AddGet, AutoCompoundingDelegations as AutoCompoundingDelegationsStorage, BalanceOf, CandidateInfo, Config, + DelegatorState, Error, Event, Pallet, Total, }, types::{Bond, BondAdjust, Delegator}, }; @@ -82,11 +82,7 @@ where /// Sets the auto-compounding value for a delegation. The `delegations_config` must be a sorted /// vector for binary_search to work. - pub fn set_for_delegator( - &mut self, - delegator: T::AccountId, - value: Percent, - ) -> Result> { + pub fn set_for_delegator(&mut self, delegator: T::AccountId, value: Percent) -> Result> { match self.0.binary_search_by(|d| d.delegator.cmp(&delegator)) { Ok(index) => if self.0[index].value == value { @@ -185,8 +181,7 @@ where ensure!(!>::is_candidate(&delegator), Error::::CandidateExists); Delegator::new(delegator.clone(), candidate.clone(), amount) }; - let mut candidate_state = - >::get(&candidate).ok_or(Error::::CandidateDNE)?; + let mut candidate_state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; ensure!( candidate_delegation_count_hint >= candidate_state.delegation_count, Error::::TooLowCandidateDelegationCountToDelegate @@ -204,16 +199,15 @@ where }; // add delegation to candidate - let (delegator_position, less_total_staked) = candidate_state - .add_delegation::(&candidate, Bond { owner: delegator.clone(), amount })?; + let (delegator_position, less_total_staked) = + candidate_state.add_delegation::(&candidate, Bond { owner: delegator.clone(), amount })?; // lock delegator amount delegator_state.adjust_bond_lock::(BondAdjust::Increase(amount))?; // adjust total locked, // only is_some if kicked the lowest bottom as a consequence of this new delegation - let net_total_increase = - if let Some(less) = less_total_staked { amount.saturating_sub(less) } else { amount }; + let net_total_increase = if let Some(less) = less_total_staked { amount.saturating_sub(less) } else { amount }; let new_total_locked = >::get().saturating_add(net_total_increase); // maybe set auto-compound config, state is Some if the percent is non-zero @@ -244,16 +238,12 @@ where candidate_auto_compounding_delegation_count_hint: u32, delegation_count_hint: u32, ) -> DispatchResultWithPostInfo { - let delegator_state = - >::get(&delegator).ok_or(>::DelegatorDNE)?; + let delegator_state = >::get(&delegator).ok_or(>::DelegatorDNE)?; ensure!( delegator_state.delegations.0.len() <= delegation_count_hint as usize, >::TooLowDelegationCountToAutoCompound, ); - ensure!( - delegator_state.delegations.0.iter().any(|b| b.owner == candidate), - >::DelegationDNE, - ); + ensure!(delegator_state.delegations.0.iter().any(|b| b.owner == candidate), >::DelegationDNE,); let mut auto_compounding_state = Self::get_storage(&candidate); ensure!( @@ -297,14 +287,8 @@ mod tests { #[test] fn test_set_for_delegator_inserts_config_and_returns_true_if_entry_missing() { - let mut delegations_config = - AutoCompoundDelegations::::new(vec![].try_into().expect("must succeed")); - assert_eq!( - true, - delegations_config - .set_for_delegator(1, Percent::from_percent(50)) - .expect("must succeed") - ); + let mut delegations_config = AutoCompoundDelegations::::new(vec![].try_into().expect("must succeed")); + assert_eq!(true, delegations_config.set_for_delegator(1, Percent::from_percent(50)).expect("must succeed")); assert_eq!( vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(50) }], delegations_config.into_inner().into_inner(), @@ -318,12 +302,7 @@ mod tests { .try_into() .expect("must succeed"), ); - assert_eq!( - true, - delegations_config - .set_for_delegator(1, Percent::from_percent(50)) - .expect("must succeed") - ); + assert_eq!(true, delegations_config.set_for_delegator(1, Percent::from_percent(50)).expect("must succeed")); assert_eq!( vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(50) }], delegations_config.into_inner().into_inner(), @@ -337,12 +316,7 @@ mod tests { .try_into() .expect("must succeed"), ); - assert_eq!( - false, - delegations_config - .set_for_delegator(1, Percent::from_percent(10)) - .expect("must succeed") - ); + assert_eq!(false, delegations_config.set_for_delegator(1, Percent::from_percent(10)).expect("must succeed")); assert_eq!( vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(10) }], delegations_config.into_inner().into_inner(), @@ -351,8 +325,7 @@ mod tests { #[test] fn test_remove_for_delegator_returns_false_if_entry_was_missing() { - let mut delegations_config = - AutoCompoundDelegations::::new(vec![].try_into().expect("must succeed")); + let mut delegations_config = AutoCompoundDelegations::::new(vec![].try_into().expect("must succeed")); assert_eq!(false, delegations_config.remove_for_delegator(&1),); } diff --git a/pallets/parachain-staking/src/benchmarks.rs b/pallets/parachain-staking/src/benchmarks.rs index 0f8ba8ad6..9380f521c 100644 --- a/pallets/parachain-staking/src/benchmarks.rs +++ b/pallets/parachain-staking/src/benchmarks.rs @@ -18,9 +18,8 @@ //! Benchmarking use crate::{ - AwardedPts, BalanceOf, Call, CandidateBondLessRequest, Config, DelegationAction, Pallet, - ParachainBondConfig, ParachainBondInfo, Points, Range, RewardPayment, Round, ScheduledRequest, - Staked, TopDelegations, + AwardedPts, BalanceOf, Call, CandidateBondLessRequest, Config, DelegationAction, Pallet, ParachainBondConfig, + ParachainBondInfo, Points, Range, RewardPayment, Round, ScheduledRequest, Staked, TopDelegations, }; use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, vec}; use frame_support::traits::{Currency, Get, OnFinalize, OnInitialize}; @@ -41,11 +40,7 @@ fn min_delegator_stk() -> BalanceOf { /// Create a funded user. /// Extra + min_candidate_stk is total minted funds /// Returns tuple (id, balance) -fn create_funded_user( - string: &'static str, - n: u32, - extra: BalanceOf, -) -> (T::AccountId, BalanceOf) { +fn create_funded_user(string: &'static str, n: u32, extra: BalanceOf) -> (T::AccountId, BalanceOf) { const SEED: u32 = 0; let user = account(string, n, SEED); let min_candidate_stk = min_candidate_stk::(); @@ -107,9 +102,7 @@ fn roll_to_and_author(round_delay: u32, author: T::AccountId) { while now < end { parachain_staking_on_finalize::(author.clone()); >::on_finalize(>::block_number()); - >::set_block_number( - >::block_number() + 1u32.into(), - ); + >::set_block_number(>::block_number() + 1u32.into()); >::on_initialize(>::block_number()); Pallet::::on_initialize(>::block_number()); now += 1u32.into(); diff --git a/pallets/parachain-staking/src/delegation_requests.rs b/pallets/parachain-staking/src/delegation_requests.rs index c1beb3d80..8f5bec1ac 100644 --- a/pallets/parachain-staking/src/delegation_requests.rs +++ b/pallets/parachain-staking/src/delegation_requests.rs @@ -19,8 +19,8 @@ use crate::{ auto_compound::AutoCompoundDelegations, pallet::{ - BalanceOf, CandidateInfo, Config, DelegationScheduledRequests, DelegatorState, Error, - Event, Pallet, Round, RoundIndex, Total, + BalanceOf, CandidateInfo, Config, DelegationScheduledRequests, DelegatorState, Error, Event, Pallet, Round, + RoundIndex, Total, }, Delegator, DelegatorStatus, }; @@ -65,10 +65,7 @@ pub struct CancelledScheduledRequest { impl From> for CancelledScheduledRequest { fn from(request: ScheduledRequest) -> Self { - CancelledScheduledRequest { - when_executable: request.when_executable, - action: request.action, - } + CancelledScheduledRequest { when_executable: request.when_executable, action: request.action } } } @@ -160,9 +157,8 @@ impl Pallet { let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; let mut scheduled_requests = >::get(&collator); - let request = - Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests) - .ok_or(>::PendingDelegationRequestDNE)?; + let request = Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests) + .ok_or(>::PendingDelegationRequestDNE)?; >::insert(collator.clone(), scheduled_requests); >::insert(delegator.clone(), state); @@ -238,10 +234,7 @@ impl Pallet { >::insert(collator, scheduled_requests); if leaving { >::remove(&delegator); - Self::deposit_event(Event::DelegatorLeft { - delegator, - unstaked_amount: amount, - }); + Self::deposit_event(Event::DelegatorLeft { delegator, unstaked_amount: amount }); } else { >::insert(&delegator, state); } @@ -258,19 +251,13 @@ impl Pallet { return if bond.amount > amount { let amount_before: BalanceOf = bond.amount; bond.amount = bond.amount.saturating_sub(amount); - let mut collator_info = >::get(&collator) - .ok_or(>::CandidateDNE)?; + let mut collator_info = + >::get(&collator).ok_or(>::CandidateDNE)?; state.total_sub_if::(amount, |total| { let new_total: BalanceOf = total; - ensure!( - new_total >= T::MinDelegation::get(), - >::DelegationBelowMin - ); - ensure!( - new_total >= T::MinDelegatorStk::get(), - >::DelegatorBondBelowMin - ); + ensure!(new_total >= T::MinDelegation::get(), >::DelegationBelowMin); + ensure!(new_total >= T::MinDelegatorStk::get(), >::DelegatorBondBelowMin); Ok(()) })?; @@ -286,10 +273,7 @@ impl Pallet { let new_total_staked = >::get().saturating_sub(amount); >::put(new_total_staked); - >::insert( - collator.clone(), - scheduled_requests, - ); + >::insert(collator.clone(), scheduled_requests); >::insert(delegator.clone(), state); Self::deposit_event(Event::DelegationDecreased { delegator, @@ -311,9 +295,7 @@ impl Pallet { /// Schedules [DelegationAction::Revoke] for the delegator, towards all delegated collator. /// The last fulfilled request causes the delegator to leave the set of delegators. - pub(crate) fn delegator_schedule_revoke_all( - delegator: T::AccountId, - ) -> DispatchResultWithPostInfo { + pub(crate) fn delegator_schedule_revoke_all(delegator: T::AccountId) -> DispatchResultWithPostInfo { let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; let mut updated_scheduled_requests = vec![]; let now = >::get().current; @@ -335,8 +317,7 @@ impl Pallet { let mut scheduled_requests = >::get(&collator); // cancel any existing requests - let request = - Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests); + let request = Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests); let request = match request { Some(revoke_req) if matches!(revoke_req.action, DelegationAction::Revoke(_)) => { existing_revoke_count += 1; @@ -358,27 +339,19 @@ impl Pallet { return Err(>::DelegatorAlreadyLeaving.into()) } - updated_scheduled_requests - .into_iter() - .for_each(|(collator, scheduled_requests)| { - >::insert(collator, scheduled_requests); - }); + updated_scheduled_requests.into_iter().for_each(|(collator, scheduled_requests)| { + >::insert(collator, scheduled_requests); + }); >::insert(delegator.clone(), state); - Self::deposit_event(Event::DelegatorExitScheduled { - round: now, - delegator, - scheduled_exit: when, - }); + Self::deposit_event(Event::DelegatorExitScheduled { round: now, delegator, scheduled_exit: when }); Ok(().into()) } /// Cancels every [DelegationAction::Revoke] request for a delegator towards a collator. /// Each delegation must have a [DelegationAction::Revoke] scheduled that must be allowed to be /// executed in the current round, for this function to succeed. - pub(crate) fn delegator_cancel_scheduled_revoke_all( - delegator: T::AccountId, - ) -> DispatchResultWithPostInfo { + pub(crate) fn delegator_cancel_scheduled_revoke_all(delegator: T::AccountId) -> DispatchResultWithPostInfo { let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; let mut updated_scheduled_requests = vec![]; @@ -397,9 +370,7 @@ impl Pallet { let scheduled_requests = >::get(&collator); scheduled_requests .iter() - .find(|req| { - req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) - }) + .find(|req| req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_))) .ok_or(>::DelegatorNotLeaving)?; } @@ -411,11 +382,9 @@ impl Pallet { updated_scheduled_requests.push((collator, scheduled_requests)); } - updated_scheduled_requests - .into_iter() - .for_each(|(collator, scheduled_requests)| { - >::insert(collator, scheduled_requests); - }); + updated_scheduled_requests.into_iter().for_each(|(collator, scheduled_requests)| { + >::insert(collator, scheduled_requests); + }); >::insert(delegator.clone(), state); Self::deposit_event(Event::DelegatorExitCancelled { delegator }); @@ -443,15 +412,9 @@ impl Pallet { ensure!(>::get().current >= when, Error::::DelegatorCannotLeaveYet); for bond in state.delegations.0.clone() { - if let Err(error) = Self::delegator_leaves_candidate( - bond.owner.clone(), - delegator.clone(), - bond.amount, - ) { - log::warn!( - "STORAGE CORRUPTED \nDelegator leaving collator failed with error: {:?}", - error - ); + if let Err(error) = Self::delegator_leaves_candidate(bond.owner.clone(), delegator.clone(), bond.amount) + { + log::warn!("STORAGE CORRUPTED \nDelegator leaving collator failed with error: {:?}", error); } Self::delegation_remove_request_with_state(&bond.owner, &delegator, &mut state); @@ -468,9 +431,7 @@ impl Pallet { let scheduled_requests = >::get(&bond.owner); let request_idx = scheduled_requests .iter() - .position(|req| { - req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) - }) + .position(|req| req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_))) .ok_or(>::DelegatorNotLeaving)?; let request = &scheduled_requests[request_idx]; @@ -484,9 +445,7 @@ impl Pallet { for (bond, mut scheduled_requests, request_idx) in validated_scheduled_requests { let collator = bond.owner; - if let Err(error) = - Self::delegator_leaves_candidate(collator.clone(), delegator.clone(), bond.amount) - { + if let Err(error) = Self::delegator_leaves_candidate(collator.clone(), delegator.clone(), bond.amount) { log::warn!( "STORAGE CORRUPTED \nDelegator {:?} leaving collator failed with error: {:?}", delegator, @@ -506,11 +465,9 @@ impl Pallet { let unstaked_amount = state.total(); state.total_sub::(unstaked_amount)?; - updated_scheduled_requests - .into_iter() - .for_each(|(collator, scheduled_requests)| { - >::insert(collator, scheduled_requests); - }); + updated_scheduled_requests.into_iter().for_each(|(collator, scheduled_requests)| { + >::insert(collator, scheduled_requests); + }); Self::deposit_event(Event::DelegatorLeft { delegator: delegator.clone(), unstaked_amount }); >::remove(&delegator); @@ -527,8 +484,7 @@ impl Pallet { ) { let mut scheduled_requests = >::get(collator); - let maybe_request_idx = - scheduled_requests.iter().position(|req| &req.delegator == delegator); + let maybe_request_idx = scheduled_requests.iter().position(|req| &req.delegator == delegator); if let Some(request_idx) = maybe_request_idx { let request = scheduled_requests.remove(request_idx); @@ -540,19 +496,14 @@ impl Pallet { /// Returns true if a [ScheduledRequest] exists for a given delegation pub fn delegation_request_exists(collator: &T::AccountId, delegator: &T::AccountId) -> bool { - >::get(collator) - .iter() - .any(|req| &req.delegator == delegator) + >::get(collator).iter().any(|req| &req.delegator == delegator) } /// Returns true if a [DelegationAction::Revoke] [ScheduledRequest] exists for a given delegation - pub fn delegation_request_revoke_exists( - collator: &T::AccountId, - delegator: &T::AccountId, - ) -> bool { - >::get(collator).iter().any(|req| { - &req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) - }) + pub fn delegation_request_revoke_exists(collator: &T::AccountId, delegator: &T::AccountId) -> bool { + >::get(collator) + .iter() + .any(|req| &req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_))) } } @@ -571,35 +522,18 @@ mod tests { status: crate::DelegatorStatus::Active, }; let mut scheduled_requests = vec![ - ScheduledRequest { - delegator: 1, - when_executable: 1, - action: DelegationAction::Revoke(100), - }, - ScheduledRequest { - delegator: 2, - when_executable: 1, - action: DelegationAction::Decrease(50), - }, + ScheduledRequest { delegator: 1, when_executable: 1, action: DelegationAction::Revoke(100) }, + ScheduledRequest { delegator: 2, when_executable: 1, action: DelegationAction::Decrease(50) }, ]; - let removed_request = - >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); + let removed_request = >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); assert_eq!( removed_request, - Some(ScheduledRequest { - delegator: 1, - when_executable: 1, - action: DelegationAction::Revoke(100), - }) + Some(ScheduledRequest { delegator: 1, when_executable: 1, action: DelegationAction::Revoke(100) }) ); assert_eq!( scheduled_requests, - vec![ScheduledRequest { - delegator: 2, - when_executable: 1, - action: DelegationAction::Decrease(50), - },] + vec![ScheduledRequest { delegator: 2, when_executable: 1, action: DelegationAction::Decrease(50) },] ); assert_eq!( state, @@ -622,22 +556,14 @@ mod tests { less_total: 100, status: crate::DelegatorStatus::Active, }; - let mut scheduled_requests = vec![ScheduledRequest { - delegator: 2, - when_executable: 1, - action: DelegationAction::Decrease(50), - }]; - let removed_request = - >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); + let mut scheduled_requests = + vec![ScheduledRequest { delegator: 2, when_executable: 1, action: DelegationAction::Decrease(50) }]; + let removed_request = >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); assert_eq!(removed_request, None,); assert_eq!( scheduled_requests, - vec![ScheduledRequest { - delegator: 2, - when_executable: 1, - action: DelegationAction::Decrease(50), - },] + vec![ScheduledRequest { delegator: 2, when_executable: 1, action: DelegationAction::Decrease(50) },] ); assert_eq!( state, diff --git a/pallets/parachain-staking/src/inflation.rs b/pallets/parachain-staking/src/inflation.rs index e6c6778d7..b2b6aacd2 100644 --- a/pallets/parachain-staking/src/inflation.rs +++ b/pallets/parachain-staking/src/inflation.rs @@ -34,9 +34,7 @@ fn rounds_per_year() -> u32 { } #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[derive( - Eq, PartialEq, Clone, Copy, Encode, Decode, Default, RuntimeDebug, MaxEncodedLen, TypeInfo, -)] +#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, Default, RuntimeDebug, MaxEncodedLen, TypeInfo)] pub struct Range { pub min: T, pub ideal: T, @@ -56,26 +54,15 @@ impl From for Range { } /// Convert an annual inflation to a round inflation /// round = (1+annual)^(1/rounds_per_year) - 1 -pub fn perbill_annual_to_perbill_round( - annual: Range, - rounds_per_year: u32, -) -> Range { +pub fn perbill_annual_to_perbill_round(annual: Range, rounds_per_year: u32) -> Range { let exponent = I64F64::from_num(1) / I64F64::from_num(rounds_per_year); let annual_to_round = |annual: Perbill| -> Perbill { let x = I64F64::from_num(annual.deconstruct()) / I64F64::from_num(Perbill::ACCURACY); let y: I64F64 = floatpow(I64F64::from_num(1) + x, exponent) .expect("Cannot overflow since rounds_per_year is u32 so worst case 0; QED"); - Perbill::from_parts( - ((y - I64F64::from_num(1)) * I64F64::from_num(Perbill::ACCURACY)) - .ceil() - .to_num::(), - ) + Perbill::from_parts(((y - I64F64::from_num(1)) * I64F64::from_num(Perbill::ACCURACY)).ceil().to_num::()) }; - Range { - min: annual_to_round(annual.min), - ideal: annual_to_round(annual.ideal), - max: annual_to_round(annual.max), - } + Range { min: annual_to_round(annual.min), ideal: annual_to_round(annual.ideal), max: annual_to_round(annual.max) } } /// Convert annual inflation rate range to round inflation range pub fn annual_to_round(annual: Range) -> Range { @@ -86,11 +73,7 @@ pub fn annual_to_round(annual: Range) -> Range { /// Compute round issuance range from round inflation range and current total issuance pub fn round_issuance_range(round: Range) -> Range> { let circulating = T::Currency::total_issuance(); - Range { - min: round.min * circulating, - ideal: round.ideal * circulating, - max: round.max * circulating, - } + Range { min: round.min * circulating, ideal: round.ideal * circulating, max: round.max * circulating } } #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] @@ -105,21 +88,21 @@ pub struct InflationInfo { } impl InflationInfo { - pub fn new( - annual: Range, - expect: Range, - ) -> InflationInfo { + pub fn new(annual: Range, expect: Range) -> InflationInfo { InflationInfo { expect, annual, round: annual_to_round::(annual) } } + /// Set round inflation range according to input annual inflation range pub fn set_round_from_annual(&mut self, new: Range) { self.round = annual_to_round::(new); } + /// Reset round inflation rate based on changes to round length pub fn reset_round(&mut self, new_length: u32) { let periods = BLOCKS_PER_YEAR / new_length; self.round = perbill_annual_to_perbill_round(self.annual, periods); } + /// Set staking expectations pub fn set_expectations(&mut self, expect: Range) { self.expect = expect; @@ -138,24 +121,16 @@ mod tests { // Round inflation range round: Range, ) -> Range { - Range { - min: round.min * circulating, - ideal: round.ideal * circulating, - max: round.max * circulating, - } + Range { min: round.min * circulating, ideal: round.ideal * circulating, max: round.max * circulating } } #[test] fn simple_issuance_conversion() { // 5% inflation for 10_000_0000 = 500,000 minted over the year // let's assume there are 10 periods in a year // => mint 500_000 over 10 periods => 50_000 minted per period - let expected_round_issuance_range: Range = - Range { min: 48_909, ideal: 48_909, max: 48_909 }; - let schedule = Range { - min: Perbill::from_percent(5), - ideal: Perbill::from_percent(5), - max: Perbill::from_percent(5), - }; + let expected_round_issuance_range: Range = Range { min: 48_909, ideal: 48_909, max: 48_909 }; + let schedule = + Range { min: Perbill::from_percent(5), ideal: Perbill::from_percent(5), max: Perbill::from_percent(5) }; assert_eq!( expected_round_issuance_range, mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 10)) @@ -166,13 +141,9 @@ mod tests { // 3-5% inflation for 10_000_0000 = 300_000-500,000 minted over the year // let's assume there are 10 periods in a year // => mint 300_000-500_000 over 10 periods => 30_000-50_000 minted per period - let expected_round_issuance_range: Range = - Range { min: 29_603, ideal: 39298, max: 48_909 }; - let schedule = Range { - min: Perbill::from_percent(3), - ideal: Perbill::from_percent(4), - max: Perbill::from_percent(5), - }; + let expected_round_issuance_range: Range = Range { min: 29_603, ideal: 39298, max: 48_909 }; + let schedule = + Range { min: Perbill::from_percent(3), ideal: Perbill::from_percent(4), max: Perbill::from_percent(5) }; assert_eq!( expected_round_issuance_range, mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 10)) @@ -181,11 +152,8 @@ mod tests { #[test] fn expected_parameterization() { let expected_round_schedule: Range = Range { min: 45, ideal: 56, max: 56 }; - let schedule = Range { - min: Perbill::from_percent(4), - ideal: Perbill::from_percent(5), - max: Perbill::from_percent(5), - }; + let schedule = + Range { min: Perbill::from_percent(4), ideal: Perbill::from_percent(5), max: Perbill::from_percent(5) }; assert_eq!( expected_round_schedule, mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 8766)) diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index 0ed5d4e24..b787a8577 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -87,8 +87,8 @@ pub mod pallet { use frame_support::{ pallet_prelude::*, traits::{ - tokens::WithdrawReasons, Currency, EstimateNextSessionRotation, Get, Imbalance, - LockIdentifier, LockableCurrency, ReservableCurrency, + tokens::WithdrawReasons, Currency, EstimateNextSessionRotation, Get, Imbalance, LockIdentifier, + LockableCurrency, ReservableCurrency, }, }; use frame_system::pallet_prelude::*; @@ -106,8 +106,7 @@ pub mod pallet { pub type RoundIndex = u32; type RewardPoint = u32; - pub type BalanceOf = - <::Currency as Currency<::AccountId>>::Balance; + pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; pub type AccountIdOf = ::AccountId; @@ -272,9 +271,13 @@ pub mod pallet { new_bond: BalanceOf, }, /// Candidate temporarily leave the set of collator candidates without unbonding. - CandidateWentOffline { candidate: T::AccountId }, + CandidateWentOffline { + candidate: T::AccountId, + }, /// Candidate rejoins the set of collator candidates. - CandidateBackOnline { candidate: T::AccountId }, + CandidateBackOnline { + candidate: T::AccountId, + }, /// Candidate has requested to leave the set of candidates. CandidateScheduledExit { exit_allowed_round: RoundIndex, @@ -282,7 +285,9 @@ pub mod pallet { scheduled_exit: RoundIndex, }, /// Cancelled request to leave the set of candidates. - CancelledCandidateExit { candidate: T::AccountId }, + CancelledCandidateExit { + candidate: T::AccountId, + }, /// Cancelled request to decrease candidate's bond. CancelledCandidateBondLess { candidate: T::AccountId, @@ -330,7 +335,10 @@ pub mod pallet { scheduled_exit: RoundIndex, }, /// Delegator has left the set of delegators. - DelegatorLeft { delegator: T::AccountId, unstaked_amount: BalanceOf }, + DelegatorLeft { + delegator: T::AccountId, + unstaked_amount: BalanceOf, + }, /// Delegation revoked. DelegationRevoked { delegator: T::AccountId, @@ -344,7 +352,9 @@ pub mod pallet { unstaked_amount: BalanceOf, }, /// Cancelled a pending request to exit the set of delegators. - DelegatorExitCancelled { delegator: T::AccountId }, + DelegatorExitCancelled { + delegator: T::AccountId, + }, /// Cancelled request to change an existing delegation. CancelledDelegationRequest { delegator: T::AccountId, @@ -367,13 +377,25 @@ pub mod pallet { total_candidate_staked: BalanceOf, }, /// Paid the account (delegator or collator) the balance as liquid rewards. - Rewarded { account: T::AccountId, rewards: BalanceOf }, + Rewarded { + account: T::AccountId, + rewards: BalanceOf, + }, /// Transferred to account which holds funds reserved for parachain bond. - ReservedForParachainBond { account: T::AccountId, value: BalanceOf }, + ReservedForParachainBond { + account: T::AccountId, + value: BalanceOf, + }, /// Account (re)set for parachain bond treasury. - ParachainBondAccountSet { old: T::AccountId, new: T::AccountId }, + ParachainBondAccountSet { + old: T::AccountId, + new: T::AccountId, + }, /// Percent of inflation reserved for parachain bond (re)set. - ParachainBondReservePercentSet { old: Percent, new: Percent }, + ParachainBondReservePercentSet { + old: Percent, + new: Percent, + }, /// Annual inflation input (first 3) was used to derive new per-round inflation (last 3) InflationSet { annual_min: Perbill, @@ -390,9 +412,15 @@ pub mod pallet { expect_max: BalanceOf, }, /// Set total selected candidates to this value. - TotalSelectedSet { old: u32, new: u32 }, + TotalSelectedSet { + old: u32, + new: u32, + }, /// Set collator commission to this value. - CollatorCommissionSet { old: Perbill, new: Perbill }, + CollatorCommissionSet { + old: Perbill, + new: Perbill, + }, /// Set blocks per round BlocksPerRoundSet { current_round: RoundIndex, @@ -404,9 +432,17 @@ pub mod pallet { new_per_round_inflation_max: Perbill, }, /// Auto-compounding reward percent was set for a delegation. - AutoCompoundSet { candidate: T::AccountId, delegator: T::AccountId, value: Percent }, + AutoCompoundSet { + candidate: T::AccountId, + delegator: T::AccountId, + value: Percent, + }, /// Compounded a portion of rewards towards the delegation. - Compounded { candidate: T::AccountId, delegator: T::AccountId, amount: BalanceOf }, + Compounded { + candidate: T::AccountId, + delegator: T::AccountId, + amount: BalanceOf, + }, } #[pallet::hooks] @@ -464,8 +500,7 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn parachain_bond_info)] /// Parachain bond config info { account, percent_of_inflation } - pub(crate) type ParachainBondInfo = - StorageValue<_, ParachainBondConfig, ValueQuery>; + pub(crate) type ParachainBondInfo = StorageValue<_, ParachainBondConfig, ValueQuery>; #[pallet::storage] #[pallet::getter(fn round)] @@ -475,13 +510,8 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn delegator_state)] /// Get delegator state associated with an account if account is delegating else None - pub(crate) type DelegatorState = StorageMap< - _, - Twox64Concat, - T::AccountId, - Delegator>, - OptionQuery, - >; + pub(crate) type DelegatorState = + StorageMap<_, Twox64Concat, T::AccountId, Delegator>, OptionQuery>; #[pallet::storage] #[pallet::getter(fn candidate_info)] @@ -492,13 +522,8 @@ pub mod pallet { /// Stores outstanding delegation requests per collator. #[pallet::storage] #[pallet::getter(fn delegation_scheduled_requests)] - pub(crate) type DelegationScheduledRequests = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - Vec>>, - ValueQuery, - >; + pub(crate) type DelegationScheduledRequests = + StorageMap<_, Blake2_128Concat, T::AccountId, Vec>>, ValueQuery>; pub struct AddGet { _phantom: PhantomData<(T, R)>, @@ -530,24 +555,14 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn top_delegations)] /// Top delegations for collator candidate - pub(crate) type TopDelegations = StorageMap< - _, - Twox64Concat, - T::AccountId, - Delegations>, - OptionQuery, - >; + pub(crate) type TopDelegations = + StorageMap<_, Twox64Concat, T::AccountId, Delegations>, OptionQuery>; #[pallet::storage] #[pallet::getter(fn bottom_delegations)] /// Bottom delegations for collator candidate - pub(crate) type BottomDelegations = StorageMap< - _, - Twox64Concat, - T::AccountId, - Delegations>, - OptionQuery, - >; + pub(crate) type BottomDelegations = + StorageMap<_, Twox64Concat, T::AccountId, Delegations>, OptionQuery>; #[pallet::storage] #[pallet::getter(fn selected_candidates)] @@ -602,15 +617,8 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn awarded_pts)] /// Points for each collator per round - pub type AwardedPts = StorageDoubleMap< - _, - Twox64Concat, - RoundIndex, - Twox64Concat, - T::AccountId, - RewardPoint, - ValueQuery, - >; + pub type AwardedPts = + StorageDoubleMap<_, Twox64Concat, RoundIndex, Twox64Concat, T::AccountId, RewardPoint, ValueQuery>; #[pallet::genesis_config] pub struct GenesisConfig { @@ -670,8 +678,7 @@ pub mod pallet { } let mut col_delegator_count: BTreeMap = BTreeMap::new(); - let mut col_auto_compound_delegator_count: BTreeMap = - BTreeMap::new(); + let mut col_auto_compound_delegator_count: BTreeMap = BTreeMap::new(); let mut del_delegation_count: BTreeMap = BTreeMap::new(); // Initialize the delegations for &(ref delegator, ref target, balance, auto_compound) in &self.delegations { @@ -679,12 +686,9 @@ pub mod pallet { >::get_delegator_stakable_free_balance(delegator) >= balance, "Account does not have enough balance to place delegation." ); - let cd_count = - if let Some(x) = col_delegator_count.get(target) { *x } else { 0u32 }; - let dd_count = - if let Some(x) = del_delegation_count.get(delegator) { *x } else { 0u32 }; - let cd_auto_compound_count = - col_auto_compound_delegator_count.get(target).cloned().unwrap_or_default(); + let cd_count = if let Some(x) = col_delegator_count.get(target) { *x } else { 0u32 }; + let dd_count = if let Some(x) = del_delegation_count.get(delegator) { *x } else { 0u32 }; + let cd_auto_compound_count = col_auto_compound_delegator_count.get(target).cloned().unwrap_or_default(); if let Err(error) = >::delegate_with_auto_compound( T::RuntimeOrigin::from(Some(delegator.clone()).into()), target.clone(), @@ -733,8 +737,7 @@ pub mod pallet { // Choose top TotalSelected collator candidates let (_, v_count, _, total_staked) = >::select_top_candidates(1u32); // Start Round 1 at Block 0 - let round: RoundInfo = - RoundInfo::new(1u32, 0u32.into(), self.blocks_per_round); + let round: RoundInfo = RoundInfo::new(1u32, 0u32.into(), self.blocks_per_round); >::put(round); // Snapshot total stake >::insert(1u32, >::get()); @@ -774,10 +777,7 @@ pub mod pallet { /// Set the annual inflation rate to derive per-round inflation #[pallet::call_index(1)] #[pallet::weight(::WeightInfo::set_inflation())] - pub fn set_inflation( - origin: OriginFor, - schedule: Range, - ) -> DispatchResultWithPostInfo { + pub fn set_inflation(origin: OriginFor, schedule: Range) -> DispatchResultWithPostInfo { T::MonetaryGovernanceOrigin::ensure_origin(origin)?; ensure!(schedule.is_valid(), Error::::InvalidSchedule); let mut config = >::get(); @@ -799,10 +799,7 @@ pub mod pallet { /// Set the account that will hold funds set aside for parachain bond #[pallet::call_index(2)] #[pallet::weight(::WeightInfo::set_parachain_bond_account())] - pub fn set_parachain_bond_account( - origin: OriginFor, - new: T::AccountId, - ) -> DispatchResultWithPostInfo { + pub fn set_parachain_bond_account(origin: OriginFor, new: T::AccountId) -> DispatchResultWithPostInfo { T::MonetaryGovernanceOrigin::ensure_origin(origin)?; let ParachainBondConfig { account: old, percent } = >::get(); ensure!(old != new, Error::::NoWritingSameValue); @@ -814,10 +811,7 @@ pub mod pallet { /// Set the percent of inflation set aside for parachain bond #[pallet::call_index(3)] #[pallet::weight(::WeightInfo::set_parachain_bond_reserve_percent())] - pub fn set_parachain_bond_reserve_percent( - origin: OriginFor, - new: Percent, - ) -> DispatchResultWithPostInfo { + pub fn set_parachain_bond_reserve_percent(origin: OriginFor, new: Percent) -> DispatchResultWithPostInfo { T::MonetaryGovernanceOrigin::ensure_origin(origin)?; let ParachainBondConfig { account, percent: old } = >::get(); ensure!(old != new, Error::::NoWritingSameValue); @@ -835,10 +829,7 @@ pub mod pallet { ensure!(new >= T::MinSelectedCandidates::get(), Error::::CannotSetBelowMin); let old = >::get(); ensure!(old != new, Error::::NoWritingSameValue); - ensure!( - new < >::get().length, - Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, - ); + ensure!(new < >::get().length, Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators,); >::put(new); Self::deposit_event(Event::TotalSelectedSet { old, new }); Ok(().into()) @@ -847,10 +838,7 @@ pub mod pallet { /// Set the commission for all collators #[pallet::call_index(5)] #[pallet::weight(::WeightInfo::set_collator_commission())] - pub fn set_collator_commission( - origin: OriginFor, - new: Perbill, - ) -> DispatchResultWithPostInfo { + pub fn set_collator_commission(origin: OriginFor, new: Perbill) -> DispatchResultWithPostInfo { frame_system::ensure_root(origin)?; let old = >::get(); ensure!(old != new, Error::::NoWritingSameValue); @@ -871,10 +859,7 @@ pub mod pallet { let mut round = >::get(); let (now, first, old) = (round.current, round.first, round.length); ensure!(old != new, Error::::NoWritingSameValue); - ensure!( - new > >::get(), - Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, - ); + ensure!(new > >::get(), Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators,); round.length = new; // update per-round inflation given new rounds per year let mut inflation_config = >::get(); @@ -907,18 +892,9 @@ pub mod pallet { ensure!(bond >= T::MinCandidateStk::get(), Error::::CandidateBondBelowMin); let mut candidates = >::get(); let old_count = candidates.0.len() as u32; - ensure!( - candidate_count >= old_count, - Error::::TooLowCandidateCountWeightHintJoinCandidates - ); - ensure!( - candidates.insert(Bond { owner: acc.clone(), amount: bond }), - Error::::CandidateExists - ); - ensure!( - Self::get_collator_stakable_free_balance(&acc) >= bond, - Error::::InsufficientBalance, - ); + ensure!(candidate_count >= old_count, Error::::TooLowCandidateCountWeightHintJoinCandidates); + ensure!(candidates.insert(Bond { owner: acc.clone(), amount: bond }), Error::::CandidateExists); + ensure!(Self::get_collator_stakable_free_balance(&acc) >= bond, Error::::InsufficientBalance,); T::Currency::set_lock(COLLATOR_LOCK_ID, &acc, bond, WithdrawReasons::all()); let candidate = CandidateMetadata::new(bond); >::insert(&acc, candidate); @@ -942,18 +918,12 @@ pub mod pallet { /// removed from the candidate pool to prevent selection as a collator. #[pallet::call_index(8)] #[pallet::weight(::WeightInfo::schedule_leave_candidates(*candidate_count))] - pub fn schedule_leave_candidates( - origin: OriginFor, - candidate_count: u32, - ) -> DispatchResultWithPostInfo { + pub fn schedule_leave_candidates(origin: OriginFor, candidate_count: u32) -> DispatchResultWithPostInfo { let collator = ensure_signed(origin)?; let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; let (now, when) = state.schedule_leave::()?; let mut candidates = >::get(); - ensure!( - candidate_count >= candidates.0.len() as u32, - Error::::TooLowCandidateCountToLeaveCandidates - ); + ensure!(candidate_count >= candidates.0.len() as u32, Error::::TooLowCandidateCountToLeaveCandidates); if candidates.remove(&Bond::from_owner(collator.clone())) { >::put(candidates); } @@ -992,11 +962,7 @@ pub mod pallet { ); if let Some(remaining) = delegator.rm_delegation::(&candidate) { - Self::delegation_remove_request_with_state( - &candidate, - &bond.owner, - &mut delegator, - ); + Self::delegation_remove_request_with_state(&candidate, &bond.owner, &mut delegator); >::remove_auto_compound(&candidate, &bond.owner); if remaining.is_zero() { @@ -1018,15 +984,13 @@ pub mod pallet { // total backing stake is at least the candidate self bond let mut total_backing = state.bond; // return all top delegations - let top_delegations = - >::take(&candidate).expect("CandidateInfo existence checked"); + let top_delegations = >::take(&candidate).expect("CandidateInfo existence checked"); for bond in top_delegations.delegations { return_stake(bond)?; } total_backing = total_backing.saturating_add(top_delegations.total); // return all bottom delegations - let bottom_delegations = - >::take(&candidate).expect("CandidateInfo existence checked"); + let bottom_delegations = >::take(&candidate).expect("CandidateInfo existence checked"); for bond in bottom_delegations.delegations { return_stake(bond)?; } @@ -1053,10 +1017,7 @@ pub mod pallet { /// - result upon successful call is the candidate is active in the candidate pool #[pallet::call_index(10)] #[pallet::weight(::WeightInfo::cancel_leave_candidates(*candidate_count))] - pub fn cancel_leave_candidates( - origin: OriginFor, - candidate_count: u32, - ) -> DispatchResultWithPostInfo { + pub fn cancel_leave_candidates(origin: OriginFor, candidate_count: u32) -> DispatchResultWithPostInfo { let collator = ensure_signed(origin)?; let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; ensure!(state.is_leaving(), Error::::CandidateNotLeaving); @@ -1116,10 +1077,7 @@ pub mod pallet { /// Increase collator candidate self bond by `more` #[pallet::call_index(13)] #[pallet::weight(::WeightInfo::candidate_bond_more())] - pub fn candidate_bond_more( - origin: OriginFor, - more: BalanceOf, - ) -> DispatchResultWithPostInfo { + pub fn candidate_bond_more(origin: OriginFor, more: BalanceOf) -> DispatchResultWithPostInfo { let collator = ensure_signed(origin)?; let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; state.bond_more::(collator.clone(), more)?; @@ -1134,10 +1092,7 @@ pub mod pallet { /// Request by collator candidate to decrease self bond by `less` #[pallet::call_index(14)] #[pallet::weight(::WeightInfo::schedule_candidate_bond_less())] - pub fn schedule_candidate_bond_less( - origin: OriginFor, - less: BalanceOf, - ) -> DispatchResultWithPostInfo { + pub fn schedule_candidate_bond_less(origin: OriginFor, less: BalanceOf) -> DispatchResultWithPostInfo { let collator = ensure_signed(origin)?; let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; let when = state.schedule_bond_less::(less)?; @@ -1275,10 +1230,7 @@ pub mod pallet { /// A revoke may not be performed if any other scheduled request is pending. #[pallet::call_index(22)] #[pallet::weight(::WeightInfo::schedule_revoke_delegation())] - pub fn schedule_revoke_delegation( - origin: OriginFor, - collator: T::AccountId, - ) -> DispatchResultWithPostInfo { + pub fn schedule_revoke_delegation(origin: OriginFor, collator: T::AccountId) -> DispatchResultWithPostInfo { let delegator = ensure_signed(origin)?; Self::delegation_schedule_revoke(collator, delegator) } @@ -1292,17 +1244,8 @@ pub mod pallet { more: BalanceOf, ) -> DispatchResultWithPostInfo { let delegator = ensure_signed(origin)?; - let in_top = Self::delegation_bond_more_without_event( - delegator.clone(), - candidate.clone(), - more, - )?; - Pallet::::deposit_event(Event::DelegationIncreased { - delegator, - candidate, - amount: more, - in_top, - }); + let in_top = Self::delegation_bond_more_without_event(delegator.clone(), candidate.clone(), more)?; + Pallet::::deposit_event(Event::DelegationIncreased { delegator, candidate, amount: more, in_top }); Ok(().into()) } @@ -1336,10 +1279,7 @@ pub mod pallet { /// Cancel request to change an existing delegation. #[pallet::call_index(26)] #[pallet::weight(::WeightInfo::cancel_delegator_bond_less())] - pub fn cancel_delegation_request( - origin: OriginFor, - candidate: T::AccountId, - ) -> DispatchResultWithPostInfo { + pub fn cancel_delegation_request(origin: OriginFor, candidate: T::AccountId) -> DispatchResultWithPostInfo { let delegator = ensure_signed(origin)?; Self::delegation_cancel_request(candidate, delegator) } @@ -1379,14 +1319,8 @@ pub mod pallet { ensure_signed(origin)?; ensure!(candidates.len() < 100, >::InsufficientBalance); for candidate in &candidates { - ensure!( - >::get(candidate).is_none(), - >::CandidateNotLeaving - ); - ensure!( - >::get(candidate).is_empty(), - >::CandidateNotLeaving - ); + ensure!(>::get(candidate).is_none(), >::CandidateNotLeaving); + ensure!(>::get(candidate).is_empty(), >::CandidateNotLeaving); } for candidate in candidates { @@ -1412,12 +1346,15 @@ pub mod pallet { pub fn is_delegator(acc: &T::AccountId) -> bool { >::get(acc).is_some() } + pub fn is_candidate(acc: &T::AccountId) -> bool { >::get(acc).is_some() } + pub fn is_selected_candidate(acc: &T::AccountId) -> bool { >::get().binary_search(acc).is_ok() } + /// Returns an account's free balance which is not locked in delegation staking pub fn get_delegator_stakable_free_balance(acc: &T::AccountId) -> BalanceOf { let mut balance = T::Currency::free_balance(acc); @@ -1426,6 +1363,7 @@ pub mod pallet { } balance } + /// Returns an account's free balance which is not locked in collator staking pub fn get_collator_stakable_free_balance(acc: &T::AccountId) -> BalanceOf { let mut balance = T::Currency::free_balance(acc); @@ -1434,13 +1372,12 @@ pub mod pallet { } balance } + /// Returns a delegations auto-compound value. - pub fn delegation_auto_compound( - candidate: &T::AccountId, - delegator: &T::AccountId, - ) -> Percent { + pub fn delegation_auto_compound(candidate: &T::AccountId, delegator: &T::AccountId) -> Percent { >::auto_compound(candidate, delegator) } + /// Caller must ensure candidate is active before calling pub(crate) fn update_active(candidate: T::AccountId, total: BalanceOf) { let mut candidates = >::get(); @@ -1448,6 +1385,7 @@ pub mod pallet { candidates.insert(Bond { owner: candidate, amount: total }); >::put(candidates); } + /// Compute round issuance based on total staked for the given round fn compute_issuance(staked: BalanceOf) -> BalanceOf { let config = >::get(); @@ -1461,6 +1399,7 @@ pub mod pallet { round_issuance.ideal } } + /// Remove delegation from candidate state /// Amount input should be retrieved from delegator and it informs the storage lookups pub(crate) fn delegator_leaves_candidate( @@ -1482,6 +1421,7 @@ pub mod pallet { }); Ok(()) } + pub(crate) fn prepare_staking_payouts(now: RoundIndex) -> Weight { // payout is now - delay rounds ago => now - delay > 0 else return early let delay = T::RewardPaymentDelay::get(); @@ -1499,9 +1439,7 @@ pub mod pallet { // reserve portion of issuance for parachain bond account let bond_config = >::get(); let parachain_bond_reserve = bond_config.percent * total_issuance; - if let Ok(imb) = - T::Currency::deposit_into_existing(&bond_config.account, parachain_bond_reserve) - { + if let Ok(imb) = T::Currency::deposit_into_existing(&bond_config.account, parachain_bond_reserve) { // update round issuance iff transfer succeeds left_issuance = left_issuance.saturating_sub(imb.peek()); Self::deposit_event(Event::ReservedForParachainBond { @@ -1578,9 +1516,7 @@ pub mod pallet { let collator_fee = payout_info.collator_commission; let collator_issuance = collator_fee * payout_info.round_issuance; - if let Some((collator, state)) = - >::iter_prefix(paid_for_round).drain().next() - { + if let Some((collator, state)) = >::iter_prefix(paid_for_round).drain().next() { // read and kill AtStake early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); @@ -1608,11 +1544,7 @@ pub mod pallet { collator.clone(), amt_due, )) - .saturating_add(T::OnCollatorPayout::on_collator_payout( - paid_for_round, - collator, - amt_due, - )); + .saturating_add(T::OnCollatorPayout::on_collator_payout(paid_for_round, collator, amt_due)); log::warn!("💵 Solo collator reward: {:?}", amt_due); } else { // pay collator first; commission + due_portion @@ -1649,8 +1581,7 @@ pub mod pallet { ( RewardPayment::Paid, - T::WeightInfo::pay_one_collator_reward(num_delegators as u32) - .saturating_add(extra_weight), + T::WeightInfo::pay_one_collator_reward(num_delegators as u32).saturating_add(extra_weight), ) } else { // Note that we don't clean up storage here; it is cleaned up in @@ -1682,11 +1613,7 @@ pub mod pallet { a.amount.cmp(&b.amount).then_with(|| a.owner.cmp(&b.owner)).reverse() }); - let mut collators = candidates - .into_iter() - .take(top_n) - .map(|x| x.owner) - .collect::>(); + let mut collators = candidates.into_iter().take(top_n).map(|x| x.owner).collect::>(); // Sort collators by AccountId collators.sort(); @@ -1698,11 +1625,11 @@ pub mod pallet { candidates.into_iter().map(|x| x.owner).collect::>() } } + /// Best as in most cumulatively supported in terms of stake /// Returns [collator_count, delegation_count, total staked] pub(crate) fn select_top_candidates(now: RoundIndex) -> (Weight, u32, u32, BalanceOf) { - let (mut collator_count, mut delegation_count, mut total) = - (0u32, 0u32, BalanceOf::::zero()); + let (mut collator_count, mut delegation_count, mut total) = (0u32, 0u32, BalanceOf::::zero()); // choose the top TotalSelected qualified candidates, ordered by stake let collators = Self::compute_top_candidates(); if collators.is_empty() { @@ -1712,8 +1639,7 @@ pub mod pallet { // set this round AtStake to last round AtStake for (account, snapshot) in >::iter_prefix(last_round) { collator_count = collator_count.saturating_add(1u32); - delegation_count = - delegation_count.saturating_add(snapshot.delegations.len() as u32); + delegation_count = delegation_count.saturating_add(snapshot.delegations.len() as u32); total = total.saturating_add(snapshot.total); total_per_candidate.insert(account.clone(), snapshot.total); >::insert(now, account, snapshot); @@ -1721,9 +1647,8 @@ pub mod pallet { // `SelectedCandidates` remains unchanged from last round // emit CollatorChosen event for tools that use this event for candidate in >::get() { - let snapshot_total = total_per_candidate - .get(&candidate) - .expect("all selected candidates have snapshots"); + let snapshot_total = + total_per_candidate.get(&candidate).expect("all selected candidates have snapshots"); Self::deposit_event(Event::CollatorChosen { round: now, collator_account: candidate, @@ -1736,8 +1661,7 @@ pub mod pallet { // snapshot exposure for round for weighting reward distribution for account in collators.iter() { - let state = >::get(account) - .expect("all members of CandidateQ must be candidates"); + let state = >::get(account).expect("all members of CandidateQ must be candidates"); collator_count = collator_count.saturating_add(1u32); delegation_count = delegation_count.saturating_add(state.delegation_count); @@ -1762,11 +1686,8 @@ pub mod pallet { }) .collect(); - let snapshot = CollatorSnapshot { - bond: state.bond, - delegations: rewardable_delegations, - total: total_counted, - }; + let snapshot = + CollatorSnapshot { bond: state.bond, delegations: rewardable_delegations, total: total_counted }; >::insert(now, account, snapshot); Self::deposit_event(Event::CollatorChosen { round: now, @@ -1841,10 +1762,7 @@ pub mod pallet { /// Mint a specified reward amount to the beneficiary account. Emits the [Rewarded] event. pub fn mint(amt: BalanceOf, to: T::AccountId) { if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&to, amt) { - Self::deposit_event(Event::Rewarded { - account: to.clone(), - rewards: amount_transferred.peek(), - }); + Self::deposit_event(Event::Rewarded { account: to.clone(), rewards: amount_transferred.peek() }); } } @@ -1875,36 +1793,27 @@ pub mod pallet { ) -> Weight { let mut weight = T::WeightInfo::mint_collator_reward(); if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&delegator, amt) { - Self::deposit_event(Event::Rewarded { - account: delegator.clone(), - rewards: amount_transferred.peek(), - }); + Self::deposit_event(Event::Rewarded { account: delegator.clone(), rewards: amount_transferred.peek() }); let compound_amount = compound_percent.mul_ceil(amount_transferred.peek()); if compound_amount.is_zero() { return weight } - if let Err(err) = Self::delegation_bond_more_without_event( - delegator.clone(), - candidate.clone(), - compound_amount, - ) { + if let Err(err) = + Self::delegation_bond_more_without_event(delegator.clone(), candidate.clone(), compound_amount) + { log::warn!( - "skipped compounding staking reward towards candidate '{:?}' for delegator '{:?}': {:?}", - candidate, - delegator, - err - ); + "skipped compounding staking reward towards candidate '{:?}' for delegator '{:?}': {:?}", + candidate, + delegator, + err + ); return weight }; weight = weight.saturating_add(T::WeightInfo::delegator_bond_more()); - Pallet::::deposit_event(Event::Compounded { - delegator, - candidate, - amount: compound_amount, - }); + Pallet::::deposit_event(Event::Compounded { delegator, candidate, amount: compound_amount }); }; weight @@ -1996,9 +1905,7 @@ pub mod pallet { ) } - fn estimate_next_session_rotation( - _now: T::BlockNumber, - ) -> (Option, Weight) { + fn estimate_next_session_rotation(_now: T::BlockNumber) -> (Option, Weight) { let round = >::get(); ( diff --git a/pallets/parachain-staking/src/mock.rs b/pallets/parachain-staking/src/mock.rs index 09f6906fc..563bceb6f 100644 --- a/pallets/parachain-staking/src/mock.rs +++ b/pallets/parachain-staking/src/mock.rs @@ -17,8 +17,8 @@ //! Test utilities use crate as pallet_parachain_staking; use crate::{ - pallet, AwardedPts, Config, Event as ParachainStakingEvent, InflationInfo, Points, Range, - COLLATOR_LOCK_ID, DELEGATOR_LOCK_ID, + pallet, AwardedPts, Config, Event as ParachainStakingEvent, InflationInfo, Points, Range, COLLATOR_LOCK_ID, + DELEGATOR_LOCK_ID, }; use frame_support::{ construct_runtime, parameter_types, @@ -63,48 +63,48 @@ parameter_types! { pub const SS58Prefix: u8 = 42; } impl frame_system::Config for Test { + type AccountData = pallet_balances::AccountData; + type AccountId = AccountId; type BaseCallFilter = Everything; - type DbWeight = RocksDbWeight; - type RuntimeOrigin = RuntimeOrigin; - type Index = u64; + type BlockHashCount = BlockHashCount; + type BlockLength = (); type BlockNumber = BlockNumber; - type RuntimeCall = RuntimeCall; + type BlockWeights = (); + type DbWeight = RocksDbWeight; type Hash = H256; type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; type Header = sp_runtime::generic::Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); + type Index = u64; + type Lookup = IdentityLookup; + type MaxConsumers = frame_support::traits::ConstU32<16>; type OnKilledAccount = (); - type SystemWeightInfo = (); - type BlockWeights = (); - type BlockLength = (); - type SS58Prefix = SS58Prefix; + type OnNewAccount = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type PalletInfo = PalletInfo; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type SS58Prefix = SS58Prefix; + type SystemWeightInfo = (); + type Version = (); } parameter_types! { pub const ExistentialDeposit: u128 = 1; } impl pallet_balances::Config for Test { - type MaxReserves = (); - type ReserveIdentifier = [u8; 4]; - type MaxLocks = (); + type AccountStore = System; type Balance = Balance; - type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); - type HoldIdentifier = (); type FreezeIdentifier = (); - type MaxHolds = (); + type HoldIdentifier = (); type MaxFreezes = (); + type MaxHolds = (); + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 4]; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); } parameter_types! { #[derive(Debug, Eq, PartialEq)] @@ -118,17 +118,17 @@ impl pallet_aura::Config for Test { } impl pallet_authorship::Config for Test { - type FindAuthor = pallet_session::FindAccountFromAuthorIndex; type EventHandler = ParachainStaking; + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; } parameter_types! { pub const MinimumPeriod: u64 = 1; } impl pallet_timestamp::Config for Test { + type MinimumPeriod = MinimumPeriod; type Moment = u64; type OnTimestampSet = Aura; - type MinimumPeriod = MinimumPeriod; type WeightInfo = (); } @@ -167,37 +167,37 @@ use sp_runtime::{ }; impl pallet_session::Config for Test { + type Keys = MockSessionKeys; + type NextSessionRotation = ParachainStaking; type RuntimeEvent = RuntimeEvent; + type SessionHandler = ::KeyTypeIdProviders; + type SessionManager = ParachainStaking; + type ShouldEndSession = ParachainStaking; type ValidatorId = AccountId; type ValidatorIdOf = ConvertInto; - type ShouldEndSession = ParachainStaking; - type NextSessionRotation = ParachainStaking; - type SessionManager = ParachainStaking; - type SessionHandler = ::KeyTypeIdProviders; - type Keys = MockSessionKeys; type WeightInfo = (); } impl Config for Test { - type RuntimeEvent = RuntimeEvent; + type CandidateBondLessDelay = CandidateBondLessDelay; type Currency = Balances; - type MonetaryGovernanceOrigin = frame_system::EnsureRoot; - type MinBlocksPerRound = MinBlocksPerRound; + type DelegationBondLessDelay = DelegationBondLessDelay; type LeaveCandidatesDelay = LeaveCandidatesDelay; - type CandidateBondLessDelay = CandidateBondLessDelay; type LeaveDelegatorsDelay = LeaveDelegatorsDelay; - type RevokeDelegationDelay = RevokeDelegationDelay; - type DelegationBondLessDelay = DelegationBondLessDelay; - type RewardPaymentDelay = RewardPaymentDelay; - type MinSelectedCandidates = MinSelectedCandidates; - type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate; type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator; + type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; + type MinBlocksPerRound = MinBlocksPerRound; type MinCandidateStk = MinCandidateStk; - type MinDelegatorStk = MinDelegatorStk; type MinDelegation = MinDelegation; + type MinDelegatorStk = MinDelegatorStk; + type MinSelectedCandidates = MinSelectedCandidates; + type MonetaryGovernanceOrigin = frame_system::EnsureRoot; type OnCollatorPayout = (); - type PayoutCollatorReward = (); type OnNewRound = (); + type PayoutCollatorReward = (); + type RevokeDelegationDelay = RevokeDelegationDelay; + type RewardPaymentDelay = RewardPaymentDelay; + type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } @@ -248,12 +248,8 @@ impl ExtBuilder { self } - pub(crate) fn with_delegations( - mut self, - delegations: Vec<(AccountId, AccountId, Balance)>, - ) -> Self { - self.delegations = - delegations.into_iter().map(|d| (d.0, d.1, d.2, Percent::zero())).collect(); + pub(crate) fn with_delegations(mut self, delegations: Vec<(AccountId, AccountId, Balance)>) -> Self { + self.delegations = delegations.into_iter().map(|d| (d.0, d.1, d.2, Percent::zero())).collect(); self } @@ -348,15 +344,7 @@ pub(crate) fn events() -> Vec> { System::events() .into_iter() .map(|r| r.event) - .filter_map( - |e| { - if let RuntimeEvent::ParachainStaking(inner) = e { - Some(inner) - } else { - None - } - }, - ) + .filter_map(|e| if let RuntimeEvent::ParachainStaking(inner) = e { Some(inner) } else { None }) .collect::>() } @@ -573,17 +561,7 @@ pub(crate) fn query_lock_amount(account_id: u64, id: LockIdentifier) -> Option::NoWritingSameValue ); }); @@ -256,33 +244,29 @@ fn cannot_set_blocks_per_round_to_current_blocks_per_round() { #[test] fn round_immediately_jumps_if_current_duration_exceeds_new_blocks_per_round() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // we can't lower the blocks per round because it must be above the number of collators, - // and we can't lower the number of collators because it must be above - // MinSelectedCandidates. so we first raise blocks per round, then lower it. - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); + ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { + // we can't lower the blocks per round because it must be above the number of collators, + // and we can't lower the number of collators because it must be above + // MinSelectedCandidates. so we first raise blocks per round, then lower it. + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); - roll_to(10); - assert_events_emitted!(Event::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 20 - },); - roll_to(17); - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); - roll_to(18); - assert_events_emitted!(Event::NewRound { - starting_block: 18, - round: 3, - selected_collators_number: 1, - total_balance: 20 - }); + roll_to(10); + assert_events_emitted!(Event::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 20 + },); + roll_to(17); + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); + roll_to(18); + assert_events_emitted!(Event::NewRound { + starting_block: 18, + round: 3, + selected_collators_number: 1, + total_balance: 20 }); + }); } // ~~ MONETARY GOVERNANCE ~~ @@ -300,22 +284,14 @@ fn invalid_monetary_origin_fails() { assert_noop!( ParachainStaking::set_inflation( RuntimeOrigin::signed(45), - Range { - min: Perbill::from_percent(3), - ideal: Perbill::from_percent(4), - max: Perbill::from_percent(5) - } + Range { min: Perbill::from_percent(3), ideal: Perbill::from_percent(4), max: Perbill::from_percent(5) } ), sp_runtime::DispatchError::BadOrigin ); assert_noop!( ParachainStaking::set_inflation( RuntimeOrigin::signed(45), - Range { - min: Perbill::from_percent(3), - ideal: Perbill::from_percent(4), - max: Perbill::from_percent(5) - } + Range { min: Perbill::from_percent(3), ideal: Perbill::from_percent(4), max: Perbill::from_percent(5) } ), sp_runtime::DispatchError::BadOrigin ); @@ -324,10 +300,7 @@ fn invalid_monetary_origin_fails() { sp_runtime::DispatchError::BadOrigin ); assert_noop!( - ParachainStaking::set_parachain_bond_reserve_percent( - RuntimeOrigin::signed(45), - Percent::from_percent(2) - ), + ParachainStaking::set_parachain_bond_reserve_percent(RuntimeOrigin::signed(45), Percent::from_percent(2)), sp_runtime::DispatchError::BadOrigin ); }); @@ -343,29 +316,19 @@ fn set_staking_event_emits_event_correctly() { RuntimeOrigin::root(), Range { min: 3u128, ideal: 4u128, max: 5u128 } )); - assert_events_eq!(Event::StakeExpectationsSet { - expect_min: 3u128, - expect_ideal: 4u128, - expect_max: 5u128, - }); + assert_events_eq!(Event::StakeExpectationsSet { expect_min: 3u128, expect_ideal: 4u128, expect_max: 5u128 }); }); } #[test] fn set_staking_updates_storage_correctly() { ExtBuilder::default().build().execute_with(|| { - assert_eq!( - ParachainStaking::inflation_config().expect, - Range { min: 700, ideal: 700, max: 700 } - ); + assert_eq!(ParachainStaking::inflation_config().expect, Range { min: 700, ideal: 700, max: 700 }); assert_ok!(ParachainStaking::set_staking_expectations( RuntimeOrigin::root(), Range { min: 3u128, ideal: 4u128, max: 5u128 } )); - assert_eq!( - ParachainStaking::inflation_config().expect, - Range { min: 3u128, ideal: 4u128, max: 5u128 } - ); + assert_eq!(ParachainStaking::inflation_config().expect, Range { min: 3u128, ideal: 4u128, max: 5u128 }); }); } @@ -407,10 +370,7 @@ fn set_inflation_event_emits_correctly() { ExtBuilder::default().build().execute_with(|| { let (min, ideal, max): (Perbill, Perbill, Perbill) = (Perbill::from_percent(3), Perbill::from_percent(4), Perbill::from_percent(5)); - assert_ok!(ParachainStaking::set_inflation( - RuntimeOrigin::root(), - Range { min, ideal, max } - )); + assert_ok!(ParachainStaking::set_inflation(RuntimeOrigin::root(), Range { min, ideal, max })); assert_events_eq!(Event::InflationSet { annual_min: min, annual_ideal: ideal, @@ -429,32 +389,17 @@ fn set_inflation_storage_updates_correctly() { (Perbill::from_percent(3), Perbill::from_percent(4), Perbill::from_percent(5)); assert_eq!( ParachainStaking::inflation_config().annual, - Range { - min: Perbill::from_percent(50), - ideal: Perbill::from_percent(50), - max: Perbill::from_percent(50) - } + Range { min: Perbill::from_percent(50), ideal: Perbill::from_percent(50), max: Perbill::from_percent(50) } ); assert_eq!( ParachainStaking::inflation_config().round, - Range { - min: Perbill::from_percent(5), - ideal: Perbill::from_percent(5), - max: Perbill::from_percent(5) - } + Range { min: Perbill::from_percent(5), ideal: Perbill::from_percent(5), max: Perbill::from_percent(5) } ); - assert_ok!(ParachainStaking::set_inflation( - RuntimeOrigin::root(), - Range { min, ideal, max } - ),); + assert_ok!(ParachainStaking::set_inflation(RuntimeOrigin::root(), Range { min, ideal, max }),); assert_eq!(ParachainStaking::inflation_config().annual, Range { min, ideal, max }); assert_eq!( ParachainStaking::inflation_config().round, - Range { - min: Perbill::from_parts(57), - ideal: Perbill::from_parts(75), - max: Perbill::from_parts(93) - } + Range { min: Perbill::from_parts(57), ideal: Perbill::from_parts(75), max: Perbill::from_parts(93) } ); }); } @@ -465,11 +410,7 @@ fn cannot_set_invalid_inflation() { assert_noop!( ParachainStaking::set_inflation( RuntimeOrigin::root(), - Range { - min: Perbill::from_percent(5), - ideal: Perbill::from_percent(4), - max: Perbill::from_percent(3) - } + Range { min: Perbill::from_percent(5), ideal: Perbill::from_percent(4), max: Perbill::from_percent(3) } ), Error::::InvalidSchedule ); @@ -481,10 +422,7 @@ fn cannot_set_same_inflation() { ExtBuilder::default().build().execute_with(|| { let (min, ideal, max): (Perbill, Perbill, Perbill) = (Perbill::from_percent(3), Perbill::from_percent(4), Perbill::from_percent(5)); - assert_ok!(ParachainStaking::set_inflation( - RuntimeOrigin::root(), - Range { min, ideal, max } - ),); + assert_ok!(ParachainStaking::set_inflation(RuntimeOrigin::root(), Range { min, ideal, max }),); assert_noop!( ParachainStaking::set_inflation(RuntimeOrigin::root(), Range { min, ideal, max }), Error::::NoWritingSameValue @@ -543,10 +481,7 @@ fn set_parachain_bond_reserve_percent_storage_updates_correctly() { fn cannot_set_same_parachain_bond_reserve_percent() { ExtBuilder::default().build().execute_with(|| { assert_noop!( - ParachainStaking::set_parachain_bond_reserve_percent( - RuntimeOrigin::root(), - Percent::from_percent(30) - ), + ParachainStaking::set_parachain_bond_reserve_percent(RuntimeOrigin::root(), Percent::from_percent(30)), Error::::NoWritingSameValue ); }); @@ -609,16 +544,12 @@ fn join_candidates_adds_to_candidate_pool() { #[test] fn cannot_join_candidates_if_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_candidates(vec![(1, 500)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 11u128, 100u32), - Error::::CandidateExists - ); - }); + ExtBuilder::default().with_balances(vec![(1, 1000)]).with_candidates(vec![(1, 500)]).build().execute_with(|| { + assert_noop!( + ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 11u128, 100u32), + Error::::CandidateExists + ); + }); } #[test] @@ -675,17 +606,7 @@ fn insufficient_join_candidates_weight_hint_fails() { #[test] fn sufficient_join_candidates_weight_hint_succeeds() { ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 20), - (3, 20), - (4, 20), - (5, 20), - (6, 20), - (7, 20), - (8, 20), - (9, 20), - ]) + .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20), (7, 20), (8, 20), (9, 20)]) .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) .build() .execute_with(|| { @@ -701,31 +622,19 @@ fn sufficient_join_candidates_weight_hint_succeeds() { #[test] fn leave_candidates_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_events_eq!(Event::CandidateScheduledExit { - exit_allowed_round: 1, - candidate: 1, - scheduled_exit: 3 - }); - }); + ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_events_eq!(Event::CandidateScheduledExit { exit_allowed_round: 1, candidate: 1, scheduled_exit: 3 }); + }); } #[test] fn leave_candidates_removes_candidate_from_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert!(ParachainStaking::candidate_pool().0.is_empty()); - }); + ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert!(ParachainStaking::candidate_pool().0.is_empty()); + }); } #[test] @@ -740,17 +649,13 @@ fn cannot_leave_candidates_if_not_candidate() { #[test] fn cannot_leave_candidates_if_already_leaving_candidates() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_noop!( - ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32), - Error::::CandidateAlreadyLeaving - ); - }); + ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_noop!( + ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32), + Error::::CandidateAlreadyLeaving + ); + }); } #[test] @@ -778,10 +683,7 @@ fn sufficient_leave_candidates_weight_hint_succeeds() { .execute_with(|| { let mut count = 5u32; for i in 1..6 { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(i), - count - )); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(i), count)); count -= 1u32; } }); @@ -791,33 +693,21 @@ fn sufficient_leave_candidates_weight_hint_succeeds() { #[test] fn execute_leave_candidates_emits_event() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert_events_emitted!(Event::CandidateLeft { - ex_candidate: 1, - unlocked_amount: 10, - new_total_amt_locked: 0 - }); - }); + ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert_events_emitted!(Event::CandidateLeft { ex_candidate: 1, unlocked_amount: 10, new_total_amt_locked: 0 }); + }); } #[test] fn execute_leave_candidates_callable_by_any_signed() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 1, 0)); - }); + ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 1, 0)); + }); } #[test] @@ -842,50 +732,37 @@ fn execute_leave_candidates_requires_correct_weight_hint() { #[test] fn execute_leave_candidates_unreserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); - }); + ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); + }); } #[test] fn execute_leave_candidates_decreases_total_staked() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 10); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert_eq!(ParachainStaking::total(), 0); - }); + ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { + assert_eq!(ParachainStaking::total(), 10); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert_eq!(ParachainStaking::total(), 0); + }); } #[test] fn execute_leave_candidates_removes_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - // candidate state is not immediately removed - let candidate_state = - ParachainStaking::candidate_info(1).expect("just left => still exists"); - assert_eq!(candidate_state.bond, 10u128); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert!(ParachainStaking::candidate_info(1).is_none()); - }); + ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + // candidate state is not immediately removed + let candidate_state = ParachainStaking::candidate_info(1).expect("just left => still exists"); + assert_eq!(candidate_state.bond, 10u128); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert!(ParachainStaking::candidate_info(1).is_none()); + }); } #[test] @@ -896,371 +773,248 @@ fn execute_leave_candidates_removes_pending_delegation_requests() { .with_delegations(vec![(2, 1, 15)]) .build() .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); let state = ParachainStaking::delegation_scheduled_requests(&1); assert_eq!( state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], + vec![ScheduledRequest { delegator: 2, when_executable: 3, action: DelegationAction::Decrease(5) }], ); assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); // candidate state is not immediately removed - let candidate_state = - ParachainStaking::candidate_info(1).expect("just left => still exists"); + let candidate_state = ParachainStaking::candidate_info(1).expect("just left => still exists"); assert_eq!(candidate_state.bond, 10u128); roll_to(10); assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 1)); assert!(ParachainStaking::candidate_info(1).is_none()); assert!( - !ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2), + !ParachainStaking::delegation_scheduled_requests(&1).iter().any(|x| x.delegator == 2), "delegation request not removed" ); - assert!( - !>::contains_key(&1), - "the key was not removed from storage" - ); + assert!(!>::contains_key(&1), "the key was not removed from storage"); }); } #[test] fn cannot_execute_leave_candidates_before_delay() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_noop!( - ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), - Error::::CandidateCannotLeaveYet - ); - roll_to(9); - assert_noop!( - ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), - Error::::CandidateCannotLeaveYet - ); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0)); - }); + ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_noop!( + ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), + Error::::CandidateCannotLeaveYet + ); + roll_to(9); + assert_noop!( + ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), + Error::::CandidateCannotLeaveYet + ); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0)); + }); } // CANCEL LEAVE CANDIDATES #[test] fn cancel_leave_candidates_emits_event() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_events_emitted!(Event::CancelledCandidateExit { candidate: 1 }); - }); + ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_events_emitted!(Event::CancelledCandidateExit { candidate: 1 }); + }); } #[test] fn cancel_leave_candidates_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); - let candidate = - ParachainStaking::candidate_info(&1).expect("just cancelled leave so exists"); - assert!(candidate.is_active()); - }); + ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); + let candidate = ParachainStaking::candidate_info(&1).expect("just cancelled leave so exists"); + assert!(candidate.is_active()); + }); } #[test] fn cancel_leave_candidates_adds_to_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 10); - }); + ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 10); + }); } // GO OFFLINE #[test] fn go_offline_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert_events_eq!(Event::CandidateWentOffline { candidate: 1 }); - }); + ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert_events_eq!(Event::CandidateWentOffline { candidate: 1 }); + }); } #[test] fn go_offline_removes_candidate_from_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert!(ParachainStaking::candidate_pool().0.is_empty()); - }); + ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert!(ParachainStaking::candidate_pool().0.is_empty()); + }); } #[test] fn go_offline_updates_candidate_state_to_idle() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - let candidate_state = ParachainStaking::candidate_info(1).expect("is active candidate"); - assert_eq!(candidate_state.status, CollatorStatus::Active); - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - let candidate_state = - ParachainStaking::candidate_info(1).expect("is candidate, just offline"); - assert_eq!(candidate_state.status, CollatorStatus::Idle); - }); + ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { + let candidate_state = ParachainStaking::candidate_info(1).expect("is active candidate"); + assert_eq!(candidate_state.status, CollatorStatus::Active); + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + let candidate_state = ParachainStaking::candidate_info(1).expect("is candidate, just offline"); + assert_eq!(candidate_state.status, CollatorStatus::Idle); + }); } #[test] fn cannot_go_offline_if_not_candidate() { ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::go_offline(RuntimeOrigin::signed(3)), - Error::::CandidateDNE - ); + assert_noop!(ParachainStaking::go_offline(RuntimeOrigin::signed(3)), Error::::CandidateDNE); }); } #[test] fn cannot_go_offline_if_already_offline() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert_noop!( - ParachainStaking::go_offline(RuntimeOrigin::signed(1)), - Error::::AlreadyOffline - ); - }); + ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert_noop!(ParachainStaking::go_offline(RuntimeOrigin::signed(1)), Error::::AlreadyOffline); + }); } // GO ONLINE #[test] fn go_online_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - roll_blocks(1); - assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); - assert_events_eq!(Event::CandidateBackOnline { candidate: 1 }); - }); + ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + roll_blocks(1); + assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); + assert_events_eq!(Event::CandidateBackOnline { candidate: 1 }); + }); } #[test] fn go_online_adds_to_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert!(ParachainStaking::candidate_pool().0.is_empty()); - assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); - }); + ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert!(ParachainStaking::candidate_pool().0.is_empty()); + assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); + }); } #[test] fn go_online_storage_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - let candidate_state = - ParachainStaking::candidate_info(1).expect("offline still exists"); - assert_eq!(candidate_state.status, CollatorStatus::Idle); - assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); - let candidate_state = ParachainStaking::candidate_info(1).expect("online so exists"); - assert_eq!(candidate_state.status, CollatorStatus::Active); - }); + ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + let candidate_state = ParachainStaking::candidate_info(1).expect("offline still exists"); + assert_eq!(candidate_state.status, CollatorStatus::Idle); + assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); + let candidate_state = ParachainStaking::candidate_info(1).expect("online so exists"); + assert_eq!(candidate_state.status, CollatorStatus::Active); + }); } #[test] fn cannot_go_online_if_not_candidate() { ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::go_online(RuntimeOrigin::signed(3)), - Error::::CandidateDNE - ); + assert_noop!(ParachainStaking::go_online(RuntimeOrigin::signed(3)), Error::::CandidateDNE); }); } #[test] fn cannot_go_online_if_already_online() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::go_online(RuntimeOrigin::signed(1)), - Error::::AlreadyActive - ); - }); + ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { + assert_noop!(ParachainStaking::go_online(RuntimeOrigin::signed(1)), Error::::AlreadyActive); + }); } #[test] fn cannot_go_online_if_leaving() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_noop!( - ParachainStaking::go_online(RuntimeOrigin::signed(1)), - Error::::CannotGoOnlineIfLeaving - ); - }); + ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_noop!(ParachainStaking::go_online(RuntimeOrigin::signed(1)), Error::::CannotGoOnlineIfLeaving); + }); } // CANDIDATE BOND MORE #[test] fn candidate_bond_more_emits_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - assert_events_eq!(Event::CandidateBondedMore { - candidate: 1, - amount: 30, - new_total_bond: 50 - }); - }); + ExtBuilder::default().with_balances(vec![(1, 50)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + assert_events_eq!(Event::CandidateBondedMore { candidate: 1, amount: 30, new_total_bond: 50 }); + }); } #[test] -fn candidate_bond_more_reserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 30); - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); - }); +fn candidate_bond_more_reserves_balance() { + ExtBuilder::default().with_balances(vec![(1, 50)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 30); + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); + }); } #[test] fn candidate_bond_more_increases_total() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - let mut total = ParachainStaking::total(); - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - total += 30; - assert_eq!(ParachainStaking::total(), total); - }); + ExtBuilder::default().with_balances(vec![(1, 50)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { + let mut total = ParachainStaking::total(); + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + total += 30; + assert_eq!(ParachainStaking::total(), total); + }); } #[test] fn candidate_bond_more_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 20); - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 50); - }); + ExtBuilder::default().with_balances(vec![(1, 50)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 20); + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 50); + }); } #[test] fn candidate_bond_more_updates_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 50); - }); + ExtBuilder::default().with_balances(vec![(1, 50)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 50); + }); } // SCHEDULE CANDIDATE BOND LESS #[test] fn schedule_candidate_bond_less_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - assert_events_eq!(Event::CandidateBondLessRequested { - candidate: 1, - amount_to_decrease: 10, - execute_round: 3, - }); - }); + ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10)); + assert_events_eq!(Event::CandidateBondLessRequested { candidate: 1, amount_to_decrease: 10, execute_round: 3 }); + }); } #[test] fn cannot_schedule_candidate_bond_less_if_request_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 5)); - assert_noop!( - ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 5), - Error::::PendingCandidateRequestAlreadyExists - ); - }); + ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 5)); + assert_noop!( + ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 5), + Error::::PendingCandidateRequestAlreadyExists + ); + }); } #[test] @@ -1275,216 +1029,134 @@ fn cannot_schedule_candidate_bond_less_if_not_candidate() { #[test] fn cannot_schedule_candidate_bond_less_if_new_total_below_min_candidate_stk() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 21), - Error::::CandidateBondBelowMin - ); - }); + ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { + assert_noop!( + ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 21), + Error::::CandidateBondBelowMin + ); + }); } #[test] fn can_schedule_candidate_bond_less_if_leaving_candidates() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - }); + ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10)); + }); } #[test] fn cannot_schedule_candidate_bond_less_if_exited_candidates() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert_noop!( - ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10), - Error::::CandidateDNE - ); - }); + ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert_noop!( + ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10), + Error::::CandidateDNE + ); + }); } // 2. EXECUTE BOND LESS REQUEST #[test] fn execute_candidate_bond_less_emits_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 50)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 30 - )); - roll_to(10); - roll_blocks(1); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - assert_events_eq!(Event::CandidateBondedLess { - candidate: 1, - amount: 30, - new_bond: 20 - }); - }); + ExtBuilder::default().with_balances(vec![(1, 50)]).with_candidates(vec![(1, 50)]).build().execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 30)); + roll_to(10); + roll_blocks(1); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + assert_events_eq!(Event::CandidateBondedLess { candidate: 1, amount: 30, new_bond: 20 }); + }); } #[test] fn execute_candidate_bond_less_unreserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); - }); + ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); + assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10)); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); + }); } #[test] fn execute_candidate_bond_less_decreases_total() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - let mut total = ParachainStaking::total(); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - total -= 10; - assert_eq!(ParachainStaking::total(), total); - }); + ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { + let mut total = ParachainStaking::total(); + assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10)); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + total -= 10; + assert_eq!(ParachainStaking::total(), total); + }); } #[test] fn execute_candidate_bond_less_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 30); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 20); - }); + ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 30); + assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10)); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 20); + }); } #[test] fn execute_candidate_bond_less_updates_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 30); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); - }); + ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 30); + assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10)); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); + }); } // CANCEL CANDIDATE BOND LESS REQUEST #[test] fn cancel_candidate_bond_less_emits_event() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - assert_ok!(ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(1))); - assert_events_emitted!(Event::CancelledCandidateBondLess { - candidate: 1, - amount: 10, - execute_round: 3, - }); - }); + ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10)); + assert_ok!(ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(1))); + assert_events_emitted!(Event::CancelledCandidateBondLess { candidate: 1, amount: 10, execute_round: 3 }); + }); } #[test] fn cancel_candidate_bond_less_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - assert_ok!(ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(1))); - assert!(ParachainStaking::candidate_info(&1).unwrap().request.is_none()); - }); + ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10)); + assert_ok!(ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(1))); + assert!(ParachainStaking::candidate_info(&1).unwrap().request.is_none()); + }); } #[test] fn only_candidate_can_cancel_candidate_bond_less_request() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - assert_noop!( - ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(2)), - Error::::CandidateDNE - ); - }); + ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10)); + assert_noop!( + ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(2)), + Error::::CandidateDNE + ); + }); } // DELEGATE #[test] fn delegate_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { + ExtBuilder::default().with_balances(vec![(1, 30), (2, 10)]).with_candidates(vec![(1, 30)]).build().execute_with( + || { assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); assert_events_eq!(Event::Delegation { delegator: 2, @@ -1493,74 +1165,61 @@ fn delegate_event_emits_correctly() { delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, auto_compound: Percent::zero(), }); - }); + }, + ); } #[test] fn delegate_reserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { + ExtBuilder::default().with_balances(vec![(1, 30), (2, 10)]).with_candidates(vec![(1, 30)]).build().execute_with( + || { assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - }); + }, + ); } #[test] fn delegate_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { + ExtBuilder::default().with_balances(vec![(1, 30), (2, 10)]).with_candidates(vec![(1, 30)]).build().execute_with( + || { assert!(ParachainStaking::delegator_state(2).is_none()); assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); - let delegator_state = - ParachainStaking::delegator_state(2).expect("just delegated => exists"); + let delegator_state = ParachainStaking::delegator_state(2).expect("just delegated => exists"); assert_eq!(delegator_state.total(), 10); assert_eq!(delegator_state.delegations.0[0].owner, 1); assert_eq!(delegator_state.delegations.0[0].amount, 10); - }); + }, + ); } #[test] fn delegate_updates_collator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - let candidate_state = - ParachainStaking::candidate_info(1).expect("registered in genesis"); + ExtBuilder::default().with_balances(vec![(1, 30), (2, 10)]).with_candidates(vec![(1, 30)]).build().execute_with( + || { + let candidate_state = ParachainStaking::candidate_info(1).expect("registered in genesis"); assert_eq!(candidate_state.total_counted, 30); - let top_delegations = - ParachainStaking::top_delegations(1).expect("registered in genesis"); + let top_delegations = ParachainStaking::top_delegations(1).expect("registered in genesis"); assert!(top_delegations.delegations.is_empty()); assert!(top_delegations.total.is_zero()); assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); - let candidate_state = - ParachainStaking::candidate_info(1).expect("just delegated => exists"); + let candidate_state = ParachainStaking::candidate_info(1).expect("just delegated => exists"); assert_eq!(candidate_state.total_counted, 40); - let top_delegations = - ParachainStaking::top_delegations(1).expect("just delegated => exists"); + let top_delegations = ParachainStaking::top_delegations(1).expect("just delegated => exists"); assert_eq!(top_delegations.delegations[0].owner, 2); assert_eq!(top_delegations.delegations[0].amount, 10); assert_eq!(top_delegations.total, 10); - }); + }, + ); } #[test] fn can_delegate_immediately_after_other_join_candidates() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 20, 0)); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 20, 0, 0)); - }); + ExtBuilder::default().with_balances(vec![(1, 20), (2, 20)]).build().execute_with(|| { + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 20, 0)); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 20, 0, 0)); + }); } #[test] @@ -1642,11 +1301,7 @@ fn can_delegate_if_full_and_new_delegation_greater_than_lowest_bottom() { .build() .execute_with(|| { assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(11), 1, 11, 8, 0)); - assert_events_emitted!(Event::DelegationKicked { - delegator: 10, - candidate: 1, - unstaked_amount: 10 - }); + assert_events_emitted!(Event::DelegationKicked { delegator: 10, candidate: 1, unstaked_amount: 10 }); assert_events_emitted!(Event::DelegatorLeft { delegator: 10, unstaked_amount: 10 }); }); } @@ -1711,42 +1366,19 @@ fn cannot_delegate_more_than_max_delegations() { #[test] fn sufficient_delegate_weight_hint_succeeds() { ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 20), - (3, 20), - (4, 20), - (5, 20), - (6, 20), - (7, 20), - (8, 20), - (9, 20), - (10, 20), - ]) + .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20), (7, 20), (8, 20), (9, 20), (10, 20)]) .with_candidates(vec![(1, 20), (2, 20)]) .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) .build() .execute_with(|| { let mut count = 4u32; for i in 7..11 { - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(i), - 1, - 10, - count, - 0u32 - )); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(i), 1, 10, count, 0u32)); count += 1u32; } let mut count = 0u32; for i in 3..11 { - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(i), - 2, - 10, - count, - 1u32 - )); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(i), 2, 10, count, 1u32)); count += 1u32; } }); @@ -1755,18 +1387,7 @@ fn sufficient_delegate_weight_hint_succeeds() { #[test] fn insufficient_delegate_weight_hint_fails() { ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 20), - (3, 20), - (4, 20), - (5, 20), - (6, 20), - (7, 20), - (8, 20), - (9, 20), - (10, 20), - ]) + .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20), (7, 20), (8, 20), (9, 20), (10, 20)]) .with_candidates(vec![(1, 20), (2, 20)]) .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) .build() @@ -1781,13 +1402,7 @@ fn insufficient_delegate_weight_hint_fails() { // to set up for next error test count = 4u32; for i in 7..11 { - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(i), - 1, - 10, - count, - 0u32 - )); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(i), 1, 10, count, 0u32)); count += 1u32; } count = 0u32; @@ -1812,11 +1427,7 @@ fn schedule_leave_delegators_event_emits_correctly() { .build() .execute_with(|| { assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 1, - delegator: 2, - scheduled_exit: 3 - }); + assert_events_eq!(Event::DelegatorExitScheduled { round: 1, delegator: 2, scheduled_exit: 3 }); }); } @@ -1838,16 +1449,14 @@ fn cannot_schedule_leave_delegators_if_already_leaving() { #[test] fn cannot_schedule_leave_delegators_if_not_delegator() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { + ExtBuilder::default().with_balances(vec![(1, 30), (2, 10)]).with_candidates(vec![(1, 30)]).build().execute_with( + || { assert_noop!( ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2)), Error::::DelegatorDNE ); - }); + }, + ); } // EXECUTE LEAVE DELEGATORS @@ -1924,28 +1533,18 @@ fn execute_leave_delegators_removes_pending_delegation_requests() { .with_delegations(vec![(2, 1, 15)]) .build() .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); let state = ParachainStaking::delegation_scheduled_requests(&1); assert_eq!( state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], + vec![ScheduledRequest { delegator: 2, when_executable: 3, action: DelegationAction::Decrease(5) }], ); assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); roll_to(10); assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); assert!(ParachainStaking::delegator_state(2).is_none()); assert!( - !ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2), + !ParachainStaking::delegation_scheduled_requests(&1).iter().any(|x| x.delegator == 2), "delegation request not removed" ) }); @@ -1960,11 +1559,9 @@ fn execute_leave_delegators_removes_delegations_from_collator_state() { .build() .execute_with(|| { for i in 2..6 { - let candidate_state = - ParachainStaking::candidate_info(i).expect("initialized in ext builder"); + let candidate_state = ParachainStaking::candidate_info(i).expect("initialized in ext builder"); assert_eq!(candidate_state.total_counted, 30); - let top_delegations = - ParachainStaking::top_delegations(i).expect("initialized in ext builder"); + let top_delegations = ParachainStaking::top_delegations(i).expect("initialized in ext builder"); assert_eq!(top_delegations.delegations[0].owner, 1); assert_eq!(top_delegations.delegations[0].amount, 10); assert_eq!(top_delegations.total, 10); @@ -1974,11 +1571,9 @@ fn execute_leave_delegators_removes_delegations_from_collator_state() { roll_to(10); assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(1), 1, 10)); for i in 2..6 { - let candidate_state = - ParachainStaking::candidate_info(i).expect("initialized in ext builder"); + let candidate_state = ParachainStaking::candidate_info(i).expect("initialized in ext builder"); assert_eq!(candidate_state.total_counted, 20); - let top_delegations = - ParachainStaking::top_delegations(i).expect("initialized in ext builder"); + let top_delegations = ParachainStaking::top_delegations(i).expect("initialized in ext builder"); assert!(top_delegations.delegations.is_empty()); } }); @@ -2060,11 +1655,7 @@ fn sufficient_execute_leave_delegators_weight_hint_succeeds() { } roll_to(10); for i in 3..7 { - assert_ok!(ParachainStaking::execute_leave_delegators( - RuntimeOrigin::signed(i), - i, - 1 - )); + assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(i), i, 1)); } }); } @@ -2095,8 +1686,7 @@ fn cancel_leave_delegators_updates_delegator_state() { .execute_with(|| { assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); - let delegator = - ParachainStaking::delegator_state(&2).expect("just cancelled exit so exists"); + let delegator = ParachainStaking::delegator_state(&2).expect("just cancelled exit so exists"); assert!(delegator.is_active()); }); } @@ -2142,11 +1732,7 @@ fn revoke_delegation_event_emits_correctly() { }); roll_to_round_begin(3); roll_blocks(1); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); assert_events_eq!( Event::DelegatorLeftCandidate { delegator: 2, @@ -2296,32 +1882,15 @@ fn delegator_bond_more_updates_candidate_state_bottom_delegations() { .with_balances(vec![(1, 30), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) .with_candidates(vec![(1, 30)]) .with_delegations(vec![(2, 1, 10), (3, 1, 20), (4, 1, 20), (5, 1, 20), (6, 1, 20)]) - .build() - .execute_with(|| { - assert_eq!( - ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].owner, - 2 - ); - assert_eq!( - ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].amount, - 10 - ); - assert_eq!(ParachainStaking::bottom_delegations(1).unwrap().total, 10); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); - assert_events_eq!(Event::DelegationIncreased { - delegator: 2, - candidate: 1, - amount: 5, - in_top: false - }); - assert_eq!( - ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].owner, - 2 - ); - assert_eq!( - ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].amount, - 15 - ); + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].owner, 2); + assert_eq!(ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].amount, 10); + assert_eq!(ParachainStaking::bottom_delegations(1).unwrap().total, 10); + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); + assert_events_eq!(Event::DelegationIncreased { delegator: 2, candidate: 1, amount: 5, in_top: false }); + assert_eq!(ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].owner, 2); + assert_eq!(ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].amount, 15); assert_eq!(ParachainStaking::bottom_delegations(1).unwrap().total, 15); }); } @@ -2377,11 +1946,7 @@ fn delegator_bond_more_allowed_when_bond_decrease_scheduled() { .with_delegations(vec![(2, 1, 15)]) .build() .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5, - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5,)); assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); }); } @@ -2396,11 +1961,7 @@ fn delegator_bond_less_event_emits_correctly() { .with_delegations(vec![(2, 1, 10)]) .build() .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); assert_events_eq!(Event::DelegationDecreaseScheduled { delegator: 2, candidate: 1, @@ -2418,19 +1979,11 @@ fn delegator_bond_less_updates_delegator_state() { .with_delegations(vec![(2, 1, 10)]) .build() .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); let state = ParachainStaking::delegation_scheduled_requests(&1); assert_eq!( state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], + vec![ScheduledRequest { delegator: 2, when_executable: 3, action: DelegationAction::Decrease(5) }], ); }); } @@ -2567,11 +2120,7 @@ fn execute_revoke_delegation_emits_exit_event_if_exit_happens() { .execute_with(|| { assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); assert_events_emitted!(Event::DelegatorLeftCandidate { delegator: 2, candidate: 1, @@ -2615,11 +2164,7 @@ fn revoke_delegation_executes_exit_if_last_delegation() { .execute_with(|| { assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); assert_events_emitted!(Event::DelegatorLeftCandidate { delegator: 2, candidate: 1, @@ -2640,11 +2185,7 @@ fn execute_revoke_delegation_emits_correct_event() { .execute_with(|| { assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); assert_events_emitted!(Event::DelegatorLeftCandidate { delegator: 2, candidate: 1, @@ -2665,11 +2206,7 @@ fn execute_revoke_delegation_unreserves_balance() { assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); }); } @@ -2682,13 +2219,9 @@ fn execute_revoke_delegation_adds_revocation_to_delegator_state() { .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) .build() .execute_with(|| { - assert!(!ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2)); + assert!(!ParachainStaking::delegation_scheduled_requests(&1).iter().any(|x| x.delegator == 2)); assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert!(ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2)); + assert!(ParachainStaking::delegation_scheduled_requests(&1).iter().any(|x| x.delegator == 2)); }); } @@ -2702,14 +2235,8 @@ fn execute_revoke_delegation_removes_revocation_from_delegator_state_upon_execut .execute_with(|| { assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!(!ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2)); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert!(!ParachainStaking::delegation_scheduled_requests(&1).iter().any(|x| x.delegator == 2)); }); } @@ -2723,15 +2250,9 @@ fn execute_revoke_delegation_removes_revocation_from_state_for_single_delegation .execute_with(|| { assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); assert!( - !ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2), + !ParachainStaking::delegation_scheduled_requests(&1).iter().any(|x| x.delegator == 2), "delegation was not removed" ); }); @@ -2748,11 +2269,7 @@ fn execute_revoke_delegation_decreases_total_staked() { assert_eq!(ParachainStaking::total(), 40); assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); assert_eq!(ParachainStaking::total(), 30); }); } @@ -2770,11 +2287,7 @@ fn execute_revoke_delegation_for_last_delegation_removes_delegator_state() { roll_to(10); // this will be confusing for people // if status is leaving, then execute_delegation_request works if last delegation - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); assert!(ParachainStaking::delegator_state(2).is_none()); }); } @@ -2790,15 +2303,8 @@ fn execute_revoke_delegation_removes_delegation_from_candidate_state() { assert_eq!(ParachainStaking::candidate_info(1).expect("exists").delegation_count, 1u32); assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!(ParachainStaking::candidate_info(1) - .expect("exists") - .delegation_count - .is_zero()); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert!(ParachainStaking::candidate_info(1).expect("exists").delegation_count.is_zero()); }); } @@ -2814,11 +2320,7 @@ fn can_execute_revoke_delegation_for_leaving_candidate() { assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); // can execute delegation request for leaving candidate - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); }); } @@ -2852,11 +2354,7 @@ fn delegator_bond_more_after_revoke_delegation_does_not_effect_exit() { assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 3, 10)); roll_to(100); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); assert!(ParachainStaking::is_delegator(&2)); assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); }); @@ -2881,23 +2379,11 @@ fn delegator_bond_less_after_revoke_delegation_does_not_effect_exit() { ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 2), Error::::PendingDelegationRequestAlreadyExists ); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 3, - 2 - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 3, 2)); roll_to(10); roll_blocks(1); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 3 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 3)); assert_events_eq!( Event::DelegatorLeftCandidate { delegator: 2, @@ -2924,17 +2410,9 @@ fn execute_delegator_bond_less_unreserves_balance() { .build() .execute_with(|| { assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 5); }); } @@ -2948,17 +2426,9 @@ fn execute_delegator_bond_less_decreases_total_staked() { .build() .execute_with(|| { assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); assert_eq!(ParachainStaking::total(), 35); }); } @@ -2972,17 +2442,9 @@ fn execute_delegator_bond_less_updates_delegator_state() { .build() .execute_with(|| { assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 10); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 5); }); } @@ -2997,17 +2459,9 @@ fn execute_delegator_bond_less_updates_candidate_state() { .execute_with(|| { assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 10); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 5); }); @@ -3022,17 +2476,9 @@ fn execute_delegator_bond_less_decreases_total() { .build() .execute_with(|| { assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); assert_eq!(ParachainStaking::total(), 35); }); } @@ -3045,34 +2491,20 @@ fn execute_delegator_bond_less_updates_just_bottom_delegations() { .with_delegations(vec![(2, 1, 10), (3, 1, 11), (4, 1, 12), (5, 1, 14), (6, 1, 15)]) .build() .execute_with(|| { - let pre_call_candidate_info = - ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let pre_call_top_delegations = - ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + let pre_call_candidate_info = ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let pre_call_top_delegations = ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); let pre_call_bottom_delegations = ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 2 - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 2)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - let post_call_candidate_info = - ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let post_call_top_delegations = - ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + let post_call_candidate_info = ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let post_call_top_delegations = ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); let post_call_bottom_delegations = ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); let mut not_equal = false; for Bond { owner, amount } in pre_call_bottom_delegations.delegations { - for Bond { owner: post_owner, amount: post_amount } in - &post_call_bottom_delegations.delegations - { + for Bond { owner: post_owner, amount: post_amount } in &post_call_bottom_delegations.delegations { if &owner == post_owner { if &amount != post_amount { not_equal = true; @@ -3084,9 +2516,7 @@ fn execute_delegator_bond_less_updates_just_bottom_delegations() { assert!(not_equal); let mut equal = true; for Bond { owner, amount } in pre_call_top_delegations.delegations { - for Bond { owner: post_owner, amount: post_amount } in - &post_call_top_delegations.delegations - { + for Bond { owner: post_owner, amount: post_amount } in &post_call_top_delegations.delegations { if &owner == post_owner { if &amount != post_amount { equal = false; @@ -3096,10 +2526,7 @@ fn execute_delegator_bond_less_updates_just_bottom_delegations() { } } assert!(equal); - assert_eq!( - pre_call_candidate_info.total_counted, - post_call_candidate_info.total_counted - ); + assert_eq!(pre_call_candidate_info.total_counted, post_call_candidate_info.total_counted); }); } @@ -3111,34 +2538,20 @@ fn execute_delegator_bond_less_does_not_delete_bottom_delegations() { .with_delegations(vec![(2, 1, 10), (3, 1, 11), (4, 1, 12), (5, 1, 14), (6, 1, 15)]) .build() .execute_with(|| { - let pre_call_candidate_info = - ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let pre_call_top_delegations = - ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + let pre_call_candidate_info = ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let pre_call_top_delegations = ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); let pre_call_bottom_delegations = ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(6), - 1, - 4 - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(6), 1, 4)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(6), - 6, - 1 - )); - let post_call_candidate_info = - ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let post_call_top_delegations = - ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(6), 6, 1)); + let post_call_candidate_info = ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let post_call_top_delegations = ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); let post_call_bottom_delegations = ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); let mut equal = true; for Bond { owner, amount } in pre_call_bottom_delegations.delegations { - for Bond { owner: post_owner, amount: post_amount } in - &post_call_bottom_delegations.delegations - { + for Bond { owner: post_owner, amount: post_amount } in &post_call_bottom_delegations.delegations { if &owner == post_owner { if &amount != post_amount { equal = false; @@ -3150,9 +2563,7 @@ fn execute_delegator_bond_less_does_not_delete_bottom_delegations() { assert!(equal); let mut not_equal = false; for Bond { owner, amount } in pre_call_top_delegations.delegations { - for Bond { owner: post_owner, amount: post_amount } in - &post_call_top_delegations.delegations - { + for Bond { owner: post_owner, amount: post_amount } in &post_call_top_delegations.delegations { if &owner == post_owner { if &amount != post_amount { not_equal = true; @@ -3162,10 +2573,7 @@ fn execute_delegator_bond_less_does_not_delete_bottom_delegations() { } } assert!(not_equal); - assert_eq!( - pre_call_candidate_info.total_counted - 4, - post_call_candidate_info.total_counted - ); + assert_eq!(pre_call_candidate_info.total_counted - 4, post_call_candidate_info.total_counted); }); } @@ -3178,18 +2586,10 @@ fn can_execute_delegator_bond_less_for_leaving_candidate() { .build() .execute_with(|| { assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); roll_to(10); // can execute bond more delegation request for leaving candidate - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); }); } @@ -3229,26 +2629,16 @@ fn cancel_revoke_delegation_updates_delegator_state() { let state = ParachainStaking::delegation_scheduled_requests(&1); assert_eq!( state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Revoke(10), - }], + vec![ScheduledRequest { delegator: 2, when_executable: 3, action: DelegationAction::Revoke(10) }], ); assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), + ParachainStaking::delegator_state(&2).map(|x| x.less_total).expect("delegator state must exist"), 10 ); assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); - assert!(!ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2)); + assert!(!ParachainStaking::delegation_scheduled_requests(&1).iter().any(|x| x.delegator == 2)); assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), + ParachainStaking::delegator_state(&2).map(|x| x.less_total).expect("delegator state must exist"), 0 ); }); @@ -3264,11 +2654,7 @@ fn cancel_delegator_bond_less_correct_event() { .with_delegations(vec![(2, 1, 15)]) .build() .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); assert_events_emitted!(Event::CancelledDelegationRequest { delegator: 2, @@ -3289,34 +2675,20 @@ fn cancel_delegator_bond_less_updates_delegator_state() { .with_delegations(vec![(2, 1, 15)]) .build() .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); let state = ParachainStaking::delegation_scheduled_requests(&1); assert_eq!( state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], + vec![ScheduledRequest { delegator: 2, when_executable: 3, action: DelegationAction::Decrease(5) }], ); assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), + ParachainStaking::delegator_state(&2).map(|x| x.less_total).expect("delegator state must exist"), 5 ); assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); - assert!(!ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2)); + assert!(!ParachainStaking::delegation_scheduled_requests(&1).iter().any(|x| x.delegator == 2)); assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), + ParachainStaking::delegator_state(&2).map(|x| x.less_total).expect("delegator state must exist"), 0 ); }); @@ -3334,53 +2706,31 @@ fn delegator_schedule_revocation_total() { .execute_with(|| { assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), + ParachainStaking::delegator_state(&2).map(|x| x.less_total).expect("delegator state must exist"), 10 ); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), + ParachainStaking::delegator_state(&2).map(|x| x.less_total).expect("delegator state must exist"), 0 ); assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 5, 10, 0, 2)); assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3)); assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 4)); assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), + ParachainStaking::delegator_state(&2).map(|x| x.less_total).expect("delegator state must exist"), 20, ); roll_to(20); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 3 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 3)); assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), + ParachainStaking::delegator_state(&2).map(|x| x.less_total).expect("delegator state must exist"), 10, ); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 4 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 4)); assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), + ParachainStaking::delegator_state(&2).map(|x| x.less_total).expect("delegator state must exist"), 0 ); }); @@ -3420,12 +2770,7 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 2, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 5, - total_balance: 140, - }, + Event::NewRound { starting_block: 5, round: 2, selected_collators_number: 5, total_balance: 140 }, ); assert_eq!(Balances::free_balance(&11), 1); // ~ set block author as 1 for all blocks this round @@ -3450,12 +2795,7 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 4, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 4, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 4, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 5, - total_balance: 140, - }, + Event::NewRound { starting_block: 15, round: 4, selected_collators_number: 5, total_balance: 140 }, Event::DelegatorExitScheduled { round: 4, delegator: 6, scheduled_exit: 6 }, ); roll_blocks(3); @@ -3474,12 +2814,7 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 5, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 5, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 5, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 20, - round: 5, - selected_collators_number: 5, - total_balance: 140, - }, + Event::NewRound { starting_block: 20, round: 5, selected_collators_number: 5, total_balance: 140 }, ); roll_blocks(3); assert_events_eq!( @@ -3497,12 +2832,7 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 6, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 25, - round: 6, - selected_collators_number: 5, - total_balance: 140, - }, + Event::NewRound { starting_block: 25, round: 6, selected_collators_number: 5, total_balance: 140 }, Event::DelegatorLeftCandidate { delegator: 6, candidate: 1, @@ -3526,12 +2856,7 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 7, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 7, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 7, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 30, - round: 7, - selected_collators_number: 5, - total_balance: 130, - }, + Event::NewRound { starting_block: 30, round: 7, selected_collators_number: 5, total_balance: 130 }, ); roll_blocks(3); assert_events_eq!( @@ -3560,12 +2885,7 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 8, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 8, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 8, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 35, - round: 8, - selected_collators_number: 5, - total_balance: 130, - }, + Event::NewRound { starting_block: 35, round: 8, selected_collators_number: 5, total_balance: 130 }, ); roll_blocks(3); assert_events_eq!( @@ -3584,12 +2904,7 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 9, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 9, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 9, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 40, - round: 9, - selected_collators_number: 5, - total_balance: 130, - }, + Event::NewRound { starting_block: 40, round: 9, selected_collators_number: 5, total_balance: 130 }, ); roll_blocks(3); assert_events_eq!( @@ -3617,12 +2932,7 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 10, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 10, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 10, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 45, - round: 10, - selected_collators_number: 5, - total_balance: 140, - }, + Event::NewRound { starting_block: 45, round: 10, selected_collators_number: 5, total_balance: 140 }, ); roll_blocks(3); assert_events_eq!( @@ -3642,12 +2952,7 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 11, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 11, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 11, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 50, - round: 11, - selected_collators_number: 5, - total_balance: 140, - }, + Event::NewRound { starting_block: 50, round: 11, selected_collators_number: 5, total_balance: 140 }, ); roll_blocks(3); assert_events_eq!( @@ -3665,12 +2970,7 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 12, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 12, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 12, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 55, - round: 12, - selected_collators_number: 5, - total_balance: 140, - }, + Event::NewRound { starting_block: 55, round: 12, selected_collators_number: 5, total_balance: 140 }, ); roll_blocks(3); assert_events_eq!( @@ -3695,17 +2995,8 @@ fn paid_collator_commission_matches_config() { assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(4), 20u128, 100u32)); assert_events_eq!( Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 40 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 1, - total_balance: 40, - }, - Event::JoinedCollatorCandidates { - account: 4, - amount_locked: 20, - new_total_amt_locked: 60, - }, + Event::NewRound { starting_block: 5, round: 2, selected_collators_number: 1, total_balance: 40 }, + Event::JoinedCollatorCandidates { account: 4, amount_locked: 20, new_total_amt_locked: 60 }, ); roll_blocks(1); @@ -3732,12 +3023,7 @@ fn paid_collator_commission_matches_config() { assert_events_eq!( Event::CollatorChosen { round: 3, collator_account: 1, total_exposed_amount: 40 }, Event::CollatorChosen { round: 3, collator_account: 4, total_exposed_amount: 40 }, - Event::NewRound { - starting_block: 10, - round: 3, - selected_collators_number: 2, - total_balance: 80, - }, + Event::NewRound { starting_block: 10, round: 3, selected_collators_number: 2, total_balance: 80 }, ); // only reward author with id 4 set_author(3, 4, 100); @@ -3747,12 +3033,7 @@ fn paid_collator_commission_matches_config() { assert_events_eq!( Event::CollatorChosen { round: 5, collator_account: 1, total_exposed_amount: 40 }, Event::CollatorChosen { round: 5, collator_account: 4, total_exposed_amount: 40 }, - Event::NewRound { - starting_block: 20, - round: 5, - selected_collators_number: 2, - total_balance: 80, - }, + Event::NewRound { starting_block: 20, round: 5, selected_collators_number: 2, total_balance: 80 }, ); roll_blocks(1); @@ -3767,28 +3048,14 @@ fn paid_collator_commission_matches_config() { #[test] fn collator_exit_executes_after_delay() { ExtBuilder::default() - .with_balances(vec![ - (1, 1000), - (2, 300), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 9), - (9, 4), - ]) + .with_balances(vec![(1, 1000), (2, 300), (3, 100), (4, 100), (5, 100), (6, 100), (7, 100), (8, 9), (9, 4)]) .with_candidates(vec![(1, 500), (2, 200)]) .with_delegations(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) .build() .execute_with(|| { roll_to(11); assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(2), 2)); - assert_events_eq!(Event::CandidateScheduledExit { - exit_allowed_round: 3, - candidate: 2, - scheduled_exit: 5, - }); + assert_events_eq!(Event::CandidateScheduledExit { exit_allowed_round: 3, candidate: 2, scheduled_exit: 5 }); let info = ParachainStaking::candidate_info(&2).unwrap(); assert_eq!(info.status, CollatorStatus::Leaving(5)); roll_to(21); @@ -3830,33 +3097,16 @@ fn collator_selection_chooses_top_candidates() { Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 80 }, Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 70 }, Event::CollatorChosen { round: 2, collator_account: 5, total_exposed_amount: 60 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 5, - total_balance: 400, - }, - Event::CandidateScheduledExit { - exit_allowed_round: 2, - candidate: 6, - scheduled_exit: 4 - }, + Event::NewRound { starting_block: 5, round: 2, selected_collators_number: 5, total_balance: 400 }, + Event::CandidateScheduledExit { exit_allowed_round: 2, candidate: 6, scheduled_exit: 4 }, ); roll_to_round_begin(4); roll_blocks(1); assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(6), 6, 0)); assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(6), 69u128, 100u32)); assert_events_eq!( - Event::CandidateLeft { - ex_candidate: 6, - unlocked_amount: 50, - new_total_amt_locked: 400, - }, - Event::JoinedCollatorCandidates { - account: 6, - amount_locked: 69u128, - new_total_amt_locked: 469u128, - }, + Event::CandidateLeft { ex_candidate: 6, unlocked_amount: 50, new_total_amt_locked: 400 }, + Event::JoinedCollatorCandidates { account: 6, amount_locked: 69u128, new_total_amt_locked: 469u128 }, ); roll_to_round_begin(6); // should choose top TotalSelectedCandidates (5), in order @@ -3866,12 +3116,7 @@ fn collator_selection_chooses_top_candidates() { Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 80 }, Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 70 }, Event::CollatorChosen { round: 6, collator_account: 6, total_exposed_amount: 69 }, - Event::NewRound { - starting_block: 25, - round: 6, - selected_collators_number: 5, - total_balance: 409, - }, + Event::NewRound { starting_block: 25, round: 6, selected_collators_number: 5, total_balance: 409 }, ); }); } @@ -3890,12 +3135,7 @@ fn payout_distribution_to_solo_collators() { Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 90 }, Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 80 }, Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 70 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 4, - total_balance: 340, - }, + Event::NewRound { starting_block: 5, round: 2, selected_collators_number: 4, total_balance: 340 }, ); // ~ set block author as 1 for all blocks this round set_author(2, 1, 100); @@ -3905,12 +3145,7 @@ fn payout_distribution_to_solo_collators() { Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 90 }, Event::CollatorChosen { round: 4, collator_account: 3, total_exposed_amount: 80 }, Event::CollatorChosen { round: 4, collator_account: 4, total_exposed_amount: 70 }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 4, - total_balance: 340, - }, + Event::NewRound { starting_block: 15, round: 4, selected_collators_number: 4, total_balance: 340 }, ); // pay total issuance to 1 at 2nd block roll_blocks(3); @@ -3926,12 +3161,7 @@ fn payout_distribution_to_solo_collators() { Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 90 }, Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 80 }, Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 70 }, - Event::NewRound { - starting_block: 25, - round: 6, - selected_collators_number: 4, - total_balance: 340, - }, + Event::NewRound { starting_block: 25, round: 6, selected_collators_number: 4, total_balance: 340 }, ); roll_blocks(3); assert_events_eq!(Event::Rewarded { account: 1, rewards: 129 }); @@ -3949,12 +3179,7 @@ fn payout_distribution_to_solo_collators() { Event::CollatorChosen { round: 8, collator_account: 2, total_exposed_amount: 90 }, Event::CollatorChosen { round: 8, collator_account: 3, total_exposed_amount: 80 }, Event::CollatorChosen { round: 8, collator_account: 4, total_exposed_amount: 70 }, - Event::NewRound { - starting_block: 35, - round: 8, - selected_collators_number: 4, - total_balance: 340, - }, + Event::NewRound { starting_block: 35, round: 8, selected_collators_number: 4, total_balance: 340 }, ); roll_blocks(1); assert_events_eq!(Event::Rewarded { account: 3, rewards: 56 }); @@ -4002,12 +3227,7 @@ fn multiple_delegations() { Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 2, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 5, - total_balance: 140, - }, + Event::NewRound { starting_block: 5, round: 2, selected_collators_number: 5, total_balance: 140 }, ); roll_blocks(1); assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(6), 2, 10, 10, 10)); @@ -4056,11 +3276,7 @@ fn multiple_delegations() { delegator_position: DelegatorAdded::AddedToBottom, auto_compound: Percent::zero(), }, - Event::CandidateScheduledExit { - exit_allowed_round: 6, - candidate: 2, - scheduled_exit: 8 - }, + Event::CandidateScheduledExit { exit_allowed_round: 6, candidate: 2, scheduled_exit: 8 }, ); roll_to_round_begin(7); assert_events_eq!( @@ -4068,12 +3284,7 @@ fn multiple_delegations() { Event::CollatorChosen { round: 7, collator_account: 3, total_exposed_amount: 30 }, Event::CollatorChosen { round: 7, collator_account: 4, total_exposed_amount: 30 }, Event::CollatorChosen { round: 7, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 30, - round: 7, - selected_collators_number: 4, - total_balance: 120, - }, + Event::NewRound { starting_block: 30, round: 7, selected_collators_number: 4, total_balance: 120 }, ); // verify that delegations are removed after collator leaves, not before assert_eq!(ParachainStaking::delegator_state(7).unwrap().total(), 90); @@ -4112,40 +3323,24 @@ fn execute_leave_candidate_removes_delegations() { .build() .execute_with(|| { // Verifies the revocation request is initially empty - assert!(!ParachainStaking::delegation_scheduled_requests(&2) - .iter() - .any(|x| x.delegator == 3)); + assert!(!ParachainStaking::delegation_scheduled_requests(&2).iter().any(|x| x.delegator == 3)); assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(2), 2)); assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(3), 2)); // Verifies the revocation request is present - assert!(ParachainStaking::delegation_scheduled_requests(&2) - .iter() - .any(|x| x.delegator == 3)); + assert!(ParachainStaking::delegation_scheduled_requests(&2).iter().any(|x| x.delegator == 3)); roll_to(16); assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 2, 2)); // Verifies the revocation request is again empty - assert!(!ParachainStaking::delegation_scheduled_requests(&2) - .iter() - .any(|x| x.delegator == 3)); + assert!(!ParachainStaking::delegation_scheduled_requests(&2).iter().any(|x| x.delegator == 3)); }); } #[test] fn payouts_follow_delegation_changes() { ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - ]) + .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (6, 100), (7, 100), (8, 100), (9, 100), (10, 100)]) .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20)]) .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) .build() @@ -4157,12 +3352,7 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 4, - total_balance: 130, - }, + Event::NewRound { starting_block: 5, round: 2, selected_collators_number: 4, total_balance: 130 }, ); // ~ set block author as 1 for all blocks this round set_author(2, 1, 100); @@ -4173,12 +3363,7 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 4, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 4, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 4, - total_balance: 130, - }, + Event::NewRound { starting_block: 15, round: 4, selected_collators_number: 4, total_balance: 130 }, ); roll_blocks(3); assert_events_eq!( @@ -4200,11 +3385,7 @@ fn payouts_follow_delegation_changes() { Error::::DelegatorDNE ); assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(6))); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 4, - delegator: 6, - scheduled_exit: 6, - }); + assert_events_eq!(Event::DelegatorExitScheduled { round: 4, delegator: 6, scheduled_exit: 6 }); // fast forward to block in which delegator 6 exit executes roll_to_round_begin(5); assert_events_eq!( @@ -4212,12 +3393,7 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 5, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 5, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 5, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 20, - round: 5, - selected_collators_number: 4, - total_balance: 130, - }, + Event::NewRound { starting_block: 20, round: 5, selected_collators_number: 4, total_balance: 130 }, ); roll_blocks(3); assert_events_eq!( @@ -4234,12 +3410,7 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 25, - round: 6, - selected_collators_number: 4, - total_balance: 130, - }, + Event::NewRound { starting_block: 25, round: 6, selected_collators_number: 4, total_balance: 130 }, Event::DelegatorLeftCandidate { delegator: 6, candidate: 1, @@ -4264,12 +3435,7 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 7, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 7, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 7, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 30, - round: 7, - selected_collators_number: 4, - total_balance: 120, - }, + Event::NewRound { starting_block: 30, round: 7, selected_collators_number: 4, total_balance: 120 }, ); roll_blocks(3); assert_events_eq!( @@ -4283,12 +3449,7 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 8, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 8, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 8, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 35, - round: 8, - selected_collators_number: 4, - total_balance: 120, - }, + Event::NewRound { starting_block: 35, round: 8, selected_collators_number: 4, total_balance: 120 }, ); roll_blocks(3); assert_events_eq!( @@ -4304,12 +3465,7 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 9, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 9, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 9, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 40, - round: 9, - selected_collators_number: 4, - total_balance: 120, - }, + Event::NewRound { starting_block: 40, round: 9, selected_collators_number: 4, total_balance: 120 }, ); roll_blocks(3); assert_events_eq!( @@ -4335,12 +3491,7 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 10, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 10, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 10, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 45, - round: 10, - selected_collators_number: 4, - total_balance: 130, - }, + Event::NewRound { starting_block: 45, round: 10, selected_collators_number: 4, total_balance: 130 }, ); roll_blocks(3); assert_events_eq!( @@ -4356,12 +3507,7 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 11, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 11, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 11, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 50, - round: 11, - selected_collators_number: 4, - total_balance: 130, - }, + Event::NewRound { starting_block: 50, round: 11, selected_collators_number: 4, total_balance: 130 }, ); roll_blocks(3); assert_events_eq!( @@ -4377,12 +3523,7 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 12, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 12, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 12, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 55, - round: 12, - selected_collators_number: 4, - total_balance: 130, - }, + Event::NewRound { starting_block: 55, round: 12, selected_collators_number: 4, total_balance: 130 }, ); roll_blocks(3); assert_events_eq!( @@ -4436,17 +3577,7 @@ fn bottom_delegations_are_empty_when_top_delegations_not_full() { #[test] fn candidate_pool_updates_when_total_counted_changes() { ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (3, 19), - (4, 20), - (5, 21), - (6, 22), - (7, 15), - (8, 16), - (9, 17), - (10, 18), - ]) + .with_balances(vec![(1, 20), (3, 19), (4, 20), (5, 21), (6, 22), (7, 15), (8, 16), (9, 17), (10, 18)]) .with_candidates(vec![(1, 20)]) .with_delegations(vec![ (3, 1, 11), @@ -4482,31 +3613,15 @@ fn candidate_pool_updates_when_total_counted_changes() { // 4: 12 -> 20 => 4 is in top, bumps out 8 // 17 + 18 + 19 + 20 + 20 = 94 (top 4 + self bond) is_candidate_pool_bond(1, 94); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(10), - 1, - 3 - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(10), 1, 3)); roll_to(30); // 10: 18 -> 15 => 10 bumped to bottom, 8 bumped to top (- 18 + 16 = -2 for count) - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(10), - 10, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(10), 10, 1)); // 16 + 17 + 19 + 20 + 20 = 92 (top 4 + self bond) is_candidate_pool_bond(1, 92); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(9), - 1, - 4 - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(9), 1, 4)); roll_to(40); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(9), - 9, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(9), 9, 1)); // 15 + 16 + 19 + 20 + 20 = 90 (top 4 + self bond) is_candidate_pool_bond(1, 90); }); @@ -4515,17 +3630,7 @@ fn candidate_pool_updates_when_total_counted_changes() { #[test] fn only_top_collators_are_counted() { ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (3, 19), - (4, 20), - (5, 21), - (6, 22), - (7, 15), - (8, 16), - (9, 17), - (10, 18), - ]) + .with_balances(vec![(1, 20), (3, 19), (4, 20), (5, 21), (6, 22), (7, 15), (8, 16), (9, 17), (10, 18)]) .with_candidates(vec![(1, 20)]) .with_delegations(vec![ (3, 1, 11), @@ -4548,45 +3653,25 @@ fn only_top_collators_are_counted() { assert_eq!(collator_state.total_counted, 86); // bump bottom to the top assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(3), 1, 8)); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 3, - candidate: 1, - amount: 8, - in_top: true, - }); + assert_events_emitted!(Event::DelegationIncreased { delegator: 3, candidate: 1, amount: 8, in_top: true }); let collator_state = ParachainStaking::candidate_info(1).unwrap(); // 16 + 17 + 18 + 19 + 20 = 90 (top 4 + self bond) assert_eq!(collator_state.total_counted, 90); // bump bottom to the top assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(4), 1, 8)); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 4, - candidate: 1, - amount: 8, - in_top: true, - }); + assert_events_emitted!(Event::DelegationIncreased { delegator: 4, candidate: 1, amount: 8, in_top: true }); let collator_state = ParachainStaking::candidate_info(1).unwrap(); // 17 + 18 + 19 + 20 + 20 = 94 (top 4 + self bond) assert_eq!(collator_state.total_counted, 94); // bump bottom to the top assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(5), 1, 8)); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 5, - candidate: 1, - amount: 8, - in_top: true, - }); + assert_events_emitted!(Event::DelegationIncreased { delegator: 5, candidate: 1, amount: 8, in_top: true }); let collator_state = ParachainStaking::candidate_info(1).unwrap(); // 18 + 19 + 20 + 21 + 20 = 98 (top 4 + self bond) assert_eq!(collator_state.total_counted, 98); - // bump bottom to the top - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(6), 1, 8)); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 6, - candidate: 1, - amount: 8, - in_top: true, - }); + // bump bottom to the top + assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(6), 1, 8)); + assert_events_emitted!(Event::DelegationIncreased { delegator: 6, candidate: 1, amount: 8, in_top: true }); let collator_state = ParachainStaking::candidate_info(1).unwrap(); // 19 + 20 + 21 + 22 + 20 = 102 (top 4 + self bond) assert_eq!(collator_state.total_counted, 102); @@ -4641,32 +3726,18 @@ fn delegation_events_convey_correct_position() { assert_eq!(collator1_state.total_counted, 74); // 8 increases delegation to the top assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(8), 1, 3)); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 8, - candidate: 1, - amount: 3, - in_top: true, - }); + assert_events_emitted!(Event::DelegationIncreased { delegator: 8, candidate: 1, amount: 3, in_top: true }); let collator1_state = ParachainStaking::candidate_info(1).unwrap(); // 13 + 13 + 14 + 15 + 20 = 75 (top 4 + self bond) assert_eq!(collator1_state.total_counted, 75); // 3 increases delegation but stays in bottom assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(3), 1, 1)); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 3, - candidate: 1, - amount: 1, - in_top: false, - }); + assert_events_emitted!(Event::DelegationIncreased { delegator: 3, candidate: 1, amount: 1, in_top: false }); let collator1_state = ParachainStaking::candidate_info(1).unwrap(); // 13 + 13 + 14 + 15 + 20 = 75 (top 4 + self bond) assert_eq!(collator1_state.total_counted, 75); // 6 decreases delegation but stays in top - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(6), - 1, - 2 - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(6), 1, 2)); assert_events_emitted!(Event::DelegationDecreaseScheduled { delegator: 6, candidate: 1, @@ -4674,26 +3745,13 @@ fn delegation_events_convey_correct_position() { execute_round: 3, }); roll_to(30); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(6), - 6, - 1 - )); - assert_events_emitted!(Event::DelegationDecreased { - delegator: 6, - candidate: 1, - amount: 2, - in_top: true, - }); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(6), 6, 1)); + assert_events_emitted!(Event::DelegationDecreased { delegator: 6, candidate: 1, amount: 2, in_top: true }); let collator1_state = ParachainStaking::candidate_info(1).unwrap(); // 12 + 13 + 13 + 15 + 20 = 73 (top 4 + self bond)ƒ assert_eq!(collator1_state.total_counted, 73); // 6 decreases delegation and is bumped to bottom - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(6), - 1, - 1 - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(6), 1, 1)); assert_events_emitted!(Event::DelegationDecreaseScheduled { delegator: 6, candidate: 1, @@ -4701,17 +3759,8 @@ fn delegation_events_convey_correct_position() { execute_round: 9, }); roll_to(40); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(6), - 6, - 1 - )); - assert_events_emitted!(Event::DelegationDecreased { - delegator: 6, - candidate: 1, - amount: 1, - in_top: false, - }); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(6), 6, 1)); + assert_events_emitted!(Event::DelegationDecreased { delegator: 6, candidate: 1, amount: 1, in_top: false }); let collator1_state = ParachainStaking::candidate_info(1).unwrap(); // 12 + 13 + 13 + 15 + 20 = 73 (top 4 + self bond) assert_eq!(collator1_state.total_counted, 73); @@ -4736,12 +3785,7 @@ fn no_rewards_paid_until_after_reward_payment_delay() { Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 20 }, Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 20 }, Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 3, - total_balance: 60, - }, + Event::NewRound { starting_block: 5, round: 2, selected_collators_number: 3, total_balance: 60 }, ); roll_to_round_begin(3); @@ -4749,12 +3793,7 @@ fn no_rewards_paid_until_after_reward_payment_delay() { Event::CollatorChosen { round: 3, collator_account: 1, total_exposed_amount: 20 }, Event::CollatorChosen { round: 3, collator_account: 2, total_exposed_amount: 20 }, Event::CollatorChosen { round: 3, collator_account: 3, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 10, - round: 3, - selected_collators_number: 3, - total_balance: 60, - }, + Event::NewRound { starting_block: 10, round: 3, selected_collators_number: 3, total_balance: 60 }, ); roll_blocks(1); @@ -4796,12 +3835,7 @@ fn deferred_payment_storage_items_are_cleaned_up() { assert_events_eq!( Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 20 }, Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 2, - total_balance: 40, - }, + Event::NewRound { starting_block: 5, round: 2, selected_collators_number: 2, total_balance: 40 }, ); // we should have AtStake snapshots as soon as we start a round... @@ -4815,35 +3849,18 @@ fn deferred_payment_storage_items_are_cleaned_up() { !>::contains_key(1), "DelayedPayouts shouldn't be populated until after RewardPaymentDelay" ); - assert!( - >::contains_key(1), - "Points should be populated during current round" - ); - assert!( - >::contains_key(1), - "Staked should be populated when round changes" - ); + assert!(>::contains_key(1), "Points should be populated during current round"); + assert!(>::contains_key(1), "Staked should be populated when round changes"); - assert!( - !>::contains_key(2), - "Points should not be populated until author noted" - ); - assert!( - >::contains_key(2), - "Staked should be populated when round changes" - ); + assert!(!>::contains_key(2), "Points should not be populated until author noted"); + assert!(>::contains_key(2), "Staked should be populated when round changes"); // first payout occurs in round 3 roll_to_round_begin(3); assert_events_eq!( Event::CollatorChosen { round: 3, collator_account: 1, total_exposed_amount: 20 }, Event::CollatorChosen { round: 3, collator_account: 2, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 10, - round: 3, - selected_collators_number: 2, - total_balance: 40, - }, + Event::NewRound { starting_block: 10, round: 3, selected_collators_number: 2, total_balance: 40 }, ); roll_blocks(1); @@ -4860,10 +3877,7 @@ fn deferred_payment_storage_items_are_cleaned_up() { "DelayedPayouts should be populated after RewardPaymentDelay" ); assert!(>::contains_key(1)); - assert!( - !>::contains_key(1), - "Staked should be cleaned up after round change" - ); + assert!(!>::contains_key(1), "Staked should be cleaned up after round change"); assert!(!>::contains_key(2)); assert!(!>::contains_key(2), "We never rewarded points for round 2"); @@ -4889,12 +3903,7 @@ fn deferred_payment_storage_items_are_cleaned_up() { assert_events_eq!( Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 20 }, Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 2, - total_balance: 40, - }, + Event::NewRound { starting_block: 15, round: 4, selected_collators_number: 2, total_balance: 40 }, ); // collators have both been paid and storage fully cleaned up for round 1 @@ -5009,13 +4018,8 @@ fn deferred_payment_steady_state_event_flow() { let new_issuance = Balances::total_issuance(); let diff = new_issuance - initial_issuance; let burned = Balances::burn(diff); - Balances::settle( - &111, - burned, - WithdrawReasons::FEE, - ExistenceRequirement::AllowDeath, - ) - .expect("Account can absorb burn"); + Balances::settle(&111, burned, WithdrawReasons::FEE, ExistenceRequirement::AllowDeath) + .expect("Account can absorb burn"); }; // fn to roll through the first RewardPaymentDelay rounds. returns new round index @@ -5039,26 +4043,10 @@ fn deferred_payment_steady_state_event_flow() { assert!(num_rounds_rolled <= 1, "expected to be at round begin already"); assert_events_eq!( - Event::CollatorChosen { - round: round as u32, - collator_account: 1, - total_exposed_amount: 400, - }, - Event::CollatorChosen { - round: round as u32, - collator_account: 2, - total_exposed_amount: 400, - }, - Event::CollatorChosen { - round: round as u32, - collator_account: 3, - total_exposed_amount: 400, - }, - Event::CollatorChosen { - round: round as u32, - collator_account: 4, - total_exposed_amount: 400, - }, + Event::CollatorChosen { round: round as u32, collator_account: 1, total_exposed_amount: 400 }, + Event::CollatorChosen { round: round as u32, collator_account: 2, total_exposed_amount: 400 }, + Event::CollatorChosen { round: round as u32, collator_account: 3, total_exposed_amount: 400 }, + Event::CollatorChosen { round: round as u32, collator_account: 4, total_exposed_amount: 400 }, Event::NewRound { starting_block: (round - 1) * 5, round: round as u32, @@ -5153,15 +4141,9 @@ fn delegation_kicked_from_bottom_removes_pending_request() { // 10 delegates to full 1 => kicks lowest delegation (2, 19) assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(10), 1, 20, 8, 0)); // check the event - assert_events_emitted!(Event::DelegationKicked { - delegator: 2, - candidate: 1, - unstaked_amount: 19, - }); + assert_events_emitted!(Event::DelegationKicked { delegator: 2, candidate: 1, unstaked_amount: 19 }); // ensure request DNE - assert!(!ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2)); + assert!(!ParachainStaking::delegation_scheduled_requests(&1).iter().any(|x| x.delegator == 2)); }); } @@ -5175,10 +4157,7 @@ fn no_selected_candidates_defaults_to_last_round_collators() { roll_to_round_begin(1); // schedule to leave for i in 1..6 { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(i), - 5 - )); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(i), 5)); } let old_round = ParachainStaking::round().current; let old_selected_candidates = ParachainStaking::selected_candidates(); @@ -5189,11 +4168,7 @@ fn no_selected_candidates_defaults_to_last_round_collators() { roll_to_round_begin(3); // execute leave for i in 1..6 { - assert_ok!(ParachainStaking::execute_leave_candidates( - RuntimeOrigin::signed(i), - i, - 0, - )); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(i), i, 0,)); } // next round roll_to_round_begin(4); @@ -5228,35 +4203,25 @@ fn test_delegator_scheduled_for_revoke_is_rewarded_for_previous_rounds_but_not_f scheduled_exit: 3, }); let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); + assert_eq!(1, collator.delegation_count, "collator's delegator count was reduced unexpectedly"); assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); roll_to_round_begin(3); assert_events_emitted_match!(Event::NewRound { round: 3, .. }); roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 4 }, - Event::Rewarded { account: 2, rewards: 1 }, - ); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 4 }, Event::Rewarded { account: 2, rewards: 1 },); roll_to_round_begin(4); assert_events_emitted_match!(Event::NewRound { round: 4, .. }); roll_blocks(3); assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); + let collator_snapshot = ParachainStaking::at_stake(ParachainStaking::round().current, 1); assert_eq!( 1, collator_snapshot.delegations.len(), "collator snapshot's delegator count was reduced unexpectedly" ); - assert_eq!( - 20, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); + assert_eq!(20, collator_snapshot.total, "collator snapshot's total was reduced unexpectedly",); }); } @@ -5279,10 +4244,7 @@ fn test_delegator_scheduled_for_revoke_is_rewarded_when_request_cancelled() { scheduled_exit: 3, }); let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); + assert_eq!(1, collator.delegation_count, "collator's delegator count was reduced unexpectedly"); assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); roll_to_round_begin(2); @@ -5292,31 +4254,23 @@ fn test_delegator_scheduled_for_revoke_is_rewarded_when_request_cancelled() { assert_events_emitted_match!(Event::NewRound { round: 4, .. }); roll_blocks(3); assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); + let collator_snapshot = ParachainStaking::at_stake(ParachainStaking::round().current, 1); assert_eq!( 1, collator_snapshot.delegations.len(), "collator snapshot's delegator count was reduced unexpectedly" ); - assert_eq!( - 30, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); + assert_eq!(30, collator_snapshot.total, "collator snapshot's total was reduced unexpectedly",); roll_to_round_begin(5); assert_events_emitted_match!(Event::NewRound { round: 5, .. }); roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 4 }, - Event::Rewarded { account: 2, rewards: 1 }, - ); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 4 }, Event::Rewarded { account: 2, rewards: 1 },); }); } #[test] -fn test_delegator_scheduled_for_bond_decrease_is_rewarded_for_previous_rounds_but_less_for_future() -{ +fn test_delegator_scheduled_for_bond_decrease_is_rewarded_for_previous_rounds_but_less_for_future() { ExtBuilder::default() .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) @@ -5326,11 +4280,7 @@ fn test_delegator_scheduled_for_bond_decrease_is_rewarded_for_previous_rounds_bu // preset rewards for rounds 1, 2 and 3 (1..=3).for_each(|round| set_author(round, 1, 1)); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 10, - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 10,)); assert_events_eq!(Event::DelegationDecreaseScheduled { execute_round: 3, delegator: 2, @@ -5338,38 +4288,25 @@ fn test_delegator_scheduled_for_bond_decrease_is_rewarded_for_previous_rounds_bu amount_to_decrease: 10, }); let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); + assert_eq!(1, collator.delegation_count, "collator's delegator count was reduced unexpectedly"); assert_eq!(40, collator.total_counted, "collator's total was reduced unexpectedly"); roll_to_round_begin(3); assert_events_emitted_match!(Event::NewRound { round: 3, .. }); roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 3 }, - Event::Rewarded { account: 2, rewards: 2 }, - ); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 3 }, Event::Rewarded { account: 2, rewards: 2 },); roll_to_round_begin(4); assert_events_emitted_match!(Event::NewRound { round: 4, .. }); roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 4 }, - Event::Rewarded { account: 2, rewards: 1 }, - ); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 4 }, Event::Rewarded { account: 2, rewards: 1 },); + let collator_snapshot = ParachainStaking::at_stake(ParachainStaking::round().current, 1); assert_eq!( 1, collator_snapshot.delegations.len(), "collator snapshot's delegator count was reduced unexpectedly" ); - assert_eq!( - 30, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); + assert_eq!(30, collator_snapshot.total, "collator snapshot's total was reduced unexpectedly",); }); } @@ -5384,11 +4321,7 @@ fn test_delegator_scheduled_for_bond_decrease_is_rewarded_when_request_cancelled // preset rewards for rounds 2, 3 and 4 (2..=4).for_each(|round| set_author(round, 1, 1)); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 10, - )); + assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 10,)); assert_events_eq!(Event::DelegationDecreaseScheduled { execute_round: 3, delegator: 2, @@ -5396,10 +4329,7 @@ fn test_delegator_scheduled_for_bond_decrease_is_rewarded_when_request_cancelled amount_to_decrease: 10, }); let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); + assert_eq!(1, collator.delegation_count, "collator's delegator count was reduced unexpectedly"); assert_eq!(40, collator.total_counted, "collator's total was reduced unexpectedly"); roll_to_round_begin(2); @@ -5408,29 +4338,19 @@ fn test_delegator_scheduled_for_bond_decrease_is_rewarded_when_request_cancelled roll_to_round_begin(4); assert_events_emitted_match!(Event::NewRound { round: 4, .. }); roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 4 }, - Event::Rewarded { account: 2, rewards: 1 }, - ); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 4 }, Event::Rewarded { account: 2, rewards: 1 },); + let collator_snapshot = ParachainStaking::at_stake(ParachainStaking::round().current, 1); assert_eq!( 1, collator_snapshot.delegations.len(), "collator snapshot's delegator count was reduced unexpectedly" ); - assert_eq!( - 40, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); + assert_eq!(40, collator_snapshot.total, "collator snapshot's total was reduced unexpectedly",); roll_to_round_begin(5); assert_events_emitted_match!(Event::NewRound { round: 5, .. }); roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 3 }, - Event::Rewarded { account: 2, rewards: 2 }, - ); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 3 }, Event::Rewarded { account: 2, rewards: 2 },); }); } @@ -5446,41 +4366,27 @@ fn test_delegator_scheduled_for_leave_is_rewarded_for_previous_rounds_but_not_fo (1..=3).for_each(|round| set_author(round, 1, 1)); assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2),)); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 1, - delegator: 2, - scheduled_exit: 3, - }); + assert_events_eq!(Event::DelegatorExitScheduled { round: 1, delegator: 2, scheduled_exit: 3 }); let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); + assert_eq!(1, collator.delegation_count, "collator's delegator count was reduced unexpectedly"); assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); roll_to_round_begin(3); assert_events_emitted_match!(Event::NewRound { round: 3, .. }); roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 4 }, - Event::Rewarded { account: 2, rewards: 1 }, - ); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 4 }, Event::Rewarded { account: 2, rewards: 1 },); roll_to_round_begin(4); assert_events_emitted_match!(Event::NewRound { round: 4, .. }); roll_blocks(3); assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); + let collator_snapshot = ParachainStaking::at_stake(ParachainStaking::round().current, 1); assert_eq!( 1, collator_snapshot.delegations.len(), "collator snapshot's delegator count was reduced unexpectedly" ); - assert_eq!( - 20, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); + assert_eq!(20, collator_snapshot.total, "collator snapshot's total was reduced unexpectedly",); }); } @@ -5496,16 +4402,9 @@ fn test_delegator_scheduled_for_leave_is_rewarded_when_request_cancelled() { (2..=4).for_each(|round| set_author(round, 1, 1)); assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 1, - delegator: 2, - scheduled_exit: 3, - }); + assert_events_eq!(Event::DelegatorExitScheduled { round: 1, delegator: 2, scheduled_exit: 3 }); let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); + assert_eq!(1, collator.delegation_count, "collator's delegator count was reduced unexpectedly"); assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); roll_to_round_begin(2); @@ -5515,25 +4414,18 @@ fn test_delegator_scheduled_for_leave_is_rewarded_when_request_cancelled() { assert_events_emitted_match!(Event::NewRound { round: 4, .. }); roll_blocks(3); assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); + let collator_snapshot = ParachainStaking::at_stake(ParachainStaking::round().current, 1); assert_eq!( 1, collator_snapshot.delegations.len(), "collator snapshot's delegator count was reduced unexpectedly" ); - assert_eq!( - 30, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); + assert_eq!(30, collator_snapshot.total, "collator snapshot's total was reduced unexpectedly",); roll_to_round_begin(5); assert_events_emitted_match!(Event::NewRound { round: 5, .. }); roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 4 }, - Event::Rewarded { account: 2, rewards: 1 }, - ); + assert_events_eq!(Event::Rewarded { account: 1, rewards: 4 }, Event::Rewarded { account: 2, rewards: 1 },); }); } @@ -5559,11 +4451,7 @@ fn test_delegation_request_exists_returns_true_when_decrease_exists() { .execute_with(|| { >::insert( 1, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], + vec![ScheduledRequest { delegator: 2, when_executable: 3, action: DelegationAction::Decrease(5) }], ); assert!(ParachainStaking::delegation_request_exists(&1, &2)); }); @@ -5579,11 +4467,7 @@ fn test_delegation_request_exists_returns_true_when_revoke_exists() { .execute_with(|| { >::insert( 1, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Revoke(5), - }], + vec![ScheduledRequest { delegator: 2, when_executable: 3, action: DelegationAction::Revoke(5) }], ); assert!(ParachainStaking::delegation_request_exists(&1, &2)); }); @@ -5611,11 +4495,7 @@ fn test_delegation_request_revoke_exists_returns_false_when_decrease_exists() { .execute_with(|| { >::insert( 1, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], + vec![ScheduledRequest { delegator: 2, when_executable: 3, action: DelegationAction::Decrease(5) }], ); assert!(!ParachainStaking::delegation_request_revoke_exists(&1, &2)); }); @@ -5631,11 +4511,7 @@ fn test_delegation_request_revoke_exists_returns_true_when_revoke_exists() { .execute_with(|| { >::insert( 1, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Revoke(5), - }], + vec![ScheduledRequest { delegator: 2, when_executable: 3, action: DelegationAction::Revoke(5) }], ); assert!(ParachainStaking::delegation_request_revoke_exists(&1, &2)); }); @@ -5643,107 +4519,63 @@ fn test_delegation_request_revoke_exists_returns_true_when_revoke_exists() { #[test] fn test_hotfix_remove_delegation_requests_exited_candidates_cleans_up() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // invalid state - >::insert( - 2, - Vec::>::new(), - ); - >::insert( - 3, - Vec::>::new(), - ); - assert_ok!(ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( - RuntimeOrigin::signed(1), - vec![2, 3, 4] // 4 does not exist, but is OK for idempotency - )); + ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { + // invalid state + >::insert(2, Vec::>::new()); + >::insert(3, Vec::>::new()); + assert_ok!(ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( + RuntimeOrigin::signed(1), + vec![2, 3, 4] // 4 does not exist, but is OK for idempotency + )); - assert!(!>::contains_key(2)); - assert!(!>::contains_key(3)); - }); + assert!(!>::contains_key(2)); + assert!(!>::contains_key(3)); + }); } #[test] fn test_hotfix_remove_delegation_requests_exited_candidates_cleans_up_only_specified_keys() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // invalid state - >::insert( - 2, - Vec::>::new(), - ); - >::insert( - 3, - Vec::>::new(), - ); - assert_ok!(ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( - RuntimeOrigin::signed(1), - vec![2] - )); + ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { + // invalid state + >::insert(2, Vec::>::new()); + >::insert(3, Vec::>::new()); + assert_ok!(ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( + RuntimeOrigin::signed(1), + vec![2] + )); - assert!(!>::contains_key(2)); - assert!(>::contains_key(3)); - }); + assert!(!>::contains_key(2)); + assert!(>::contains_key(3)); + }); } #[test] fn test_hotfix_remove_delegation_requests_exited_candidates_errors_when_requests_not_empty() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // invalid state - >::insert( - 2, - Vec::>::new(), - ); - >::insert( - 3, - vec![ScheduledRequest { - delegator: 10, - when_executable: 1, - action: DelegationAction::Revoke(10), - }], - ); + ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { + // invalid state + >::insert(2, Vec::>::new()); + >::insert( + 3, + vec![ScheduledRequest { delegator: 10, when_executable: 1, action: DelegationAction::Revoke(10) }], + ); - assert_noop!( - ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( - RuntimeOrigin::signed(1), - vec![2, 3] - ), - >::CandidateNotLeaving, - ); - }); + assert_noop!( + ParachainStaking::hotfix_remove_delegation_requests_exited_candidates(RuntimeOrigin::signed(1), vec![2, 3]), + >::CandidateNotLeaving, + ); + }); } #[test] fn test_hotfix_remove_delegation_requests_exited_candidates_errors_when_candidate_not_exited() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // invalid state - >::insert( - 1, - Vec::>::new(), - ); - assert_noop!( - ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( - RuntimeOrigin::signed(1), - vec![1] - ), - >::CandidateNotLeaving, - ); - }); + ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { + // invalid state + >::insert(1, Vec::>::new()); + assert_noop!( + ParachainStaking::hotfix_remove_delegation_requests_exited_candidates(RuntimeOrigin::signed(1), vec![1]), + >::CandidateNotLeaving, + ); + }); } #[test] @@ -5778,21 +4610,13 @@ fn revoke_last_removes_lock() { // schedule and remove one... assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(3), 1)); roll_to_round_begin(3); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(3), - 3, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(3), 3, 1)); assert_eq!(crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), Some(25)); // schedule and remove the other... assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(3), 2)); roll_to_round_begin(5); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(3), - 3, - 2 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(3), 3, 2)); assert_eq!(crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), None); }); } @@ -5818,11 +4642,7 @@ fn test_delegator_with_deprecated_status_leaving_can_schedule_leave_delegators_a assert!(>::get(1) .iter() .any(|r| r.delegator == 2 && matches!(r.action, DelegationAction::Revoke(_)))); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 1, - delegator: 2, - scheduled_exit: 3 - }); + assert_events_eq!(Event::DelegatorExitScheduled { round: 1, delegator: 2, scheduled_exit: 3 }); let state = >::get(2); assert!(matches!(state.unwrap().status, DelegatorStatus::Active)); @@ -6034,18 +4854,8 @@ fn test_set_auto_compound_removes_if_auto_compound_zero_percent() { ) .set_storage(&1); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::zero(), - 1, - 1, - )); - assert_events_emitted!(Event::AutoCompoundSet { - candidate: 1, - delegator: 2, - value: Percent::zero(), - }); + assert_ok!(ParachainStaking::set_auto_compound(RuntimeOrigin::signed(2), 1, Percent::zero(), 1, 1,)); + assert_events_emitted!(Event::AutoCompoundSet { candidate: 1, delegator: 2, value: Percent::zero() }); assert_eq!(0, ParachainStaking::auto_compounding_delegations(&1).len(),); }); } @@ -6074,21 +4884,13 @@ fn test_execute_revoke_delegation_removes_auto_compounding_from_state_for_delega )); assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); + assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), + !ParachainStaking::auto_compounding_delegations(&1).iter().any(|x| x.delegator == 2), "delegation auto-compound config was not removed" ); assert!( - ParachainStaking::auto_compounding_delegations(&3) - .iter() - .any(|x| x.delegator == 2), + ParachainStaking::auto_compounding_delegations(&3).iter().any(|x| x.delegator == 2), "delegation auto-compound config was erroneously removed" ); }); @@ -6122,15 +4924,11 @@ fn test_execute_leave_delegators_removes_auto_compounding_state() { assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2,)); assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), + !ParachainStaking::auto_compounding_delegations(&1).iter().any(|x| x.delegator == 2), "delegation auto-compound config was not removed" ); assert!( - !ParachainStaking::auto_compounding_delegations(&3) - .iter() - .any(|x| x.delegator == 2), + !ParachainStaking::auto_compounding_delegations(&3).iter().any(|x| x.delegator == 2), "delegation auto-compound config was not removed" ); }); @@ -6169,15 +4967,11 @@ fn test_execute_leave_delegators_with_deprecated_status_leaving_removes_auto_com assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2,)); assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), + !ParachainStaking::auto_compounding_delegations(&1).iter().any(|x| x.delegator == 2), "delegation auto-compound config was not removed" ); assert!( - !ParachainStaking::auto_compounding_delegations(&3) - .iter() - .any(|x| x.delegator == 2), + !ParachainStaking::auto_compounding_delegations(&3).iter().any(|x| x.delegator == 2), "delegation auto-compound config was not removed" ); }); @@ -6211,15 +5005,11 @@ fn test_execute_leave_candidates_removes_auto_compounding_state() { assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 1,)); assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), + !ParachainStaking::auto_compounding_delegations(&1).iter().any(|x| x.delegator == 2), "delegation auto-compound config was not removed" ); assert!( - ParachainStaking::auto_compounding_delegations(&3) - .iter() - .any(|x| x.delegator == 2), + ParachainStaking::auto_compounding_delegations(&3).iter().any(|x| x.delegator == 2), "delegation auto-compound config was erroneously removed" ); }); @@ -6267,9 +5057,7 @@ fn test_delegation_kicked_from_bottom_delegation_removes_auto_compounding_state( assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(10), 1, 20, 8, 0)); assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), + !ParachainStaking::auto_compounding_delegations(&1).iter().any(|x| x.delegator == 2), "delegation auto-compound config was not removed" ); }); @@ -6306,12 +5094,7 @@ fn test_rewards_do_not_auto_compound_on_payment_if_delegation_scheduled_revoke_e assert_events_eq!( Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 500 }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 1, - total_balance: 500, - }, + Event::NewRound { starting_block: 15, round: 4, selected_collators_number: 1, total_balance: 500 }, ); roll_blocks(1); @@ -6360,12 +5143,7 @@ fn test_rewards_auto_compound_on_payment_as_per_auto_compound_config() { assert_events_eq!( Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 900 }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 1, - total_balance: 900, - }, + Event::NewRound { starting_block: 15, round: 4, selected_collators_number: 1, total_balance: 900 }, ); roll_blocks(1); @@ -6468,11 +5246,8 @@ fn test_delegate_with_auto_compound_fails_if_invalid_candidate_auto_compounding_ #[test] fn test_delegate_with_auto_compound_sets_auto_compound_config() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { + ExtBuilder::default().with_balances(vec![(1, 30), (2, 25)]).with_candidates(vec![(1, 30)]).build().execute_with( + || { assert_ok!(ParachainStaking::delegate_with_auto_compound( RuntimeOrigin::signed(2), 1, @@ -6493,16 +5268,14 @@ fn test_delegate_with_auto_compound_sets_auto_compound_config() { vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(50) }], ParachainStaking::auto_compounding_delegations(&1).into_inner(), ); - }); + }, + ); } #[test] fn test_delegate_with_auto_compound_skips_storage_but_emits_event_for_zero_auto_compound() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { + ExtBuilder::default().with_balances(vec![(1, 30), (2, 10)]).with_candidates(vec![(1, 30)]).build().execute_with( + || { assert_ok!(ParachainStaking::delegate_with_auto_compound( RuntimeOrigin::signed(2), 1, @@ -6520,16 +5293,14 @@ fn test_delegate_with_auto_compound_skips_storage_but_emits_event_for_zero_auto_ delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, auto_compound: Percent::zero(), }); - }); + }, + ); } #[test] fn test_delegate_with_auto_compound_reserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { + ExtBuilder::default().with_balances(vec![(1, 30), (2, 10)]).with_candidates(vec![(1, 30)]).build().execute_with( + || { assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); assert_ok!(ParachainStaking::delegate_with_auto_compound( RuntimeOrigin::signed(2), @@ -6541,16 +5312,14 @@ fn test_delegate_with_auto_compound_reserves_balance() { 0, )); assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - }); + }, + ); } #[test] fn test_delegate_with_auto_compound_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { + ExtBuilder::default().with_balances(vec![(1, 30), (2, 10)]).with_candidates(vec![(1, 30)]).build().execute_with( + || { assert!(ParachainStaking::delegator_state(2).is_none()); assert_ok!(ParachainStaking::delegate_with_auto_compound( RuntimeOrigin::signed(2), @@ -6561,26 +5330,21 @@ fn test_delegate_with_auto_compound_updates_delegator_state() { 0, 0 )); - let delegator_state = - ParachainStaking::delegator_state(2).expect("just delegated => exists"); + let delegator_state = ParachainStaking::delegator_state(2).expect("just delegated => exists"); assert_eq!(delegator_state.total(), 10); assert_eq!(delegator_state.delegations.0[0].owner, 1); assert_eq!(delegator_state.delegations.0[0].amount, 10); - }); + }, + ); } #[test] fn test_delegate_with_auto_compound_updates_collator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - let candidate_state = - ParachainStaking::candidate_info(1).expect("registered in genesis"); + ExtBuilder::default().with_balances(vec![(1, 30), (2, 10)]).with_candidates(vec![(1, 30)]).build().execute_with( + || { + let candidate_state = ParachainStaking::candidate_info(1).expect("registered in genesis"); assert_eq!(candidate_state.total_counted, 30); - let top_delegations = - ParachainStaking::top_delegations(1).expect("registered in genesis"); + let top_delegations = ParachainStaking::top_delegations(1).expect("registered in genesis"); assert!(top_delegations.delegations.is_empty()); assert!(top_delegations.total.is_zero()); assert_ok!(ParachainStaking::delegate_with_auto_compound( @@ -6592,34 +5356,30 @@ fn test_delegate_with_auto_compound_updates_collator_state() { 0, 0 )); - let candidate_state = - ParachainStaking::candidate_info(1).expect("just delegated => exists"); + let candidate_state = ParachainStaking::candidate_info(1).expect("just delegated => exists"); assert_eq!(candidate_state.total_counted, 40); - let top_delegations = - ParachainStaking::top_delegations(1).expect("just delegated => exists"); + let top_delegations = ParachainStaking::top_delegations(1).expect("just delegated => exists"); assert_eq!(top_delegations.delegations[0].owner, 2); assert_eq!(top_delegations.delegations[0].amount, 10); assert_eq!(top_delegations.total, 10); - }); + }, + ); } #[test] fn test_delegate_with_auto_compound_can_delegate_immediately_after_other_join_candidates() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 20, 0)); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 20, - Percent::from_percent(50), - 0, - 0, - 0 - )); - }); + ExtBuilder::default().with_balances(vec![(1, 20), (2, 20)]).build().execute_with(|| { + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 20, 0)); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 20, + Percent::from_percent(50), + 0, + 0, + 0 + )); + }); } #[test] @@ -6725,11 +5485,7 @@ fn test_delegate_with_auto_compound_can_delegate_if_greater_than_lowest_bottom() 0, 0 )); - assert_events_emitted!(Event::DelegationKicked { - delegator: 10, - candidate: 1, - unstaked_amount: 10 - }); + assert_events_emitted!(Event::DelegationKicked { delegator: 10, candidate: 1, unstaked_amount: 10 }); assert_events_emitted!(Event::DelegatorLeft { delegator: 10, unstaked_amount: 10 }); }); } @@ -6903,11 +5659,9 @@ fn test_on_initialize_weights() { // TODO: this should be the same as >. I believe this relates to // genesis building let num_avg_delegations = 8; - expected_weight += PalletWeights::::select_top_candidates( - >::get(), - num_avg_delegations, - ) - .ref_time(); + expected_weight += + PalletWeights::::select_top_candidates(>::get(), num_avg_delegations) + .ref_time(); // Round and Staked writes, done in on-round-change code block inside on_initialize() expected_weight += RocksDbWeight::get().reads_writes(0, 2).ref_time(); // more reads/writes manually accounted for for on_finalize diff --git a/pallets/parachain-staking/src/traits.rs b/pallets/parachain-staking/src/traits.rs index 2b30b04cc..746d193e2 100644 --- a/pallets/parachain-staking/src/traits.rs +++ b/pallets/parachain-staking/src/traits.rs @@ -19,18 +19,10 @@ use frame_support::pallet_prelude::Weight; pub trait OnCollatorPayout { - fn on_collator_payout( - for_round: crate::RoundIndex, - collator_id: AccountId, - amount: Balance, - ) -> Weight; + fn on_collator_payout(for_round: crate::RoundIndex, collator_id: AccountId, amount: Balance) -> Weight; } impl OnCollatorPayout for () { - fn on_collator_payout( - _for_round: crate::RoundIndex, - _collator_id: AccountId, - _amount: Balance, - ) -> Weight { + fn on_collator_payout(_for_round: crate::RoundIndex, _collator_id: AccountId, _amount: Balance) -> Weight { Weight::zero() } } diff --git a/pallets/parachain-staking/src/types.rs b/pallets/parachain-staking/src/types.rs index 1ef686b2f..18b98c8c4 100644 --- a/pallets/parachain-staking/src/types.rs +++ b/pallets/parachain-staking/src/types.rs @@ -17,9 +17,9 @@ //! Types for parachain-staking use crate::{ - auto_compound::AutoCompoundDelegations, set::OrderedSet, BalanceOf, BottomDelegations, - CandidateInfo, Config, DelegatorState, Error, Event, Pallet, Round, RoundIndex, TopDelegations, - Total, COLLATOR_LOCK_ID, DELEGATOR_LOCK_ID, + auto_compound::AutoCompoundDelegations, set::OrderedSet, BalanceOf, BottomDelegations, CandidateInfo, Config, + DelegatorState, Error, Event, Pallet, Round, RoundIndex, TopDelegations, Total, COLLATOR_LOCK_ID, + DELEGATOR_LOCK_ID, }; use frame_support::{ pallet_prelude::*, @@ -244,12 +244,11 @@ impl Default for Delegations { } } -impl - Delegations -{ +impl Delegations { pub fn sort_greatest_to_least(&mut self) { self.delegations.sort_by(|a, b| b.amount.cmp(&a.amount)); } + /// Insert sorted greatest to least and increase .total accordingly /// Insertion respects first come first serve so new delegations are pushed after existing /// delegations if the amount is the same @@ -283,6 +282,7 @@ impl self.delegations.insert(i, delegation), } } + /// Return the capacity status for top delegations pub fn top_capacity(&self) -> CapacityStatus { match &self.delegations { @@ -291,19 +291,21 @@ impl CapacityStatus::Partial, } } + /// Return the capacity status for bottom delegations pub fn bottom_capacity(&self) -> CapacityStatus { match &self.delegations { - x if x.len() as u32 >= T::MaxBottomDelegationsPerCandidate::get() => - CapacityStatus::Full, + x if x.len() as u32 >= T::MaxBottomDelegationsPerCandidate::get() => CapacityStatus::Full, x if x.is_empty() => CapacityStatus::Empty, _ => CapacityStatus::Partial, } } + /// Return last delegation amount without popping the delegation pub fn lowest_delegation_amount(&self) -> Balance { self.delegations.last().map(|x| x.amount).unwrap_or(Balance::zero()) } + /// Return highest delegation amount pub fn highest_delegation_amount(&self) -> Balance { self.delegations.first().map(|x| x.amount).unwrap_or(Balance::zero()) @@ -371,12 +373,15 @@ impl< status: CollatorStatus::Active, } } + pub fn is_active(&self) -> bool { matches!(self.status, CollatorStatus::Active) } + pub fn is_leaving(&self) -> bool { matches!(self.status, CollatorStatus::Leaving(_)) } + pub fn schedule_leave(&mut self) -> Result<(RoundIndex, RoundIndex), DispatchError> { ensure!(!self.is_leaving(), Error::::CandidateAlreadyLeaving); let now = >::get().current; @@ -384,6 +389,7 @@ impl< self.status = CollatorStatus::Leaving(when); Ok((now, when)) } + pub fn can_leave(&self) -> DispatchResult { if let CollatorStatus::Leaving(when) = self.status { ensure!(>::get().current >= when, Error::::CandidateCannotLeaveYet); @@ -392,20 +398,20 @@ impl< Err(Error::::CandidateNotLeaving.into()) } } + pub fn go_offline(&mut self) { self.status = CollatorStatus::Idle; } + pub fn go_online(&mut self) { self.status = CollatorStatus::Active; } + pub fn bond_more(&mut self, who: T::AccountId, more: Balance) -> DispatchResult where BalanceOf: From, { - ensure!( - >::get_collator_stakable_free_balance(&who) >= more.into(), - Error::::InsufficientBalance - ); + ensure!(>::get_collator_stakable_free_balance(&who) >= more.into(), Error::::InsufficientBalance); let new_total = >::get().saturating_add(more.into()); >::put(new_total); self.bond = self.bond.saturating_add(more); @@ -418,12 +424,10 @@ impl< }); Ok(()) } + /// Schedule executable decrease of collator candidate self bond /// Returns the round at which the collator can execute the pending request - pub fn schedule_bond_less( - &mut self, - less: Balance, - ) -> Result + pub fn schedule_bond_less(&mut self, less: Balance) -> Result where BalanceOf: Into, { @@ -431,14 +435,12 @@ impl< ensure!(self.request.is_none(), Error::::PendingCandidateRequestAlreadyExists); // ensure bond above min after decrease ensure!(self.bond > less, Error::::CandidateBondBelowMin); - ensure!( - self.bond - less >= T::MinCandidateStk::get().into(), - Error::::CandidateBondBelowMin - ); + ensure!(self.bond - less >= T::MinCandidateStk::get().into(), Error::::CandidateBondBelowMin); let when_executable = >::get().current + T::CandidateBondLessDelay::get(); self.request = Some(CandidateBondLessRequest { amount: less, when_executable }); Ok(when_executable) } + /// Execute pending request to decrease the collator self bond /// Returns the event to be emitted pub fn execute_bond_less(&mut self, who: T::AccountId) -> DispatchResult @@ -446,10 +448,7 @@ impl< BalanceOf: From, { let request = self.request.ok_or(Error::::PendingCandidateRequestsDNE)?; - ensure!( - request.when_executable <= >::get().current, - Error::::PendingCandidateRequestNotDueYet - ); + ensure!(request.when_executable <= >::get().current, Error::::PendingCandidateRequestNotDueYet); let new_total_staked = >::get().saturating_sub(request.amount.into()); >::put(new_total_staked); // Arithmetic assumptions are self.bond > less && self.bond - less > CollatorMinBond @@ -471,6 +470,7 @@ impl< Pallet::::deposit_event(event); Ok(()) } + /// Cancel candidate bond less request pub fn cancel_bond_less(&mut self, who: T::AccountId) -> DispatchResult where @@ -486,6 +486,7 @@ impl< Pallet::::deposit_event(event); Ok(()) } + /// Reset top delegations metadata pub fn reset_top_data( &mut self, @@ -505,18 +506,17 @@ impl< Pallet::::update_active(candidate, self.total_counted.into()); } } + /// Reset bottom delegations metadata - pub fn reset_bottom_data( - &mut self, - bottom_delegations: &Delegations>, - ) where + pub fn reset_bottom_data(&mut self, bottom_delegations: &Delegations>) + where BalanceOf: Into, { self.lowest_bottom_delegation_amount = bottom_delegations.lowest_delegation_amount().into(); - self.highest_bottom_delegation_amount = - bottom_delegations.highest_delegation_amount().into(); + self.highest_bottom_delegation_amount = bottom_delegations.highest_delegation_amount().into(); self.bottom_capacity = bottom_delegations.bottom_capacity::(); } + /// Add delegation /// Returns whether delegator was added and an optional negative total counted remainder /// for if a bottom delegation was kicked @@ -561,6 +561,7 @@ impl< }; Ok((delegator_added, less_total_staked)) } + /// Add delegation to top delegation /// Returns Option /// Only call if lowest top delegation is less than delegation.amount || !top_full @@ -573,14 +574,13 @@ impl< BalanceOf: Into + From, { let mut less_total_staked = None; - let mut top_delegations = >::get(candidate) - .expect("CandidateInfo existence => TopDelegations existence"); + let mut top_delegations = + >::get(candidate).expect("CandidateInfo existence => TopDelegations existence"); let max_top_delegations_per_candidate = T::MaxTopDelegationsPerCandidate::get(); if top_delegations.delegations.len() as u32 == max_top_delegations_per_candidate { // pop lowest top delegation let new_bottom_delegation = top_delegations.delegations.pop().expect(""); - top_delegations.total = - top_delegations.total.saturating_sub(new_bottom_delegation.amount); + top_delegations.total = top_delegations.total.saturating_sub(new_bottom_delegation.amount); if matches!(self.bottom_capacity, CapacityStatus::Full) { less_total_staked = Some(self.lowest_bottom_delegation_amount); } @@ -597,6 +597,7 @@ impl< >::insert(candidate, top_delegations); less_total_staked } + /// Add delegation to bottom delegations /// Check before call that if capacity is full, inserted delegation is higher than lowest /// bottom delegation (and if so, need to adjust the total storage item) @@ -609,57 +610,52 @@ impl< ) where BalanceOf: Into + From, { - let mut bottom_delegations = >::get(candidate) - .expect("CandidateInfo existence => BottomDelegations existence"); + let mut bottom_delegations = + >::get(candidate).expect("CandidateInfo existence => BottomDelegations existence"); // if bottom is full, kick the lowest bottom (which is expected to be lower than input // as per check) - let increase_delegation_count = if bottom_delegations.delegations.len() as u32 == - T::MaxBottomDelegationsPerCandidate::get() - { - let lowest_bottom_to_be_kicked = bottom_delegations - .delegations - .pop() - .expect("if at full capacity (>0), then >0 bottom delegations exist; qed"); - // EXPECT lowest_bottom_to_be_kicked.amount < delegation.amount enforced by caller - // if lowest_bottom_to_be_kicked.amount == delegation.amount, we will still kick - // the lowest bottom to enforce first come first served - bottom_delegations.total = - bottom_delegations.total.saturating_sub(lowest_bottom_to_be_kicked.amount); - // update delegator state - // total staked is updated via propagation of lowest bottom delegation amount prior - // to call - let mut delegator_state = >::get(&lowest_bottom_to_be_kicked.owner) - .expect("Delegation existence => DelegatorState existence"); - let leaving = delegator_state.delegations.0.len() == 1usize; - delegator_state.rm_delegation::(candidate); - >::delegation_remove_request_with_state( - candidate, - &lowest_bottom_to_be_kicked.owner, - &mut delegator_state, - ); - >::remove_auto_compound( - candidate, - &lowest_bottom_to_be_kicked.owner, - ); + let increase_delegation_count = + if bottom_delegations.delegations.len() as u32 == T::MaxBottomDelegationsPerCandidate::get() { + let lowest_bottom_to_be_kicked = bottom_delegations + .delegations + .pop() + .expect("if at full capacity (>0), then >0 bottom delegations exist; qed"); + // EXPECT lowest_bottom_to_be_kicked.amount < delegation.amount enforced by caller + // if lowest_bottom_to_be_kicked.amount == delegation.amount, we will still kick + // the lowest bottom to enforce first come first served + bottom_delegations.total = bottom_delegations.total.saturating_sub(lowest_bottom_to_be_kicked.amount); + // update delegator state + // total staked is updated via propagation of lowest bottom delegation amount prior + // to call + let mut delegator_state = >::get(&lowest_bottom_to_be_kicked.owner) + .expect("Delegation existence => DelegatorState existence"); + let leaving = delegator_state.delegations.0.len() == 1usize; + delegator_state.rm_delegation::(candidate); + >::delegation_remove_request_with_state( + candidate, + &lowest_bottom_to_be_kicked.owner, + &mut delegator_state, + ); + >::remove_auto_compound(candidate, &lowest_bottom_to_be_kicked.owner); - Pallet::::deposit_event(Event::DelegationKicked { - delegator: lowest_bottom_to_be_kicked.owner.clone(), - candidate: candidate.clone(), - unstaked_amount: lowest_bottom_to_be_kicked.amount, - }); - if leaving { - >::remove(&lowest_bottom_to_be_kicked.owner); - Pallet::::deposit_event(Event::DelegatorLeft { - delegator: lowest_bottom_to_be_kicked.owner, + Pallet::::deposit_event(Event::DelegationKicked { + delegator: lowest_bottom_to_be_kicked.owner.clone(), + candidate: candidate.clone(), unstaked_amount: lowest_bottom_to_be_kicked.amount, }); + if leaving { + >::remove(&lowest_bottom_to_be_kicked.owner); + Pallet::::deposit_event(Event::DelegatorLeft { + delegator: lowest_bottom_to_be_kicked.owner, + unstaked_amount: lowest_bottom_to_be_kicked.amount, + }); + } else { + >::insert(&lowest_bottom_to_be_kicked.owner, delegator_state); + } + false } else { - >::insert(&lowest_bottom_to_be_kicked.owner, delegator_state); - } - false - } else { - !bumped_from_top - }; + !bumped_from_top + }; // only increase delegation count if new bottom delegation (1) doesn't come from top && // (2) doesn't pop the lowest delegation from the bottom if increase_delegation_count { @@ -669,6 +665,7 @@ impl< self.reset_bottom_data::(&bottom_delegations); >::insert(candidate, bottom_delegations); } + /// Remove delegation /// Removes from top if amount is above lowest top or top is not full /// Return Ok(if_total_counted_changed) @@ -683,8 +680,7 @@ impl< { let amount_geq_lowest_top = amount >= self.lowest_top_delegation_amount; let top_is_not_full = !matches!(self.top_capacity, CapacityStatus::Full); - let lowest_top_eq_highest_bottom = - self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; + let lowest_top_eq_highest_bottom = self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); if top_is_not_full || (amount_geq_lowest_top && !lowest_top_eq_highest_bottom) { self.rm_top_delegation::(candidate, delegator) @@ -700,6 +696,7 @@ impl< self.rm_bottom_delegation::(candidate, delegator) } } + /// Remove top delegation, bumps top bottom delegation if exists pub fn rm_top_delegation( &mut self, @@ -711,8 +708,8 @@ impl< { let old_total_counted = self.total_counted; // remove top delegation - let mut top_delegations = >::get(candidate) - .expect("CandidateInfo exists => TopDelegations exists"); + let mut top_delegations = + >::get(candidate).expect("CandidateInfo exists => TopDelegations exists"); let mut actual_amount_option: Option> = None; top_delegations.delegations = top_delegations .delegations @@ -735,8 +732,7 @@ impl< >::get(candidate).expect("bottom is nonempty as just checked"); // expect already stored greatest to least by bond amount let highest_bottom_delegation = bottom_delegations.delegations.remove(0); - bottom_delegations.total = - bottom_delegations.total.saturating_sub(highest_bottom_delegation.amount); + bottom_delegations.total = bottom_delegations.total.saturating_sub(highest_bottom_delegation.amount); self.reset_bottom_data::(&bottom_delegations); >::insert(candidate, bottom_delegations); // insert highest bottom into top delegations @@ -749,6 +745,7 @@ impl< // return whether total counted changed Ok(old_total_counted == self.total_counted) } + /// Remove bottom delegation /// Returns if_total_counted_changed: bool pub fn rm_bottom_delegation( @@ -760,8 +757,8 @@ impl< BalanceOf: Into, { // remove bottom delegation - let mut bottom_delegations = >::get(candidate) - .expect("CandidateInfo exists => BottomDelegations exists"); + let mut bottom_delegations = + >::get(candidate).expect("CandidateInfo exists => BottomDelegations exists"); let mut actual_amount_option: Option> = None; bottom_delegations.delegations = bottom_delegations .delegations @@ -784,6 +781,7 @@ impl< >::insert(candidate, bottom_delegations); Ok(false) } + /// Increase delegation amount pub fn increase_delegation( &mut self, @@ -795,8 +793,7 @@ impl< where BalanceOf: Into + From, { - let lowest_top_eq_highest_bottom = - self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; + let lowest_top_eq_highest_bottom = self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; let bond_geq_lowest_top = bond.into() >= self.lowest_top_delegation_amount; let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); if bond_geq_lowest_top && !lowest_top_eq_highest_bottom { @@ -815,6 +812,7 @@ impl< self.increase_bottom_delegation::(candidate, delegator, bond, more) } } + /// Increase top delegation pub fn increase_top_delegation( &mut self, @@ -825,8 +823,8 @@ impl< where BalanceOf: Into + From, { - let mut top_delegations = >::get(candidate) - .expect("CandidateInfo exists => TopDelegations exists"); + let mut top_delegations = + >::get(candidate).expect("CandidateInfo exists => TopDelegations exists"); let mut in_top = false; top_delegations.delegations = top_delegations .delegations @@ -849,6 +847,7 @@ impl< >::insert(candidate, top_delegations); Ok(true) } + /// Increase bottom delegation pub fn increase_bottom_delegation( &mut self, @@ -860,11 +859,9 @@ impl< where BalanceOf: Into + From, { - let mut bottom_delegations = - >::get(candidate).ok_or(Error::::CandidateDNE)?; + let mut bottom_delegations = >::get(candidate).ok_or(Error::::CandidateDNE)?; let mut delegation_option: Option>> = None; - let in_top_after = if (bond.saturating_add(more)).into() > self.lowest_top_delegation_amount - { + let in_top_after = if (bond.saturating_add(more)).into() > self.lowest_top_delegation_amount { // bump it from bottom bottom_delegations.delegations = bottom_delegations .delegations @@ -874,10 +871,8 @@ impl< if d.owner != delegator { true } else { - delegation_option = Some(Bond { - owner: d.owner.clone(), - amount: d.amount.saturating_add(more), - }); + delegation_option = + Some(Bond { owner: d.owner.clone(), amount: d.amount.saturating_add(more) }); false } }) @@ -885,17 +880,14 @@ impl< let delegation = delegation_option.ok_or(Error::::DelegationDNE)?; bottom_delegations.total = bottom_delegations.total.saturating_sub(bond); // add it to top - let mut top_delegations = >::get(candidate) - .expect("CandidateInfo existence => TopDelegations existence"); + let mut top_delegations = + >::get(candidate).expect("CandidateInfo existence => TopDelegations existence"); // if top is full, pop lowest top if matches!(top_delegations.top_capacity::(), CapacityStatus::Full) { // pop lowest top delegation - let new_bottom_delegation = top_delegations - .delegations - .pop() - .expect("Top capacity full => Exists at least 1 top delegation"); - top_delegations.total = - top_delegations.total.saturating_sub(new_bottom_delegation.amount); + let new_bottom_delegation = + top_delegations.delegations.pop().expect("Top capacity full => Exists at least 1 top delegation"); + top_delegations.total = top_delegations.total.saturating_sub(new_bottom_delegation.amount); bottom_delegations.insert_sorted_greatest_to_least(new_bottom_delegation); } // insert into top @@ -928,6 +920,7 @@ impl< >::insert(candidate, bottom_delegations); Ok(in_top_after) } + /// Decrease delegation pub fn decrease_delegation( &mut self, @@ -939,8 +932,7 @@ impl< where BalanceOf: Into + From, { - let lowest_top_eq_highest_bottom = - self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; + let lowest_top_eq_highest_bottom = self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; let bond_geq_lowest_top = bond >= self.lowest_top_delegation_amount; let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); if bond_geq_lowest_top && !lowest_top_eq_highest_bottom { @@ -949,8 +941,7 @@ impl< } else if bond_geq_lowest_top && lowest_top_eq_highest_bottom { // update top but if error then update bottom (because could be in bottom because // lowest_top_eq_highest_bottom) - let result = - self.decrease_top_delegation::(candidate, delegator.clone(), bond.into(), less); + let result = self.decrease_top_delegation::(candidate, delegator.clone(), bond.into(), less); if result == Err(delegation_dne_err) { self.decrease_bottom_delegation::(candidate, delegator, less) } else { @@ -960,6 +951,7 @@ impl< self.decrease_bottom_delegation::(candidate, delegator, less) } } + /// Decrease top delegation pub fn decrease_top_delegation( &mut self, @@ -976,10 +968,9 @@ impl< let bond_after_less_than_highest_bottom = bond.saturating_sub(less).into() < self.highest_bottom_delegation_amount; // The top delegations is full and the bottom delegations has at least one delegation - let full_top_and_nonempty_bottom = matches!(self.top_capacity, CapacityStatus::Full) && - !matches!(self.bottom_capacity, CapacityStatus::Empty); - let mut top_delegations = - >::get(candidate).ok_or(Error::::CandidateDNE)?; + let full_top_and_nonempty_bottom = + matches!(self.top_capacity, CapacityStatus::Full) && !matches!(self.bottom_capacity, CapacityStatus::Empty); + let mut top_delegations = >::get(candidate).ok_or(Error::::CandidateDNE)?; let in_top_after = if bond_after_less_than_highest_bottom && full_top_and_nonempty_bottom { let mut delegation_option: Option>> = None; // take delegation from top @@ -992,21 +983,18 @@ impl< true } else { top_delegations.total = top_delegations.total.saturating_sub(d.amount); - delegation_option = Some(Bond { - owner: d.owner.clone(), - amount: d.amount.saturating_sub(less), - }); + delegation_option = + Some(Bond { owner: d.owner.clone(), amount: d.amount.saturating_sub(less) }); false } }) .collect(); let delegation = delegation_option.ok_or(Error::::DelegationDNE)?; // pop highest bottom by reverse and popping - let mut bottom_delegations = >::get(candidate) - .expect("CandidateInfo existence => BottomDelegations existence"); + let mut bottom_delegations = + >::get(candidate).expect("CandidateInfo existence => BottomDelegations existence"); let highest_bottom_delegation = bottom_delegations.delegations.remove(0); - bottom_delegations.total = - bottom_delegations.total.saturating_sub(highest_bottom_delegation.amount); + bottom_delegations.total = bottom_delegations.total.saturating_sub(highest_bottom_delegation.amount); // insert highest bottom into top top_delegations.insert_sorted_greatest_to_least(highest_bottom_delegation); // insert previous top into bottom @@ -1039,6 +1027,7 @@ impl< >::insert(candidate, top_delegations); Ok(in_top_after) } + /// Decrease bottom delegation pub fn decrease_bottom_delegation( &mut self, @@ -1049,8 +1038,8 @@ impl< where BalanceOf: Into, { - let mut bottom_delegations = >::get(candidate) - .expect("CandidateInfo exists => BottomDelegations exists"); + let mut bottom_delegations = + >::get(candidate).expect("CandidateInfo exists => BottomDelegations exists"); let mut in_bottom = false; bottom_delegations.delegations = bottom_delegations .delegations @@ -1118,12 +1107,7 @@ pub enum DelegatorAdded { impl< A: Ord + Clone + sp_std::fmt::Debug, - B: AtLeast32BitUnsigned - + Ord - + Copy - + sp_std::ops::AddAssign - + sp_std::ops::SubAssign - + sp_std::fmt::Debug, + B: AtLeast32BitUnsigned + Ord + Copy + sp_std::ops::AddAssign + sp_std::ops::SubAssign + sp_std::fmt::Debug, > CollatorCandidate { pub fn is_active(&self) -> bool { @@ -1138,11 +1122,7 @@ impl From> for CollatorSnapshot delegations: other .top_delegations .into_iter() - .map(|d| BondWithAutoCompound { - owner: d.owner, - amount: d.amount, - auto_compound: Percent::zero(), - }) + .map(|d| BondWithAutoCompound { owner: d.owner, amount: d.amount, auto_compound: Percent::zero() }) .collect(), total: other.total_counted, } @@ -1281,6 +1261,7 @@ impl< false } } + // Return Some(remaining balance), must be more than MinDelegatorStk // Return None if delegation not found pub fn rm_delegation(&mut self, collator: &AccountId) -> Option @@ -1335,8 +1316,7 @@ impl< self.adjust_bond_lock::(BondAdjust::Increase(amount))?; // update collator state delegation - let mut collator_state = - >::get(&candidate_id).ok_or(Error::::CandidateDNE)?; + let mut collator_state = >::get(&candidate_id).ok_or(Error::::CandidateDNE)?; let before = collator_state.total_counted; let in_top = collator_state.increase_delegation::( &candidate_id, @@ -1367,10 +1347,7 @@ impl< /// `additional_required_balance` should reflect the change to the amount that should be locked if /// positive, 0 otherwise (e.g. `min(0, change_in_total_bond)`). This is necessary because it is /// not possible to query the amount that is locked for a given lock id. - pub fn adjust_bond_lock( - &mut self, - additional_required_balance: BondAdjust, - ) -> DispatchResult + pub fn adjust_bond_lock(&mut self, additional_required_balance: BondAdjust) -> DispatchResult where BalanceOf: From, T::AccountId: From, @@ -1378,8 +1355,7 @@ impl< match additional_required_balance { BondAdjust::Increase(amount) => { ensure!( - >::get_delegator_stakable_free_balance(&self.id.clone().into()) >= - amount.into(), + >::get_delegator_stakable_free_balance(&self.id.clone().into()) >= amount.into(), Error::::InsufficientBalance, ); @@ -1449,11 +1425,7 @@ pub mod deprecated { impl Default for PendingDelegationRequests { fn default() -> PendingDelegationRequests { - PendingDelegationRequests { - revocations_count: 0u32, - requests: BTreeMap::new(), - less_total: B::zero(), - } + PendingDelegationRequests { revocations_count: 0u32, requests: BTreeMap::new(), less_total: B::zero() } } } @@ -1577,26 +1549,24 @@ pub struct RoundInfo { /// The length of the current round in number of blocks pub length: u32, } -impl< - B: Copy + sp_std::ops::Add + sp_std::ops::Sub + From + PartialOrd, - > RoundInfo -{ +impl + sp_std::ops::Sub + From + PartialOrd> RoundInfo { pub fn new(current: RoundIndex, first: B, length: u32) -> RoundInfo { RoundInfo { current, first, length } } + /// Check if the round should be updated pub fn should_update(&self, now: B) -> bool { now - self.first >= self.length.into() } + /// New round pub fn update(&mut self, now: B) { self.current = self.current.saturating_add(1u32); self.first = now; } } -impl< - B: Copy + sp_std::ops::Add + sp_std::ops::Sub + From + PartialOrd, - > Default for RoundInfo +impl + sp_std::ops::Sub + From + PartialOrd> Default + for RoundInfo { fn default() -> RoundInfo { RoundInfo::new(1u32, 1u32.into(), 20u32) diff --git a/pallets/sandbox/src/lib.rs b/pallets/sandbox/src/lib.rs index a5e2961ec..202b411d4 100644 --- a/pallets/sandbox/src/lib.rs +++ b/pallets/sandbox/src/lib.rs @@ -34,8 +34,7 @@ pub mod pallet { let retail_user = ensure_signed(origin)?; let project_id: ::ProjectIdentifier = project_id.into(); // Check project is in the community round - let project_info = funding::Pallet::::project_info(project_id) - .ok_or(Error::::ProjectNotFound)?; + let project_info = funding::Pallet::::project_info(project_id).ok_or(Error::::ProjectNotFound)?; ensure!( project_info.project_status == funding::ProjectStatus::CommunityRound, "Project is not in the community round" @@ -43,12 +42,11 @@ pub mod pallet { // Calculate how much funding was done already let project_contributions: ::Balance = - funding::Contributions::::iter_prefix_values(project_id).flatten().fold( - 0u64.into(), - |total_tokens_bought, contribution| { + funding::Contributions::::iter_prefix_values(project_id) + .flatten() + .fold(0u64.into(), |total_tokens_bought, contribution| { total_tokens_bought + contribution.contribution_amount - }, - ); + }); ensure!( project_contributions >= 500_000_0_000_000_000u64.into(), diff --git a/pallets/sandbox/src/mock.rs b/pallets/sandbox/src/mock.rs index 4bcc626da..b94682855 100644 --- a/pallets/sandbox/src/mock.rs +++ b/pallets/sandbox/src/mock.rs @@ -61,30 +61,30 @@ parameter_types! { } impl system::Config for TestRuntime { + type AccountData = pallet_balances::AccountData; + type AccountId = AccountId; type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); + type BlockHashCount = BlockHashCount; type BlockLength = (); - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Index = u64; type BlockNumber = BlockNumber; + type BlockWeights = (); + type DbWeight = (); type Hash = H256; type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; type Header = Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type DbWeight = (); - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); + type Index = u64; + type Lookup = IdentityLookup; + type MaxConsumers = frame_support::traits::ConstU32<16>; type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = ConstU16<42>; + type OnNewAccount = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type PalletInfo = PalletInfo; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type SS58Prefix = ConstU16<42>; + type SystemWeightInfo = (); + type Version = (); } parameter_types! { @@ -92,44 +92,44 @@ parameter_types! { } impl pallet_balances::Config for TestRuntime { - type MaxLocks = frame_support::traits::ConstU32<1024>; - type MaxReserves = frame_support::traits::ConstU32<1024>; - type ReserveIdentifier = pallet_funding::BondType; + type AccountStore = System; type Balance = Balance; - type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); - type HoldIdentifier = pallet_funding::BondType; type FreezeIdentifier = pallet_funding::BondType; - type MaxHolds = (); + type HoldIdentifier = pallet_funding::BondType; type MaxFreezes = (); + type MaxHolds = (); + type MaxLocks = frame_support::traits::ConstU32<1024>; + type MaxReserves = frame_support::traits::ConstU32<1024>; + type ReserveIdentifier = pallet_funding::BondType; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); } impl pallet_insecure_randomness_collective_flip::Config for TestRuntime {} impl pallet_assets::Config for TestRuntime { - type RuntimeEvent = RuntimeEvent; - type Balance = Balance; + type ApprovalDeposit = ConstU128<1>; + type AssetAccountDeposit = ConstU128<10>; + type AssetDeposit = ConstU128<1>; type AssetId = Identifier; + type AssetIdParameter = Identifier; + type Balance = Balance; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); + type CallbackHandle = (); + type CreateOrigin = AsEnsureOriginWithArg>; type Currency = Balances; + type Extra = (); type ForceOrigin = frame_system::EnsureRoot; - type AssetDeposit = ConstU128<1>; - type AssetAccountDeposit = ConstU128<10>; + type Freezer = (); type MetadataDepositBase = ConstU128<1>; type MetadataDepositPerByte = ConstU128<1>; - type ApprovalDeposit = ConstU128<1>; + type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; + type RuntimeEvent = RuntimeEvent; type StringLimit = ConstU32<50>; - type Freezer = (); type WeightInfo = (); - type Extra = (); - type AssetIdParameter = Identifier; - type CreateOrigin = AsEnsureOriginWithArg>; - type CallbackHandle = (); - type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); } // REMARK: In the production configuration we use DAYS instead of HOURS. @@ -144,33 +144,33 @@ parameter_types! { } impl pallet_funding::Config for TestRuntime { - type RuntimeEvent = RuntimeEvent; - type StringLimit = ConstU32<64>; - type ProjectIdentifier = Identifier; - type ProjectIdParameter = Identifier; + type AuctionInitializePeriodDuration = AuctionInitializePeriodDuration; + type Balance = Balance; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); type BidId = u128; + type CandleAuctionDuration = CandleAuctionDuration; + type CommunityFundingDuration = CommunityRoundDuration; type ContributionTokenCurrency = Assets; - type EvaluationDuration = EvaluationDuration; - type AuctionInitializePeriodDuration = AuctionInitializePeriodDuration; + type ContributionVesting = ConstU32<4>; type EnglishAuctionDuration = EnglishAuctionDuration; - type CandleAuctionDuration = CandleAuctionDuration; - type RemainderFundingDuration = RemainderFundingDuration; - type PalletId = FundingPalletId; + type EvaluationDuration = EvaluationDuration; + type FundingCurrency = Balances; + type MaxContributionsPerUser = ConstU32<4>; type MaxProjectsToUpdatePerBlock = ConstU32<100>; - type CommunityFundingDuration = CommunityRoundDuration; - type Randomness = RandomnessCollectiveFlip; - type PreImageLimit = ConstU32<1024>; // Low value to simplify the tests type MaximumBidsPerUser = ConstU32<4>; - type MaxContributionsPerUser = ConstU32<4>; - type ContributionVesting = ConstU32<4>; - type WeightInfo = (); - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); type Multiplier = pallet_funding::types::Multiplier; - type Balance = Balance; type NativeCurrency = Balances; - type FundingCurrency = Balances; + type PalletId = FundingPalletId; + type PreImageLimit = ConstU32<1024>; + type ProjectIdParameter = Identifier; + type ProjectIdentifier = Identifier; + type Randomness = RandomnessCollectiveFlip; + type RemainderFundingDuration = RemainderFundingDuration; + type RuntimeEvent = RuntimeEvent; + type StringLimit = ConstU32<64>; + type WeightInfo = (); } // Build genesis storage according to the mock runtime. diff --git a/pallets/sandbox/src/tests.rs b/pallets/sandbox/src/tests.rs index 52ee116a2..8545884e9 100644 --- a/pallets/sandbox/src/tests.rs +++ b/pallets/sandbox/src/tests.rs @@ -19,11 +19,7 @@ fn test_buy_if_popular() { let project = default_project(0); assert_ok!(FundingModule::create(RuntimeOrigin::signed(creator), project.clone(),)); assert_ok!(FundingModule::start_evaluation(RuntimeOrigin::signed(creator), 0)); - assert_ok!(FundingModule::bond_evaluation( - RuntimeOrigin::signed(evaluator), - 0, - 120_000 * PLMC - )); + assert_ok!(FundingModule::bond_evaluation(RuntimeOrigin::signed(evaluator), 0, 120_000 * PLMC)); // advance time for _block in 0..::EvaluationDuration::get() + 10 { @@ -76,9 +72,7 @@ const METADATA: &str = r#" "usage_of_founds":"ipfs_url" }"#; -pub fn default_project( - nonce: u64, -) -> ProjectMetadata>, u128, sp_core::H256> { +pub fn default_project(nonce: u64) -> ProjectMetadata>, u128, sp_core::H256> { let bounded_name = BoundedVec::try_from("Contribution Token TEST".as_bytes().to_vec()).unwrap(); let bounded_symbol = BoundedVec::try_from("CTEST".as_bytes().to_vec()).unwrap(); let metadata_hash = hashed(format!("{}-{}", METADATA, nonce)); @@ -91,11 +85,7 @@ pub fn default_project( conversion_rate: 0, participation_currencies: Default::default(), offchain_information_hash: Some(metadata_hash), - token_information: CurrencyMetadata { - name: bounded_name, - symbol: bounded_symbol, - decimals: ASSET_DECIMALS, - }, + token_information: CurrencyMetadata { name: bounded_name, symbol: bounded_symbol, decimals: ASSET_DECIMALS }, } } @@ -104,12 +94,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities { GenesisConfig { balances: BalancesConfig { - balances: vec![ - (1, 1_000_000 * PLMC), - (2, 1_000_000 * PLMC), - (3, 1_000_000 * PLMC), - (4, 10_000_000 * PLMC), - ], + balances: vec![(1, 1_000_000 * PLMC), (2, 1_000_000 * PLMC), (3, 1_000_000 * PLMC), (4, 10_000_000 * PLMC)], }, ..Default::default() } diff --git a/runtimes/base/build.rs b/runtimes/base/build.rs index b81f7762c..657bcc0d1 100644 --- a/runtimes/base/build.rs +++ b/runtimes/base/build.rs @@ -17,9 +17,5 @@ use substrate_wasm_builder::WasmBuilder; fn main() { - WasmBuilder::new() - .with_current_project() - .export_heap_base() - .import_memory() - .build() + WasmBuilder::new().with_current_project().export_heap_base().import_memory().build() } diff --git a/runtimes/base/src/lib.rs b/runtimes/base/src/lib.rs index 701846e13..d4884e971 100644 --- a/runtimes/base/src/lib.rs +++ b/runtimes/base/src/lib.rs @@ -37,10 +37,7 @@ use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; pub use sp_runtime::BuildStorage; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{ - AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, OpaqueKeys, - Verify, - }, + traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, OpaqueKeys, Verify}, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, MultiSignature, }; @@ -112,20 +109,14 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = frame_executive::Executive< - Runtime, - Block, - frame_system::ChainContext, - Runtime, - AllPalletsWithSystem, ->; +pub type Executive = + frame_executive::Executive, Runtime, AllPalletsWithSystem>; /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know /// the specifics of the runtime. They can then be made to be agnostic over specific formats @@ -176,103 +167,103 @@ parameter_types! { // Configure FRAME pallets to include in runtime. impl frame_system::Config for Runtime { + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; /// The identifier used to distinguish between accounts. type AccountId = AccountId; - /// The aggregated dispatch type that is available for extrinsics. - type RuntimeCall = RuntimeCall; - /// The lookup mechanism to get account ID from whatever is passed in dispatchers. - type Lookup = AccountIdLookup; - /// The index type for storing how many extrinsics an account has signed. - type Index = Index; + /// The basic call filter to use in dispatchable. + type BaseCallFilter = Everything; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + /// The maximum length of a block (in bytes). + type BlockLength = RuntimeBlockLength; /// The index type for blocks. type BlockNumber = BlockNumber; + /// Block & extrinsics weights: base values and limits. + type BlockWeights = RuntimeBlockWeights; + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; /// The type for hashing blocks and tries. type Hash = Hash; /// The hashing algorithm used. type Hashing = BlakeTwo256; /// The header type. type Header = generic::Header; + /// The index type for storing how many extrinsics an account has signed. + type Index = Index; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = AccountIdLookup; + type MaxConsumers = frame_support::traits::ConstU32<16>; + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); + /// What to do if a new account is created. + type OnNewAccount = (); + /// The action to take on a Runtime Upgrade + type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; + /// Converts a module to an index of this module in the runtime. + type PalletInfo = PalletInfo; + /// The aggregated dispatch type that is available for extrinsics. + type RuntimeCall = RuntimeCall; /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; /// The ubiquitous origin type. type RuntimeOrigin = RuntimeOrigin; - /// Maximum number of block number to block hash mappings to keep (oldest pruned first). - type BlockHashCount = BlockHashCount; - /// Runtime version. - type Version = Version; - /// Converts a module to an index of this module in the runtime. - type PalletInfo = PalletInfo; - /// The data to be stored in an account. - type AccountData = pallet_balances::AccountData; - /// What to do if a new account is created. - type OnNewAccount = (); - /// What to do if an account is fully reaped from the system. - type OnKilledAccount = (); - /// The weight of database operations that the runtime can invoke. - type DbWeight = RocksDbWeight; - /// The basic call filter to use in dispatchable. - type BaseCallFilter = Everything; - /// Weight information for the extrinsics of this pallet. - type SystemWeightInfo = (); - /// Block & extrinsics weights: base values and limits. - type BlockWeights = RuntimeBlockWeights; - /// The maximum length of a block (in bytes). - type BlockLength = RuntimeBlockLength; /// This is used as an identifier of the chain. 42 is the generic substrate prefix. type SS58Prefix = SS58Prefix; - /// The action to take on a Runtime Upgrade - type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; - type MaxConsumers = frame_support::traits::ConstU32<16>; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = (); + /// Runtime version. + type Version = Version; } impl pallet_timestamp::Config for Runtime { + type MinimumPeriod = MinimumPeriod; /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - type MinimumPeriod = MinimumPeriod; type WeightInfo = (); } impl pallet_authorship::Config for Runtime { - type FindAuthor = pallet_session::FindAccountFromAuthorIndex; type EventHandler = ParachainStaking; + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; } impl pallet_balances::Config for Runtime { - type MaxLocks = MaxLocks; + type AccountStore = System; type Balance = Balance; - type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type MaxReserves = MaxReserves; - type MaxHolds = MaxLocks; - type MaxFreezes = MaxReserves; - type HoldIdentifier = (); type FreezeIdentifier = (); + type HoldIdentifier = (); + type MaxFreezes = MaxReserves; + type MaxHolds = MaxLocks; + type MaxLocks = MaxLocks; + type MaxReserves = MaxReserves; type ReserveIdentifier = [u8; 8]; + type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } impl pallet_transaction_payment::Config for Runtime { - type RuntimeEvent = RuntimeEvent; + type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type LengthToFee = ConstantMultiplier; type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type OperationalFeeMultiplier = frame_support::traits::ConstU8<5>; + type RuntimeEvent = RuntimeEvent; type WeightToFee = WeightToFee; - type LengthToFee = ConstantMultiplier; - type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; } impl cumulus_pallet_parachain_system::Config for Runtime { - type RuntimeEvent = RuntimeEvent; + type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; + type DmpMessageHandler = DmpQueue; type OnSystemEvent = (); - type SelfParaId = parachain_info::Pallet; type OutboundXcmpMessageSource = XcmpQueue; - type DmpMessageHandler = DmpQueue; type ReservedDmpWeight = ReservedDmpWeight; - type XcmpMessageHandler = XcmpQueue; type ReservedXcmpWeight = ReservedXcmpWeight; - type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; + type RuntimeEvent = RuntimeEvent; + type SelfParaId = parachain_info::Pallet; + type XcmpMessageHandler = XcmpQueue; } impl parachain_info::Config for Runtime {} @@ -280,32 +271,32 @@ impl parachain_info::Config for Runtime {} impl cumulus_pallet_aura_ext::Config for Runtime {} impl cumulus_pallet_xcmp_queue::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; type ChannelInfo = ParachainSystem; - type VersionWrapper = (); - type ExecuteOverweightOrigin = EnsureRoot; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; - type WeightInfo = (); + type ExecuteOverweightOrigin = EnsureRoot; type PriceForSiblingDelivery = (); + type RuntimeEvent = RuntimeEvent; + type VersionWrapper = (); + type WeightInfo = (); + type XcmExecutor = XcmExecutor; } impl cumulus_pallet_dmp_queue::Config for Runtime { + type ExecuteOverweightOrigin = EnsureRoot; type RuntimeEvent = RuntimeEvent; type XcmExecutor = XcmExecutor; - type ExecuteOverweightOrigin = EnsureRoot; } impl pallet_session::Config for Runtime { + type Keys = SessionKeys; + type NextSessionRotation = ParachainStaking; type RuntimeEvent = RuntimeEvent; + type SessionHandler = ::KeyTypeIdProviders; + type SessionManager = ParachainStaking; + type ShouldEndSession = ParachainStaking; type ValidatorId = AccountId; type ValidatorIdOf = ConvertInto; - type ShouldEndSession = ParachainStaking; - type NextSessionRotation = ParachainStaking; - type SessionManager = ParachainStaking; - type SessionHandler = ::KeyTypeIdProviders; - type Keys = SessionKeys; type WeightInfo = (); } @@ -321,27 +312,27 @@ impl pallet_sudo::Config for Runtime { } impl pallet_parachain_staking::Config for Runtime { - type RuntimeEvent = RuntimeEvent; + type CandidateBondLessDelay = CandidateBondLessDelay; type Currency = Balances; - type MonetaryGovernanceOrigin = frame_system::EnsureRoot; - type MinBlocksPerRound = MinBlocksPerRound; + type DelegationBondLessDelay = DelegationBondLessDelay; type LeaveCandidatesDelay = LeaveCandidatesDelay; - type CandidateBondLessDelay = CandidateBondLessDelay; type LeaveDelegatorsDelay = LeaveDelegatorsDelay; - type RevokeDelegationDelay = RevokeDelegationDelay; - type DelegationBondLessDelay = DelegationBondLessDelay; - type RewardPaymentDelay = RewardPaymentDelay; - type MinSelectedCandidates = MinSelectedCandidates; - type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate; type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator; + type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; + type MinBlocksPerRound = MinBlocksPerRound; type MinCandidateStk = MinCandidateStk; - type MinDelegatorStk = MinDelegatorStk; type MinDelegation = MinDelegation; + type MinDelegatorStk = MinDelegatorStk; + type MinSelectedCandidates = MinSelectedCandidates; + type MonetaryGovernanceOrigin = frame_system::EnsureRoot; type OnCollatorPayout = (); + type OnNewRound = (); // We use the default implementation, so we leave () here. type PayoutCollatorReward = (); - type OnNewRound = (); + type RevokeDelegationDelay = RevokeDelegationDelay; + type RewardPaymentDelay = RewardPaymentDelay; + type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_parachain_staking::weights::SubstrateWeight; } @@ -598,17 +589,15 @@ impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { block: &Block, relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, ) -> sp_inherents::CheckInherentsResult { - let relay_chain_slot = relay_state_proof - .read_slot() - .expect("Could not read the relay chain slot from the proof"); - - let inherent_data = - cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( - relay_chain_slot, - sp_std::time::Duration::from_secs(6), - ) - .create_inherent_data() - .expect("Could not create the timestamp inherent data"); + let relay_chain_slot = + relay_state_proof.read_slot().expect("Could not read the relay chain slot from the proof"); + + let inherent_data = cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( + relay_chain_slot, + sp_std::time::Duration::from_secs(6), + ) + .create_inherent_data() + .expect("Could not create the timestamp inherent data"); inherent_data.check_extrinsics(block) } diff --git a/runtimes/base/src/xcm_config.rs b/runtimes/base/src/xcm_config.rs index ab1307a1b..5f7ae306e 100644 --- a/runtimes/base/src/xcm_config.rs +++ b/runtimes/base/src/xcm_config.rs @@ -15,8 +15,8 @@ // along with this program. If not, see . use super::{ - AccountId, AllPalletsWithSystem, Balances, EnsureRoot, ParachainInfo, ParachainSystem, - PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, + AccountId, AllPalletsWithSystem, Balances, EnsureRoot, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, + RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, }; use frame_support::{ match_types, parameter_types, @@ -29,11 +29,10 @@ use polkadot_parachain::primitives::Sibling; use polkadot_runtime_common::impls::ToAuthor; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowTopLevelPaidExecutionFrom, - CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, IsConcrete, NativeAsset, ParentIsPreset, - RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - UsingComponents, WithComputedOrigin, + AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, + EnsureXcmOrigin, FixedWeightBounds, IsConcrete, NativeAsset, ParentIsPreset, RelayChainAsNative, + SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, WithComputedOrigin, }; use xcm_executor::XcmExecutor; @@ -123,32 +122,31 @@ pub type Barrier = DenyThenTry< pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { - type RuntimeCall = RuntimeCall; - type XcmSender = XcmRouter; + type AssetClaims = PolkadotXcm; + type AssetExchanger = (); + type AssetLocker = (); // How to withdraw and deposit an asset. type AssetTransactor = LocalAssetTransactor; - type OriginConverter = XcmOriginToTransactDispatchOrigin; + type AssetTrap = PolkadotXcm; + type Barrier = Barrier; + type CallDispatcher = RuntimeCall; + type FeeManager = (); type IsReserve = NativeAsset; type IsTeleporter = (); - // Teleporting is disabled. - type UniversalLocation = UniversalLocation; - type Barrier = Barrier; - type Weigher = FixedWeightBounds; - type Trader = - UsingComponents>; - type ResponseHandler = PolkadotXcm; - type AssetTrap = PolkadotXcm; - type AssetClaims = PolkadotXcm; - type SubscriptionService = PolkadotXcm; - type PalletInstancesInfo = AllPalletsWithSystem; type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type AssetLocker = (); - type AssetExchanger = (); - type FeeManager = (); type MessageExporter = (); - type UniversalAliases = Nothing; - type CallDispatcher = RuntimeCall; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type PalletInstancesInfo = AllPalletsWithSystem; + type ResponseHandler = PolkadotXcm; + type RuntimeCall = RuntimeCall; type SafeCallFilter = Everything; + type SubscriptionService = PolkadotXcm; + type Trader = UsingComponents>; + type UniversalAliases = Nothing; + // Teleporting is disabled. + type UniversalLocation = UniversalLocation; + type Weigher = FixedWeightBounds; + type XcmSender = XcmRouter; } /// No local origins on this chain are allowed to dispatch XCM sends/executions. @@ -170,32 +168,32 @@ parameter_types! { impl pallet_xcm::Config for Runtime { type AdminOrigin = EnsureRoot; + // ^ Override for AdvertisedXcmVersion default + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; + type Currency = Balances; + type CurrencyMatcher = (); + type ExecuteXcmOrigin = EnsureXcmOrigin; + type MaxLockers = ConstU32<8>; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; type SendXcmOrigin = EnsureXcmOrigin; - type XcmRouter = XcmRouter; - type ExecuteXcmOrigin = EnsureXcmOrigin; + type SovereignAccountOf = LocationToAccountId; + type TrustedLockers = (); + type UniversalLocation = UniversalLocation; + type Weigher = FixedWeightBounds; + type WeightInfo = pallet_xcm::TestWeightInfo; type XcmExecuteFilter = Nothing; // ^ Disable dispatchable execute on the XCM pallet. // Needs to be `Everything` for local testing. type XcmExecutor = XcmExecutor; - type XcmTeleportFilter = Everything; type XcmReserveTransferFilter = Nothing; - type Weigher = FixedWeightBounds; - type UniversalLocation = UniversalLocation; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; + type XcmRouter = XcmRouter; + type XcmTeleportFilter = Everything; const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; - // ^ Override for AdvertisedXcmVersion default - type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; - type Currency = Balances; - type CurrencyMatcher = (); - type TrustedLockers = (); - type SovereignAccountOf = LocationToAccountId; - type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/runtimes/shared-configuration/src/fee.rs b/runtimes/shared-configuration/src/fee.rs index 2fd88b717..a95a31252 100644 --- a/runtimes/shared-configuration/src/fee.rs +++ b/runtimes/shared-configuration/src/fee.rs @@ -17,10 +17,7 @@ use crate::{currency::MILLI_PLMC, Balance}; use frame_support::{ parameter_types, - weights::{ - constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients, - WeightToFeePolynomial, - }, + weights::{constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}, }; use parachains_common::SLOT_DURATION; use smallvec::smallvec; @@ -29,6 +26,7 @@ use sp_arithmetic::Perbill; pub struct WeightToFee; impl WeightToFeePolynomial for WeightToFee { type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { // extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: let p = 10 * MILLI_PLMC; diff --git a/runtimes/shared-configuration/src/weights/block_weights.rs b/runtimes/shared-configuration/src/weights/block_weights.rs index f24090fb4..b17b64afc 100644 --- a/runtimes/shared-configuration/src/weights/block_weights.rs +++ b/runtimes/shared-configuration/src/weights/block_weights.rs @@ -43,10 +43,7 @@ pub mod constants { "Weight should be at least 100 µs." ); // At most 50 ms. - assert!( - w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, - "Weight should be at most 50 ms." - ); + assert!(w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 50 ms."); } } } diff --git a/runtimes/shared-configuration/src/weights/extrinsic_weights.rs b/runtimes/shared-configuration/src/weights/extrinsic_weights.rs index 465a4c5fe..5aabc4cdb 100644 --- a/runtimes/shared-configuration/src/weights/extrinsic_weights.rs +++ b/runtimes/shared-configuration/src/weights/extrinsic_weights.rs @@ -38,15 +38,9 @@ pub mod constants { let w = super::constants::ExtrinsicBaseWeight::get(); // At least 10 µs. - assert!( - w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, - "Weight should be at least 10 µs." - ); + assert!(w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, "Weight should be at least 10 µs."); // At most 1 ms. - assert!( - w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, - "Weight should be at most 1 ms." - ); + assert!(w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 1 ms."); } } } diff --git a/runtimes/standalone/build.rs b/runtimes/standalone/build.rs index b81f7762c..657bcc0d1 100644 --- a/runtimes/standalone/build.rs +++ b/runtimes/standalone/build.rs @@ -17,9 +17,5 @@ use substrate_wasm_builder::WasmBuilder; fn main() { - WasmBuilder::new() - .with_current_project() - .export_heap_base() - .import_memory() - .build() + WasmBuilder::new().with_current_project().export_heap_base().import_memory().build() } diff --git a/runtimes/standalone/src/lib.rs b/runtimes/standalone/src/lib.rs index 646c294fe..a419de698 100644 --- a/runtimes/standalone/src/lib.rs +++ b/runtimes/standalone/src/lib.rs @@ -25,13 +25,11 @@ extern crate frame_benchmarking; pub use frame_support::{ construct_runtime, parameter_types, traits::{ - ConstU128, ConstU32, ConstU64, ConstU8, Contains, EitherOfDiverse, EqualPrivilegeOnly, - KeyOwnerProofSystem, Randomness, StorageInfo, WithdrawReasons, + ConstU128, ConstU32, ConstU64, ConstU8, Contains, EitherOfDiverse, EqualPrivilegeOnly, KeyOwnerProofSystem, + Randomness, StorageInfo, WithdrawReasons, }, weights::{ - constants::{ - BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND, - }, + constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND}, IdentityFee, Weight, }, PalletId, StorageValue, @@ -53,8 +51,7 @@ pub use sp_runtime::BuildStorage; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{ - AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, NumberFor, - One, OpaqueKeys, Verify, + AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, NumberFor, One, OpaqueKeys, Verify, }, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, MultiSignature, @@ -202,55 +199,55 @@ parameter_types! { // Configure FRAME pallets to include in runtime. impl frame_system::Config for Runtime { + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; /// The basic call filter to use in dispatchable. type BaseCallFilter = frame_support::traits::Everything; - /// Block & extrinsics weights: base values and limits. - type BlockWeights = BlockWeights; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; /// The maximum length of a block (in bytes). type BlockLength = BlockLength; - /// The identifier used to distinguish between accounts. - type AccountId = AccountId; - /// The aggregated dispatch type that is available for extrinsics. - type RuntimeCall = RuntimeCall; - /// The lookup mechanism to get account ID from whatever is passed in dispatchers. - type Lookup = AccountIdLookup; - /// The index type for storing how many extrinsics an account has signed. - type Index = Index; /// The index type for blocks. type BlockNumber = BlockNumber; + /// Block & extrinsics weights: base values and limits. + type BlockWeights = BlockWeights; + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; /// The type for hashing blocks and tries. type Hash = Hash; /// The hashing algorithm used. type Hashing = BlakeTwo256; /// The header type. type Header = generic::Header; - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; - /// The ubiquitous origin type. - type RuntimeOrigin = RuntimeOrigin; - /// Maximum number of block number to block hash mappings to keep (oldest pruned first). - type BlockHashCount = BlockHashCount; - /// The weight of database operations that the runtime can invoke. - type DbWeight = RocksDbWeight; - /// Version of the runtime. - type Version = Version; + /// The index type for storing how many extrinsics an account has signed. + type Index = Index; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = AccountIdLookup; + type MaxConsumers = frame_support::traits::ConstU32<16>; + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); + /// What to do if a new account is created. + type OnNewAccount = (); + /// The set code logic, just the default since we're not a parachain. + type OnSetCode = (); /// Converts a module to the index of the module in `construct_runtime!`. /// /// This type is being generated by `construct_runtime!`. type PalletInfo = PalletInfo; - /// What to do if a new account is created. - type OnNewAccount = (); - /// What to do if an account is fully reaped from the system. - type OnKilledAccount = (); - /// The data to be stored in an account. - type AccountData = pallet_balances::AccountData; - /// Weight information for the extrinsics of this pallet. - type SystemWeightInfo = (); + /// The aggregated dispatch type that is available for extrinsics. + type RuntimeCall = RuntimeCall; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + /// The ubiquitous origin type. + type RuntimeOrigin = RuntimeOrigin; /// This is used as an identifier of the chain. 42 is the generic substrate prefix. type SS58Prefix = SS58Prefix; - /// The set code logic, just the default since we're not a parachain. - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = (); + /// Version of the runtime. + type Version = Version; } impl pallet_insecure_randomness_collective_flip::Config for Runtime {} @@ -262,36 +259,34 @@ impl pallet_aura::Config for Runtime { } impl pallet_grandpa::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - - type WeightInfo = (); + type EquivocationReportSystem = (); + type KeyOwnerProof = sp_core::Void; type MaxAuthorities = ConstU32<32>; type MaxSetIdSessionEntries = ConstU64<0>; - - type KeyOwnerProof = sp_core::Void; - type EquivocationReportSystem = (); + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); } impl pallet_timestamp::Config for Runtime { + type MinimumPeriod = MinimumPeriod; type Moment = u64; type OnTimestampSet = Aura; - type MinimumPeriod = MinimumPeriod; type WeightInfo = (); } impl pallet_balances::Config for Runtime { - type MaxLocks = MaxLocks; + type AccountStore = System; type Balance = Balance; - type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type MaxReserves = MaxReserves; - type MaxHolds = MaxLocks; - type MaxFreezes = MaxReserves; - type HoldIdentifier = (); type FreezeIdentifier = (); + type HoldIdentifier = (); + type MaxFreezes = MaxReserves; + type MaxHolds = MaxLocks; + type MaxLocks = MaxLocks; + type MaxReserves = MaxReserves; type ReserveIdentifier = BondType; + type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } @@ -300,40 +295,40 @@ parameter_types! { } impl pallet_transaction_payment::Config for Runtime { - type RuntimeEvent = RuntimeEvent; + type FeeMultiplierUpdate = ConstFeeMultiplier; + type LengthToFee = IdentityFee; type OnChargeTransaction = CurrencyAdapter; type OperationalFeeMultiplier = ConstU8<5>; + type RuntimeEvent = RuntimeEvent; type WeightToFee = IdentityFee; - type LengthToFee = IdentityFee; - type FeeMultiplierUpdate = ConstFeeMultiplier; } impl pallet_sudo::Config for Runtime { - type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; } impl pallet_assets::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Balance = Balance; + type ApprovalDeposit = ExistentialDeposit; + type AssetAccountDeposit = AssetAccountDeposit; + type AssetDeposit = AssetDeposit; type AssetId = u32; type AssetIdParameter = parity_scale_codec::Compact; - type Currency = Balances; + type Balance = Balance; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); + type CallbackHandle = (); type CreateOrigin = AsEnsureOriginWithArg>; + type Currency = Balances; + type Extra = (); type ForceOrigin = EnsureRoot; - type AssetDeposit = AssetDeposit; + type Freezer = (); type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type ApprovalDeposit = ExistentialDeposit; + type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; + type RuntimeEvent = RuntimeEvent; type StringLimit = AssetsStringLimit; - type Freezer = (); - type Extra = (); type WeightInfo = (); - type CallbackHandle = (); - type AssetAccountDeposit = AssetAccountDeposit; - type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); } parameter_types! { @@ -348,45 +343,45 @@ parameter_types! { } impl pallet_funding::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type ProjectIdentifier = u32; - type ProjectIdParameter = parity_scale_codec::Compact; - type Multiplier = FundingMultiplier; + type AuctionInitializePeriodDuration = AuctionInitializePeriodDuration; type Balance = Balance; - type NativeCurrency = Balances; - type FundingCurrency = Balances; - type ContributionTokenCurrency = Assets; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); type BidId = u128; - type Randomness = Random; - type StringLimit = ConstU32<64>; - type PreImageLimit = ConstU32<1024>; - type EvaluationDuration = EvaluationDuration; - type AuctionInitializePeriodDuration = AuctionInitializePeriodDuration; - type EnglishAuctionDuration = EnglishAuctionDuration; type CandleAuctionDuration = CandleAuctionDuration; type CommunityFundingDuration = CommunityRoundDuration; - type RemainderFundingDuration = RemainderFundingDuration; - type PalletId = FundingPalletId; + type ContributionTokenCurrency = Assets; + type ContributionVesting = ContributionVestingDuration; + type EnglishAuctionDuration = EnglishAuctionDuration; + type EvaluationDuration = EvaluationDuration; + type FundingCurrency = Balances; + type MaxContributionsPerUser = ConstU32<64>; type MaxProjectsToUpdatePerBlock = ConstU32<100>; type MaximumBidsPerUser = ConstU32<256>; - type MaxContributionsPerUser = ConstU32<64>; - type ContributionVesting = ContributionVestingDuration; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); + type Multiplier = FundingMultiplier; + type NativeCurrency = Balances; + type PalletId = FundingPalletId; + type PreImageLimit = ConstU32<1024>; + type ProjectIdParameter = parity_scale_codec::Compact; + type ProjectIdentifier = u32; + type Randomness = Random; + type RemainderFundingDuration = RemainderFundingDuration; + type RuntimeEvent = RuntimeEvent; + type StringLimit = ConstU32<64>; type WeightInfo = (); } impl pallet_scheduler::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; + type MaxScheduledPerBlock = (); + type MaximumWeight = (); + type OriginPrivilegeCmp = EqualPrivilegeOnly; type PalletsOrigin = OriginCaller; + type Preimages = (); type RuntimeCall = RuntimeCall; - type MaximumWeight = (); + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; type ScheduleOrigin = EnsureRoot; - type MaxScheduledPerBlock = (); type WeightInfo = (); - type OriginPrivilegeCmp = EqualPrivilegeOnly; - type Preimages = (); } parameter_types! { @@ -397,16 +392,16 @@ parameter_types! { type CouncilCollective = pallet_collective::Instance1; impl pallet_collective::Config for Runtime { - type RuntimeOrigin = RuntimeOrigin; + type DefaultVote = pallet_collective::PrimeDefaultVote; + type MaxMembers = CouncilMaxMembers; + type MaxProposalWeight = MaxCollectivesProposalWeight; + type MaxProposals = CouncilMaxProposals; + type MotionDuration = CouncilMotionDuration; type Proposal = RuntimeCall; type RuntimeEvent = RuntimeEvent; - type MotionDuration = CouncilMotionDuration; - type MaxProposals = CouncilMaxProposals; - type MaxMembers = CouncilMaxMembers; - type DefaultVote = pallet_collective::PrimeDefaultVote; - type WeightInfo = pallet_collective::weights::SubstrateWeight; + type RuntimeOrigin = RuntimeOrigin; type SetMembersOrigin = EnsureRoot; - type MaxProposalWeight = MaxCollectivesProposalWeight; + type WeightInfo = pallet_collective::weights::SubstrateWeight; } parameter_types! { @@ -417,16 +412,16 @@ parameter_types! { type TechnicalCollective = pallet_collective::Instance2; impl pallet_collective::Config for Runtime { - type RuntimeOrigin = RuntimeOrigin; + type DefaultVote = pallet_collective::PrimeDefaultVote; + type MaxMembers = TechnicalMaxMembers; + type MaxProposalWeight = MaxCollectivesProposalWeight; + type MaxProposals = TechnicalMaxProposals; + type MotionDuration = TechnicalMotionDuration; type Proposal = RuntimeCall; type RuntimeEvent = RuntimeEvent; - type MotionDuration = TechnicalMotionDuration; - type MaxProposals = TechnicalMaxProposals; - type MaxMembers = TechnicalMaxMembers; - type DefaultVote = pallet_collective::PrimeDefaultVote; - type WeightInfo = pallet_collective::weights::SubstrateWeight; + type RuntimeOrigin = RuntimeOrigin; type SetMembersOrigin = EnsureRoot; - type MaxProposalWeight = MaxCollectivesProposalWeight; + type WeightInfo = pallet_collective::weights::SubstrateWeight; } parameter_types! { @@ -443,55 +438,50 @@ parameter_types! { } impl pallet_democracy::Config for Runtime { - type RuntimeEvent = RuntimeEvent; + type BlacklistOrigin = EnsureRoot; + // To cancel a proposal before it has been passed, the technical committee must be unanimous or + // Root must agree. + type CancelProposalOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionAtLeast, + >; + // To cancel a proposal which has been passed, 2/3 of the council must agree to it. + type CancellationOrigin = pallet_collective::EnsureProportionAtLeast; + type CooloffPeriod = CooloffPeriod; type Currency = Balances; type EnactmentPeriod = EnactmentPeriod; - type LaunchPeriod = LaunchPeriod; - type VotingPeriod = VotingPeriod; - type VoteLockingPeriod = EnactmentPeriod; // Same as EnactmentPeriod - type MinimumDeposit = MinimumDeposit; - /// A straight majority of the council can decide what their next motion is. - type ExternalOrigin = - pallet_collective::EnsureProportionAtLeast; - /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. - type ExternalMajorityOrigin = - pallet_collective::EnsureProportionAtLeast; /// A unanimous council can have the next scheduled referendum be a straight default-carries /// (NTB) vote. - type ExternalDefaultOrigin = - pallet_collective::EnsureProportionAtLeast; + type ExternalDefaultOrigin = pallet_collective::EnsureProportionAtLeast; + /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. + type ExternalMajorityOrigin = pallet_collective::EnsureProportionAtLeast; + /// A straight majority of the council can decide what their next motion is. + type ExternalOrigin = pallet_collective::EnsureProportionAtLeast; /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote /// be tabled immediately and with a shorter voting/enactment period. - type FastTrackOrigin = - pallet_collective::EnsureProportionAtLeast; - type InstantOrigin = - pallet_collective::EnsureProportionAtLeast; - type InstantAllowed = frame_support::traits::ConstBool; + type FastTrackOrigin = pallet_collective::EnsureProportionAtLeast; type FastTrackVotingPeriod = FastTrackVotingPeriod; - // To cancel a proposal which has been passed, 2/3 of the council must agree to it. - type CancellationOrigin = - pallet_collective::EnsureProportionAtLeast; - // To cancel a proposal before it has been passed, the technical committee must be unanimous or - // Root must agree. - type CancelProposalOrigin = EitherOfDiverse< - EnsureRoot, - pallet_collective::EnsureProportionAtLeast, - >; - type BlacklistOrigin = EnsureRoot; + type InstantAllowed = frame_support::traits::ConstBool; + type InstantOrigin = pallet_collective::EnsureProportionAtLeast; + type LaunchPeriod = LaunchPeriod; + type MaxBlacklisted = (); + type MaxDeposits = (); + type MaxProposals = MaxProposals; + type MaxVotes = ConstU32<100>; + // Same as EnactmentPeriod + type MinimumDeposit = MinimumDeposit; + type PalletsOrigin = OriginCaller; + type Preimages = (); + type RuntimeEvent = RuntimeEvent; + type Scheduler = Scheduler; + type Slash = (); + type SubmitOrigin = EnsureSigned; // Any single technical committee member may veto a coming council proposal, however they can // only do it once and it lasts only for the cool-off period. type VetoOrigin = pallet_collective::EnsureMember; - type CooloffPeriod = CooloffPeriod; - type Slash = (); - type Scheduler = Scheduler; - type PalletsOrigin = OriginCaller; - type MaxVotes = ConstU32<100>; + type VoteLockingPeriod = EnactmentPeriod; + type VotingPeriod = VotingPeriod; type WeightInfo = pallet_democracy::weights::SubstrateWeight; - type MaxProposals = MaxProposals; - type Preimages = (); - type MaxDeposits = (); - type MaxBlacklisted = (); - type SubmitOrigin = EnsureSigned; } parameter_types! { @@ -500,14 +490,14 @@ parameter_types! { } impl pallet_session::Config for Runtime { + type Keys = opaque::SessionKeys; + type NextSessionRotation = (); type RuntimeEvent = RuntimeEvent; + type SessionHandler = ::KeyTypeIdProviders; + type SessionManager = (); + type ShouldEndSession = pallet_session::PeriodicSessions; type ValidatorId = AccountId; type ValidatorIdOf = (); - type ShouldEndSession = pallet_session::PeriodicSessions; - type NextSessionRotation = (); - type SessionManager = (); - type SessionHandler = ::KeyTypeIdProviders; - type Keys = opaque::SessionKeys; type WeightInfo = (); } @@ -516,8 +506,8 @@ parameter_types! { } impl pallet_authorship::Config for Runtime { - type FindAuthor = pallet_session::FindAccountFromAuthorIndex; type EventHandler = (); + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; } parameter_types! { @@ -529,19 +519,19 @@ parameter_types! { } impl pallet_multisig::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; type Currency = Balances; type DepositBase = DepositBase; type DepositFactor = DepositFactor; type MaxSignatories = MaxSignatories; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } impl pallet_utility::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; type PalletsOrigin = OriginCaller; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } @@ -553,12 +543,13 @@ parameter_types! { } impl pallet_vesting::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Currency = Balances; type BlockNumberToBalance = ConvertInto; + type Currency = Balances; type MinVestedTransfer = MinVestedTransfer; - type WeightInfo = pallet_vesting::weights::SubstrateWeight; + type RuntimeEvent = RuntimeEvent; type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; + type WeightInfo = pallet_vesting::weights::SubstrateWeight; + // `VestingInfo` encode length is 36bytes. 28 schedules gets encoded as 1009 bytes, which is the // highest number of schedules that encodes less than 2^10. const MAX_VESTING_SCHEDULES: u32 = 28; @@ -621,18 +612,12 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// The payload being signed in transactions. pub type SignedPayload = generic::SignedPayload; /// Executive: handles dispatch to the various modules. -pub type Executive = frame_executive::Executive< - Runtime, - Block, - frame_system::ChainContext, - Runtime, - AllPalletsWithSystem, ->; +pub type Executive = + frame_executive::Executive, Runtime, AllPalletsWithSystem>; #[cfg(feature = "runtime-benchmarks")] mod benches { @@ -891,24 +876,14 @@ mod tests { .collect(); // Block Number - assert!( - whitelist.contains("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac") - ); + assert!(whitelist.contains("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac")); // Total Issuance - assert!( - whitelist.contains("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80") - ); + assert!(whitelist.contains("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80")); // Execution Phase - assert!( - whitelist.contains("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a") - ); + assert!(whitelist.contains("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a")); // Event Count - assert!( - whitelist.contains("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850") - ); + assert!(whitelist.contains("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850")); // System Events - assert!( - whitelist.contains("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7") - ); + assert!(whitelist.contains("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7")); } } diff --git a/runtimes/testnet/build.rs b/runtimes/testnet/build.rs index b81f7762c..657bcc0d1 100644 --- a/runtimes/testnet/build.rs +++ b/runtimes/testnet/build.rs @@ -17,9 +17,5 @@ use substrate_wasm_builder::WasmBuilder; fn main() { - WasmBuilder::new() - .with_current_project() - .export_heap_base() - .import_memory() - .build() + WasmBuilder::new().with_current_project().export_heap_base().import_memory().build() } diff --git a/runtimes/testnet/src/lib.rs b/runtimes/testnet/src/lib.rs index d1b240b85..5455833ef 100644 --- a/runtimes/testnet/src/lib.rs +++ b/runtimes/testnet/src/lib.rs @@ -25,16 +25,14 @@ extern crate frame_benchmarking; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use frame_support::{ construct_runtime, parameter_types, - traits::{ - AsEnsureOriginWithArg, ConstU32, Currency, EitherOfDiverse, EqualPrivilegeOnly, Everything, - }, + traits::{AsEnsureOriginWithArg, ConstU32, Currency, EitherOfDiverse, EqualPrivilegeOnly, Everything}, weights::{ConstantMultiplier, Weight}, }; use frame_system::{EnsureRoot, EnsureSigned}; pub use parachains_common::{ - impls::DealWithFees, opaque, AccountId, AssetIdForTrustBackedAssets as AssetId, AuraId, - Balance, BlockNumber, Hash, Header, Index, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, - MAXIMUM_BLOCK_WEIGHT, MINUTES, NORMAL_DISPATCH_RATIO, SLOT_DURATION, + impls::DealWithFees, opaque, AccountId, AssetIdForTrustBackedAssets as AssetId, AuraId, Balance, BlockNumber, Hash, + Header, Index, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, MAXIMUM_BLOCK_WEIGHT, MINUTES, + NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; // Polkadot imports @@ -78,9 +76,8 @@ pub use shared_configuration::{ weights::*, }; -pub type NegativeImbalanceOf = as Currency< - ::AccountId, ->>::NegativeImbalance; +pub type NegativeImbalanceOf = + as Currency<::AccountId>>::NegativeImbalance; /// The address format for describing accounts. pub type Address = MultiAddress; @@ -107,20 +104,14 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = frame_executive::Executive< - Runtime, - Block, - frame_system::ChainContext, - Runtime, - AllPalletsWithSystem, ->; +pub type Executive = + frame_executive::Executive, Runtime, AllPalletsWithSystem>; impl_opaque_keys! { pub struct SessionKeys { @@ -154,106 +145,101 @@ parameter_types! { // Configure FRAME pallets to include in runtime. impl frame_system::Config for Runtime { + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; /// The basic call filter to use in dispatchable. type BaseCallFilter = Everything; - /// Block & extrinsics weights: base values and limits. - type BlockWeights = RuntimeBlockWeights; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; /// The maximum length of a block (in bytes). type BlockLength = RuntimeBlockLength; - /// The ubiquitous origin type. - type RuntimeOrigin = RuntimeOrigin; - /// The aggregated dispatch type that is available for extrinsics. - type RuntimeCall = RuntimeCall; - /// The index type for storing how many extrinsics an account has signed. - type Index = Index; /// The index type for blocks. type BlockNumber = BlockNumber; + /// Block & extrinsics weights: base values and limits. + type BlockWeights = RuntimeBlockWeights; + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; /// The type for hashing blocks and tries. type Hash = Hash; /// The hashing algorithm used. type Hashing = BlakeTwo256; - /// The identifier used to distinguish between accounts. - type AccountId = AccountId; - /// The lookup mechanism to get account ID from whatever is passed in dispatchers. - type Lookup = AccountIdLookup; /// The header type. type Header = Header; - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; - /// Maximum number of block number to block hash mappings to keep (oldest pruned first). - type BlockHashCount = BlockHashCount; - /// The weight of database operations that the runtime can invoke. - type DbWeight = RocksDbWeight; - /// Runtime version. - type Version = Version; - /// Converts a module to an index of this module in the runtime. - type PalletInfo = PalletInfo; - /// The data to be stored in an account. - type AccountData = pallet_balances::AccountData; - /// What to do if a new account is created. - type OnNewAccount = (); + /// The index type for storing how many extrinsics an account has signed. + type Index = Index; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = AccountIdLookup; + type MaxConsumers = frame_support::traits::ConstU32<16>; /// What to do if an account is fully reaped from the system. type OnKilledAccount = (); + /// What to do if a new account is created. + type OnNewAccount = (); + /// The action to take on a Runtime Upgrade + type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; + /// Converts a module to an index of this module in the runtime. + type PalletInfo = PalletInfo; + /// The aggregated dispatch type that is available for extrinsics. + type RuntimeCall = RuntimeCall; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + /// The ubiquitous origin type. + type RuntimeOrigin = RuntimeOrigin; + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = SS58Prefix; /// Weight information for the extrinsics of this pallet. /// weights::frame_system::WeightInfo; type SystemWeightInfo = (); - /// This is used as an identifier of the chain. 42 is the generic substrate prefix. - type SS58Prefix = SS58Prefix; - /// The action to take on a Runtime Upgrade - type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; - type MaxConsumers = frame_support::traits::ConstU32<16>; + /// Runtime version. + type Version = Version; } impl pallet_timestamp::Config for Runtime { + type MinimumPeriod = MinimumPeriod; /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - type MinimumPeriod = MinimumPeriod; type WeightInfo = (); } impl pallet_authorship::Config for Runtime { - type FindAuthor = pallet_session::FindAccountFromAuthorIndex; type EventHandler = (ParachainStaking,); + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; } impl pallet_balances::Config for Runtime { - type MaxLocks = MaxLocks; + type AccountStore = System; type Balance = Balance; - type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type MaxReserves = MaxReserves; - type MaxHolds = MaxLocks; - type MaxFreezes = MaxReserves; - type HoldIdentifier = (); type FreezeIdentifier = (); + type HoldIdentifier = (); + type MaxFreezes = MaxReserves; + type MaxHolds = MaxLocks; + type MaxLocks = MaxLocks; + type MaxReserves = MaxReserves; type ReserveIdentifier = BondType; + type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } impl pallet_transaction_payment::Config for Runtime { - type RuntimeEvent = RuntimeEvent; + type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type LengthToFee = ConstantMultiplier; type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type OperationalFeeMultiplier = frame_support::traits::ConstU8<5>; + type RuntimeEvent = RuntimeEvent; type WeightToFee = WeightToFee; - type LengthToFee = ConstantMultiplier; - type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; } impl pallet_asset_tx_payment::Config for Runtime { - type RuntimeEvent = RuntimeEvent; type Fungibles = StatemintAssets; type OnChargeAssetTransaction = pallet_asset_tx_payment::FungiblesAdapter< - pallet_assets::BalanceToAssetBalance< - Balances, - Runtime, - ConvertInto, - StatemintAssetsInstance, - >, + pallet_assets::BalanceToAssetBalance, xcm_config::AssetsToBlockAuthor, >; + type RuntimeEvent = RuntimeEvent; } impl pallet_sudo::Config for Runtime { @@ -262,15 +248,15 @@ impl pallet_sudo::Config for Runtime { } impl cumulus_pallet_parachain_system::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type OnSystemEvent = (); - type SelfParaId = ParachainInfo; + type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; type DmpMessageHandler = DmpQueue; - type ReservedDmpWeight = ReservedDmpWeight; + type OnSystemEvent = (); type OutboundXcmpMessageSource = XcmpQueue; - type XcmpMessageHandler = XcmpQueue; + type ReservedDmpWeight = ReservedDmpWeight; type ReservedXcmpWeight = ReservedXcmpWeight; - type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; + type RuntimeEvent = RuntimeEvent; + type SelfParaId = ParachainInfo; + type XcmpMessageHandler = XcmpQueue; } impl parachain_info::Config for Runtime {} @@ -278,32 +264,32 @@ impl parachain_info::Config for Runtime {} impl cumulus_pallet_aura_ext::Config for Runtime {} impl cumulus_pallet_xcmp_queue::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; type ChannelInfo = ParachainSystem; - type VersionWrapper = PolkadotXcm; - type ExecuteOverweightOrigin = EnsureRoot; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = xcm_config::XcmOriginToTransactDispatchOrigin; + type ExecuteOverweightOrigin = EnsureRoot; type PriceForSiblingDelivery = (); + type RuntimeEvent = RuntimeEvent; + type VersionWrapper = PolkadotXcm; type WeightInfo = (); + type XcmExecutor = XcmExecutor; } impl cumulus_pallet_dmp_queue::Config for Runtime { + type ExecuteOverweightOrigin = EnsureRoot; type RuntimeEvent = RuntimeEvent; type XcmExecutor = XcmExecutor; - type ExecuteOverweightOrigin = EnsureRoot; } impl pallet_session::Config for Runtime { + type Keys = SessionKeys; + type NextSessionRotation = ParachainStaking; type RuntimeEvent = RuntimeEvent; + type SessionHandler = ::KeyTypeIdProviders; + type SessionManager = ParachainStaking; + type ShouldEndSession = ParachainStaking; type ValidatorId = ::AccountId; type ValidatorIdOf = ConvertInto; - type ShouldEndSession = ParachainStaking; - type NextSessionRotation = ParachainStaking; - type SessionManager = ParachainStaking; - type SessionHandler = ::KeyTypeIdProviders; - type Keys = SessionKeys; type WeightInfo = (); } @@ -316,122 +302,84 @@ impl pallet_aura::Config for Runtime { impl pallet_insecure_randomness_collective_flip::Config for Runtime {} impl pallet_funding::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type ProjectIdentifier = u32; - type ProjectIdParameter = parity_scale_codec::Compact; - type Multiplier = FundingMultiplier; + type AuctionInitializePeriodDuration = AuctionInitializePeriodDuration; type Balance = Balance; - type NativeCurrency = Balances; - type FundingCurrency = Balances; - type ContributionTokenCurrency = LocalAssets; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); type BidId = u128; - type Randomness = Random; - type StringLimit = ConstU32<64>; - type PreImageLimit = ConstU32<1024>; - type EvaluationDuration = EvaluationDuration; - type AuctionInitializePeriodDuration = AuctionInitializePeriodDuration; - type EnglishAuctionDuration = EnglishAuctionDuration; type CandleAuctionDuration = CandleAuctionDuration; type CommunityFundingDuration = CommunityFundingDuration; - type RemainderFundingDuration = RemainderFundingDuration; - type PalletId = FundingPalletId; + type ContributionTokenCurrency = LocalAssets; + type ContributionVesting = ContributionVestingDuration; + type EnglishAuctionDuration = EnglishAuctionDuration; + type EvaluationDuration = EvaluationDuration; + type FundingCurrency = Balances; + type MaxContributionsPerUser = ConstU32<256>; type MaxProjectsToUpdatePerBlock = ConstU32<100>; type MaximumBidsPerUser = ConstU32<256>; - - type MaxContributionsPerUser = ConstU32<256>; - type ContributionVesting = ContributionVestingDuration; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); + type Multiplier = FundingMultiplier; + type NativeCurrency = Balances; + type PalletId = FundingPalletId; + type PreImageLimit = ConstU32<1024>; + type ProjectIdParameter = parity_scale_codec::Compact; + type ProjectIdentifier = u32; + type Randomness = Random; + type RemainderFundingDuration = RemainderFundingDuration; + type RuntimeEvent = RuntimeEvent; + type StringLimit = ConstU32<64>; type WeightInfo = (); } impl pallet_treasury::Config for Runtime { - type Currency = Balances; // TODO: Use the Council instead of Root! type ApproveOrigin = EnsureRoot; - type RejectOrigin = EnsureRoot; - type RuntimeEvent = RuntimeEvent; + type Burn = Burn; + type BurnDestination = (); + type Currency = Balances; + type MaxApprovals = MaxApprovals; type OnSlash = Treasury; + type PalletId = TreasuryId; type ProposalBond = ProposalBond; - type ProposalBondMinimum = ProposalBondMinimum; type ProposalBondMaximum = (); - type SpendPeriod = SpendPeriod; - type Burn = Burn; - type PalletId = TreasuryId; - type BurnDestination = (); - type WeightInfo = (); + type ProposalBondMinimum = ProposalBondMinimum; + type RejectOrigin = EnsureRoot; + type RuntimeEvent = RuntimeEvent; type SpendFunds = (); - type MaxApprovals = MaxApprovals; type SpendOrigin = frame_support::traits::NeverEnsureOrigin; + type SpendPeriod = SpendPeriod; + type WeightInfo = (); } // TODO: VERY BASIC implementation, more work needed type CouncilCollective = pallet_collective::Instance1; impl pallet_collective::Config for Runtime { - type RuntimeOrigin = RuntimeOrigin; + type DefaultVote = pallet_collective::PrimeDefaultVote; + type MaxMembers = CouncilMaxMembers; + type MaxProposalWeight = MaxCollectivesProposalWeight; + type MaxProposals = CouncilMaxProposals; + type MotionDuration = CouncilMotionDuration; type Proposal = RuntimeCall; type RuntimeEvent = RuntimeEvent; - type MotionDuration = CouncilMotionDuration; - type MaxProposals = CouncilMaxProposals; - type MaxMembers = CouncilMaxMembers; - type DefaultVote = pallet_collective::PrimeDefaultVote; - type WeightInfo = pallet_collective::weights::SubstrateWeight; + type RuntimeOrigin = RuntimeOrigin; type SetMembersOrigin = EnsureRoot; - type MaxProposalWeight = MaxCollectivesProposalWeight; + type WeightInfo = pallet_collective::weights::SubstrateWeight; } type TechnicalCollective = pallet_collective::Instance2; impl pallet_collective::Config for Runtime { - type RuntimeOrigin = RuntimeOrigin; + type DefaultVote = pallet_collective::PrimeDefaultVote; + type MaxMembers = TechnicalMaxMembers; + type MaxProposalWeight = MaxCollectivesProposalWeight; + type MaxProposals = TechnicalMaxProposals; + type MotionDuration = TechnicalMotionDuration; type Proposal = RuntimeCall; type RuntimeEvent = RuntimeEvent; - type MotionDuration = TechnicalMotionDuration; - type MaxProposals = TechnicalMaxProposals; - type MaxMembers = TechnicalMaxMembers; - type DefaultVote = pallet_collective::PrimeDefaultVote; - type WeightInfo = pallet_collective::weights::SubstrateWeight; + type RuntimeOrigin = RuntimeOrigin; type SetMembersOrigin = EnsureRoot; - type MaxProposalWeight = MaxCollectivesProposalWeight; + type WeightInfo = pallet_collective::weights::SubstrateWeight; } impl pallet_democracy::Config for Runtime { - type WeightInfo = pallet_democracy::weights::SubstrateWeight; - type RuntimeEvent = RuntimeEvent; - type Scheduler = Scheduler; - type Preimages = Preimage; - type Currency = Balances; - type EnactmentPeriod = EnactmentPeriod; - type LaunchPeriod = LaunchPeriod; - type VotingPeriod = VotingPeriod; - type VoteLockingPeriod = EnactmentPeriod; - // Same as EnactmentPeriod - type MinimumDeposit = MinimumDeposit; - type InstantAllowed = frame_support::traits::ConstBool; - type FastTrackVotingPeriod = FastTrackVotingPeriod; - type CooloffPeriod = CooloffPeriod; - type MaxVotes = ConstU32<128>; - type MaxProposals = MaxProposals; - type MaxDeposits = (); - type MaxBlacklisted = (); - /// A straight majority of the council can decide what their next motion is. - type ExternalOrigin = - pallet_collective::EnsureProportionAtLeast; - /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. - type ExternalMajorityOrigin = - pallet_collective::EnsureProportionAtLeast; - /// A unanimous council can have the next scheduled referendum be a straight default-carries - /// (NTB) vote. - type ExternalDefaultOrigin = - pallet_collective::EnsureProportionAtLeast; - /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote - /// be tabled immediately and with a shorter voting/enactment period. - type FastTrackOrigin = - pallet_collective::EnsureProportionAtLeast; - type InstantOrigin = - pallet_collective::EnsureProportionAtLeast; - // To cancel a proposal which has been passed, 2/3 of the council must agree to it. - type CancellationOrigin = - pallet_collective::EnsureProportionAtLeast; type BlacklistOrigin = EnsureRoot; // To cancel a proposal before it has been passed, the technical committee must be unanimous or // Root must agree. @@ -439,136 +387,168 @@ impl pallet_democracy::Config for Runtime { EnsureRoot, pallet_collective::EnsureProportionAtLeast, >; - // Any single technical committee member may veto a coming council proposal, however they can - // only do it once and it lasts only for the cool-off period. - type VetoOrigin = pallet_collective::EnsureMember; + // To cancel a proposal which has been passed, 2/3 of the council must agree to it. + type CancellationOrigin = pallet_collective::EnsureProportionAtLeast; + type CooloffPeriod = CooloffPeriod; + type Currency = Balances; + type EnactmentPeriod = EnactmentPeriod; + /// A unanimous council can have the next scheduled referendum be a straight default-carries + /// (NTB) vote. + type ExternalDefaultOrigin = pallet_collective::EnsureProportionAtLeast; + /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. + type ExternalMajorityOrigin = pallet_collective::EnsureProportionAtLeast; + /// A straight majority of the council can decide what their next motion is. + type ExternalOrigin = pallet_collective::EnsureProportionAtLeast; + /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote + /// be tabled immediately and with a shorter voting/enactment period. + type FastTrackOrigin = pallet_collective::EnsureProportionAtLeast; + type FastTrackVotingPeriod = FastTrackVotingPeriod; + type InstantAllowed = frame_support::traits::ConstBool; + type InstantOrigin = pallet_collective::EnsureProportionAtLeast; + type LaunchPeriod = LaunchPeriod; + type MaxBlacklisted = (); + type MaxDeposits = (); + type MaxProposals = MaxProposals; + type MaxVotes = ConstU32<128>; + // Same as EnactmentPeriod + type MinimumDeposit = MinimumDeposit; type PalletsOrigin = OriginCaller; + type Preimages = Preimage; + type RuntimeEvent = RuntimeEvent; + type Scheduler = Scheduler; type Slash = (); type SubmitOrigin = EnsureSigned; + // Any single technical committee member may veto a coming council proposal, however they can + // only do it once and it lasts only for the cool-off period. + type VetoOrigin = pallet_collective::EnsureMember; + type VoteLockingPeriod = EnactmentPeriod; + type VotingPeriod = VotingPeriod; + type WeightInfo = pallet_democracy::weights::SubstrateWeight; } impl pallet_scheduler::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; + type MaxScheduledPerBlock = MaxScheduledPerBlock; + type MaximumWeight = MaximumSchedulerWeight; + type OriginPrivilegeCmp = EqualPrivilegeOnly; type PalletsOrigin = OriginCaller; + type Preimages = Preimage; type RuntimeCall = RuntimeCall; - type MaximumWeight = MaximumSchedulerWeight; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; type ScheduleOrigin = EnsureRoot; - type OriginPrivilegeCmp = EqualPrivilegeOnly; - type MaxScheduledPerBlock = MaxScheduledPerBlock; type WeightInfo = (); - type Preimages = Preimage; } impl pallet_utility::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; type PalletsOrigin = OriginCaller; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } impl pallet_multisig::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type RuntimeCall = RuntimeCall; type Currency = Balances; type DepositBase = DepositBase; type DepositFactor = DepositFactor; type MaxSignatories = MaxSignatories; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } impl pallet_preimage::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = (); - type Currency = Balances; - type ManagerOrigin = EnsureRoot; type BaseDeposit = PreimageBaseDeposit; type ByteDeposit = (); + type Currency = Balances; + type ManagerOrigin = EnsureRoot; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); } pub type LocalAssetsInstance = pallet_assets::Instance1; pub type StatemintAssetsInstance = pallet_assets::Instance2; impl pallet_assets::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Balance = Balance; - type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; + type ApprovalDeposit = ExistentialDeposit; + type AssetAccountDeposit = AssetAccountDeposit; + type AssetDeposit = AssetDeposit; type AssetId = AssetId; type AssetIdParameter = parity_scale_codec::Compact; - type Currency = Balances; + type Balance = Balance; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); + type CallbackHandle = (); type CreateOrigin = AsEnsureOriginWithArg>; + type Currency = Balances; + type Extra = (); type ForceOrigin = EnsureRoot; - type AssetDeposit = AssetDeposit; - type AssetAccountDeposit = AssetAccountDeposit; + type Freezer = (); type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type ApprovalDeposit = ExistentialDeposit; + type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; + type RuntimeEvent = RuntimeEvent; type StringLimit = AssetsStringLimit; - type Freezer = (); - type Extra = (); - type CallbackHandle = (); type WeightInfo = (); - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); } impl pallet_assets::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Balance = Balance; - type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; + type ApprovalDeposit = ExistentialDeposit; + type AssetAccountDeposit = AssetAccountDeposit; + type AssetDeposit = AssetDeposit; type AssetId = AssetId; type AssetIdParameter = parity_scale_codec::Compact; - type Currency = Balances; + type Balance = Balance; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); + type CallbackHandle = (); type CreateOrigin = AsEnsureOriginWithArg>; + type Currency = Balances; + type Extra = (); type ForceOrigin = EnsureRoot; - type AssetDeposit = AssetDeposit; - type AssetAccountDeposit = AssetAccountDeposit; + type Freezer = (); type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type ApprovalDeposit = ExistentialDeposit; + type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; + type RuntimeEvent = RuntimeEvent; type StringLimit = AssetsStringLimit; - type Freezer = (); - type Extra = (); - type CallbackHandle = (); type WeightInfo = (); - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); } impl pallet_vesting::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Currency = Balances; type BlockNumberToBalance = ConvertInto; + type Currency = Balances; type MinVestedTransfer = MinVestedTransfer; - type WeightInfo = pallet_vesting::weights::SubstrateWeight; + type RuntimeEvent = RuntimeEvent; type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; + type WeightInfo = pallet_vesting::weights::SubstrateWeight; + // `VestingInfo` encode length is 36bytes. 28 schedules gets encoded as 1009 bytes, which is the // highest number of schedules that encodes less than 2^10. const MAX_VESTING_SCHEDULES: u32 = 28; } impl pallet_parachain_staking::Config for Runtime { - type RuntimeEvent = RuntimeEvent; + type CandidateBondLessDelay = CandidateBondLessDelay; type Currency = Balances; - type MonetaryGovernanceOrigin = frame_system::EnsureRoot; - type MinBlocksPerRound = MinBlocksPerRound; + type DelegationBondLessDelay = DelegationBondLessDelay; type LeaveCandidatesDelay = LeaveCandidatesDelay; - type CandidateBondLessDelay = CandidateBondLessDelay; type LeaveDelegatorsDelay = LeaveDelegatorsDelay; - type RevokeDelegationDelay = RevokeDelegationDelay; - type DelegationBondLessDelay = DelegationBondLessDelay; - type RewardPaymentDelay = RewardPaymentDelay; - type MinSelectedCandidates = MinSelectedCandidates; - type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate; type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator; + type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; + type MinBlocksPerRound = MinBlocksPerRound; type MinCandidateStk = MinCandidateStk; - type MinDelegatorStk = MinDelegatorStk; type MinDelegation = MinDelegation; + type MinDelegatorStk = MinDelegatorStk; + type MinSelectedCandidates = MinSelectedCandidates; + type MonetaryGovernanceOrigin = frame_system::EnsureRoot; type OnCollatorPayout = (); + type OnNewRound = (); // We use the default implementation, so we leave () here. type PayoutCollatorReward = (); - type OnNewRound = (); + type RevokeDelegationDelay = RevokeDelegationDelay; + type RewardPaymentDelay = RewardPaymentDelay; + type RuntimeEvent = RuntimeEvent; type WeightInfo = pallet_parachain_staking::weights::SubstrateWeight; } @@ -851,17 +831,15 @@ impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { block: &Block, relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, ) -> sp_inherents::CheckInherentsResult { - let relay_chain_slot = relay_state_proof - .read_slot() - .expect("Could not read the relay chain slot from the proof"); - - let inherent_data = - cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( - relay_chain_slot, - sp_std::time::Duration::from_secs(6), - ) - .create_inherent_data() - .expect("Could not create the timestamp inherent data"); + let relay_chain_slot = + relay_state_proof.read_slot().expect("Could not read the relay chain slot from the proof"); + + let inherent_data = cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( + relay_chain_slot, + sp_std::time::Duration::from_secs(6), + ) + .create_inherent_data() + .expect("Could not create the timestamp inherent data"); inherent_data.check_extrinsics(block) } diff --git a/runtimes/testnet/src/xcm_config.rs b/runtimes/testnet/src/xcm_config.rs index 75b876ee7..1c43b34db 100644 --- a/runtimes/testnet/src/xcm_config.rs +++ b/runtimes/testnet/src/xcm_config.rs @@ -39,13 +39,11 @@ use polkadot_runtime_common::impls::ToAuthor; use sp_runtime::traits::Zero; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, - AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, - ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, - FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, ParentIsPreset, RelayChainAsNative, - SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, - WithComputedOrigin, + AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, + FixedRateOfFungible, FixedWeightBounds, FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, WithComputedOrigin, }; use xcm_executor::{ traits::{Convert, Error, JustTry, MatchesFungibles}, @@ -53,9 +51,9 @@ use xcm_executor::{ }; use super::{ - AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Balance, Balances, EnsureRoot, - ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, - StatemintAssets, WeightToFee, XcmpQueue, + AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Balance, Balances, EnsureRoot, ParachainInfo, + ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, StatemintAssets, WeightToFee, + XcmpQueue, }; const DOT_ASSET_ID: AssetId = Concrete(RelayLocation::get()); @@ -128,6 +126,7 @@ impl Convert for NativeToFungible { _ => Err(asset), } } + fn reverse(value: AssetIdPalletAssets) -> Result { if value == AssetIdPalletAssets::from(0u32) { Ok(MultiLocation { parents: 1, interior: Here }) @@ -151,10 +150,8 @@ impl< for NonBlockingConvertedConcreteId { fn matches_fungibles(a: &MultiAsset) -> Result<(AssetId, Balance), Error> { - ConvertedConcreteId::::matches_fungibles( - a, - ) - .map_err(|_| Error::AssetNotHandled) + ConvertedConcreteId::::matches_fungibles(a) + .map_err(|_| Error::AssetNotHandled) } } @@ -175,8 +172,7 @@ pub type StatemintDotTransactor = FungiblesAdapter< >; /// Means for transacting assets on this chain. -pub type AssetTransactors = - (CurrencyTransactor, StatemintDotTransactor, StatemintFungiblesTransactor); +pub type AssetTransactors = (CurrencyTransactor, StatemintDotTransactor, StatemintFungiblesTransactor); /// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, /// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can @@ -228,10 +224,7 @@ pub type Barrier = DenyThenTry< // If the message is one that immediately attemps to pay for execution, then allow it. AllowTopLevelPaidExecutionFrom, // Common Good Assets parachain, parent and its exec plurality get free execution - AllowExplicitUnpaidExecutionFrom<( - CommonGoodAssetsParachain, - ParentOrParentsExecutivePlurality, - )>, + AllowExplicitUnpaidExecutionFrom<(CommonGoodAssetsParachain, ParentOrParentsExecutivePlurality)>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, ), @@ -256,16 +249,10 @@ impl ContainsPair for StatemintAssetsFilter { &loc == origin && match asset { MultiAsset { - id: - Concrete(MultiLocation { - parents: 0, - interior: X2(PalletInstance(50), GeneralIndex(_)), - }), + id: Concrete(MultiLocation { parents: 0, interior: X2(PalletInstance(50), GeneralIndex(_)) }), .. } => true, - MultiAsset { - id: Concrete(MultiLocation { parents: 1, interior: Here }), .. - } => true, + MultiAsset { id: Concrete(MultiLocation { parents: 1, interior: Here }), .. } => true, _ => false, } @@ -363,35 +350,35 @@ pub type Reserves = (NativeAsset, StatemintAssetsFilter); pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { - type RuntimeCall = RuntimeCall; - type XcmSender = XcmRouter; + type AssetClaims = PolkadotXcm; + type AssetExchanger = (); + type AssetLocker = (); // How to withdraw and deposit an asset. type AssetTransactor = AssetTransactors; - type OriginConverter = XcmOriginToTransactDispatchOrigin; + type AssetTrap = PolkadotXcm; + type Barrier = Barrier; + type CallDispatcher = RuntimeCall; + type FeeManager = (); type IsReserve = Reserves; type IsTeleporter = NativeAsset; - type UniversalLocation = UniversalLocation; - type Barrier = Barrier; - type Weigher = FixedWeightBounds; + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type MessageExporter = (); + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type PalletInstancesInfo = AllPalletsWithSystem; + type ResponseHandler = PolkadotXcm; + type RuntimeCall = RuntimeCall; + // TODO: Restrict this to a subset of allowed `RuntimeCall`. + type SafeCallFilter = Everything; + type SubscriptionService = PolkadotXcm; type Trader = ( // TODO: weight to fee has to be carefully considered. For now use default UsingComponents>, FixedRateOfFungible, ); - type ResponseHandler = PolkadotXcm; - type AssetTrap = PolkadotXcm; - type AssetClaims = PolkadotXcm; - type SubscriptionService = PolkadotXcm; - type PalletInstancesInfo = AllPalletsWithSystem; - type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type AssetLocker = (); - type AssetExchanger = (); - type FeeManager = (); - type MessageExporter = (); type UniversalAliases = Nothing; - type CallDispatcher = RuntimeCall; - // TODO: Restrict this to a subset of allowed `RuntimeCall`. - type SafeCallFilter = Everything; + type UniversalLocation = UniversalLocation; + type Weigher = FixedWeightBounds; + type XcmSender = XcmRouter; } /// No local origins on this chain are allowed to dispatch XCM sends/executions. @@ -412,34 +399,34 @@ parameter_types! { } impl pallet_xcm::Config for Runtime { - type RuntimeEvent = RuntimeEvent; + type AdminOrigin = EnsureRoot; + // ^ Override for AdvertisedXcmVersion default + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; type Currency = Balances; type CurrencyMatcher = (); - type SendXcmOrigin = EnsureXcmOrigin; - type XcmRouter = XcmRouter; type ExecuteXcmOrigin = EnsureXcmOrigin; + type MaxLockers = ConstU32<8>; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type SendXcmOrigin = EnsureXcmOrigin; + type SovereignAccountOf = LocationToAccountId; + type TrustedLockers = (); + type UniversalLocation = UniversalLocation; + type Weigher = FixedWeightBounds; + type WeightInfo = pallet_xcm::TestWeightInfo; // TODO: change back to `Nothing` once we add the xcm functionalities into a pallet type XcmExecuteFilter = Everything; // ^ Disable dispatchable execute on the XCM pallet. // Needs to be `Everything` for local testing. type XcmExecutor = XcmExecutor; - type XcmTeleportFilter = Everything; type XcmReserveTransferFilter = Everything; - type Weigher = FixedWeightBounds; - type UniversalLocation = UniversalLocation; + type XcmRouter = XcmRouter; + type XcmTeleportFilter = Everything; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; - // ^ Override for AdvertisedXcmVersion default - type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; - type TrustedLockers = (); - type SovereignAccountOf = LocationToAccountId; - type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; - type AdminOrigin = EnsureRoot; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/rustfmt.toml b/rustfmt.toml index 6df3a1834..a7034e8d6 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,6 +1,6 @@ # Basic hard_tabs = true -max_width = 100 +max_width = 120 use_small_heuristics = "Max" # Imports imports_granularity = "Crate" @@ -8,17 +8,12 @@ reorder_imports = true # Consistency newline_style = "Unix" # Misc -chain_width = 80 spaces_around_ranges = false binop_separator = "Back" -reorder_impl_items = false +reorder_impl_items = true match_arm_leading_pipes = "Preserve" match_arm_blocks = false match_block_trailing_comma = true -trailing_comma = "Vertical" trailing_semicolon = false use_field_init_shorthand = true -ignore = [ - "bridges", -] edition = "2021" \ No newline at end of file From 5cd3a9f5c08d2d54e8fb0c6e0c51303017910ac1 Mon Sep 17 00:00:00 2001 From: Juan Ignacio RIos Date: Fri, 21 Jul 2023 10:32:41 +0200 Subject: [PATCH 38/80] chore(214): fix warnings --- .../pallets/funding/src/functions.rs | 5 ++--- polimec-skeleton/pallets/funding/src/tests.rs | 19 ++++++------------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/polimec-skeleton/pallets/funding/src/functions.rs b/polimec-skeleton/pallets/funding/src/functions.rs index edc18deae..45ecb29ba 100644 --- a/polimec-skeleton/pallets/funding/src/functions.rs +++ b/polimec-skeleton/pallets/funding/src/functions.rs @@ -32,7 +32,7 @@ use frame_support::{ Get, }, }; -use itertools::Itertools; + use sp_arithmetic::Perquintill; use sp_arithmetic::traits::{CheckedSub, Zero}; @@ -1726,8 +1726,7 @@ impl Pallet { let project_account = Self::fund_account_id(project_id); let plmc_price = T::PriceProvider::get_price(PLMC_STATEMINT_ID).ok_or(Error::::PLMCPriceNotAvailable)?; // sort bids by price, and equal prices sorted by block number - bids.sort(); - bids.reverse(); + bids.sort_by(|a, b| b.cmp(a)); // accept only bids that were made before `end_block` i.e end of candle auction let bids: Result, DispatchError> = bids .into_iter() diff --git a/polimec-skeleton/pallets/funding/src/tests.rs b/polimec-skeleton/pallets/funding/src/tests.rs index b903447bd..1aad61778 100644 --- a/polimec-skeleton/pallets/funding/src/tests.rs +++ b/polimec-skeleton/pallets/funding/src/tests.rs @@ -348,6 +348,7 @@ impl TestEnvironment { balances }) } + #[allow(dead_code)] fn get_all_reserved_plmc_balances(&self, reserve_type: LockType>) -> UserToPLMCBalance { self.ext_env.borrow_mut().execute_with(|| { let mut fundings = UserToPLMCBalance::new(); @@ -901,7 +902,7 @@ impl<'a> CommunityFundingProject<'a> { "Weighted average price should exist" ); - for mut filter in bid_expectations { + for filter in bid_expectations { let _found_bid = flattened_bids.iter().find(|bid| filter.matches_bid(&bid)).unwrap(); } @@ -1954,9 +1955,7 @@ mod evaluation_round_success { remainder_funding_project.end_funding(); test_env.advance_time(10).unwrap(); - let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc.iter().map(|(evaluator, amount)| (*evaluator, Zero::zero())).collect(); - - let temp_actual_par_lock = test_env.get_all_reserved_plmc_balances(LockType::Participation(project_id)); + let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc.iter().map(|(evaluator, _amount)| (*evaluator, Zero::zero())).collect(); test_env.do_reserved_plmc_assertions(post_unbond_amounts.clone(), LockType::Evaluation(project_id)); test_env.do_reserved_plmc_assertions(post_unbond_amounts, LockType::Participation(project_id)); @@ -1992,9 +1991,8 @@ mod evaluation_round_success { assert_eq!(finished_project.get_project_details().status, ProjectStatus::FundingFailed); test_env.advance_time(10).unwrap(); - let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc.iter().map(|(evaluator, amount)| (*evaluator, Zero::zero())).collect(); + let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc.iter().map(|(evaluator, _amount)| (*evaluator, Zero::zero())).collect(); - let temp_actual_par_lock = test_env.get_all_reserved_plmc_balances(LockType::Participation(project_id)); test_env.do_reserved_plmc_assertions(post_unbond_amounts.clone(), LockType::Evaluation(project_id)); test_env.do_reserved_plmc_assertions(post_unbond_amounts, LockType::Participation(project_id)); @@ -2826,9 +2824,6 @@ mod auction_round_failure { project_id, ); - let community_funding_project = auctioning_project.start_community_funding(); - let details = community_funding_project.get_project_details(); - test_env.do_free_plmc_assertions(vec![(BIDDER_1, get_ed()), (BIDDER_2, plmc_fundings[1].1 + get_ed())]); test_env.do_reserved_plmc_assertions( @@ -2902,9 +2897,6 @@ mod auction_round_failure { project_id, ); - let community_funding_project = auctioning_project.start_community_funding(); - let details = community_funding_project.get_project_details(); - test_env.do_free_plmc_assertions(vec![(BIDDER_1, get_ed()), (BIDDER_2, plmc_fundings[1].1 + get_ed())]); test_env.do_reserved_plmc_assertions( @@ -2928,6 +2920,7 @@ mod auction_round_failure { #[cfg(test)] mod community_round_success { + use frame_support::traits::fungible::Inspect; use super::*; pub const HOURS: BlockNumber = 300u64; @@ -3221,7 +3214,7 @@ mod community_round_success { // Check that the right amount of PLMC is bonded, and funding currency is transferred let contributor_post_buy_plmc_balance = - project.in_ext(|| ::NativeCurrency::free_balance(&CONTRIBUTOR)); + project.in_ext(|| ::NativeCurrency::balance(&CONTRIBUTOR)); let contributor_post_buy_statemint_asset_balance = project.in_ext(|| ::FundingCurrency::balance(USDT_STATEMINT_ID, &CONTRIBUTOR)); From dee16ba2d6a9aa9d644890bff05dc244434570f9 Mon Sep 17 00:00:00 2001 From: Juan Ignacio RIos Date: Fri, 21 Jul 2023 10:38:57 +0200 Subject: [PATCH 39/80] fix(214): broken auction unbond test fixed --- polimec-skeleton/pallets/funding/src/tests.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/polimec-skeleton/pallets/funding/src/tests.rs b/polimec-skeleton/pallets/funding/src/tests.rs index 1aad61778..640a72d8e 100644 --- a/polimec-skeleton/pallets/funding/src/tests.rs +++ b/polimec-skeleton/pallets/funding/src/tests.rs @@ -2824,6 +2824,8 @@ mod auction_round_failure { project_id, ); + let _community_funding_project = auctioning_project.start_community_funding(); + test_env.do_free_plmc_assertions(vec![(BIDDER_1, get_ed()), (BIDDER_2, plmc_fundings[1].1 + get_ed())]); test_env.do_reserved_plmc_assertions( @@ -2897,6 +2899,8 @@ mod auction_round_failure { project_id, ); + let _community_funding_project = auctioning_project.start_community_funding(); + test_env.do_free_plmc_assertions(vec![(BIDDER_1, get_ed()), (BIDDER_2, plmc_fundings[1].1 + get_ed())]); test_env.do_reserved_plmc_assertions( From 6affad0d0f145a7ddf9c7e91d6539fce3a91b950 Mon Sep 17 00:00:00 2001 From: Juan Ignacio RIos Date: Fri, 21 Jul 2023 10:39:46 +0200 Subject: [PATCH 40/80] chore(214): cargo fmt --- .../pallets/funding/src/functions.rs | 4 +- polimec-skeleton/pallets/funding/src/tests.rs | 94 +++++++++++++------ 2 files changed, 65 insertions(+), 33 deletions(-) diff --git a/polimec-skeleton/pallets/funding/src/functions.rs b/polimec-skeleton/pallets/funding/src/functions.rs index 45ecb29ba..fe8bd4c19 100644 --- a/polimec-skeleton/pallets/funding/src/functions.rs +++ b/polimec-skeleton/pallets/funding/src/functions.rs @@ -639,8 +639,8 @@ impl Pallet { // * Validity checks * ensure!( remaining_cts == 0u32.into() - || project_details.status == ProjectStatus::FundingFailed - || matches!(remainder_end_block, Some(end_block) if now > end_block), + || project_details.status == ProjectStatus::FundingFailed + || matches!(remainder_end_block, Some(end_block) if now > end_block), Error::::TooEarlyForFundingEnd ); diff --git a/polimec-skeleton/pallets/funding/src/tests.rs b/polimec-skeleton/pallets/funding/src/tests.rs index 640a72d8e..8dd7aacb9 100644 --- a/polimec-skeleton/pallets/funding/src/tests.rs +++ b/polimec-skeleton/pallets/funding/src/tests.rs @@ -100,7 +100,17 @@ impl TestContribution { pub type TestContributions = Vec; #[derive(Clone, PartialEq, Eq, Debug)] -pub struct BidInfoFilter { +pub struct BidInfoFilter< + Id, + ProjectId, + Balance: BalanceT, + Price, + AccountId, + Multiplier, + BlockNumber, + PlmcVesting, + CTVesting, +> { pub id: Option, pub project_id: Option, pub bidder: Option, @@ -182,7 +192,9 @@ impl BidInfoFilterOf { if self.funding_asset.is_some() && self.funding_asset.unwrap() != bid.funding_asset { return false; } - if self.funding_asset_amount_locked.is_some() && self.funding_asset_amount_locked.unwrap() != bid.funding_asset_amount_locked { + if self.funding_asset_amount_locked.is_some() + && self.funding_asset_amount_locked.unwrap() != bid.funding_asset_amount_locked + { return false; } if self.multiplier.is_some() && self.multiplier.unwrap() != bid.multiplier { @@ -385,7 +397,9 @@ impl TestEnvironment { balances }) } - fn get_reserved_plmc_balances_for(&self, user_keys: Vec, lock_type: LockType>) -> UserToPLMCBalance { + fn get_reserved_plmc_balances_for( + &self, user_keys: Vec, lock_type: LockType>, + ) -> UserToPLMCBalance { self.ext_env.borrow_mut().execute_with(|| { let mut balances = UserToPLMCBalance::new(); for user in user_keys { @@ -1601,15 +1615,12 @@ pub mod helper_functions { frame_system::EventRecord { event: RuntimeEvent::FundingModule(Event::TransitionError { project_id: _, error }), .. - } => { - match error { - DispatchError::Module(module_error) => { - let pallet_error: Error = Decode::decode(&mut &module_error.error[..]).unwrap(); - Err(pallet_error) - - } - _ => panic!("wrong conversion") + } => match error { + DispatchError::Module(module_error) => { + let pallet_error: Error = Decode::decode(&mut &module_error.error[..]).unwrap(); + Err(pallet_error) } + _ => panic!("wrong conversion"), }, _ => Ok(()), } @@ -1937,7 +1948,7 @@ mod evaluation_round_success { fn plmc_unbonded_after_funding_success() { let test_env = TestEnvironment::new(); let evaluations = default_evaluations(); - let evaluators = evaluations.iter().map(|ev|ev.0.clone()).collect::>(); + let evaluators = evaluations.iter().map(|ev| ev.0.clone()).collect::>(); let remainder_funding_project = RemainderFundingProject::new_with( &test_env, @@ -1948,14 +1959,18 @@ mod evaluation_round_success { default_community_buys(), ); let project_id = remainder_funding_project.get_project_id(); - let prev_reserved_plmc = test_env.get_reserved_plmc_balances_for(evaluators.clone(), LockType::Evaluation(project_id)); + let prev_reserved_plmc = + test_env.get_reserved_plmc_balances_for(evaluators.clone(), LockType::Evaluation(project_id)); let prev_free_plmc = test_env.get_free_plmc_balances_for(evaluators.clone()); remainder_funding_project.end_funding(); test_env.advance_time(10).unwrap(); - let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc.iter().map(|(evaluator, _amount)| (*evaluator, Zero::zero())).collect(); + let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc + .iter() + .map(|(evaluator, _amount)| (*evaluator, Zero::zero())) + .collect(); test_env.do_reserved_plmc_assertions(post_unbond_amounts.clone(), LockType::Evaluation(project_id)); test_env.do_reserved_plmc_assertions(post_unbond_amounts, LockType::Participation(project_id)); @@ -1971,28 +1986,45 @@ mod evaluation_round_success { fn plmc_unbonded_after_funding_failure() { let test_env = TestEnvironment::new(); let evaluations = default_evaluations(); - let evaluators = evaluations.iter().map(|ev|ev.0.clone()).collect::>(); + let evaluators = evaluations.iter().map(|ev| ev.0.clone()).collect::>(); let remainder_funding_project = RemainderFundingProject::new_with( &test_env, default_project(test_env.get_new_nonce()), ISSUER, evaluations.clone(), - vec![TestBid::new(BUYER_1, 1000 * ASSET_UNIT, 10u128.into(), None, AcceptedFundingAsset::USDT)], - vec![TestContribution::new(BUYER_1, 1000 * US_DOLLAR, None, AcceptedFundingAsset::USDT)], + vec![TestBid::new( + BUYER_1, + 1000 * ASSET_UNIT, + 10u128.into(), + None, + AcceptedFundingAsset::USDT, + )], + vec![TestContribution::new( + BUYER_1, + 1000 * US_DOLLAR, + None, + AcceptedFundingAsset::USDT, + )], ); let project_id = remainder_funding_project.get_project_id(); - let prev_reserved_plmc = test_env.get_reserved_plmc_balances_for(evaluators.clone(), LockType::Evaluation(project_id)); + let prev_reserved_plmc = + test_env.get_reserved_plmc_balances_for(evaluators.clone(), LockType::Evaluation(project_id)); let prev_free_plmc = test_env.get_free_plmc_balances_for(evaluators.clone()); let finished_project = remainder_funding_project.end_funding(); - assert_eq!(finished_project.get_project_details().status, ProjectStatus::FundingFailed); + assert_eq!( + finished_project.get_project_details().status, + ProjectStatus::FundingFailed + ); test_env.advance_time(10).unwrap(); - let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc.iter().map(|(evaluator, _amount)| (*evaluator, Zero::zero())).collect(); - + let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc + .iter() + .map(|(evaluator, _amount)| (*evaluator, Zero::zero())) + .collect(); test_env.do_reserved_plmc_assertions(post_unbond_amounts.clone(), LockType::Evaluation(project_id)); test_env.do_reserved_plmc_assertions(post_unbond_amounts, LockType::Participation(project_id)); @@ -2003,8 +2035,6 @@ mod evaluation_round_success { assert_eq!(increased_amounts, calculate_evaluation_plmc_spent(evaluations)) } - - } #[cfg(test)] @@ -2868,11 +2898,13 @@ mod auction_round_failure { .bid_for_users(vec![bid_in]) .expect("Bids should pass"); - test_env.advance_time( - ::EnglishAuctionDuration::get() - + ::CandleAuctionDuration::get() - - 1, - ).unwrap(); + test_env + .advance_time( + ::EnglishAuctionDuration::get() + + ::CandleAuctionDuration::get() + - 1, + ) + .unwrap(); auctioning_project .bid_for_users(vec![bid_out]) @@ -2924,8 +2956,8 @@ mod auction_round_failure { #[cfg(test)] mod community_round_success { - use frame_support::traits::fungible::Inspect; use super::*; + use frame_support::traits::fungible::Inspect; pub const HOURS: BlockNumber = 300u64; @@ -3671,7 +3703,7 @@ mod remainder_round_success { ISSUER, default_evaluations(), default_bids(), - default_community_buys() + default_community_buys(), ); const BOB: AccountId = 808; @@ -3737,7 +3769,7 @@ mod remainder_round_success { ISSUER, default_evaluations(), default_bids(), - default_community_buys() + default_community_buys(), ); const BOB: AccountId = 808; const OVERBUY_CT: BalanceOf = 40 * ASSET_UNIT; From cca032cdea3ab80430aca4eb04ea813d7241559d Mon Sep 17 00:00:00 2001 From: Juan Ignacio RIos Date: Fri, 21 Jul 2023 10:42:15 +0200 Subject: [PATCH 41/80] chore(214): unsafe math fix --- polimec-skeleton/pallets/funding/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polimec-skeleton/pallets/funding/src/lib.rs b/polimec-skeleton/pallets/funding/src/lib.rs index 8aa43afc4..771ffe272 100644 --- a/polimec-skeleton/pallets/funding/src/lib.rs +++ b/polimec-skeleton/pallets/funding/src/lib.rs @@ -946,7 +946,7 @@ pub mod pallet { let mut consumed_weight = T::WeightInfo::insert_cleaned_project(); while !consumed_weight.any_gt(max_weight_per_project) { if let Ok(weight) = project_finalizer.do_one_operation::(project_id) { - consumed_weight += weight + consumed_weight.saturating_accrue(weight); } else { break; } From 0b3beb8c817ee7755f8c261903e0a1c33b187671 Mon Sep 17 00:00:00 2001 From: Juan Ignacio RIos Date: Fri, 21 Jul 2023 11:50:59 +0200 Subject: [PATCH 42/80] chore(220): reorder imports --- polimec-skeleton/pallets/funding/src/lib.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/polimec-skeleton/pallets/funding/src/lib.rs b/polimec-skeleton/pallets/funding/src/lib.rs index 771ffe272..eb5ca7fbe 100644 --- a/polimec-skeleton/pallets/funding/src/lib.rs +++ b/polimec-skeleton/pallets/funding/src/lib.rs @@ -177,14 +177,9 @@ // we add more without this limit. #![cfg_attr(feature = "runtime-benchmarks", recursion_limit = "512")] -pub use pallet::*; - pub mod types; -pub use types::*; - pub mod weights; - -mod functions; +pub mod functions; #[cfg(test)] pub mod mock; @@ -193,10 +188,13 @@ pub mod mock; pub mod tests; #[cfg(feature = "runtime-benchmarks")] -mod benchmarking; -mod impls; +pub mod benchmarking; +pub mod impls; pub mod traits; +pub use pallet::*; +pub use types::*; + #[allow(unused_imports)] use polimec_traits::{MemberRole, PolimecMembers}; From 69ff08e1780d0b6b6ee35df83dadaa77a8590140 Mon Sep 17 00:00:00 2001 From: Juan Ignacio RIos Date: Fri, 21 Jul 2023 12:04:38 +0200 Subject: [PATCH 43/80] feat(220): do_evaluation_end uses the config type as threshold. Config type renamed --- polimec-skeleton/pallets/funding/src/functions.rs | 4 ++-- polimec-skeleton/pallets/funding/src/lib.rs | 2 +- polimec-skeleton/runtime/src/lib.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/polimec-skeleton/pallets/funding/src/functions.rs b/polimec-skeleton/pallets/funding/src/functions.rs index fe8bd4c19..3762e8dd3 100644 --- a/polimec-skeleton/pallets/funding/src/functions.rs +++ b/polimec-skeleton/pallets/funding/src/functions.rs @@ -247,7 +247,7 @@ impl Pallet { total.saturating_add(user_total_plmc_bond) }); - let evaluation_target_usd = Perquintill::from_percent(10) * fundraising_target_usd; + let evaluation_target_usd = ::EvaluationSuccessThreshold::get() * fundraising_target_usd; let evaluation_target_plmc = current_plmc_price .reciprocal() .ok_or(Error::::BadMath)? @@ -790,7 +790,7 @@ impl Pallet { let mut caller_existing_evaluations = Evaluations::::get(project_id, evaluator.clone()); let plmc_usd_price = T::PriceProvider::get_price(PLMC_STATEMINT_ID).ok_or(Error::::PLMCPriceNotAvailable)?; let early_evaluation_reward_threshold_usd = - T::EarlyEvaluationThreshold::get() * project_details.fundraising_target; + T::EvaluationSuccessThreshold::get() * project_details.fundraising_target; let evaluation_round_info = &mut project_details.evaluation_round_info; // * Validity Checks * diff --git a/polimec-skeleton/pallets/funding/src/lib.rs b/polimec-skeleton/pallets/funding/src/lib.rs index eb5ca7fbe..8a9bafd41 100644 --- a/polimec-skeleton/pallets/funding/src/lib.rs +++ b/polimec-skeleton/pallets/funding/src/lib.rs @@ -381,7 +381,7 @@ pub mod pallet { type FeeBrackets: Get>; - type EarlyEvaluationThreshold: Get; + type EvaluationSuccessThreshold: Get; } #[pallet::storage] diff --git a/polimec-skeleton/runtime/src/lib.rs b/polimec-skeleton/runtime/src/lib.rs index e764445a1..0dc93dd96 100644 --- a/polimec-skeleton/runtime/src/lib.rs +++ b/polimec-skeleton/runtime/src/lib.rs @@ -602,7 +602,7 @@ impl pallet_funding::Config for Runtime { type BenchmarkHelper = (); type WeightInfo = (); type FeeBrackets = FeeBrackets; - type EarlyEvaluationThreshold = EarlyEvaluationThreshold; + type EvaluationSuccessThreshold = EarlyEvaluationThreshold; } impl pallet_credentials::Config for Runtime { From d5b4430efc42bdfdf72453b5d2e0262ee2ff2ca2 Mon Sep 17 00:00:00 2001 From: lrazovic <4128940+lrazovic@users.noreply.github.com> Date: Tue, 18 Jul 2023 23:02:45 +0200 Subject: [PATCH 44/80] feat: add linear release to the funding pallet --- polimec-skeleton/pallets/linear-release/src/lib.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/lib.rs b/polimec-skeleton/pallets/linear-release/src/lib.rs index ceb9645b3..fe36643a6 100644 --- a/polimec-skeleton/pallets/linear-release/src/lib.rs +++ b/polimec-skeleton/pallets/linear-release/src/lib.rs @@ -317,11 +317,7 @@ pub mod pallet { let transactor = ensure_signed(origin)?; Self::do_vested_transfer(transactor, target, schedule, reason) } - /// Force a vested transfer. - /// - /// The dispatch origin for this call must be _Root_. - /// /// - `source`: The account whose funds should be transferred. /// - `target`: The account that should be transferred the vested funds. /// - `schedule`: The vesting schedule attached to the transfer. From 1020a30fca5fcf8e616a938974af640b16002b3f Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:45:12 +0200 Subject: [PATCH 45/80] tests: fix the used reason --- polimec-skeleton/pallets/linear-release/src/tests.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/tests.rs b/polimec-skeleton/pallets/linear-release/src/tests.rs index 3703b0a01..966b345ce 100644 --- a/polimec-skeleton/pallets/linear-release/src/tests.rs +++ b/polimec-skeleton/pallets/linear-release/src/tests.rs @@ -23,7 +23,7 @@ where T: pallet::Config, { // Its ok for this to fail because the user may already have no schedules. - let _result: Result<(), DispatchError> = Vesting::vest(Some(account).into(), LockType::Participation(0)); + let _result: Result<(), DispatchError> = Vesting::vest(Some(account).into(), reason); assert!(!>::contains_key(account, reason)); } @@ -1257,14 +1257,12 @@ fn multile_holds_release_schedule() { assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(1)), Some(7 * ED)); System::set_block_number(16); - assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(0))); - assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), None); + vest_and_assert_no_vesting::(3, LockType::Participation(0)); let user_3_free_balance = Balances::free_balance(&3); assert_eq!(user_3_free_balance, 23 * ED); System::set_block_number(100); - assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(1))); - assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(1)), None); + vest_and_assert_no_vesting::(3, LockType::Participation(1)); let user_3_free_balance = Balances::free_balance(&3); assert_eq!(user_3_free_balance, 30 * ED); }); From 640ce58f08894ecbf7e7bfd67fdb92e73d5d882a Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:50:49 +0200 Subject: [PATCH 46/80] Revert "tests: fix the used reason" This reverts commit 1020a30fca5fcf8e616a938974af640b16002b3f. --- polimec-skeleton/pallets/linear-release/src/tests.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/tests.rs b/polimec-skeleton/pallets/linear-release/src/tests.rs index 966b345ce..3703b0a01 100644 --- a/polimec-skeleton/pallets/linear-release/src/tests.rs +++ b/polimec-skeleton/pallets/linear-release/src/tests.rs @@ -23,7 +23,7 @@ where T: pallet::Config, { // Its ok for this to fail because the user may already have no schedules. - let _result: Result<(), DispatchError> = Vesting::vest(Some(account).into(), reason); + let _result: Result<(), DispatchError> = Vesting::vest(Some(account).into(), LockType::Participation(0)); assert!(!>::contains_key(account, reason)); } @@ -1257,12 +1257,14 @@ fn multile_holds_release_schedule() { assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(1)), Some(7 * ED)); System::set_block_number(16); - vest_and_assert_no_vesting::(3, LockType::Participation(0)); + assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(0))); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), None); let user_3_free_balance = Balances::free_balance(&3); assert_eq!(user_3_free_balance, 23 * ED); System::set_block_number(100); - vest_and_assert_no_vesting::(3, LockType::Participation(1)); + assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(1))); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(1)), None); let user_3_free_balance = Balances::free_balance(&3); assert_eq!(user_3_free_balance, 30 * ED); }); From 749be272fb0ace73c0f1e6e58ffb6904c66db48c Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:50:51 +0200 Subject: [PATCH 47/80] Revert "feat: add linear release to the funding pallet" This reverts commit d5b4430efc42bdfdf72453b5d2e0262ee2ff2ca2. --- polimec-skeleton/pallets/linear-release/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/polimec-skeleton/pallets/linear-release/src/lib.rs b/polimec-skeleton/pallets/linear-release/src/lib.rs index fe36643a6..ceb9645b3 100644 --- a/polimec-skeleton/pallets/linear-release/src/lib.rs +++ b/polimec-skeleton/pallets/linear-release/src/lib.rs @@ -317,7 +317,11 @@ pub mod pallet { let transactor = ensure_signed(origin)?; Self::do_vested_transfer(transactor, target, schedule, reason) } + /// Force a vested transfer. + /// + /// The dispatch origin for this call must be _Root_. + /// /// - `source`: The account whose funds should be transferred. /// - `target`: The account that should be transferred the vested funds. /// - `schedule`: The vesting schedule attached to the transfer. From ef0f2e9ed26420db07ee06f169aaf3fea44eac3d Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:50:52 +0200 Subject: [PATCH 48/80] Revert "feat(220): do_evaluation_end uses the config type as threshold. Config type renamed" This reverts commit 69ff08e1780d0b6b6ee35df83dadaa77a8590140. --- polimec-skeleton/pallets/funding/src/functions.rs | 4 ++-- polimec-skeleton/pallets/funding/src/lib.rs | 2 +- polimec-skeleton/runtime/src/lib.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/polimec-skeleton/pallets/funding/src/functions.rs b/polimec-skeleton/pallets/funding/src/functions.rs index 3762e8dd3..fe8bd4c19 100644 --- a/polimec-skeleton/pallets/funding/src/functions.rs +++ b/polimec-skeleton/pallets/funding/src/functions.rs @@ -247,7 +247,7 @@ impl Pallet { total.saturating_add(user_total_plmc_bond) }); - let evaluation_target_usd = ::EvaluationSuccessThreshold::get() * fundraising_target_usd; + let evaluation_target_usd = Perquintill::from_percent(10) * fundraising_target_usd; let evaluation_target_plmc = current_plmc_price .reciprocal() .ok_or(Error::::BadMath)? @@ -790,7 +790,7 @@ impl Pallet { let mut caller_existing_evaluations = Evaluations::::get(project_id, evaluator.clone()); let plmc_usd_price = T::PriceProvider::get_price(PLMC_STATEMINT_ID).ok_or(Error::::PLMCPriceNotAvailable)?; let early_evaluation_reward_threshold_usd = - T::EvaluationSuccessThreshold::get() * project_details.fundraising_target; + T::EarlyEvaluationThreshold::get() * project_details.fundraising_target; let evaluation_round_info = &mut project_details.evaluation_round_info; // * Validity Checks * diff --git a/polimec-skeleton/pallets/funding/src/lib.rs b/polimec-skeleton/pallets/funding/src/lib.rs index 8a9bafd41..eb5ca7fbe 100644 --- a/polimec-skeleton/pallets/funding/src/lib.rs +++ b/polimec-skeleton/pallets/funding/src/lib.rs @@ -381,7 +381,7 @@ pub mod pallet { type FeeBrackets: Get>; - type EvaluationSuccessThreshold: Get; + type EarlyEvaluationThreshold: Get; } #[pallet::storage] diff --git a/polimec-skeleton/runtime/src/lib.rs b/polimec-skeleton/runtime/src/lib.rs index 0dc93dd96..e764445a1 100644 --- a/polimec-skeleton/runtime/src/lib.rs +++ b/polimec-skeleton/runtime/src/lib.rs @@ -602,7 +602,7 @@ impl pallet_funding::Config for Runtime { type BenchmarkHelper = (); type WeightInfo = (); type FeeBrackets = FeeBrackets; - type EvaluationSuccessThreshold = EarlyEvaluationThreshold; + type EarlyEvaluationThreshold = EarlyEvaluationThreshold; } impl pallet_credentials::Config for Runtime { From daac339cf41882b9af0286570192f9ff3170264e Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:50:52 +0200 Subject: [PATCH 49/80] Revert "chore(220): reorder imports" This reverts commit 0b3beb8c817ee7755f8c261903e0a1c33b187671. --- polimec-skeleton/pallets/funding/src/lib.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/polimec-skeleton/pallets/funding/src/lib.rs b/polimec-skeleton/pallets/funding/src/lib.rs index eb5ca7fbe..771ffe272 100644 --- a/polimec-skeleton/pallets/funding/src/lib.rs +++ b/polimec-skeleton/pallets/funding/src/lib.rs @@ -177,9 +177,14 @@ // we add more without this limit. #![cfg_attr(feature = "runtime-benchmarks", recursion_limit = "512")] +pub use pallet::*; + pub mod types; +pub use types::*; + pub mod weights; -pub mod functions; + +mod functions; #[cfg(test)] pub mod mock; @@ -188,13 +193,10 @@ pub mod mock; pub mod tests; #[cfg(feature = "runtime-benchmarks")] -pub mod benchmarking; -pub mod impls; +mod benchmarking; +mod impls; pub mod traits; -pub use pallet::*; -pub use types::*; - #[allow(unused_imports)] use polimec_traits::{MemberRole, PolimecMembers}; From 2b0a9acb282ab4c2e1a0d61984ccbbc1f35bb4c7 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:50:53 +0200 Subject: [PATCH 50/80] Revert "chore(214): unsafe math fix" This reverts commit cca032cdea3ab80430aca4eb04ea813d7241559d. --- polimec-skeleton/pallets/funding/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polimec-skeleton/pallets/funding/src/lib.rs b/polimec-skeleton/pallets/funding/src/lib.rs index 771ffe272..8aa43afc4 100644 --- a/polimec-skeleton/pallets/funding/src/lib.rs +++ b/polimec-skeleton/pallets/funding/src/lib.rs @@ -946,7 +946,7 @@ pub mod pallet { let mut consumed_weight = T::WeightInfo::insert_cleaned_project(); while !consumed_weight.any_gt(max_weight_per_project) { if let Ok(weight) = project_finalizer.do_one_operation::(project_id) { - consumed_weight.saturating_accrue(weight); + consumed_weight += weight } else { break; } From fc4c5b97f1e6d06239976e75c43c3f1c19ba0ba5 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:50:53 +0200 Subject: [PATCH 51/80] Revert "chore(214): cargo fmt" This reverts commit 6affad0d0f145a7ddf9c7e91d6539fce3a91b950. --- .../pallets/funding/src/functions.rs | 4 +- polimec-skeleton/pallets/funding/src/tests.rs | 94 ++++++------------- 2 files changed, 33 insertions(+), 65 deletions(-) diff --git a/polimec-skeleton/pallets/funding/src/functions.rs b/polimec-skeleton/pallets/funding/src/functions.rs index fe8bd4c19..45ecb29ba 100644 --- a/polimec-skeleton/pallets/funding/src/functions.rs +++ b/polimec-skeleton/pallets/funding/src/functions.rs @@ -639,8 +639,8 @@ impl Pallet { // * Validity checks * ensure!( remaining_cts == 0u32.into() - || project_details.status == ProjectStatus::FundingFailed - || matches!(remainder_end_block, Some(end_block) if now > end_block), + || project_details.status == ProjectStatus::FundingFailed + || matches!(remainder_end_block, Some(end_block) if now > end_block), Error::::TooEarlyForFundingEnd ); diff --git a/polimec-skeleton/pallets/funding/src/tests.rs b/polimec-skeleton/pallets/funding/src/tests.rs index 8dd7aacb9..640a72d8e 100644 --- a/polimec-skeleton/pallets/funding/src/tests.rs +++ b/polimec-skeleton/pallets/funding/src/tests.rs @@ -100,17 +100,7 @@ impl TestContribution { pub type TestContributions = Vec; #[derive(Clone, PartialEq, Eq, Debug)] -pub struct BidInfoFilter< - Id, - ProjectId, - Balance: BalanceT, - Price, - AccountId, - Multiplier, - BlockNumber, - PlmcVesting, - CTVesting, -> { +pub struct BidInfoFilter { pub id: Option, pub project_id: Option, pub bidder: Option, @@ -192,9 +182,7 @@ impl BidInfoFilterOf { if self.funding_asset.is_some() && self.funding_asset.unwrap() != bid.funding_asset { return false; } - if self.funding_asset_amount_locked.is_some() - && self.funding_asset_amount_locked.unwrap() != bid.funding_asset_amount_locked - { + if self.funding_asset_amount_locked.is_some() && self.funding_asset_amount_locked.unwrap() != bid.funding_asset_amount_locked { return false; } if self.multiplier.is_some() && self.multiplier.unwrap() != bid.multiplier { @@ -397,9 +385,7 @@ impl TestEnvironment { balances }) } - fn get_reserved_plmc_balances_for( - &self, user_keys: Vec, lock_type: LockType>, - ) -> UserToPLMCBalance { + fn get_reserved_plmc_balances_for(&self, user_keys: Vec, lock_type: LockType>) -> UserToPLMCBalance { self.ext_env.borrow_mut().execute_with(|| { let mut balances = UserToPLMCBalance::new(); for user in user_keys { @@ -1615,12 +1601,15 @@ pub mod helper_functions { frame_system::EventRecord { event: RuntimeEvent::FundingModule(Event::TransitionError { project_id: _, error }), .. - } => match error { - DispatchError::Module(module_error) => { - let pallet_error: Error = Decode::decode(&mut &module_error.error[..]).unwrap(); - Err(pallet_error) + } => { + match error { + DispatchError::Module(module_error) => { + let pallet_error: Error = Decode::decode(&mut &module_error.error[..]).unwrap(); + Err(pallet_error) + + } + _ => panic!("wrong conversion") } - _ => panic!("wrong conversion"), }, _ => Ok(()), } @@ -1948,7 +1937,7 @@ mod evaluation_round_success { fn plmc_unbonded_after_funding_success() { let test_env = TestEnvironment::new(); let evaluations = default_evaluations(); - let evaluators = evaluations.iter().map(|ev| ev.0.clone()).collect::>(); + let evaluators = evaluations.iter().map(|ev|ev.0.clone()).collect::>(); let remainder_funding_project = RemainderFundingProject::new_with( &test_env, @@ -1959,18 +1948,14 @@ mod evaluation_round_success { default_community_buys(), ); let project_id = remainder_funding_project.get_project_id(); - let prev_reserved_plmc = - test_env.get_reserved_plmc_balances_for(evaluators.clone(), LockType::Evaluation(project_id)); + let prev_reserved_plmc = test_env.get_reserved_plmc_balances_for(evaluators.clone(), LockType::Evaluation(project_id)); let prev_free_plmc = test_env.get_free_plmc_balances_for(evaluators.clone()); remainder_funding_project.end_funding(); test_env.advance_time(10).unwrap(); - let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc - .iter() - .map(|(evaluator, _amount)| (*evaluator, Zero::zero())) - .collect(); + let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc.iter().map(|(evaluator, _amount)| (*evaluator, Zero::zero())).collect(); test_env.do_reserved_plmc_assertions(post_unbond_amounts.clone(), LockType::Evaluation(project_id)); test_env.do_reserved_plmc_assertions(post_unbond_amounts, LockType::Participation(project_id)); @@ -1986,45 +1971,28 @@ mod evaluation_round_success { fn plmc_unbonded_after_funding_failure() { let test_env = TestEnvironment::new(); let evaluations = default_evaluations(); - let evaluators = evaluations.iter().map(|ev| ev.0.clone()).collect::>(); + let evaluators = evaluations.iter().map(|ev|ev.0.clone()).collect::>(); let remainder_funding_project = RemainderFundingProject::new_with( &test_env, default_project(test_env.get_new_nonce()), ISSUER, evaluations.clone(), - vec![TestBid::new( - BUYER_1, - 1000 * ASSET_UNIT, - 10u128.into(), - None, - AcceptedFundingAsset::USDT, - )], - vec![TestContribution::new( - BUYER_1, - 1000 * US_DOLLAR, - None, - AcceptedFundingAsset::USDT, - )], + vec![TestBid::new(BUYER_1, 1000 * ASSET_UNIT, 10u128.into(), None, AcceptedFundingAsset::USDT)], + vec![TestContribution::new(BUYER_1, 1000 * US_DOLLAR, None, AcceptedFundingAsset::USDT)], ); let project_id = remainder_funding_project.get_project_id(); - let prev_reserved_plmc = - test_env.get_reserved_plmc_balances_for(evaluators.clone(), LockType::Evaluation(project_id)); + let prev_reserved_plmc = test_env.get_reserved_plmc_balances_for(evaluators.clone(), LockType::Evaluation(project_id)); let prev_free_plmc = test_env.get_free_plmc_balances_for(evaluators.clone()); let finished_project = remainder_funding_project.end_funding(); - assert_eq!( - finished_project.get_project_details().status, - ProjectStatus::FundingFailed - ); + assert_eq!(finished_project.get_project_details().status, ProjectStatus::FundingFailed); test_env.advance_time(10).unwrap(); - let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc - .iter() - .map(|(evaluator, _amount)| (*evaluator, Zero::zero())) - .collect(); + let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc.iter().map(|(evaluator, _amount)| (*evaluator, Zero::zero())).collect(); + test_env.do_reserved_plmc_assertions(post_unbond_amounts.clone(), LockType::Evaluation(project_id)); test_env.do_reserved_plmc_assertions(post_unbond_amounts, LockType::Participation(project_id)); @@ -2035,6 +2003,8 @@ mod evaluation_round_success { assert_eq!(increased_amounts, calculate_evaluation_plmc_spent(evaluations)) } + + } #[cfg(test)] @@ -2898,13 +2868,11 @@ mod auction_round_failure { .bid_for_users(vec![bid_in]) .expect("Bids should pass"); - test_env - .advance_time( - ::EnglishAuctionDuration::get() - + ::CandleAuctionDuration::get() - - 1, - ) - .unwrap(); + test_env.advance_time( + ::EnglishAuctionDuration::get() + + ::CandleAuctionDuration::get() + - 1, + ).unwrap(); auctioning_project .bid_for_users(vec![bid_out]) @@ -2956,8 +2924,8 @@ mod auction_round_failure { #[cfg(test)] mod community_round_success { - use super::*; use frame_support::traits::fungible::Inspect; + use super::*; pub const HOURS: BlockNumber = 300u64; @@ -3703,7 +3671,7 @@ mod remainder_round_success { ISSUER, default_evaluations(), default_bids(), - default_community_buys(), + default_community_buys() ); const BOB: AccountId = 808; @@ -3769,7 +3737,7 @@ mod remainder_round_success { ISSUER, default_evaluations(), default_bids(), - default_community_buys(), + default_community_buys() ); const BOB: AccountId = 808; const OVERBUY_CT: BalanceOf = 40 * ASSET_UNIT; From 528e6f0fbf9236b9943a97a0160d29773012554c Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:50:54 +0200 Subject: [PATCH 52/80] Revert "fix(214): broken auction unbond test fixed" This reverts commit dee16ba2d6a9aa9d644890bff05dc244434570f9. --- polimec-skeleton/pallets/funding/src/tests.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/polimec-skeleton/pallets/funding/src/tests.rs b/polimec-skeleton/pallets/funding/src/tests.rs index 640a72d8e..1aad61778 100644 --- a/polimec-skeleton/pallets/funding/src/tests.rs +++ b/polimec-skeleton/pallets/funding/src/tests.rs @@ -2824,8 +2824,6 @@ mod auction_round_failure { project_id, ); - let _community_funding_project = auctioning_project.start_community_funding(); - test_env.do_free_plmc_assertions(vec![(BIDDER_1, get_ed()), (BIDDER_2, plmc_fundings[1].1 + get_ed())]); test_env.do_reserved_plmc_assertions( @@ -2899,8 +2897,6 @@ mod auction_round_failure { project_id, ); - let _community_funding_project = auctioning_project.start_community_funding(); - test_env.do_free_plmc_assertions(vec![(BIDDER_1, get_ed()), (BIDDER_2, plmc_fundings[1].1 + get_ed())]); test_env.do_reserved_plmc_assertions( From a8baa84a75087e988c25668b091ea4a9a84a756f Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:50:54 +0200 Subject: [PATCH 53/80] Revert "chore(214): fix warnings" This reverts commit 5cd3a9f5c08d2d54e8fb0c6e0c51303017910ac1. --- .../pallets/funding/src/functions.rs | 5 +++-- polimec-skeleton/pallets/funding/src/tests.rs | 19 +++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/polimec-skeleton/pallets/funding/src/functions.rs b/polimec-skeleton/pallets/funding/src/functions.rs index 45ecb29ba..edc18deae 100644 --- a/polimec-skeleton/pallets/funding/src/functions.rs +++ b/polimec-skeleton/pallets/funding/src/functions.rs @@ -32,7 +32,7 @@ use frame_support::{ Get, }, }; - +use itertools::Itertools; use sp_arithmetic::Perquintill; use sp_arithmetic::traits::{CheckedSub, Zero}; @@ -1726,7 +1726,8 @@ impl Pallet { let project_account = Self::fund_account_id(project_id); let plmc_price = T::PriceProvider::get_price(PLMC_STATEMINT_ID).ok_or(Error::::PLMCPriceNotAvailable)?; // sort bids by price, and equal prices sorted by block number - bids.sort_by(|a, b| b.cmp(a)); + bids.sort(); + bids.reverse(); // accept only bids that were made before `end_block` i.e end of candle auction let bids: Result, DispatchError> = bids .into_iter() diff --git a/polimec-skeleton/pallets/funding/src/tests.rs b/polimec-skeleton/pallets/funding/src/tests.rs index 1aad61778..b903447bd 100644 --- a/polimec-skeleton/pallets/funding/src/tests.rs +++ b/polimec-skeleton/pallets/funding/src/tests.rs @@ -348,7 +348,6 @@ impl TestEnvironment { balances }) } - #[allow(dead_code)] fn get_all_reserved_plmc_balances(&self, reserve_type: LockType>) -> UserToPLMCBalance { self.ext_env.borrow_mut().execute_with(|| { let mut fundings = UserToPLMCBalance::new(); @@ -902,7 +901,7 @@ impl<'a> CommunityFundingProject<'a> { "Weighted average price should exist" ); - for filter in bid_expectations { + for mut filter in bid_expectations { let _found_bid = flattened_bids.iter().find(|bid| filter.matches_bid(&bid)).unwrap(); } @@ -1955,7 +1954,9 @@ mod evaluation_round_success { remainder_funding_project.end_funding(); test_env.advance_time(10).unwrap(); - let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc.iter().map(|(evaluator, _amount)| (*evaluator, Zero::zero())).collect(); + let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc.iter().map(|(evaluator, amount)| (*evaluator, Zero::zero())).collect(); + + let temp_actual_par_lock = test_env.get_all_reserved_plmc_balances(LockType::Participation(project_id)); test_env.do_reserved_plmc_assertions(post_unbond_amounts.clone(), LockType::Evaluation(project_id)); test_env.do_reserved_plmc_assertions(post_unbond_amounts, LockType::Participation(project_id)); @@ -1991,8 +1992,9 @@ mod evaluation_round_success { assert_eq!(finished_project.get_project_details().status, ProjectStatus::FundingFailed); test_env.advance_time(10).unwrap(); - let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc.iter().map(|(evaluator, _amount)| (*evaluator, Zero::zero())).collect(); + let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc.iter().map(|(evaluator, amount)| (*evaluator, Zero::zero())).collect(); + let temp_actual_par_lock = test_env.get_all_reserved_plmc_balances(LockType::Participation(project_id)); test_env.do_reserved_plmc_assertions(post_unbond_amounts.clone(), LockType::Evaluation(project_id)); test_env.do_reserved_plmc_assertions(post_unbond_amounts, LockType::Participation(project_id)); @@ -2824,6 +2826,9 @@ mod auction_round_failure { project_id, ); + let community_funding_project = auctioning_project.start_community_funding(); + let details = community_funding_project.get_project_details(); + test_env.do_free_plmc_assertions(vec![(BIDDER_1, get_ed()), (BIDDER_2, plmc_fundings[1].1 + get_ed())]); test_env.do_reserved_plmc_assertions( @@ -2897,6 +2902,9 @@ mod auction_round_failure { project_id, ); + let community_funding_project = auctioning_project.start_community_funding(); + let details = community_funding_project.get_project_details(); + test_env.do_free_plmc_assertions(vec![(BIDDER_1, get_ed()), (BIDDER_2, plmc_fundings[1].1 + get_ed())]); test_env.do_reserved_plmc_assertions( @@ -2920,7 +2928,6 @@ mod auction_round_failure { #[cfg(test)] mod community_round_success { - use frame_support::traits::fungible::Inspect; use super::*; pub const HOURS: BlockNumber = 300u64; @@ -3214,7 +3221,7 @@ mod community_round_success { // Check that the right amount of PLMC is bonded, and funding currency is transferred let contributor_post_buy_plmc_balance = - project.in_ext(|| ::NativeCurrency::balance(&CONTRIBUTOR)); + project.in_ext(|| ::NativeCurrency::free_balance(&CONTRIBUTOR)); let contributor_post_buy_statemint_asset_balance = project.in_ext(|| ::FundingCurrency::balance(USDT_STATEMINT_ID, &CONTRIBUTOR)); From f57bd6af27955e93ac44792f8c7dd2615626a94d Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:50:55 +0200 Subject: [PATCH 54/80] Revert "chore: fmt" This reverts commit 79a616c7fbf3fe61d30404a4f69d9fecd41aeb34. --- integration-tests/modified-penpal/build.rs | 6 +- integration-tests/modified-penpal/src/lib.rs | 195 +- .../src/weights/block_weights.rs | 5 +- .../src/weights/extrinsic_weights.rs | 10 +- .../modified-penpal/src/xcm_config.rs | 104 +- integration-tests/src/lib.rs | 525 ++-- nodes/parachain/src/chain_spec.rs | 8 +- nodes/parachain/src/chain_spec/base.rs | 54 +- nodes/parachain/src/chain_spec/testnet.rs | 63 +- nodes/parachain/src/cli.rs | 6 +- nodes/parachain/src/command.rs | 48 +- nodes/parachain/src/rpc.rs | 4 +- nodes/parachain/src/service.rs | 98 +- nodes/standalone/src/benchmarking.rs | 32 +- nodes/standalone/src/chain_spec.rs | 17 +- nodes/standalone/src/command.rs | 48 +- nodes/standalone/src/rpc.rs | 4 +- nodes/standalone/src/service.rs | 133 +- pallets/funding/src/benchmarking.rs | 21 +- pallets/funding/src/functions.rs | 376 ++- pallets/funding/src/lib.rs | 49 +- pallets/funding/src/mock.rs | 112 +- pallets/funding/src/tests.rs | 627 ++-- pallets/funding/src/types.rs | 77 +- .../parachain-staking/src/auto_compound.rs | 55 +- pallets/parachain-staking/src/benchmarks.rs | 15 +- .../src/delegation_requests.rs | 164 +- pallets/parachain-staking/src/inflation.rs | 68 +- pallets/parachain-staking/src/lib.rs | 347 ++- pallets/parachain-staking/src/mock.rs | 172 +- pallets/parachain-staking/src/tests.rs | 2528 ++++++++++++----- pallets/parachain-staking/src/traits.rs | 12 +- pallets/parachain-staking/src/types.rs | 282 +- pallets/sandbox/src/lib.rs | 12 +- pallets/sandbox/src/mock.rs | 112 +- pallets/sandbox/src/tests.rs | 23 +- runtimes/base/build.rs | 6 +- runtimes/base/src/lib.rs | 177 +- runtimes/base/src/xcm_config.rs | 84 +- runtimes/shared-configuration/src/fee.rs | 6 +- .../src/weights/block_weights.rs | 5 +- .../src/weights/extrinsic_weights.rs | 10 +- runtimes/standalone/build.rs | 6 +- runtimes/standalone/src/lib.rs | 339 ++- runtimes/testnet/build.rs | 6 +- runtimes/testnet/src/lib.rs | 440 +-- runtimes/testnet/src/xcm_config.rs | 115 +- rustfmt.toml | 9 +- 48 files changed, 5084 insertions(+), 2531 deletions(-) diff --git a/integration-tests/modified-penpal/build.rs b/integration-tests/modified-penpal/build.rs index e02e83524..fe1a2ea91 100644 --- a/integration-tests/modified-penpal/build.rs +++ b/integration-tests/modified-penpal/build.rs @@ -17,5 +17,9 @@ use substrate_wasm_builder::WasmBuilder; fn main() { - WasmBuilder::new().with_current_project().export_heap_base().import_memory().build() + WasmBuilder::new() + .with_current_project() + .export_heap_base() + .import_memory() + .build() } diff --git a/integration-tests/modified-penpal/src/lib.rs b/integration-tests/modified-penpal/src/lib.rs index 781bfb980..0ca13534b 100644 --- a/integration-tests/modified-penpal/src/lib.rs +++ b/integration-tests/modified-penpal/src/lib.rs @@ -123,12 +123,14 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; -pub type Migrations = (pallet_balances::migration::MigrateToTrackInactive,); +pub type Migrations = + (pallet_balances::migration::MigrateToTrackInactive,); /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< @@ -153,7 +155,6 @@ pub type Executive = frame_executive::Executive< pub struct WeightToFee; impl WeightToFeePolynomial for WeightToFee { type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 MILLIUNIT: // in our template, we map to 1/10 of that, or 1/10 MILLIUNIT @@ -281,66 +282,66 @@ parameter_types! { // Configure FRAME pallets to include in runtime. impl frame_system::Config for Runtime { - /// The data to be stored in an account. - type AccountData = pallet_balances::AccountData; /// The identifier used to distinguish between accounts. type AccountId = AccountId; - /// The basic call filter to use in dispatchable. - type BaseCallFilter = Everything; - /// Maximum number of block number to block hash mappings to keep (oldest pruned first). - type BlockHashCount = BlockHashCount; - /// The maximum length of a block (in bytes). - type BlockLength = RuntimeBlockLength; + /// The aggregated dispatch type that is available for extrinsics. + type RuntimeCall = RuntimeCall; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = AccountIdLookup; + /// The index type for storing how many extrinsics an account has signed. + type Index = Index; /// The index type for blocks. type BlockNumber = BlockNumber; - /// Block & extrinsics weights: base values and limits. - type BlockWeights = RuntimeBlockWeights; - /// The weight of database operations that the runtime can invoke. - type DbWeight = RocksDbWeight; /// The type for hashing blocks and tries. type Hash = Hash; /// The hashing algorithm used. type Hashing = BlakeTwo256; /// The header type. type Header = generic::Header; - /// The index type for storing how many extrinsics an account has signed. - type Index = Index; - /// The lookup mechanism to get account ID from whatever is passed in dispatchers. - type Lookup = AccountIdLookup; - type MaxConsumers = frame_support::traits::ConstU32<16>; - /// What to do if an account is fully reaped from the system. - type OnKilledAccount = (); - /// What to do if a new account is created. - type OnNewAccount = (); - /// The action to take on a Runtime Upgrade - type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; - /// Converts a module to an index of this module in the runtime. - type PalletInfo = PalletInfo; - /// The aggregated dispatch type that is available for extrinsics. - type RuntimeCall = RuntimeCall; /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; /// The ubiquitous origin type. type RuntimeOrigin = RuntimeOrigin; - /// This is used as an identifier of the chain. 42 is the generic substrate prefix. - type SS58Prefix = SS58Prefix; - /// Weight information for the extrinsics of this pallet. - type SystemWeightInfo = (); + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; /// Runtime version. type Version = Version; + /// Converts a module to an index of this module in the runtime. + type PalletInfo = PalletInfo; + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; + /// What to do if a new account is created. + type OnNewAccount = (); + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; + /// The basic call filter to use in dispatchable. + type BaseCallFilter = Everything; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = (); + /// Block & extrinsics weights: base values and limits. + type BlockWeights = RuntimeBlockWeights; + /// The maximum length of a block (in bytes). + type BlockLength = RuntimeBlockLength; + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = SS58Prefix; + /// The action to take on a Runtime Upgrade + type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_timestamp::Config for Runtime { - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; + type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; type WeightInfo = (); } impl pallet_authorship::Config for Runtime { - type EventHandler = (CollatorSelection,); type FindAuthor = pallet_session::FindAccountFromAuthorIndex; + type EventHandler = (CollatorSelection,); } parameter_types! { @@ -348,21 +349,21 @@ parameter_types! { } impl pallet_balances::Config for Runtime { - type AccountStore = System; + type MaxLocks = ConstU32<50>; /// The type for recording an account's balance. type Balance = Balance; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; - type FreezeIdentifier = (); - type HoldIdentifier = (); - type MaxFreezes = ConstU32<0>; - type MaxHolds = ConstU32<0>; - type MaxLocks = ConstU32<50>; + type AccountStore = System; + type WeightInfo = pallet_balances::weights::SubstrateWeight; type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_balances::weights::SubstrateWeight; + type HoldIdentifier = (); + type FreezeIdentifier = (); + type MaxHolds = ConstU32<0>; + type MaxFreezes = ConstU32<0>; } parameter_types! { @@ -371,12 +372,12 @@ parameter_types! { } impl pallet_transaction_payment::Config for Runtime { - type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; - type LengthToFee = ConstantMultiplier; - type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; - type OperationalFeeMultiplier = ConstU8<5>; type RuntimeEvent = RuntimeEvent; + type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type WeightToFee = WeightToFee; + type LengthToFee = ConstantMultiplier; + type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type OperationalFeeMultiplier = ConstU8<5>; } parameter_types! { @@ -393,26 +394,26 @@ parameter_types! { // EnsureOneOf, EnsureXcm>>; impl pallet_assets::Config for Runtime { - type ApprovalDeposit = ApprovalDeposit; - type AssetAccountDeposit = AssetAccountDeposit; - type AssetDeposit = AssetDeposit; + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; type AssetId = AssetId; type AssetIdParameter = parity_scale_codec::Compact; - type Balance = Balance; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); - type CallbackHandle = (); - type CreateOrigin = AsEnsureOriginWithArg>; type Currency = Balances; - type Extra = (); + type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = EnsureRoot; - type Freezer = (); + type AssetDeposit = AssetDeposit; type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; - type RuntimeEvent = RuntimeEvent; + type ApprovalDeposit = ApprovalDeposit; type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); type WeightInfo = pallet_assets::weights::SubstrateWeight; + type CallbackHandle = (); + type AssetAccountDeposit = AssetAccountDeposit; + type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); } parameter_types! { @@ -421,15 +422,15 @@ parameter_types! { } impl cumulus_pallet_parachain_system::Config for Runtime { - type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; - type DmpMessageHandler = DmpQueue; - type OnSystemEvent = (); - type OutboundXcmpMessageSource = XcmpQueue; - type ReservedDmpWeight = ReservedDmpWeight; - type ReservedXcmpWeight = ReservedXcmpWeight; type RuntimeEvent = RuntimeEvent; + type OnSystemEvent = (); type SelfParaId = parachain_info::Pallet; + type DmpMessageHandler = DmpQueue; + type ReservedDmpWeight = ReservedDmpWeight; + type OutboundXcmpMessageSource = XcmpQueue; type XcmpMessageHandler = XcmpQueue; + type ReservedXcmpWeight = ReservedXcmpWeight; + type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; } impl parachain_info::Config for Runtime {} @@ -437,21 +438,21 @@ impl parachain_info::Config for Runtime {} impl cumulus_pallet_aura_ext::Config for Runtime {} impl cumulus_pallet_xcmp_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; type ChannelInfo = ParachainSystem; + type VersionWrapper = PolkadotXcm; + type ExecuteOverweightOrigin = EnsureRoot; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; - type ExecuteOverweightOrigin = EnsureRoot; - type PriceForSiblingDelivery = (); - type RuntimeEvent = RuntimeEvent; - type VersionWrapper = PolkadotXcm; type WeightInfo = (); - type XcmExecutor = XcmExecutor; + type PriceForSiblingDelivery = (); } impl cumulus_pallet_dmp_queue::Config for Runtime { - type ExecuteOverweightOrigin = EnsureRoot; type RuntimeEvent = RuntimeEvent; type XcmExecutor = XcmExecutor; + type ExecuteOverweightOrigin = EnsureRoot; } parameter_types! { @@ -460,16 +461,16 @@ parameter_types! { } impl pallet_session::Config for Runtime { - type Keys = SessionKeys; - type NextSessionRotation = pallet_session::PeriodicSessions; type RuntimeEvent = RuntimeEvent; - // Essentially just Aura, but let's be pedantic. - type SessionHandler = ::KeyTypeIdProviders; - type SessionManager = CollatorSelection; - type ShouldEndSession = pallet_session::PeriodicSessions; type ValidatorId = ::AccountId; // we don't have stash and controller, thus we don't need the convert as well. type ValidatorIdOf = pallet_collator_selection::IdentityCollator; + type ShouldEndSession = pallet_session::PeriodicSessions; + type NextSessionRotation = pallet_session::PeriodicSessions; + type SessionManager = CollatorSelection; + // Essentially just Aura, but let's be pedantic. + type SessionHandler = ::KeyTypeIdProviders; + type Keys = SessionKeys; type WeightInfo = (); } @@ -492,15 +493,15 @@ parameter_types! { pub type CollatorSelectionUpdateOrigin = EnsureRoot; impl pallet_collator_selection::Config for Runtime { + type RuntimeEvent = RuntimeEvent; type Currency = Balances; - // should be a multiple of session or things will get inconsistent - type KickThreshold = Period; + type UpdateOrigin = CollatorSelectionUpdateOrigin; + type PotId = PotId; type MaxCandidates = MaxCandidates; - type MaxInvulnerables = MaxInvulnerables; type MinCandidates = MinCandidates; - type PotId = PotId; - type RuntimeEvent = RuntimeEvent; - type UpdateOrigin = CollatorSelectionUpdateOrigin; + type MaxInvulnerables = MaxInvulnerables; + // should be a multiple of session or things will get inconsistent + type KickThreshold = Period; type ValidatorId = ::AccountId; type ValidatorIdOf = pallet_collator_selection::IdentityCollator; type ValidatorRegistration = Session; @@ -508,17 +509,17 @@ impl pallet_collator_selection::Config for Runtime { } impl pallet_asset_tx_payment::Config for Runtime { + type RuntimeEvent = RuntimeEvent; type Fungibles = Assets; type OnChargeAssetTransaction = pallet_asset_tx_payment::FungiblesAdapter< pallet_assets::BalanceToAssetBalance, AssetsToBlockAuthor, >; - type RuntimeEvent = RuntimeEvent; } impl pallet_sudo::Config for Runtime { - type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; } // Create the runtime by composing the FRAME pallets that were previously configured. @@ -799,15 +800,17 @@ impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { block: &Block, relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, ) -> sp_inherents::CheckInherentsResult { - let relay_chain_slot = - relay_state_proof.read_slot().expect("Could not read the relay chain slot from the proof"); - - let inherent_data = cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( - relay_chain_slot, - sp_std::time::Duration::from_secs(6), - ) - .create_inherent_data() - .expect("Could not create the timestamp inherent data"); + let relay_chain_slot = relay_state_proof + .read_slot() + .expect("Could not read the relay chain slot from the proof"); + + let inherent_data = + cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( + relay_chain_slot, + sp_std::time::Duration::from_secs(6), + ) + .create_inherent_data() + .expect("Could not create the timestamp inherent data"); inherent_data.check_extrinsics(block) } diff --git a/integration-tests/modified-penpal/src/weights/block_weights.rs b/integration-tests/modified-penpal/src/weights/block_weights.rs index 4aee7fb93..ea8a341b5 100644 --- a/integration-tests/modified-penpal/src/weights/block_weights.rs +++ b/integration-tests/modified-penpal/src/weights/block_weights.rs @@ -44,7 +44,10 @@ pub mod constants { "Weight should be at least 100 µs." ); // At most 50 ms. - assert!(w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 50 ms."); + assert!( + w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, + "Weight should be at most 50 ms." + ); } } } diff --git a/integration-tests/modified-penpal/src/weights/extrinsic_weights.rs b/integration-tests/modified-penpal/src/weights/extrinsic_weights.rs index f7008216c..0512efb60 100644 --- a/integration-tests/modified-penpal/src/weights/extrinsic_weights.rs +++ b/integration-tests/modified-penpal/src/weights/extrinsic_weights.rs @@ -39,9 +39,15 @@ pub mod constants { let w = super::constants::ExtrinsicBaseWeight::get(); // At least 10 µs. - assert!(w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, "Weight should be at least 10 µs."); + assert!( + w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, + "Weight should be at least 10 µs." + ); // At most 1 ms. - assert!(w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 1 ms."); + assert!( + w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, + "Weight should be at most 1 ms." + ); } } } diff --git a/integration-tests/modified-penpal/src/xcm_config.rs b/integration-tests/modified-penpal/src/xcm_config.rs index c6ee42a9e..436ed023b 100644 --- a/integration-tests/modified-penpal/src/xcm_config.rs +++ b/integration-tests/modified-penpal/src/xcm_config.rs @@ -22,9 +22,9 @@ //! with statemine as the reserve. At present no derivative tokens are minted on receipt of a //! ReserveAssetTransferDeposited message but that will but the intension will be to support this soon. use super::{ - AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Assets, Balance, Balances, EnsureRoot, - ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, - XcmpQueue, + AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Assets, Balance, Balances, + EnsureRoot, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, + RuntimeOrigin, WeightToFee, XcmpQueue, }; use core::marker::PhantomData; use frame_support::{ @@ -43,11 +43,13 @@ use polkadot_runtime_common::impls::ToAuthor; use sp_runtime::traits::Zero; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, - FixedWeightBounds, FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, ParentIsPreset, RelayChainAsNative, - SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, WithComputedOrigin, + AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, + AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, + ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, FungiblesAdapter, + IsConcrete, LocalMint, NativeAsset, ParentIsPreset, RelayChainAsNative, + SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, + WithComputedOrigin, }; use xcm_executor::{traits::JustTry, XcmExecutor}; @@ -159,7 +161,10 @@ pub type Barrier = DenyThenTry< // If the message is one that immediately attemps to pay for execution, then allow it. AllowTopLevelPaidExecutionFrom, // Common Good Assets parachain, parent and its exec plurality get free execution - AllowExplicitUnpaidExecutionFrom<(CommonGoodAssetsParachain, ParentOrParentsExecutivePlurality)>, + AllowExplicitUnpaidExecutionFrom<( + CommonGoodAssetsParachain, + ParentOrParentsExecutivePlurality, + )>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, ), @@ -266,10 +271,16 @@ impl ContainsPair for StatemintAssets { &loc == origin && match asset { MultiAsset { - id: Concrete(MultiLocation { parents: 0, interior: X2(PalletInstance(50), GeneralIndex(_)) }), + id: + Concrete(MultiLocation { + parents: 0, + interior: X2(PalletInstance(50), GeneralIndex(_)), + }), .. } => true, - MultiAsset { id: Concrete(MultiLocation { parents: 1, interior: Here }), .. } => true, + MultiAsset { + id: Concrete(MultiLocation { parents: 1, interior: Here }), .. + } => true, _ => false, } @@ -280,30 +291,31 @@ pub type Reserves = (NativeAsset, StatemintAssets); pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { - type AssetClaims = PolkadotXcm; - type AssetExchanger = (); - type AssetLocker = (); + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; // How to withdraw and deposit an asset. type AssetTransactor = AssetTransactors; - type AssetTrap = PolkadotXcm; - type Barrier = Barrier; - type CallDispatcher = RuntimeCall; - type FeeManager = (); + type OriginConverter = XcmOriginToTransactDispatchOrigin; type IsReserve = Reserves; type IsTeleporter = NativeAsset; - type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type MessageExporter = (); - type OriginConverter = XcmOriginToTransactDispatchOrigin; - type PalletInstancesInfo = AllPalletsWithSystem; + type UniversalLocation = UniversalLocation; + type Barrier = Barrier; + type Weigher = FixedWeightBounds; + type Trader = + UsingComponents>; type ResponseHandler = PolkadotXcm; - type RuntimeCall = RuntimeCall; - type SafeCallFilter = Everything; + type AssetTrap = PolkadotXcm; + type AssetClaims = PolkadotXcm; type SubscriptionService = PolkadotXcm; - type Trader = UsingComponents>; + type PalletInstancesInfo = AllPalletsWithSystem; + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type AssetLocker = (); + type AssetExchanger = (); + type FeeManager = (); + type MessageExporter = (); type UniversalAliases = Nothing; - type UniversalLocation = UniversalLocation; - type Weigher = FixedWeightBounds; - type XcmSender = XcmRouter; + type CallDispatcher = RuntimeCall; + type SafeCallFilter = Everything; } /// No local origins on this chain are allowed to dispatch XCM sends/executions. @@ -324,33 +336,33 @@ parameter_types! { } impl pallet_xcm::Config for Runtime { - type AdminOrigin = EnsureRoot; - // ^ Override for AdvertisedXcmVersion default - type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; - type Currency = Balances; - type CurrencyMatcher = (); - type ExecuteXcmOrigin = EnsureXcmOrigin; - type MaxLockers = ConstU32<8>; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; type SendXcmOrigin = EnsureXcmOrigin; - type SovereignAccountOf = LocationToAccountId; - type TrustedLockers = (); - type UniversalLocation = UniversalLocation; - type Weigher = FixedWeightBounds; - type WeightInfo = pallet_xcm::TestWeightInfo; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; type XcmExecuteFilter = Everything; // ^ Disable dispatchable execute on the XCM pallet. // Needs to be `Everything` for local testing. type XcmExecutor = XcmExecutor; - type XcmReserveTransferFilter = Everything; - type XcmRouter = XcmRouter; type XcmTeleportFilter = Everything; + type XcmReserveTransferFilter = Everything; + type Weigher = FixedWeightBounds; + type UniversalLocation = UniversalLocation; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + // ^ Override for AdvertisedXcmVersion default + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; + type Currency = Balances; + type CurrencyMatcher = (); + type TrustedLockers = (); + type SovereignAccountOf = LocationToAccountId; + type MaxLockers = ConstU32<8>; + type WeightInfo = pallet_xcm::TestWeightInfo; + type AdminOrigin = EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs index 7ea151ac7..fa5b321ee 100644 --- a/integration-tests/src/lib.rs +++ b/integration-tests/src/lib.rs @@ -24,8 +24,8 @@ use sp_core::{ecdsa, ed25519, sr25519, Pair}; use sp_runtime::{traits::AccountIdConversion, AccountId32 as RuntimeAccountId32}; use xcm::{v3::prelude::*, VersionedMultiAssets, VersionedMultiLocation, VersionedXcm}; use xcm_emulator::{ - cumulus_pallet_xcmp_queue, decl_test_network, decl_test_parachain, decl_test_relay_chain, polkadot_primitives, - TestExt, + cumulus_pallet_xcmp_queue, decl_test_network, decl_test_parachain, decl_test_relay_chain, + polkadot_primitives, TestExt, }; const RELAY_ASSET_ID: u32 = 0; @@ -104,7 +104,6 @@ impl ParachainAccounts { fn polimec_child_account() -> RuntimeAccountId32 { ParaId::new(polimec_id()).into_account_truncating() } - fn polimec_sibling_account() -> RuntimeAccountId32 { SiblingId::from(polimec_id()).into_account_truncating() } @@ -112,7 +111,6 @@ impl ParachainAccounts { fn statemint_child_account() -> RuntimeAccountId32 { ParaId::from(statemint_id()).into_account_truncating() } - fn statemint_sibling_account() -> RuntimeAccountId32 { SiblingId::from(statemint_id()).into_account_truncating() } @@ -120,14 +118,15 @@ impl ParachainAccounts { fn penpal_child_account() -> RuntimeAccountId32 { ParaId::from(penpal_id()).into_account_truncating() } - fn penpal_sibling_account() -> RuntimeAccountId32 { SiblingId::from(penpal_id()).into_account_truncating() } } fn default_parachains_host_configuration( -) -> polkadot_runtime_parachains::configuration::HostConfiguration { +) -> polkadot_runtime_parachains::configuration::HostConfiguration< + polkadot_primitives::v4::BlockNumber, +> { use polkadot_primitives::v4::{MAX_CODE_SIZE, MAX_POV_SIZE}; polkadot_runtime_parachains::configuration::HostConfiguration { @@ -190,7 +189,11 @@ pub fn polkadot_ext() -> sp_io::TestExternalities { .unwrap(); let xcm_config = pallet_xcm::GenesisConfig { safe_xcm_version: Some(3) }; - >::assimilate_storage(&xcm_config, &mut t).unwrap(); + >::assimilate_storage( + &xcm_config, + &mut t, + ) + .unwrap(); let mut ext = sp_io::TestExternalities::new(t); ext.execute_with(|| System::set_block_number(1)); @@ -204,11 +207,18 @@ pub fn polimec_ext(para_id: u32) -> sp_io::TestExternalities { let parachain_info_config = parachain_info::GenesisConfig { parachain_id: para_id.into() }; - >::assimilate_storage(¶chain_info_config, &mut t) - .unwrap(); + >::assimilate_storage( + ¶chain_info_config, + &mut t, + ) + .unwrap(); let xcm_config = pallet_xcm::GenesisConfig { safe_xcm_version: Some(3) }; - >::assimilate_storage(&xcm_config, &mut t).unwrap(); + >::assimilate_storage( + &xcm_config, + &mut t, + ) + .unwrap(); pallet_balances::GenesisConfig:: { balances: vec![ @@ -222,7 +232,12 @@ pub fn polimec_ext(para_id: u32) -> sp_io::TestExternalities { .unwrap(); pallet_assets::GenesisConfig:: { - metadata: vec![(RELAY_ASSET_ID, "Local DOT".as_bytes().to_vec(), "DOT".as_bytes().to_vec(), 12)], + metadata: vec![( + RELAY_ASSET_ID, + "Local DOT".as_bytes().to_vec(), + "DOT".as_bytes().to_vec(), + 12, + )], accounts: vec![(RELAY_ASSET_ID, ALICE, INITIAL_BALANCE)], assets: vec![( RELAY_ASSET_ID, @@ -246,11 +261,18 @@ pub fn statemint_ext(para_id: u32) -> sp_io::TestExternalities { let parachain_info_config = parachain_info::GenesisConfig { parachain_id: para_id.into() }; - >::assimilate_storage(¶chain_info_config, &mut t) - .unwrap(); + >::assimilate_storage( + ¶chain_info_config, + &mut t, + ) + .unwrap(); let xcm_config = pallet_xcm::GenesisConfig { safe_xcm_version: Some(3) }; - >::assimilate_storage(&xcm_config, &mut t).unwrap(); + >::assimilate_storage( + &xcm_config, + &mut t, + ) + .unwrap(); pallet_balances::GenesisConfig:: { balances: vec![ @@ -273,11 +295,18 @@ pub fn penpal_ext(para_id: u32) -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); let parachain_info_config = parachain_info::GenesisConfig { parachain_id: para_id.into() }; - >::assimilate_storage(¶chain_info_config, &mut t) - .unwrap(); + >::assimilate_storage( + ¶chain_info_config, + &mut t, + ) + .unwrap(); let xcm_config = pallet_xcm::GenesisConfig { safe_xcm_version: Some(3) }; - >::assimilate_storage(&xcm_config, &mut t).unwrap(); + >::assimilate_storage( + &xcm_config, + &mut t, + ) + .unwrap(); pallet_balances::GenesisConfig:: { balances: vec![ @@ -314,7 +343,8 @@ pub mod shortcuts { pub type PenpalBalances = pallet_balances::Pallet; pub type PolkadotAssets = pallet_assets::Pallet; - pub type PolimecAssets = pallet_assets::Pallet; + pub type PolimecAssets = + pallet_assets::Pallet; pub type StatemintAssets = pallet_assets::Pallet; pub type PenpalAssets = pallet_assets::Pallet; @@ -354,7 +384,10 @@ mod network_tests { UnpaidExecution { weight_limit: WeightLimit::Unlimited, check_origin: None }, Transact { origin_kind: OriginKind::SovereignAccount, - require_weight_at_most: Weight::from_parts(INITIAL_BALANCE as u64, 1024 * 1024), + require_weight_at_most: Weight::from_parts( + INITIAL_BALANCE as u64, + 1024 * 1024 + ), call: remark.encode().into(), } ]), @@ -375,10 +408,11 @@ mod network_tests { fn ump() { Network::reset(); - let burn_transfer = PolkadotCall::Balances(pallet_balances::Call::::transfer { - dest: PolkadotAccountId::from([0u8; 32]).into(), - value: 1_000, - }); + let burn_transfer = + PolkadotCall::Balances(pallet_balances::Call::::transfer { + dest: PolkadotAccountId::from([0u8; 32]).into(), + value: 1_000, + }); let here_asset: MultiAsset = (MultiLocation::here(), INITIAL_BALANCE / 2).into(); @@ -393,7 +427,10 @@ mod network_tests { BuyExecution { fees: here_asset.clone(), weight_limit: Unlimited }, Transact { origin_kind: OriginKind::SovereignAccount, - require_weight_at_most: Weight::from_parts(INITIAL_BALANCE as u64, 1024 * 1024), + require_weight_at_most: Weight::from_parts( + INITIAL_BALANCE as u64, + 1024 * 1024 + ), call: burn_transfer.encode().into(), } ]), @@ -405,7 +442,10 @@ mod network_tests { let events = System::events(); assert!(events.iter().any(|r| matches!( r.event, - RuntimeEvent::Ump(polkadot_runtime_parachains::ump::Event::ExecutedUpward(_, Outcome::Complete(_),)) + RuntimeEvent::Ump(polkadot_runtime_parachains::ump::Event::ExecutedUpward( + _, + Outcome::Complete(_), + )) ))); }); } @@ -414,10 +454,11 @@ mod network_tests { fn xcmp() { Network::reset(); - let burn_transfer = PolimecCall::Balances(pallet_balances::Call::::transfer { - dest: PolimecAccountId::from([0u8; 32]).into(), - value: 1_000, - }); + let burn_transfer = + PolimecCall::Balances(pallet_balances::Call::::transfer { + dest: PolimecAccountId::from([0u8; 32]).into(), + value: 1_000, + }); let here_asset: MultiAsset = (MultiLocation::here(), INITIAL_BALANCE / 2).into(); @@ -430,7 +471,10 @@ mod network_tests { BuyExecution { fees: here_asset.clone(), weight_limit: Unlimited }, Transact { origin_kind: OriginKind::SovereignAccount, - require_weight_at_most: Weight::from_parts(INITIAL_BALANCE as u64, 1024 * 1024), + require_weight_at_most: Weight::from_parts( + INITIAL_BALANCE as u64, + 1024 * 1024 + ), call: burn_transfer.encode().into(), } ]), @@ -440,9 +484,10 @@ mod network_tests { PolimecNet::execute_with(|| { use polimec_runtime::{RuntimeEvent, System}; let events = System::events(); - assert!(events - .iter() - .any(|r| matches!(r.event, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. })))); + assert!(events.iter().any(|r| matches!( + r.event, + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) + ))); }); } } @@ -474,20 +519,26 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_polimec_dot_balance, statemint_prev_dot_issuance) = - StatemintNet::execute_with(|| { - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::free_balance(ParachainAccounts::polimec_child_account()), - StatemintBalances::total_issuance(), - ) - }); + let ( + statemint_prev_alice_dot_balance, + statemint_prev_polimec_dot_balance, + statemint_prev_dot_issuance, + ) = StatemintNet::execute_with(|| { + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::free_balance(ParachainAccounts::polimec_child_account()), + StatemintBalances::total_issuance(), + ) + }); // do the transfer StatemintNet::execute_with(|| { assert_ok!(StatemintXcmPallet::limited_reserve_transfer_assets( StatemintOrigin::signed(ALICE), - Box::new(VersionedMultiLocation::V3(MultiLocation::new(1, X1(Parachain(polimec_id())),))), + Box::new(VersionedMultiLocation::V3(MultiLocation::new( + 1, + X1(Parachain(polimec_id())), + ))), Box::new(VersionedMultiLocation::V3(MultiLocation::from(AccountId32 { network: None, id: ALICE.into(), @@ -502,9 +553,10 @@ mod reserve_backed_transfers { PolimecNet::execute_with(|| { use polimec_runtime::{RuntimeEvent, System}; let events = System::events(); - assert!(events - .iter() - .any(|r| matches!(r.event, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. })))); + assert!(events.iter().any(|r| matches!( + r.event, + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) + ))); }); // check Polimec's post transfer balances and issuance @@ -524,25 +576,32 @@ mod reserve_backed_transfers { }); // check Statemint's post transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_polimec_dot_balance, statemint_post_dot_issuance) = - StatemintNet::execute_with(|| { - statemint_runtime::System::reset_events(); - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::free_balance(ParachainAccounts::polimec_child_account()), - StatemintBalances::total_issuance(), - ) - }); + let ( + statemint_post_alice_dot_balance, + statemint_post_polimec_dot_balance, + statemint_post_dot_issuance, + ) = StatemintNet::execute_with(|| { + statemint_runtime::System::reset_events(); + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::free_balance(ParachainAccounts::polimec_child_account()), + StatemintBalances::total_issuance(), + ) + }); - let polimec_delta_alice_dot_balance = polimec_post_alice_dot_balance - polimec_prev_alice_dot_balance; + let polimec_delta_alice_dot_balance = + polimec_post_alice_dot_balance - polimec_prev_alice_dot_balance; let polimec_delta_dot_issuance = polimec_post_dot_issuance - polimec_prev_dot_issuance; - let polimec_delta_alice_plmc_balance = polimec_post_alice_plmc_balance - polimec_prev_alice_plmc_balance; + let polimec_delta_alice_plmc_balance = + polimec_post_alice_plmc_balance - polimec_prev_alice_plmc_balance; let polimec_delta_plmc_issuance = polimec_post_plmc_issuance - polimec_prev_plmc_issuance; - let statemint_delta_alice_dot_balance = statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; + let statemint_delta_alice_dot_balance = + statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; let statemint_delta_polimec_dot_balance = statemint_post_polimec_dot_balance - statemint_prev_polimec_dot_balance; - let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_dot_issuance = + statemint_prev_dot_issuance - statemint_post_dot_issuance; assert!( polimec_delta_alice_dot_balance >= RESERVE_TRANSFER_AMOUNT - polimec_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) && @@ -551,9 +610,10 @@ mod reserve_backed_transfers { ); assert!( - polimec_delta_dot_issuance >= - RESERVE_TRANSFER_AMOUNT - polimec_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) && - polimec_delta_dot_issuance <= RESERVE_TRANSFER_AMOUNT, + polimec_delta_dot_issuance + >= RESERVE_TRANSFER_AMOUNT + - polimec_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) + && polimec_delta_dot_issuance <= RESERVE_TRANSFER_AMOUNT, "Polimec DOT issuance should have increased by at least the transfer amount minus the XCM execution fee" ); @@ -572,7 +632,10 @@ mod reserve_backed_transfers { "Statemint's DOT issuance should not change, since it acts as a reserve for that asset (except for fees which are burnt)" ); - assert_eq!(polimec_delta_alice_plmc_balance, 0, "Polimec ALICE PLMC balance should not have changed"); + assert_eq!( + polimec_delta_alice_plmc_balance, 0, + "Polimec ALICE PLMC balance should not have changed" + ); assert_eq!(polimec_delta_plmc_issuance, 0, "Polimec PLMC issuance should not have changed"); } @@ -601,9 +664,10 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = + StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); // construct the XCM to transfer from Polimec to Statemint's reserve let transfer_xcm: Xcm = Xcm(vec![ @@ -613,10 +677,16 @@ mod reserve_backed_transfers { assets: All.into(), reserve: MultiLocation::new(1, X1(Parachain(statemint_id()))), xcm: Xcm(vec![ - BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, + BuyExecution { + fees: execution_dot.clone(), + weight_limit: Limited(MAX_XCM_WEIGHT), + }, DepositAsset { assets: All.into(), - beneficiary: MultiLocation::new(0, AccountId32 { network: None, id: ALICE.into() }), + beneficiary: MultiLocation::new( + 0, + AccountId32 { network: None, id: ALICE.into() }, + ), }, ]), }, @@ -635,9 +705,10 @@ mod reserve_backed_transfers { StatemintNet::execute_with(|| { use statemint_runtime::{RuntimeEvent, System}; let events = System::events(); - assert!(events - .iter() - .any(|r| matches!(r.event, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. })))); + assert!(events.iter().any(|r| matches!( + r.event, + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) + ))); }); // check Polimec's post transfer balances and issuance @@ -656,17 +727,22 @@ mod reserve_backed_transfers { }); // check Statemint's post transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = + StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); let polimec_delta_dot_issuance = polimec_prev_dot_issuance - polimec_post_dot_issuance; let polimec_delta_plmc_issuance = polimec_prev_plmc_issuance - polimec_post_plmc_issuance; - let polimec_delta_alice_dot_balance = polimec_prev_alice_dot_balance - polimec_post_alice_dot_balance; - let polimec_delta_alice_plmc_balance = polimec_prev_alice_plmc_balance - polimec_post_alice_plmc_balance; + let polimec_delta_alice_dot_balance = + polimec_prev_alice_dot_balance - polimec_post_alice_dot_balance; + let polimec_delta_alice_plmc_balance = + polimec_prev_alice_plmc_balance - polimec_post_alice_plmc_balance; - let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; - let statemint_delta_alice_dot_balance = statemint_post_alice_dot_balance - statemint_prev_alice_dot_balance; + let statemint_delta_dot_issuance = + statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = + statemint_post_alice_dot_balance - statemint_prev_alice_dot_balance; assert_eq!( polimec_delta_alice_dot_balance, RESERVE_TRANSFER_AMOUNT, @@ -682,10 +758,10 @@ mod reserve_backed_transfers { assert_eq!(polimec_delta_alice_plmc_balance, 0, "Polimec's Alice PLMC should not change"); assert!( - statemint_delta_alice_dot_balance >= - RESERVE_TRANSFER_AMOUNT - - statemint_runtime::constants::fee::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) && - statemint_delta_alice_dot_balance <= RESERVE_TRANSFER_AMOUNT, + statemint_delta_alice_dot_balance + >= RESERVE_TRANSFER_AMOUNT + - statemint_runtime::constants::fee::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) + && statemint_delta_alice_dot_balance <= RESERVE_TRANSFER_AMOUNT, "Statemint's ALICE DOT balance should increase by at least the transfer amount minus the max allowed fees" ); @@ -703,23 +779,31 @@ mod reserve_backed_transfers { // check Penpal's pre transfer balances and issuance let (penpal_prev_alice_dot_balance, penpal_prev_dot_issuance) = - PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); + PenpalNet::execute_with(|| { + (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) + }); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_penpal_dot_balance, statemint_prev_dot_issuance) = - StatemintNet::execute_with(|| { - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::free_balance(ParachainAccounts::penpal_child_account()), - StatemintBalances::total_issuance(), - ) - }); + let ( + statemint_prev_alice_dot_balance, + statemint_prev_penpal_dot_balance, + statemint_prev_dot_issuance, + ) = StatemintNet::execute_with(|| { + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::free_balance(ParachainAccounts::penpal_child_account()), + StatemintBalances::total_issuance(), + ) + }); // do the transfer StatemintNet::execute_with(|| { assert_ok!(StatemintXcmPallet::limited_reserve_transfer_assets( StatemintOrigin::signed(ALICE), - Box::new(VersionedMultiLocation::V3(MultiLocation::new(1, X1(Parachain(penpal_id())),))), + Box::new(VersionedMultiLocation::V3(MultiLocation::new( + 1, + X1(Parachain(penpal_id())), + ))), Box::new(VersionedMultiLocation::V3(MultiLocation::from(AccountId32 { network: None, id: ALICE.into(), @@ -734,34 +818,43 @@ mod reserve_backed_transfers { PenpalNet::execute_with(|| { use penpal_runtime::{RuntimeEvent, System}; let events = System::events(); - assert!(events - .iter() - .any(|r| matches!(r.event, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. })))); + assert!(events.iter().any(|r| matches!( + r.event, + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) + ))); }); // check Penpal's post transfer balances and issuance - let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = PenpalNet::execute_with(|| { - penpal_runtime::System::reset_events(); - (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) - }); + let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = + PenpalNet::execute_with(|| { + penpal_runtime::System::reset_events(); + (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) + }); // check Statemint's post transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_penpal_dot_balance, statemint_post_dot_issuance) = - StatemintNet::execute_with(|| { - statemint_runtime::System::reset_events(); - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::free_balance(ParachainAccounts::penpal_child_account()), - StatemintBalances::total_issuance(), - ) - }); + let ( + statemint_post_alice_dot_balance, + statemint_post_penpal_dot_balance, + statemint_post_dot_issuance, + ) = StatemintNet::execute_with(|| { + statemint_runtime::System::reset_events(); + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::free_balance(ParachainAccounts::penpal_child_account()), + StatemintBalances::total_issuance(), + ) + }); - let penpal_delta_alice_dot_balance = penpal_post_alice_dot_balance - penpal_prev_alice_dot_balance; + let penpal_delta_alice_dot_balance = + penpal_post_alice_dot_balance - penpal_prev_alice_dot_balance; let penpal_delta_dot_issuance = penpal_post_dot_issuance - penpal_prev_dot_issuance; - let statemint_delta_alice_dot_balance = statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; - let statemint_delta_penpal_dot_balance = statemint_post_penpal_dot_balance - statemint_prev_penpal_dot_balance; - let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = + statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; + let statemint_delta_penpal_dot_balance = + statemint_post_penpal_dot_balance - statemint_prev_penpal_dot_balance; + let statemint_delta_dot_issuance = + statemint_prev_dot_issuance - statemint_post_dot_issuance; assert!( penpal_delta_alice_dot_balance >= RESERVE_TRANSFER_AMOUNT - penpal_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) && @@ -770,9 +863,9 @@ mod reserve_backed_transfers { ); assert!( - penpal_delta_dot_issuance >= - RESERVE_TRANSFER_AMOUNT - penpal_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) && - penpal_delta_dot_issuance <= RESERVE_TRANSFER_AMOUNT, + penpal_delta_dot_issuance + >= RESERVE_TRANSFER_AMOUNT - penpal_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) + && penpal_delta_dot_issuance <= RESERVE_TRANSFER_AMOUNT, "Penpal DOT issuance should have increased by at least the transfer amount minus the XCM execution fee" ); @@ -802,12 +895,15 @@ mod reserve_backed_transfers { // check Penpal's pre transfer balances and issuance let (penpal_prev_alice_dot_balance, penpal_prev_dot_issuance) = - PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); + PenpalNet::execute_with(|| { + (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) + }); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = + StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); // construct the XCM to transfer from Penpal to Statemint's reserve let transfer_xcm: Xcm = Xcm(vec![ @@ -817,10 +913,16 @@ mod reserve_backed_transfers { assets: All.into(), reserve: MultiLocation::new(1, X1(Parachain(statemint_id()))), xcm: Xcm(vec![ - BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, + BuyExecution { + fees: execution_dot.clone(), + weight_limit: Limited(MAX_XCM_WEIGHT), + }, DepositAsset { assets: All.into(), - beneficiary: MultiLocation::new(0, AccountId32 { network: None, id: ALICE.into() }), + beneficiary: MultiLocation::new( + 0, + AccountId32 { network: None, id: ALICE.into() }, + ), }, ]), }, @@ -839,25 +941,32 @@ mod reserve_backed_transfers { StatemintNet::execute_with(|| { use statemint_runtime::{RuntimeEvent, System}; let events = System::events(); - assert!(events - .iter() - .any(|r| matches!(r.event, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. })))); + assert!(events.iter().any(|r| matches!( + r.event, + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) + ))); }); // check Penpal's post transfer balances and issuance let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = - PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); + PenpalNet::execute_with(|| { + (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) + }); // check Statemint's post transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = + StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); let penpal_delta_dot_issuance = penpal_prev_dot_issuance - penpal_post_dot_issuance; - let penpal_delta_alice_dot_balance = penpal_prev_alice_dot_balance - penpal_post_alice_dot_balance; + let penpal_delta_alice_dot_balance = + penpal_prev_alice_dot_balance - penpal_post_alice_dot_balance; - let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; - let statemint_delta_alice_dot_balance = statemint_post_alice_dot_balance - statemint_prev_alice_dot_balance; + let statemint_delta_dot_issuance = + statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = + statemint_post_alice_dot_balance - statemint_prev_alice_dot_balance; assert_eq!( penpal_delta_alice_dot_balance, RESERVE_TRANSFER_AMOUNT, @@ -870,10 +979,10 @@ mod reserve_backed_transfers { ); assert!( - statemint_delta_alice_dot_balance >= - RESERVE_TRANSFER_AMOUNT - - statemint_runtime::constants::fee::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) && - statemint_delta_alice_dot_balance <= RESERVE_TRANSFER_AMOUNT, + statemint_delta_alice_dot_balance + >= RESERVE_TRANSFER_AMOUNT + - statemint_runtime::constants::fee::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) + && statemint_delta_alice_dot_balance <= RESERVE_TRANSFER_AMOUNT, "Statemint's ALICE DOT balance should increase by at least the transfer amount minus the max allowed fees" ); @@ -897,15 +1006,22 @@ mod reserve_backed_transfers { assets: All.into(), reserve: MultiLocation::new(1, X1(Parachain(statemint_id()))), xcm: Xcm::<()>(vec![ - BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, + BuyExecution { + fees: execution_dot.clone(), + weight_limit: Limited(MAX_XCM_WEIGHT), + }, DepositReserveAsset { assets: All.into(), dest: MultiLocation::new(1, X1(Parachain(penpal_id()))), xcm: Xcm::<()>(vec![ - BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, + BuyExecution { + fees: execution_dot.clone(), + weight_limit: Limited(MAX_XCM_WEIGHT), + }, DepositAsset { assets: All.into(), - beneficiary: X1(AccountId32 { network: None, id: ALICE.into() }).into(), + beneficiary: X1(AccountId32 { network: None, id: ALICE.into() }) + .into(), }, ]), }, @@ -929,13 +1045,16 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = + StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); // check Penpal's pre transfer balances and issuance let (penpal_prev_alice_dot_balance, penpal_prev_dot_issuance) = - PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); + PenpalNet::execute_with(|| { + (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) + }); // send the XCM message PolimecNet::execute_with(|| { @@ -949,17 +1068,19 @@ mod reserve_backed_transfers { StatemintNet::execute_with(|| { use statemint_runtime::{RuntimeEvent, System}; let events = System::events(); - assert!(events - .iter() - .any(|r| matches!(r.event, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. })))); + assert!(events.iter().any(|r| matches!( + r.event, + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) + ))); }); PenpalNet::execute_with(|| { use penpal_runtime::{RuntimeEvent, System}; let events = System::events(); - assert!(events - .iter() - .any(|r| matches!(r.event, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. })))); + assert!(events.iter().any(|r| matches!( + r.event, + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) + ))); }); // check Polimec's pre transfer balances and issuance @@ -978,24 +1099,32 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = + StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); // check Penpal's pre transfer balances and issuance let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = - PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); + PenpalNet::execute_with(|| { + (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) + }); let penpal_delta_dot_issuance = penpal_post_dot_issuance - penpal_prev_dot_issuance; - let penpal_delta_alice_dot_balance = penpal_post_alice_dot_balance - penpal_prev_alice_dot_balance; + let penpal_delta_alice_dot_balance = + penpal_post_alice_dot_balance - penpal_prev_alice_dot_balance; let polimec_delta_dot_issuance = polimec_prev_dot_issuance - polimec_post_dot_issuance; - let polimec_delta_alice_dot_balance = polimec_prev_alice_dot_balance - polimec_post_alice_dot_balance; + let polimec_delta_alice_dot_balance = + polimec_prev_alice_dot_balance - polimec_post_alice_dot_balance; let polimec_delta_plmc_issuance = polimec_prev_plmc_issuance - polimec_post_plmc_issuance; - let polimec_delta_alice_plmc_balance = polimec_prev_alice_plmc_balance - polimec_post_alice_plmc_balance; + let polimec_delta_alice_plmc_balance = + polimec_prev_alice_plmc_balance - polimec_post_alice_plmc_balance; - let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; - let statemint_delta_alice_dot_balance = statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; + let statemint_delta_dot_issuance = + statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = + statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; assert!( penpal_delta_alice_dot_balance > RESERVE_TRANSFER_AMOUNT - MAX_XCM_FEE * 3 && @@ -1023,9 +1152,15 @@ mod reserve_backed_transfers { "Statemint's DOT issuance should not change, since it acts as a reserve for that asset (except for fees which are burnt)" ); - assert_eq!(statemint_delta_alice_dot_balance, 0, "ALICE account on Statemint should not have changed"); + assert_eq!( + statemint_delta_alice_dot_balance, 0, + "ALICE account on Statemint should not have changed" + ); - assert_eq!(polimec_delta_alice_plmc_balance, 0, "Polimec ALICE PLMC balance should not have changed"); + assert_eq!( + polimec_delta_alice_plmc_balance, 0, + "Polimec ALICE PLMC balance should not have changed" + ); assert_eq!(polimec_delta_plmc_issuance, 0, "Polimec PLMC issuance should not have changed"); } @@ -1044,15 +1179,22 @@ mod reserve_backed_transfers { assets: All.into(), reserve: MultiLocation::new(1, X1(Parachain(statemint_id()))), xcm: Xcm::<()>(vec![ - BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, + BuyExecution { + fees: execution_dot.clone(), + weight_limit: Limited(MAX_XCM_WEIGHT), + }, DepositReserveAsset { assets: All.into(), dest: MultiLocation::new(1, X1(Parachain(polimec_id()))), xcm: Xcm::<()>(vec![ - BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, + BuyExecution { + fees: execution_dot.clone(), + weight_limit: Limited(MAX_XCM_WEIGHT), + }, DepositAsset { assets: All.into(), - beneficiary: X1(AccountId32 { network: None, id: ALICE.into() }).into(), + beneficiary: X1(AccountId32 { network: None, id: ALICE.into() }) + .into(), }, ]), }, @@ -1076,13 +1218,16 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = + StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); // check Penpal's pre transfer balances and issuance let (penpal_prev_alice_dot_balance, penpal_prev_dot_issuance) = - PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); + PenpalNet::execute_with(|| { + (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) + }); // send the XCM message PenpalNet::execute_with(|| { @@ -1096,17 +1241,19 @@ mod reserve_backed_transfers { StatemintNet::execute_with(|| { use statemint_runtime::{RuntimeEvent, System}; let events = System::events(); - assert!(events - .iter() - .any(|r| matches!(r.event, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. })))); + assert!(events.iter().any(|r| matches!( + r.event, + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) + ))); }); PolimecNet::execute_with(|| { use polimec_runtime::{RuntimeEvent, System}; let events = System::events(); - assert!(events - .iter() - .any(|r| matches!(r.event, RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. })))); + assert!(events.iter().any(|r| matches!( + r.event, + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Success { .. }) + ))); }); // check Polimec's pre transfer balances and issuance @@ -1125,24 +1272,32 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = + StatemintNet::execute_with(|| { + (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) + }); // check Penpal's pre transfer balances and issuance let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = - PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); + PenpalNet::execute_with(|| { + (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) + }); let penpal_delta_dot_issuance = penpal_prev_dot_issuance - penpal_post_dot_issuance; - let penpal_delta_alice_dot_balance = penpal_prev_alice_dot_balance - penpal_post_alice_dot_balance; + let penpal_delta_alice_dot_balance = + penpal_prev_alice_dot_balance - penpal_post_alice_dot_balance; let polimec_delta_dot_issuance = polimec_post_dot_issuance - polimec_prev_dot_issuance; - let polimec_delta_alice_dot_balance = polimec_post_alice_dot_balance - polimec_prev_alice_dot_balance; + let polimec_delta_alice_dot_balance = + polimec_post_alice_dot_balance - polimec_prev_alice_dot_balance; let polimec_delta_plmc_issuance = polimec_post_plmc_issuance - polimec_prev_plmc_issuance; - let polimec_delta_alice_plmc_balance = polimec_post_alice_plmc_balance - polimec_prev_alice_plmc_balance; + let polimec_delta_alice_plmc_balance = + polimec_post_alice_plmc_balance - polimec_prev_alice_plmc_balance; - let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; - let statemint_delta_alice_dot_balance = statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; + let statemint_delta_dot_issuance = + statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = + statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; assert!( polimec_delta_alice_dot_balance > RESERVE_TRANSFER_AMOUNT - MAX_XCM_FEE * 3 && @@ -1170,9 +1325,15 @@ mod reserve_backed_transfers { "Statemint's DOT issuance should not change, since it acts as a reserve for that asset (except for fees which are burnt)" ); - assert_eq!(statemint_delta_alice_dot_balance, 0, "ALICE account on Statemint should not have changed"); + assert_eq!( + statemint_delta_alice_dot_balance, 0, + "ALICE account on Statemint should not have changed" + ); - assert_eq!(polimec_delta_alice_plmc_balance, 0, "Polimec ALICE PLMC balance should not have changed"); + assert_eq!( + polimec_delta_alice_plmc_balance, 0, + "Polimec ALICE PLMC balance should not have changed" + ); assert_eq!(polimec_delta_plmc_issuance, 0, "Polimec PLMC issuance should not have changed"); } diff --git a/nodes/parachain/src/chain_spec.rs b/nodes/parachain/src/chain_spec.rs index 920f71dbd..7c6a1dc99 100644 --- a/nodes/parachain/src/chain_spec.rs +++ b/nodes/parachain/src/chain_spec.rs @@ -32,11 +32,15 @@ const DEFAULT_PARA_ID: ParaId = LOWEST_PUBLIC_ID; /// Helper function to generate a crypto pair from seed pub fn get_from_seed(seed: &str) -> ::Public { - TPublic::Pair::from_string(&format!("//{seed}"), None).expect("static values are valid; qed").public() + TPublic::Pair::from_string(&format!("//{seed}"), None) + .expect("static values are valid; qed") + .public() } /// The extensions for the [`ChainSpec`]. -#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)] +#[derive( + Debug, Clone, Eq, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension, +)] #[serde(deny_unknown_fields)] pub struct Extensions { /// The relay chain of the Parachain. diff --git a/nodes/parachain/src/chain_spec/base.rs b/nodes/parachain/src/chain_spec/base.rs index c1e167fa7..48fa084bc 100644 --- a/nodes/parachain/src/chain_spec/base.rs +++ b/nodes/parachain/src/chain_spec/base.rs @@ -31,8 +31,9 @@ use base_runtime::{ inflation::{perbill_annual_to_perbill_round, BLOCKS_PER_YEAR}, InflationInfo, Range, }, - AccountId, AuraId as AuthorityId, Balance, BalancesConfig, GenesisConfig, MinCandidateStk, ParachainInfoConfig, - ParachainStakingConfig, PolkadotXcmConfig, SessionConfig, SudoConfig, SystemConfig, PLMC, + AccountId, AuraId as AuthorityId, Balance, BalancesConfig, GenesisConfig, MinCandidateStk, + ParachainInfoConfig, ParachainStakingConfig, PolkadotXcmConfig, SessionConfig, SudoConfig, + SystemConfig, PLMC, }; /// The default XCM version to set in genesis config. @@ -54,8 +55,11 @@ pub fn polimec_inflation_config() -> InflationInfo { ) } - let annual = - Range { min: Perbill::from_percent(2), ideal: Perbill::from_percent(3), max: Perbill::from_percent(3) }; + let annual = Range { + min: Perbill::from_percent(2), + ideal: Perbill::from_percent(3), + max: Perbill::from_percent(3), + }; InflationInfo { // staking expectations @@ -82,8 +86,16 @@ pub fn get_local_base_chain_spec() -> Result { base_testnet_genesis( wasm, vec![ - (get_account_id_from_seed::("Alice"), None, 2 * MinCandidateStk::get()), - (get_account_id_from_seed::("Bob"), None, 2 * MinCandidateStk::get()), + ( + get_account_id_from_seed::("Alice"), + None, + 2 * MinCandidateStk::get(), + ), + ( + get_account_id_from_seed::("Bob"), + None, + 2 * MinCandidateStk::get(), + ), ], polimec_inflation_config(), vec![ @@ -91,12 +103,30 @@ pub fn get_local_base_chain_spec() -> Result { get_account_id_from_seed::("Bob"), ], vec![ - (get_account_id_from_seed::("Alice"), 5 * MinCandidateStk::get()), - (get_account_id_from_seed::("Bob"), 5 * MinCandidateStk::get()), - (get_account_id_from_seed::("Charlie"), 5 * MinCandidateStk::get()), - (get_account_id_from_seed::("Dave"), 5 * MinCandidateStk::get()), - (get_account_id_from_seed::("Eve"), 5 * MinCandidateStk::get()), - (get_account_id_from_seed::("Ferdie"), 5 * MinCandidateStk::get()), + ( + get_account_id_from_seed::("Alice"), + 5 * MinCandidateStk::get(), + ), + ( + get_account_id_from_seed::("Bob"), + 5 * MinCandidateStk::get(), + ), + ( + get_account_id_from_seed::("Charlie"), + 5 * MinCandidateStk::get(), + ), + ( + get_account_id_from_seed::("Dave"), + 5 * MinCandidateStk::get(), + ), + ( + get_account_id_from_seed::("Eve"), + 5 * MinCandidateStk::get(), + ), + ( + get_account_id_from_seed::("Ferdie"), + 5 * MinCandidateStk::get(), + ), ], get_account_id_from_seed::("Alice"), DEFAULT_PARA_ID, diff --git a/nodes/parachain/src/chain_spec/testnet.rs b/nodes/parachain/src/chain_spec/testnet.rs index e32191cf0..d71f3cb6a 100644 --- a/nodes/parachain/src/chain_spec/testnet.rs +++ b/nodes/parachain/src/chain_spec/testnet.rs @@ -28,8 +28,9 @@ use polimec_parachain_runtime::{ }; use polimec_parachain_runtime::{ - AccountId, Balance, BalancesConfig, CouncilConfig, GenesisConfig, ParachainInfoConfig, PolkadotXcmConfig, - SessionConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig, VestingConfig, + AccountId, Balance, BalancesConfig, CouncilConfig, GenesisConfig, ParachainInfoConfig, + PolkadotXcmConfig, SessionConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig, + VestingConfig, }; use sc_service::ChainType; use sp_core::{crypto::UncheckedInto, sr25519}; @@ -57,8 +58,11 @@ pub fn polimec_inflation_config() -> InflationInfo { ) } - let annual = - Range { min: Perbill::from_percent(2), ideal: Perbill::from_percent(3), max: Perbill::from_percent(3) }; + let annual = Range { + min: Perbill::from_percent(2), + ideal: Perbill::from_percent(3), + max: Perbill::from_percent(3), + }; InflationInfo { // staking expectations @@ -85,8 +89,16 @@ pub fn get_chain_spec_dev() -> Result { testnet_genesis( wasm, vec![ - (get_account_id_from_seed::("Alice"), None, 2 * MinCandidateStk::get()), - (get_account_id_from_seed::("Bob"), None, 2 * MinCandidateStk::get()), + ( + get_account_id_from_seed::("Alice"), + None, + 2 * MinCandidateStk::get(), + ), + ( + get_account_id_from_seed::("Bob"), + None, + 2 * MinCandidateStk::get(), + ), ], polimec_inflation_config(), vec![ @@ -94,12 +106,30 @@ pub fn get_chain_spec_dev() -> Result { get_account_id_from_seed::("Bob"), ], vec![ - (get_account_id_from_seed::("Alice"), 5 * MinCandidateStk::get()), - (get_account_id_from_seed::("Bob"), 5 * MinCandidateStk::get()), - (get_account_id_from_seed::("Charlie"), 5 * MinCandidateStk::get()), - (get_account_id_from_seed::("Dave"), 5 * MinCandidateStk::get()), - (get_account_id_from_seed::("Eve"), 5 * MinCandidateStk::get()), - (get_account_id_from_seed::("Ferdie"), 5 * MinCandidateStk::get()), + ( + get_account_id_from_seed::("Alice"), + 5 * MinCandidateStk::get(), + ), + ( + get_account_id_from_seed::("Bob"), + 5 * MinCandidateStk::get(), + ), + ( + get_account_id_from_seed::("Charlie"), + 5 * MinCandidateStk::get(), + ), + ( + get_account_id_from_seed::("Dave"), + 5 * MinCandidateStk::get(), + ), + ( + get_account_id_from_seed::("Eve"), + 5 * MinCandidateStk::get(), + ), + ( + get_account_id_from_seed::("Ferdie"), + 5 * MinCandidateStk::get(), + ), ], get_account_id_from_seed::("Alice"), DEFAULT_PARA_ID, @@ -198,7 +228,9 @@ fn testnet_genesis( ( acc.clone(), acc.clone(), - get_testnet_session_keys(Into::<[u8; 32]>::into(acc.clone()).unchecked_into()), + get_testnet_session_keys( + Into::<[u8; 32]>::into(acc.clone()).unchecked_into(), + ), ) }) .collect::>(), @@ -207,7 +239,10 @@ fn testnet_genesis( treasury: Default::default(), sudo: SudoConfig { key: Some(sudo_account) }, council: CouncilConfig { members: accounts.clone(), phantom: Default::default() }, - technical_committee: TechnicalCommitteeConfig { members: accounts.clone(), phantom: Default::default() }, + technical_committee: TechnicalCommitteeConfig { + members: accounts.clone(), + phantom: Default::default(), + }, democracy: Default::default(), vesting: VestingConfig { vesting: vec![] }, } diff --git a/nodes/parachain/src/cli.rs b/nodes/parachain/src/cli.rs index 4a184008b..e99d6dc94 100644 --- a/nodes/parachain/src/cli.rs +++ b/nodes/parachain/src/cli.rs @@ -61,7 +61,11 @@ pub enum Subcommand { } #[derive(Debug, clap::Parser)] -#[command(propagate_version = true, args_conflicts_with_subcommands = true, subcommand_negates_reqs = true)] +#[command( + propagate_version = true, + args_conflicts_with_subcommands = true, + subcommand_negates_reqs = true +)] pub struct Cli { #[command(subcommand)] pub subcommand: Option, diff --git a/nodes/parachain/src/command.rs b/nodes/parachain/src/command.rs index 82b0ce4f6..c46e4a73c 100644 --- a/nodes/parachain/src/command.rs +++ b/nodes/parachain/src/command.rs @@ -23,8 +23,8 @@ use log::{info, warn}; use parity_scale_codec::Encode; use polimec_parachain_runtime::Block; use sc_cli::{ - ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, NetworkParams, Result, - RuntimeVersion, SharedParams, SubstrateCli, + ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, + NetworkParams, Result, RuntimeVersion, SharedParams, SubstrateCli, }; use sc_service::config::{BasePath, PrometheusConfig}; use sp_core::hexdisplay::HexDisplay; @@ -65,8 +65,8 @@ impl RuntimeResolver for PathBuf { let file = std::fs::File::open(self).expect("Failed to open file"); let reader = std::io::BufReader::new(file); - let chain_spec: EmptyChainSpecWithId = - sp_serializer::from_reader(reader).expect("Failed to read 'json' file with ChainSpec configuration"); + let chain_spec: EmptyChainSpecWithId = sp_serializer::from_reader(reader) + .expect("Failed to read 'json' file with ChainSpec configuration"); runtime(&chain_spec.id) } } @@ -98,7 +98,9 @@ fn load_spec(id: &str) -> std::result::Result, String> { "polimec-polkadot" => Box::new(chain_spec::testnet::get_prod_chain_spec()?), // -- Fallback (generic chainspec) "" => { - log::warn!("No ChainSpec.id specified, so using default one, based on polimec-rococo-local"); + log::warn!( + "No ChainSpec.id specified, so using default one, based on polimec-rococo-local" + ); Box::new(chain_spec::testnet::get_chain_spec_dev()?) }, // A custom chainspec path @@ -219,10 +221,14 @@ pub fn run() -> Result<()> { }) }, Some(Subcommand::ExportBlocks(cmd)) => { - construct_async_run!(|components, cli, cmd, config| Ok(cmd.run(components.client, config.database))) + construct_async_run!(|components, cli, cmd, config| Ok( + cmd.run(components.client, config.database) + )) }, Some(Subcommand::ExportState(cmd)) => { - construct_async_run!(|components, cli, cmd, config| Ok(cmd.run(components.client, config.chain_spec))) + construct_async_run!(|components, cli, cmd, config| Ok( + cmd.run(components.client, config.chain_spec) + )) }, Some(Subcommand::ImportBlocks(cmd)) => { construct_async_run!(|components, cli, cmd, config| { @@ -243,9 +249,12 @@ pub fn run() -> Result<()> { [RelayChainCli::executable_name()].iter().chain(cli.relay_chain_args.iter()), ); - let polkadot_config = - SubstrateCli::create_configuration(&polkadot_cli, &polkadot_cli, config.tokio_handle.clone()) - .map_err(|err| format!("Relay chain argument error: {}", err))?; + let polkadot_config = SubstrateCli::create_configuration( + &polkadot_cli, + &polkadot_cli, + config.tokio_handle.clone(), + ) + .map_err(|err| format!("Relay chain argument error: {}", err))?; cmd.run(config, polkadot_config) }) @@ -316,10 +325,13 @@ pub fn run() -> Result<()> { // grab the task manager. let registry = &runner.config().prometheus_config.as_ref().map(|cfg| &cfg.registry); - let task_manager = sc_service::TaskManager::new(runner.config().tokio_handle.clone(), *registry) - .map_err(|e| format!("Error: {:?}", e))?; + let task_manager = + sc_service::TaskManager::new(runner.config().tokio_handle.clone(), *registry) + .map_err(|e| format!("Error: {:?}", e))?; - runner.async_run(|_| Ok((cmd.run::>(), task_manager))) + runner.async_run(|_| { + Ok((cmd.run::>(), task_manager)) + }) }, #[cfg(not(feature = "try-runtime"))] Some(Subcommand::TryRuntime) => Err("Try-runtime was not enabled when building the node. \ @@ -422,7 +434,10 @@ impl CliConfiguration for RelayChainCli { } fn base_path(&self) -> Result> { - Ok(self.shared_params().base_path()?.or_else(|| self.base_path.clone().map(Into::into))) + Ok(self + .shared_params() + .base_path()? + .or_else(|| self.base_path.clone().map(Into::into))) } fn rpc_http(&self, default_listen_port: u16) -> Result> { @@ -508,7 +523,10 @@ impl CliConfiguration for RelayChainCli { self.base.base.announce_block() } - fn telemetry_endpoints(&self, chain_spec: &Box) -> Result> { + fn telemetry_endpoints( + &self, + chain_spec: &Box, + ) -> Result> { self.base.base.telemetry_endpoints(chain_spec) } diff --git a/nodes/parachain/src/rpc.rs b/nodes/parachain/src/rpc.rs index 44a745abe..6cff4195a 100644 --- a/nodes/parachain/src/rpc.rs +++ b/nodes/parachain/src/rpc.rs @@ -43,7 +43,9 @@ pub struct FullDeps { } /// Instantiate all RPC extensions. -pub fn create_full(deps: FullDeps) -> Result> +pub fn create_full( + deps: FullDeps, +) -> Result> where C: ProvideRuntimeApi + HeaderBackend diff --git a/nodes/parachain/src/service.rs b/nodes/parachain/src/service.rs index ea54c0fa9..d21e7b66c 100644 --- a/nodes/parachain/src/service.rs +++ b/nodes/parachain/src/service.rs @@ -25,10 +25,12 @@ use polimec_parachain_runtime::{opaque::Block, RuntimeApi}; // Cumulus Imports use cumulus_client_consensus_aura::{AuraConsensus, BuildAuraConsensusParams, SlotProportion}; -use cumulus_client_consensus_common::{ParachainBlockImport as TParachainBlockImport, ParachainConsensus}; +use cumulus_client_consensus_common::{ + ParachainBlockImport as TParachainBlockImport, ParachainConsensus, +}; use cumulus_client_service::{ - build_network, build_relay_chain_interface, prepare_node_config, start_collator, start_full_node, - BuildNetworkParams, StartCollatorParams, StartFullNodeParams, + build_network, build_relay_chain_interface, prepare_node_config, start_collator, + start_full_node, BuildNetworkParams, StartCollatorParams, StartFullNodeParams, }; use cumulus_primitives_core::ParaId; use cumulus_relay_chain_interface::RelayChainInterface; @@ -36,7 +38,9 @@ use cumulus_relay_chain_interface::RelayChainInterface; // Substrate Imports use frame_benchmarking_cli::SUBSTRATE_REFERENCE_HARDWARE; use sc_consensus::ImportQueue; -use sc_executor::{HeapAllocStrategy, NativeElseWasmExecutor, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY}; +use sc_executor::{ + HeapAllocStrategy, NativeElseWasmExecutor, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY, +}; use sc_network::NetworkBlock; use sc_network_sync::SyncingService; use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager}; @@ -110,11 +114,12 @@ pub fn new_partial( let executor = ParachainExecutor::new_with_wasm_executor(wasm); - let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( - config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; + let (client, backend, keystore_container, task_manager) = + sc_service::new_full_parts::( + config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, + )?; let client = Arc::new(client); let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle()); @@ -217,7 +222,11 @@ async fn start_node_impl( let transaction_pool = transaction_pool.clone(); Box::new(move |deny_unsafe, _| { - let deps = crate::rpc::FullDeps { client: client.clone(), pool: transaction_pool.clone(), deny_unsafe }; + let deps = crate::rpc::FullDeps { + client: client.clone(), + pool: transaction_pool.clone(), + deny_unsafe, + }; crate::rpc::create_full(deps).map_err(Into::into) }) @@ -244,7 +253,9 @@ async fn start_node_impl( // in there and swapping out the requirements for your own are probably a good idea. The // requirements for a para-chain are dictated by its relay-chain. if !SUBSTRATE_REFERENCE_HARDWARE.check_hardware(&hwbench) && validator { - log::warn!("⚠️ The hardware does not meet the minimal requirements for role 'Authority'."); + log::warn!( + "⚠️ The hardware does not meet the minimal requirements for role 'Authority'." + ); } if let Some(ref mut telemetry) = telemetry { @@ -264,8 +275,9 @@ async fn start_node_impl( let relay_chain_slot_duration = Duration::from_secs(6); - let overseer_handle = - relay_chain_interface.overseer_handle().map_err(|e| sc_service::Error::Application(Box::new(e)))?; + let overseer_handle = relay_chain_interface + .overseer_handle() + .map_err(|e| sc_service::Error::Application(Box::new(e)))?; if validator { let parachain_consensus = build_consensus( @@ -331,25 +343,31 @@ fn build_import_queue( ) -> Result, sc_service::Error> { let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; - cumulus_client_consensus_aura::import_queue::( - cumulus_client_consensus_aura::ImportQueueParams { - block_import, - client, - create_inherent_data_providers: move |_, _| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + cumulus_client_consensus_aura::import_queue::< + sp_consensus_aura::sr25519::AuthorityPair, + _, + _, + _, + _, + _, + >(cumulus_client_consensus_aura::ImportQueueParams { + block_import, + client, + create_inherent_data_providers: move |_, _| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, slot_duration, ); - Ok((slot, timestamp)) - }, - registry: config.prometheus_registry(), - spawner: &task_manager.spawn_essential_handle(), - telemetry, + Ok((slot, timestamp)) }, - ) + registry: config.prometheus_registry(), + spawner: &task_manager.spawn_essential_handle(), + telemetry, + }) .map_err(Into::into) } @@ -382,22 +400,26 @@ fn build_consensus( create_inherent_data_providers: move |_, (relay_parent, validation_data)| { let relay_chain_interface = relay_chain_interface.clone(); async move { - let parachain_inherent = cumulus_primitives_parachain_inherent::ParachainInherentData::create_at( - relay_parent, - &relay_chain_interface, - &validation_data, - para_id, - ) - .await; + let parachain_inherent = + cumulus_primitives_parachain_inherent::ParachainInherentData::create_at( + relay_parent, + &relay_chain_interface, + &validation_data, + para_id, + ) + .await; let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); let parachain_inherent = parachain_inherent.ok_or_else(|| { - Box::::from("Failed to create parachain inherent") + Box::::from( + "Failed to create parachain inherent", + ) })?; Ok((slot, timestamp, parachain_inherent)) } diff --git a/nodes/standalone/src/benchmarking.rs b/nodes/standalone/src/benchmarking.rs index cf1c1c51c..9ecb50ae6 100644 --- a/nodes/standalone/src/benchmarking.rs +++ b/nodes/standalone/src/benchmarking.rs @@ -56,9 +56,13 @@ impl frame_benchmarking_cli::ExtrinsicBuilder for RemarkBuilder { fn build(&self, nonce: u32) -> std::result::Result { let acc = Sr25519Keyring::Bob.pair(); - let extrinsic: OpaqueExtrinsic = - create_benchmark_extrinsic(self.client.as_ref(), acc, SystemCall::remark { remark: vec![] }.into(), nonce) - .into(); + let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic( + self.client.as_ref(), + acc, + SystemCall::remark { remark: vec![] }.into(), + nonce, + ) + .into(); Ok(extrinsic) } @@ -94,7 +98,11 @@ impl frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder { let extrinsic: OpaqueExtrinsic = create_benchmark_extrinsic( self.client.as_ref(), acc, - BalancesCall::transfer_keep_alive { dest: self.dest.clone().into(), value: self.value.into() }.into(), + BalancesCall::transfer_keep_alive { + dest: self.dest.clone().into(), + value: self.value.into(), + } + .into(), nonce, ) .into(); @@ -116,7 +124,10 @@ pub fn create_benchmark_extrinsic( let best_hash = client.chain_info().best_hash; let best_block = client.chain_info().best_number; - let period = runtime::BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2) as u64; + let period = runtime::BlockHashCount::get() + .checked_next_power_of_two() + .map(|c| c / 2) + .unwrap_or(2) as u64; let extra: runtime::SignedExtra = ( frame_system::CheckNonZeroSender::::new(), frame_system::CheckSpecVersion::::new(), @@ -134,7 +145,16 @@ pub fn create_benchmark_extrinsic( let raw_payload = runtime::SignedPayload::from_raw( call.clone(), extra.clone(), - ((), runtime::VERSION.spec_version, runtime::VERSION.transaction_version, genesis_hash, best_hash, (), (), ()), + ( + (), + runtime::VERSION.spec_version, + runtime::VERSION.transaction_version, + genesis_hash, + best_hash, + (), + (), + (), + ), ); let signature = raw_payload.using_encoded(|e| sender.sign(e)); diff --git a/nodes/standalone/src/chain_spec.rs b/nodes/standalone/src/chain_spec.rs index 8d7e956c7..ec044fd58 100644 --- a/nodes/standalone/src/chain_spec.rs +++ b/nodes/standalone/src/chain_spec.rs @@ -15,7 +15,8 @@ // along with this program. If not, see . use polimec_standalone_runtime::{ - AccountId, BalancesConfig, GenesisConfig, SessionConfig, Signature, SudoConfig, SystemConfig, WASM_BINARY, + AccountId, BalancesConfig, GenesisConfig, SessionConfig, Signature, SudoConfig, SystemConfig, + WASM_BINARY, }; use sc_service::{ChainType, Properties}; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -38,7 +39,9 @@ fn polimec_properties() -> Properties { /// Helper function to generate a crypto pair from seed fn get_from_secret(seed: &str) -> ::Public { - TPublic::Pair::from_string(seed, None).unwrap_or_else(|_| panic!("Invalid string '{seed}'")).public() + TPublic::Pair::from_string(seed, None) + .unwrap_or_else(|_| panic!("Invalid string '{seed}'")) + .public() } /// Helper function to generate an account ID from seed @@ -117,7 +120,10 @@ pub fn local_testnet_config() -> Result { testnet_genesis( wasm_binary, // Initial PoA authorities - vec![get_authority_keys_from_secret("//Alice"), get_authority_keys_from_secret("//Bob")], + vec![ + get_authority_keys_from_secret("//Alice"), + get_authority_keys_from_secret("//Bob"), + ], // Sudo account get_account_id_from_secret::("//Alice"), // Pre-funded accounts @@ -178,7 +184,10 @@ fn testnet_genesis( ( x.0.clone(), x.0.clone(), - polimec_standalone_runtime::opaque::SessionKeys { aura: x.1.clone(), grandpa: x.2.clone() }, + polimec_standalone_runtime::opaque::SessionKeys { + aura: x.1.clone(), + grandpa: x.2.clone(), + }, ) }) .collect::>(), diff --git a/nodes/standalone/src/command.rs b/nodes/standalone/src/command.rs index 8f07f6943..892c41ce5 100644 --- a/nodes/standalone/src/command.rs +++ b/nodes/standalone/src/command.rs @@ -42,7 +42,8 @@ impl SubstrateCli for Cli { Ok(match id { "dev" => Box::new(chain_spec::development_config()?), "" | "local" => Box::new(chain_spec::local_testnet_config()?), - path => Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?), + path => + Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?), }) } @@ -64,7 +65,8 @@ pub fn run() -> sc_cli::Result<()> { Some(Subcommand::CheckBlock(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { client, task_manager, import_queue, .. } = service::new_partial(&config)?; + let PartialComponents { client, task_manager, import_queue, .. } = + service::new_partial(&config)?; Ok((cmd.run(client, import_queue), task_manager)) }) }, @@ -85,7 +87,8 @@ pub fn run() -> sc_cli::Result<()> { Some(Subcommand::ImportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { client, task_manager, import_queue, .. } = service::new_partial(&config)?; + let PartialComponents { client, task_manager, import_queue, .. } = + service::new_partial(&config)?; Ok((cmd.run(client, import_queue), task_manager)) }) }, @@ -96,7 +99,8 @@ pub fn run() -> sc_cli::Result<()> { Some(Subcommand::Revert(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { client, task_manager, backend, .. } = service::new_partial(&config)?; + let PartialComponents { client, task_manager, backend, .. } = + service::new_partial(&config)?; let aux_revert = Box::new(|client, _, blocks| { sc_consensus_grandpa::revert(client, blocks)?; Ok(()) @@ -113,9 +117,11 @@ pub fn run() -> sc_cli::Result<()> { match cmd { BenchmarkCmd::Pallet(cmd) => { if !cfg!(feature = "runtime-benchmarks") { - return Err("Runtime benchmarking wasn't enabled when building the node. \ + return Err( + "Runtime benchmarking wasn't enabled when building the node. \ You can enable it with `--features runtime-benchmarks`." - .into()) + .into(), + ) } cmd.run::(config) @@ -125,11 +131,14 @@ pub fn run() -> sc_cli::Result<()> { cmd.run(client) }, #[cfg(not(feature = "runtime-benchmarks"))] - BenchmarkCmd::Storage(_) => - Err("Storage benchmarking can be enabled with `--features runtime-benchmarks`.".into()), + BenchmarkCmd::Storage(_) => Err( + "Storage benchmarking can be enabled with `--features runtime-benchmarks`." + .into(), + ), #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => { - let PartialComponents { client, backend, .. } = service::new_partial(&config)?; + let PartialComponents { client, backend, .. } = + service::new_partial(&config)?; let db = backend.expose_db(); let storage = backend.expose_storage(); @@ -139,7 +148,13 @@ pub fn run() -> sc_cli::Result<()> { let PartialComponents { client, .. } = service::new_partial(&config)?; let ext_builder = RemarkBuilder::new(client.clone()); - cmd.run(config, client, inherent_benchmark_data()?, Vec::new(), &ext_builder) + cmd.run( + config, + client, + inherent_benchmark_data()?, + Vec::new(), + &ext_builder, + ) }, BenchmarkCmd::Extrinsic(cmd) => { let PartialComponents { client, .. } = service::new_partial(&config)?; @@ -155,7 +170,8 @@ pub fn run() -> sc_cli::Result<()> { cmd.run(client, inherent_benchmark_data()?, Vec::new(), &ext_factory) }, - BenchmarkCmd::Machine(cmd) => cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone()), + BenchmarkCmd::Machine(cmd) => + cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone()), } }) }, @@ -168,8 +184,9 @@ pub fn run() -> sc_cli::Result<()> { // we don't need any of the components of new_partial, just a runtime, or a task // manager to do `async_run`. let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); - let task_manager = sc_service::TaskManager::new(config.tokio_handle.clone(), registry) - .map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?; + let task_manager = + sc_service::TaskManager::new(config.tokio_handle.clone(), registry) + .map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?; let info_provider = timestamp_with_aura_info(6000); Ok(( @@ -191,8 +208,9 @@ pub fn run() -> sc_cli::Result<()> { }, None => { let runner = cli.create_runner(&cli.run)?; - runner - .run_node_until_exit(|config| async move { service::new_full(config).map_err(sc_cli::Error::Service) }) + runner.run_node_until_exit(|config| async move { + service::new_full(config).map_err(sc_cli::Error::Service) + }) }, } } diff --git a/nodes/standalone/src/rpc.rs b/nodes/standalone/src/rpc.rs index 495ce1991..d1cd753fd 100644 --- a/nodes/standalone/src/rpc.rs +++ b/nodes/standalone/src/rpc.rs @@ -43,7 +43,9 @@ pub struct FullDeps { } /// Instantiate all full RPC extensions. -pub fn create_full(deps: FullDeps) -> Result, Box> +pub fn create_full( + deps: FullDeps, +) -> Result, Box> where C: ProvideRuntimeApi, C: HeaderBackend + HeaderMetadata + 'static, diff --git a/nodes/standalone/src/service.rs b/nodes/standalone/src/service.rs index 56ac2c958..0ce896d35 100644 --- a/nodes/standalone/src/service.rs +++ b/nodes/standalone/src/service.rs @@ -46,7 +46,8 @@ impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { } } -pub(crate) type FullClient = sc_service::TFullClient>; +pub(crate) type FullClient = + sc_service::TFullClient>; type FullBackend = sc_service::TFullBackend; type FullSelectChain = sc_consensus::LongestChain; @@ -60,7 +61,12 @@ pub fn new_partial( sc_consensus::DefaultImportQueue, sc_transaction_pool::FullPool, ( - sc_consensus_grandpa::GrandpaBlockImport, + sc_consensus_grandpa::GrandpaBlockImport< + FullBackend, + Block, + FullClient, + FullSelectChain, + >, sc_consensus_grandpa::LinkHalf, Option, ), @@ -80,11 +86,12 @@ pub fn new_partial( let executor = sc_service::new_native_or_wasm_executor(&config); - let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( - config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; + let (client, backend, keystore_container, task_manager) = + sc_service::new_full_parts::( + config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, + )?; let client = Arc::new(client); let telemetry = telemetry.map(|(worker, telemetry)| { @@ -111,26 +118,28 @@ pub fn new_partial( let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { - block_import: grandpa_block_import.clone(), - justification_import: Some(Box::new(grandpa_block_import.clone())), - client: client.clone(), - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + let import_queue = + sc_consensus_aura::import_queue::(ImportQueueParams { + block_import: grandpa_block_import.clone(), + justification_import: Some(Box::new(grandpa_block_import.clone())), + client: client.clone(), + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); - - Ok((slot, timestamp)) - }, - spawner: &task_manager.spawn_essential_handle(), - registry: config.prometheus_registry(), - check_for_equivocation: Default::default(), - telemetry: telemetry.as_ref().map(|x| x.handle()), - compatibility_mode: Default::default(), - })?; + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); + + Ok((slot, timestamp)) + }, + spawner: &task_manager.spawn_essential_handle(), + registry: config.prometheus_registry(), + check_for_equivocation: Default::default(), + telemetry: telemetry.as_ref().map(|x| x.handle()), + compatibility_mode: Default::default(), + })?; Ok(sc_service::PartialComponents { client, @@ -162,7 +171,10 @@ pub fn new_full(mut config: Configuration) -> Result &config.chain_spec, ); - config.network.extra_sets.push(sc_consensus_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone())); + config + .network + .extra_sets + .push(sc_consensus_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone())); let warp_sync = Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), @@ -181,7 +193,12 @@ pub fn new_full(mut config: Configuration) -> Result })?; if config.offchain_worker.enabled { - sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); + sc_service::build_offchain_workers( + &config, + task_manager.spawn_handle(), + client.clone(), + network.clone(), + ); } let role = config.role.clone(); @@ -196,7 +213,8 @@ pub fn new_full(mut config: Configuration) -> Result let pool = transaction_pool.clone(); Box::new(move |deny_unsafe, _| { - let deps = crate::rpc::FullDeps { client: client.clone(), pool: pool.clone(), deny_unsafe }; + let deps = + crate::rpc::FullDeps { client: client.clone(), pool: pool.clone(), deny_unsafe }; crate::rpc::create_full(deps).map_err(Into::into) }) }; @@ -227,36 +245,41 @@ pub fn new_full(mut config: Configuration) -> Result let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - let aura = sc_consensus_aura::start_aura::(StartAuraParams { - slot_duration, - client, - select_chain, - block_import, - proposer_factory, - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); - - Ok((slot, timestamp)) + let aura = sc_consensus_aura::start_aura::( + StartAuraParams { + slot_duration, + client, + select_chain, + block_import, + proposer_factory, + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); + + Ok((slot, timestamp)) + }, + force_authoring, + backoff_authoring_blocks, + keystore: keystore_container.keystore(), + sync_oracle: sync_service.clone(), + justification_sync_link: sync_service.clone(), + block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), + max_block_proposal_slot_portion: None, + telemetry: telemetry.as_ref().map(|x| x.handle()), + compatibility_mode: Default::default(), }, - force_authoring, - backoff_authoring_blocks, - keystore: keystore_container.keystore(), - sync_oracle: sync_service.clone(), - justification_sync_link: sync_service.clone(), - block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), - max_block_proposal_slot_portion: None, - telemetry: telemetry.as_ref().map(|x| x.handle()), - compatibility_mode: Default::default(), - })?; + )?; // the AURA authoring task is considered essential, i.e. if it // fails we take down the service with it. - task_manager.spawn_essential_handle().spawn_blocking("aura", Some("block-authoring"), aura); + task_manager + .spawn_essential_handle() + .spawn_blocking("aura", Some("block-authoring"), aura); } if enable_grandpa { diff --git a/pallets/funding/src/benchmarking.rs b/pallets/funding/src/benchmarking.rs index 359096b49..e443e7cb3 100644 --- a/pallets/funding/src/benchmarking.rs +++ b/pallets/funding/src/benchmarking.rs @@ -62,10 +62,15 @@ fn assert_last_event(generic_event: ::RuntimeEvent) { #[allow(unused)] fn get_events() -> frame_benchmarking::Vec<::RuntimeEvent> { - frame_system::Pallet::::events().into_iter().map(|r| r.event).collect::>() + frame_system::Pallet::::events() + .into_iter() + .map(|r| r.event) + .collect::>() } -fn create_default_project(id: Option) -> (T::ProjectIdParameter, T::AccountId, ProjectMetadataOf) { +fn create_default_project( + id: Option, +) -> (T::ProjectIdParameter, T::AccountId, ProjectMetadataOf) { let issuer: T::AccountId = account::("Alice", 1, 1); let project_id_parameter = id.unwrap_or(0); let project_id = T::BenchmarkHelper::create_project_id_parameter(project_id_parameter); @@ -74,9 +79,13 @@ fn create_default_project(id: Option) -> (T::ProjectIdParameter, (project_id, issuer, project) } -fn create_default_minted_project(id: Option) -> (T::ProjectIdParameter, T::AccountId) { +fn create_default_minted_project( + id: Option, +) -> (T::ProjectIdParameter, T::AccountId) { let (project_id, issuer, project) = create_default_project::(id); - assert!(PolimecFunding::::create(SystemOrigin::Signed(issuer.clone()).into(), project).is_ok()); + assert!( + PolimecFunding::::create(SystemOrigin::Signed(issuer.clone()).into(), project).is_ok() + ); (project_id, issuer) } @@ -86,7 +95,9 @@ pub fn run_to_block(n: T::BlockNumber) { crate::Pallet::::on_finalize(frame_system::Pallet::::block_number()); frame_system::Pallet::::on_finalize(frame_system::Pallet::::block_number()); crate::Pallet::::on_idle(frame_system::Pallet::::block_number(), max_weight); - frame_system::Pallet::::set_block_number(frame_system::Pallet::::block_number() + One::one()); + frame_system::Pallet::::set_block_number( + frame_system::Pallet::::block_number() + One::one(), + ); frame_system::Pallet::::on_initialize(frame_system::Pallet::::block_number()); crate::Pallet::::on_initialize(frame_system::Pallet::::block_number()); crate::Pallet::::on_idle(frame_system::Pallet::::block_number(), max_weight); diff --git a/pallets/funding/src/functions.rs b/pallets/funding/src/functions.rs index 0a32ddea2..9c2e4e839 100644 --- a/pallets/funding/src/functions.rs +++ b/pallets/funding/src/functions.rs @@ -48,7 +48,10 @@ impl Pallet { /// # Next step /// The issuer will call an extrinsic to start the evaluation round of the project. /// [`do_evaluation_start`](Self::do_evaluation_start) will be executed. - pub fn do_create(issuer: T::AccountId, project: ProjectMetadataOf) -> Result<(), DispatchError> { + pub fn do_create( + issuer: T::AccountId, + project: ProjectMetadataOf, + ) -> Result<(), DispatchError> { // TODO: Probably the issuers don't want to sell all of their tokens. Is there some logic for this? // also even if an issuer wants to sell all their tokens, they could target a lower amount than that to consider it a success // * Get variables * @@ -63,7 +66,8 @@ impl Pallet { if let Err(error) = project.validity_check() { return match error { ValidityError::PriceTooLow => Err(Error::::PriceTooLow.into()), - ValidityError::ParticipantsSizeError => Err(Error::::ParticipantsSizeError.into()), + ValidityError::ParticipantsSizeError => + Err(Error::::ParticipantsSizeError.into()), ValidityError::TicketSizeError => Err(Error::::TicketSizeError.into()), } } @@ -75,7 +79,10 @@ impl Pallet { fundraising_target, project_status: ProjectStatus::Application, phase_transition_points: PhaseTransitionPoints { - application: BlockNumberPair::new(Some(>::block_number()), None), + application: BlockNumberPair::new( + Some(>::block_number()), + None, + ), evaluation: BlockNumberPair::new(None, None), auction_initialize_period: BlockNumberPair::new(None, None), english_auction: BlockNumberPair::new(None, None), @@ -121,19 +128,26 @@ impl Pallet { /// to the next round by `on_initialize` using [`do_evaluation_end`](Self::do_evaluation_end) pub fn do_evaluation_start(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; let now = >::block_number(); // * Validity checks * - ensure!(project_info.project_status == ProjectStatus::Application, Error::::ProjectNotInApplicationRound); + ensure!( + project_info.project_status == ProjectStatus::Application, + Error::::ProjectNotInApplicationRound + ); ensure!(!project_info.is_frozen, Error::::ProjectAlreadyFrozen); ensure!(project.offchain_information_hash.is_some(), Error::::MetadataNotProvided); // * Calculate new variables * let evaluation_end_block = now + T::EvaluationDuration::get(); project_info.phase_transition_points.application.update(None, Some(now)); - project_info.phase_transition_points.evaluation.update(Some(now + 1u32.into()), Some(evaluation_end_block)); + project_info + .phase_transition_points + .evaluation + .update(Some(now + 1u32.into()), Some(evaluation_end_block)); project_info.is_frozen = true; project_info.project_status = ProjectStatus::EvaluationRound; @@ -141,7 +155,10 @@ impl Pallet { // TODO: Should we make it possible to end an application, and schedule for a later point the evaluation? // Or should we just make it so that the evaluation starts immediately after the application ends? ProjectsDetails::::insert(project_id, project_info); - Self::add_to_update_store(evaluation_end_block + 1u32.into(), (&project_id, UpdateType::EvaluationEnd)); + Self::add_to_update_store( + evaluation_end_block + 1u32.into(), + (&project_id, UpdateType::EvaluationEnd), + ); // * Emit events * Self::deposit_event(Event::::EvaluationStarted { project_id }); @@ -179,14 +196,21 @@ impl Pallet { /// unbonds the evaluators funds. pub fn do_evaluation_end(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); - let evaluation_end_block = - project_info.phase_transition_points.evaluation.end().ok_or(Error::::FieldIsNone)?; + let evaluation_end_block = project_info + .phase_transition_points + .evaluation + .end() + .ok_or(Error::::FieldIsNone)?; let fundraising_target = project_info.fundraising_target; // * Validity checks * - ensure!(project_info.project_status == ProjectStatus::EvaluationRound, Error::::ProjectNotInEvaluationRound); + ensure!( + project_info.project_status == ProjectStatus::EvaluationRound, + Error::::ProjectNotInEvaluationRound + ); ensure!(now > evaluation_end_block, Error::::EvaluationPeriodNotEnded); // * Calculate new variables * @@ -208,10 +232,10 @@ impl Pallet { // Successful path if is_funded { // * Update storage * - project_info - .phase_transition_points - .auction_initialize_period - .update(Some(auction_initialize_period_start_block), Some(auction_initialize_period_end_block)); + project_info.phase_transition_points.auction_initialize_period.update( + Some(auction_initialize_period_start_block), + Some(auction_initialize_period_end_block), + ); project_info.project_status = ProjectStatus::AuctionInitializePeriod; ProjectsDetails::::insert(project_id, project_info); Self::add_to_update_store( @@ -267,7 +291,8 @@ impl Pallet { /// [`do_candle_auction`](Self::do_candle_auction). pub fn do_english_auction(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); let auction_initialize_period_start_block = project_info .phase_transition_points @@ -281,7 +306,10 @@ impl Pallet { .ok_or(Error::::EvaluationPeriodNotEnded)?; // * Validity checks * - ensure!(now >= auction_initialize_period_start_block, Error::::TooEarlyForEnglishAuctionStart); + ensure!( + now >= auction_initialize_period_start_block, + Error::::TooEarlyForEnglishAuctionStart + ); ensure!( project_info.project_status == ProjectStatus::AuctionInitializePeriod, Error::::ProjectNotInAuctionInitializePeriodRound @@ -292,7 +320,10 @@ impl Pallet { let english_end_block = now + T::EnglishAuctionDuration::get(); // * Update Storage * - project_info.phase_transition_points.english_auction.update(Some(english_start_block), Some(english_end_block)); + project_info + .phase_transition_points + .english_auction + .update(Some(english_start_block), Some(english_end_block)); project_info.project_status = ProjectStatus::AuctionRound(AuctionPhase::English); ProjectsDetails::::insert(project_id, project_info); @@ -302,7 +333,10 @@ impl Pallet { Self::remove_from_update_store(&project_id)?; } // Schedule for automatic transition to candle auction round - Self::add_to_update_store(english_end_block + 1u32.into(), (&project_id, UpdateType::CandleAuctionStart)); + Self::add_to_update_store( + english_end_block + 1u32.into(), + (&project_id, UpdateType::CandleAuctionStart), + ); // * Emit events * Self::deposit_event(Event::::EnglishAuctionStarted { project_id, when: now }); @@ -335,10 +369,14 @@ impl Pallet { /// by calling [`do_community_funding`](Self::do_community_funding). pub fn do_candle_auction(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); - let english_end_block = - project_info.phase_transition_points.english_auction.end().ok_or(Error::::FieldIsNone)?; + let english_end_block = project_info + .phase_transition_points + .english_auction + .end() + .ok_or(Error::::FieldIsNone)?; // * Validity checks * ensure!(now > english_end_block, Error::::TooEarlyForCandleAuctionStart); @@ -352,11 +390,17 @@ impl Pallet { let candle_end_block = now + T::CandleAuctionDuration::get(); // * Update Storage * - project_info.phase_transition_points.candle_auction.update(Some(candle_start_block), Some(candle_end_block)); + project_info + .phase_transition_points + .candle_auction + .update(Some(candle_start_block), Some(candle_end_block)); project_info.project_status = ProjectStatus::AuctionRound(AuctionPhase::Candle); ProjectsDetails::::insert(project_id, project_info); // Schedule for automatic check by on_initialize. Success depending on enough funding reached - Self::add_to_update_store(candle_end_block + 1u32.into(), (&project_id, UpdateType::CommunityFundingStart)); + Self::add_to_update_store( + candle_end_block + 1u32.into(), + (&project_id, UpdateType::CommunityFundingStart), + ); // * Emit events * Self::deposit_event(Event::::CandleAuctionStarted { project_id, when: now }); @@ -388,12 +432,19 @@ impl Pallet { /// starts the remainder round, where anyone can buy at that price point. pub fn do_community_funding(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); - let auction_candle_start_block = - project_info.phase_transition_points.candle_auction.start().ok_or(Error::::FieldIsNone)?; - let auction_candle_end_block = - project_info.phase_transition_points.candle_auction.end().ok_or(Error::::FieldIsNone)?; + let auction_candle_start_block = project_info + .phase_transition_points + .candle_auction + .start() + .ok_or(Error::::FieldIsNone)?; + let auction_candle_end_block = project_info + .phase_transition_points + .candle_auction + .end() + .ok_or(Error::::FieldIsNone)?; // * Validity checks * ensure!(now > auction_candle_end_block, Error::::TooEarlyForCommunityRoundStart); @@ -403,20 +454,32 @@ impl Pallet { ); // * Calculate new variables * - let end_block = Self::select_random_block(auction_candle_start_block, auction_candle_end_block); + let end_block = + Self::select_random_block(auction_candle_start_block, auction_candle_end_block); let community_start_block = now + 1u32.into(); let community_end_block = now + T::CommunityFundingDuration::get(); // * Update Storage * - Self::calculate_weighted_average_price(project_id, end_block, project_info.fundraising_target)?; + Self::calculate_weighted_average_price( + project_id, + end_block, + project_info.fundraising_target, + )?; // Get info again after updating it with new price. - let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; project_info.phase_transition_points.random_candle_ending = Some(end_block); - project_info.phase_transition_points.community.update(Some(community_start_block), Some(community_end_block)); + project_info + .phase_transition_points + .community + .update(Some(community_start_block), Some(community_end_block)); project_info.project_status = ProjectStatus::CommunityRound; ProjectsDetails::::insert(project_id, project_info); // Schedule for automatic transition by `on_initialize` - Self::add_to_update_store(community_end_block + 1u32.into(), (&project_id, UpdateType::RemainderFundingStart)); + Self::add_to_update_store( + community_end_block + 1u32.into(), + (&project_id, UpdateType::RemainderFundingStart), + ); // * Emit events * Self::deposit_event(Event::::CommunityFundingStarted { project_id }); @@ -446,25 +509,38 @@ impl Pallet { /// [`do_end_funding`](Self::do_end_funding). pub fn do_remainder_funding(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); - let community_end_block = - project_info.phase_transition_points.community.end().ok_or(Error::::FieldIsNone)?; + let community_end_block = project_info + .phase_transition_points + .community + .end() + .ok_or(Error::::FieldIsNone)?; // * Validity checks * ensure!(now > community_end_block, Error::::TooEarlyForRemainderRoundStart); - ensure!(project_info.project_status == ProjectStatus::CommunityRound, Error::::ProjectNotInCommunityRound); + ensure!( + project_info.project_status == ProjectStatus::CommunityRound, + Error::::ProjectNotInCommunityRound + ); // * Calculate new variables * let remainder_start_block = now + 1u32.into(); let remainder_end_block = now + T::RemainderFundingDuration::get(); // * Update Storage * - project_info.phase_transition_points.remainder.update(Some(remainder_start_block), Some(remainder_end_block)); + project_info + .phase_transition_points + .remainder + .update(Some(remainder_start_block), Some(remainder_end_block)); project_info.project_status = ProjectStatus::RemainderRound; ProjectsDetails::::insert(project_id, project_info); // Schedule for automatic transition by `on_initialize` - Self::add_to_update_store(remainder_end_block + 1u32.into(), (&project_id, UpdateType::FundingEnd)); + Self::add_to_update_store( + remainder_end_block + 1u32.into(), + (&project_id, UpdateType::FundingEnd), + ); // * Emit events * Self::deposit_event(Event::::RemainderFundingStarted { project_id }); @@ -504,10 +580,12 @@ impl Pallet { /// If **unsuccessful**, users every user should have their PLMC vesting unbonded. pub fn do_end_funding(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); // TODO: PLMC-149 Check if make sense to set the admin as T::fund_account_id(project_id) - let issuer = ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; + let issuer = + ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; let project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; let token_information = project.token_information; let remaining_cts = project_info.remaining_contribution_tokens; @@ -562,10 +640,14 @@ impl Pallet { /// WIP pub fn do_ready_to_launch(project_id: &T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; // * Validity checks * - ensure!(project_info.project_status == ProjectStatus::FundingEnded, Error::::ProjectNotInFundingEndedRound); + ensure!( + project_info.project_status == ProjectStatus::FundingEnded, + Error::::ProjectNotInFundingEndedRound + ); // Update project Info project_info.project_status = ProjectStatus::ReadyToLaunch; @@ -595,13 +677,18 @@ impl Pallet { project_metadata_hash: T::Hash, ) -> Result<(), DispatchError> { // * Get variables * - let mut project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; - let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project = + ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; + let project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; // * Validity checks * ensure!(ProjectsIssuers::::get(project_id) == Some(issuer), Error::::NotAllowed); ensure!(!project_info.is_frozen, Error::::Frozen); - ensure!(!Images::::contains_key(project_metadata_hash), Error::::MetadataAlreadyExists); + ensure!( + !Images::::contains_key(project_metadata_hash), + Error::::MetadataAlreadyExists + ); // TODO: PLMC-133. Replace this when this PR is merged: https://github.com/KILTprotocol/kilt-node/pull/448 // ensure!( @@ -639,8 +726,10 @@ impl Pallet { amount: BalanceOf, ) -> Result<(), DispatchError> { // * Get variables * - let project_issuer = ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; - let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let project_issuer = + ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; + let project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; // * Validity checks * // TODO: PLMC-133. Replace this when this PR is merged: https://github.com/KILTprotocol/kilt-node/pull/448 @@ -649,7 +738,10 @@ impl Pallet { // Error::::NotAuthorized // ); ensure!(evaluator != project_issuer, Error::::ContributionToThemselves); - ensure!(project_info.project_status == ProjectStatus::EvaluationRound, Error::::EvaluationNotStarted); + ensure!( + project_info.project_status == ProjectStatus::EvaluationRound, + Error::::EvaluationNotStarted + ); // * Calculate new variables * @@ -677,7 +769,11 @@ impl Pallet { .map_err(|_| Error::::InsufficientBalance)?; }, } - Self::deposit_event(Event::::FundsBonded { project_id, amount, bonder: evaluator.clone() }); + Self::deposit_event(Event::::FundsBonded { + project_id, + amount, + bonder: evaluator.clone(), + }); Result::<(), Error>::Ok(()) })?; @@ -700,10 +796,14 @@ impl Pallet { releaser: T::AccountId, ) -> Result<(), DispatchError> { // * Get variables * - let project_info = ProjectsDetails::::get(bond.project).ok_or(Error::::ProjectInfoNotFound)?; + let project_info = + ProjectsDetails::::get(bond.project).ok_or(Error::::ProjectInfoNotFound)?; // * Validity checks * - ensure!(project_info.project_status == ProjectStatus::EvaluationFailed, Error::::EvaluationNotFailed); + ensure!( + project_info.project_status == ProjectStatus::EvaluationFailed, + Error::::EvaluationNotFailed + ); // * Calculate new variables * @@ -744,8 +844,10 @@ impl Pallet { multiplier: Option>, ) -> Result<(), DispatchError> { // * Get variables * - let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; - let project_issuer = ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; + let project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let project_issuer = + ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; let project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; let project_ticket_size = amount.saturating_mul(price); let now = >::block_number(); @@ -754,7 +856,10 @@ impl Pallet { // * Validity checks * ensure!(bidder != project_issuer, Error::::ContributionToThemselves); - ensure!(matches!(project_info.project_status, ProjectStatus::AuctionRound(_)), Error::::AuctionNotStarted); + ensure!( + matches!(project_info.project_status, ProjectStatus::AuctionRound(_)), + Error::::AuctionNotStarted + ); ensure!(price >= project.minimum_price, Error::::BidTooLow); if let Some(minimum_ticket_size) = project.ticket_size.minimum { // Make sure the bid amount is greater than the minimum specified by the issuer @@ -766,9 +871,14 @@ impl Pallet { }; // * Calculate new variables * - let (plmc_vesting_period, ct_vesting_period) = - Self::calculate_vesting_periods(bidder.clone(), multiplier.clone(), amount, price, decimals) - .map_err(|_| Error::::BadMath)?; + let (plmc_vesting_period, ct_vesting_period) = Self::calculate_vesting_periods( + bidder.clone(), + multiplier.clone(), + amount, + price, + decimals, + ) + .map_err(|_| Error::::BadMath)?; let bid_id = Self::next_bid_id(); let required_plmc_bond = plmc_vesting_period.amount; let bid = BidInfo::new( @@ -812,8 +922,9 @@ impl Pallet { }, Err(_) => { // Since the bids are sorted by price, and in this branch the Vec is full, the last element is the lowest bid - let lowest_bid_index: usize = - (T::MaximumBidsPerUser::get() - 1).try_into().map_err(|_| Error::::BadMath)?; + let lowest_bid_index: usize = (T::MaximumBidsPerUser::get() - 1) + .try_into() + .map_err(|_| Error::::BadMath)?; let lowest_bid = user_bids.swap_remove(lowest_bid_index); ensure!(bid > lowest_bid, Error::::BidTooLow); // Unreserve the lowest bid first @@ -821,7 +932,9 @@ impl Pallet { // Reserve the new bid T::FundingCurrency::reserve(&bidder, bid.ticket_size)?; // Add the new bid to the AuctionsInfo, this should never fail since we just removed an element - user_bids.try_push(bid).expect("We removed an element, so there is always space"); + user_bids + .try_push(bid) + .expect("We removed an element, so there is always space"); user_bids.sort_by_key(|bid| Reverse(bid.price)); AuctionsInfo::::set(project_id, bidder, Some(user_bids)); // TODO: PLMC-159. Send an XCM message to Statemine to transfer amount * multiplier USDT to the PalletId Account @@ -855,12 +968,15 @@ impl Pallet { multiplier: Option>, ) -> Result<(), DispatchError> { // * Get variables * - let project_issuer = ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; - let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let project_issuer = + ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; + let project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; // Default should normally be multiplier of 1 let multiplier = multiplier.unwrap_or_default(); - let weighted_average_price = project_info.weighted_average_price.ok_or(Error::::AuctionNotStarted)?; + let weighted_average_price = + project_info.weighted_average_price.ok_or(Error::::AuctionNotStarted)?; let decimals = project.token_information.decimals; let fund_account = Self::fund_account_id(project_id); @@ -897,8 +1013,11 @@ impl Pallet { decimals, ) .map_err(|_| Error::::BadMath)?; - let contribution = - ContributionInfo { contribution_amount: ticket_size, plmc_vesting: plmc_vesting.clone(), ct_vesting }; + let contribution = ContributionInfo { + contribution_amount: ticket_size, + plmc_vesting: plmc_vesting.clone(), + ct_vesting, + }; // Calculate how much plmc is required to be bonded for this contribution, // based on existing unused PLMC bonds for the project @@ -906,13 +1025,15 @@ impl Pallet { let bonded_plmc = ContributingBonds::::get(project_id, contributor.clone()) .map(|bond| bond.amount) .unwrap_or_else(Zero::zero); - let mut user_contributions = Contributions::::get(project_id, contributor.clone()).unwrap_or_default(); + let mut user_contributions = + Contributions::::get(project_id, contributor.clone()).unwrap_or_default(); for contribution in user_contributions.iter() { bonded_plmc.saturating_sub(contribution.plmc_vesting.amount); } required_plmc_bond.saturating_sub(bonded_plmc); - let remaining_cts_after_purchase = project_info.remaining_contribution_tokens.saturating_sub(buyable_tokens); + let remaining_cts_after_purchase = + project_info.remaining_contribution_tokens.saturating_sub(buyable_tokens); let now = >::block_number(); // * Update storage * @@ -924,13 +1045,15 @@ impl Pallet { Ok(_) => { // TODO: PLMC-159. Send an XCM message to Statemint/e to transfer a `bid.market_cap` amount of USDC (or the Currency specified by the issuer) to the PalletId Account // Alternative TODO: PLMC-159. The user should have the specified currency (e.g: USDC) already on Polimec - user_contributions.sort_by_key(|contribution| Reverse(contribution.plmc_vesting.amount)); + user_contributions + .sort_by_key(|contribution| Reverse(contribution.plmc_vesting.amount)); Contributions::::set(project_id, contributor.clone(), Some(user_contributions)); }, Err(_) => { // The contributions are sorted by highest PLMC bond. If the contribution vector for the user is full, we drop the lowest/last item - let lowest_contribution_index: usize = - (T::MaxContributionsPerUser::get() - 1).try_into().map_err(|_| Error::::BadMath)?; + let lowest_contribution_index: usize = (T::MaxContributionsPerUser::get() - 1) + .try_into() + .map_err(|_| Error::::BadMath)?; let lowest_contribution = user_contributions.swap_remove(lowest_contribution_index); ensure!( contribution.plmc_vesting.amount > lowest_contribution.plmc_vesting.amount, @@ -954,7 +1077,8 @@ impl Pallet { // Update the ContributingBonds storage ContributingBonds::::mutate(project_id, contributor.clone(), |maybe_bond| { if let Some(bond) = maybe_bond { - bond.amount = bond.amount.saturating_sub(lowest_contribution.plmc_vesting.amount); + bond.amount = + bond.amount.saturating_sub(lowest_contribution.plmc_vesting.amount); } }); @@ -962,7 +1086,8 @@ impl Pallet { user_contributions .try_push(contribution) .expect("We removed an element, so there is always space; qed"); - user_contributions.sort_by_key(|contribution| Reverse(contribution.plmc_vesting.amount)); + user_contributions + .sort_by_key(|contribution| Reverse(contribution.plmc_vesting.amount)); Contributions::::set(project_id, contributor.clone(), Some(user_contributions)); // TODO: PLMC-159. Send an XCM message to Statemine to transfer amount * multiplier USDT to the PalletId Account }, @@ -990,7 +1115,12 @@ impl Pallet { } // * Emit events * - Self::deposit_event(Event::::Contribution { project_id, contributor, amount: token_amount, multiplier }); + Self::deposit_event(Event::::Contribution { + project_id, + contributor, + amount: token_amount, + multiplier, + }); Ok(()) } @@ -1040,7 +1170,8 @@ impl Pallet { // Update the new vector that will go in AuctionInfo with the updated vesting period struct new_bids.push(bid.clone()); // Update the BiddingBonds map with the reduced amount for that project-user - let mut bond = BiddingBonds::::get(bid.project, bid.bidder.clone()).ok_or(Error::::FieldIsNone)?; + let mut bond = BiddingBonds::::get(bid.project, bid.bidder.clone()) + .ok_or(Error::::FieldIsNone)?; bond.amount = bond.amount.saturating_sub(unbond_amount); // TODO: maybe the BiddingBonds map is redundant, since we can iterate over the Bids vec and calculate it ourselves BiddingBonds::::insert(bid.project, bid.bidder.clone(), bond); @@ -1140,8 +1271,10 @@ impl Pallet { claimer: T::AccountId, ) -> Result<(), DispatchError> { // * Get variables * - let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; - let contributions = Contributions::::get(project_id, &claimer).ok_or(Error::::BidNotFound)?; + let project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; + let contributions = + Contributions::::get(project_id, &claimer).ok_or(Error::::BidNotFound)?; let now = >::block_number(); let mut updated_contributions = vec![]; @@ -1151,7 +1284,10 @@ impl Pallet { // T::HandleMembers::is_in(&MemberRole::Issuer, &issuer), // Error::::NotAuthorized // ); - ensure!(project_info.project_status == ProjectStatus::FundingEnded, Error::::CannotClaimYet); + ensure!( + project_info.project_status == ProjectStatus::FundingEnded, + Error::::CannotClaimYet + ); // TODO: PLMC-160. Check the flow of the final_price if the final price discovery during the Auction Round fails for mut contribution in contributions { @@ -1216,8 +1352,10 @@ impl Pallet { claimer: T::AccountId, ) -> Result<(), DispatchError> { // * Get variables * - let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; - let contributions = Contributions::::get(project_id, &claimer).ok_or(Error::::BidNotFound)?; + let project_info = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; + let contributions = + Contributions::::get(project_id, &claimer).ok_or(Error::::BidNotFound)?; let now = >::block_number(); let mut updated_contributions = vec![]; @@ -1227,7 +1365,10 @@ impl Pallet { // T::HandleMembers::is_in(&MemberRole::Issuer, &issuer), // Error::::NotAuthorized // ); - ensure!(project_info.project_status == ProjectStatus::FundingEnded, Error::::CannotClaimYet); + ensure!( + project_info.project_status == ProjectStatus::FundingEnded, + Error::::CannotClaimYet + ); // TODO: PLMC-160. Check the flow of the final_price if the final price discovery during the Auction Round fails for mut contribution in contributions { @@ -1294,7 +1435,9 @@ impl Pallet { amount: BalanceOf, ) -> Result<(), DispatchError> { let now = >::block_number(); - let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound).unwrap(); + let project_info = ProjectsDetails::::get(project_id) + .ok_or(Error::::ProjectInfoNotFound) + .unwrap(); if let Some(bidding_end_block) = project_info.phase_transition_points.candle_auction.end() { ensure!(now < bidding_end_block, Error::::TooLateForBidBonding); @@ -1322,7 +1465,11 @@ impl Pallet { .map_err(|_| Error::::InsufficientBalance)?; }, } - Self::deposit_event(Event::::FundsBonded { project_id, amount, bonder: caller.clone() }); + Self::deposit_event(Event::::FundsBonded { + project_id, + amount, + bonder: caller.clone(), + }); Result::<(), Error>::Ok(()) })?; @@ -1335,7 +1482,9 @@ impl Pallet { amount: BalanceOf, ) -> Result<(), DispatchError> { let now = >::block_number(); - let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound).unwrap(); + let project_info = ProjectsDetails::::get(project_id) + .ok_or(Error::::ProjectInfoNotFound) + .unwrap(); if let Some(remainder_end_block) = project_info.phase_transition_points.remainder.end() { ensure!(now < remainder_end_block, Error::::TooLateForContributingBonding); @@ -1351,14 +1500,22 @@ impl Pallet { }, None => { // If the user has not bonded yet, create a new bond - *maybe_bond = Some(ContributingBond { project: project_id, account: caller.clone(), amount }); + *maybe_bond = Some(ContributingBond { + project: project_id, + account: caller.clone(), + amount, + }); // Reserve the required PLMC T::NativeCurrency::reserve_named(&BondType::Contributing, &caller, amount) .map_err(|_| Error::::InsufficientBalance)?; }, } - Self::deposit_event(Event::::FundsBonded { project_id, amount, bonder: caller.clone() }); + Self::deposit_event(Event::::FundsBonded { + project_id, + amount, + bonder: caller.clone(), + }); Result::<(), Error>::Ok(()) })?; @@ -1366,7 +1523,10 @@ impl Pallet { } /// Adds a project to the ProjectsToUpdate storage, so it can be updated at some later point in time. - pub fn add_to_update_store(block_number: T::BlockNumber, store: (&T::ProjectIdentifier, UpdateType)) { + pub fn add_to_update_store( + block_number: T::BlockNumber, + store: (&T::ProjectIdentifier, UpdateType), + ) { // Try to get the project into the earliest possible block to update. // There is a limit for how many projects can update each block, so we need to make sure we don't exceed that limit let mut block_number = block_number; @@ -1376,10 +1536,13 @@ impl Pallet { } } - pub fn remove_from_update_store(project_id: &T::ProjectIdentifier) -> Result<(), DispatchError> { + pub fn remove_from_update_store( + project_id: &T::ProjectIdentifier, + ) -> Result<(), DispatchError> { let (block_position, project_index) = ProjectsToUpdate::::iter() .find_map(|(block, project_vec)| { - let project_index = project_vec.iter().position(|(id, _update_type)| id == project_id)?; + let project_index = + project_vec.iter().position(|(id, _update_type)| id == project_id)?; Some((block, project_index)) }) .ok_or(Error::::ProjectNotInUpdateStore)?; @@ -1399,7 +1562,8 @@ impl Pallet { token_amount: BalanceOf, token_price: BalanceOf, decimals: u8, - ) -> Result<(Vesting>, Vesting>), ()> { + ) -> Result<(Vesting>, Vesting>), ()> + { let plmc_start: T::BlockNumber = 0u32.into(); let ct_start: T::BlockNumber = (T::MaxProjectsToUpdatePerBlock::get() * 7).into(); // TODO: Calculate real vesting periods based on multiplier and caller type @@ -1459,7 +1623,8 @@ impl Pallet { } else { bid_amount_sum.saturating_accrue(buyable_amount); bid_value_sum.saturating_accrue(buyable_amount * bid.price); - bid.status = BidStatus::PartiallyAccepted(buyable_amount, RejectionReason::NoTokensLeft) + bid.status = + BidStatus::PartiallyAccepted(buyable_amount, RejectionReason::NoTokensLeft) // TODO: PLMC-147. Refund remaining amount } @@ -1469,13 +1634,20 @@ impl Pallet { // Update the bid in the storage for bid in bids.iter() { - AuctionsInfo::::mutate(project_id, bid.bidder.clone(), |maybe_bids| -> Result<(), DispatchError> { - let mut bids = maybe_bids.clone().ok_or(Error::::ImpossibleState)?; - let bid_index = bids.iter().position(|b| b.bid_id == bid.bid_id).ok_or(Error::::ImpossibleState)?; - bids[bid_index] = bid.clone(); - *maybe_bids = Some(bids); - Ok(()) - })?; + AuctionsInfo::::mutate( + project_id, + bid.bidder.clone(), + |maybe_bids| -> Result<(), DispatchError> { + let mut bids = maybe_bids.clone().ok_or(Error::::ImpossibleState)?; + let bid_index = bids + .iter() + .position(|b| b.bid_id == bid.bid_id) + .ok_or(Error::::ImpossibleState)?; + bids[bid_index] = bid.clone(); + *maybe_bids = Some(bids); + Ok(()) + }, + )?; } // Calculate the weighted price of the token for the next funding rounds, using winning bids. @@ -1500,7 +1672,8 @@ impl Pallet { // TODO: PLMC-150. collecting due to previous mut borrow, find a way to not collect and borrow bid on filter_map .into_iter() .filter_map(|bid| match bid.status { - BidStatus::Accepted => Some(Perbill::from_rational(bid.amount * bid.price, bid_value_sum) * bid.price), + BidStatus::Accepted => + Some(Perbill::from_rational(bid.amount * bid.price, bid_value_sum) * bid.price), BidStatus::PartiallyAccepted(amount, _) => Some(Perbill::from_rational(amount * bid.price, bid_value_sum) * bid.price), _ => None, @@ -1512,7 +1685,8 @@ impl Pallet { ProjectsDetails::::mutate(project_id, |maybe_info| -> Result<(), DispatchError> { if let Some(info) = maybe_info { info.weighted_average_price = Some(weighted_token_price); - info.remaining_contribution_tokens = info.remaining_contribution_tokens.saturating_sub(bid_amount_sum); + info.remaining_contribution_tokens = + info.remaining_contribution_tokens.saturating_sub(bid_amount_sum); Ok(()) } else { Err(Error::::ProjectNotFound.into()) diff --git a/pallets/funding/src/lib.rs b/pallets/funding/src/lib.rs index 3f5d77c30..41202a2dc 100644 --- a/pallets/funding/src/lib.rs +++ b/pallets/funding/src/lib.rs @@ -218,8 +218,11 @@ use sp_std::prelude::*; type BalanceOf = ::Balance; -type ProjectMetadataOf = - ProjectMetadata::StringLimit>, BalanceOf, ::Hash>; +type ProjectMetadataOf = ProjectMetadata< + BoundedVec::StringLimit>, + BalanceOf, + ::Hash, +>; type ProjectDetailsOf = ProjectDetails<::BlockNumber, BalanceOf>; @@ -392,17 +395,20 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn projects)] /// A StorageMap containing the primary project information of projects - pub type ProjectsMetadata = StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, ProjectMetadataOf>; + pub type ProjectsMetadata = + StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, ProjectMetadataOf>; #[pallet::storage] #[pallet::getter(fn project_issuer)] /// StorageMap to get the issuer of a project - pub type ProjectsIssuers = StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, T::AccountId>; + pub type ProjectsIssuers = + StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, T::AccountId>; #[pallet::storage] #[pallet::getter(fn project_info)] /// StorageMap containing additional information for the projects, relevant for correctness of the protocol - pub type ProjectsDetails = StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, ProjectDetailsOf>; + pub type ProjectsDetails = + StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, ProjectDetailsOf>; #[pallet::storage] #[pallet::getter(fn projects_to_update)] @@ -508,7 +514,12 @@ pub mod pallet { releaser: T::AccountId, }, /// A bid was made for a project - Bid { project_id: T::ProjectIdentifier, amount: BalanceOf, price: BalanceOf, multiplier: MultiplierOf }, + Bid { + project_id: T::ProjectIdentifier, + amount: BalanceOf, + price: BalanceOf, + multiplier: MultiplierOf, + }, /// A contribution was made for a project. i.e token purchase Contribution { project_id: T::ProjectIdentifier, @@ -668,7 +679,10 @@ pub mod pallet { /// Starts the evaluation round of a project. It needs to be called by the project issuer. #[pallet::weight(T::WeightInfo::start_evaluation())] - pub fn start_evaluation(origin: OriginFor, project_id: T::ProjectIdParameter) -> DispatchResult { + pub fn start_evaluation( + origin: OriginFor, + project_id: T::ProjectIdParameter, + ) -> DispatchResult { let issuer = ensure_signed(origin)?; let project_id = project_id.into(); @@ -687,7 +701,10 @@ pub mod pallet { /// institutional user can set bids for a token_amount/token_price pair. /// Any bids from this point until the candle_auction starts, will be considered as valid. #[pallet::weight(T::WeightInfo::start_auction())] - pub fn start_auction(origin: OriginFor, project_id: T::ProjectIdParameter) -> DispatchResult { + pub fn start_auction( + origin: OriginFor, + project_id: T::ProjectIdParameter, + ) -> DispatchResult { let issuer = ensure_signed(origin)?; let project_id = project_id.into(); @@ -722,7 +739,8 @@ pub mod pallet { bonder: T::AccountId, ) -> DispatchResult { let releaser = ensure_signed(origin)?; - let bond = EvaluationBonds::::get(project_id.into(), bonder).ok_or(Error::::BondNotFound)?; + let bond = EvaluationBonds::::get(project_id.into(), bonder) + .ok_or(Error::::BondNotFound)?; Self::do_failed_evaluation_unbond_for(bond, releaser) } @@ -858,7 +876,8 @@ pub mod pallet { } fn on_idle(_now: T::BlockNumber, max_weight: Weight) -> Weight { - let pallet_account: T::AccountId = ::PalletId::get().into_account_truncating(); + let pallet_account: T::AccountId = + ::PalletId::get().into_account_truncating(); let mut remaining_weight = max_weight; @@ -875,7 +894,9 @@ pub mod pallet { // Get a flat list of bonds .flat_map(|project_id| { // get all the bonds for projects with a failed evaluation phase - EvaluationBonds::::iter_prefix(project_id).map(|(_bonder, bond)| bond).collect::>() + EvaluationBonds::::iter_prefix(project_id) + .map(|(_bonder, bond)| bond) + .collect::>() }) // Retrieve as many as possible for the given weight .take_while(|_| { @@ -915,7 +936,6 @@ pub mod pallet { fn create_project_id_parameter(id: u32) -> T::ProjectIdParameter { id.into() } - fn create_dummy_project(metadata_hash: T::Hash) -> ProjectMetadataOf { let project: ProjectMetadataOf = ProjectMetadata { total_allocation_size: 1_000_000u64.into(), @@ -956,7 +976,10 @@ pub mod local_macros { match $option { Ok(val) => val, Err(err) => { - Self::deposit_event(Event::::TransitionError { project_id: $project_id, error: err }); + Self::deposit_event(Event::::TransitionError { + project_id: $project_id, + error: err, + }); continue }, } diff --git a/pallets/funding/src/mock.rs b/pallets/funding/src/mock.rs index 9814c651e..9459da70c 100644 --- a/pallets/funding/src/mock.rs +++ b/pallets/funding/src/mock.rs @@ -63,30 +63,30 @@ parameter_types! { } impl system::Config for TestRuntime { - type AccountData = pallet_balances::AccountData; - type AccountId = AccountId; type BaseCallFilter = frame_support::traits::Everything; - type BlockHashCount = BlockHashCount; + type BlockWeights = (); type BlockLength = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = u64; type BlockNumber = BlockNumber; - type BlockWeights = (); - type DbWeight = (); type Hash = H256; type Hashing = BlakeTwo256; - type Header = Header; - type Index = u64; + type AccountId = AccountId; type Lookup = IdentityLookup; - type MaxConsumers = frame_support::traits::ConstU32<16>; - type OnKilledAccount = (); - type OnNewAccount = (); - type OnSetCode = (); - type PalletInfo = PalletInfo; - type RuntimeCall = RuntimeCall; + type Header = Header; type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; - type SS58Prefix = ConstU16<42>; - type SystemWeightInfo = (); + type BlockHashCount = BlockHashCount; + type DbWeight = (); type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = ConstU16<42>; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { @@ -94,44 +94,44 @@ parameter_types! { } impl pallet_balances::Config for TestRuntime { - type AccountStore = System; - type Balance = Balance; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type FreezeIdentifier = (); - type HoldIdentifier = BondType; - type MaxFreezes = (); - type MaxHolds = ConstU32<1024>; type MaxLocks = frame_support::traits::ConstU32<1024>; type MaxReserves = frame_support::traits::ConstU32<1024>; type ReserveIdentifier = BondType; + type Balance = Balance; type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; type WeightInfo = (); + type MaxHolds = ConstU32<1024>; + type MaxFreezes = (); + type HoldIdentifier = BondType; + type FreezeIdentifier = (); } impl pallet_insecure_randomness_collective_flip::Config for TestRuntime {} impl pallet_assets::Config for TestRuntime { - type ApprovalDeposit = ConstU128<1>; - type AssetAccountDeposit = ConstU128<10>; - type AssetDeposit = ConstU128<1>; - type AssetId = Identifier; - type AssetIdParameter = Identifier; + type RuntimeEvent = RuntimeEvent; type Balance = Balance; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); - type CallbackHandle = (); - type CreateOrigin = AsEnsureOriginWithArg>; + type AssetId = Identifier; type Currency = Balances; - type Extra = (); type ForceOrigin = frame_system::EnsureRoot; - type Freezer = (); + type AssetDeposit = ConstU128<1>; + type AssetAccountDeposit = ConstU128<10>; type MetadataDepositBase = ConstU128<1>; type MetadataDepositPerByte = ConstU128<1>; - type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; - type RuntimeEvent = RuntimeEvent; + type ApprovalDeposit = ConstU128<1>; type StringLimit = ConstU32<50>; + type Freezer = (); type WeightInfo = (); + type Extra = (); + type AssetIdParameter = Identifier; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); } pub const HOURS: BlockNumber = 300u64; @@ -148,33 +148,33 @@ parameter_types! { } impl pallet_funding::Config for TestRuntime { - type AuctionInitializePeriodDuration = AuctionInitializePeriodDuration; - type Balance = Balance; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); + type RuntimeEvent = RuntimeEvent; + type StringLimit = ConstU32<64>; + type ProjectIdentifier = Identifier; + type ProjectIdParameter = Identifier; type BidId = u128; - type CandleAuctionDuration = CandleAuctionDuration; - type CommunityFundingDuration = CommunityRoundDuration; type ContributionTokenCurrency = Assets; - type ContributionVesting = ConstU32<4>; - type EnglishAuctionDuration = EnglishAuctionDuration; type EvaluationDuration = EvaluationDuration; - type FundingCurrency = Balances; - type MaxContributionsPerUser = ConstU32<4>; + type AuctionInitializePeriodDuration = AuctionInitializePeriodDuration; + type EnglishAuctionDuration = EnglishAuctionDuration; + type CandleAuctionDuration = CandleAuctionDuration; + type RemainderFundingDuration = RemainderFundingDuration; + type PalletId = FundingPalletId; type MaxProjectsToUpdatePerBlock = ConstU32<100>; + type CommunityFundingDuration = CommunityRoundDuration; + type Randomness = RandomnessCollectiveFlip; + type PreImageLimit = ConstU32<1024>; // Low value to simplify the tests type MaximumBidsPerUser = ConstU32<4>; + type MaxContributionsPerUser = ConstU32<4>; + type ContributionVesting = ConstU32<4>; + type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); type Multiplier = types::Multiplier; + type Balance = Balance; type NativeCurrency = Balances; - type PalletId = FundingPalletId; - type PreImageLimit = ConstU32<1024>; - type ProjectIdParameter = Identifier; - type ProjectIdentifier = Identifier; - type Randomness = RandomnessCollectiveFlip; - type RemainderFundingDuration = RemainderFundingDuration; - type RuntimeEvent = RuntimeEvent; - type StringLimit = ConstU32<64>; - type WeightInfo = (); + type FundingCurrency = Balances; } // Build genesis storage according to the mock runtime. diff --git a/pallets/funding/src/tests.rs b/pallets/funding/src/tests.rs index 2f1f3f87e..a62e9b98d 100644 --- a/pallets/funding/src/tests.rs +++ b/pallets/funding/src/tests.rs @@ -36,8 +36,12 @@ use std::cell::RefCell; type ProjectIdOf = ::ProjectIdentifier; type UserToBalance = Vec<(mock::AccountId, BalanceOf)>; // User -> token_amount, price_per_token, multiplier -type UserToBid = Vec<(AccountId, (BalanceOf, BalanceOf, Option>))>; -type UserToContribution = Vec<(AccountId, (BalanceOf, Option>))>; +type UserToBid = Vec<( + AccountId, + (BalanceOf, BalanceOf, Option>), +)>; +type UserToContribution = + Vec<(AccountId, (BalanceOf, Option>))>; const ISSUER: AccountId = 1; const EVALUATOR_1: AccountId = 2; @@ -68,11 +72,17 @@ const METADATA: &str = r#" // } /// Remove accounts from fundings_1 that are not in fundings_2 -fn remove_missing_accounts_from_fundings(fundings_1: UserToBalance, fundings_2: UserToBalance) -> UserToBalance { +fn remove_missing_accounts_from_fundings( + fundings_1: UserToBalance, + fundings_2: UserToBalance, +) -> UserToBalance { let mut fundings_1 = fundings_1; let fundings_2 = fundings_2; fundings_1.retain(|(account, _)| { - fundings_2.iter().find_map(|(account_2, _)| if account == account_2 { Some(()) } else { None }).is_some() + fundings_2 + .iter() + .find_map(|(account_2, _)| if account == account_2 { Some(()) } else { None }) + .is_some() }); fundings_1 } @@ -83,18 +93,19 @@ trait ProjectInstance { fn get_creator(&self) -> AccountId; fn get_project_id(&self) -> ProjectIdOf; fn get_project(&self) -> ProjectMetadataOf { - self.get_test_environment() - .ext_env - .borrow_mut() - .execute_with(|| FundingModule::projects(self.get_project_id()).expect("Project info should exist")) + self.get_test_environment().ext_env.borrow_mut().execute_with(|| { + FundingModule::projects(self.get_project_id()).expect("Project info should exist") + }) } fn get_project_info(&self) -> ProjectDetailsOf { - self.get_test_environment() - .ext_env - .borrow_mut() - .execute_with(|| FundingModule::project_info(self.get_project_id()).expect("Project info should exist")) + self.get_test_environment().ext_env.borrow_mut().execute_with(|| { + FundingModule::project_info(self.get_project_id()).expect("Project info should exist") + }) } - fn do_project_assertions(&self, project_assertions: impl Fn(ProjectIdOf, &TestEnvironment) -> ()) { + fn do_project_assertions( + &self, + project_assertions: impl Fn(ProjectIdOf, &TestEnvironment) -> (), + ) { let project_id = self.get_project_id(); let test_env = self.get_test_environment(); project_assertions(project_id, test_env); @@ -111,21 +122,23 @@ impl TestEnvironment { pub fn new() -> Self { Self { ext_env: RefCell::new(new_test_ext()), nonce: RefCell::new(0u64) } } - fn create_project( &self, creator: mock::AccountId, project: ProjectMetadataOf, ) -> Result { // Create project in the externalities environment of this struct instance - self.ext_env.borrow_mut().execute_with(|| FundingModule::create(RuntimeOrigin::signed(creator), project))?; + self.ext_env + .borrow_mut() + .execute_with(|| FundingModule::create(RuntimeOrigin::signed(creator), project))?; // Retrieve the project_id from the events let project_id = self.ext_env.borrow_mut().execute_with(|| { frame_system::Pallet::::events() .iter() .filter_map(|event| match event.event { - RuntimeEvent::FundingModule(crate::Event::Created { project_id }) => Some(project_id), + RuntimeEvent::FundingModule(crate::Event::Created { project_id }) => + Some(project_id), _ => None, }) .last() @@ -135,13 +148,13 @@ impl TestEnvironment { Ok(CreatedProject { test_env: self, creator, project_id }) } - /// Returns the *free* fundings of the Users. #[allow(dead_code)] fn get_free_fundings(&self) -> UserToBalance { self.ext_env.borrow_mut().execute_with(|| { let mut fundings = UserToBalance::new(); - let user_keys: Vec = frame_system::Account::::iter_keys().collect(); + let user_keys: Vec = + frame_system::Account::::iter_keys().collect(); for user in user_keys { let funding = Balances::free_balance(&user); fundings.push((user, funding)); @@ -149,13 +162,13 @@ impl TestEnvironment { fundings }) } - /// Returns the *reserved* fundings of the Users. #[allow(dead_code)] fn get_reserved_fundings(&self, reserve_type: BondType) -> UserToBalance { self.ext_env.borrow_mut().execute_with(|| { let mut fundings = UserToBalance::new(); - let user_keys: Vec = frame_system::Account::::iter_keys().collect(); + let user_keys: Vec = + frame_system::Account::::iter_keys().collect(); for user in user_keys { let funding = Balances::reserved_balance_named(&reserve_type, &user); fundings.push((user, funding)); @@ -163,7 +176,6 @@ impl TestEnvironment { fundings }) } - fn fund_accounts(&self, fundings: UserToBalance) { self.ext_env.borrow_mut().execute_with(|| { for (account, amount) in fundings { @@ -171,22 +183,22 @@ impl TestEnvironment { } }); } - fn current_block(&self) -> BlockNumber { self.ext_env.borrow_mut().execute_with(|| System::block_number()) } - fn advance_time(&self, amount: BlockNumber) { self.ext_env.borrow_mut().execute_with(|| { for _block in 0..amount { >::on_finalize(System::block_number()); - >::on_idle(System::block_number(), Weight::MAX); + >::on_idle( + System::block_number(), + Weight::MAX, + ); System::set_block_number(System::block_number() + 1); >::on_initialize(System::block_number()); } }); } - fn do_free_funds_assertions(&self, correct_funds: UserToBalance) { for (user, balance) in correct_funds { self.ext_env.borrow_mut().execute_with(|| { @@ -195,7 +207,6 @@ impl TestEnvironment { }); } } - fn do_reserved_funds_assertions(&self, correct_funds: UserToBalance, reserve_type: BondType) { for (user, balance) in correct_funds { self.ext_env.borrow_mut().execute_with(|| { @@ -216,11 +227,9 @@ impl<'a> ProjectInstance for CreatedProject<'a> { fn get_test_environment(&self) -> &TestEnvironment { self.test_env } - fn get_creator(&self) -> AccountId { self.creator.clone() } - fn get_project_id(&self) -> ProjectIdOf { self.project_id.clone() } @@ -229,20 +238,28 @@ impl<'a> CreatedProject<'a> { fn new_default(test_env: &'a TestEnvironment) -> Self { test_env.fund_accounts(default_fundings()); let creator = default_fundings()[0].0; - let project = test_env.create_project(creator, default_project(test_env.nonce.borrow().clone())).unwrap(); + let project = test_env + .create_project(creator, default_project(test_env.nonce.borrow().clone())) + .unwrap(); project.do_project_assertions(default_creation_assertions); *test_env.nonce.borrow_mut() += 1; project } // Move to next project phase - fn start_evaluation(self, caller: mock::AccountId) -> Result, DispatchError> { - self.test_env - .ext_env - .borrow_mut() - .execute_with(|| FundingModule::start_evaluation(RuntimeOrigin::signed(caller), self.project_id))?; + fn start_evaluation( + self, + caller: mock::AccountId, + ) -> Result, DispatchError> { + self.test_env.ext_env.borrow_mut().execute_with(|| { + FundingModule::start_evaluation(RuntimeOrigin::signed(caller), self.project_id) + })?; - Ok(EvaluatingProject { test_env: self.test_env, creator: self.creator, project_id: self.project_id }) + Ok(EvaluatingProject { + test_env: self.test_env, + creator: self.creator, + project_id: self.project_id, + }) } } @@ -256,11 +273,9 @@ impl<'a> ProjectInstance for EvaluatingProject<'a> { fn get_test_environment(&self) -> &TestEnvironment { self.test_env } - fn get_creator(&self) -> AccountId { self.creator.clone() } - fn get_project_id(&self) -> ProjectIdOf { self.project_id.clone() } @@ -278,10 +293,9 @@ impl<'a> EvaluatingProject<'a> { fn bond_for_users(&self, bonds: UserToBalance) -> Result<(), DispatchError> { let project_id = self.get_project_id(); for (account, amount) in bonds { - self.test_env - .ext_env - .borrow_mut() - .execute_with(|| FundingModule::bond_evaluation(RuntimeOrigin::signed(account), project_id, amount))?; + self.test_env.ext_env.borrow_mut().execute_with(|| { + FundingModule::bond_evaluation(RuntimeOrigin::signed(account), project_id, amount) + })?; } Ok(()) } @@ -289,7 +303,11 @@ impl<'a> EvaluatingProject<'a> { fn start_auction(self, caller: AccountId) -> Result, DispatchError> { self.test_env.ext_env.borrow_mut().execute_with(|| { FundingModule::start_auction(RuntimeOrigin::signed(caller), self.project_id)?; - Ok(AuctioningProject { test_env: self.test_env, creator: self.creator, project_id: self.project_id }) + Ok(AuctioningProject { + test_env: self.test_env, + creator: self.creator, + project_id: self.project_id, + }) }) } } @@ -304,11 +322,9 @@ impl<'a> ProjectInstance for AuctioningProject<'a> { fn get_test_environment(&self) -> &TestEnvironment { self.test_env } - fn get_creator(&self) -> AccountId { self.creator.clone() } - fn get_project_id(&self) -> ProjectIdOf { self.project_id.clone() } @@ -319,7 +335,9 @@ impl<'a> AuctioningProject<'a> { let creator = evaluating_project.get_creator(); // Do Evaluation bonding - evaluating_project.bond_for_users(default_evaluation_bonds()).expect("Bonding should work"); + evaluating_project + .bond_for_users(default_evaluation_bonds()) + .expect("Bonding should work"); // Check that enough funds are reserved test_env.do_reserved_funds_assertions(default_evaluation_bonds(), BondType::Evaluation); @@ -384,7 +402,11 @@ impl<'a> AuctioningProject<'a> { .expect("Candle end point should exist"); self.test_env.advance_time(candle_end - self.test_env.current_block() + 1); assert_eq!(self.get_project_info().project_status, ProjectStatus::CommunityRound); - CommunityFundingProject { test_env: self.test_env, creator: self.creator, project_id: self.project_id } + CommunityFundingProject { + test_env: self.test_env, + creator: self.creator, + project_id: self.project_id, + } } } @@ -398,11 +420,9 @@ impl<'a> ProjectInstance for CommunityFundingProject<'a> { fn get_test_environment(&self) -> &TestEnvironment { self.test_env } - fn get_creator(&self) -> AccountId { self.creator.clone() } - fn get_project_id(&self) -> ProjectIdOf { self.project_id.clone() } @@ -412,7 +432,9 @@ impl<'a> CommunityFundingProject<'a> { let auctioning_project = AuctioningProject::new_default(test_env); // Do Auction bidding - auctioning_project.bid_for_users(default_auction_bids()).expect("Bidding should work"); + auctioning_project + .bid_for_users(default_auction_bids()) + .expect("Bidding should work"); // Check our auction was properly interpreted test_env.advance_time(1); @@ -431,7 +453,12 @@ impl<'a> CommunityFundingProject<'a> { let project_id = self.get_project_id(); for (account, (ct_amount, multiplier)) in buys { self.test_env.ext_env.borrow_mut().execute_with(|| { - FundingModule::contribute(RuntimeOrigin::signed(account), project_id, ct_amount, multiplier) + FundingModule::contribute( + RuntimeOrigin::signed(account), + project_id, + ct_amount, + multiplier, + ) })?; } Ok(()) @@ -444,9 +471,14 @@ impl<'a> CommunityFundingProject<'a> { .community .end() .expect("Community funding end point should exist"); - self.test_env.advance_time(community_funding_end - self.test_env.current_block() + 1); + self.test_env + .advance_time(community_funding_end - self.test_env.current_block() + 1); assert_eq!(self.get_project_info().project_status, ProjectStatus::RemainderRound); - RemainderFundingProject { test_env: self.test_env, creator: self.creator, project_id: self.project_id } + RemainderFundingProject { + test_env: self.test_env, + creator: self.creator, + project_id: self.project_id, + } } } @@ -460,11 +492,9 @@ impl<'a> ProjectInstance for RemainderFundingProject<'a> { fn get_test_environment(&self) -> &TestEnvironment { self.test_env } - fn get_creator(&self) -> AccountId { self.creator.clone() } - fn get_project_id(&self) -> ProjectIdOf { self.project_id.clone() } @@ -474,7 +504,12 @@ impl<'a> RemainderFundingProject<'a> { let project_id = self.get_project_id(); for (account, (ct_amount, multiplier)) in buys { self.test_env.ext_env.borrow_mut().execute_with(|| { - FundingModule::contribute(RuntimeOrigin::signed(account), project_id, ct_amount, multiplier) + FundingModule::contribute( + RuntimeOrigin::signed(account), + project_id, + ct_amount, + multiplier, + ) })?; } Ok(()) @@ -484,7 +519,9 @@ impl<'a> RemainderFundingProject<'a> { let community_funding_project = CommunityFundingProject::new_default(test_env); // Do community buying - community_funding_project.buy_for_retail_users(default_community_buys()).expect("Community buying should work"); + community_funding_project + .buy_for_retail_users(default_community_buys()) + .expect("Community buying should work"); // Check our buys were properly interpreted test_env.advance_time(1); @@ -506,9 +543,14 @@ impl<'a> RemainderFundingProject<'a> { .remainder .end() .expect("Remainder funding end point should exist"); - self.test_env.advance_time(remainder_funding_end - self.test_env.current_block() + 1); + self.test_env + .advance_time(remainder_funding_end - self.test_env.current_block() + 1); assert_eq!(self.get_project_info().project_status, ProjectStatus::FundingEnded); - FinishedProject { test_env: self.test_env, creator: self.creator, project_id: self.project_id } + FinishedProject { + test_env: self.test_env, + creator: self.creator, + project_id: self.project_id, + } } } @@ -522,11 +564,9 @@ impl<'a> ProjectInstance for FinishedProject<'a> { fn get_test_environment(&self) -> &TestEnvironment { self.test_env } - fn get_creator(&self) -> AccountId { self.creator.clone() } - fn get_project_id(&self) -> ProjectIdOf { self.project_id.clone() } @@ -534,7 +574,9 @@ impl<'a> ProjectInstance for FinishedProject<'a> { impl<'a> FinishedProject<'a> { fn new_default(test_env: &'a TestEnvironment) -> Self { let remainder_funding_project = RemainderFundingProject::new_default(test_env); - remainder_funding_project.buy_for_any_user(default_remainder_buys()).expect("Buying should work"); + remainder_funding_project + .buy_for_any_user(default_remainder_buys()) + .expect("Buying should work"); // End project funding by moving block to after the end of remainder round let finished_project = remainder_funding_project.finish_project(); @@ -550,8 +592,11 @@ mod defaults { use super::*; use crate::traits::BondingRequirementCalculation; - pub fn default_project(nonce: u64) -> ProjectMetadata>, u128, sp_core::H256> { - let bounded_name = BoundedVec::try_from("Contribution Token TEST".as_bytes().to_vec()).unwrap(); + pub fn default_project( + nonce: u64, + ) -> ProjectMetadata>, u128, sp_core::H256> { + let bounded_name = + BoundedVec::try_from("Contribution Token TEST".as_bytes().to_vec()).unwrap(); let bounded_symbol = BoundedVec::try_from("CTEST".as_bytes().to_vec()).unwrap(); let metadata_hash = hashed(format!("{}-{}", METADATA, nonce)); ProjectMetadata { @@ -590,11 +635,18 @@ mod defaults { pub fn default_evaluation_bonds() -> UserToBalance { // currently the default project needs 100_000 PLMC to be successful in the evaluation round // we assume we will use this bond twice - vec![(EVALUATOR_1, 20_000 * PLMC), (EVALUATOR_2, 30_000 * PLMC), (EVALUATOR_3, 60_000 * PLMC)] + vec![ + (EVALUATOR_1, 20_000 * PLMC), + (EVALUATOR_2, 30_000 * PLMC), + (EVALUATOR_3, 60_000 * PLMC), + ] } pub fn default_failing_evaluation_bonds() -> UserToBalance { - default_evaluation_bonds().into_iter().map(|(user, balance)| (user, balance / 2)).collect::() + default_evaluation_bonds() + .into_iter() + .map(|(user, balance)| (user, balance / 2)) + .collect::() } pub fn default_auction_bids() -> UserToBid { @@ -610,26 +662,46 @@ mod defaults { default_auction_bids() .into_iter() .map(|(user, (amount, price, mult))| { - (user, (mult.unwrap_or_default().calculate_bonding_requirement(amount * price).unwrap())) + ( + user, + (mult + .unwrap_or_default() + .calculate_bonding_requirement(amount * price) + .unwrap()), + ) }) .collect() } pub fn default_auction_bids_currency_reserved() -> UserToBalance { - default_auction_bids().into_iter().map(|(user, (amount, price, _mult))| (user, (amount * price))).collect() + default_auction_bids() + .into_iter() + .map(|(user, (amount, price, _mult))| (user, (amount * price))) + .collect() } pub fn default_community_plmc_bondings(price: BalanceOf) -> UserToBalance { default_community_buys() .into_iter() .map(|(user, (amount, multiplier))| { - (user, (multiplier.unwrap_or_default().calculate_bonding_requirement(amount * price).unwrap())) + ( + user, + (multiplier + .unwrap_or_default() + .calculate_bonding_requirement(amount * price) + .unwrap()), + ) }) .collect() } - pub fn default_community_buys_currency_reserved(price: BalanceOf) -> UserToBalance { - default_community_buys().into_iter().map(|(user, (amount, _multiplier))| (user, (amount * price))).collect() + pub fn default_community_buys_currency_reserved( + price: BalanceOf, + ) -> UserToBalance { + default_community_buys() + .into_iter() + .map(|(user, (amount, _multiplier))| (user, (amount * price))) + .collect() } pub fn default_community_buys() -> UserToContribution { @@ -646,37 +718,60 @@ mod defaults { // vec![(BUYER_1, (100 * PLMC)), (BUYER_2, (6000 * PLMC))] // } - pub fn default_creation_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { + pub fn default_creation_assertions( + project_id: ProjectIdOf, + test_env: &TestEnvironment, + ) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = + FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::Application); }); } - pub fn default_evaluation_start_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { + pub fn default_evaluation_start_assertions( + project_id: ProjectIdOf, + test_env: &TestEnvironment, + ) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = + FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::EvaluationRound); }); } - pub fn default_evaluation_end_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { + pub fn default_evaluation_end_assertions( + project_id: ProjectIdOf, + test_env: &TestEnvironment, + ) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = + FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::AuctionInitializePeriod); }); } - pub fn default_auction_start_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { + pub fn default_auction_start_assertions( + project_id: ProjectIdOf, + test_env: &TestEnvironment, + ) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); - assert_eq!(project_info.project_status, ProjectStatus::AuctionRound(AuctionPhase::English)); + let project_info = + FundingModule::project_info(project_id).expect("Project info should exist"); + assert_eq!( + project_info.project_status, + ProjectStatus::AuctionRound(AuctionPhase::English) + ); }); } - pub fn default_auction_end_assertions(_project_id: ProjectIdOf, test_env: &TestEnvironment) { + pub fn default_auction_end_assertions( + _project_id: ProjectIdOf, + test_env: &TestEnvironment, + ) { // Check that enough PLMC is bonded - test_env.do_reserved_funds_assertions(default_auction_bids_plmc_bondings(), BondType::Bidding); + test_env + .do_reserved_funds_assertions(default_auction_bids_plmc_bondings(), BondType::Bidding); // Check that the bidding currency is reserved test_env.ext_env.borrow_mut().execute_with(|| { @@ -697,7 +792,8 @@ mod defaults { // Check that free funds were reduced let mut free_funds = default_fundings(); // Remove accounts that didnt bond from free_funds - free_funds = remove_missing_accounts_from_fundings(free_funds, default_auction_bids_plmc_bondings()); + free_funds = + remove_missing_accounts_from_fundings(free_funds, default_auction_bids_plmc_bondings()); // Subtract plmc bonded bidding funds free_funds = free_funds .iter() @@ -735,21 +831,30 @@ mod defaults { }); // PLMC should still be reserved, since its only a bond - test_env.do_reserved_funds_assertions(default_auction_bids_plmc_bondings(), BondType::Bidding); + test_env + .do_reserved_funds_assertions(default_auction_bids_plmc_bondings(), BondType::Bidding); // Check for correct project information test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = + FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::CommunityRound); // Check correct weighted_average_price - let token_price = project_info.weighted_average_price.expect("Token price should exist"); - assert_eq!(token_price, default_token_average_price(), "Weighted average token price is incorrect"); + let token_price = + project_info.weighted_average_price.expect("Token price should exist"); + assert_eq!( + token_price, + default_token_average_price(), + "Weighted average token price is incorrect" + ); // Check that remaining CTs are updated let project = FundingModule::project_info(project_id).expect("Project should exist"); - let bought_tokens: u128 = - default_auction_bids().iter().map(|(_account, (amount, _price, _multiplier))| amount).sum(); + let bought_tokens: u128 = default_auction_bids() + .iter() + .map(|(_account, (amount, _price, _multiplier))| amount) + .sum(); assert_eq!( project.remaining_contribution_tokens, default_project(0).total_allocation_size - bought_tokens, @@ -759,31 +864,43 @@ mod defaults { // Check status of bids test_env.ext_env.borrow_mut().execute_with(|| { - let project_bids = crate::pallet::AuctionsInfo::::iter_prefix(project_id).collect::>(); + let project_bids = crate::pallet::AuctionsInfo::::iter_prefix(project_id) + .collect::>(); let project_info = FundingModule::project_info(project_id).unwrap(); - assert!(matches!(project_info.weighted_average_price, Some(_)), "Weighted average price should exist"); + assert!( + matches!(project_info.weighted_average_price, Some(_)), + "Weighted average price should exist" + ); assert!(project_bids .into_iter() - .find(|(_bidder, bids)| { !bids.iter().all(|bid| bid.status == BidStatus::Accepted) }) + .find(|(_bidder, bids)| { + !bids.iter().all(|bid| bid.status == BidStatus::Accepted) + }) .is_none()); }); } - pub fn default_community_funding_end_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { + pub fn default_community_funding_end_assertions( + project_id: ProjectIdOf, + test_env: &TestEnvironment, + ) { let token_price = test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = + FundingModule::project_info(project_id).expect("Project info should exist"); project_info.weighted_average_price.expect("Token price should exist") }); let expected_plmc_bondings = default_community_plmc_bondings(token_price); let expected_buys = default_community_buys_currency_reserved(token_price); // Check that enough PLMC is bonded - test_env.do_reserved_funds_assertions(expected_plmc_bondings.clone(), BondType::Contributing); + test_env + .do_reserved_funds_assertions(expected_plmc_bondings.clone(), BondType::Contributing); // Check that free funds were reduced let mut free_funds = default_fundings(); // Remove accounts that didnt bond from free_funds - free_funds = remove_missing_accounts_from_fundings(free_funds, expected_plmc_bondings.clone()); + free_funds = + remove_missing_accounts_from_fundings(free_funds, expected_plmc_bondings.clone()); // Subtract the amount spent on the buys from the free funds free_funds = free_funds .iter() @@ -808,13 +925,19 @@ mod defaults { // Check that remaining CTs are updated test_env.ext_env.borrow_mut().execute_with(|| { let project = FundingModule::project_info(project_id).expect("Project should exist"); - let auction_bought_tokens: u128 = - default_auction_bids().iter().map(|(_account, (amount, _price, _multiplier))| amount).sum(); - let community_bought_tokens: u128 = - default_community_buys().iter().map(|(_account, (amount, _multiplier))| amount).sum(); + let auction_bought_tokens: u128 = default_auction_bids() + .iter() + .map(|(_account, (amount, _price, _multiplier))| amount) + .sum(); + let community_bought_tokens: u128 = default_community_buys() + .iter() + .map(|(_account, (amount, _multiplier))| amount) + .sum(); assert_eq!( project.remaining_contribution_tokens, - default_project(0).total_allocation_size - auction_bought_tokens - community_bought_tokens, + default_project(0).total_allocation_size - + auction_bought_tokens - + community_bought_tokens, "Remaining CTs are incorrect" ); }); @@ -825,27 +948,38 @@ mod defaults { test_env: &TestEnvironment, ) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = + FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::RemainderRound); }); } - pub fn default_project_end_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { + pub fn default_project_end_assertions( + project_id: ProjectIdOf, + test_env: &TestEnvironment, + ) { // Check that project status is correct test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = + FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::FundingEnded); }); // Check that remaining CTs are updated test_env.ext_env.borrow_mut().execute_with(|| { let project = FundingModule::project_info(project_id).expect("Project should exist"); - let auction_bought_tokens: u128 = - default_auction_bids().iter().map(|(_account, (amount, _price, _multiplier))| amount).sum(); - let community_bought_tokens: u128 = - default_community_buys().iter().map(|(_account, (amount, _multiplier))| amount).sum(); - let remainder_bought_tokens: u128 = - default_remainder_buys().iter().map(|(_account, (amount, _multiplier))| amount).sum(); + let auction_bought_tokens: u128 = default_auction_bids() + .iter() + .map(|(_account, (amount, _price, _multiplier))| amount) + .sum(); + let community_bought_tokens: u128 = default_community_buys() + .iter() + .map(|(_account, (amount, _multiplier))| amount) + .sum(); + let remainder_bought_tokens: u128 = default_remainder_buys() + .iter() + .map(|(_account, (amount, _multiplier))| amount) + .sum(); assert_eq!( project.remaining_contribution_tokens, default_project(0).total_allocation_size - @@ -893,7 +1027,11 @@ mod creation_round_success { let test_env = TestEnvironment::new(); test_env.fund_accounts(default_fundings()); test_env.ext_env.borrow_mut().execute_with(|| { - assert_ok!(Balances::transfer(RuntimeOrigin::signed(EVALUATOR_1), EVALUATOR_2, 1 * PLMC)); + assert_ok!(Balances::transfer( + RuntimeOrigin::signed(EVALUATOR_1), + EVALUATOR_2, + 1 * PLMC + )); }); } @@ -1023,11 +1161,19 @@ mod evaluation_round_success { let evaluating_project = EvaluatingProject::new_default(&test_env); evaluating_project.bond_for_users(default_evaluation_bonds()).unwrap(); let project_info = evaluating_project.get_project_info(); - test_env.advance_time(project_info.phase_transition_points.evaluation.end().unwrap() + 1u64); - let end_block = - evaluating_project.get_project_info().phase_transition_points.auction_initialize_period.end().unwrap(); + test_env + .advance_time(project_info.phase_transition_points.evaluation.end().unwrap() + 1u64); + let end_block = evaluating_project + .get_project_info() + .phase_transition_points + .auction_initialize_period + .end() + .unwrap(); test_env.advance_time(end_block - test_env.current_block() + 1); - assert_eq!(evaluating_project.get_project_info().project_status, ProjectStatus::AuctionRound(English)); + assert_eq!( + evaluating_project.get_project_info().project_status, + ProjectStatus::AuctionRound(English) + ); } } @@ -1041,16 +1187,20 @@ mod evaluation_round_failure { let evaluating_project = EvaluatingProject::new_default(&test_env); // Partially bond for evaluation - evaluating_project.bond_for_users(default_failing_evaluation_bonds()).expect("Bonding should work"); + evaluating_project + .bond_for_users(default_failing_evaluation_bonds()) + .expect("Bonding should work"); // Check that enough funds are reserved - test_env.do_reserved_funds_assertions(default_failing_evaluation_bonds(), BondType::Evaluation); + test_env + .do_reserved_funds_assertions(default_failing_evaluation_bonds(), BondType::Evaluation); // Check that free funds were reduced let mut free_funds = default_fundings(); // Remove accounts that didnt bond from free_funds - free_funds = remove_missing_accounts_from_fundings(free_funds, default_failing_evaluation_bonds()); + free_funds = + remove_missing_accounts_from_fundings(free_funds, default_failing_evaluation_bonds()); free_funds = free_funds .iter() .zip(default_failing_evaluation_bonds().iter()) @@ -1129,7 +1279,11 @@ mod auction_round_success { let mut bidding_account = 1000; let bid_info = default_auction_bids()[0].1; let necessary_funding = (bid_info.0 * bid_info.1) + - (bid_info.2.unwrap_or_default().calculate_bonding_requirement(bid_info.0 * bid_info.1).unwrap()); + (bid_info + .2 + .unwrap_or_default() + .calculate_bonding_requirement(bid_info.0 * bid_info.1) + .unwrap()); let mut bids_made: UserToBid = vec![]; let starting_bid_block = test_env.current_block(); assert_eq!(test_env.current_block(), starting_bid_block); @@ -1141,7 +1295,9 @@ mod auction_round_success { ); test_env.fund_accounts(vec![(bidding_account, necessary_funding)]); let bids: UserToBid = vec![(bidding_account, bid_info)]; - auctioning_project.bid_for_users(bids.clone()).expect("Candle Bidding should not fail"); + auctioning_project + .bid_for_users(bids.clone()) + .expect("Candle Bidding should not fail"); bids_made.push(bids[0]); bidding_account += 1; test_env.advance_time(1); @@ -1157,8 +1313,10 @@ mod auction_round_success { let split = (random_end - starting_bid_block + 1) as usize; let excluded_bids = bids_made.split_off(split); let included_bids = bids_made; - let _weighted_price = - auctioning_project.get_project_info().weighted_average_price.expect("Weighted price should exist"); + let _weighted_price = auctioning_project + .get_project_info() + .weighted_average_price + .expect("Weighted price should exist"); // let all_bids = test_env.ext_env.borrow_mut().execute_with(|| { // AuctionsInfo::::iter_prefix_values(auctioning_project.project_id) // .map(|bids| bids[0].clone()) @@ -1167,11 +1325,19 @@ mod auction_round_success { for (bidder, (_amount, _price, _multiplier)) in included_bids { test_env.ext_env.borrow_mut().execute_with(|| { let pid = auctioning_project.project_id; - let stored_bid = FundingModule::auctions_info(pid, bidder).expect("Bid should exist"); + let stored_bid = + FundingModule::auctions_info(pid, bidder).expect("Bid should exist"); assert!( matches!( stored_bid[0], - BidInfo { project: _pid, amount: _, price: _, ticket_size: _, bidder: _, .. } + BidInfo { + project: _pid, + amount: _, + price: _, + ticket_size: _, + bidder: _, + .. + } ), "Stored bid does not match the bid that was made" ); @@ -1182,11 +1348,19 @@ mod auction_round_success { for (bidder, (_amount, _price, _multiplier)) in excluded_bids { test_env.ext_env.borrow_mut().execute_with(|| { let pid = auctioning_project.project_id; - let stored_bid = FundingModule::auctions_info(pid, bidder).expect("Bid should exist"); + let stored_bid = + FundingModule::auctions_info(pid, bidder).expect("Bid should exist"); assert!( matches!( stored_bid[0], - BidInfo { project: _pid, amount: _, price: _, ticket_size: _, bidder: _, .. } + BidInfo { + project: _pid, + amount: _, + price: _, + ticket_size: _, + bidder: _, + .. + } ), "Stored bid does not match the bid that was made" ); @@ -1257,8 +1431,10 @@ mod auction_round_failure { (DAVE, (20_000, 8 * PLMC, None)), ]; - let mut fundings: UserToBalance = - bids.iter().map(|(user, (amount, price, _))| (*user, *amount * *price)).collect::>(); + let mut fundings: UserToBalance = bids + .iter() + .map(|(user, (amount, price, _))| (*user, *amount * *price)) + .collect::>(); // Existential deposit on DAVE fundings.push((DAVE, 100 * PLMC)); @@ -1334,12 +1510,16 @@ mod community_round_success { let community_funding_project = CommunityFundingProject::new_default(&test_env); const BOB: AccountId = 808; test_env.ext_env.borrow_mut().execute_with(|| { - let bob_balance = ::NativeCurrency::reserved_balance(&BOB); + let bob_balance = + ::NativeCurrency::reserved_balance(&BOB); let stop = "here"; }); - let remaining_ct = community_funding_project.get_project_info().remaining_contribution_tokens; - let ct_price = - community_funding_project.get_project_info().weighted_average_price.expect("CT Price should exist"); + let remaining_ct = + community_funding_project.get_project_info().remaining_contribution_tokens; + let ct_price = community_funding_project + .get_project_info() + .weighted_average_price + .expect("CT Price should exist"); // Necessary funds to buy remaining CTs, plus some extra for keeping it account alive let buyers: UserToBalance = vec![(BOB, remaining_ct * ct_price), (BOB, 50 * PLMC)]; @@ -1364,7 +1544,10 @@ mod community_round_success { assert_eq!(community_funding_project.get_project_info().remaining_contribution_tokens, 0); // Check project is in FundingEnded state - assert_eq!(community_funding_project.get_project_info().project_status, ProjectStatus::FundingEnded); + assert_eq!( + community_funding_project.get_project_info().project_status, + ProjectStatus::FundingEnded + ); test_env.do_free_funds_assertions(vec![(BOB, (50 * PLMC) * 2)]); } @@ -1375,9 +1558,12 @@ mod community_round_success { let community_funding_project = CommunityFundingProject::new_default(&test_env); const BOB: AccountId = 808; - let remaining_ct = community_funding_project.get_project_info().remaining_contribution_tokens + 40; // Overbuy - let ct_price = - community_funding_project.get_project_info().weighted_average_price.expect("CT Price should exist"); + let remaining_ct = + community_funding_project.get_project_info().remaining_contribution_tokens + 40; // Overbuy + let ct_price = community_funding_project + .get_project_info() + .weighted_average_price + .expect("CT Price should exist"); // Necessary funds to buy remaining CTs, plus some extra for keeping it account alive let buyers: UserToBalance = vec![(BOB, remaining_ct * ct_price), (BOB, 50 * PLMC)]; @@ -1395,7 +1581,10 @@ mod community_round_success { assert_eq!(community_funding_project.get_project_info().remaining_contribution_tokens, 0); // Check project is in FundingEnded state - assert_eq!(community_funding_project.get_project_info().project_status, ProjectStatus::FundingEnded); + assert_eq!( + community_funding_project.get_project_info().project_status, + ProjectStatus::FundingEnded + ); test_env.do_free_funds_assertions(vec![(BOB, (40 * ct_price) * 2 + (50 * PLMC) * 2)]); } @@ -1404,126 +1593,144 @@ mod community_round_success { fn contribution_is_returned_on_limit_reached_same_mult_diff_ct() { let test_env = TestEnvironment::new(); let project = CommunityFundingProject::new_default(&test_env); - let buyer_2_initial_balance = test_env - .ext_env - .borrow_mut() - .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); + let buyer_2_initial_balance = test_env.ext_env.borrow_mut().execute_with(|| { + ::NativeCurrency::free_balance(&BUYER_2) + }); let project_details = project.get_project_info(); // Create a contribution that will reach the limit of contributions for a user-project let multiplier: Option> = None; let token_amount: BalanceOf = 1; let range = 0..::MaxContributionsPerUser::get(); - let contributions: UserToContribution = range.map(|_| (BUYER_2, (token_amount, multiplier))).collect(); + let contributions: UserToContribution = + range.map(|_| (BUYER_2, (token_amount, multiplier))).collect(); // Calculate currencies being transferred and bonded - let contribution_ticket_size = token_amount * project_details.weighted_average_price.unwrap(); - let plmc_bond = multiplier.unwrap_or_default().calculate_bonding_requirement(contribution_ticket_size).unwrap(); + let contribution_ticket_size = + token_amount * project_details.weighted_average_price.unwrap(); + let plmc_bond = multiplier + .unwrap_or_default() + .calculate_bonding_requirement(contribution_ticket_size) + .unwrap(); // Reach the limit of contributions for a user-project project.buy_for_retail_users(contributions.clone()).unwrap(); // Check that the right amount of PLMC is bonded, and funding currency is transferred - let buyer_2_post_buy_balance = test_env - .ext_env - .borrow_mut() - .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); + let buyer_2_post_buy_balance = test_env.ext_env.borrow_mut().execute_with(|| { + ::NativeCurrency::free_balance(&BUYER_2) + }); assert_eq!( buyer_2_post_buy_balance, - buyer_2_initial_balance - (contribution_ticket_size + plmc_bond) * contributions.len() as u128 + buyer_2_initial_balance - + (contribution_ticket_size + plmc_bond) * contributions.len() as u128 ); - let plmc_bond_stored = test_env - .ext_env - .borrow_mut() - .execute_with(|| crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap()); + let plmc_bond_stored = test_env.ext_env.borrow_mut().execute_with(|| { + crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap() + }); assert_eq!(plmc_bond_stored.amount, plmc_bond * contributions.len() as u128); // Make a new contribution with a PLMC bond bigger than the lowest bond already in store for that account let new_multiplier: Option> = None; let new_token_amount: BalanceOf = 2; - let new_contribution: UserToContribution = vec![(BUYER_2, (new_token_amount, new_multiplier))]; + let new_contribution: UserToContribution = + vec![(BUYER_2, (new_token_amount, new_multiplier))]; let new_ticket_size = new_token_amount * project_details.weighted_average_price.unwrap(); - let new_plmc_bond = new_multiplier.unwrap_or_default().calculate_bonding_requirement(new_ticket_size).unwrap(); + let new_plmc_bond = new_multiplier + .unwrap_or_default() + .calculate_bonding_requirement(new_ticket_size) + .unwrap(); project.buy_for_retail_users(new_contribution.clone()).unwrap(); // Check that the previous contribution returned the reserved PLMC and the transferred funding currency - let buyer_2_post_return_balance = test_env - .ext_env - .borrow_mut() - .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); + let buyer_2_post_return_balance = test_env.ext_env.borrow_mut().execute_with(|| { + ::NativeCurrency::free_balance(&BUYER_2) + }); assert_eq!( buyer_2_post_return_balance, - buyer_2_post_buy_balance + (contribution_ticket_size + plmc_bond) - (new_ticket_size + new_plmc_bond) + buyer_2_post_buy_balance + (contribution_ticket_size + plmc_bond) - + (new_ticket_size + new_plmc_bond) + ); + let new_plmc_bond_stored = test_env.ext_env.borrow_mut().execute_with(|| { + crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap() + }); + assert_eq!( + new_plmc_bond_stored.amount, + plmc_bond_stored.amount - plmc_bond + new_plmc_bond ); - let new_plmc_bond_stored = test_env - .ext_env - .borrow_mut() - .execute_with(|| crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap()); - assert_eq!(new_plmc_bond_stored.amount, plmc_bond_stored.amount - plmc_bond + new_plmc_bond); } #[test] fn contribution_is_returned_on_limit_reached_diff_mult_same_ct() { let test_env = TestEnvironment::new(); let project = CommunityFundingProject::new_default(&test_env); - let buyer_2_initial_balance = test_env - .ext_env - .borrow_mut() - .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); + let buyer_2_initial_balance = test_env.ext_env.borrow_mut().execute_with(|| { + ::NativeCurrency::free_balance(&BUYER_2) + }); let project_details = project.get_project_info(); // Create a contribution that will reach the limit of contributions for a user-project let multiplier: Option> = Some(Multiplier(2)); let token_amount: BalanceOf = 1; let range = 0..::MaxContributionsPerUser::get(); - let contributions: UserToContribution = range.map(|_| (BUYER_2, (token_amount, multiplier))).collect(); + let contributions: UserToContribution = + range.map(|_| (BUYER_2, (token_amount, multiplier))).collect(); // Calculate currencies being transferred and bonded - let contribution_ticket_size = token_amount * project_details.weighted_average_price.unwrap(); - let plmc_bond = multiplier.unwrap_or_default().calculate_bonding_requirement(contribution_ticket_size).unwrap(); + let contribution_ticket_size = + token_amount * project_details.weighted_average_price.unwrap(); + let plmc_bond = multiplier + .unwrap_or_default() + .calculate_bonding_requirement(contribution_ticket_size) + .unwrap(); // Reach the limit of contributions for a user-project project.buy_for_retail_users(contributions.clone()).unwrap(); // Check that the right amount of PLMC is bonded, and funding currency is transferred - let buyer_2_post_buy_balance = test_env - .ext_env - .borrow_mut() - .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); + let buyer_2_post_buy_balance = test_env.ext_env.borrow_mut().execute_with(|| { + ::NativeCurrency::free_balance(&BUYER_2) + }); assert_eq!( buyer_2_post_buy_balance, - buyer_2_initial_balance - (contribution_ticket_size + plmc_bond) * contributions.len() as u128 + buyer_2_initial_balance - + (contribution_ticket_size + plmc_bond) * contributions.len() as u128 ); - let plmc_bond_stored = test_env - .ext_env - .borrow_mut() - .execute_with(|| crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap()); + let plmc_bond_stored = test_env.ext_env.borrow_mut().execute_with(|| { + crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap() + }); assert_eq!(plmc_bond_stored.amount, plmc_bond * contributions.len() as u128); // Make a new contribution with a PLMC bond bigger than the lowest bond already in store for that account let new_multiplier: Option> = Some(Multiplier(1)); let new_token_amount: BalanceOf = 1; - let new_contribution: UserToContribution = vec![(BUYER_2, (new_token_amount, new_multiplier))]; + let new_contribution: UserToContribution = + vec![(BUYER_2, (new_token_amount, new_multiplier))]; let new_ticket_size = new_token_amount * project_details.weighted_average_price.unwrap(); - let new_plmc_bond = new_multiplier.unwrap_or_default().calculate_bonding_requirement(new_ticket_size).unwrap(); + let new_plmc_bond = new_multiplier + .unwrap_or_default() + .calculate_bonding_requirement(new_ticket_size) + .unwrap(); project.buy_for_retail_users(new_contribution.clone()).unwrap(); // Check that the previous contribution returned the reserved PLMC and the transferred funding currency - let buyer_2_post_return_balance = test_env - .ext_env - .borrow_mut() - .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); + let buyer_2_post_return_balance = test_env.ext_env.borrow_mut().execute_with(|| { + ::NativeCurrency::free_balance(&BUYER_2) + }); assert_eq!( buyer_2_post_return_balance, - buyer_2_post_buy_balance + (contribution_ticket_size + plmc_bond) - (new_ticket_size + new_plmc_bond) + buyer_2_post_buy_balance + (contribution_ticket_size + plmc_bond) - + (new_ticket_size + new_plmc_bond) + ); + let new_plmc_bond_stored = test_env.ext_env.borrow_mut().execute_with(|| { + crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap() + }); + assert_eq!( + new_plmc_bond_stored.amount, + plmc_bond_stored.amount - plmc_bond + new_plmc_bond ); - let new_plmc_bond_stored = test_env - .ext_env - .borrow_mut() - .execute_with(|| crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap()); - assert_eq!(new_plmc_bond_stored.amount, plmc_bond_stored.amount - plmc_bond + new_plmc_bond); } } @@ -1543,8 +1750,10 @@ mod purchased_vesting { let test_env = TestEnvironment::new(); let finished_project = FinishedProject::new_default(&test_env); let project_id = finished_project.project_id; - let token_price = - finished_project.get_project_info().weighted_average_price.expect("CT price should exist at this point"); + let token_price = finished_project + .get_project_info() + .weighted_average_price + .expect("CT price should exist at this point"); let project = finished_project.get_project(); let decimals = project.token_information.decimals; @@ -1568,20 +1777,26 @@ mod purchased_vesting { let test_env = TestEnvironment::new(); let finished_project = FinishedProject::new_default(&test_env); let project_id = finished_project.project_id; - let price = - finished_project.get_project_info().weighted_average_price.expect("CT price should exist at this point"); + let price = finished_project + .get_project_info() + .weighted_average_price + .expect("CT price should exist at this point"); test_env.ext_env.borrow_mut().execute_with(|| { for (buyer, (token_amount, multiplier)) in default_community_buys() { - let theoretical_bonded_plmc = - multiplier.unwrap_or_default().calculate_bonding_requirement(token_amount * price).unwrap(); - let actual_bonded_plmc = Balances::reserved_balance_named(&BondType::Contributing, &buyer); + let theoretical_bonded_plmc = multiplier + .unwrap_or_default() + .calculate_bonding_requirement(token_amount * price) + .unwrap(); + let actual_bonded_plmc = + Balances::reserved_balance_named(&BondType::Contributing, &buyer); assert_eq!(theoretical_bonded_plmc, actual_bonded_plmc); assert_ok!(FundingModule::vested_plmc_purchase_unbond_for( RuntimeOrigin::signed(buyer), project_id, buyer )); - let actual_bonded_plmc = Balances::reserved_balance_named(&BondType::Contributing, &buyer); + let actual_bonded_plmc = + Balances::reserved_balance_named(&BondType::Contributing, &buyer); assert_eq!(actual_bonded_plmc, 0u32.into()); } }); @@ -1626,16 +1841,20 @@ mod bids_vesting { let _decimals = project.token_information.decimals; test_env.ext_env.borrow_mut().execute_with(|| { for (bidder, (amount, price, multiplier)) in bidders { - let theoretical_bonded_plmc = - multiplier.unwrap_or_default().calculate_bonding_requirement(amount * price).unwrap(); - let actual_bonded_plmc = Balances::reserved_balance_named(&BondType::Bidding, &bidder); + let theoretical_bonded_plmc = multiplier + .unwrap_or_default() + .calculate_bonding_requirement(amount * price) + .unwrap(); + let actual_bonded_plmc = + Balances::reserved_balance_named(&BondType::Bidding, &bidder); assert_eq!(theoretical_bonded_plmc, actual_bonded_plmc); assert_ok!(FundingModule::vested_plmc_bid_unbond_for( RuntimeOrigin::signed(bidder), project_id, bidder )); - let actual_bonded_plmc = Balances::reserved_balance_named(&BondType::Bidding, &bidder); + let actual_bonded_plmc = + Balances::reserved_balance_named(&BondType::Bidding, &bidder); assert_eq!(actual_bonded_plmc, 0u32.into()); } }); diff --git a/pallets/funding/src/types.rs b/pallets/funding/src/types.rs index ca82b4770..4c376e256 100644 --- a/pallets/funding/src/types.rs +++ b/pallets/funding/src/types.rs @@ -174,7 +174,6 @@ impl BlockNumberPair { pub fn new(start: Option, end: Option) -> Self { Self { start, end } } - pub fn start(&self) -> Option { self.start } @@ -199,7 +198,15 @@ impl BlockNumberPair { } #[derive(Default, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)] -pub struct BidInfo { +pub struct BidInfo< + BidId, + ProjectId, + Balance: BalanceT, + AccountId, + BlockNumber, + PlmcVesting, + CTVesting, +> { pub bid_id: BidId, pub project: ProjectId, #[codec(compact)] @@ -250,16 +257,32 @@ impl - sp_std::cmp::Ord for BidInfo +impl< + BidId: Eq, + ProjectId: Eq, + Balance: BalanceT, + AccountId: Eq, + BlockNumber: Eq, + PlmcVesting: Eq, + CTVesting: Eq, + > sp_std::cmp::Ord + for BidInfo { fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering { self.price.cmp(&other.price) } } -impl - sp_std::cmp::PartialOrd for BidInfo +impl< + BidId: Eq, + ProjectId: Eq, + Balance: BalanceT, + AccountId: Eq, + BlockNumber: Eq, + PlmcVesting: Eq, + CTVesting: Eq, + > sp_std::cmp::PartialOrd + for BidInfo { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) @@ -327,7 +350,19 @@ pub enum RejectionReason { } /// Enum used to identify PLMC named reserves -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen, Copy, Ord, PartialOrd)] +#[derive( + Clone, + Encode, + Decode, + Eq, + PartialEq, + RuntimeDebug, + TypeInfo, + MaxEncodedLen, + Copy, + Ord, + PartialOrd, +)] pub enum BondType { Evaluation, Bidding, @@ -393,7 +428,19 @@ impl< } /// Tells on_initialize what to do with the project -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen, Copy, Ord, PartialOrd)] +#[derive( + Clone, + Encode, + Decode, + Eq, + PartialEq, + RuntimeDebug, + TypeInfo, + MaxEncodedLen, + Copy, + Ord, + PartialOrd, +)] pub enum UpdateType { EvaluationEnd, EnglishAuctionStart, @@ -403,7 +450,19 @@ pub enum UpdateType { FundingEnd, } -#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen, Copy, Ord, PartialOrd)] +#[derive( + Clone, + Encode, + Decode, + Eq, + PartialEq, + RuntimeDebug, + TypeInfo, + MaxEncodedLen, + Copy, + Ord, + PartialOrd, +)] pub struct Multiplier(pub T::Balance); impl BondingRequirementCalculation for Multiplier { fn calculate_bonding_requirement(&self, ticket_size: BalanceOf) -> Result, ()> { diff --git a/pallets/parachain-staking/src/auto_compound.rs b/pallets/parachain-staking/src/auto_compound.rs index 214b212c0..830c4c077 100644 --- a/pallets/parachain-staking/src/auto_compound.rs +++ b/pallets/parachain-staking/src/auto_compound.rs @@ -18,8 +18,8 @@ use crate::{ pallet::{ - AddGet, AutoCompoundingDelegations as AutoCompoundingDelegationsStorage, BalanceOf, CandidateInfo, Config, - DelegatorState, Error, Event, Pallet, Total, + AddGet, AutoCompoundingDelegations as AutoCompoundingDelegationsStorage, BalanceOf, + CandidateInfo, Config, DelegatorState, Error, Event, Pallet, Total, }, types::{Bond, BondAdjust, Delegator}, }; @@ -82,7 +82,11 @@ where /// Sets the auto-compounding value for a delegation. The `delegations_config` must be a sorted /// vector for binary_search to work. - pub fn set_for_delegator(&mut self, delegator: T::AccountId, value: Percent) -> Result> { + pub fn set_for_delegator( + &mut self, + delegator: T::AccountId, + value: Percent, + ) -> Result> { match self.0.binary_search_by(|d| d.delegator.cmp(&delegator)) { Ok(index) => if self.0[index].value == value { @@ -181,7 +185,8 @@ where ensure!(!>::is_candidate(&delegator), Error::::CandidateExists); Delegator::new(delegator.clone(), candidate.clone(), amount) }; - let mut candidate_state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; + let mut candidate_state = + >::get(&candidate).ok_or(Error::::CandidateDNE)?; ensure!( candidate_delegation_count_hint >= candidate_state.delegation_count, Error::::TooLowCandidateDelegationCountToDelegate @@ -199,15 +204,16 @@ where }; // add delegation to candidate - let (delegator_position, less_total_staked) = - candidate_state.add_delegation::(&candidate, Bond { owner: delegator.clone(), amount })?; + let (delegator_position, less_total_staked) = candidate_state + .add_delegation::(&candidate, Bond { owner: delegator.clone(), amount })?; // lock delegator amount delegator_state.adjust_bond_lock::(BondAdjust::Increase(amount))?; // adjust total locked, // only is_some if kicked the lowest bottom as a consequence of this new delegation - let net_total_increase = if let Some(less) = less_total_staked { amount.saturating_sub(less) } else { amount }; + let net_total_increase = + if let Some(less) = less_total_staked { amount.saturating_sub(less) } else { amount }; let new_total_locked = >::get().saturating_add(net_total_increase); // maybe set auto-compound config, state is Some if the percent is non-zero @@ -238,12 +244,16 @@ where candidate_auto_compounding_delegation_count_hint: u32, delegation_count_hint: u32, ) -> DispatchResultWithPostInfo { - let delegator_state = >::get(&delegator).ok_or(>::DelegatorDNE)?; + let delegator_state = + >::get(&delegator).ok_or(>::DelegatorDNE)?; ensure!( delegator_state.delegations.0.len() <= delegation_count_hint as usize, >::TooLowDelegationCountToAutoCompound, ); - ensure!(delegator_state.delegations.0.iter().any(|b| b.owner == candidate), >::DelegationDNE,); + ensure!( + delegator_state.delegations.0.iter().any(|b| b.owner == candidate), + >::DelegationDNE, + ); let mut auto_compounding_state = Self::get_storage(&candidate); ensure!( @@ -287,8 +297,14 @@ mod tests { #[test] fn test_set_for_delegator_inserts_config_and_returns_true_if_entry_missing() { - let mut delegations_config = AutoCompoundDelegations::::new(vec![].try_into().expect("must succeed")); - assert_eq!(true, delegations_config.set_for_delegator(1, Percent::from_percent(50)).expect("must succeed")); + let mut delegations_config = + AutoCompoundDelegations::::new(vec![].try_into().expect("must succeed")); + assert_eq!( + true, + delegations_config + .set_for_delegator(1, Percent::from_percent(50)) + .expect("must succeed") + ); assert_eq!( vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(50) }], delegations_config.into_inner().into_inner(), @@ -302,7 +318,12 @@ mod tests { .try_into() .expect("must succeed"), ); - assert_eq!(true, delegations_config.set_for_delegator(1, Percent::from_percent(50)).expect("must succeed")); + assert_eq!( + true, + delegations_config + .set_for_delegator(1, Percent::from_percent(50)) + .expect("must succeed") + ); assert_eq!( vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(50) }], delegations_config.into_inner().into_inner(), @@ -316,7 +337,12 @@ mod tests { .try_into() .expect("must succeed"), ); - assert_eq!(false, delegations_config.set_for_delegator(1, Percent::from_percent(10)).expect("must succeed")); + assert_eq!( + false, + delegations_config + .set_for_delegator(1, Percent::from_percent(10)) + .expect("must succeed") + ); assert_eq!( vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(10) }], delegations_config.into_inner().into_inner(), @@ -325,7 +351,8 @@ mod tests { #[test] fn test_remove_for_delegator_returns_false_if_entry_was_missing() { - let mut delegations_config = AutoCompoundDelegations::::new(vec![].try_into().expect("must succeed")); + let mut delegations_config = + AutoCompoundDelegations::::new(vec![].try_into().expect("must succeed")); assert_eq!(false, delegations_config.remove_for_delegator(&1),); } diff --git a/pallets/parachain-staking/src/benchmarks.rs b/pallets/parachain-staking/src/benchmarks.rs index 9380f521c..0f8ba8ad6 100644 --- a/pallets/parachain-staking/src/benchmarks.rs +++ b/pallets/parachain-staking/src/benchmarks.rs @@ -18,8 +18,9 @@ //! Benchmarking use crate::{ - AwardedPts, BalanceOf, Call, CandidateBondLessRequest, Config, DelegationAction, Pallet, ParachainBondConfig, - ParachainBondInfo, Points, Range, RewardPayment, Round, ScheduledRequest, Staked, TopDelegations, + AwardedPts, BalanceOf, Call, CandidateBondLessRequest, Config, DelegationAction, Pallet, + ParachainBondConfig, ParachainBondInfo, Points, Range, RewardPayment, Round, ScheduledRequest, + Staked, TopDelegations, }; use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, vec}; use frame_support::traits::{Currency, Get, OnFinalize, OnInitialize}; @@ -40,7 +41,11 @@ fn min_delegator_stk() -> BalanceOf { /// Create a funded user. /// Extra + min_candidate_stk is total minted funds /// Returns tuple (id, balance) -fn create_funded_user(string: &'static str, n: u32, extra: BalanceOf) -> (T::AccountId, BalanceOf) { +fn create_funded_user( + string: &'static str, + n: u32, + extra: BalanceOf, +) -> (T::AccountId, BalanceOf) { const SEED: u32 = 0; let user = account(string, n, SEED); let min_candidate_stk = min_candidate_stk::(); @@ -102,7 +107,9 @@ fn roll_to_and_author(round_delay: u32, author: T::AccountId) { while now < end { parachain_staking_on_finalize::(author.clone()); >::on_finalize(>::block_number()); - >::set_block_number(>::block_number() + 1u32.into()); + >::set_block_number( + >::block_number() + 1u32.into(), + ); >::on_initialize(>::block_number()); Pallet::::on_initialize(>::block_number()); now += 1u32.into(); diff --git a/pallets/parachain-staking/src/delegation_requests.rs b/pallets/parachain-staking/src/delegation_requests.rs index 8f5bec1ac..c1beb3d80 100644 --- a/pallets/parachain-staking/src/delegation_requests.rs +++ b/pallets/parachain-staking/src/delegation_requests.rs @@ -19,8 +19,8 @@ use crate::{ auto_compound::AutoCompoundDelegations, pallet::{ - BalanceOf, CandidateInfo, Config, DelegationScheduledRequests, DelegatorState, Error, Event, Pallet, Round, - RoundIndex, Total, + BalanceOf, CandidateInfo, Config, DelegationScheduledRequests, DelegatorState, Error, + Event, Pallet, Round, RoundIndex, Total, }, Delegator, DelegatorStatus, }; @@ -65,7 +65,10 @@ pub struct CancelledScheduledRequest { impl From> for CancelledScheduledRequest { fn from(request: ScheduledRequest) -> Self { - CancelledScheduledRequest { when_executable: request.when_executable, action: request.action } + CancelledScheduledRequest { + when_executable: request.when_executable, + action: request.action, + } } } @@ -157,8 +160,9 @@ impl Pallet { let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; let mut scheduled_requests = >::get(&collator); - let request = Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests) - .ok_or(>::PendingDelegationRequestDNE)?; + let request = + Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests) + .ok_or(>::PendingDelegationRequestDNE)?; >::insert(collator.clone(), scheduled_requests); >::insert(delegator.clone(), state); @@ -234,7 +238,10 @@ impl Pallet { >::insert(collator, scheduled_requests); if leaving { >::remove(&delegator); - Self::deposit_event(Event::DelegatorLeft { delegator, unstaked_amount: amount }); + Self::deposit_event(Event::DelegatorLeft { + delegator, + unstaked_amount: amount, + }); } else { >::insert(&delegator, state); } @@ -251,13 +258,19 @@ impl Pallet { return if bond.amount > amount { let amount_before: BalanceOf = bond.amount; bond.amount = bond.amount.saturating_sub(amount); - let mut collator_info = - >::get(&collator).ok_or(>::CandidateDNE)?; + let mut collator_info = >::get(&collator) + .ok_or(>::CandidateDNE)?; state.total_sub_if::(amount, |total| { let new_total: BalanceOf = total; - ensure!(new_total >= T::MinDelegation::get(), >::DelegationBelowMin); - ensure!(new_total >= T::MinDelegatorStk::get(), >::DelegatorBondBelowMin); + ensure!( + new_total >= T::MinDelegation::get(), + >::DelegationBelowMin + ); + ensure!( + new_total >= T::MinDelegatorStk::get(), + >::DelegatorBondBelowMin + ); Ok(()) })?; @@ -273,7 +286,10 @@ impl Pallet { let new_total_staked = >::get().saturating_sub(amount); >::put(new_total_staked); - >::insert(collator.clone(), scheduled_requests); + >::insert( + collator.clone(), + scheduled_requests, + ); >::insert(delegator.clone(), state); Self::deposit_event(Event::DelegationDecreased { delegator, @@ -295,7 +311,9 @@ impl Pallet { /// Schedules [DelegationAction::Revoke] for the delegator, towards all delegated collator. /// The last fulfilled request causes the delegator to leave the set of delegators. - pub(crate) fn delegator_schedule_revoke_all(delegator: T::AccountId) -> DispatchResultWithPostInfo { + pub(crate) fn delegator_schedule_revoke_all( + delegator: T::AccountId, + ) -> DispatchResultWithPostInfo { let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; let mut updated_scheduled_requests = vec![]; let now = >::get().current; @@ -317,7 +335,8 @@ impl Pallet { let mut scheduled_requests = >::get(&collator); // cancel any existing requests - let request = Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests); + let request = + Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests); let request = match request { Some(revoke_req) if matches!(revoke_req.action, DelegationAction::Revoke(_)) => { existing_revoke_count += 1; @@ -339,19 +358,27 @@ impl Pallet { return Err(>::DelegatorAlreadyLeaving.into()) } - updated_scheduled_requests.into_iter().for_each(|(collator, scheduled_requests)| { - >::insert(collator, scheduled_requests); - }); + updated_scheduled_requests + .into_iter() + .for_each(|(collator, scheduled_requests)| { + >::insert(collator, scheduled_requests); + }); >::insert(delegator.clone(), state); - Self::deposit_event(Event::DelegatorExitScheduled { round: now, delegator, scheduled_exit: when }); + Self::deposit_event(Event::DelegatorExitScheduled { + round: now, + delegator, + scheduled_exit: when, + }); Ok(().into()) } /// Cancels every [DelegationAction::Revoke] request for a delegator towards a collator. /// Each delegation must have a [DelegationAction::Revoke] scheduled that must be allowed to be /// executed in the current round, for this function to succeed. - pub(crate) fn delegator_cancel_scheduled_revoke_all(delegator: T::AccountId) -> DispatchResultWithPostInfo { + pub(crate) fn delegator_cancel_scheduled_revoke_all( + delegator: T::AccountId, + ) -> DispatchResultWithPostInfo { let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; let mut updated_scheduled_requests = vec![]; @@ -370,7 +397,9 @@ impl Pallet { let scheduled_requests = >::get(&collator); scheduled_requests .iter() - .find(|req| req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_))) + .find(|req| { + req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) + }) .ok_or(>::DelegatorNotLeaving)?; } @@ -382,9 +411,11 @@ impl Pallet { updated_scheduled_requests.push((collator, scheduled_requests)); } - updated_scheduled_requests.into_iter().for_each(|(collator, scheduled_requests)| { - >::insert(collator, scheduled_requests); - }); + updated_scheduled_requests + .into_iter() + .for_each(|(collator, scheduled_requests)| { + >::insert(collator, scheduled_requests); + }); >::insert(delegator.clone(), state); Self::deposit_event(Event::DelegatorExitCancelled { delegator }); @@ -412,9 +443,15 @@ impl Pallet { ensure!(>::get().current >= when, Error::::DelegatorCannotLeaveYet); for bond in state.delegations.0.clone() { - if let Err(error) = Self::delegator_leaves_candidate(bond.owner.clone(), delegator.clone(), bond.amount) - { - log::warn!("STORAGE CORRUPTED \nDelegator leaving collator failed with error: {:?}", error); + if let Err(error) = Self::delegator_leaves_candidate( + bond.owner.clone(), + delegator.clone(), + bond.amount, + ) { + log::warn!( + "STORAGE CORRUPTED \nDelegator leaving collator failed with error: {:?}", + error + ); } Self::delegation_remove_request_with_state(&bond.owner, &delegator, &mut state); @@ -431,7 +468,9 @@ impl Pallet { let scheduled_requests = >::get(&bond.owner); let request_idx = scheduled_requests .iter() - .position(|req| req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_))) + .position(|req| { + req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) + }) .ok_or(>::DelegatorNotLeaving)?; let request = &scheduled_requests[request_idx]; @@ -445,7 +484,9 @@ impl Pallet { for (bond, mut scheduled_requests, request_idx) in validated_scheduled_requests { let collator = bond.owner; - if let Err(error) = Self::delegator_leaves_candidate(collator.clone(), delegator.clone(), bond.amount) { + if let Err(error) = + Self::delegator_leaves_candidate(collator.clone(), delegator.clone(), bond.amount) + { log::warn!( "STORAGE CORRUPTED \nDelegator {:?} leaving collator failed with error: {:?}", delegator, @@ -465,9 +506,11 @@ impl Pallet { let unstaked_amount = state.total(); state.total_sub::(unstaked_amount)?; - updated_scheduled_requests.into_iter().for_each(|(collator, scheduled_requests)| { - >::insert(collator, scheduled_requests); - }); + updated_scheduled_requests + .into_iter() + .for_each(|(collator, scheduled_requests)| { + >::insert(collator, scheduled_requests); + }); Self::deposit_event(Event::DelegatorLeft { delegator: delegator.clone(), unstaked_amount }); >::remove(&delegator); @@ -484,7 +527,8 @@ impl Pallet { ) { let mut scheduled_requests = >::get(collator); - let maybe_request_idx = scheduled_requests.iter().position(|req| &req.delegator == delegator); + let maybe_request_idx = + scheduled_requests.iter().position(|req| &req.delegator == delegator); if let Some(request_idx) = maybe_request_idx { let request = scheduled_requests.remove(request_idx); @@ -496,14 +540,19 @@ impl Pallet { /// Returns true if a [ScheduledRequest] exists for a given delegation pub fn delegation_request_exists(collator: &T::AccountId, delegator: &T::AccountId) -> bool { - >::get(collator).iter().any(|req| &req.delegator == delegator) + >::get(collator) + .iter() + .any(|req| &req.delegator == delegator) } /// Returns true if a [DelegationAction::Revoke] [ScheduledRequest] exists for a given delegation - pub fn delegation_request_revoke_exists(collator: &T::AccountId, delegator: &T::AccountId) -> bool { - >::get(collator) - .iter() - .any(|req| &req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_))) + pub fn delegation_request_revoke_exists( + collator: &T::AccountId, + delegator: &T::AccountId, + ) -> bool { + >::get(collator).iter().any(|req| { + &req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) + }) } } @@ -522,18 +571,35 @@ mod tests { status: crate::DelegatorStatus::Active, }; let mut scheduled_requests = vec![ - ScheduledRequest { delegator: 1, when_executable: 1, action: DelegationAction::Revoke(100) }, - ScheduledRequest { delegator: 2, when_executable: 1, action: DelegationAction::Decrease(50) }, + ScheduledRequest { + delegator: 1, + when_executable: 1, + action: DelegationAction::Revoke(100), + }, + ScheduledRequest { + delegator: 2, + when_executable: 1, + action: DelegationAction::Decrease(50), + }, ]; - let removed_request = >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); + let removed_request = + >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); assert_eq!( removed_request, - Some(ScheduledRequest { delegator: 1, when_executable: 1, action: DelegationAction::Revoke(100) }) + Some(ScheduledRequest { + delegator: 1, + when_executable: 1, + action: DelegationAction::Revoke(100), + }) ); assert_eq!( scheduled_requests, - vec![ScheduledRequest { delegator: 2, when_executable: 1, action: DelegationAction::Decrease(50) },] + vec![ScheduledRequest { + delegator: 2, + when_executable: 1, + action: DelegationAction::Decrease(50), + },] ); assert_eq!( state, @@ -556,14 +622,22 @@ mod tests { less_total: 100, status: crate::DelegatorStatus::Active, }; - let mut scheduled_requests = - vec![ScheduledRequest { delegator: 2, when_executable: 1, action: DelegationAction::Decrease(50) }]; - let removed_request = >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); + let mut scheduled_requests = vec![ScheduledRequest { + delegator: 2, + when_executable: 1, + action: DelegationAction::Decrease(50), + }]; + let removed_request = + >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); assert_eq!(removed_request, None,); assert_eq!( scheduled_requests, - vec![ScheduledRequest { delegator: 2, when_executable: 1, action: DelegationAction::Decrease(50) },] + vec![ScheduledRequest { + delegator: 2, + when_executable: 1, + action: DelegationAction::Decrease(50), + },] ); assert_eq!( state, diff --git a/pallets/parachain-staking/src/inflation.rs b/pallets/parachain-staking/src/inflation.rs index b2b6aacd2..e6c6778d7 100644 --- a/pallets/parachain-staking/src/inflation.rs +++ b/pallets/parachain-staking/src/inflation.rs @@ -34,7 +34,9 @@ fn rounds_per_year() -> u32 { } #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[derive(Eq, PartialEq, Clone, Copy, Encode, Decode, Default, RuntimeDebug, MaxEncodedLen, TypeInfo)] +#[derive( + Eq, PartialEq, Clone, Copy, Encode, Decode, Default, RuntimeDebug, MaxEncodedLen, TypeInfo, +)] pub struct Range { pub min: T, pub ideal: T, @@ -54,15 +56,26 @@ impl From for Range { } /// Convert an annual inflation to a round inflation /// round = (1+annual)^(1/rounds_per_year) - 1 -pub fn perbill_annual_to_perbill_round(annual: Range, rounds_per_year: u32) -> Range { +pub fn perbill_annual_to_perbill_round( + annual: Range, + rounds_per_year: u32, +) -> Range { let exponent = I64F64::from_num(1) / I64F64::from_num(rounds_per_year); let annual_to_round = |annual: Perbill| -> Perbill { let x = I64F64::from_num(annual.deconstruct()) / I64F64::from_num(Perbill::ACCURACY); let y: I64F64 = floatpow(I64F64::from_num(1) + x, exponent) .expect("Cannot overflow since rounds_per_year is u32 so worst case 0; QED"); - Perbill::from_parts(((y - I64F64::from_num(1)) * I64F64::from_num(Perbill::ACCURACY)).ceil().to_num::()) + Perbill::from_parts( + ((y - I64F64::from_num(1)) * I64F64::from_num(Perbill::ACCURACY)) + .ceil() + .to_num::(), + ) }; - Range { min: annual_to_round(annual.min), ideal: annual_to_round(annual.ideal), max: annual_to_round(annual.max) } + Range { + min: annual_to_round(annual.min), + ideal: annual_to_round(annual.ideal), + max: annual_to_round(annual.max), + } } /// Convert annual inflation rate range to round inflation range pub fn annual_to_round(annual: Range) -> Range { @@ -73,7 +86,11 @@ pub fn annual_to_round(annual: Range) -> Range { /// Compute round issuance range from round inflation range and current total issuance pub fn round_issuance_range(round: Range) -> Range> { let circulating = T::Currency::total_issuance(); - Range { min: round.min * circulating, ideal: round.ideal * circulating, max: round.max * circulating } + Range { + min: round.min * circulating, + ideal: round.ideal * circulating, + max: round.max * circulating, + } } #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] @@ -88,21 +105,21 @@ pub struct InflationInfo { } impl InflationInfo { - pub fn new(annual: Range, expect: Range) -> InflationInfo { + pub fn new( + annual: Range, + expect: Range, + ) -> InflationInfo { InflationInfo { expect, annual, round: annual_to_round::(annual) } } - /// Set round inflation range according to input annual inflation range pub fn set_round_from_annual(&mut self, new: Range) { self.round = annual_to_round::(new); } - /// Reset round inflation rate based on changes to round length pub fn reset_round(&mut self, new_length: u32) { let periods = BLOCKS_PER_YEAR / new_length; self.round = perbill_annual_to_perbill_round(self.annual, periods); } - /// Set staking expectations pub fn set_expectations(&mut self, expect: Range) { self.expect = expect; @@ -121,16 +138,24 @@ mod tests { // Round inflation range round: Range, ) -> Range { - Range { min: round.min * circulating, ideal: round.ideal * circulating, max: round.max * circulating } + Range { + min: round.min * circulating, + ideal: round.ideal * circulating, + max: round.max * circulating, + } } #[test] fn simple_issuance_conversion() { // 5% inflation for 10_000_0000 = 500,000 minted over the year // let's assume there are 10 periods in a year // => mint 500_000 over 10 periods => 50_000 minted per period - let expected_round_issuance_range: Range = Range { min: 48_909, ideal: 48_909, max: 48_909 }; - let schedule = - Range { min: Perbill::from_percent(5), ideal: Perbill::from_percent(5), max: Perbill::from_percent(5) }; + let expected_round_issuance_range: Range = + Range { min: 48_909, ideal: 48_909, max: 48_909 }; + let schedule = Range { + min: Perbill::from_percent(5), + ideal: Perbill::from_percent(5), + max: Perbill::from_percent(5), + }; assert_eq!( expected_round_issuance_range, mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 10)) @@ -141,9 +166,13 @@ mod tests { // 3-5% inflation for 10_000_0000 = 300_000-500,000 minted over the year // let's assume there are 10 periods in a year // => mint 300_000-500_000 over 10 periods => 30_000-50_000 minted per period - let expected_round_issuance_range: Range = Range { min: 29_603, ideal: 39298, max: 48_909 }; - let schedule = - Range { min: Perbill::from_percent(3), ideal: Perbill::from_percent(4), max: Perbill::from_percent(5) }; + let expected_round_issuance_range: Range = + Range { min: 29_603, ideal: 39298, max: 48_909 }; + let schedule = Range { + min: Perbill::from_percent(3), + ideal: Perbill::from_percent(4), + max: Perbill::from_percent(5), + }; assert_eq!( expected_round_issuance_range, mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 10)) @@ -152,8 +181,11 @@ mod tests { #[test] fn expected_parameterization() { let expected_round_schedule: Range = Range { min: 45, ideal: 56, max: 56 }; - let schedule = - Range { min: Perbill::from_percent(4), ideal: Perbill::from_percent(5), max: Perbill::from_percent(5) }; + let schedule = Range { + min: Perbill::from_percent(4), + ideal: Perbill::from_percent(5), + max: Perbill::from_percent(5), + }; assert_eq!( expected_round_schedule, mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 8766)) diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs index b787a8577..0ed5d4e24 100644 --- a/pallets/parachain-staking/src/lib.rs +++ b/pallets/parachain-staking/src/lib.rs @@ -87,8 +87,8 @@ pub mod pallet { use frame_support::{ pallet_prelude::*, traits::{ - tokens::WithdrawReasons, Currency, EstimateNextSessionRotation, Get, Imbalance, LockIdentifier, - LockableCurrency, ReservableCurrency, + tokens::WithdrawReasons, Currency, EstimateNextSessionRotation, Get, Imbalance, + LockIdentifier, LockableCurrency, ReservableCurrency, }, }; use frame_system::pallet_prelude::*; @@ -106,7 +106,8 @@ pub mod pallet { pub type RoundIndex = u32; type RewardPoint = u32; - pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; + pub type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; pub type AccountIdOf = ::AccountId; @@ -271,13 +272,9 @@ pub mod pallet { new_bond: BalanceOf, }, /// Candidate temporarily leave the set of collator candidates without unbonding. - CandidateWentOffline { - candidate: T::AccountId, - }, + CandidateWentOffline { candidate: T::AccountId }, /// Candidate rejoins the set of collator candidates. - CandidateBackOnline { - candidate: T::AccountId, - }, + CandidateBackOnline { candidate: T::AccountId }, /// Candidate has requested to leave the set of candidates. CandidateScheduledExit { exit_allowed_round: RoundIndex, @@ -285,9 +282,7 @@ pub mod pallet { scheduled_exit: RoundIndex, }, /// Cancelled request to leave the set of candidates. - CancelledCandidateExit { - candidate: T::AccountId, - }, + CancelledCandidateExit { candidate: T::AccountId }, /// Cancelled request to decrease candidate's bond. CancelledCandidateBondLess { candidate: T::AccountId, @@ -335,10 +330,7 @@ pub mod pallet { scheduled_exit: RoundIndex, }, /// Delegator has left the set of delegators. - DelegatorLeft { - delegator: T::AccountId, - unstaked_amount: BalanceOf, - }, + DelegatorLeft { delegator: T::AccountId, unstaked_amount: BalanceOf }, /// Delegation revoked. DelegationRevoked { delegator: T::AccountId, @@ -352,9 +344,7 @@ pub mod pallet { unstaked_amount: BalanceOf, }, /// Cancelled a pending request to exit the set of delegators. - DelegatorExitCancelled { - delegator: T::AccountId, - }, + DelegatorExitCancelled { delegator: T::AccountId }, /// Cancelled request to change an existing delegation. CancelledDelegationRequest { delegator: T::AccountId, @@ -377,25 +367,13 @@ pub mod pallet { total_candidate_staked: BalanceOf, }, /// Paid the account (delegator or collator) the balance as liquid rewards. - Rewarded { - account: T::AccountId, - rewards: BalanceOf, - }, + Rewarded { account: T::AccountId, rewards: BalanceOf }, /// Transferred to account which holds funds reserved for parachain bond. - ReservedForParachainBond { - account: T::AccountId, - value: BalanceOf, - }, + ReservedForParachainBond { account: T::AccountId, value: BalanceOf }, /// Account (re)set for parachain bond treasury. - ParachainBondAccountSet { - old: T::AccountId, - new: T::AccountId, - }, + ParachainBondAccountSet { old: T::AccountId, new: T::AccountId }, /// Percent of inflation reserved for parachain bond (re)set. - ParachainBondReservePercentSet { - old: Percent, - new: Percent, - }, + ParachainBondReservePercentSet { old: Percent, new: Percent }, /// Annual inflation input (first 3) was used to derive new per-round inflation (last 3) InflationSet { annual_min: Perbill, @@ -412,15 +390,9 @@ pub mod pallet { expect_max: BalanceOf, }, /// Set total selected candidates to this value. - TotalSelectedSet { - old: u32, - new: u32, - }, + TotalSelectedSet { old: u32, new: u32 }, /// Set collator commission to this value. - CollatorCommissionSet { - old: Perbill, - new: Perbill, - }, + CollatorCommissionSet { old: Perbill, new: Perbill }, /// Set blocks per round BlocksPerRoundSet { current_round: RoundIndex, @@ -432,17 +404,9 @@ pub mod pallet { new_per_round_inflation_max: Perbill, }, /// Auto-compounding reward percent was set for a delegation. - AutoCompoundSet { - candidate: T::AccountId, - delegator: T::AccountId, - value: Percent, - }, + AutoCompoundSet { candidate: T::AccountId, delegator: T::AccountId, value: Percent }, /// Compounded a portion of rewards towards the delegation. - Compounded { - candidate: T::AccountId, - delegator: T::AccountId, - amount: BalanceOf, - }, + Compounded { candidate: T::AccountId, delegator: T::AccountId, amount: BalanceOf }, } #[pallet::hooks] @@ -500,7 +464,8 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn parachain_bond_info)] /// Parachain bond config info { account, percent_of_inflation } - pub(crate) type ParachainBondInfo = StorageValue<_, ParachainBondConfig, ValueQuery>; + pub(crate) type ParachainBondInfo = + StorageValue<_, ParachainBondConfig, ValueQuery>; #[pallet::storage] #[pallet::getter(fn round)] @@ -510,8 +475,13 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn delegator_state)] /// Get delegator state associated with an account if account is delegating else None - pub(crate) type DelegatorState = - StorageMap<_, Twox64Concat, T::AccountId, Delegator>, OptionQuery>; + pub(crate) type DelegatorState = StorageMap< + _, + Twox64Concat, + T::AccountId, + Delegator>, + OptionQuery, + >; #[pallet::storage] #[pallet::getter(fn candidate_info)] @@ -522,8 +492,13 @@ pub mod pallet { /// Stores outstanding delegation requests per collator. #[pallet::storage] #[pallet::getter(fn delegation_scheduled_requests)] - pub(crate) type DelegationScheduledRequests = - StorageMap<_, Blake2_128Concat, T::AccountId, Vec>>, ValueQuery>; + pub(crate) type DelegationScheduledRequests = StorageMap< + _, + Blake2_128Concat, + T::AccountId, + Vec>>, + ValueQuery, + >; pub struct AddGet { _phantom: PhantomData<(T, R)>, @@ -555,14 +530,24 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn top_delegations)] /// Top delegations for collator candidate - pub(crate) type TopDelegations = - StorageMap<_, Twox64Concat, T::AccountId, Delegations>, OptionQuery>; + pub(crate) type TopDelegations = StorageMap< + _, + Twox64Concat, + T::AccountId, + Delegations>, + OptionQuery, + >; #[pallet::storage] #[pallet::getter(fn bottom_delegations)] /// Bottom delegations for collator candidate - pub(crate) type BottomDelegations = - StorageMap<_, Twox64Concat, T::AccountId, Delegations>, OptionQuery>; + pub(crate) type BottomDelegations = StorageMap< + _, + Twox64Concat, + T::AccountId, + Delegations>, + OptionQuery, + >; #[pallet::storage] #[pallet::getter(fn selected_candidates)] @@ -617,8 +602,15 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn awarded_pts)] /// Points for each collator per round - pub type AwardedPts = - StorageDoubleMap<_, Twox64Concat, RoundIndex, Twox64Concat, T::AccountId, RewardPoint, ValueQuery>; + pub type AwardedPts = StorageDoubleMap< + _, + Twox64Concat, + RoundIndex, + Twox64Concat, + T::AccountId, + RewardPoint, + ValueQuery, + >; #[pallet::genesis_config] pub struct GenesisConfig { @@ -678,7 +670,8 @@ pub mod pallet { } let mut col_delegator_count: BTreeMap = BTreeMap::new(); - let mut col_auto_compound_delegator_count: BTreeMap = BTreeMap::new(); + let mut col_auto_compound_delegator_count: BTreeMap = + BTreeMap::new(); let mut del_delegation_count: BTreeMap = BTreeMap::new(); // Initialize the delegations for &(ref delegator, ref target, balance, auto_compound) in &self.delegations { @@ -686,9 +679,12 @@ pub mod pallet { >::get_delegator_stakable_free_balance(delegator) >= balance, "Account does not have enough balance to place delegation." ); - let cd_count = if let Some(x) = col_delegator_count.get(target) { *x } else { 0u32 }; - let dd_count = if let Some(x) = del_delegation_count.get(delegator) { *x } else { 0u32 }; - let cd_auto_compound_count = col_auto_compound_delegator_count.get(target).cloned().unwrap_or_default(); + let cd_count = + if let Some(x) = col_delegator_count.get(target) { *x } else { 0u32 }; + let dd_count = + if let Some(x) = del_delegation_count.get(delegator) { *x } else { 0u32 }; + let cd_auto_compound_count = + col_auto_compound_delegator_count.get(target).cloned().unwrap_or_default(); if let Err(error) = >::delegate_with_auto_compound( T::RuntimeOrigin::from(Some(delegator.clone()).into()), target.clone(), @@ -737,7 +733,8 @@ pub mod pallet { // Choose top TotalSelected collator candidates let (_, v_count, _, total_staked) = >::select_top_candidates(1u32); // Start Round 1 at Block 0 - let round: RoundInfo = RoundInfo::new(1u32, 0u32.into(), self.blocks_per_round); + let round: RoundInfo = + RoundInfo::new(1u32, 0u32.into(), self.blocks_per_round); >::put(round); // Snapshot total stake >::insert(1u32, >::get()); @@ -777,7 +774,10 @@ pub mod pallet { /// Set the annual inflation rate to derive per-round inflation #[pallet::call_index(1)] #[pallet::weight(::WeightInfo::set_inflation())] - pub fn set_inflation(origin: OriginFor, schedule: Range) -> DispatchResultWithPostInfo { + pub fn set_inflation( + origin: OriginFor, + schedule: Range, + ) -> DispatchResultWithPostInfo { T::MonetaryGovernanceOrigin::ensure_origin(origin)?; ensure!(schedule.is_valid(), Error::::InvalidSchedule); let mut config = >::get(); @@ -799,7 +799,10 @@ pub mod pallet { /// Set the account that will hold funds set aside for parachain bond #[pallet::call_index(2)] #[pallet::weight(::WeightInfo::set_parachain_bond_account())] - pub fn set_parachain_bond_account(origin: OriginFor, new: T::AccountId) -> DispatchResultWithPostInfo { + pub fn set_parachain_bond_account( + origin: OriginFor, + new: T::AccountId, + ) -> DispatchResultWithPostInfo { T::MonetaryGovernanceOrigin::ensure_origin(origin)?; let ParachainBondConfig { account: old, percent } = >::get(); ensure!(old != new, Error::::NoWritingSameValue); @@ -811,7 +814,10 @@ pub mod pallet { /// Set the percent of inflation set aside for parachain bond #[pallet::call_index(3)] #[pallet::weight(::WeightInfo::set_parachain_bond_reserve_percent())] - pub fn set_parachain_bond_reserve_percent(origin: OriginFor, new: Percent) -> DispatchResultWithPostInfo { + pub fn set_parachain_bond_reserve_percent( + origin: OriginFor, + new: Percent, + ) -> DispatchResultWithPostInfo { T::MonetaryGovernanceOrigin::ensure_origin(origin)?; let ParachainBondConfig { account, percent: old } = >::get(); ensure!(old != new, Error::::NoWritingSameValue); @@ -829,7 +835,10 @@ pub mod pallet { ensure!(new >= T::MinSelectedCandidates::get(), Error::::CannotSetBelowMin); let old = >::get(); ensure!(old != new, Error::::NoWritingSameValue); - ensure!(new < >::get().length, Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators,); + ensure!( + new < >::get().length, + Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, + ); >::put(new); Self::deposit_event(Event::TotalSelectedSet { old, new }); Ok(().into()) @@ -838,7 +847,10 @@ pub mod pallet { /// Set the commission for all collators #[pallet::call_index(5)] #[pallet::weight(::WeightInfo::set_collator_commission())] - pub fn set_collator_commission(origin: OriginFor, new: Perbill) -> DispatchResultWithPostInfo { + pub fn set_collator_commission( + origin: OriginFor, + new: Perbill, + ) -> DispatchResultWithPostInfo { frame_system::ensure_root(origin)?; let old = >::get(); ensure!(old != new, Error::::NoWritingSameValue); @@ -859,7 +871,10 @@ pub mod pallet { let mut round = >::get(); let (now, first, old) = (round.current, round.first, round.length); ensure!(old != new, Error::::NoWritingSameValue); - ensure!(new > >::get(), Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators,); + ensure!( + new > >::get(), + Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, + ); round.length = new; // update per-round inflation given new rounds per year let mut inflation_config = >::get(); @@ -892,9 +907,18 @@ pub mod pallet { ensure!(bond >= T::MinCandidateStk::get(), Error::::CandidateBondBelowMin); let mut candidates = >::get(); let old_count = candidates.0.len() as u32; - ensure!(candidate_count >= old_count, Error::::TooLowCandidateCountWeightHintJoinCandidates); - ensure!(candidates.insert(Bond { owner: acc.clone(), amount: bond }), Error::::CandidateExists); - ensure!(Self::get_collator_stakable_free_balance(&acc) >= bond, Error::::InsufficientBalance,); + ensure!( + candidate_count >= old_count, + Error::::TooLowCandidateCountWeightHintJoinCandidates + ); + ensure!( + candidates.insert(Bond { owner: acc.clone(), amount: bond }), + Error::::CandidateExists + ); + ensure!( + Self::get_collator_stakable_free_balance(&acc) >= bond, + Error::::InsufficientBalance, + ); T::Currency::set_lock(COLLATOR_LOCK_ID, &acc, bond, WithdrawReasons::all()); let candidate = CandidateMetadata::new(bond); >::insert(&acc, candidate); @@ -918,12 +942,18 @@ pub mod pallet { /// removed from the candidate pool to prevent selection as a collator. #[pallet::call_index(8)] #[pallet::weight(::WeightInfo::schedule_leave_candidates(*candidate_count))] - pub fn schedule_leave_candidates(origin: OriginFor, candidate_count: u32) -> DispatchResultWithPostInfo { + pub fn schedule_leave_candidates( + origin: OriginFor, + candidate_count: u32, + ) -> DispatchResultWithPostInfo { let collator = ensure_signed(origin)?; let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; let (now, when) = state.schedule_leave::()?; let mut candidates = >::get(); - ensure!(candidate_count >= candidates.0.len() as u32, Error::::TooLowCandidateCountToLeaveCandidates); + ensure!( + candidate_count >= candidates.0.len() as u32, + Error::::TooLowCandidateCountToLeaveCandidates + ); if candidates.remove(&Bond::from_owner(collator.clone())) { >::put(candidates); } @@ -962,7 +992,11 @@ pub mod pallet { ); if let Some(remaining) = delegator.rm_delegation::(&candidate) { - Self::delegation_remove_request_with_state(&candidate, &bond.owner, &mut delegator); + Self::delegation_remove_request_with_state( + &candidate, + &bond.owner, + &mut delegator, + ); >::remove_auto_compound(&candidate, &bond.owner); if remaining.is_zero() { @@ -984,13 +1018,15 @@ pub mod pallet { // total backing stake is at least the candidate self bond let mut total_backing = state.bond; // return all top delegations - let top_delegations = >::take(&candidate).expect("CandidateInfo existence checked"); + let top_delegations = + >::take(&candidate).expect("CandidateInfo existence checked"); for bond in top_delegations.delegations { return_stake(bond)?; } total_backing = total_backing.saturating_add(top_delegations.total); // return all bottom delegations - let bottom_delegations = >::take(&candidate).expect("CandidateInfo existence checked"); + let bottom_delegations = + >::take(&candidate).expect("CandidateInfo existence checked"); for bond in bottom_delegations.delegations { return_stake(bond)?; } @@ -1017,7 +1053,10 @@ pub mod pallet { /// - result upon successful call is the candidate is active in the candidate pool #[pallet::call_index(10)] #[pallet::weight(::WeightInfo::cancel_leave_candidates(*candidate_count))] - pub fn cancel_leave_candidates(origin: OriginFor, candidate_count: u32) -> DispatchResultWithPostInfo { + pub fn cancel_leave_candidates( + origin: OriginFor, + candidate_count: u32, + ) -> DispatchResultWithPostInfo { let collator = ensure_signed(origin)?; let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; ensure!(state.is_leaving(), Error::::CandidateNotLeaving); @@ -1077,7 +1116,10 @@ pub mod pallet { /// Increase collator candidate self bond by `more` #[pallet::call_index(13)] #[pallet::weight(::WeightInfo::candidate_bond_more())] - pub fn candidate_bond_more(origin: OriginFor, more: BalanceOf) -> DispatchResultWithPostInfo { + pub fn candidate_bond_more( + origin: OriginFor, + more: BalanceOf, + ) -> DispatchResultWithPostInfo { let collator = ensure_signed(origin)?; let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; state.bond_more::(collator.clone(), more)?; @@ -1092,7 +1134,10 @@ pub mod pallet { /// Request by collator candidate to decrease self bond by `less` #[pallet::call_index(14)] #[pallet::weight(::WeightInfo::schedule_candidate_bond_less())] - pub fn schedule_candidate_bond_less(origin: OriginFor, less: BalanceOf) -> DispatchResultWithPostInfo { + pub fn schedule_candidate_bond_less( + origin: OriginFor, + less: BalanceOf, + ) -> DispatchResultWithPostInfo { let collator = ensure_signed(origin)?; let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; let when = state.schedule_bond_less::(less)?; @@ -1230,7 +1275,10 @@ pub mod pallet { /// A revoke may not be performed if any other scheduled request is pending. #[pallet::call_index(22)] #[pallet::weight(::WeightInfo::schedule_revoke_delegation())] - pub fn schedule_revoke_delegation(origin: OriginFor, collator: T::AccountId) -> DispatchResultWithPostInfo { + pub fn schedule_revoke_delegation( + origin: OriginFor, + collator: T::AccountId, + ) -> DispatchResultWithPostInfo { let delegator = ensure_signed(origin)?; Self::delegation_schedule_revoke(collator, delegator) } @@ -1244,8 +1292,17 @@ pub mod pallet { more: BalanceOf, ) -> DispatchResultWithPostInfo { let delegator = ensure_signed(origin)?; - let in_top = Self::delegation_bond_more_without_event(delegator.clone(), candidate.clone(), more)?; - Pallet::::deposit_event(Event::DelegationIncreased { delegator, candidate, amount: more, in_top }); + let in_top = Self::delegation_bond_more_without_event( + delegator.clone(), + candidate.clone(), + more, + )?; + Pallet::::deposit_event(Event::DelegationIncreased { + delegator, + candidate, + amount: more, + in_top, + }); Ok(().into()) } @@ -1279,7 +1336,10 @@ pub mod pallet { /// Cancel request to change an existing delegation. #[pallet::call_index(26)] #[pallet::weight(::WeightInfo::cancel_delegator_bond_less())] - pub fn cancel_delegation_request(origin: OriginFor, candidate: T::AccountId) -> DispatchResultWithPostInfo { + pub fn cancel_delegation_request( + origin: OriginFor, + candidate: T::AccountId, + ) -> DispatchResultWithPostInfo { let delegator = ensure_signed(origin)?; Self::delegation_cancel_request(candidate, delegator) } @@ -1319,8 +1379,14 @@ pub mod pallet { ensure_signed(origin)?; ensure!(candidates.len() < 100, >::InsufficientBalance); for candidate in &candidates { - ensure!(>::get(candidate).is_none(), >::CandidateNotLeaving); - ensure!(>::get(candidate).is_empty(), >::CandidateNotLeaving); + ensure!( + >::get(candidate).is_none(), + >::CandidateNotLeaving + ); + ensure!( + >::get(candidate).is_empty(), + >::CandidateNotLeaving + ); } for candidate in candidates { @@ -1346,15 +1412,12 @@ pub mod pallet { pub fn is_delegator(acc: &T::AccountId) -> bool { >::get(acc).is_some() } - pub fn is_candidate(acc: &T::AccountId) -> bool { >::get(acc).is_some() } - pub fn is_selected_candidate(acc: &T::AccountId) -> bool { >::get().binary_search(acc).is_ok() } - /// Returns an account's free balance which is not locked in delegation staking pub fn get_delegator_stakable_free_balance(acc: &T::AccountId) -> BalanceOf { let mut balance = T::Currency::free_balance(acc); @@ -1363,7 +1426,6 @@ pub mod pallet { } balance } - /// Returns an account's free balance which is not locked in collator staking pub fn get_collator_stakable_free_balance(acc: &T::AccountId) -> BalanceOf { let mut balance = T::Currency::free_balance(acc); @@ -1372,12 +1434,13 @@ pub mod pallet { } balance } - /// Returns a delegations auto-compound value. - pub fn delegation_auto_compound(candidate: &T::AccountId, delegator: &T::AccountId) -> Percent { + pub fn delegation_auto_compound( + candidate: &T::AccountId, + delegator: &T::AccountId, + ) -> Percent { >::auto_compound(candidate, delegator) } - /// Caller must ensure candidate is active before calling pub(crate) fn update_active(candidate: T::AccountId, total: BalanceOf) { let mut candidates = >::get(); @@ -1385,7 +1448,6 @@ pub mod pallet { candidates.insert(Bond { owner: candidate, amount: total }); >::put(candidates); } - /// Compute round issuance based on total staked for the given round fn compute_issuance(staked: BalanceOf) -> BalanceOf { let config = >::get(); @@ -1399,7 +1461,6 @@ pub mod pallet { round_issuance.ideal } } - /// Remove delegation from candidate state /// Amount input should be retrieved from delegator and it informs the storage lookups pub(crate) fn delegator_leaves_candidate( @@ -1421,7 +1482,6 @@ pub mod pallet { }); Ok(()) } - pub(crate) fn prepare_staking_payouts(now: RoundIndex) -> Weight { // payout is now - delay rounds ago => now - delay > 0 else return early let delay = T::RewardPaymentDelay::get(); @@ -1439,7 +1499,9 @@ pub mod pallet { // reserve portion of issuance for parachain bond account let bond_config = >::get(); let parachain_bond_reserve = bond_config.percent * total_issuance; - if let Ok(imb) = T::Currency::deposit_into_existing(&bond_config.account, parachain_bond_reserve) { + if let Ok(imb) = + T::Currency::deposit_into_existing(&bond_config.account, parachain_bond_reserve) + { // update round issuance iff transfer succeeds left_issuance = left_issuance.saturating_sub(imb.peek()); Self::deposit_event(Event::ReservedForParachainBond { @@ -1516,7 +1578,9 @@ pub mod pallet { let collator_fee = payout_info.collator_commission; let collator_issuance = collator_fee * payout_info.round_issuance; - if let Some((collator, state)) = >::iter_prefix(paid_for_round).drain().next() { + if let Some((collator, state)) = + >::iter_prefix(paid_for_round).drain().next() + { // read and kill AtStake early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); @@ -1544,7 +1608,11 @@ pub mod pallet { collator.clone(), amt_due, )) - .saturating_add(T::OnCollatorPayout::on_collator_payout(paid_for_round, collator, amt_due)); + .saturating_add(T::OnCollatorPayout::on_collator_payout( + paid_for_round, + collator, + amt_due, + )); log::warn!("💵 Solo collator reward: {:?}", amt_due); } else { // pay collator first; commission + due_portion @@ -1581,7 +1649,8 @@ pub mod pallet { ( RewardPayment::Paid, - T::WeightInfo::pay_one_collator_reward(num_delegators as u32).saturating_add(extra_weight), + T::WeightInfo::pay_one_collator_reward(num_delegators as u32) + .saturating_add(extra_weight), ) } else { // Note that we don't clean up storage here; it is cleaned up in @@ -1613,7 +1682,11 @@ pub mod pallet { a.amount.cmp(&b.amount).then_with(|| a.owner.cmp(&b.owner)).reverse() }); - let mut collators = candidates.into_iter().take(top_n).map(|x| x.owner).collect::>(); + let mut collators = candidates + .into_iter() + .take(top_n) + .map(|x| x.owner) + .collect::>(); // Sort collators by AccountId collators.sort(); @@ -1625,11 +1698,11 @@ pub mod pallet { candidates.into_iter().map(|x| x.owner).collect::>() } } - /// Best as in most cumulatively supported in terms of stake /// Returns [collator_count, delegation_count, total staked] pub(crate) fn select_top_candidates(now: RoundIndex) -> (Weight, u32, u32, BalanceOf) { - let (mut collator_count, mut delegation_count, mut total) = (0u32, 0u32, BalanceOf::::zero()); + let (mut collator_count, mut delegation_count, mut total) = + (0u32, 0u32, BalanceOf::::zero()); // choose the top TotalSelected qualified candidates, ordered by stake let collators = Self::compute_top_candidates(); if collators.is_empty() { @@ -1639,7 +1712,8 @@ pub mod pallet { // set this round AtStake to last round AtStake for (account, snapshot) in >::iter_prefix(last_round) { collator_count = collator_count.saturating_add(1u32); - delegation_count = delegation_count.saturating_add(snapshot.delegations.len() as u32); + delegation_count = + delegation_count.saturating_add(snapshot.delegations.len() as u32); total = total.saturating_add(snapshot.total); total_per_candidate.insert(account.clone(), snapshot.total); >::insert(now, account, snapshot); @@ -1647,8 +1721,9 @@ pub mod pallet { // `SelectedCandidates` remains unchanged from last round // emit CollatorChosen event for tools that use this event for candidate in >::get() { - let snapshot_total = - total_per_candidate.get(&candidate).expect("all selected candidates have snapshots"); + let snapshot_total = total_per_candidate + .get(&candidate) + .expect("all selected candidates have snapshots"); Self::deposit_event(Event::CollatorChosen { round: now, collator_account: candidate, @@ -1661,7 +1736,8 @@ pub mod pallet { // snapshot exposure for round for weighting reward distribution for account in collators.iter() { - let state = >::get(account).expect("all members of CandidateQ must be candidates"); + let state = >::get(account) + .expect("all members of CandidateQ must be candidates"); collator_count = collator_count.saturating_add(1u32); delegation_count = delegation_count.saturating_add(state.delegation_count); @@ -1686,8 +1762,11 @@ pub mod pallet { }) .collect(); - let snapshot = - CollatorSnapshot { bond: state.bond, delegations: rewardable_delegations, total: total_counted }; + let snapshot = CollatorSnapshot { + bond: state.bond, + delegations: rewardable_delegations, + total: total_counted, + }; >::insert(now, account, snapshot); Self::deposit_event(Event::CollatorChosen { round: now, @@ -1762,7 +1841,10 @@ pub mod pallet { /// Mint a specified reward amount to the beneficiary account. Emits the [Rewarded] event. pub fn mint(amt: BalanceOf, to: T::AccountId) { if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&to, amt) { - Self::deposit_event(Event::Rewarded { account: to.clone(), rewards: amount_transferred.peek() }); + Self::deposit_event(Event::Rewarded { + account: to.clone(), + rewards: amount_transferred.peek(), + }); } } @@ -1793,27 +1875,36 @@ pub mod pallet { ) -> Weight { let mut weight = T::WeightInfo::mint_collator_reward(); if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&delegator, amt) { - Self::deposit_event(Event::Rewarded { account: delegator.clone(), rewards: amount_transferred.peek() }); + Self::deposit_event(Event::Rewarded { + account: delegator.clone(), + rewards: amount_transferred.peek(), + }); let compound_amount = compound_percent.mul_ceil(amount_transferred.peek()); if compound_amount.is_zero() { return weight } - if let Err(err) = - Self::delegation_bond_more_without_event(delegator.clone(), candidate.clone(), compound_amount) - { + if let Err(err) = Self::delegation_bond_more_without_event( + delegator.clone(), + candidate.clone(), + compound_amount, + ) { log::warn!( - "skipped compounding staking reward towards candidate '{:?}' for delegator '{:?}': {:?}", - candidate, - delegator, - err - ); + "skipped compounding staking reward towards candidate '{:?}' for delegator '{:?}': {:?}", + candidate, + delegator, + err + ); return weight }; weight = weight.saturating_add(T::WeightInfo::delegator_bond_more()); - Pallet::::deposit_event(Event::Compounded { delegator, candidate, amount: compound_amount }); + Pallet::::deposit_event(Event::Compounded { + delegator, + candidate, + amount: compound_amount, + }); }; weight @@ -1905,7 +1996,9 @@ pub mod pallet { ) } - fn estimate_next_session_rotation(_now: T::BlockNumber) -> (Option, Weight) { + fn estimate_next_session_rotation( + _now: T::BlockNumber, + ) -> (Option, Weight) { let round = >::get(); ( diff --git a/pallets/parachain-staking/src/mock.rs b/pallets/parachain-staking/src/mock.rs index 563bceb6f..09f6906fc 100644 --- a/pallets/parachain-staking/src/mock.rs +++ b/pallets/parachain-staking/src/mock.rs @@ -17,8 +17,8 @@ //! Test utilities use crate as pallet_parachain_staking; use crate::{ - pallet, AwardedPts, Config, Event as ParachainStakingEvent, InflationInfo, Points, Range, COLLATOR_LOCK_ID, - DELEGATOR_LOCK_ID, + pallet, AwardedPts, Config, Event as ParachainStakingEvent, InflationInfo, Points, Range, + COLLATOR_LOCK_ID, DELEGATOR_LOCK_ID, }; use frame_support::{ construct_runtime, parameter_types, @@ -63,48 +63,48 @@ parameter_types! { pub const SS58Prefix: u8 = 42; } impl frame_system::Config for Test { - type AccountData = pallet_balances::AccountData; - type AccountId = AccountId; type BaseCallFilter = Everything; - type BlockHashCount = BlockHashCount; - type BlockLength = (); - type BlockNumber = BlockNumber; - type BlockWeights = (); type DbWeight = RocksDbWeight; + type RuntimeOrigin = RuntimeOrigin; + type Index = u64; + type BlockNumber = BlockNumber; + type RuntimeCall = RuntimeCall; type Hash = H256; type Hashing = BlakeTwo256; - type Header = sp_runtime::generic::Header; - type Index = u64; + type AccountId = AccountId; type Lookup = IdentityLookup; - type MaxConsumers = frame_support::traits::ConstU32<16>; - type OnKilledAccount = (); - type OnNewAccount = (); - type OnSetCode = (); - type PalletInfo = PalletInfo; - type RuntimeCall = RuntimeCall; + type Header = sp_runtime::generic::Header; type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; - type SS58Prefix = SS58Prefix; - type SystemWeightInfo = (); + type BlockHashCount = BlockHashCount; type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type BlockWeights = (); + type BlockLength = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { pub const ExistentialDeposit: u128 = 1; } impl pallet_balances::Config for Test { - type AccountStore = System; + type MaxReserves = (); + type ReserveIdentifier = [u8; 4]; + type MaxLocks = (); type Balance = Balance; + type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; - type FreezeIdentifier = (); + type AccountStore = System; + type WeightInfo = (); type HoldIdentifier = (); - type MaxFreezes = (); + type FreezeIdentifier = (); type MaxHolds = (); - type MaxLocks = (); - type MaxReserves = (); - type ReserveIdentifier = [u8; 4]; - type RuntimeEvent = RuntimeEvent; - type WeightInfo = (); + type MaxFreezes = (); } parameter_types! { #[derive(Debug, Eq, PartialEq)] @@ -118,17 +118,17 @@ impl pallet_aura::Config for Test { } impl pallet_authorship::Config for Test { - type EventHandler = ParachainStaking; type FindAuthor = pallet_session::FindAccountFromAuthorIndex; + type EventHandler = ParachainStaking; } parameter_types! { pub const MinimumPeriod: u64 = 1; } impl pallet_timestamp::Config for Test { - type MinimumPeriod = MinimumPeriod; type Moment = u64; type OnTimestampSet = Aura; + type MinimumPeriod = MinimumPeriod; type WeightInfo = (); } @@ -167,37 +167,37 @@ use sp_runtime::{ }; impl pallet_session::Config for Test { - type Keys = MockSessionKeys; - type NextSessionRotation = ParachainStaking; type RuntimeEvent = RuntimeEvent; - type SessionHandler = ::KeyTypeIdProviders; - type SessionManager = ParachainStaking; - type ShouldEndSession = ParachainStaking; type ValidatorId = AccountId; type ValidatorIdOf = ConvertInto; + type ShouldEndSession = ParachainStaking; + type NextSessionRotation = ParachainStaking; + type SessionManager = ParachainStaking; + type SessionHandler = ::KeyTypeIdProviders; + type Keys = MockSessionKeys; type WeightInfo = (); } impl Config for Test { - type CandidateBondLessDelay = CandidateBondLessDelay; + type RuntimeEvent = RuntimeEvent; type Currency = Balances; - type DelegationBondLessDelay = DelegationBondLessDelay; + type MonetaryGovernanceOrigin = frame_system::EnsureRoot; + type MinBlocksPerRound = MinBlocksPerRound; type LeaveCandidatesDelay = LeaveCandidatesDelay; + type CandidateBondLessDelay = CandidateBondLessDelay; type LeaveDelegatorsDelay = LeaveDelegatorsDelay; + type RevokeDelegationDelay = RevokeDelegationDelay; + type DelegationBondLessDelay = DelegationBondLessDelay; + type RewardPaymentDelay = RewardPaymentDelay; + type MinSelectedCandidates = MinSelectedCandidates; + type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate; type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator; - type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; - type MinBlocksPerRound = MinBlocksPerRound; type MinCandidateStk = MinCandidateStk; - type MinDelegation = MinDelegation; type MinDelegatorStk = MinDelegatorStk; - type MinSelectedCandidates = MinSelectedCandidates; - type MonetaryGovernanceOrigin = frame_system::EnsureRoot; + type MinDelegation = MinDelegation; type OnCollatorPayout = (); - type OnNewRound = (); type PayoutCollatorReward = (); - type RevokeDelegationDelay = RevokeDelegationDelay; - type RewardPaymentDelay = RewardPaymentDelay; - type RuntimeEvent = RuntimeEvent; + type OnNewRound = (); type WeightInfo = (); } @@ -248,8 +248,12 @@ impl ExtBuilder { self } - pub(crate) fn with_delegations(mut self, delegations: Vec<(AccountId, AccountId, Balance)>) -> Self { - self.delegations = delegations.into_iter().map(|d| (d.0, d.1, d.2, Percent::zero())).collect(); + pub(crate) fn with_delegations( + mut self, + delegations: Vec<(AccountId, AccountId, Balance)>, + ) -> Self { + self.delegations = + delegations.into_iter().map(|d| (d.0, d.1, d.2, Percent::zero())).collect(); self } @@ -344,7 +348,15 @@ pub(crate) fn events() -> Vec> { System::events() .into_iter() .map(|r| r.event) - .filter_map(|e| if let RuntimeEvent::ParachainStaking(inner) = e { Some(inner) } else { None }) + .filter_map( + |e| { + if let RuntimeEvent::ParachainStaking(inner) = e { + Some(inner) + } else { + None + } + }, + ) .collect::>() } @@ -561,7 +573,17 @@ pub(crate) fn query_lock_amount(account_id: u64, id: LockIdentifier) -> Option::NoWritingSameValue ); }); @@ -244,29 +256,33 @@ fn cannot_set_blocks_per_round_to_current_blocks_per_round() { #[test] fn round_immediately_jumps_if_current_duration_exceeds_new_blocks_per_round() { - ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { - // we can't lower the blocks per round because it must be above the number of collators, - // and we can't lower the number of collators because it must be above - // MinSelectedCandidates. so we first raise blocks per round, then lower it. - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // we can't lower the blocks per round because it must be above the number of collators, + // and we can't lower the number of collators because it must be above + // MinSelectedCandidates. so we first raise blocks per round, then lower it. + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); - roll_to(10); - assert_events_emitted!(Event::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 20 - },); - roll_to(17); - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); - roll_to(18); - assert_events_emitted!(Event::NewRound { - starting_block: 18, - round: 3, - selected_collators_number: 1, - total_balance: 20 + roll_to(10); + assert_events_emitted!(Event::NewRound { + starting_block: 10, + round: 2, + selected_collators_number: 1, + total_balance: 20 + },); + roll_to(17); + assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); + roll_to(18); + assert_events_emitted!(Event::NewRound { + starting_block: 18, + round: 3, + selected_collators_number: 1, + total_balance: 20 + }); }); - }); } // ~~ MONETARY GOVERNANCE ~~ @@ -284,14 +300,22 @@ fn invalid_monetary_origin_fails() { assert_noop!( ParachainStaking::set_inflation( RuntimeOrigin::signed(45), - Range { min: Perbill::from_percent(3), ideal: Perbill::from_percent(4), max: Perbill::from_percent(5) } + Range { + min: Perbill::from_percent(3), + ideal: Perbill::from_percent(4), + max: Perbill::from_percent(5) + } ), sp_runtime::DispatchError::BadOrigin ); assert_noop!( ParachainStaking::set_inflation( RuntimeOrigin::signed(45), - Range { min: Perbill::from_percent(3), ideal: Perbill::from_percent(4), max: Perbill::from_percent(5) } + Range { + min: Perbill::from_percent(3), + ideal: Perbill::from_percent(4), + max: Perbill::from_percent(5) + } ), sp_runtime::DispatchError::BadOrigin ); @@ -300,7 +324,10 @@ fn invalid_monetary_origin_fails() { sp_runtime::DispatchError::BadOrigin ); assert_noop!( - ParachainStaking::set_parachain_bond_reserve_percent(RuntimeOrigin::signed(45), Percent::from_percent(2)), + ParachainStaking::set_parachain_bond_reserve_percent( + RuntimeOrigin::signed(45), + Percent::from_percent(2) + ), sp_runtime::DispatchError::BadOrigin ); }); @@ -316,19 +343,29 @@ fn set_staking_event_emits_event_correctly() { RuntimeOrigin::root(), Range { min: 3u128, ideal: 4u128, max: 5u128 } )); - assert_events_eq!(Event::StakeExpectationsSet { expect_min: 3u128, expect_ideal: 4u128, expect_max: 5u128 }); + assert_events_eq!(Event::StakeExpectationsSet { + expect_min: 3u128, + expect_ideal: 4u128, + expect_max: 5u128, + }); }); } #[test] fn set_staking_updates_storage_correctly() { ExtBuilder::default().build().execute_with(|| { - assert_eq!(ParachainStaking::inflation_config().expect, Range { min: 700, ideal: 700, max: 700 }); + assert_eq!( + ParachainStaking::inflation_config().expect, + Range { min: 700, ideal: 700, max: 700 } + ); assert_ok!(ParachainStaking::set_staking_expectations( RuntimeOrigin::root(), Range { min: 3u128, ideal: 4u128, max: 5u128 } )); - assert_eq!(ParachainStaking::inflation_config().expect, Range { min: 3u128, ideal: 4u128, max: 5u128 }); + assert_eq!( + ParachainStaking::inflation_config().expect, + Range { min: 3u128, ideal: 4u128, max: 5u128 } + ); }); } @@ -370,7 +407,10 @@ fn set_inflation_event_emits_correctly() { ExtBuilder::default().build().execute_with(|| { let (min, ideal, max): (Perbill, Perbill, Perbill) = (Perbill::from_percent(3), Perbill::from_percent(4), Perbill::from_percent(5)); - assert_ok!(ParachainStaking::set_inflation(RuntimeOrigin::root(), Range { min, ideal, max })); + assert_ok!(ParachainStaking::set_inflation( + RuntimeOrigin::root(), + Range { min, ideal, max } + )); assert_events_eq!(Event::InflationSet { annual_min: min, annual_ideal: ideal, @@ -389,17 +429,32 @@ fn set_inflation_storage_updates_correctly() { (Perbill::from_percent(3), Perbill::from_percent(4), Perbill::from_percent(5)); assert_eq!( ParachainStaking::inflation_config().annual, - Range { min: Perbill::from_percent(50), ideal: Perbill::from_percent(50), max: Perbill::from_percent(50) } + Range { + min: Perbill::from_percent(50), + ideal: Perbill::from_percent(50), + max: Perbill::from_percent(50) + } ); assert_eq!( ParachainStaking::inflation_config().round, - Range { min: Perbill::from_percent(5), ideal: Perbill::from_percent(5), max: Perbill::from_percent(5) } + Range { + min: Perbill::from_percent(5), + ideal: Perbill::from_percent(5), + max: Perbill::from_percent(5) + } ); - assert_ok!(ParachainStaking::set_inflation(RuntimeOrigin::root(), Range { min, ideal, max }),); + assert_ok!(ParachainStaking::set_inflation( + RuntimeOrigin::root(), + Range { min, ideal, max } + ),); assert_eq!(ParachainStaking::inflation_config().annual, Range { min, ideal, max }); assert_eq!( ParachainStaking::inflation_config().round, - Range { min: Perbill::from_parts(57), ideal: Perbill::from_parts(75), max: Perbill::from_parts(93) } + Range { + min: Perbill::from_parts(57), + ideal: Perbill::from_parts(75), + max: Perbill::from_parts(93) + } ); }); } @@ -410,7 +465,11 @@ fn cannot_set_invalid_inflation() { assert_noop!( ParachainStaking::set_inflation( RuntimeOrigin::root(), - Range { min: Perbill::from_percent(5), ideal: Perbill::from_percent(4), max: Perbill::from_percent(3) } + Range { + min: Perbill::from_percent(5), + ideal: Perbill::from_percent(4), + max: Perbill::from_percent(3) + } ), Error::::InvalidSchedule ); @@ -422,7 +481,10 @@ fn cannot_set_same_inflation() { ExtBuilder::default().build().execute_with(|| { let (min, ideal, max): (Perbill, Perbill, Perbill) = (Perbill::from_percent(3), Perbill::from_percent(4), Perbill::from_percent(5)); - assert_ok!(ParachainStaking::set_inflation(RuntimeOrigin::root(), Range { min, ideal, max }),); + assert_ok!(ParachainStaking::set_inflation( + RuntimeOrigin::root(), + Range { min, ideal, max } + ),); assert_noop!( ParachainStaking::set_inflation(RuntimeOrigin::root(), Range { min, ideal, max }), Error::::NoWritingSameValue @@ -481,7 +543,10 @@ fn set_parachain_bond_reserve_percent_storage_updates_correctly() { fn cannot_set_same_parachain_bond_reserve_percent() { ExtBuilder::default().build().execute_with(|| { assert_noop!( - ParachainStaking::set_parachain_bond_reserve_percent(RuntimeOrigin::root(), Percent::from_percent(30)), + ParachainStaking::set_parachain_bond_reserve_percent( + RuntimeOrigin::root(), + Percent::from_percent(30) + ), Error::::NoWritingSameValue ); }); @@ -544,12 +609,16 @@ fn join_candidates_adds_to_candidate_pool() { #[test] fn cannot_join_candidates_if_candidate() { - ExtBuilder::default().with_balances(vec![(1, 1000)]).with_candidates(vec![(1, 500)]).build().execute_with(|| { - assert_noop!( - ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 11u128, 100u32), - Error::::CandidateExists - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 1000)]) + .with_candidates(vec![(1, 500)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 11u128, 100u32), + Error::::CandidateExists + ); + }); } #[test] @@ -606,7 +675,17 @@ fn insufficient_join_candidates_weight_hint_fails() { #[test] fn sufficient_join_candidates_weight_hint_succeeds() { ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20), (7, 20), (8, 20), (9, 20)]) + .with_balances(vec![ + (1, 20), + (2, 20), + (3, 20), + (4, 20), + (5, 20), + (6, 20), + (7, 20), + (8, 20), + (9, 20), + ]) .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) .build() .execute_with(|| { @@ -622,19 +701,31 @@ fn sufficient_join_candidates_weight_hint_succeeds() { #[test] fn leave_candidates_event_emits_correctly() { - ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_events_eq!(Event::CandidateScheduledExit { exit_allowed_round: 1, candidate: 1, scheduled_exit: 3 }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_events_eq!(Event::CandidateScheduledExit { + exit_allowed_round: 1, + candidate: 1, + scheduled_exit: 3 + }); + }); } #[test] fn leave_candidates_removes_candidate_from_candidate_pool() { - ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert!(ParachainStaking::candidate_pool().0.is_empty()); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert!(ParachainStaking::candidate_pool().0.is_empty()); + }); } #[test] @@ -649,13 +740,17 @@ fn cannot_leave_candidates_if_not_candidate() { #[test] fn cannot_leave_candidates_if_already_leaving_candidates() { - ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_noop!( - ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32), - Error::::CandidateAlreadyLeaving - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_noop!( + ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32), + Error::::CandidateAlreadyLeaving + ); + }); } #[test] @@ -683,7 +778,10 @@ fn sufficient_leave_candidates_weight_hint_succeeds() { .execute_with(|| { let mut count = 5u32; for i in 1..6 { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(i), count)); + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(i), + count + )); count -= 1u32; } }); @@ -693,21 +791,33 @@ fn sufficient_leave_candidates_weight_hint_succeeds() { #[test] fn execute_leave_candidates_emits_event() { - ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert_events_emitted!(Event::CandidateLeft { ex_candidate: 1, unlocked_amount: 10, new_total_amt_locked: 0 }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert_events_emitted!(Event::CandidateLeft { + ex_candidate: 1, + unlocked_amount: 10, + new_total_amt_locked: 0 + }); + }); } #[test] fn execute_leave_candidates_callable_by_any_signed() { - ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 1, 0)); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 1, 0)); + }); } #[test] @@ -732,37 +842,50 @@ fn execute_leave_candidates_requires_correct_weight_hint() { #[test] fn execute_leave_candidates_unreserves_balance() { - ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); + }); } #[test] fn execute_leave_candidates_decreases_total_staked() { - ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { - assert_eq!(ParachainStaking::total(), 10); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert_eq!(ParachainStaking::total(), 0); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::total(), 10); + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert_eq!(ParachainStaking::total(), 0); + }); } #[test] fn execute_leave_candidates_removes_candidate_state() { - ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - // candidate state is not immediately removed - let candidate_state = ParachainStaking::candidate_info(1).expect("just left => still exists"); - assert_eq!(candidate_state.bond, 10u128); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert!(ParachainStaking::candidate_info(1).is_none()); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + // candidate state is not immediately removed + let candidate_state = + ParachainStaking::candidate_info(1).expect("just left => still exists"); + assert_eq!(candidate_state.bond, 10u128); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert!(ParachainStaking::candidate_info(1).is_none()); + }); } #[test] @@ -773,248 +896,371 @@ fn execute_leave_candidates_removes_pending_delegation_requests() { .with_delegations(vec![(2, 1, 15)]) .build() .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); let state = ParachainStaking::delegation_scheduled_requests(&1); assert_eq!( state, - vec![ScheduledRequest { delegator: 2, when_executable: 3, action: DelegationAction::Decrease(5) }], + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], ); assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); // candidate state is not immediately removed - let candidate_state = ParachainStaking::candidate_info(1).expect("just left => still exists"); + let candidate_state = + ParachainStaking::candidate_info(1).expect("just left => still exists"); assert_eq!(candidate_state.bond, 10u128); roll_to(10); assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 1)); assert!(ParachainStaking::candidate_info(1).is_none()); assert!( - !ParachainStaking::delegation_scheduled_requests(&1).iter().any(|x| x.delegator == 2), + !ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2), "delegation request not removed" ); - assert!(!>::contains_key(&1), "the key was not removed from storage"); + assert!( + !>::contains_key(&1), + "the key was not removed from storage" + ); }); } #[test] fn cannot_execute_leave_candidates_before_delay() { - ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_noop!( - ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), - Error::::CandidateCannotLeaveYet - ); - roll_to(9); - assert_noop!( - ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), - Error::::CandidateCannotLeaveYet - ); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0)); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_noop!( + ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), + Error::::CandidateCannotLeaveYet + ); + roll_to(9); + assert_noop!( + ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), + Error::::CandidateCannotLeaveYet + ); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0)); + }); } // CANCEL LEAVE CANDIDATES #[test] fn cancel_leave_candidates_emits_event() { - ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_events_emitted!(Event::CancelledCandidateExit { candidate: 1 }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_events_emitted!(Event::CancelledCandidateExit { candidate: 1 }); + }); } #[test] fn cancel_leave_candidates_updates_candidate_state() { - ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); - let candidate = ParachainStaking::candidate_info(&1).expect("just cancelled leave so exists"); - assert!(candidate.is_active()); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); + let candidate = + ParachainStaking::candidate_info(&1).expect("just cancelled leave so exists"); + assert!(candidate.is_active()); + }); } #[test] fn cancel_leave_candidates_adds_to_candidate_pool() { - ExtBuilder::default().with_balances(vec![(1, 10)]).with_candidates(vec![(1, 10)]).build().execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 10); - }); + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_candidates(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); + assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 10); + }); } // GO OFFLINE #[test] fn go_offline_event_emits_correctly() { - ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert_events_eq!(Event::CandidateWentOffline { candidate: 1 }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert_events_eq!(Event::CandidateWentOffline { candidate: 1 }); + }); } #[test] fn go_offline_removes_candidate_from_candidate_pool() { - ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert!(ParachainStaking::candidate_pool().0.is_empty()); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert!(ParachainStaking::candidate_pool().0.is_empty()); + }); } #[test] fn go_offline_updates_candidate_state_to_idle() { - ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { - let candidate_state = ParachainStaking::candidate_info(1).expect("is active candidate"); - assert_eq!(candidate_state.status, CollatorStatus::Active); - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - let candidate_state = ParachainStaking::candidate_info(1).expect("is candidate, just offline"); - assert_eq!(candidate_state.status, CollatorStatus::Idle); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + let candidate_state = ParachainStaking::candidate_info(1).expect("is active candidate"); + assert_eq!(candidate_state.status, CollatorStatus::Active); + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + let candidate_state = + ParachainStaking::candidate_info(1).expect("is candidate, just offline"); + assert_eq!(candidate_state.status, CollatorStatus::Idle); + }); } #[test] fn cannot_go_offline_if_not_candidate() { ExtBuilder::default().build().execute_with(|| { - assert_noop!(ParachainStaking::go_offline(RuntimeOrigin::signed(3)), Error::::CandidateDNE); + assert_noop!( + ParachainStaking::go_offline(RuntimeOrigin::signed(3)), + Error::::CandidateDNE + ); }); } #[test] fn cannot_go_offline_if_already_offline() { - ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert_noop!(ParachainStaking::go_offline(RuntimeOrigin::signed(1)), Error::::AlreadyOffline); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert_noop!( + ParachainStaking::go_offline(RuntimeOrigin::signed(1)), + Error::::AlreadyOffline + ); + }); } // GO ONLINE #[test] fn go_online_event_emits_correctly() { - ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - roll_blocks(1); - assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); - assert_events_eq!(Event::CandidateBackOnline { candidate: 1 }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + roll_blocks(1); + assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); + assert_events_eq!(Event::CandidateBackOnline { candidate: 1 }); + }); } #[test] fn go_online_adds_to_candidate_pool() { - ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert!(ParachainStaking::candidate_pool().0.is_empty()); - assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + assert!(ParachainStaking::candidate_pool().0.is_empty()); + assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); + }); } #[test] fn go_online_storage_updates_candidate_state() { - ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - let candidate_state = ParachainStaking::candidate_info(1).expect("offline still exists"); - assert_eq!(candidate_state.status, CollatorStatus::Idle); - assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); - let candidate_state = ParachainStaking::candidate_info(1).expect("online so exists"); - assert_eq!(candidate_state.status, CollatorStatus::Active); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); + let candidate_state = + ParachainStaking::candidate_info(1).expect("offline still exists"); + assert_eq!(candidate_state.status, CollatorStatus::Idle); + assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); + let candidate_state = ParachainStaking::candidate_info(1).expect("online so exists"); + assert_eq!(candidate_state.status, CollatorStatus::Active); + }); } #[test] fn cannot_go_online_if_not_candidate() { ExtBuilder::default().build().execute_with(|| { - assert_noop!(ParachainStaking::go_online(RuntimeOrigin::signed(3)), Error::::CandidateDNE); + assert_noop!( + ParachainStaking::go_online(RuntimeOrigin::signed(3)), + Error::::CandidateDNE + ); }); } #[test] fn cannot_go_online_if_already_online() { - ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { - assert_noop!(ParachainStaking::go_online(RuntimeOrigin::signed(1)), Error::::AlreadyActive); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::go_online(RuntimeOrigin::signed(1)), + Error::::AlreadyActive + ); + }); } #[test] fn cannot_go_online_if_leaving() { - ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_noop!(ParachainStaking::go_online(RuntimeOrigin::signed(1)), Error::::CannotGoOnlineIfLeaving); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_noop!( + ParachainStaking::go_online(RuntimeOrigin::signed(1)), + Error::::CannotGoOnlineIfLeaving + ); + }); } // CANDIDATE BOND MORE #[test] fn candidate_bond_more_emits_correct_event() { - ExtBuilder::default().with_balances(vec![(1, 50)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - assert_events_eq!(Event::CandidateBondedMore { candidate: 1, amount: 30, new_total_bond: 50 }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + assert_events_eq!(Event::CandidateBondedMore { + candidate: 1, + amount: 30, + new_total_bond: 50 + }); + }); } #[test] fn candidate_bond_more_reserves_balance() { - ExtBuilder::default().with_balances(vec![(1, 50)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 30); - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); - }); + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 30); + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); + }); } #[test] fn candidate_bond_more_increases_total() { - ExtBuilder::default().with_balances(vec![(1, 50)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { - let mut total = ParachainStaking::total(); - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - total += 30; - assert_eq!(ParachainStaking::total(), total); - }); + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + let mut total = ParachainStaking::total(); + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + total += 30; + assert_eq!(ParachainStaking::total(), total); + }); } #[test] fn candidate_bond_more_updates_candidate_state() { - ExtBuilder::default().with_balances(vec![(1, 50)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 20); - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 50); - }); + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 20); + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 50); + }); } #[test] fn candidate_bond_more_updates_candidate_pool() { - ExtBuilder::default().with_balances(vec![(1, 50)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 50); - }); + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); + assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 50); + }); } // SCHEDULE CANDIDATE BOND LESS #[test] fn schedule_candidate_bond_less_event_emits_correctly() { - ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10)); - assert_events_eq!(Event::CandidateBondLessRequested { candidate: 1, amount_to_decrease: 10, execute_round: 3 }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + assert_events_eq!(Event::CandidateBondLessRequested { + candidate: 1, + amount_to_decrease: 10, + execute_round: 3, + }); + }); } #[test] fn cannot_schedule_candidate_bond_less_if_request_exists() { - ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 5)); - assert_noop!( - ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 5), - Error::::PendingCandidateRequestAlreadyExists - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 5)); + assert_noop!( + ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 5), + Error::::PendingCandidateRequestAlreadyExists + ); + }); } #[test] @@ -1029,134 +1275,216 @@ fn cannot_schedule_candidate_bond_less_if_not_candidate() { #[test] fn cannot_schedule_candidate_bond_less_if_new_total_below_min_candidate_stk() { - ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { - assert_noop!( - ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 21), - Error::::CandidateBondBelowMin - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_noop!( + ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 21), + Error::::CandidateBondBelowMin + ); + }); } #[test] fn can_schedule_candidate_bond_less_if_leaving_candidates() { - ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10)); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + }); } #[test] fn cannot_schedule_candidate_bond_less_if_exited_candidates() { - ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert_noop!( - ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10), - Error::::CandidateDNE - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); + roll_to(10); + assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); + assert_noop!( + ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10), + Error::::CandidateDNE + ); + }); } // 2. EXECUTE BOND LESS REQUEST #[test] fn execute_candidate_bond_less_emits_correct_event() { - ExtBuilder::default().with_balances(vec![(1, 50)]).with_candidates(vec![(1, 50)]).build().execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 30)); - roll_to(10); - roll_blocks(1); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - assert_events_eq!(Event::CandidateBondedLess { candidate: 1, amount: 30, new_bond: 20 }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 50)]) + .with_candidates(vec![(1, 50)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 30 + )); + roll_to(10); + roll_blocks(1); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + assert_events_eq!(Event::CandidateBondedLess { + candidate: 1, + amount: 30, + new_bond: 20 + }); + }); } #[test] fn execute_candidate_bond_less_unreserves_balance() { - ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); - assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10)); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); + }); } #[test] fn execute_candidate_bond_less_decreases_total() { - ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { - let mut total = ParachainStaking::total(); - assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10)); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - total -= 10; - assert_eq!(ParachainStaking::total(), total); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + let mut total = ParachainStaking::total(); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + total -= 10; + assert_eq!(ParachainStaking::total(), total); + }); } #[test] fn execute_candidate_bond_less_updates_candidate_state() { - ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 30); - assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10)); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 20); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 30); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); + assert_eq!(candidate_state.bond, 20); + }); } #[test] fn execute_candidate_bond_less_updates_candidate_pool() { - ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 30); - assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10)); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 30); + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + roll_to(10); + assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); + assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); + assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); + }); } // CANCEL CANDIDATE BOND LESS REQUEST #[test] fn cancel_candidate_bond_less_emits_event() { - ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10)); - assert_ok!(ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(1))); - assert_events_emitted!(Event::CancelledCandidateBondLess { candidate: 1, amount: 10, execute_round: 3 }); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + assert_ok!(ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(1))); + assert_events_emitted!(Event::CancelledCandidateBondLess { + candidate: 1, + amount: 10, + execute_round: 3, + }); + }); } #[test] fn cancel_candidate_bond_less_updates_candidate_state() { - ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10)); - assert_ok!(ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(1))); - assert!(ParachainStaking::candidate_info(&1).unwrap().request.is_none()); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + assert_ok!(ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(1))); + assert!(ParachainStaking::candidate_info(&1).unwrap().request.is_none()); + }); } #[test] fn only_candidate_can_cancel_candidate_bond_less_request() { - ExtBuilder::default().with_balances(vec![(1, 30)]).with_candidates(vec![(1, 30)]).build().execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10)); - assert_noop!( - ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(2)), - Error::::CandidateDNE - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 30)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::schedule_candidate_bond_less( + RuntimeOrigin::signed(1), + 10 + )); + assert_noop!( + ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(2)), + Error::::CandidateDNE + ); + }); } // DELEGATE #[test] fn delegate_event_emits_correctly() { - ExtBuilder::default().with_balances(vec![(1, 30), (2, 10)]).with_candidates(vec![(1, 30)]).build().execute_with( - || { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); assert_events_eq!(Event::Delegation { delegator: 2, @@ -1165,61 +1493,74 @@ fn delegate_event_emits_correctly() { delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, auto_compound: Percent::zero(), }); - }, - ); + }); } #[test] fn delegate_reserves_balance() { - ExtBuilder::default().with_balances(vec![(1, 30), (2, 10)]).with_candidates(vec![(1, 30)]).build().execute_with( - || { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - }, - ); + }); } #[test] fn delegate_updates_delegator_state() { - ExtBuilder::default().with_balances(vec![(1, 30), (2, 10)]).with_candidates(vec![(1, 30)]).build().execute_with( - || { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { assert!(ParachainStaking::delegator_state(2).is_none()); assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); - let delegator_state = ParachainStaking::delegator_state(2).expect("just delegated => exists"); + let delegator_state = + ParachainStaking::delegator_state(2).expect("just delegated => exists"); assert_eq!(delegator_state.total(), 10); assert_eq!(delegator_state.delegations.0[0].owner, 1); assert_eq!(delegator_state.delegations.0[0].amount, 10); - }, - ); + }); } #[test] fn delegate_updates_collator_state() { - ExtBuilder::default().with_balances(vec![(1, 30), (2, 10)]).with_candidates(vec![(1, 30)]).build().execute_with( - || { - let candidate_state = ParachainStaking::candidate_info(1).expect("registered in genesis"); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + let candidate_state = + ParachainStaking::candidate_info(1).expect("registered in genesis"); assert_eq!(candidate_state.total_counted, 30); - let top_delegations = ParachainStaking::top_delegations(1).expect("registered in genesis"); + let top_delegations = + ParachainStaking::top_delegations(1).expect("registered in genesis"); assert!(top_delegations.delegations.is_empty()); assert!(top_delegations.total.is_zero()); assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); - let candidate_state = ParachainStaking::candidate_info(1).expect("just delegated => exists"); + let candidate_state = + ParachainStaking::candidate_info(1).expect("just delegated => exists"); assert_eq!(candidate_state.total_counted, 40); - let top_delegations = ParachainStaking::top_delegations(1).expect("just delegated => exists"); + let top_delegations = + ParachainStaking::top_delegations(1).expect("just delegated => exists"); assert_eq!(top_delegations.delegations[0].owner, 2); assert_eq!(top_delegations.delegations[0].amount, 10); assert_eq!(top_delegations.total, 10); - }, - ); + }); } #[test] fn can_delegate_immediately_after_other_join_candidates() { - ExtBuilder::default().with_balances(vec![(1, 20), (2, 20)]).build().execute_with(|| { - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 20, 0)); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 20, 0, 0)); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 20, 0)); + assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 20, 0, 0)); + }); } #[test] @@ -1301,7 +1642,11 @@ fn can_delegate_if_full_and_new_delegation_greater_than_lowest_bottom() { .build() .execute_with(|| { assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(11), 1, 11, 8, 0)); - assert_events_emitted!(Event::DelegationKicked { delegator: 10, candidate: 1, unstaked_amount: 10 }); + assert_events_emitted!(Event::DelegationKicked { + delegator: 10, + candidate: 1, + unstaked_amount: 10 + }); assert_events_emitted!(Event::DelegatorLeft { delegator: 10, unstaked_amount: 10 }); }); } @@ -1366,19 +1711,42 @@ fn cannot_delegate_more_than_max_delegations() { #[test] fn sufficient_delegate_weight_hint_succeeds() { ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20), (7, 20), (8, 20), (9, 20), (10, 20)]) + .with_balances(vec![ + (1, 20), + (2, 20), + (3, 20), + (4, 20), + (5, 20), + (6, 20), + (7, 20), + (8, 20), + (9, 20), + (10, 20), + ]) .with_candidates(vec![(1, 20), (2, 20)]) .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) .build() .execute_with(|| { let mut count = 4u32; for i in 7..11 { - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(i), 1, 10, count, 0u32)); + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(i), + 1, + 10, + count, + 0u32 + )); count += 1u32; } let mut count = 0u32; for i in 3..11 { - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(i), 2, 10, count, 1u32)); + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(i), + 2, + 10, + count, + 1u32 + )); count += 1u32; } }); @@ -1387,7 +1755,18 @@ fn sufficient_delegate_weight_hint_succeeds() { #[test] fn insufficient_delegate_weight_hint_fails() { ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20), (7, 20), (8, 20), (9, 20), (10, 20)]) + .with_balances(vec![ + (1, 20), + (2, 20), + (3, 20), + (4, 20), + (5, 20), + (6, 20), + (7, 20), + (8, 20), + (9, 20), + (10, 20), + ]) .with_candidates(vec![(1, 20), (2, 20)]) .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) .build() @@ -1402,7 +1781,13 @@ fn insufficient_delegate_weight_hint_fails() { // to set up for next error test count = 4u32; for i in 7..11 { - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(i), 1, 10, count, 0u32)); + assert_ok!(ParachainStaking::delegate( + RuntimeOrigin::signed(i), + 1, + 10, + count, + 0u32 + )); count += 1u32; } count = 0u32; @@ -1427,7 +1812,11 @@ fn schedule_leave_delegators_event_emits_correctly() { .build() .execute_with(|| { assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_events_eq!(Event::DelegatorExitScheduled { round: 1, delegator: 2, scheduled_exit: 3 }); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 1, + delegator: 2, + scheduled_exit: 3 + }); }); } @@ -1449,14 +1838,16 @@ fn cannot_schedule_leave_delegators_if_already_leaving() { #[test] fn cannot_schedule_leave_delegators_if_not_delegator() { - ExtBuilder::default().with_balances(vec![(1, 30), (2, 10)]).with_candidates(vec![(1, 30)]).build().execute_with( - || { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { assert_noop!( ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2)), Error::::DelegatorDNE ); - }, - ); + }); } // EXECUTE LEAVE DELEGATORS @@ -1533,18 +1924,28 @@ fn execute_leave_delegators_removes_pending_delegation_requests() { .with_delegations(vec![(2, 1, 15)]) .build() .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); let state = ParachainStaking::delegation_scheduled_requests(&1); assert_eq!( state, - vec![ScheduledRequest { delegator: 2, when_executable: 3, action: DelegationAction::Decrease(5) }], + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], ); assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); roll_to(10); assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); assert!(ParachainStaking::delegator_state(2).is_none()); assert!( - !ParachainStaking::delegation_scheduled_requests(&1).iter().any(|x| x.delegator == 2), + !ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2), "delegation request not removed" ) }); @@ -1559,9 +1960,11 @@ fn execute_leave_delegators_removes_delegations_from_collator_state() { .build() .execute_with(|| { for i in 2..6 { - let candidate_state = ParachainStaking::candidate_info(i).expect("initialized in ext builder"); + let candidate_state = + ParachainStaking::candidate_info(i).expect("initialized in ext builder"); assert_eq!(candidate_state.total_counted, 30); - let top_delegations = ParachainStaking::top_delegations(i).expect("initialized in ext builder"); + let top_delegations = + ParachainStaking::top_delegations(i).expect("initialized in ext builder"); assert_eq!(top_delegations.delegations[0].owner, 1); assert_eq!(top_delegations.delegations[0].amount, 10); assert_eq!(top_delegations.total, 10); @@ -1571,9 +1974,11 @@ fn execute_leave_delegators_removes_delegations_from_collator_state() { roll_to(10); assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(1), 1, 10)); for i in 2..6 { - let candidate_state = ParachainStaking::candidate_info(i).expect("initialized in ext builder"); + let candidate_state = + ParachainStaking::candidate_info(i).expect("initialized in ext builder"); assert_eq!(candidate_state.total_counted, 20); - let top_delegations = ParachainStaking::top_delegations(i).expect("initialized in ext builder"); + let top_delegations = + ParachainStaking::top_delegations(i).expect("initialized in ext builder"); assert!(top_delegations.delegations.is_empty()); } }); @@ -1655,7 +2060,11 @@ fn sufficient_execute_leave_delegators_weight_hint_succeeds() { } roll_to(10); for i in 3..7 { - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(i), i, 1)); + assert_ok!(ParachainStaking::execute_leave_delegators( + RuntimeOrigin::signed(i), + i, + 1 + )); } }); } @@ -1686,7 +2095,8 @@ fn cancel_leave_delegators_updates_delegator_state() { .execute_with(|| { assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); - let delegator = ParachainStaking::delegator_state(&2).expect("just cancelled exit so exists"); + let delegator = + ParachainStaking::delegator_state(&2).expect("just cancelled exit so exists"); assert!(delegator.is_active()); }); } @@ -1732,7 +2142,11 @@ fn revoke_delegation_event_emits_correctly() { }); roll_to_round_begin(3); roll_blocks(1); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); assert_events_eq!( Event::DelegatorLeftCandidate { delegator: 2, @@ -1884,13 +2298,30 @@ fn delegator_bond_more_updates_candidate_state_bottom_delegations() { .with_delegations(vec![(2, 1, 10), (3, 1, 20), (4, 1, 20), (5, 1, 20), (6, 1, 20)]) .build() .execute_with(|| { - assert_eq!(ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].owner, 2); - assert_eq!(ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].amount, 10); + assert_eq!( + ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].owner, + 2 + ); + assert_eq!( + ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].amount, + 10 + ); assert_eq!(ParachainStaking::bottom_delegations(1).unwrap().total, 10); assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); - assert_events_eq!(Event::DelegationIncreased { delegator: 2, candidate: 1, amount: 5, in_top: false }); - assert_eq!(ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].owner, 2); - assert_eq!(ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].amount, 15); + assert_events_eq!(Event::DelegationIncreased { + delegator: 2, + candidate: 1, + amount: 5, + in_top: false + }); + assert_eq!( + ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].owner, + 2 + ); + assert_eq!( + ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].amount, + 15 + ); assert_eq!(ParachainStaking::bottom_delegations(1).unwrap().total, 15); }); } @@ -1946,7 +2377,11 @@ fn delegator_bond_more_allowed_when_bond_decrease_scheduled() { .with_delegations(vec![(2, 1, 15)]) .build() .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5,)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5, + )); assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); }); } @@ -1961,7 +2396,11 @@ fn delegator_bond_less_event_emits_correctly() { .with_delegations(vec![(2, 1, 10)]) .build() .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); assert_events_eq!(Event::DelegationDecreaseScheduled { delegator: 2, candidate: 1, @@ -1979,11 +2418,19 @@ fn delegator_bond_less_updates_delegator_state() { .with_delegations(vec![(2, 1, 10)]) .build() .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); let state = ParachainStaking::delegation_scheduled_requests(&1); assert_eq!( state, - vec![ScheduledRequest { delegator: 2, when_executable: 3, action: DelegationAction::Decrease(5) }], + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], ); }); } @@ -2120,7 +2567,11 @@ fn execute_revoke_delegation_emits_exit_event_if_exit_happens() { .execute_with(|| { assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); assert_events_emitted!(Event::DelegatorLeftCandidate { delegator: 2, candidate: 1, @@ -2164,7 +2615,11 @@ fn revoke_delegation_executes_exit_if_last_delegation() { .execute_with(|| { assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); assert_events_emitted!(Event::DelegatorLeftCandidate { delegator: 2, candidate: 1, @@ -2185,7 +2640,11 @@ fn execute_revoke_delegation_emits_correct_event() { .execute_with(|| { assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); assert_events_emitted!(Event::DelegatorLeftCandidate { delegator: 2, candidate: 1, @@ -2206,7 +2665,11 @@ fn execute_revoke_delegation_unreserves_balance() { assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); }); } @@ -2219,9 +2682,13 @@ fn execute_revoke_delegation_adds_revocation_to_delegator_state() { .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) .build() .execute_with(|| { - assert!(!ParachainStaking::delegation_scheduled_requests(&1).iter().any(|x| x.delegator == 2)); + assert!(!ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2)); assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert!(ParachainStaking::delegation_scheduled_requests(&1).iter().any(|x| x.delegator == 2)); + assert!(ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2)); }); } @@ -2235,8 +2702,14 @@ fn execute_revoke_delegation_removes_revocation_from_delegator_state_upon_execut .execute_with(|| { assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); - assert!(!ParachainStaking::delegation_scheduled_requests(&1).iter().any(|x| x.delegator == 2)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!(!ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2)); }); } @@ -2250,9 +2723,15 @@ fn execute_revoke_delegation_removes_revocation_from_state_for_single_delegation .execute_with(|| { assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); assert!( - !ParachainStaking::delegation_scheduled_requests(&1).iter().any(|x| x.delegator == 2), + !ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2), "delegation was not removed" ); }); @@ -2269,7 +2748,11 @@ fn execute_revoke_delegation_decreases_total_staked() { assert_eq!(ParachainStaking::total(), 40); assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); assert_eq!(ParachainStaking::total(), 30); }); } @@ -2287,7 +2770,11 @@ fn execute_revoke_delegation_for_last_delegation_removes_delegator_state() { roll_to(10); // this will be confusing for people // if status is leaving, then execute_delegation_request works if last delegation - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); assert!(ParachainStaking::delegator_state(2).is_none()); }); } @@ -2303,8 +2790,15 @@ fn execute_revoke_delegation_removes_delegation_from_candidate_state() { assert_eq!(ParachainStaking::candidate_info(1).expect("exists").delegation_count, 1u32); assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); - assert!(ParachainStaking::candidate_info(1).expect("exists").delegation_count.is_zero()); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert!(ParachainStaking::candidate_info(1) + .expect("exists") + .delegation_count + .is_zero()); }); } @@ -2320,7 +2814,11 @@ fn can_execute_revoke_delegation_for_leaving_candidate() { assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); // can execute delegation request for leaving candidate - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); }); } @@ -2354,7 +2852,11 @@ fn delegator_bond_more_after_revoke_delegation_does_not_effect_exit() { assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 3, 10)); roll_to(100); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); assert!(ParachainStaking::is_delegator(&2)); assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); }); @@ -2379,11 +2881,23 @@ fn delegator_bond_less_after_revoke_delegation_does_not_effect_exit() { ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 2), Error::::PendingDelegationRequestAlreadyExists ); - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 3, 2)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 3, + 2 + )); roll_to(10); roll_blocks(1); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 3)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 3 + )); assert_events_eq!( Event::DelegatorLeftCandidate { delegator: 2, @@ -2410,9 +2924,17 @@ fn execute_delegator_bond_less_unreserves_balance() { .build() .execute_with(|| { assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 5); }); } @@ -2426,9 +2948,17 @@ fn execute_delegator_bond_less_decreases_total_staked() { .build() .execute_with(|| { assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); assert_eq!(ParachainStaking::total(), 35); }); } @@ -2442,9 +2972,17 @@ fn execute_delegator_bond_less_updates_delegator_state() { .build() .execute_with(|| { assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 10); - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 5); }); } @@ -2459,9 +2997,17 @@ fn execute_delegator_bond_less_updates_candidate_state() { .execute_with(|| { assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 10); - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 5); }); @@ -2476,9 +3022,17 @@ fn execute_delegator_bond_less_decreases_total() { .build() .execute_with(|| { assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); assert_eq!(ParachainStaking::total(), 35); }); } @@ -2491,20 +3045,34 @@ fn execute_delegator_bond_less_updates_just_bottom_delegations() { .with_delegations(vec![(2, 1, 10), (3, 1, 11), (4, 1, 12), (5, 1, 14), (6, 1, 15)]) .build() .execute_with(|| { - let pre_call_candidate_info = ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let pre_call_top_delegations = ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + let pre_call_candidate_info = + ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let pre_call_top_delegations = + ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); let pre_call_bottom_delegations = ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 2)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 2 + )); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); - let post_call_candidate_info = ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let post_call_top_delegations = ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); + let post_call_candidate_info = + ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let post_call_top_delegations = + ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); let post_call_bottom_delegations = ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); let mut not_equal = false; for Bond { owner, amount } in pre_call_bottom_delegations.delegations { - for Bond { owner: post_owner, amount: post_amount } in &post_call_bottom_delegations.delegations { + for Bond { owner: post_owner, amount: post_amount } in + &post_call_bottom_delegations.delegations + { if &owner == post_owner { if &amount != post_amount { not_equal = true; @@ -2516,7 +3084,9 @@ fn execute_delegator_bond_less_updates_just_bottom_delegations() { assert!(not_equal); let mut equal = true; for Bond { owner, amount } in pre_call_top_delegations.delegations { - for Bond { owner: post_owner, amount: post_amount } in &post_call_top_delegations.delegations { + for Bond { owner: post_owner, amount: post_amount } in + &post_call_top_delegations.delegations + { if &owner == post_owner { if &amount != post_amount { equal = false; @@ -2526,7 +3096,10 @@ fn execute_delegator_bond_less_updates_just_bottom_delegations() { } } assert!(equal); - assert_eq!(pre_call_candidate_info.total_counted, post_call_candidate_info.total_counted); + assert_eq!( + pre_call_candidate_info.total_counted, + post_call_candidate_info.total_counted + ); }); } @@ -2538,20 +3111,34 @@ fn execute_delegator_bond_less_does_not_delete_bottom_delegations() { .with_delegations(vec![(2, 1, 10), (3, 1, 11), (4, 1, 12), (5, 1, 14), (6, 1, 15)]) .build() .execute_with(|| { - let pre_call_candidate_info = ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let pre_call_top_delegations = ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + let pre_call_candidate_info = + ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let pre_call_top_delegations = + ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); let pre_call_bottom_delegations = ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(6), 1, 4)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(6), + 1, + 4 + )); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(6), 6, 1)); - let post_call_candidate_info = ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let post_call_top_delegations = ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(6), + 6, + 1 + )); + let post_call_candidate_info = + ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); + let post_call_top_delegations = + ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); let post_call_bottom_delegations = ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); let mut equal = true; for Bond { owner, amount } in pre_call_bottom_delegations.delegations { - for Bond { owner: post_owner, amount: post_amount } in &post_call_bottom_delegations.delegations { + for Bond { owner: post_owner, amount: post_amount } in + &post_call_bottom_delegations.delegations + { if &owner == post_owner { if &amount != post_amount { equal = false; @@ -2563,7 +3150,9 @@ fn execute_delegator_bond_less_does_not_delete_bottom_delegations() { assert!(equal); let mut not_equal = false; for Bond { owner, amount } in pre_call_top_delegations.delegations { - for Bond { owner: post_owner, amount: post_amount } in &post_call_top_delegations.delegations { + for Bond { owner: post_owner, amount: post_amount } in + &post_call_top_delegations.delegations + { if &owner == post_owner { if &amount != post_amount { not_equal = true; @@ -2573,7 +3162,10 @@ fn execute_delegator_bond_less_does_not_delete_bottom_delegations() { } } assert!(not_equal); - assert_eq!(pre_call_candidate_info.total_counted - 4, post_call_candidate_info.total_counted); + assert_eq!( + pre_call_candidate_info.total_counted - 4, + post_call_candidate_info.total_counted + ); }); } @@ -2586,10 +3178,18 @@ fn can_execute_delegator_bond_less_for_leaving_candidate() { .build() .execute_with(|| { assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); roll_to(10); // can execute bond more delegation request for leaving candidate - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); }); } @@ -2629,16 +3229,26 @@ fn cancel_revoke_delegation_updates_delegator_state() { let state = ParachainStaking::delegation_scheduled_requests(&1); assert_eq!( state, - vec![ScheduledRequest { delegator: 2, when_executable: 3, action: DelegationAction::Revoke(10) }], + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Revoke(10), + }], ); assert_eq!( - ParachainStaking::delegator_state(&2).map(|x| x.less_total).expect("delegator state must exist"), + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), 10 ); assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); - assert!(!ParachainStaking::delegation_scheduled_requests(&1).iter().any(|x| x.delegator == 2)); + assert!(!ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2)); assert_eq!( - ParachainStaking::delegator_state(&2).map(|x| x.less_total).expect("delegator state must exist"), + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), 0 ); }); @@ -2654,7 +3264,11 @@ fn cancel_delegator_bond_less_correct_event() { .with_delegations(vec![(2, 1, 15)]) .build() .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); assert_events_emitted!(Event::CancelledDelegationRequest { delegator: 2, @@ -2675,20 +3289,34 @@ fn cancel_delegator_bond_less_updates_delegator_state() { .with_delegations(vec![(2, 1, 15)]) .build() .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 5 + )); let state = ParachainStaking::delegation_scheduled_requests(&1); assert_eq!( state, - vec![ScheduledRequest { delegator: 2, when_executable: 3, action: DelegationAction::Decrease(5) }], + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], ); assert_eq!( - ParachainStaking::delegator_state(&2).map(|x| x.less_total).expect("delegator state must exist"), + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), 5 ); assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); - assert!(!ParachainStaking::delegation_scheduled_requests(&1).iter().any(|x| x.delegator == 2)); + assert!(!ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2)); assert_eq!( - ParachainStaking::delegator_state(&2).map(|x| x.less_total).expect("delegator state must exist"), + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), 0 ); }); @@ -2706,31 +3334,53 @@ fn delegator_schedule_revocation_total() { .execute_with(|| { assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); assert_eq!( - ParachainStaking::delegator_state(&2).map(|x| x.less_total).expect("delegator state must exist"), + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), 10 ); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); assert_eq!( - ParachainStaking::delegator_state(&2).map(|x| x.less_total).expect("delegator state must exist"), + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), 0 ); assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 5, 10, 0, 2)); assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3)); assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 4)); assert_eq!( - ParachainStaking::delegator_state(&2).map(|x| x.less_total).expect("delegator state must exist"), + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), 20, ); roll_to(20); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 3)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 3 + )); assert_eq!( - ParachainStaking::delegator_state(&2).map(|x| x.less_total).expect("delegator state must exist"), + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), 10, ); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 4)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 4 + )); assert_eq!( - ParachainStaking::delegator_state(&2).map(|x| x.less_total).expect("delegator state must exist"), + ParachainStaking::delegator_state(&2) + .map(|x| x.less_total) + .expect("delegator state must exist"), 0 ); }); @@ -2770,7 +3420,12 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 2, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { starting_block: 5, round: 2, selected_collators_number: 5, total_balance: 140 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 5, + total_balance: 140, + }, ); assert_eq!(Balances::free_balance(&11), 1); // ~ set block author as 1 for all blocks this round @@ -2795,7 +3450,12 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 4, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 4, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 4, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { starting_block: 15, round: 4, selected_collators_number: 5, total_balance: 140 }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 5, + total_balance: 140, + }, Event::DelegatorExitScheduled { round: 4, delegator: 6, scheduled_exit: 6 }, ); roll_blocks(3); @@ -2814,7 +3474,12 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 5, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 5, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 5, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { starting_block: 20, round: 5, selected_collators_number: 5, total_balance: 140 }, + Event::NewRound { + starting_block: 20, + round: 5, + selected_collators_number: 5, + total_balance: 140, + }, ); roll_blocks(3); assert_events_eq!( @@ -2832,7 +3497,12 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 6, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { starting_block: 25, round: 6, selected_collators_number: 5, total_balance: 140 }, + Event::NewRound { + starting_block: 25, + round: 6, + selected_collators_number: 5, + total_balance: 140, + }, Event::DelegatorLeftCandidate { delegator: 6, candidate: 1, @@ -2856,7 +3526,12 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 7, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 7, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 7, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { starting_block: 30, round: 7, selected_collators_number: 5, total_balance: 130 }, + Event::NewRound { + starting_block: 30, + round: 7, + selected_collators_number: 5, + total_balance: 130, + }, ); roll_blocks(3); assert_events_eq!( @@ -2885,7 +3560,12 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 8, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 8, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 8, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { starting_block: 35, round: 8, selected_collators_number: 5, total_balance: 130 }, + Event::NewRound { + starting_block: 35, + round: 8, + selected_collators_number: 5, + total_balance: 130, + }, ); roll_blocks(3); assert_events_eq!( @@ -2904,7 +3584,12 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 9, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 9, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 9, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { starting_block: 40, round: 9, selected_collators_number: 5, total_balance: 130 }, + Event::NewRound { + starting_block: 40, + round: 9, + selected_collators_number: 5, + total_balance: 130, + }, ); roll_blocks(3); assert_events_eq!( @@ -2932,7 +3617,12 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 10, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 10, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 10, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { starting_block: 45, round: 10, selected_collators_number: 5, total_balance: 140 }, + Event::NewRound { + starting_block: 45, + round: 10, + selected_collators_number: 5, + total_balance: 140, + }, ); roll_blocks(3); assert_events_eq!( @@ -2952,7 +3642,12 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 11, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 11, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 11, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { starting_block: 50, round: 11, selected_collators_number: 5, total_balance: 140 }, + Event::NewRound { + starting_block: 50, + round: 11, + selected_collators_number: 5, + total_balance: 140, + }, ); roll_blocks(3); assert_events_eq!( @@ -2970,7 +3665,12 @@ fn parachain_bond_inflation_reserve_matches_config() { Event::CollatorChosen { round: 12, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 12, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 12, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { starting_block: 55, round: 12, selected_collators_number: 5, total_balance: 140 }, + Event::NewRound { + starting_block: 55, + round: 12, + selected_collators_number: 5, + total_balance: 140, + }, ); roll_blocks(3); assert_events_eq!( @@ -2995,8 +3695,17 @@ fn paid_collator_commission_matches_config() { assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(4), 20u128, 100u32)); assert_events_eq!( Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 40 }, - Event::NewRound { starting_block: 5, round: 2, selected_collators_number: 1, total_balance: 40 }, - Event::JoinedCollatorCandidates { account: 4, amount_locked: 20, new_total_amt_locked: 60 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 1, + total_balance: 40, + }, + Event::JoinedCollatorCandidates { + account: 4, + amount_locked: 20, + new_total_amt_locked: 60, + }, ); roll_blocks(1); @@ -3023,7 +3732,12 @@ fn paid_collator_commission_matches_config() { assert_events_eq!( Event::CollatorChosen { round: 3, collator_account: 1, total_exposed_amount: 40 }, Event::CollatorChosen { round: 3, collator_account: 4, total_exposed_amount: 40 }, - Event::NewRound { starting_block: 10, round: 3, selected_collators_number: 2, total_balance: 80 }, + Event::NewRound { + starting_block: 10, + round: 3, + selected_collators_number: 2, + total_balance: 80, + }, ); // only reward author with id 4 set_author(3, 4, 100); @@ -3033,7 +3747,12 @@ fn paid_collator_commission_matches_config() { assert_events_eq!( Event::CollatorChosen { round: 5, collator_account: 1, total_exposed_amount: 40 }, Event::CollatorChosen { round: 5, collator_account: 4, total_exposed_amount: 40 }, - Event::NewRound { starting_block: 20, round: 5, selected_collators_number: 2, total_balance: 80 }, + Event::NewRound { + starting_block: 20, + round: 5, + selected_collators_number: 2, + total_balance: 80, + }, ); roll_blocks(1); @@ -3048,14 +3767,28 @@ fn paid_collator_commission_matches_config() { #[test] fn collator_exit_executes_after_delay() { ExtBuilder::default() - .with_balances(vec![(1, 1000), (2, 300), (3, 100), (4, 100), (5, 100), (6, 100), (7, 100), (8, 9), (9, 4)]) + .with_balances(vec![ + (1, 1000), + (2, 300), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 9), + (9, 4), + ]) .with_candidates(vec![(1, 500), (2, 200)]) .with_delegations(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) .build() .execute_with(|| { roll_to(11); assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(2), 2)); - assert_events_eq!(Event::CandidateScheduledExit { exit_allowed_round: 3, candidate: 2, scheduled_exit: 5 }); + assert_events_eq!(Event::CandidateScheduledExit { + exit_allowed_round: 3, + candidate: 2, + scheduled_exit: 5, + }); let info = ParachainStaking::candidate_info(&2).unwrap(); assert_eq!(info.status, CollatorStatus::Leaving(5)); roll_to(21); @@ -3097,16 +3830,33 @@ fn collator_selection_chooses_top_candidates() { Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 80 }, Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 70 }, Event::CollatorChosen { round: 2, collator_account: 5, total_exposed_amount: 60 }, - Event::NewRound { starting_block: 5, round: 2, selected_collators_number: 5, total_balance: 400 }, - Event::CandidateScheduledExit { exit_allowed_round: 2, candidate: 6, scheduled_exit: 4 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 5, + total_balance: 400, + }, + Event::CandidateScheduledExit { + exit_allowed_round: 2, + candidate: 6, + scheduled_exit: 4 + }, ); roll_to_round_begin(4); roll_blocks(1); assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(6), 6, 0)); assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(6), 69u128, 100u32)); assert_events_eq!( - Event::CandidateLeft { ex_candidate: 6, unlocked_amount: 50, new_total_amt_locked: 400 }, - Event::JoinedCollatorCandidates { account: 6, amount_locked: 69u128, new_total_amt_locked: 469u128 }, + Event::CandidateLeft { + ex_candidate: 6, + unlocked_amount: 50, + new_total_amt_locked: 400, + }, + Event::JoinedCollatorCandidates { + account: 6, + amount_locked: 69u128, + new_total_amt_locked: 469u128, + }, ); roll_to_round_begin(6); // should choose top TotalSelectedCandidates (5), in order @@ -3116,7 +3866,12 @@ fn collator_selection_chooses_top_candidates() { Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 80 }, Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 70 }, Event::CollatorChosen { round: 6, collator_account: 6, total_exposed_amount: 69 }, - Event::NewRound { starting_block: 25, round: 6, selected_collators_number: 5, total_balance: 409 }, + Event::NewRound { + starting_block: 25, + round: 6, + selected_collators_number: 5, + total_balance: 409, + }, ); }); } @@ -3135,7 +3890,12 @@ fn payout_distribution_to_solo_collators() { Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 90 }, Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 80 }, Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 70 }, - Event::NewRound { starting_block: 5, round: 2, selected_collators_number: 4, total_balance: 340 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 4, + total_balance: 340, + }, ); // ~ set block author as 1 for all blocks this round set_author(2, 1, 100); @@ -3145,7 +3905,12 @@ fn payout_distribution_to_solo_collators() { Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 90 }, Event::CollatorChosen { round: 4, collator_account: 3, total_exposed_amount: 80 }, Event::CollatorChosen { round: 4, collator_account: 4, total_exposed_amount: 70 }, - Event::NewRound { starting_block: 15, round: 4, selected_collators_number: 4, total_balance: 340 }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 4, + total_balance: 340, + }, ); // pay total issuance to 1 at 2nd block roll_blocks(3); @@ -3161,7 +3926,12 @@ fn payout_distribution_to_solo_collators() { Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 90 }, Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 80 }, Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 70 }, - Event::NewRound { starting_block: 25, round: 6, selected_collators_number: 4, total_balance: 340 }, + Event::NewRound { + starting_block: 25, + round: 6, + selected_collators_number: 4, + total_balance: 340, + }, ); roll_blocks(3); assert_events_eq!(Event::Rewarded { account: 1, rewards: 129 }); @@ -3179,7 +3949,12 @@ fn payout_distribution_to_solo_collators() { Event::CollatorChosen { round: 8, collator_account: 2, total_exposed_amount: 90 }, Event::CollatorChosen { round: 8, collator_account: 3, total_exposed_amount: 80 }, Event::CollatorChosen { round: 8, collator_account: 4, total_exposed_amount: 70 }, - Event::NewRound { starting_block: 35, round: 8, selected_collators_number: 4, total_balance: 340 }, + Event::NewRound { + starting_block: 35, + round: 8, + selected_collators_number: 4, + total_balance: 340, + }, ); roll_blocks(1); assert_events_eq!(Event::Rewarded { account: 3, rewards: 56 }); @@ -3227,7 +4002,12 @@ fn multiple_delegations() { Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 20 }, Event::CollatorChosen { round: 2, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { starting_block: 5, round: 2, selected_collators_number: 5, total_balance: 140 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 5, + total_balance: 140, + }, ); roll_blocks(1); assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(6), 2, 10, 10, 10)); @@ -3276,7 +4056,11 @@ fn multiple_delegations() { delegator_position: DelegatorAdded::AddedToBottom, auto_compound: Percent::zero(), }, - Event::CandidateScheduledExit { exit_allowed_round: 6, candidate: 2, scheduled_exit: 8 }, + Event::CandidateScheduledExit { + exit_allowed_round: 6, + candidate: 2, + scheduled_exit: 8 + }, ); roll_to_round_begin(7); assert_events_eq!( @@ -3284,7 +4068,12 @@ fn multiple_delegations() { Event::CollatorChosen { round: 7, collator_account: 3, total_exposed_amount: 30 }, Event::CollatorChosen { round: 7, collator_account: 4, total_exposed_amount: 30 }, Event::CollatorChosen { round: 7, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { starting_block: 30, round: 7, selected_collators_number: 4, total_balance: 120 }, + Event::NewRound { + starting_block: 30, + round: 7, + selected_collators_number: 4, + total_balance: 120, + }, ); // verify that delegations are removed after collator leaves, not before assert_eq!(ParachainStaking::delegator_state(7).unwrap().total(), 90); @@ -3323,24 +4112,40 @@ fn execute_leave_candidate_removes_delegations() { .build() .execute_with(|| { // Verifies the revocation request is initially empty - assert!(!ParachainStaking::delegation_scheduled_requests(&2).iter().any(|x| x.delegator == 3)); + assert!(!ParachainStaking::delegation_scheduled_requests(&2) + .iter() + .any(|x| x.delegator == 3)); assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(2), 2)); assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(3), 2)); // Verifies the revocation request is present - assert!(ParachainStaking::delegation_scheduled_requests(&2).iter().any(|x| x.delegator == 3)); + assert!(ParachainStaking::delegation_scheduled_requests(&2) + .iter() + .any(|x| x.delegator == 3)); roll_to(16); assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 2, 2)); // Verifies the revocation request is again empty - assert!(!ParachainStaking::delegation_scheduled_requests(&2).iter().any(|x| x.delegator == 3)); + assert!(!ParachainStaking::delegation_scheduled_requests(&2) + .iter() + .any(|x| x.delegator == 3)); }); } #[test] fn payouts_follow_delegation_changes() { ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (6, 100), (7, 100), (8, 100), (9, 100), (10, 100)]) + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + ]) .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20)]) .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) .build() @@ -3352,7 +4157,12 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { starting_block: 5, round: 2, selected_collators_number: 4, total_balance: 130 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 4, + total_balance: 130, + }, ); // ~ set block author as 1 for all blocks this round set_author(2, 1, 100); @@ -3363,7 +4173,12 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 4, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 4, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { starting_block: 15, round: 4, selected_collators_number: 4, total_balance: 130 }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 4, + total_balance: 130, + }, ); roll_blocks(3); assert_events_eq!( @@ -3385,7 +4200,11 @@ fn payouts_follow_delegation_changes() { Error::::DelegatorDNE ); assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(6))); - assert_events_eq!(Event::DelegatorExitScheduled { round: 4, delegator: 6, scheduled_exit: 6 }); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 4, + delegator: 6, + scheduled_exit: 6, + }); // fast forward to block in which delegator 6 exit executes roll_to_round_begin(5); assert_events_eq!( @@ -3393,7 +4212,12 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 5, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 5, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 5, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { starting_block: 20, round: 5, selected_collators_number: 4, total_balance: 130 }, + Event::NewRound { + starting_block: 20, + round: 5, + selected_collators_number: 4, + total_balance: 130, + }, ); roll_blocks(3); assert_events_eq!( @@ -3410,7 +4234,12 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { starting_block: 25, round: 6, selected_collators_number: 4, total_balance: 130 }, + Event::NewRound { + starting_block: 25, + round: 6, + selected_collators_number: 4, + total_balance: 130, + }, Event::DelegatorLeftCandidate { delegator: 6, candidate: 1, @@ -3435,7 +4264,12 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 7, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 7, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 7, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { starting_block: 30, round: 7, selected_collators_number: 4, total_balance: 120 }, + Event::NewRound { + starting_block: 30, + round: 7, + selected_collators_number: 4, + total_balance: 120, + }, ); roll_blocks(3); assert_events_eq!( @@ -3449,7 +4283,12 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 8, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 8, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 8, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { starting_block: 35, round: 8, selected_collators_number: 4, total_balance: 120 }, + Event::NewRound { + starting_block: 35, + round: 8, + selected_collators_number: 4, + total_balance: 120, + }, ); roll_blocks(3); assert_events_eq!( @@ -3465,7 +4304,12 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 9, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 9, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 9, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { starting_block: 40, round: 9, selected_collators_number: 4, total_balance: 120 }, + Event::NewRound { + starting_block: 40, + round: 9, + selected_collators_number: 4, + total_balance: 120, + }, ); roll_blocks(3); assert_events_eq!( @@ -3491,7 +4335,12 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 10, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 10, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 10, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { starting_block: 45, round: 10, selected_collators_number: 4, total_balance: 130 }, + Event::NewRound { + starting_block: 45, + round: 10, + selected_collators_number: 4, + total_balance: 130, + }, ); roll_blocks(3); assert_events_eq!( @@ -3507,7 +4356,12 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 11, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 11, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 11, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { starting_block: 50, round: 11, selected_collators_number: 4, total_balance: 130 }, + Event::NewRound { + starting_block: 50, + round: 11, + selected_collators_number: 4, + total_balance: 130, + }, ); roll_blocks(3); assert_events_eq!( @@ -3523,7 +4377,12 @@ fn payouts_follow_delegation_changes() { Event::CollatorChosen { round: 12, collator_account: 2, total_exposed_amount: 40 }, Event::CollatorChosen { round: 12, collator_account: 3, total_exposed_amount: 20 }, Event::CollatorChosen { round: 12, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { starting_block: 55, round: 12, selected_collators_number: 4, total_balance: 130 }, + Event::NewRound { + starting_block: 55, + round: 12, + selected_collators_number: 4, + total_balance: 130, + }, ); roll_blocks(3); assert_events_eq!( @@ -3577,7 +4436,17 @@ fn bottom_delegations_are_empty_when_top_delegations_not_full() { #[test] fn candidate_pool_updates_when_total_counted_changes() { ExtBuilder::default() - .with_balances(vec![(1, 20), (3, 19), (4, 20), (5, 21), (6, 22), (7, 15), (8, 16), (9, 17), (10, 18)]) + .with_balances(vec![ + (1, 20), + (3, 19), + (4, 20), + (5, 21), + (6, 22), + (7, 15), + (8, 16), + (9, 17), + (10, 18), + ]) .with_candidates(vec![(1, 20)]) .with_delegations(vec![ (3, 1, 11), @@ -3613,15 +4482,31 @@ fn candidate_pool_updates_when_total_counted_changes() { // 4: 12 -> 20 => 4 is in top, bumps out 8 // 17 + 18 + 19 + 20 + 20 = 94 (top 4 + self bond) is_candidate_pool_bond(1, 94); - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(10), 1, 3)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(10), + 1, + 3 + )); roll_to(30); // 10: 18 -> 15 => 10 bumped to bottom, 8 bumped to top (- 18 + 16 = -2 for count) - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(10), 10, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(10), + 10, + 1 + )); // 16 + 17 + 19 + 20 + 20 = 92 (top 4 + self bond) is_candidate_pool_bond(1, 92); - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(9), 1, 4)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(9), + 1, + 4 + )); roll_to(40); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(9), 9, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(9), + 9, + 1 + )); // 15 + 16 + 19 + 20 + 20 = 90 (top 4 + self bond) is_candidate_pool_bond(1, 90); }); @@ -3630,7 +4515,17 @@ fn candidate_pool_updates_when_total_counted_changes() { #[test] fn only_top_collators_are_counted() { ExtBuilder::default() - .with_balances(vec![(1, 20), (3, 19), (4, 20), (5, 21), (6, 22), (7, 15), (8, 16), (9, 17), (10, 18)]) + .with_balances(vec![ + (1, 20), + (3, 19), + (4, 20), + (5, 21), + (6, 22), + (7, 15), + (8, 16), + (9, 17), + (10, 18), + ]) .with_candidates(vec![(1, 20)]) .with_delegations(vec![ (3, 1, 11), @@ -3653,25 +4548,45 @@ fn only_top_collators_are_counted() { assert_eq!(collator_state.total_counted, 86); // bump bottom to the top assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(3), 1, 8)); - assert_events_emitted!(Event::DelegationIncreased { delegator: 3, candidate: 1, amount: 8, in_top: true }); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 3, + candidate: 1, + amount: 8, + in_top: true, + }); let collator_state = ParachainStaking::candidate_info(1).unwrap(); // 16 + 17 + 18 + 19 + 20 = 90 (top 4 + self bond) assert_eq!(collator_state.total_counted, 90); // bump bottom to the top assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(4), 1, 8)); - assert_events_emitted!(Event::DelegationIncreased { delegator: 4, candidate: 1, amount: 8, in_top: true }); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 4, + candidate: 1, + amount: 8, + in_top: true, + }); let collator_state = ParachainStaking::candidate_info(1).unwrap(); // 17 + 18 + 19 + 20 + 20 = 94 (top 4 + self bond) assert_eq!(collator_state.total_counted, 94); // bump bottom to the top assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(5), 1, 8)); - assert_events_emitted!(Event::DelegationIncreased { delegator: 5, candidate: 1, amount: 8, in_top: true }); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 5, + candidate: 1, + amount: 8, + in_top: true, + }); let collator_state = ParachainStaking::candidate_info(1).unwrap(); // 18 + 19 + 20 + 21 + 20 = 98 (top 4 + self bond) assert_eq!(collator_state.total_counted, 98); // bump bottom to the top assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(6), 1, 8)); - assert_events_emitted!(Event::DelegationIncreased { delegator: 6, candidate: 1, amount: 8, in_top: true }); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 6, + candidate: 1, + amount: 8, + in_top: true, + }); let collator_state = ParachainStaking::candidate_info(1).unwrap(); // 19 + 20 + 21 + 22 + 20 = 102 (top 4 + self bond) assert_eq!(collator_state.total_counted, 102); @@ -3726,18 +4641,32 @@ fn delegation_events_convey_correct_position() { assert_eq!(collator1_state.total_counted, 74); // 8 increases delegation to the top assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(8), 1, 3)); - assert_events_emitted!(Event::DelegationIncreased { delegator: 8, candidate: 1, amount: 3, in_top: true }); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 8, + candidate: 1, + amount: 3, + in_top: true, + }); let collator1_state = ParachainStaking::candidate_info(1).unwrap(); // 13 + 13 + 14 + 15 + 20 = 75 (top 4 + self bond) assert_eq!(collator1_state.total_counted, 75); // 3 increases delegation but stays in bottom assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(3), 1, 1)); - assert_events_emitted!(Event::DelegationIncreased { delegator: 3, candidate: 1, amount: 1, in_top: false }); + assert_events_emitted!(Event::DelegationIncreased { + delegator: 3, + candidate: 1, + amount: 1, + in_top: false, + }); let collator1_state = ParachainStaking::candidate_info(1).unwrap(); // 13 + 13 + 14 + 15 + 20 = 75 (top 4 + self bond) assert_eq!(collator1_state.total_counted, 75); // 6 decreases delegation but stays in top - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(6), 1, 2)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(6), + 1, + 2 + )); assert_events_emitted!(Event::DelegationDecreaseScheduled { delegator: 6, candidate: 1, @@ -3745,13 +4674,26 @@ fn delegation_events_convey_correct_position() { execute_round: 3, }); roll_to(30); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(6), 6, 1)); - assert_events_emitted!(Event::DelegationDecreased { delegator: 6, candidate: 1, amount: 2, in_top: true }); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(6), + 6, + 1 + )); + assert_events_emitted!(Event::DelegationDecreased { + delegator: 6, + candidate: 1, + amount: 2, + in_top: true, + }); let collator1_state = ParachainStaking::candidate_info(1).unwrap(); // 12 + 13 + 13 + 15 + 20 = 73 (top 4 + self bond)ƒ assert_eq!(collator1_state.total_counted, 73); // 6 decreases delegation and is bumped to bottom - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(6), 1, 1)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(6), + 1, + 1 + )); assert_events_emitted!(Event::DelegationDecreaseScheduled { delegator: 6, candidate: 1, @@ -3759,8 +4701,17 @@ fn delegation_events_convey_correct_position() { execute_round: 9, }); roll_to(40); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(6), 6, 1)); - assert_events_emitted!(Event::DelegationDecreased { delegator: 6, candidate: 1, amount: 1, in_top: false }); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(6), + 6, + 1 + )); + assert_events_emitted!(Event::DelegationDecreased { + delegator: 6, + candidate: 1, + amount: 1, + in_top: false, + }); let collator1_state = ParachainStaking::candidate_info(1).unwrap(); // 12 + 13 + 13 + 15 + 20 = 73 (top 4 + self bond) assert_eq!(collator1_state.total_counted, 73); @@ -3785,7 +4736,12 @@ fn no_rewards_paid_until_after_reward_payment_delay() { Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 20 }, Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 20 }, Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, - Event::NewRound { starting_block: 5, round: 2, selected_collators_number: 3, total_balance: 60 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 3, + total_balance: 60, + }, ); roll_to_round_begin(3); @@ -3793,7 +4749,12 @@ fn no_rewards_paid_until_after_reward_payment_delay() { Event::CollatorChosen { round: 3, collator_account: 1, total_exposed_amount: 20 }, Event::CollatorChosen { round: 3, collator_account: 2, total_exposed_amount: 20 }, Event::CollatorChosen { round: 3, collator_account: 3, total_exposed_amount: 20 }, - Event::NewRound { starting_block: 10, round: 3, selected_collators_number: 3, total_balance: 60 }, + Event::NewRound { + starting_block: 10, + round: 3, + selected_collators_number: 3, + total_balance: 60, + }, ); roll_blocks(1); @@ -3835,7 +4796,12 @@ fn deferred_payment_storage_items_are_cleaned_up() { assert_events_eq!( Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 20 }, Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 20 }, - Event::NewRound { starting_block: 5, round: 2, selected_collators_number: 2, total_balance: 40 }, + Event::NewRound { + starting_block: 5, + round: 2, + selected_collators_number: 2, + total_balance: 40, + }, ); // we should have AtStake snapshots as soon as we start a round... @@ -3849,18 +4815,35 @@ fn deferred_payment_storage_items_are_cleaned_up() { !>::contains_key(1), "DelayedPayouts shouldn't be populated until after RewardPaymentDelay" ); - assert!(>::contains_key(1), "Points should be populated during current round"); - assert!(>::contains_key(1), "Staked should be populated when round changes"); + assert!( + >::contains_key(1), + "Points should be populated during current round" + ); + assert!( + >::contains_key(1), + "Staked should be populated when round changes" + ); - assert!(!>::contains_key(2), "Points should not be populated until author noted"); - assert!(>::contains_key(2), "Staked should be populated when round changes"); + assert!( + !>::contains_key(2), + "Points should not be populated until author noted" + ); + assert!( + >::contains_key(2), + "Staked should be populated when round changes" + ); // first payout occurs in round 3 roll_to_round_begin(3); assert_events_eq!( Event::CollatorChosen { round: 3, collator_account: 1, total_exposed_amount: 20 }, Event::CollatorChosen { round: 3, collator_account: 2, total_exposed_amount: 20 }, - Event::NewRound { starting_block: 10, round: 3, selected_collators_number: 2, total_balance: 40 }, + Event::NewRound { + starting_block: 10, + round: 3, + selected_collators_number: 2, + total_balance: 40, + }, ); roll_blocks(1); @@ -3877,7 +4860,10 @@ fn deferred_payment_storage_items_are_cleaned_up() { "DelayedPayouts should be populated after RewardPaymentDelay" ); assert!(>::contains_key(1)); - assert!(!>::contains_key(1), "Staked should be cleaned up after round change"); + assert!( + !>::contains_key(1), + "Staked should be cleaned up after round change" + ); assert!(!>::contains_key(2)); assert!(!>::contains_key(2), "We never rewarded points for round 2"); @@ -3903,7 +4889,12 @@ fn deferred_payment_storage_items_are_cleaned_up() { assert_events_eq!( Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 20 }, Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 20 }, - Event::NewRound { starting_block: 15, round: 4, selected_collators_number: 2, total_balance: 40 }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 2, + total_balance: 40, + }, ); // collators have both been paid and storage fully cleaned up for round 1 @@ -4018,8 +5009,13 @@ fn deferred_payment_steady_state_event_flow() { let new_issuance = Balances::total_issuance(); let diff = new_issuance - initial_issuance; let burned = Balances::burn(diff); - Balances::settle(&111, burned, WithdrawReasons::FEE, ExistenceRequirement::AllowDeath) - .expect("Account can absorb burn"); + Balances::settle( + &111, + burned, + WithdrawReasons::FEE, + ExistenceRequirement::AllowDeath, + ) + .expect("Account can absorb burn"); }; // fn to roll through the first RewardPaymentDelay rounds. returns new round index @@ -4043,10 +5039,26 @@ fn deferred_payment_steady_state_event_flow() { assert!(num_rounds_rolled <= 1, "expected to be at round begin already"); assert_events_eq!( - Event::CollatorChosen { round: round as u32, collator_account: 1, total_exposed_amount: 400 }, - Event::CollatorChosen { round: round as u32, collator_account: 2, total_exposed_amount: 400 }, - Event::CollatorChosen { round: round as u32, collator_account: 3, total_exposed_amount: 400 }, - Event::CollatorChosen { round: round as u32, collator_account: 4, total_exposed_amount: 400 }, + Event::CollatorChosen { + round: round as u32, + collator_account: 1, + total_exposed_amount: 400, + }, + Event::CollatorChosen { + round: round as u32, + collator_account: 2, + total_exposed_amount: 400, + }, + Event::CollatorChosen { + round: round as u32, + collator_account: 3, + total_exposed_amount: 400, + }, + Event::CollatorChosen { + round: round as u32, + collator_account: 4, + total_exposed_amount: 400, + }, Event::NewRound { starting_block: (round - 1) * 5, round: round as u32, @@ -4141,9 +5153,15 @@ fn delegation_kicked_from_bottom_removes_pending_request() { // 10 delegates to full 1 => kicks lowest delegation (2, 19) assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(10), 1, 20, 8, 0)); // check the event - assert_events_emitted!(Event::DelegationKicked { delegator: 2, candidate: 1, unstaked_amount: 19 }); + assert_events_emitted!(Event::DelegationKicked { + delegator: 2, + candidate: 1, + unstaked_amount: 19, + }); // ensure request DNE - assert!(!ParachainStaking::delegation_scheduled_requests(&1).iter().any(|x| x.delegator == 2)); + assert!(!ParachainStaking::delegation_scheduled_requests(&1) + .iter() + .any(|x| x.delegator == 2)); }); } @@ -4157,7 +5175,10 @@ fn no_selected_candidates_defaults_to_last_round_collators() { roll_to_round_begin(1); // schedule to leave for i in 1..6 { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(i), 5)); + assert_ok!(ParachainStaking::schedule_leave_candidates( + RuntimeOrigin::signed(i), + 5 + )); } let old_round = ParachainStaking::round().current; let old_selected_candidates = ParachainStaking::selected_candidates(); @@ -4168,7 +5189,11 @@ fn no_selected_candidates_defaults_to_last_round_collators() { roll_to_round_begin(3); // execute leave for i in 1..6 { - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(i), i, 0,)); + assert_ok!(ParachainStaking::execute_leave_candidates( + RuntimeOrigin::signed(i), + i, + 0, + )); } // next round roll_to_round_begin(4); @@ -4203,25 +5228,35 @@ fn test_delegator_scheduled_for_revoke_is_rewarded_for_previous_rounds_but_not_f scheduled_exit: 3, }); let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!(1, collator.delegation_count, "collator's delegator count was reduced unexpectedly"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); roll_to_round_begin(3); assert_events_emitted_match!(Event::NewRound { round: 3, .. }); roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 4 }, Event::Rewarded { account: 2, rewards: 1 },); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 4 }, + Event::Rewarded { account: 2, rewards: 1 }, + ); roll_to_round_begin(4); assert_events_emitted_match!(Event::NewRound { round: 4, .. }); roll_blocks(3); assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); - let collator_snapshot = ParachainStaking::at_stake(ParachainStaking::round().current, 1); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); assert_eq!( 1, collator_snapshot.delegations.len(), "collator snapshot's delegator count was reduced unexpectedly" ); - assert_eq!(20, collator_snapshot.total, "collator snapshot's total was reduced unexpectedly",); + assert_eq!( + 20, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); }); } @@ -4244,7 +5279,10 @@ fn test_delegator_scheduled_for_revoke_is_rewarded_when_request_cancelled() { scheduled_exit: 3, }); let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!(1, collator.delegation_count, "collator's delegator count was reduced unexpectedly"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); roll_to_round_begin(2); @@ -4254,23 +5292,31 @@ fn test_delegator_scheduled_for_revoke_is_rewarded_when_request_cancelled() { assert_events_emitted_match!(Event::NewRound { round: 4, .. }); roll_blocks(3); assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); - let collator_snapshot = ParachainStaking::at_stake(ParachainStaking::round().current, 1); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); assert_eq!( 1, collator_snapshot.delegations.len(), "collator snapshot's delegator count was reduced unexpectedly" ); - assert_eq!(30, collator_snapshot.total, "collator snapshot's total was reduced unexpectedly",); + assert_eq!( + 30, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); roll_to_round_begin(5); assert_events_emitted_match!(Event::NewRound { round: 5, .. }); roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 4 }, Event::Rewarded { account: 2, rewards: 1 },); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 4 }, + Event::Rewarded { account: 2, rewards: 1 }, + ); }); } #[test] -fn test_delegator_scheduled_for_bond_decrease_is_rewarded_for_previous_rounds_but_less_for_future() { +fn test_delegator_scheduled_for_bond_decrease_is_rewarded_for_previous_rounds_but_less_for_future() +{ ExtBuilder::default() .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) @@ -4280,7 +5326,11 @@ fn test_delegator_scheduled_for_bond_decrease_is_rewarded_for_previous_rounds_bu // preset rewards for rounds 1, 2 and 3 (1..=3).for_each(|round| set_author(round, 1, 1)); - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 10,)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 10, + )); assert_events_eq!(Event::DelegationDecreaseScheduled { execute_round: 3, delegator: 2, @@ -4288,25 +5338,38 @@ fn test_delegator_scheduled_for_bond_decrease_is_rewarded_for_previous_rounds_bu amount_to_decrease: 10, }); let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!(1, collator.delegation_count, "collator's delegator count was reduced unexpectedly"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); assert_eq!(40, collator.total_counted, "collator's total was reduced unexpectedly"); roll_to_round_begin(3); assert_events_emitted_match!(Event::NewRound { round: 3, .. }); roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 3 }, Event::Rewarded { account: 2, rewards: 2 },); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 3 }, + Event::Rewarded { account: 2, rewards: 2 }, + ); roll_to_round_begin(4); assert_events_emitted_match!(Event::NewRound { round: 4, .. }); roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 4 }, Event::Rewarded { account: 2, rewards: 1 },); - let collator_snapshot = ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 4 }, + Event::Rewarded { account: 2, rewards: 1 }, + ); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); assert_eq!( 1, collator_snapshot.delegations.len(), "collator snapshot's delegator count was reduced unexpectedly" ); - assert_eq!(30, collator_snapshot.total, "collator snapshot's total was reduced unexpectedly",); + assert_eq!( + 30, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); }); } @@ -4321,7 +5384,11 @@ fn test_delegator_scheduled_for_bond_decrease_is_rewarded_when_request_cancelled // preset rewards for rounds 2, 3 and 4 (2..=4).for_each(|round| set_author(round, 1, 1)); - assert_ok!(ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 10,)); + assert_ok!(ParachainStaking::schedule_delegator_bond_less( + RuntimeOrigin::signed(2), + 1, + 10, + )); assert_events_eq!(Event::DelegationDecreaseScheduled { execute_round: 3, delegator: 2, @@ -4329,7 +5396,10 @@ fn test_delegator_scheduled_for_bond_decrease_is_rewarded_when_request_cancelled amount_to_decrease: 10, }); let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!(1, collator.delegation_count, "collator's delegator count was reduced unexpectedly"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); assert_eq!(40, collator.total_counted, "collator's total was reduced unexpectedly"); roll_to_round_begin(2); @@ -4338,19 +5408,29 @@ fn test_delegator_scheduled_for_bond_decrease_is_rewarded_when_request_cancelled roll_to_round_begin(4); assert_events_emitted_match!(Event::NewRound { round: 4, .. }); roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 4 }, Event::Rewarded { account: 2, rewards: 1 },); - let collator_snapshot = ParachainStaking::at_stake(ParachainStaking::round().current, 1); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 4 }, + Event::Rewarded { account: 2, rewards: 1 }, + ); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); assert_eq!( 1, collator_snapshot.delegations.len(), "collator snapshot's delegator count was reduced unexpectedly" ); - assert_eq!(40, collator_snapshot.total, "collator snapshot's total was reduced unexpectedly",); + assert_eq!( + 40, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); roll_to_round_begin(5); assert_events_emitted_match!(Event::NewRound { round: 5, .. }); roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 3 }, Event::Rewarded { account: 2, rewards: 2 },); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 3 }, + Event::Rewarded { account: 2, rewards: 2 }, + ); }); } @@ -4366,27 +5446,41 @@ fn test_delegator_scheduled_for_leave_is_rewarded_for_previous_rounds_but_not_fo (1..=3).for_each(|round| set_author(round, 1, 1)); assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2),)); - assert_events_eq!(Event::DelegatorExitScheduled { round: 1, delegator: 2, scheduled_exit: 3 }); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 1, + delegator: 2, + scheduled_exit: 3, + }); let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!(1, collator.delegation_count, "collator's delegator count was reduced unexpectedly"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); roll_to_round_begin(3); assert_events_emitted_match!(Event::NewRound { round: 3, .. }); roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 4 }, Event::Rewarded { account: 2, rewards: 1 },); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 4 }, + Event::Rewarded { account: 2, rewards: 1 }, + ); roll_to_round_begin(4); assert_events_emitted_match!(Event::NewRound { round: 4, .. }); roll_blocks(3); assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); - let collator_snapshot = ParachainStaking::at_stake(ParachainStaking::round().current, 1); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); assert_eq!( 1, collator_snapshot.delegations.len(), "collator snapshot's delegator count was reduced unexpectedly" ); - assert_eq!(20, collator_snapshot.total, "collator snapshot's total was reduced unexpectedly",); + assert_eq!( + 20, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); }); } @@ -4402,9 +5496,16 @@ fn test_delegator_scheduled_for_leave_is_rewarded_when_request_cancelled() { (2..=4).for_each(|round| set_author(round, 1, 1)); assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_events_eq!(Event::DelegatorExitScheduled { round: 1, delegator: 2, scheduled_exit: 3 }); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 1, + delegator: 2, + scheduled_exit: 3, + }); let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!(1, collator.delegation_count, "collator's delegator count was reduced unexpectedly"); + assert_eq!( + 1, collator.delegation_count, + "collator's delegator count was reduced unexpectedly" + ); assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); roll_to_round_begin(2); @@ -4414,18 +5515,25 @@ fn test_delegator_scheduled_for_leave_is_rewarded_when_request_cancelled() { assert_events_emitted_match!(Event::NewRound { round: 4, .. }); roll_blocks(3); assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); - let collator_snapshot = ParachainStaking::at_stake(ParachainStaking::round().current, 1); + let collator_snapshot = + ParachainStaking::at_stake(ParachainStaking::round().current, 1); assert_eq!( 1, collator_snapshot.delegations.len(), "collator snapshot's delegator count was reduced unexpectedly" ); - assert_eq!(30, collator_snapshot.total, "collator snapshot's total was reduced unexpectedly",); + assert_eq!( + 30, collator_snapshot.total, + "collator snapshot's total was reduced unexpectedly", + ); roll_to_round_begin(5); assert_events_emitted_match!(Event::NewRound { round: 5, .. }); roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 4 }, Event::Rewarded { account: 2, rewards: 1 },); + assert_events_eq!( + Event::Rewarded { account: 1, rewards: 4 }, + Event::Rewarded { account: 2, rewards: 1 }, + ); }); } @@ -4451,7 +5559,11 @@ fn test_delegation_request_exists_returns_true_when_decrease_exists() { .execute_with(|| { >::insert( 1, - vec![ScheduledRequest { delegator: 2, when_executable: 3, action: DelegationAction::Decrease(5) }], + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], ); assert!(ParachainStaking::delegation_request_exists(&1, &2)); }); @@ -4467,7 +5579,11 @@ fn test_delegation_request_exists_returns_true_when_revoke_exists() { .execute_with(|| { >::insert( 1, - vec![ScheduledRequest { delegator: 2, when_executable: 3, action: DelegationAction::Revoke(5) }], + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Revoke(5), + }], ); assert!(ParachainStaking::delegation_request_exists(&1, &2)); }); @@ -4495,7 +5611,11 @@ fn test_delegation_request_revoke_exists_returns_false_when_decrease_exists() { .execute_with(|| { >::insert( 1, - vec![ScheduledRequest { delegator: 2, when_executable: 3, action: DelegationAction::Decrease(5) }], + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Decrease(5), + }], ); assert!(!ParachainStaking::delegation_request_revoke_exists(&1, &2)); }); @@ -4511,7 +5631,11 @@ fn test_delegation_request_revoke_exists_returns_true_when_revoke_exists() { .execute_with(|| { >::insert( 1, - vec![ScheduledRequest { delegator: 2, when_executable: 3, action: DelegationAction::Revoke(5) }], + vec![ScheduledRequest { + delegator: 2, + when_executable: 3, + action: DelegationAction::Revoke(5), + }], ); assert!(ParachainStaking::delegation_request_revoke_exists(&1, &2)); }); @@ -4519,63 +5643,107 @@ fn test_delegation_request_revoke_exists_returns_true_when_revoke_exists() { #[test] fn test_hotfix_remove_delegation_requests_exited_candidates_cleans_up() { - ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { - // invalid state - >::insert(2, Vec::>::new()); - >::insert(3, Vec::>::new()); - assert_ok!(ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( - RuntimeOrigin::signed(1), - vec![2, 3, 4] // 4 does not exist, but is OK for idempotency - )); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // invalid state + >::insert( + 2, + Vec::>::new(), + ); + >::insert( + 3, + Vec::>::new(), + ); + assert_ok!(ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( + RuntimeOrigin::signed(1), + vec![2, 3, 4] // 4 does not exist, but is OK for idempotency + )); - assert!(!>::contains_key(2)); - assert!(!>::contains_key(3)); - }); + assert!(!>::contains_key(2)); + assert!(!>::contains_key(3)); + }); } #[test] fn test_hotfix_remove_delegation_requests_exited_candidates_cleans_up_only_specified_keys() { - ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { - // invalid state - >::insert(2, Vec::>::new()); - >::insert(3, Vec::>::new()); - assert_ok!(ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( - RuntimeOrigin::signed(1), - vec![2] - )); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // invalid state + >::insert( + 2, + Vec::>::new(), + ); + >::insert( + 3, + Vec::>::new(), + ); + assert_ok!(ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( + RuntimeOrigin::signed(1), + vec![2] + )); - assert!(!>::contains_key(2)); - assert!(>::contains_key(3)); - }); + assert!(!>::contains_key(2)); + assert!(>::contains_key(3)); + }); } #[test] fn test_hotfix_remove_delegation_requests_exited_candidates_errors_when_requests_not_empty() { - ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { - // invalid state - >::insert(2, Vec::>::new()); - >::insert( - 3, - vec![ScheduledRequest { delegator: 10, when_executable: 1, action: DelegationAction::Revoke(10) }], - ); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // invalid state + >::insert( + 2, + Vec::>::new(), + ); + >::insert( + 3, + vec![ScheduledRequest { + delegator: 10, + when_executable: 1, + action: DelegationAction::Revoke(10), + }], + ); - assert_noop!( - ParachainStaking::hotfix_remove_delegation_requests_exited_candidates(RuntimeOrigin::signed(1), vec![2, 3]), - >::CandidateNotLeaving, - ); - }); + assert_noop!( + ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( + RuntimeOrigin::signed(1), + vec![2, 3] + ), + >::CandidateNotLeaving, + ); + }); } #[test] fn test_hotfix_remove_delegation_requests_exited_candidates_errors_when_candidate_not_exited() { - ExtBuilder::default().with_balances(vec![(1, 20)]).with_candidates(vec![(1, 20)]).build().execute_with(|| { - // invalid state - >::insert(1, Vec::>::new()); - assert_noop!( - ParachainStaking::hotfix_remove_delegation_requests_exited_candidates(RuntimeOrigin::signed(1), vec![1]), - >::CandidateNotLeaving, - ); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20)]) + .with_candidates(vec![(1, 20)]) + .build() + .execute_with(|| { + // invalid state + >::insert( + 1, + Vec::>::new(), + ); + assert_noop!( + ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( + RuntimeOrigin::signed(1), + vec![1] + ), + >::CandidateNotLeaving, + ); + }); } #[test] @@ -4610,13 +5778,21 @@ fn revoke_last_removes_lock() { // schedule and remove one... assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(3), 1)); roll_to_round_begin(3); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(3), 3, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(3), + 3, + 1 + )); assert_eq!(crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), Some(25)); // schedule and remove the other... assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(3), 2)); roll_to_round_begin(5); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(3), 3, 2)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(3), + 3, + 2 + )); assert_eq!(crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), None); }); } @@ -4642,7 +5818,11 @@ fn test_delegator_with_deprecated_status_leaving_can_schedule_leave_delegators_a assert!(>::get(1) .iter() .any(|r| r.delegator == 2 && matches!(r.action, DelegationAction::Revoke(_)))); - assert_events_eq!(Event::DelegatorExitScheduled { round: 1, delegator: 2, scheduled_exit: 3 }); + assert_events_eq!(Event::DelegatorExitScheduled { + round: 1, + delegator: 2, + scheduled_exit: 3 + }); let state = >::get(2); assert!(matches!(state.unwrap().status, DelegatorStatus::Active)); @@ -4854,8 +6034,18 @@ fn test_set_auto_compound_removes_if_auto_compound_zero_percent() { ) .set_storage(&1); - assert_ok!(ParachainStaking::set_auto_compound(RuntimeOrigin::signed(2), 1, Percent::zero(), 1, 1,)); - assert_events_emitted!(Event::AutoCompoundSet { candidate: 1, delegator: 2, value: Percent::zero() }); + assert_ok!(ParachainStaking::set_auto_compound( + RuntimeOrigin::signed(2), + 1, + Percent::zero(), + 1, + 1, + )); + assert_events_emitted!(Event::AutoCompoundSet { + candidate: 1, + delegator: 2, + value: Percent::zero(), + }); assert_eq!(0, ParachainStaking::auto_compounding_delegations(&1).len(),); }); } @@ -4884,13 +6074,21 @@ fn test_execute_revoke_delegation_removes_auto_compounding_from_state_for_delega )); assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1)); + assert_ok!(ParachainStaking::execute_delegation_request( + RuntimeOrigin::signed(2), + 2, + 1 + )); assert!( - !ParachainStaking::auto_compounding_delegations(&1).iter().any(|x| x.delegator == 2), + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), "delegation auto-compound config was not removed" ); assert!( - ParachainStaking::auto_compounding_delegations(&3).iter().any(|x| x.delegator == 2), + ParachainStaking::auto_compounding_delegations(&3) + .iter() + .any(|x| x.delegator == 2), "delegation auto-compound config was erroneously removed" ); }); @@ -4924,11 +6122,15 @@ fn test_execute_leave_delegators_removes_auto_compounding_state() { assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2,)); assert!( - !ParachainStaking::auto_compounding_delegations(&1).iter().any(|x| x.delegator == 2), + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), "delegation auto-compound config was not removed" ); assert!( - !ParachainStaking::auto_compounding_delegations(&3).iter().any(|x| x.delegator == 2), + !ParachainStaking::auto_compounding_delegations(&3) + .iter() + .any(|x| x.delegator == 2), "delegation auto-compound config was not removed" ); }); @@ -4967,11 +6169,15 @@ fn test_execute_leave_delegators_with_deprecated_status_leaving_removes_auto_com assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2,)); assert!( - !ParachainStaking::auto_compounding_delegations(&1).iter().any(|x| x.delegator == 2), + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), "delegation auto-compound config was not removed" ); assert!( - !ParachainStaking::auto_compounding_delegations(&3).iter().any(|x| x.delegator == 2), + !ParachainStaking::auto_compounding_delegations(&3) + .iter() + .any(|x| x.delegator == 2), "delegation auto-compound config was not removed" ); }); @@ -5005,11 +6211,15 @@ fn test_execute_leave_candidates_removes_auto_compounding_state() { assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 1,)); assert!( - !ParachainStaking::auto_compounding_delegations(&1).iter().any(|x| x.delegator == 2), + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), "delegation auto-compound config was not removed" ); assert!( - ParachainStaking::auto_compounding_delegations(&3).iter().any(|x| x.delegator == 2), + ParachainStaking::auto_compounding_delegations(&3) + .iter() + .any(|x| x.delegator == 2), "delegation auto-compound config was erroneously removed" ); }); @@ -5057,7 +6267,9 @@ fn test_delegation_kicked_from_bottom_delegation_removes_auto_compounding_state( assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(10), 1, 20, 8, 0)); assert!( - !ParachainStaking::auto_compounding_delegations(&1).iter().any(|x| x.delegator == 2), + !ParachainStaking::auto_compounding_delegations(&1) + .iter() + .any(|x| x.delegator == 2), "delegation auto-compound config was not removed" ); }); @@ -5094,7 +6306,12 @@ fn test_rewards_do_not_auto_compound_on_payment_if_delegation_scheduled_revoke_e assert_events_eq!( Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 500 }, - Event::NewRound { starting_block: 15, round: 4, selected_collators_number: 1, total_balance: 500 }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 1, + total_balance: 500, + }, ); roll_blocks(1); @@ -5143,7 +6360,12 @@ fn test_rewards_auto_compound_on_payment_as_per_auto_compound_config() { assert_events_eq!( Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 900 }, - Event::NewRound { starting_block: 15, round: 4, selected_collators_number: 1, total_balance: 900 }, + Event::NewRound { + starting_block: 15, + round: 4, + selected_collators_number: 1, + total_balance: 900, + }, ); roll_blocks(1); @@ -5246,8 +6468,11 @@ fn test_delegate_with_auto_compound_fails_if_invalid_candidate_auto_compounding_ #[test] fn test_delegate_with_auto_compound_sets_auto_compound_config() { - ExtBuilder::default().with_balances(vec![(1, 30), (2, 25)]).with_candidates(vec![(1, 30)]).build().execute_with( - || { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 25)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { assert_ok!(ParachainStaking::delegate_with_auto_compound( RuntimeOrigin::signed(2), 1, @@ -5268,14 +6493,16 @@ fn test_delegate_with_auto_compound_sets_auto_compound_config() { vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(50) }], ParachainStaking::auto_compounding_delegations(&1).into_inner(), ); - }, - ); + }); } #[test] fn test_delegate_with_auto_compound_skips_storage_but_emits_event_for_zero_auto_compound() { - ExtBuilder::default().with_balances(vec![(1, 30), (2, 10)]).with_candidates(vec![(1, 30)]).build().execute_with( - || { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { assert_ok!(ParachainStaking::delegate_with_auto_compound( RuntimeOrigin::signed(2), 1, @@ -5293,14 +6520,16 @@ fn test_delegate_with_auto_compound_skips_storage_but_emits_event_for_zero_auto_ delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, auto_compound: Percent::zero(), }); - }, - ); + }); } #[test] fn test_delegate_with_auto_compound_reserves_balance() { - ExtBuilder::default().with_balances(vec![(1, 30), (2, 10)]).with_candidates(vec![(1, 30)]).build().execute_with( - || { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); assert_ok!(ParachainStaking::delegate_with_auto_compound( RuntimeOrigin::signed(2), @@ -5312,14 +6541,16 @@ fn test_delegate_with_auto_compound_reserves_balance() { 0, )); assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - }, - ); + }); } #[test] fn test_delegate_with_auto_compound_updates_delegator_state() { - ExtBuilder::default().with_balances(vec![(1, 30), (2, 10)]).with_candidates(vec![(1, 30)]).build().execute_with( - || { + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { assert!(ParachainStaking::delegator_state(2).is_none()); assert_ok!(ParachainStaking::delegate_with_auto_compound( RuntimeOrigin::signed(2), @@ -5330,21 +6561,26 @@ fn test_delegate_with_auto_compound_updates_delegator_state() { 0, 0 )); - let delegator_state = ParachainStaking::delegator_state(2).expect("just delegated => exists"); + let delegator_state = + ParachainStaking::delegator_state(2).expect("just delegated => exists"); assert_eq!(delegator_state.total(), 10); assert_eq!(delegator_state.delegations.0[0].owner, 1); assert_eq!(delegator_state.delegations.0[0].amount, 10); - }, - ); + }); } #[test] fn test_delegate_with_auto_compound_updates_collator_state() { - ExtBuilder::default().with_balances(vec![(1, 30), (2, 10)]).with_candidates(vec![(1, 30)]).build().execute_with( - || { - let candidate_state = ParachainStaking::candidate_info(1).expect("registered in genesis"); + ExtBuilder::default() + .with_balances(vec![(1, 30), (2, 10)]) + .with_candidates(vec![(1, 30)]) + .build() + .execute_with(|| { + let candidate_state = + ParachainStaking::candidate_info(1).expect("registered in genesis"); assert_eq!(candidate_state.total_counted, 30); - let top_delegations = ParachainStaking::top_delegations(1).expect("registered in genesis"); + let top_delegations = + ParachainStaking::top_delegations(1).expect("registered in genesis"); assert!(top_delegations.delegations.is_empty()); assert!(top_delegations.total.is_zero()); assert_ok!(ParachainStaking::delegate_with_auto_compound( @@ -5356,30 +6592,34 @@ fn test_delegate_with_auto_compound_updates_collator_state() { 0, 0 )); - let candidate_state = ParachainStaking::candidate_info(1).expect("just delegated => exists"); + let candidate_state = + ParachainStaking::candidate_info(1).expect("just delegated => exists"); assert_eq!(candidate_state.total_counted, 40); - let top_delegations = ParachainStaking::top_delegations(1).expect("just delegated => exists"); + let top_delegations = + ParachainStaking::top_delegations(1).expect("just delegated => exists"); assert_eq!(top_delegations.delegations[0].owner, 2); assert_eq!(top_delegations.delegations[0].amount, 10); assert_eq!(top_delegations.total, 10); - }, - ); + }); } #[test] fn test_delegate_with_auto_compound_can_delegate_immediately_after_other_join_candidates() { - ExtBuilder::default().with_balances(vec![(1, 20), (2, 20)]).build().execute_with(|| { - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 20, 0)); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 20, - Percent::from_percent(50), - 0, - 0, - 0 - )); - }); + ExtBuilder::default() + .with_balances(vec![(1, 20), (2, 20)]) + .build() + .execute_with(|| { + assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 20, 0)); + assert_ok!(ParachainStaking::delegate_with_auto_compound( + RuntimeOrigin::signed(2), + 1, + 20, + Percent::from_percent(50), + 0, + 0, + 0 + )); + }); } #[test] @@ -5485,7 +6725,11 @@ fn test_delegate_with_auto_compound_can_delegate_if_greater_than_lowest_bottom() 0, 0 )); - assert_events_emitted!(Event::DelegationKicked { delegator: 10, candidate: 1, unstaked_amount: 10 }); + assert_events_emitted!(Event::DelegationKicked { + delegator: 10, + candidate: 1, + unstaked_amount: 10 + }); assert_events_emitted!(Event::DelegatorLeft { delegator: 10, unstaked_amount: 10 }); }); } @@ -5659,9 +6903,11 @@ fn test_on_initialize_weights() { // TODO: this should be the same as >. I believe this relates to // genesis building let num_avg_delegations = 8; - expected_weight += - PalletWeights::::select_top_candidates(>::get(), num_avg_delegations) - .ref_time(); + expected_weight += PalletWeights::::select_top_candidates( + >::get(), + num_avg_delegations, + ) + .ref_time(); // Round and Staked writes, done in on-round-change code block inside on_initialize() expected_weight += RocksDbWeight::get().reads_writes(0, 2).ref_time(); // more reads/writes manually accounted for for on_finalize diff --git a/pallets/parachain-staking/src/traits.rs b/pallets/parachain-staking/src/traits.rs index 746d193e2..2b30b04cc 100644 --- a/pallets/parachain-staking/src/traits.rs +++ b/pallets/parachain-staking/src/traits.rs @@ -19,10 +19,18 @@ use frame_support::pallet_prelude::Weight; pub trait OnCollatorPayout { - fn on_collator_payout(for_round: crate::RoundIndex, collator_id: AccountId, amount: Balance) -> Weight; + fn on_collator_payout( + for_round: crate::RoundIndex, + collator_id: AccountId, + amount: Balance, + ) -> Weight; } impl OnCollatorPayout for () { - fn on_collator_payout(_for_round: crate::RoundIndex, _collator_id: AccountId, _amount: Balance) -> Weight { + fn on_collator_payout( + _for_round: crate::RoundIndex, + _collator_id: AccountId, + _amount: Balance, + ) -> Weight { Weight::zero() } } diff --git a/pallets/parachain-staking/src/types.rs b/pallets/parachain-staking/src/types.rs index 18b98c8c4..1ef686b2f 100644 --- a/pallets/parachain-staking/src/types.rs +++ b/pallets/parachain-staking/src/types.rs @@ -17,9 +17,9 @@ //! Types for parachain-staking use crate::{ - auto_compound::AutoCompoundDelegations, set::OrderedSet, BalanceOf, BottomDelegations, CandidateInfo, Config, - DelegatorState, Error, Event, Pallet, Round, RoundIndex, TopDelegations, Total, COLLATOR_LOCK_ID, - DELEGATOR_LOCK_ID, + auto_compound::AutoCompoundDelegations, set::OrderedSet, BalanceOf, BottomDelegations, + CandidateInfo, Config, DelegatorState, Error, Event, Pallet, Round, RoundIndex, TopDelegations, + Total, COLLATOR_LOCK_ID, DELEGATOR_LOCK_ID, }; use frame_support::{ pallet_prelude::*, @@ -244,11 +244,12 @@ impl Default for Delegations { } } -impl Delegations { +impl + Delegations +{ pub fn sort_greatest_to_least(&mut self) { self.delegations.sort_by(|a, b| b.amount.cmp(&a.amount)); } - /// Insert sorted greatest to least and increase .total accordingly /// Insertion respects first come first serve so new delegations are pushed after existing /// delegations if the amount is the same @@ -282,7 +283,6 @@ impl self.delegations.insert(i, delegation), } } - /// Return the capacity status for top delegations pub fn top_capacity(&self) -> CapacityStatus { match &self.delegations { @@ -291,21 +291,19 @@ impl CapacityStatus::Partial, } } - /// Return the capacity status for bottom delegations pub fn bottom_capacity(&self) -> CapacityStatus { match &self.delegations { - x if x.len() as u32 >= T::MaxBottomDelegationsPerCandidate::get() => CapacityStatus::Full, + x if x.len() as u32 >= T::MaxBottomDelegationsPerCandidate::get() => + CapacityStatus::Full, x if x.is_empty() => CapacityStatus::Empty, _ => CapacityStatus::Partial, } } - /// Return last delegation amount without popping the delegation pub fn lowest_delegation_amount(&self) -> Balance { self.delegations.last().map(|x| x.amount).unwrap_or(Balance::zero()) } - /// Return highest delegation amount pub fn highest_delegation_amount(&self) -> Balance { self.delegations.first().map(|x| x.amount).unwrap_or(Balance::zero()) @@ -373,15 +371,12 @@ impl< status: CollatorStatus::Active, } } - pub fn is_active(&self) -> bool { matches!(self.status, CollatorStatus::Active) } - pub fn is_leaving(&self) -> bool { matches!(self.status, CollatorStatus::Leaving(_)) } - pub fn schedule_leave(&mut self) -> Result<(RoundIndex, RoundIndex), DispatchError> { ensure!(!self.is_leaving(), Error::::CandidateAlreadyLeaving); let now = >::get().current; @@ -389,7 +384,6 @@ impl< self.status = CollatorStatus::Leaving(when); Ok((now, when)) } - pub fn can_leave(&self) -> DispatchResult { if let CollatorStatus::Leaving(when) = self.status { ensure!(>::get().current >= when, Error::::CandidateCannotLeaveYet); @@ -398,20 +392,20 @@ impl< Err(Error::::CandidateNotLeaving.into()) } } - pub fn go_offline(&mut self) { self.status = CollatorStatus::Idle; } - pub fn go_online(&mut self) { self.status = CollatorStatus::Active; } - pub fn bond_more(&mut self, who: T::AccountId, more: Balance) -> DispatchResult where BalanceOf: From, { - ensure!(>::get_collator_stakable_free_balance(&who) >= more.into(), Error::::InsufficientBalance); + ensure!( + >::get_collator_stakable_free_balance(&who) >= more.into(), + Error::::InsufficientBalance + ); let new_total = >::get().saturating_add(more.into()); >::put(new_total); self.bond = self.bond.saturating_add(more); @@ -424,10 +418,12 @@ impl< }); Ok(()) } - /// Schedule executable decrease of collator candidate self bond /// Returns the round at which the collator can execute the pending request - pub fn schedule_bond_less(&mut self, less: Balance) -> Result + pub fn schedule_bond_less( + &mut self, + less: Balance, + ) -> Result where BalanceOf: Into, { @@ -435,12 +431,14 @@ impl< ensure!(self.request.is_none(), Error::::PendingCandidateRequestAlreadyExists); // ensure bond above min after decrease ensure!(self.bond > less, Error::::CandidateBondBelowMin); - ensure!(self.bond - less >= T::MinCandidateStk::get().into(), Error::::CandidateBondBelowMin); + ensure!( + self.bond - less >= T::MinCandidateStk::get().into(), + Error::::CandidateBondBelowMin + ); let when_executable = >::get().current + T::CandidateBondLessDelay::get(); self.request = Some(CandidateBondLessRequest { amount: less, when_executable }); Ok(when_executable) } - /// Execute pending request to decrease the collator self bond /// Returns the event to be emitted pub fn execute_bond_less(&mut self, who: T::AccountId) -> DispatchResult @@ -448,7 +446,10 @@ impl< BalanceOf: From, { let request = self.request.ok_or(Error::::PendingCandidateRequestsDNE)?; - ensure!(request.when_executable <= >::get().current, Error::::PendingCandidateRequestNotDueYet); + ensure!( + request.when_executable <= >::get().current, + Error::::PendingCandidateRequestNotDueYet + ); let new_total_staked = >::get().saturating_sub(request.amount.into()); >::put(new_total_staked); // Arithmetic assumptions are self.bond > less && self.bond - less > CollatorMinBond @@ -470,7 +471,6 @@ impl< Pallet::::deposit_event(event); Ok(()) } - /// Cancel candidate bond less request pub fn cancel_bond_less(&mut self, who: T::AccountId) -> DispatchResult where @@ -486,7 +486,6 @@ impl< Pallet::::deposit_event(event); Ok(()) } - /// Reset top delegations metadata pub fn reset_top_data( &mut self, @@ -506,17 +505,18 @@ impl< Pallet::::update_active(candidate, self.total_counted.into()); } } - /// Reset bottom delegations metadata - pub fn reset_bottom_data(&mut self, bottom_delegations: &Delegations>) - where + pub fn reset_bottom_data( + &mut self, + bottom_delegations: &Delegations>, + ) where BalanceOf: Into, { self.lowest_bottom_delegation_amount = bottom_delegations.lowest_delegation_amount().into(); - self.highest_bottom_delegation_amount = bottom_delegations.highest_delegation_amount().into(); + self.highest_bottom_delegation_amount = + bottom_delegations.highest_delegation_amount().into(); self.bottom_capacity = bottom_delegations.bottom_capacity::(); } - /// Add delegation /// Returns whether delegator was added and an optional negative total counted remainder /// for if a bottom delegation was kicked @@ -561,7 +561,6 @@ impl< }; Ok((delegator_added, less_total_staked)) } - /// Add delegation to top delegation /// Returns Option /// Only call if lowest top delegation is less than delegation.amount || !top_full @@ -574,13 +573,14 @@ impl< BalanceOf: Into + From, { let mut less_total_staked = None; - let mut top_delegations = - >::get(candidate).expect("CandidateInfo existence => TopDelegations existence"); + let mut top_delegations = >::get(candidate) + .expect("CandidateInfo existence => TopDelegations existence"); let max_top_delegations_per_candidate = T::MaxTopDelegationsPerCandidate::get(); if top_delegations.delegations.len() as u32 == max_top_delegations_per_candidate { // pop lowest top delegation let new_bottom_delegation = top_delegations.delegations.pop().expect(""); - top_delegations.total = top_delegations.total.saturating_sub(new_bottom_delegation.amount); + top_delegations.total = + top_delegations.total.saturating_sub(new_bottom_delegation.amount); if matches!(self.bottom_capacity, CapacityStatus::Full) { less_total_staked = Some(self.lowest_bottom_delegation_amount); } @@ -597,7 +597,6 @@ impl< >::insert(candidate, top_delegations); less_total_staked } - /// Add delegation to bottom delegations /// Check before call that if capacity is full, inserted delegation is higher than lowest /// bottom delegation (and if so, need to adjust the total storage item) @@ -610,52 +609,57 @@ impl< ) where BalanceOf: Into + From, { - let mut bottom_delegations = - >::get(candidate).expect("CandidateInfo existence => BottomDelegations existence"); + let mut bottom_delegations = >::get(candidate) + .expect("CandidateInfo existence => BottomDelegations existence"); // if bottom is full, kick the lowest bottom (which is expected to be lower than input // as per check) - let increase_delegation_count = - if bottom_delegations.delegations.len() as u32 == T::MaxBottomDelegationsPerCandidate::get() { - let lowest_bottom_to_be_kicked = bottom_delegations - .delegations - .pop() - .expect("if at full capacity (>0), then >0 bottom delegations exist; qed"); - // EXPECT lowest_bottom_to_be_kicked.amount < delegation.amount enforced by caller - // if lowest_bottom_to_be_kicked.amount == delegation.amount, we will still kick - // the lowest bottom to enforce first come first served - bottom_delegations.total = bottom_delegations.total.saturating_sub(lowest_bottom_to_be_kicked.amount); - // update delegator state - // total staked is updated via propagation of lowest bottom delegation amount prior - // to call - let mut delegator_state = >::get(&lowest_bottom_to_be_kicked.owner) - .expect("Delegation existence => DelegatorState existence"); - let leaving = delegator_state.delegations.0.len() == 1usize; - delegator_state.rm_delegation::(candidate); - >::delegation_remove_request_with_state( - candidate, - &lowest_bottom_to_be_kicked.owner, - &mut delegator_state, - ); - >::remove_auto_compound(candidate, &lowest_bottom_to_be_kicked.owner); + let increase_delegation_count = if bottom_delegations.delegations.len() as u32 == + T::MaxBottomDelegationsPerCandidate::get() + { + let lowest_bottom_to_be_kicked = bottom_delegations + .delegations + .pop() + .expect("if at full capacity (>0), then >0 bottom delegations exist; qed"); + // EXPECT lowest_bottom_to_be_kicked.amount < delegation.amount enforced by caller + // if lowest_bottom_to_be_kicked.amount == delegation.amount, we will still kick + // the lowest bottom to enforce first come first served + bottom_delegations.total = + bottom_delegations.total.saturating_sub(lowest_bottom_to_be_kicked.amount); + // update delegator state + // total staked is updated via propagation of lowest bottom delegation amount prior + // to call + let mut delegator_state = >::get(&lowest_bottom_to_be_kicked.owner) + .expect("Delegation existence => DelegatorState existence"); + let leaving = delegator_state.delegations.0.len() == 1usize; + delegator_state.rm_delegation::(candidate); + >::delegation_remove_request_with_state( + candidate, + &lowest_bottom_to_be_kicked.owner, + &mut delegator_state, + ); + >::remove_auto_compound( + candidate, + &lowest_bottom_to_be_kicked.owner, + ); - Pallet::::deposit_event(Event::DelegationKicked { - delegator: lowest_bottom_to_be_kicked.owner.clone(), - candidate: candidate.clone(), + Pallet::::deposit_event(Event::DelegationKicked { + delegator: lowest_bottom_to_be_kicked.owner.clone(), + candidate: candidate.clone(), + unstaked_amount: lowest_bottom_to_be_kicked.amount, + }); + if leaving { + >::remove(&lowest_bottom_to_be_kicked.owner); + Pallet::::deposit_event(Event::DelegatorLeft { + delegator: lowest_bottom_to_be_kicked.owner, unstaked_amount: lowest_bottom_to_be_kicked.amount, }); - if leaving { - >::remove(&lowest_bottom_to_be_kicked.owner); - Pallet::::deposit_event(Event::DelegatorLeft { - delegator: lowest_bottom_to_be_kicked.owner, - unstaked_amount: lowest_bottom_to_be_kicked.amount, - }); - } else { - >::insert(&lowest_bottom_to_be_kicked.owner, delegator_state); - } - false } else { - !bumped_from_top - }; + >::insert(&lowest_bottom_to_be_kicked.owner, delegator_state); + } + false + } else { + !bumped_from_top + }; // only increase delegation count if new bottom delegation (1) doesn't come from top && // (2) doesn't pop the lowest delegation from the bottom if increase_delegation_count { @@ -665,7 +669,6 @@ impl< self.reset_bottom_data::(&bottom_delegations); >::insert(candidate, bottom_delegations); } - /// Remove delegation /// Removes from top if amount is above lowest top or top is not full /// Return Ok(if_total_counted_changed) @@ -680,7 +683,8 @@ impl< { let amount_geq_lowest_top = amount >= self.lowest_top_delegation_amount; let top_is_not_full = !matches!(self.top_capacity, CapacityStatus::Full); - let lowest_top_eq_highest_bottom = self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; + let lowest_top_eq_highest_bottom = + self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); if top_is_not_full || (amount_geq_lowest_top && !lowest_top_eq_highest_bottom) { self.rm_top_delegation::(candidate, delegator) @@ -696,7 +700,6 @@ impl< self.rm_bottom_delegation::(candidate, delegator) } } - /// Remove top delegation, bumps top bottom delegation if exists pub fn rm_top_delegation( &mut self, @@ -708,8 +711,8 @@ impl< { let old_total_counted = self.total_counted; // remove top delegation - let mut top_delegations = - >::get(candidate).expect("CandidateInfo exists => TopDelegations exists"); + let mut top_delegations = >::get(candidate) + .expect("CandidateInfo exists => TopDelegations exists"); let mut actual_amount_option: Option> = None; top_delegations.delegations = top_delegations .delegations @@ -732,7 +735,8 @@ impl< >::get(candidate).expect("bottom is nonempty as just checked"); // expect already stored greatest to least by bond amount let highest_bottom_delegation = bottom_delegations.delegations.remove(0); - bottom_delegations.total = bottom_delegations.total.saturating_sub(highest_bottom_delegation.amount); + bottom_delegations.total = + bottom_delegations.total.saturating_sub(highest_bottom_delegation.amount); self.reset_bottom_data::(&bottom_delegations); >::insert(candidate, bottom_delegations); // insert highest bottom into top delegations @@ -745,7 +749,6 @@ impl< // return whether total counted changed Ok(old_total_counted == self.total_counted) } - /// Remove bottom delegation /// Returns if_total_counted_changed: bool pub fn rm_bottom_delegation( @@ -757,8 +760,8 @@ impl< BalanceOf: Into, { // remove bottom delegation - let mut bottom_delegations = - >::get(candidate).expect("CandidateInfo exists => BottomDelegations exists"); + let mut bottom_delegations = >::get(candidate) + .expect("CandidateInfo exists => BottomDelegations exists"); let mut actual_amount_option: Option> = None; bottom_delegations.delegations = bottom_delegations .delegations @@ -781,7 +784,6 @@ impl< >::insert(candidate, bottom_delegations); Ok(false) } - /// Increase delegation amount pub fn increase_delegation( &mut self, @@ -793,7 +795,8 @@ impl< where BalanceOf: Into + From, { - let lowest_top_eq_highest_bottom = self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; + let lowest_top_eq_highest_bottom = + self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; let bond_geq_lowest_top = bond.into() >= self.lowest_top_delegation_amount; let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); if bond_geq_lowest_top && !lowest_top_eq_highest_bottom { @@ -812,7 +815,6 @@ impl< self.increase_bottom_delegation::(candidate, delegator, bond, more) } } - /// Increase top delegation pub fn increase_top_delegation( &mut self, @@ -823,8 +825,8 @@ impl< where BalanceOf: Into + From, { - let mut top_delegations = - >::get(candidate).expect("CandidateInfo exists => TopDelegations exists"); + let mut top_delegations = >::get(candidate) + .expect("CandidateInfo exists => TopDelegations exists"); let mut in_top = false; top_delegations.delegations = top_delegations .delegations @@ -847,7 +849,6 @@ impl< >::insert(candidate, top_delegations); Ok(true) } - /// Increase bottom delegation pub fn increase_bottom_delegation( &mut self, @@ -859,9 +860,11 @@ impl< where BalanceOf: Into + From, { - let mut bottom_delegations = >::get(candidate).ok_or(Error::::CandidateDNE)?; + let mut bottom_delegations = + >::get(candidate).ok_or(Error::::CandidateDNE)?; let mut delegation_option: Option>> = None; - let in_top_after = if (bond.saturating_add(more)).into() > self.lowest_top_delegation_amount { + let in_top_after = if (bond.saturating_add(more)).into() > self.lowest_top_delegation_amount + { // bump it from bottom bottom_delegations.delegations = bottom_delegations .delegations @@ -871,8 +874,10 @@ impl< if d.owner != delegator { true } else { - delegation_option = - Some(Bond { owner: d.owner.clone(), amount: d.amount.saturating_add(more) }); + delegation_option = Some(Bond { + owner: d.owner.clone(), + amount: d.amount.saturating_add(more), + }); false } }) @@ -880,14 +885,17 @@ impl< let delegation = delegation_option.ok_or(Error::::DelegationDNE)?; bottom_delegations.total = bottom_delegations.total.saturating_sub(bond); // add it to top - let mut top_delegations = - >::get(candidate).expect("CandidateInfo existence => TopDelegations existence"); + let mut top_delegations = >::get(candidate) + .expect("CandidateInfo existence => TopDelegations existence"); // if top is full, pop lowest top if matches!(top_delegations.top_capacity::(), CapacityStatus::Full) { // pop lowest top delegation - let new_bottom_delegation = - top_delegations.delegations.pop().expect("Top capacity full => Exists at least 1 top delegation"); - top_delegations.total = top_delegations.total.saturating_sub(new_bottom_delegation.amount); + let new_bottom_delegation = top_delegations + .delegations + .pop() + .expect("Top capacity full => Exists at least 1 top delegation"); + top_delegations.total = + top_delegations.total.saturating_sub(new_bottom_delegation.amount); bottom_delegations.insert_sorted_greatest_to_least(new_bottom_delegation); } // insert into top @@ -920,7 +928,6 @@ impl< >::insert(candidate, bottom_delegations); Ok(in_top_after) } - /// Decrease delegation pub fn decrease_delegation( &mut self, @@ -932,7 +939,8 @@ impl< where BalanceOf: Into + From, { - let lowest_top_eq_highest_bottom = self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; + let lowest_top_eq_highest_bottom = + self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; let bond_geq_lowest_top = bond >= self.lowest_top_delegation_amount; let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); if bond_geq_lowest_top && !lowest_top_eq_highest_bottom { @@ -941,7 +949,8 @@ impl< } else if bond_geq_lowest_top && lowest_top_eq_highest_bottom { // update top but if error then update bottom (because could be in bottom because // lowest_top_eq_highest_bottom) - let result = self.decrease_top_delegation::(candidate, delegator.clone(), bond.into(), less); + let result = + self.decrease_top_delegation::(candidate, delegator.clone(), bond.into(), less); if result == Err(delegation_dne_err) { self.decrease_bottom_delegation::(candidate, delegator, less) } else { @@ -951,7 +960,6 @@ impl< self.decrease_bottom_delegation::(candidate, delegator, less) } } - /// Decrease top delegation pub fn decrease_top_delegation( &mut self, @@ -968,9 +976,10 @@ impl< let bond_after_less_than_highest_bottom = bond.saturating_sub(less).into() < self.highest_bottom_delegation_amount; // The top delegations is full and the bottom delegations has at least one delegation - let full_top_and_nonempty_bottom = - matches!(self.top_capacity, CapacityStatus::Full) && !matches!(self.bottom_capacity, CapacityStatus::Empty); - let mut top_delegations = >::get(candidate).ok_or(Error::::CandidateDNE)?; + let full_top_and_nonempty_bottom = matches!(self.top_capacity, CapacityStatus::Full) && + !matches!(self.bottom_capacity, CapacityStatus::Empty); + let mut top_delegations = + >::get(candidate).ok_or(Error::::CandidateDNE)?; let in_top_after = if bond_after_less_than_highest_bottom && full_top_and_nonempty_bottom { let mut delegation_option: Option>> = None; // take delegation from top @@ -983,18 +992,21 @@ impl< true } else { top_delegations.total = top_delegations.total.saturating_sub(d.amount); - delegation_option = - Some(Bond { owner: d.owner.clone(), amount: d.amount.saturating_sub(less) }); + delegation_option = Some(Bond { + owner: d.owner.clone(), + amount: d.amount.saturating_sub(less), + }); false } }) .collect(); let delegation = delegation_option.ok_or(Error::::DelegationDNE)?; // pop highest bottom by reverse and popping - let mut bottom_delegations = - >::get(candidate).expect("CandidateInfo existence => BottomDelegations existence"); + let mut bottom_delegations = >::get(candidate) + .expect("CandidateInfo existence => BottomDelegations existence"); let highest_bottom_delegation = bottom_delegations.delegations.remove(0); - bottom_delegations.total = bottom_delegations.total.saturating_sub(highest_bottom_delegation.amount); + bottom_delegations.total = + bottom_delegations.total.saturating_sub(highest_bottom_delegation.amount); // insert highest bottom into top top_delegations.insert_sorted_greatest_to_least(highest_bottom_delegation); // insert previous top into bottom @@ -1027,7 +1039,6 @@ impl< >::insert(candidate, top_delegations); Ok(in_top_after) } - /// Decrease bottom delegation pub fn decrease_bottom_delegation( &mut self, @@ -1038,8 +1049,8 @@ impl< where BalanceOf: Into, { - let mut bottom_delegations = - >::get(candidate).expect("CandidateInfo exists => BottomDelegations exists"); + let mut bottom_delegations = >::get(candidate) + .expect("CandidateInfo exists => BottomDelegations exists"); let mut in_bottom = false; bottom_delegations.delegations = bottom_delegations .delegations @@ -1107,7 +1118,12 @@ pub enum DelegatorAdded { impl< A: Ord + Clone + sp_std::fmt::Debug, - B: AtLeast32BitUnsigned + Ord + Copy + sp_std::ops::AddAssign + sp_std::ops::SubAssign + sp_std::fmt::Debug, + B: AtLeast32BitUnsigned + + Ord + + Copy + + sp_std::ops::AddAssign + + sp_std::ops::SubAssign + + sp_std::fmt::Debug, > CollatorCandidate { pub fn is_active(&self) -> bool { @@ -1122,7 +1138,11 @@ impl From> for CollatorSnapshot delegations: other .top_delegations .into_iter() - .map(|d| BondWithAutoCompound { owner: d.owner, amount: d.amount, auto_compound: Percent::zero() }) + .map(|d| BondWithAutoCompound { + owner: d.owner, + amount: d.amount, + auto_compound: Percent::zero(), + }) .collect(), total: other.total_counted, } @@ -1261,7 +1281,6 @@ impl< false } } - // Return Some(remaining balance), must be more than MinDelegatorStk // Return None if delegation not found pub fn rm_delegation(&mut self, collator: &AccountId) -> Option @@ -1316,7 +1335,8 @@ impl< self.adjust_bond_lock::(BondAdjust::Increase(amount))?; // update collator state delegation - let mut collator_state = >::get(&candidate_id).ok_or(Error::::CandidateDNE)?; + let mut collator_state = + >::get(&candidate_id).ok_or(Error::::CandidateDNE)?; let before = collator_state.total_counted; let in_top = collator_state.increase_delegation::( &candidate_id, @@ -1347,7 +1367,10 @@ impl< /// `additional_required_balance` should reflect the change to the amount that should be locked if /// positive, 0 otherwise (e.g. `min(0, change_in_total_bond)`). This is necessary because it is /// not possible to query the amount that is locked for a given lock id. - pub fn adjust_bond_lock(&mut self, additional_required_balance: BondAdjust) -> DispatchResult + pub fn adjust_bond_lock( + &mut self, + additional_required_balance: BondAdjust, + ) -> DispatchResult where BalanceOf: From, T::AccountId: From, @@ -1355,7 +1378,8 @@ impl< match additional_required_balance { BondAdjust::Increase(amount) => { ensure!( - >::get_delegator_stakable_free_balance(&self.id.clone().into()) >= amount.into(), + >::get_delegator_stakable_free_balance(&self.id.clone().into()) >= + amount.into(), Error::::InsufficientBalance, ); @@ -1425,7 +1449,11 @@ pub mod deprecated { impl Default for PendingDelegationRequests { fn default() -> PendingDelegationRequests { - PendingDelegationRequests { revocations_count: 0u32, requests: BTreeMap::new(), less_total: B::zero() } + PendingDelegationRequests { + revocations_count: 0u32, + requests: BTreeMap::new(), + less_total: B::zero(), + } } } @@ -1549,24 +1577,26 @@ pub struct RoundInfo { /// The length of the current round in number of blocks pub length: u32, } -impl + sp_std::ops::Sub + From + PartialOrd> RoundInfo { +impl< + B: Copy + sp_std::ops::Add + sp_std::ops::Sub + From + PartialOrd, + > RoundInfo +{ pub fn new(current: RoundIndex, first: B, length: u32) -> RoundInfo { RoundInfo { current, first, length } } - /// Check if the round should be updated pub fn should_update(&self, now: B) -> bool { now - self.first >= self.length.into() } - /// New round pub fn update(&mut self, now: B) { self.current = self.current.saturating_add(1u32); self.first = now; } } -impl + sp_std::ops::Sub + From + PartialOrd> Default - for RoundInfo +impl< + B: Copy + sp_std::ops::Add + sp_std::ops::Sub + From + PartialOrd, + > Default for RoundInfo { fn default() -> RoundInfo { RoundInfo::new(1u32, 1u32.into(), 20u32) diff --git a/pallets/sandbox/src/lib.rs b/pallets/sandbox/src/lib.rs index 202b411d4..a5e2961ec 100644 --- a/pallets/sandbox/src/lib.rs +++ b/pallets/sandbox/src/lib.rs @@ -34,7 +34,8 @@ pub mod pallet { let retail_user = ensure_signed(origin)?; let project_id: ::ProjectIdentifier = project_id.into(); // Check project is in the community round - let project_info = funding::Pallet::::project_info(project_id).ok_or(Error::::ProjectNotFound)?; + let project_info = funding::Pallet::::project_info(project_id) + .ok_or(Error::::ProjectNotFound)?; ensure!( project_info.project_status == funding::ProjectStatus::CommunityRound, "Project is not in the community round" @@ -42,11 +43,12 @@ pub mod pallet { // Calculate how much funding was done already let project_contributions: ::Balance = - funding::Contributions::::iter_prefix_values(project_id) - .flatten() - .fold(0u64.into(), |total_tokens_bought, contribution| { + funding::Contributions::::iter_prefix_values(project_id).flatten().fold( + 0u64.into(), + |total_tokens_bought, contribution| { total_tokens_bought + contribution.contribution_amount - }); + }, + ); ensure!( project_contributions >= 500_000_0_000_000_000u64.into(), diff --git a/pallets/sandbox/src/mock.rs b/pallets/sandbox/src/mock.rs index b94682855..4bcc626da 100644 --- a/pallets/sandbox/src/mock.rs +++ b/pallets/sandbox/src/mock.rs @@ -61,30 +61,30 @@ parameter_types! { } impl system::Config for TestRuntime { - type AccountData = pallet_balances::AccountData; - type AccountId = AccountId; type BaseCallFilter = frame_support::traits::Everything; - type BlockHashCount = BlockHashCount; + type BlockWeights = (); type BlockLength = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = u64; type BlockNumber = BlockNumber; - type BlockWeights = (); - type DbWeight = (); type Hash = H256; type Hashing = BlakeTwo256; - type Header = Header; - type Index = u64; + type AccountId = AccountId; type Lookup = IdentityLookup; - type MaxConsumers = frame_support::traits::ConstU32<16>; - type OnKilledAccount = (); - type OnNewAccount = (); - type OnSetCode = (); - type PalletInfo = PalletInfo; - type RuntimeCall = RuntimeCall; + type Header = Header; type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; - type SS58Prefix = ConstU16<42>; - type SystemWeightInfo = (); + type BlockHashCount = BlockHashCount; + type DbWeight = (); type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = ConstU16<42>; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } parameter_types! { @@ -92,44 +92,44 @@ parameter_types! { } impl pallet_balances::Config for TestRuntime { - type AccountStore = System; - type Balance = Balance; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type FreezeIdentifier = pallet_funding::BondType; - type HoldIdentifier = pallet_funding::BondType; - type MaxFreezes = (); - type MaxHolds = (); type MaxLocks = frame_support::traits::ConstU32<1024>; type MaxReserves = frame_support::traits::ConstU32<1024>; type ReserveIdentifier = pallet_funding::BondType; + type Balance = Balance; type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; type WeightInfo = (); + type HoldIdentifier = pallet_funding::BondType; + type FreezeIdentifier = pallet_funding::BondType; + type MaxHolds = (); + type MaxFreezes = (); } impl pallet_insecure_randomness_collective_flip::Config for TestRuntime {} impl pallet_assets::Config for TestRuntime { - type ApprovalDeposit = ConstU128<1>; - type AssetAccountDeposit = ConstU128<10>; - type AssetDeposit = ConstU128<1>; - type AssetId = Identifier; - type AssetIdParameter = Identifier; + type RuntimeEvent = RuntimeEvent; type Balance = Balance; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); - type CallbackHandle = (); - type CreateOrigin = AsEnsureOriginWithArg>; + type AssetId = Identifier; type Currency = Balances; - type Extra = (); type ForceOrigin = frame_system::EnsureRoot; - type Freezer = (); + type AssetDeposit = ConstU128<1>; + type AssetAccountDeposit = ConstU128<10>; type MetadataDepositBase = ConstU128<1>; type MetadataDepositPerByte = ConstU128<1>; - type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; - type RuntimeEvent = RuntimeEvent; + type ApprovalDeposit = ConstU128<1>; type StringLimit = ConstU32<50>; + type Freezer = (); type WeightInfo = (); + type Extra = (); + type AssetIdParameter = Identifier; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); } // REMARK: In the production configuration we use DAYS instead of HOURS. @@ -144,33 +144,33 @@ parameter_types! { } impl pallet_funding::Config for TestRuntime { - type AuctionInitializePeriodDuration = AuctionInitializePeriodDuration; - type Balance = Balance; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); + type RuntimeEvent = RuntimeEvent; + type StringLimit = ConstU32<64>; + type ProjectIdentifier = Identifier; + type ProjectIdParameter = Identifier; type BidId = u128; - type CandleAuctionDuration = CandleAuctionDuration; - type CommunityFundingDuration = CommunityRoundDuration; type ContributionTokenCurrency = Assets; - type ContributionVesting = ConstU32<4>; - type EnglishAuctionDuration = EnglishAuctionDuration; type EvaluationDuration = EvaluationDuration; - type FundingCurrency = Balances; - type MaxContributionsPerUser = ConstU32<4>; + type AuctionInitializePeriodDuration = AuctionInitializePeriodDuration; + type EnglishAuctionDuration = EnglishAuctionDuration; + type CandleAuctionDuration = CandleAuctionDuration; + type RemainderFundingDuration = RemainderFundingDuration; + type PalletId = FundingPalletId; type MaxProjectsToUpdatePerBlock = ConstU32<100>; + type CommunityFundingDuration = CommunityRoundDuration; + type Randomness = RandomnessCollectiveFlip; + type PreImageLimit = ConstU32<1024>; // Low value to simplify the tests type MaximumBidsPerUser = ConstU32<4>; + type MaxContributionsPerUser = ConstU32<4>; + type ContributionVesting = ConstU32<4>; + type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); type Multiplier = pallet_funding::types::Multiplier; + type Balance = Balance; type NativeCurrency = Balances; - type PalletId = FundingPalletId; - type PreImageLimit = ConstU32<1024>; - type ProjectIdParameter = Identifier; - type ProjectIdentifier = Identifier; - type Randomness = RandomnessCollectiveFlip; - type RemainderFundingDuration = RemainderFundingDuration; - type RuntimeEvent = RuntimeEvent; - type StringLimit = ConstU32<64>; - type WeightInfo = (); + type FundingCurrency = Balances; } // Build genesis storage according to the mock runtime. diff --git a/pallets/sandbox/src/tests.rs b/pallets/sandbox/src/tests.rs index 8545884e9..52ee116a2 100644 --- a/pallets/sandbox/src/tests.rs +++ b/pallets/sandbox/src/tests.rs @@ -19,7 +19,11 @@ fn test_buy_if_popular() { let project = default_project(0); assert_ok!(FundingModule::create(RuntimeOrigin::signed(creator), project.clone(),)); assert_ok!(FundingModule::start_evaluation(RuntimeOrigin::signed(creator), 0)); - assert_ok!(FundingModule::bond_evaluation(RuntimeOrigin::signed(evaluator), 0, 120_000 * PLMC)); + assert_ok!(FundingModule::bond_evaluation( + RuntimeOrigin::signed(evaluator), + 0, + 120_000 * PLMC + )); // advance time for _block in 0..::EvaluationDuration::get() + 10 { @@ -72,7 +76,9 @@ const METADATA: &str = r#" "usage_of_founds":"ipfs_url" }"#; -pub fn default_project(nonce: u64) -> ProjectMetadata>, u128, sp_core::H256> { +pub fn default_project( + nonce: u64, +) -> ProjectMetadata>, u128, sp_core::H256> { let bounded_name = BoundedVec::try_from("Contribution Token TEST".as_bytes().to_vec()).unwrap(); let bounded_symbol = BoundedVec::try_from("CTEST".as_bytes().to_vec()).unwrap(); let metadata_hash = hashed(format!("{}-{}", METADATA, nonce)); @@ -85,7 +91,11 @@ pub fn default_project(nonce: u64) -> ProjectMetadata sp_io::TestExternalities { GenesisConfig { balances: BalancesConfig { - balances: vec![(1, 1_000_000 * PLMC), (2, 1_000_000 * PLMC), (3, 1_000_000 * PLMC), (4, 10_000_000 * PLMC)], + balances: vec![ + (1, 1_000_000 * PLMC), + (2, 1_000_000 * PLMC), + (3, 1_000_000 * PLMC), + (4, 10_000_000 * PLMC), + ], }, ..Default::default() } diff --git a/runtimes/base/build.rs b/runtimes/base/build.rs index 657bcc0d1..b81f7762c 100644 --- a/runtimes/base/build.rs +++ b/runtimes/base/build.rs @@ -17,5 +17,9 @@ use substrate_wasm_builder::WasmBuilder; fn main() { - WasmBuilder::new().with_current_project().export_heap_base().import_memory().build() + WasmBuilder::new() + .with_current_project() + .export_heap_base() + .import_memory() + .build() } diff --git a/runtimes/base/src/lib.rs b/runtimes/base/src/lib.rs index d4884e971..701846e13 100644 --- a/runtimes/base/src/lib.rs +++ b/runtimes/base/src/lib.rs @@ -37,7 +37,10 @@ use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; pub use sp_runtime::BuildStorage; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, OpaqueKeys, Verify}, + traits::{ + AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, OpaqueKeys, + Verify, + }, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, MultiSignature, }; @@ -109,14 +112,20 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = - frame_executive::Executive, Runtime, AllPalletsWithSystem>; +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPalletsWithSystem, +>; /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know /// the specifics of the runtime. They can then be made to be agnostic over specific formats @@ -167,103 +176,103 @@ parameter_types! { // Configure FRAME pallets to include in runtime. impl frame_system::Config for Runtime { - /// The data to be stored in an account. - type AccountData = pallet_balances::AccountData; /// The identifier used to distinguish between accounts. type AccountId = AccountId; - /// The basic call filter to use in dispatchable. - type BaseCallFilter = Everything; - /// Maximum number of block number to block hash mappings to keep (oldest pruned first). - type BlockHashCount = BlockHashCount; - /// The maximum length of a block (in bytes). - type BlockLength = RuntimeBlockLength; + /// The aggregated dispatch type that is available for extrinsics. + type RuntimeCall = RuntimeCall; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = AccountIdLookup; + /// The index type for storing how many extrinsics an account has signed. + type Index = Index; /// The index type for blocks. type BlockNumber = BlockNumber; - /// Block & extrinsics weights: base values and limits. - type BlockWeights = RuntimeBlockWeights; - /// The weight of database operations that the runtime can invoke. - type DbWeight = RocksDbWeight; /// The type for hashing blocks and tries. type Hash = Hash; /// The hashing algorithm used. type Hashing = BlakeTwo256; /// The header type. type Header = generic::Header; - /// The index type for storing how many extrinsics an account has signed. - type Index = Index; - /// The lookup mechanism to get account ID from whatever is passed in dispatchers. - type Lookup = AccountIdLookup; - type MaxConsumers = frame_support::traits::ConstU32<16>; - /// What to do if an account is fully reaped from the system. - type OnKilledAccount = (); - /// What to do if a new account is created. - type OnNewAccount = (); - /// The action to take on a Runtime Upgrade - type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; - /// Converts a module to an index of this module in the runtime. - type PalletInfo = PalletInfo; - /// The aggregated dispatch type that is available for extrinsics. - type RuntimeCall = RuntimeCall; /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; /// The ubiquitous origin type. type RuntimeOrigin = RuntimeOrigin; - /// This is used as an identifier of the chain. 42 is the generic substrate prefix. - type SS58Prefix = SS58Prefix; - /// Weight information for the extrinsics of this pallet. - type SystemWeightInfo = (); + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; /// Runtime version. type Version = Version; + /// Converts a module to an index of this module in the runtime. + type PalletInfo = PalletInfo; + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; + /// What to do if a new account is created. + type OnNewAccount = (); + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; + /// The basic call filter to use in dispatchable. + type BaseCallFilter = Everything; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = (); + /// Block & extrinsics weights: base values and limits. + type BlockWeights = RuntimeBlockWeights; + /// The maximum length of a block (in bytes). + type BlockLength = RuntimeBlockLength; + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = SS58Prefix; + /// The action to take on a Runtime Upgrade + type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_timestamp::Config for Runtime { - type MinimumPeriod = MinimumPeriod; /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; + type MinimumPeriod = MinimumPeriod; type WeightInfo = (); } impl pallet_authorship::Config for Runtime { - type EventHandler = ParachainStaking; type FindAuthor = pallet_session::FindAccountFromAuthorIndex; + type EventHandler = ParachainStaking; } impl pallet_balances::Config for Runtime { - type AccountStore = System; + type MaxLocks = MaxLocks; type Balance = Balance; + type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; - type FreezeIdentifier = (); - type HoldIdentifier = (); - type MaxFreezes = MaxReserves; - type MaxHolds = MaxLocks; - type MaxLocks = MaxLocks; + type AccountStore = System; type MaxReserves = MaxReserves; + type MaxHolds = MaxLocks; + type MaxFreezes = MaxReserves; + type HoldIdentifier = (); + type FreezeIdentifier = (); type ReserveIdentifier = [u8; 8]; - type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } impl pallet_transaction_payment::Config for Runtime { - type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; - type LengthToFee = ConstantMultiplier; + type RuntimeEvent = RuntimeEvent; type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type OperationalFeeMultiplier = frame_support::traits::ConstU8<5>; - type RuntimeEvent = RuntimeEvent; type WeightToFee = WeightToFee; + type LengthToFee = ConstantMultiplier; + type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; } impl cumulus_pallet_parachain_system::Config for Runtime { - type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; - type DmpMessageHandler = DmpQueue; + type RuntimeEvent = RuntimeEvent; type OnSystemEvent = (); + type SelfParaId = parachain_info::Pallet; type OutboundXcmpMessageSource = XcmpQueue; + type DmpMessageHandler = DmpQueue; type ReservedDmpWeight = ReservedDmpWeight; - type ReservedXcmpWeight = ReservedXcmpWeight; - type RuntimeEvent = RuntimeEvent; - type SelfParaId = parachain_info::Pallet; type XcmpMessageHandler = XcmpQueue; + type ReservedXcmpWeight = ReservedXcmpWeight; + type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; } impl parachain_info::Config for Runtime {} @@ -271,32 +280,32 @@ impl parachain_info::Config for Runtime {} impl cumulus_pallet_aura_ext::Config for Runtime {} impl cumulus_pallet_xcmp_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; type ChannelInfo = ParachainSystem; + type VersionWrapper = (); + type ExecuteOverweightOrigin = EnsureRoot; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; - type ExecuteOverweightOrigin = EnsureRoot; - type PriceForSiblingDelivery = (); - type RuntimeEvent = RuntimeEvent; - type VersionWrapper = (); type WeightInfo = (); - type XcmExecutor = XcmExecutor; + type PriceForSiblingDelivery = (); } impl cumulus_pallet_dmp_queue::Config for Runtime { - type ExecuteOverweightOrigin = EnsureRoot; type RuntimeEvent = RuntimeEvent; type XcmExecutor = XcmExecutor; + type ExecuteOverweightOrigin = EnsureRoot; } impl pallet_session::Config for Runtime { - type Keys = SessionKeys; - type NextSessionRotation = ParachainStaking; type RuntimeEvent = RuntimeEvent; - type SessionHandler = ::KeyTypeIdProviders; - type SessionManager = ParachainStaking; - type ShouldEndSession = ParachainStaking; type ValidatorId = AccountId; type ValidatorIdOf = ConvertInto; + type ShouldEndSession = ParachainStaking; + type NextSessionRotation = ParachainStaking; + type SessionManager = ParachainStaking; + type SessionHandler = ::KeyTypeIdProviders; + type Keys = SessionKeys; type WeightInfo = (); } @@ -312,27 +321,27 @@ impl pallet_sudo::Config for Runtime { } impl pallet_parachain_staking::Config for Runtime { - type CandidateBondLessDelay = CandidateBondLessDelay; + type RuntimeEvent = RuntimeEvent; type Currency = Balances; - type DelegationBondLessDelay = DelegationBondLessDelay; + type MonetaryGovernanceOrigin = frame_system::EnsureRoot; + type MinBlocksPerRound = MinBlocksPerRound; type LeaveCandidatesDelay = LeaveCandidatesDelay; + type CandidateBondLessDelay = CandidateBondLessDelay; type LeaveDelegatorsDelay = LeaveDelegatorsDelay; + type RevokeDelegationDelay = RevokeDelegationDelay; + type DelegationBondLessDelay = DelegationBondLessDelay; + type RewardPaymentDelay = RewardPaymentDelay; + type MinSelectedCandidates = MinSelectedCandidates; + type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate; type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator; - type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; - type MinBlocksPerRound = MinBlocksPerRound; type MinCandidateStk = MinCandidateStk; - type MinDelegation = MinDelegation; type MinDelegatorStk = MinDelegatorStk; - type MinSelectedCandidates = MinSelectedCandidates; - type MonetaryGovernanceOrigin = frame_system::EnsureRoot; + type MinDelegation = MinDelegation; type OnCollatorPayout = (); - type OnNewRound = (); // We use the default implementation, so we leave () here. type PayoutCollatorReward = (); - type RevokeDelegationDelay = RevokeDelegationDelay; - type RewardPaymentDelay = RewardPaymentDelay; - type RuntimeEvent = RuntimeEvent; + type OnNewRound = (); type WeightInfo = pallet_parachain_staking::weights::SubstrateWeight; } @@ -589,15 +598,17 @@ impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { block: &Block, relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, ) -> sp_inherents::CheckInherentsResult { - let relay_chain_slot = - relay_state_proof.read_slot().expect("Could not read the relay chain slot from the proof"); - - let inherent_data = cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( - relay_chain_slot, - sp_std::time::Duration::from_secs(6), - ) - .create_inherent_data() - .expect("Could not create the timestamp inherent data"); + let relay_chain_slot = relay_state_proof + .read_slot() + .expect("Could not read the relay chain slot from the proof"); + + let inherent_data = + cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( + relay_chain_slot, + sp_std::time::Duration::from_secs(6), + ) + .create_inherent_data() + .expect("Could not create the timestamp inherent data"); inherent_data.check_extrinsics(block) } diff --git a/runtimes/base/src/xcm_config.rs b/runtimes/base/src/xcm_config.rs index 5f7ae306e..ab1307a1b 100644 --- a/runtimes/base/src/xcm_config.rs +++ b/runtimes/base/src/xcm_config.rs @@ -15,8 +15,8 @@ // along with this program. If not, see . use super::{ - AccountId, AllPalletsWithSystem, Balances, EnsureRoot, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, - RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, + AccountId, AllPalletsWithSystem, Balances, EnsureRoot, ParachainInfo, ParachainSystem, + PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, }; use frame_support::{ match_types, parameter_types, @@ -29,10 +29,11 @@ use polkadot_parachain::primitives::Sibling; use polkadot_runtime_common::impls::ToAuthor; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, - EnsureXcmOrigin, FixedWeightBounds, IsConcrete, NativeAsset, ParentIsPreset, RelayChainAsNative, - SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, WithComputedOrigin, + AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowTopLevelPaidExecutionFrom, + CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, IsConcrete, NativeAsset, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + UsingComponents, WithComputedOrigin, }; use xcm_executor::XcmExecutor; @@ -122,31 +123,32 @@ pub type Barrier = DenyThenTry< pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { - type AssetClaims = PolkadotXcm; - type AssetExchanger = (); - type AssetLocker = (); + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; // How to withdraw and deposit an asset. type AssetTransactor = LocalAssetTransactor; - type AssetTrap = PolkadotXcm; - type Barrier = Barrier; - type CallDispatcher = RuntimeCall; - type FeeManager = (); + type OriginConverter = XcmOriginToTransactDispatchOrigin; type IsReserve = NativeAsset; type IsTeleporter = (); - type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type MessageExporter = (); - type OriginConverter = XcmOriginToTransactDispatchOrigin; - type PalletInstancesInfo = AllPalletsWithSystem; - type ResponseHandler = PolkadotXcm; - type RuntimeCall = RuntimeCall; - type SafeCallFilter = Everything; - type SubscriptionService = PolkadotXcm; - type Trader = UsingComponents>; - type UniversalAliases = Nothing; // Teleporting is disabled. type UniversalLocation = UniversalLocation; + type Barrier = Barrier; type Weigher = FixedWeightBounds; - type XcmSender = XcmRouter; + type Trader = + UsingComponents>; + type ResponseHandler = PolkadotXcm; + type AssetTrap = PolkadotXcm; + type AssetClaims = PolkadotXcm; + type SubscriptionService = PolkadotXcm; + type PalletInstancesInfo = AllPalletsWithSystem; + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type AssetLocker = (); + type AssetExchanger = (); + type FeeManager = (); + type MessageExporter = (); + type UniversalAliases = Nothing; + type CallDispatcher = RuntimeCall; + type SafeCallFilter = Everything; } /// No local origins on this chain are allowed to dispatch XCM sends/executions. @@ -168,32 +170,32 @@ parameter_types! { impl pallet_xcm::Config for Runtime { type AdminOrigin = EnsureRoot; - // ^ Override for AdvertisedXcmVersion default - type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; - type Currency = Balances; - type CurrencyMatcher = (); - type ExecuteXcmOrigin = EnsureXcmOrigin; - type MaxLockers = ConstU32<8>; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; type SendXcmOrigin = EnsureXcmOrigin; - type SovereignAccountOf = LocationToAccountId; - type TrustedLockers = (); - type UniversalLocation = UniversalLocation; - type Weigher = FixedWeightBounds; - type WeightInfo = pallet_xcm::TestWeightInfo; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; type XcmExecuteFilter = Nothing; // ^ Disable dispatchable execute on the XCM pallet. // Needs to be `Everything` for local testing. type XcmExecutor = XcmExecutor; - type XcmReserveTransferFilter = Nothing; - type XcmRouter = XcmRouter; type XcmTeleportFilter = Everything; + type XcmReserveTransferFilter = Nothing; + type Weigher = FixedWeightBounds; + type UniversalLocation = UniversalLocation; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + // ^ Override for AdvertisedXcmVersion default + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; + type Currency = Balances; + type CurrencyMatcher = (); + type TrustedLockers = (); + type SovereignAccountOf = LocationToAccountId; + type MaxLockers = ConstU32<8>; + type WeightInfo = pallet_xcm::TestWeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/runtimes/shared-configuration/src/fee.rs b/runtimes/shared-configuration/src/fee.rs index a95a31252..2fd88b717 100644 --- a/runtimes/shared-configuration/src/fee.rs +++ b/runtimes/shared-configuration/src/fee.rs @@ -17,7 +17,10 @@ use crate::{currency::MILLI_PLMC, Balance}; use frame_support::{ parameter_types, - weights::{constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}, + weights::{ + constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients, + WeightToFeePolynomial, + }, }; use parachains_common::SLOT_DURATION; use smallvec::smallvec; @@ -26,7 +29,6 @@ use sp_arithmetic::Perbill; pub struct WeightToFee; impl WeightToFeePolynomial for WeightToFee { type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { // extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: let p = 10 * MILLI_PLMC; diff --git a/runtimes/shared-configuration/src/weights/block_weights.rs b/runtimes/shared-configuration/src/weights/block_weights.rs index b17b64afc..f24090fb4 100644 --- a/runtimes/shared-configuration/src/weights/block_weights.rs +++ b/runtimes/shared-configuration/src/weights/block_weights.rs @@ -43,7 +43,10 @@ pub mod constants { "Weight should be at least 100 µs." ); // At most 50 ms. - assert!(w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 50 ms."); + assert!( + w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, + "Weight should be at most 50 ms." + ); } } } diff --git a/runtimes/shared-configuration/src/weights/extrinsic_weights.rs b/runtimes/shared-configuration/src/weights/extrinsic_weights.rs index 5aabc4cdb..465a4c5fe 100644 --- a/runtimes/shared-configuration/src/weights/extrinsic_weights.rs +++ b/runtimes/shared-configuration/src/weights/extrinsic_weights.rs @@ -38,9 +38,15 @@ pub mod constants { let w = super::constants::ExtrinsicBaseWeight::get(); // At least 10 µs. - assert!(w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, "Weight should be at least 10 µs."); + assert!( + w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, + "Weight should be at least 10 µs." + ); // At most 1 ms. - assert!(w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 1 ms."); + assert!( + w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, + "Weight should be at most 1 ms." + ); } } } diff --git a/runtimes/standalone/build.rs b/runtimes/standalone/build.rs index 657bcc0d1..b81f7762c 100644 --- a/runtimes/standalone/build.rs +++ b/runtimes/standalone/build.rs @@ -17,5 +17,9 @@ use substrate_wasm_builder::WasmBuilder; fn main() { - WasmBuilder::new().with_current_project().export_heap_base().import_memory().build() + WasmBuilder::new() + .with_current_project() + .export_heap_base() + .import_memory() + .build() } diff --git a/runtimes/standalone/src/lib.rs b/runtimes/standalone/src/lib.rs index a419de698..646c294fe 100644 --- a/runtimes/standalone/src/lib.rs +++ b/runtimes/standalone/src/lib.rs @@ -25,11 +25,13 @@ extern crate frame_benchmarking; pub use frame_support::{ construct_runtime, parameter_types, traits::{ - ConstU128, ConstU32, ConstU64, ConstU8, Contains, EitherOfDiverse, EqualPrivilegeOnly, KeyOwnerProofSystem, - Randomness, StorageInfo, WithdrawReasons, + ConstU128, ConstU32, ConstU64, ConstU8, Contains, EitherOfDiverse, EqualPrivilegeOnly, + KeyOwnerProofSystem, Randomness, StorageInfo, WithdrawReasons, }, weights::{ - constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND}, + constants::{ + BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND, + }, IdentityFee, Weight, }, PalletId, StorageValue, @@ -51,7 +53,8 @@ pub use sp_runtime::BuildStorage; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{ - AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, NumberFor, One, OpaqueKeys, Verify, + AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, NumberFor, + One, OpaqueKeys, Verify, }, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, MultiSignature, @@ -199,55 +202,55 @@ parameter_types! { // Configure FRAME pallets to include in runtime. impl frame_system::Config for Runtime { - /// The data to be stored in an account. - type AccountData = pallet_balances::AccountData; - /// The identifier used to distinguish between accounts. - type AccountId = AccountId; /// The basic call filter to use in dispatchable. type BaseCallFilter = frame_support::traits::Everything; - /// Maximum number of block number to block hash mappings to keep (oldest pruned first). - type BlockHashCount = BlockHashCount; + /// Block & extrinsics weights: base values and limits. + type BlockWeights = BlockWeights; /// The maximum length of a block (in bytes). type BlockLength = BlockLength; + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The aggregated dispatch type that is available for extrinsics. + type RuntimeCall = RuntimeCall; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = AccountIdLookup; + /// The index type for storing how many extrinsics an account has signed. + type Index = Index; /// The index type for blocks. type BlockNumber = BlockNumber; - /// Block & extrinsics weights: base values and limits. - type BlockWeights = BlockWeights; - /// The weight of database operations that the runtime can invoke. - type DbWeight = RocksDbWeight; /// The type for hashing blocks and tries. type Hash = Hash; /// The hashing algorithm used. type Hashing = BlakeTwo256; /// The header type. type Header = generic::Header; - /// The index type for storing how many extrinsics an account has signed. - type Index = Index; - /// The lookup mechanism to get account ID from whatever is passed in dispatchers. - type Lookup = AccountIdLookup; - type MaxConsumers = frame_support::traits::ConstU32<16>; - /// What to do if an account is fully reaped from the system. - type OnKilledAccount = (); - /// What to do if a new account is created. - type OnNewAccount = (); - /// The set code logic, just the default since we're not a parachain. - type OnSetCode = (); - /// Converts a module to the index of the module in `construct_runtime!`. - /// - /// This type is being generated by `construct_runtime!`. - type PalletInfo = PalletInfo; - /// The aggregated dispatch type that is available for extrinsics. - type RuntimeCall = RuntimeCall; /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; /// The ubiquitous origin type. type RuntimeOrigin = RuntimeOrigin; - /// This is used as an identifier of the chain. 42 is the generic substrate prefix. - type SS58Prefix = SS58Prefix; - /// Weight information for the extrinsics of this pallet. - type SystemWeightInfo = (); + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; /// Version of the runtime. type Version = Version; + /// Converts a module to the index of the module in `construct_runtime!`. + /// + /// This type is being generated by `construct_runtime!`. + type PalletInfo = PalletInfo; + /// What to do if a new account is created. + type OnNewAccount = (); + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = (); + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = SS58Prefix; + /// The set code logic, just the default since we're not a parachain. + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_insecure_randomness_collective_flip::Config for Runtime {} @@ -259,34 +262,36 @@ impl pallet_aura::Config for Runtime { } impl pallet_grandpa::Config for Runtime { - type EquivocationReportSystem = (); - type KeyOwnerProof = sp_core::Void; - type MaxAuthorities = ConstU32<32>; - type MaxSetIdSessionEntries = ConstU64<0>; type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); + type MaxAuthorities = ConstU32<32>; + type MaxSetIdSessionEntries = ConstU64<0>; + + type KeyOwnerProof = sp_core::Void; + type EquivocationReportSystem = (); } impl pallet_timestamp::Config for Runtime { - type MinimumPeriod = MinimumPeriod; type Moment = u64; type OnTimestampSet = Aura; + type MinimumPeriod = MinimumPeriod; type WeightInfo = (); } impl pallet_balances::Config for Runtime { - type AccountStore = System; + type MaxLocks = MaxLocks; type Balance = Balance; + type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; - type FreezeIdentifier = (); - type HoldIdentifier = (); - type MaxFreezes = MaxReserves; - type MaxHolds = MaxLocks; - type MaxLocks = MaxLocks; + type AccountStore = System; type MaxReserves = MaxReserves; + type MaxHolds = MaxLocks; + type MaxFreezes = MaxReserves; + type HoldIdentifier = (); + type FreezeIdentifier = (); type ReserveIdentifier = BondType; - type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } @@ -295,40 +300,40 @@ parameter_types! { } impl pallet_transaction_payment::Config for Runtime { - type FeeMultiplierUpdate = ConstFeeMultiplier; - type LengthToFee = IdentityFee; + type RuntimeEvent = RuntimeEvent; type OnChargeTransaction = CurrencyAdapter; type OperationalFeeMultiplier = ConstU8<5>; - type RuntimeEvent = RuntimeEvent; type WeightToFee = IdentityFee; + type LengthToFee = IdentityFee; + type FeeMultiplierUpdate = ConstFeeMultiplier; } impl pallet_sudo::Config for Runtime { - type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; } impl pallet_assets::Config for Runtime { - type ApprovalDeposit = ExistentialDeposit; - type AssetAccountDeposit = AssetAccountDeposit; - type AssetDeposit = AssetDeposit; + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; type AssetId = u32; type AssetIdParameter = parity_scale_codec::Compact; - type Balance = Balance; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); - type CallbackHandle = (); - type CreateOrigin = AsEnsureOriginWithArg>; type Currency = Balances; - type Extra = (); + type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = EnsureRoot; - type Freezer = (); + type AssetDeposit = AssetDeposit; type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; - type RuntimeEvent = RuntimeEvent; + type ApprovalDeposit = ExistentialDeposit; type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); type WeightInfo = (); + type CallbackHandle = (); + type AssetAccountDeposit = AssetAccountDeposit; + type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); } parameter_types! { @@ -343,45 +348,45 @@ parameter_types! { } impl pallet_funding::Config for Runtime { - type AuctionInitializePeriodDuration = AuctionInitializePeriodDuration; + type RuntimeEvent = RuntimeEvent; + type ProjectIdentifier = u32; + type ProjectIdParameter = parity_scale_codec::Compact; + type Multiplier = FundingMultiplier; type Balance = Balance; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); + type NativeCurrency = Balances; + type FundingCurrency = Balances; + type ContributionTokenCurrency = Assets; type BidId = u128; + type Randomness = Random; + type StringLimit = ConstU32<64>; + type PreImageLimit = ConstU32<1024>; + type EvaluationDuration = EvaluationDuration; + type AuctionInitializePeriodDuration = AuctionInitializePeriodDuration; + type EnglishAuctionDuration = EnglishAuctionDuration; type CandleAuctionDuration = CandleAuctionDuration; type CommunityFundingDuration = CommunityRoundDuration; - type ContributionTokenCurrency = Assets; - type ContributionVesting = ContributionVestingDuration; - type EnglishAuctionDuration = EnglishAuctionDuration; - type EvaluationDuration = EvaluationDuration; - type FundingCurrency = Balances; - type MaxContributionsPerUser = ConstU32<64>; + type RemainderFundingDuration = RemainderFundingDuration; + type PalletId = FundingPalletId; type MaxProjectsToUpdatePerBlock = ConstU32<100>; type MaximumBidsPerUser = ConstU32<256>; - type Multiplier = FundingMultiplier; - type NativeCurrency = Balances; - type PalletId = FundingPalletId; - type PreImageLimit = ConstU32<1024>; - type ProjectIdParameter = parity_scale_codec::Compact; - type ProjectIdentifier = u32; - type Randomness = Random; - type RemainderFundingDuration = RemainderFundingDuration; - type RuntimeEvent = RuntimeEvent; - type StringLimit = ConstU32<64>; + type MaxContributionsPerUser = ConstU32<64>; + type ContributionVesting = ContributionVestingDuration; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); type WeightInfo = (); } impl pallet_scheduler::Config for Runtime { - type MaxScheduledPerBlock = (); - type MaximumWeight = (); - type OriginPrivilegeCmp = EqualPrivilegeOnly; - type PalletsOrigin = OriginCaller; - type Preimages = (); - type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; + type PalletsOrigin = OriginCaller; + type RuntimeCall = RuntimeCall; + type MaximumWeight = (); type ScheduleOrigin = EnsureRoot; + type MaxScheduledPerBlock = (); type WeightInfo = (); + type OriginPrivilegeCmp = EqualPrivilegeOnly; + type Preimages = (); } parameter_types! { @@ -392,16 +397,16 @@ parameter_types! { type CouncilCollective = pallet_collective::Instance1; impl pallet_collective::Config for Runtime { - type DefaultVote = pallet_collective::PrimeDefaultVote; - type MaxMembers = CouncilMaxMembers; - type MaxProposalWeight = MaxCollectivesProposalWeight; - type MaxProposals = CouncilMaxProposals; - type MotionDuration = CouncilMotionDuration; + type RuntimeOrigin = RuntimeOrigin; type Proposal = RuntimeCall; type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; - type SetMembersOrigin = EnsureRoot; + type MotionDuration = CouncilMotionDuration; + type MaxProposals = CouncilMaxProposals; + type MaxMembers = CouncilMaxMembers; + type DefaultVote = pallet_collective::PrimeDefaultVote; type WeightInfo = pallet_collective::weights::SubstrateWeight; + type SetMembersOrigin = EnsureRoot; + type MaxProposalWeight = MaxCollectivesProposalWeight; } parameter_types! { @@ -412,16 +417,16 @@ parameter_types! { type TechnicalCollective = pallet_collective::Instance2; impl pallet_collective::Config for Runtime { - type DefaultVote = pallet_collective::PrimeDefaultVote; - type MaxMembers = TechnicalMaxMembers; - type MaxProposalWeight = MaxCollectivesProposalWeight; - type MaxProposals = TechnicalMaxProposals; - type MotionDuration = TechnicalMotionDuration; + type RuntimeOrigin = RuntimeOrigin; type Proposal = RuntimeCall; type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; - type SetMembersOrigin = EnsureRoot; + type MotionDuration = TechnicalMotionDuration; + type MaxProposals = TechnicalMaxProposals; + type MaxMembers = TechnicalMaxMembers; + type DefaultVote = pallet_collective::PrimeDefaultVote; type WeightInfo = pallet_collective::weights::SubstrateWeight; + type SetMembersOrigin = EnsureRoot; + type MaxProposalWeight = MaxCollectivesProposalWeight; } parameter_types! { @@ -438,50 +443,55 @@ parameter_types! { } impl pallet_democracy::Config for Runtime { - type BlacklistOrigin = EnsureRoot; - // To cancel a proposal before it has been passed, the technical committee must be unanimous or - // Root must agree. - type CancelProposalOrigin = EitherOfDiverse< - EnsureRoot, - pallet_collective::EnsureProportionAtLeast, - >; - // To cancel a proposal which has been passed, 2/3 of the council must agree to it. - type CancellationOrigin = pallet_collective::EnsureProportionAtLeast; - type CooloffPeriod = CooloffPeriod; + type RuntimeEvent = RuntimeEvent; type Currency = Balances; type EnactmentPeriod = EnactmentPeriod; + type LaunchPeriod = LaunchPeriod; + type VotingPeriod = VotingPeriod; + type VoteLockingPeriod = EnactmentPeriod; // Same as EnactmentPeriod + type MinimumDeposit = MinimumDeposit; + /// A straight majority of the council can decide what their next motion is. + type ExternalOrigin = + pallet_collective::EnsureProportionAtLeast; + /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. + type ExternalMajorityOrigin = + pallet_collective::EnsureProportionAtLeast; /// A unanimous council can have the next scheduled referendum be a straight default-carries /// (NTB) vote. - type ExternalDefaultOrigin = pallet_collective::EnsureProportionAtLeast; - /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. - type ExternalMajorityOrigin = pallet_collective::EnsureProportionAtLeast; - /// A straight majority of the council can decide what their next motion is. - type ExternalOrigin = pallet_collective::EnsureProportionAtLeast; + type ExternalDefaultOrigin = + pallet_collective::EnsureProportionAtLeast; /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote /// be tabled immediately and with a shorter voting/enactment period. - type FastTrackOrigin = pallet_collective::EnsureProportionAtLeast; - type FastTrackVotingPeriod = FastTrackVotingPeriod; + type FastTrackOrigin = + pallet_collective::EnsureProportionAtLeast; + type InstantOrigin = + pallet_collective::EnsureProportionAtLeast; type InstantAllowed = frame_support::traits::ConstBool; - type InstantOrigin = pallet_collective::EnsureProportionAtLeast; - type LaunchPeriod = LaunchPeriod; - type MaxBlacklisted = (); - type MaxDeposits = (); - type MaxProposals = MaxProposals; - type MaxVotes = ConstU32<100>; - // Same as EnactmentPeriod - type MinimumDeposit = MinimumDeposit; - type PalletsOrigin = OriginCaller; - type Preimages = (); - type RuntimeEvent = RuntimeEvent; - type Scheduler = Scheduler; - type Slash = (); - type SubmitOrigin = EnsureSigned; + type FastTrackVotingPeriod = FastTrackVotingPeriod; + // To cancel a proposal which has been passed, 2/3 of the council must agree to it. + type CancellationOrigin = + pallet_collective::EnsureProportionAtLeast; + // To cancel a proposal before it has been passed, the technical committee must be unanimous or + // Root must agree. + type CancelProposalOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionAtLeast, + >; + type BlacklistOrigin = EnsureRoot; // Any single technical committee member may veto a coming council proposal, however they can // only do it once and it lasts only for the cool-off period. type VetoOrigin = pallet_collective::EnsureMember; - type VoteLockingPeriod = EnactmentPeriod; - type VotingPeriod = VotingPeriod; + type CooloffPeriod = CooloffPeriod; + type Slash = (); + type Scheduler = Scheduler; + type PalletsOrigin = OriginCaller; + type MaxVotes = ConstU32<100>; type WeightInfo = pallet_democracy::weights::SubstrateWeight; + type MaxProposals = MaxProposals; + type Preimages = (); + type MaxDeposits = (); + type MaxBlacklisted = (); + type SubmitOrigin = EnsureSigned; } parameter_types! { @@ -490,14 +500,14 @@ parameter_types! { } impl pallet_session::Config for Runtime { - type Keys = opaque::SessionKeys; - type NextSessionRotation = (); type RuntimeEvent = RuntimeEvent; - type SessionHandler = ::KeyTypeIdProviders; - type SessionManager = (); - type ShouldEndSession = pallet_session::PeriodicSessions; type ValidatorId = AccountId; type ValidatorIdOf = (); + type ShouldEndSession = pallet_session::PeriodicSessions; + type NextSessionRotation = (); + type SessionManager = (); + type SessionHandler = ::KeyTypeIdProviders; + type Keys = opaque::SessionKeys; type WeightInfo = (); } @@ -506,8 +516,8 @@ parameter_types! { } impl pallet_authorship::Config for Runtime { - type EventHandler = (); type FindAuthor = pallet_session::FindAccountFromAuthorIndex; + type EventHandler = (); } parameter_types! { @@ -519,19 +529,19 @@ parameter_types! { } impl pallet_multisig::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; type Currency = Balances; type DepositBase = DepositBase; type DepositFactor = DepositFactor; type MaxSignatories = MaxSignatories; - type RuntimeCall = RuntimeCall; - type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } impl pallet_utility::Config for Runtime { - type PalletsOrigin = OriginCaller; - type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PalletsOrigin = OriginCaller; type WeightInfo = (); } @@ -543,13 +553,12 @@ parameter_types! { } impl pallet_vesting::Config for Runtime { - type BlockNumberToBalance = ConvertInto; + type RuntimeEvent = RuntimeEvent; type Currency = Balances; + type BlockNumberToBalance = ConvertInto; type MinVestedTransfer = MinVestedTransfer; - type RuntimeEvent = RuntimeEvent; - type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; type WeightInfo = pallet_vesting::weights::SubstrateWeight; - + type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; // `VestingInfo` encode length is 36bytes. 28 schedules gets encoded as 1009 bytes, which is the // highest number of schedules that encodes less than 2^10. const MAX_VESTING_SCHEDULES: u32 = 28; @@ -612,12 +621,18 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic; /// The payload being signed in transactions. pub type SignedPayload = generic::SignedPayload; /// Executive: handles dispatch to the various modules. -pub type Executive = - frame_executive::Executive, Runtime, AllPalletsWithSystem>; +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPalletsWithSystem, +>; #[cfg(feature = "runtime-benchmarks")] mod benches { @@ -876,14 +891,24 @@ mod tests { .collect(); // Block Number - assert!(whitelist.contains("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac")); + assert!( + whitelist.contains("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac") + ); // Total Issuance - assert!(whitelist.contains("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80")); + assert!( + whitelist.contains("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80") + ); // Execution Phase - assert!(whitelist.contains("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a")); + assert!( + whitelist.contains("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a") + ); // Event Count - assert!(whitelist.contains("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850")); + assert!( + whitelist.contains("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850") + ); // System Events - assert!(whitelist.contains("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7")); + assert!( + whitelist.contains("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7") + ); } } diff --git a/runtimes/testnet/build.rs b/runtimes/testnet/build.rs index 657bcc0d1..b81f7762c 100644 --- a/runtimes/testnet/build.rs +++ b/runtimes/testnet/build.rs @@ -17,5 +17,9 @@ use substrate_wasm_builder::WasmBuilder; fn main() { - WasmBuilder::new().with_current_project().export_heap_base().import_memory().build() + WasmBuilder::new() + .with_current_project() + .export_heap_base() + .import_memory() + .build() } diff --git a/runtimes/testnet/src/lib.rs b/runtimes/testnet/src/lib.rs index 5455833ef..d1b240b85 100644 --- a/runtimes/testnet/src/lib.rs +++ b/runtimes/testnet/src/lib.rs @@ -25,14 +25,16 @@ extern crate frame_benchmarking; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use frame_support::{ construct_runtime, parameter_types, - traits::{AsEnsureOriginWithArg, ConstU32, Currency, EitherOfDiverse, EqualPrivilegeOnly, Everything}, + traits::{ + AsEnsureOriginWithArg, ConstU32, Currency, EitherOfDiverse, EqualPrivilegeOnly, Everything, + }, weights::{ConstantMultiplier, Weight}, }; use frame_system::{EnsureRoot, EnsureSigned}; pub use parachains_common::{ - impls::DealWithFees, opaque, AccountId, AssetIdForTrustBackedAssets as AssetId, AuraId, Balance, BlockNumber, Hash, - Header, Index, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, MAXIMUM_BLOCK_WEIGHT, MINUTES, - NORMAL_DISPATCH_RATIO, SLOT_DURATION, + impls::DealWithFees, opaque, AccountId, AssetIdForTrustBackedAssets as AssetId, AuraId, + Balance, BlockNumber, Hash, Header, Index, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, + MAXIMUM_BLOCK_WEIGHT, MINUTES, NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; // Polkadot imports @@ -76,8 +78,9 @@ pub use shared_configuration::{ weights::*, }; -pub type NegativeImbalanceOf = - as Currency<::AccountId>>::NegativeImbalance; +pub type NegativeImbalanceOf = as Currency< + ::AccountId, +>>::NegativeImbalance; /// The address format for describing accounts. pub type Address = MultiAddress; @@ -104,14 +107,20 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = - frame_executive::Executive, Runtime, AllPalletsWithSystem>; +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPalletsWithSystem, +>; impl_opaque_keys! { pub struct SessionKeys { @@ -145,101 +154,106 @@ parameter_types! { // Configure FRAME pallets to include in runtime. impl frame_system::Config for Runtime { - /// The data to be stored in an account. - type AccountData = pallet_balances::AccountData; - /// The identifier used to distinguish between accounts. - type AccountId = AccountId; /// The basic call filter to use in dispatchable. type BaseCallFilter = Everything; - /// Maximum number of block number to block hash mappings to keep (oldest pruned first). - type BlockHashCount = BlockHashCount; + /// Block & extrinsics weights: base values and limits. + type BlockWeights = RuntimeBlockWeights; /// The maximum length of a block (in bytes). type BlockLength = RuntimeBlockLength; + /// The ubiquitous origin type. + type RuntimeOrigin = RuntimeOrigin; + /// The aggregated dispatch type that is available for extrinsics. + type RuntimeCall = RuntimeCall; + /// The index type for storing how many extrinsics an account has signed. + type Index = Index; /// The index type for blocks. type BlockNumber = BlockNumber; - /// Block & extrinsics weights: base values and limits. - type BlockWeights = RuntimeBlockWeights; - /// The weight of database operations that the runtime can invoke. - type DbWeight = RocksDbWeight; /// The type for hashing blocks and tries. type Hash = Hash; /// The hashing algorithm used. type Hashing = BlakeTwo256; - /// The header type. - type Header = Header; - /// The index type for storing how many extrinsics an account has signed. - type Index = Index; + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; /// The lookup mechanism to get account ID from whatever is passed in dispatchers. type Lookup = AccountIdLookup; - type MaxConsumers = frame_support::traits::ConstU32<16>; - /// What to do if an account is fully reaped from the system. - type OnKilledAccount = (); - /// What to do if a new account is created. - type OnNewAccount = (); - /// The action to take on a Runtime Upgrade - type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; - /// Converts a module to an index of this module in the runtime. - type PalletInfo = PalletInfo; - /// The aggregated dispatch type that is available for extrinsics. - type RuntimeCall = RuntimeCall; + /// The header type. + type Header = Header; /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; - /// The ubiquitous origin type. - type RuntimeOrigin = RuntimeOrigin; - /// This is used as an identifier of the chain. 42 is the generic substrate prefix. - type SS58Prefix = SS58Prefix; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; + /// Runtime version. + type Version = Version; + /// Converts a module to an index of this module in the runtime. + type PalletInfo = PalletInfo; + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; + /// What to do if a new account is created. + type OnNewAccount = (); + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); /// Weight information for the extrinsics of this pallet. /// weights::frame_system::WeightInfo; type SystemWeightInfo = (); - /// Runtime version. - type Version = Version; + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = SS58Prefix; + /// The action to take on a Runtime Upgrade + type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; + type MaxConsumers = frame_support::traits::ConstU32<16>; } impl pallet_timestamp::Config for Runtime { - type MinimumPeriod = MinimumPeriod; /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; + type MinimumPeriod = MinimumPeriod; type WeightInfo = (); } impl pallet_authorship::Config for Runtime { - type EventHandler = (ParachainStaking,); type FindAuthor = pallet_session::FindAccountFromAuthorIndex; + type EventHandler = (ParachainStaking,); } impl pallet_balances::Config for Runtime { - type AccountStore = System; + type MaxLocks = MaxLocks; type Balance = Balance; + type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; - type FreezeIdentifier = (); - type HoldIdentifier = (); - type MaxFreezes = MaxReserves; - type MaxHolds = MaxLocks; - type MaxLocks = MaxLocks; + type AccountStore = System; type MaxReserves = MaxReserves; + type MaxHolds = MaxLocks; + type MaxFreezes = MaxReserves; + type HoldIdentifier = (); + type FreezeIdentifier = (); type ReserveIdentifier = BondType; - type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } impl pallet_transaction_payment::Config for Runtime { - type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; - type LengthToFee = ConstantMultiplier; + type RuntimeEvent = RuntimeEvent; type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type OperationalFeeMultiplier = frame_support::traits::ConstU8<5>; - type RuntimeEvent = RuntimeEvent; type WeightToFee = WeightToFee; + type LengthToFee = ConstantMultiplier; + type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; } impl pallet_asset_tx_payment::Config for Runtime { + type RuntimeEvent = RuntimeEvent; type Fungibles = StatemintAssets; type OnChargeAssetTransaction = pallet_asset_tx_payment::FungiblesAdapter< - pallet_assets::BalanceToAssetBalance, + pallet_assets::BalanceToAssetBalance< + Balances, + Runtime, + ConvertInto, + StatemintAssetsInstance, + >, xcm_config::AssetsToBlockAuthor, >; - type RuntimeEvent = RuntimeEvent; } impl pallet_sudo::Config for Runtime { @@ -248,15 +262,15 @@ impl pallet_sudo::Config for Runtime { } impl cumulus_pallet_parachain_system::Config for Runtime { - type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; - type DmpMessageHandler = DmpQueue; - type OnSystemEvent = (); - type OutboundXcmpMessageSource = XcmpQueue; - type ReservedDmpWeight = ReservedDmpWeight; - type ReservedXcmpWeight = ReservedXcmpWeight; type RuntimeEvent = RuntimeEvent; + type OnSystemEvent = (); type SelfParaId = ParachainInfo; + type DmpMessageHandler = DmpQueue; + type ReservedDmpWeight = ReservedDmpWeight; + type OutboundXcmpMessageSource = XcmpQueue; type XcmpMessageHandler = XcmpQueue; + type ReservedXcmpWeight = ReservedXcmpWeight; + type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; } impl parachain_info::Config for Runtime {} @@ -264,32 +278,32 @@ impl parachain_info::Config for Runtime {} impl cumulus_pallet_aura_ext::Config for Runtime {} impl cumulus_pallet_xcmp_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; type ChannelInfo = ParachainSystem; + type VersionWrapper = PolkadotXcm; + type ExecuteOverweightOrigin = EnsureRoot; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = xcm_config::XcmOriginToTransactDispatchOrigin; - type ExecuteOverweightOrigin = EnsureRoot; type PriceForSiblingDelivery = (); - type RuntimeEvent = RuntimeEvent; - type VersionWrapper = PolkadotXcm; type WeightInfo = (); - type XcmExecutor = XcmExecutor; } impl cumulus_pallet_dmp_queue::Config for Runtime { - type ExecuteOverweightOrigin = EnsureRoot; type RuntimeEvent = RuntimeEvent; type XcmExecutor = XcmExecutor; + type ExecuteOverweightOrigin = EnsureRoot; } impl pallet_session::Config for Runtime { - type Keys = SessionKeys; - type NextSessionRotation = ParachainStaking; type RuntimeEvent = RuntimeEvent; - type SessionHandler = ::KeyTypeIdProviders; - type SessionManager = ParachainStaking; - type ShouldEndSession = ParachainStaking; type ValidatorId = ::AccountId; type ValidatorIdOf = ConvertInto; + type ShouldEndSession = ParachainStaking; + type NextSessionRotation = ParachainStaking; + type SessionManager = ParachainStaking; + type SessionHandler = ::KeyTypeIdProviders; + type Keys = SessionKeys; type WeightInfo = (); } @@ -302,84 +316,122 @@ impl pallet_aura::Config for Runtime { impl pallet_insecure_randomness_collective_flip::Config for Runtime {} impl pallet_funding::Config for Runtime { - type AuctionInitializePeriodDuration = AuctionInitializePeriodDuration; + type RuntimeEvent = RuntimeEvent; + type ProjectIdentifier = u32; + type ProjectIdParameter = parity_scale_codec::Compact; + type Multiplier = FundingMultiplier; type Balance = Balance; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); + type NativeCurrency = Balances; + type FundingCurrency = Balances; + type ContributionTokenCurrency = LocalAssets; type BidId = u128; + type Randomness = Random; + type StringLimit = ConstU32<64>; + type PreImageLimit = ConstU32<1024>; + type EvaluationDuration = EvaluationDuration; + type AuctionInitializePeriodDuration = AuctionInitializePeriodDuration; + type EnglishAuctionDuration = EnglishAuctionDuration; type CandleAuctionDuration = CandleAuctionDuration; type CommunityFundingDuration = CommunityFundingDuration; - type ContributionTokenCurrency = LocalAssets; - type ContributionVesting = ContributionVestingDuration; - type EnglishAuctionDuration = EnglishAuctionDuration; - type EvaluationDuration = EvaluationDuration; - type FundingCurrency = Balances; - type MaxContributionsPerUser = ConstU32<256>; + type RemainderFundingDuration = RemainderFundingDuration; + type PalletId = FundingPalletId; type MaxProjectsToUpdatePerBlock = ConstU32<100>; type MaximumBidsPerUser = ConstU32<256>; - type Multiplier = FundingMultiplier; - type NativeCurrency = Balances; - type PalletId = FundingPalletId; - type PreImageLimit = ConstU32<1024>; - type ProjectIdParameter = parity_scale_codec::Compact; - type ProjectIdentifier = u32; - type Randomness = Random; - type RemainderFundingDuration = RemainderFundingDuration; - type RuntimeEvent = RuntimeEvent; - type StringLimit = ConstU32<64>; + + type MaxContributionsPerUser = ConstU32<256>; + type ContributionVesting = ContributionVestingDuration; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); type WeightInfo = (); } impl pallet_treasury::Config for Runtime { + type Currency = Balances; // TODO: Use the Council instead of Root! type ApproveOrigin = EnsureRoot; - type Burn = Burn; - type BurnDestination = (); - type Currency = Balances; - type MaxApprovals = MaxApprovals; + type RejectOrigin = EnsureRoot; + type RuntimeEvent = RuntimeEvent; type OnSlash = Treasury; - type PalletId = TreasuryId; type ProposalBond = ProposalBond; - type ProposalBondMaximum = (); type ProposalBondMinimum = ProposalBondMinimum; - type RejectOrigin = EnsureRoot; - type RuntimeEvent = RuntimeEvent; - type SpendFunds = (); - type SpendOrigin = frame_support::traits::NeverEnsureOrigin; + type ProposalBondMaximum = (); type SpendPeriod = SpendPeriod; + type Burn = Burn; + type PalletId = TreasuryId; + type BurnDestination = (); type WeightInfo = (); + type SpendFunds = (); + type MaxApprovals = MaxApprovals; + type SpendOrigin = frame_support::traits::NeverEnsureOrigin; } // TODO: VERY BASIC implementation, more work needed type CouncilCollective = pallet_collective::Instance1; impl pallet_collective::Config for Runtime { - type DefaultVote = pallet_collective::PrimeDefaultVote; - type MaxMembers = CouncilMaxMembers; - type MaxProposalWeight = MaxCollectivesProposalWeight; - type MaxProposals = CouncilMaxProposals; - type MotionDuration = CouncilMotionDuration; + type RuntimeOrigin = RuntimeOrigin; type Proposal = RuntimeCall; type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; - type SetMembersOrigin = EnsureRoot; + type MotionDuration = CouncilMotionDuration; + type MaxProposals = CouncilMaxProposals; + type MaxMembers = CouncilMaxMembers; + type DefaultVote = pallet_collective::PrimeDefaultVote; type WeightInfo = pallet_collective::weights::SubstrateWeight; + type SetMembersOrigin = EnsureRoot; + type MaxProposalWeight = MaxCollectivesProposalWeight; } type TechnicalCollective = pallet_collective::Instance2; impl pallet_collective::Config for Runtime { - type DefaultVote = pallet_collective::PrimeDefaultVote; - type MaxMembers = TechnicalMaxMembers; - type MaxProposalWeight = MaxCollectivesProposalWeight; - type MaxProposals = TechnicalMaxProposals; - type MotionDuration = TechnicalMotionDuration; + type RuntimeOrigin = RuntimeOrigin; type Proposal = RuntimeCall; type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; - type SetMembersOrigin = EnsureRoot; + type MotionDuration = TechnicalMotionDuration; + type MaxProposals = TechnicalMaxProposals; + type MaxMembers = TechnicalMaxMembers; + type DefaultVote = pallet_collective::PrimeDefaultVote; type WeightInfo = pallet_collective::weights::SubstrateWeight; + type SetMembersOrigin = EnsureRoot; + type MaxProposalWeight = MaxCollectivesProposalWeight; } impl pallet_democracy::Config for Runtime { + type WeightInfo = pallet_democracy::weights::SubstrateWeight; + type RuntimeEvent = RuntimeEvent; + type Scheduler = Scheduler; + type Preimages = Preimage; + type Currency = Balances; + type EnactmentPeriod = EnactmentPeriod; + type LaunchPeriod = LaunchPeriod; + type VotingPeriod = VotingPeriod; + type VoteLockingPeriod = EnactmentPeriod; + // Same as EnactmentPeriod + type MinimumDeposit = MinimumDeposit; + type InstantAllowed = frame_support::traits::ConstBool; + type FastTrackVotingPeriod = FastTrackVotingPeriod; + type CooloffPeriod = CooloffPeriod; + type MaxVotes = ConstU32<128>; + type MaxProposals = MaxProposals; + type MaxDeposits = (); + type MaxBlacklisted = (); + /// A straight majority of the council can decide what their next motion is. + type ExternalOrigin = + pallet_collective::EnsureProportionAtLeast; + /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. + type ExternalMajorityOrigin = + pallet_collective::EnsureProportionAtLeast; + /// A unanimous council can have the next scheduled referendum be a straight default-carries + /// (NTB) vote. + type ExternalDefaultOrigin = + pallet_collective::EnsureProportionAtLeast; + /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote + /// be tabled immediately and with a shorter voting/enactment period. + type FastTrackOrigin = + pallet_collective::EnsureProportionAtLeast; + type InstantOrigin = + pallet_collective::EnsureProportionAtLeast; + // To cancel a proposal which has been passed, 2/3 of the council must agree to it. + type CancellationOrigin = + pallet_collective::EnsureProportionAtLeast; type BlacklistOrigin = EnsureRoot; // To cancel a proposal before it has been passed, the technical committee must be unanimous or // Root must agree. @@ -387,168 +439,136 @@ impl pallet_democracy::Config for Runtime { EnsureRoot, pallet_collective::EnsureProportionAtLeast, >; - // To cancel a proposal which has been passed, 2/3 of the council must agree to it. - type CancellationOrigin = pallet_collective::EnsureProportionAtLeast; - type CooloffPeriod = CooloffPeriod; - type Currency = Balances; - type EnactmentPeriod = EnactmentPeriod; - /// A unanimous council can have the next scheduled referendum be a straight default-carries - /// (NTB) vote. - type ExternalDefaultOrigin = pallet_collective::EnsureProportionAtLeast; - /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. - type ExternalMajorityOrigin = pallet_collective::EnsureProportionAtLeast; - /// A straight majority of the council can decide what their next motion is. - type ExternalOrigin = pallet_collective::EnsureProportionAtLeast; - /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote - /// be tabled immediately and with a shorter voting/enactment period. - type FastTrackOrigin = pallet_collective::EnsureProportionAtLeast; - type FastTrackVotingPeriod = FastTrackVotingPeriod; - type InstantAllowed = frame_support::traits::ConstBool; - type InstantOrigin = pallet_collective::EnsureProportionAtLeast; - type LaunchPeriod = LaunchPeriod; - type MaxBlacklisted = (); - type MaxDeposits = (); - type MaxProposals = MaxProposals; - type MaxVotes = ConstU32<128>; - // Same as EnactmentPeriod - type MinimumDeposit = MinimumDeposit; - type PalletsOrigin = OriginCaller; - type Preimages = Preimage; - type RuntimeEvent = RuntimeEvent; - type Scheduler = Scheduler; - type Slash = (); - type SubmitOrigin = EnsureSigned; // Any single technical committee member may veto a coming council proposal, however they can // only do it once and it lasts only for the cool-off period. type VetoOrigin = pallet_collective::EnsureMember; - type VoteLockingPeriod = EnactmentPeriod; - type VotingPeriod = VotingPeriod; - type WeightInfo = pallet_democracy::weights::SubstrateWeight; + type PalletsOrigin = OriginCaller; + type Slash = (); + type SubmitOrigin = EnsureSigned; } impl pallet_scheduler::Config for Runtime { - type MaxScheduledPerBlock = MaxScheduledPerBlock; - type MaximumWeight = MaximumSchedulerWeight; - type OriginPrivilegeCmp = EqualPrivilegeOnly; - type PalletsOrigin = OriginCaller; - type Preimages = Preimage; - type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; + type PalletsOrigin = OriginCaller; + type RuntimeCall = RuntimeCall; + type MaximumWeight = MaximumSchedulerWeight; type ScheduleOrigin = EnsureRoot; + type OriginPrivilegeCmp = EqualPrivilegeOnly; + type MaxScheduledPerBlock = MaxScheduledPerBlock; type WeightInfo = (); + type Preimages = Preimage; } impl pallet_utility::Config for Runtime { - type PalletsOrigin = OriginCaller; - type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PalletsOrigin = OriginCaller; type WeightInfo = (); } impl pallet_multisig::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; type Currency = Balances; type DepositBase = DepositBase; type DepositFactor = DepositFactor; type MaxSignatories = MaxSignatories; - type RuntimeCall = RuntimeCall; - type RuntimeEvent = RuntimeEvent; type WeightInfo = (); } impl pallet_preimage::Config for Runtime { - type BaseDeposit = PreimageBaseDeposit; - type ByteDeposit = (); - type Currency = Balances; - type ManagerOrigin = EnsureRoot; type RuntimeEvent = RuntimeEvent; type WeightInfo = (); + type Currency = Balances; + type ManagerOrigin = EnsureRoot; + type BaseDeposit = PreimageBaseDeposit; + type ByteDeposit = (); } pub type LocalAssetsInstance = pallet_assets::Instance1; pub type StatemintAssetsInstance = pallet_assets::Instance2; impl pallet_assets::Config for Runtime { - type ApprovalDeposit = ExistentialDeposit; - type AssetAccountDeposit = AssetAccountDeposit; - type AssetDeposit = AssetDeposit; + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; type AssetId = AssetId; type AssetIdParameter = parity_scale_codec::Compact; - type Balance = Balance; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); - type CallbackHandle = (); - type CreateOrigin = AsEnsureOriginWithArg>; type Currency = Balances; - type Extra = (); + type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = EnsureRoot; - type Freezer = (); + type AssetDeposit = AssetDeposit; + type AssetAccountDeposit = AssetAccountDeposit; type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; - type RuntimeEvent = RuntimeEvent; + type ApprovalDeposit = ExistentialDeposit; type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); + type CallbackHandle = (); type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); } impl pallet_assets::Config for Runtime { - type ApprovalDeposit = ExistentialDeposit; - type AssetAccountDeposit = AssetAccountDeposit; - type AssetDeposit = AssetDeposit; + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; type AssetId = AssetId; type AssetIdParameter = parity_scale_codec::Compact; - type Balance = Balance; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); - type CallbackHandle = (); - type CreateOrigin = AsEnsureOriginWithArg>; type Currency = Balances; - type Extra = (); + type CreateOrigin = AsEnsureOriginWithArg>; type ForceOrigin = EnsureRoot; - type Freezer = (); + type AssetDeposit = AssetDeposit; + type AssetAccountDeposit = AssetAccountDeposit; type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; - type RuntimeEvent = RuntimeEvent; + type ApprovalDeposit = ExistentialDeposit; type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); + type CallbackHandle = (); type WeightInfo = (); + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); } impl pallet_vesting::Config for Runtime { - type BlockNumberToBalance = ConvertInto; + type RuntimeEvent = RuntimeEvent; type Currency = Balances; + type BlockNumberToBalance = ConvertInto; type MinVestedTransfer = MinVestedTransfer; - type RuntimeEvent = RuntimeEvent; - type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; type WeightInfo = pallet_vesting::weights::SubstrateWeight; - + type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; // `VestingInfo` encode length is 36bytes. 28 schedules gets encoded as 1009 bytes, which is the // highest number of schedules that encodes less than 2^10. const MAX_VESTING_SCHEDULES: u32 = 28; } impl pallet_parachain_staking::Config for Runtime { - type CandidateBondLessDelay = CandidateBondLessDelay; + type RuntimeEvent = RuntimeEvent; type Currency = Balances; - type DelegationBondLessDelay = DelegationBondLessDelay; + type MonetaryGovernanceOrigin = frame_system::EnsureRoot; + type MinBlocksPerRound = MinBlocksPerRound; type LeaveCandidatesDelay = LeaveCandidatesDelay; + type CandidateBondLessDelay = CandidateBondLessDelay; type LeaveDelegatorsDelay = LeaveDelegatorsDelay; + type RevokeDelegationDelay = RevokeDelegationDelay; + type DelegationBondLessDelay = DelegationBondLessDelay; + type RewardPaymentDelay = RewardPaymentDelay; + type MinSelectedCandidates = MinSelectedCandidates; + type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate; type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator; - type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; - type MinBlocksPerRound = MinBlocksPerRound; type MinCandidateStk = MinCandidateStk; - type MinDelegation = MinDelegation; type MinDelegatorStk = MinDelegatorStk; - type MinSelectedCandidates = MinSelectedCandidates; - type MonetaryGovernanceOrigin = frame_system::EnsureRoot; + type MinDelegation = MinDelegation; type OnCollatorPayout = (); - type OnNewRound = (); // We use the default implementation, so we leave () here. type PayoutCollatorReward = (); - type RevokeDelegationDelay = RevokeDelegationDelay; - type RewardPaymentDelay = RewardPaymentDelay; - type RuntimeEvent = RuntimeEvent; + type OnNewRound = (); type WeightInfo = pallet_parachain_staking::weights::SubstrateWeight; } @@ -831,15 +851,17 @@ impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { block: &Block, relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, ) -> sp_inherents::CheckInherentsResult { - let relay_chain_slot = - relay_state_proof.read_slot().expect("Could not read the relay chain slot from the proof"); - - let inherent_data = cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( - relay_chain_slot, - sp_std::time::Duration::from_secs(6), - ) - .create_inherent_data() - .expect("Could not create the timestamp inherent data"); + let relay_chain_slot = relay_state_proof + .read_slot() + .expect("Could not read the relay chain slot from the proof"); + + let inherent_data = + cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( + relay_chain_slot, + sp_std::time::Duration::from_secs(6), + ) + .create_inherent_data() + .expect("Could not create the timestamp inherent data"); inherent_data.check_extrinsics(block) } diff --git a/runtimes/testnet/src/xcm_config.rs b/runtimes/testnet/src/xcm_config.rs index 1c43b34db..75b876ee7 100644 --- a/runtimes/testnet/src/xcm_config.rs +++ b/runtimes/testnet/src/xcm_config.rs @@ -39,11 +39,13 @@ use polkadot_runtime_common::impls::ToAuthor; use sp_runtime::traits::Zero; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, - FixedRateOfFungible, FixedWeightBounds, FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, ParentIsPreset, - RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, WithComputedOrigin, + AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, + AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, + ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, + FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, ParentIsPreset, RelayChainAsNative, + SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, + WithComputedOrigin, }; use xcm_executor::{ traits::{Convert, Error, JustTry, MatchesFungibles}, @@ -51,9 +53,9 @@ use xcm_executor::{ }; use super::{ - AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Balance, Balances, EnsureRoot, ParachainInfo, - ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, StatemintAssets, WeightToFee, - XcmpQueue, + AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Balance, Balances, EnsureRoot, + ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, + StatemintAssets, WeightToFee, XcmpQueue, }; const DOT_ASSET_ID: AssetId = Concrete(RelayLocation::get()); @@ -126,7 +128,6 @@ impl Convert for NativeToFungible { _ => Err(asset), } } - fn reverse(value: AssetIdPalletAssets) -> Result { if value == AssetIdPalletAssets::from(0u32) { Ok(MultiLocation { parents: 1, interior: Here }) @@ -150,8 +151,10 @@ impl< for NonBlockingConvertedConcreteId { fn matches_fungibles(a: &MultiAsset) -> Result<(AssetId, Balance), Error> { - ConvertedConcreteId::::matches_fungibles(a) - .map_err(|_| Error::AssetNotHandled) + ConvertedConcreteId::::matches_fungibles( + a, + ) + .map_err(|_| Error::AssetNotHandled) } } @@ -172,7 +175,8 @@ pub type StatemintDotTransactor = FungiblesAdapter< >; /// Means for transacting assets on this chain. -pub type AssetTransactors = (CurrencyTransactor, StatemintDotTransactor, StatemintFungiblesTransactor); +pub type AssetTransactors = + (CurrencyTransactor, StatemintDotTransactor, StatemintFungiblesTransactor); /// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, /// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can @@ -224,7 +228,10 @@ pub type Barrier = DenyThenTry< // If the message is one that immediately attemps to pay for execution, then allow it. AllowTopLevelPaidExecutionFrom, // Common Good Assets parachain, parent and its exec plurality get free execution - AllowExplicitUnpaidExecutionFrom<(CommonGoodAssetsParachain, ParentOrParentsExecutivePlurality)>, + AllowExplicitUnpaidExecutionFrom<( + CommonGoodAssetsParachain, + ParentOrParentsExecutivePlurality, + )>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, ), @@ -249,10 +256,16 @@ impl ContainsPair for StatemintAssetsFilter { &loc == origin && match asset { MultiAsset { - id: Concrete(MultiLocation { parents: 0, interior: X2(PalletInstance(50), GeneralIndex(_)) }), + id: + Concrete(MultiLocation { + parents: 0, + interior: X2(PalletInstance(50), GeneralIndex(_)), + }), .. } => true, - MultiAsset { id: Concrete(MultiLocation { parents: 1, interior: Here }), .. } => true, + MultiAsset { + id: Concrete(MultiLocation { parents: 1, interior: Here }), .. + } => true, _ => false, } @@ -350,35 +363,35 @@ pub type Reserves = (NativeAsset, StatemintAssetsFilter); pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { - type AssetClaims = PolkadotXcm; - type AssetExchanger = (); - type AssetLocker = (); + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; // How to withdraw and deposit an asset. type AssetTransactor = AssetTransactors; - type AssetTrap = PolkadotXcm; - type Barrier = Barrier; - type CallDispatcher = RuntimeCall; - type FeeManager = (); + type OriginConverter = XcmOriginToTransactDispatchOrigin; type IsReserve = Reserves; type IsTeleporter = NativeAsset; - type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type MessageExporter = (); - type OriginConverter = XcmOriginToTransactDispatchOrigin; - type PalletInstancesInfo = AllPalletsWithSystem; - type ResponseHandler = PolkadotXcm; - type RuntimeCall = RuntimeCall; - // TODO: Restrict this to a subset of allowed `RuntimeCall`. - type SafeCallFilter = Everything; - type SubscriptionService = PolkadotXcm; + type UniversalLocation = UniversalLocation; + type Barrier = Barrier; + type Weigher = FixedWeightBounds; type Trader = ( // TODO: weight to fee has to be carefully considered. For now use default UsingComponents>, FixedRateOfFungible, ); + type ResponseHandler = PolkadotXcm; + type AssetTrap = PolkadotXcm; + type AssetClaims = PolkadotXcm; + type SubscriptionService = PolkadotXcm; + type PalletInstancesInfo = AllPalletsWithSystem; + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type AssetLocker = (); + type AssetExchanger = (); + type FeeManager = (); + type MessageExporter = (); type UniversalAliases = Nothing; - type UniversalLocation = UniversalLocation; - type Weigher = FixedWeightBounds; - type XcmSender = XcmRouter; + type CallDispatcher = RuntimeCall; + // TODO: Restrict this to a subset of allowed `RuntimeCall`. + type SafeCallFilter = Everything; } /// No local origins on this chain are allowed to dispatch XCM sends/executions. @@ -399,34 +412,34 @@ parameter_types! { } impl pallet_xcm::Config for Runtime { - type AdminOrigin = EnsureRoot; - // ^ Override for AdvertisedXcmVersion default - type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; + type RuntimeEvent = RuntimeEvent; type Currency = Balances; type CurrencyMatcher = (); - type ExecuteXcmOrigin = EnsureXcmOrigin; - type MaxLockers = ConstU32<8>; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; - type RuntimeCall = RuntimeCall; - type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; type SendXcmOrigin = EnsureXcmOrigin; - type SovereignAccountOf = LocationToAccountId; - type TrustedLockers = (); - type UniversalLocation = UniversalLocation; - type Weigher = FixedWeightBounds; - type WeightInfo = pallet_xcm::TestWeightInfo; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; // TODO: change back to `Nothing` once we add the xcm functionalities into a pallet type XcmExecuteFilter = Everything; // ^ Disable dispatchable execute on the XCM pallet. // Needs to be `Everything` for local testing. type XcmExecutor = XcmExecutor; - type XcmReserveTransferFilter = Everything; - type XcmRouter = XcmRouter; type XcmTeleportFilter = Everything; + type XcmReserveTransferFilter = Everything; + type Weigher = FixedWeightBounds; + type UniversalLocation = UniversalLocation; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + // ^ Override for AdvertisedXcmVersion default + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; + type TrustedLockers = (); + type SovereignAccountOf = LocationToAccountId; + type MaxLockers = ConstU32<8>; + type WeightInfo = pallet_xcm::TestWeightInfo; + type AdminOrigin = EnsureRoot; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; } impl cumulus_pallet_xcm::Config for Runtime { diff --git a/rustfmt.toml b/rustfmt.toml index a7034e8d6..6df3a1834 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,6 +1,6 @@ # Basic hard_tabs = true -max_width = 120 +max_width = 100 use_small_heuristics = "Max" # Imports imports_granularity = "Crate" @@ -8,12 +8,17 @@ reorder_imports = true # Consistency newline_style = "Unix" # Misc +chain_width = 80 spaces_around_ranges = false binop_separator = "Back" -reorder_impl_items = true +reorder_impl_items = false match_arm_leading_pipes = "Preserve" match_arm_blocks = false match_block_trailing_comma = true +trailing_comma = "Vertical" trailing_semicolon = false use_field_init_shorthand = true +ignore = [ + "bridges", +] edition = "2021" \ No newline at end of file From fb2fb8091f7a5e2114edcb5a14e479593679a65f Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:50:55 +0200 Subject: [PATCH 55/80] Revert "fix: building using workspace inheritance" This reverts commit 4489e8c65001cfee53c035a76376af786d8456ab. --- Cargo.lock | 10 +++++----- pallets/parachain-staking/Cargo.toml | 23 ++++++----------------- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 59c63407c..07b6234cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6239,7 +6239,7 @@ dependencies = [ [[package]] name = "pallet-parachain-staking" -version = "0.1.0" +version = "3.0.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -12684,9 +12684,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.19.13" +version = "0.19.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f8751d9c1b03c6500c387e96f81f815a4f8e72d142d2d4a9ffa6fedd51ddee7" +checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78" dependencies = [ "indexmap 2.0.0", "serde", @@ -14174,9 +14174,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.5.0" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7" +checksum = "81a2094c43cc94775293eaa0e499fbc30048a6d824ac82c0351a8c0bf9112529" dependencies = [ "memchr", ] diff --git a/pallets/parachain-staking/Cargo.toml b/pallets/parachain-staking/Cargo.toml index 7b964271a..ef13ae5e2 100644 --- a/pallets/parachain-staking/Cargo.toml +++ b/pallets/parachain-staking/Cargo.toml @@ -1,28 +1,19 @@ [package] name = "pallet-parachain-staking" -description = "prachain staking pallet for collator selection and reward distribution" -authors.workspace = true -documentation.workspace = true -edition.workspace = true -homepage.workspace = true -license-file.workspace = true -readme.workspace = true -repository.workspace = true -version.workspace = true +description = "parachain staking pallet for collator selection and reward distribution" +edition = "2021" +version = "3.0.0" [dependencies] serde = { version = "1", default-features = false, optional = true } log = "0.4" -parity-scale-codec = { workspace = true, features = [ - "derive", -] } -scale-info = { workspace = true, features = ["derive"] } - -# FRAME +# Substrate frame-benchmarking = { workspace = true, optional = true } frame-support.workspace = true frame-system.workspace = true +parity-scale-codec.workspace = true +scale-info.workspace = true sp-runtime.workspace = true sp-std.workspace = true substrate-fixed.workspace = true @@ -53,8 +44,6 @@ std = [ "sp-staking/std", "pallet-authorship/std", "pallet-session/std", - "pallet-balances/std", - "sp-consensus-aura/std" ] runtime-benchmarks = ["frame-benchmarking"] try-runtime = ["frame-support/try-runtime"] From 46173006a9ebeb9c8d6b46c70542e8007ce42992 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:50:56 +0200 Subject: [PATCH 56/80] Revert "feat: add parachain staking" This reverts commit 272b76014d67ceb95db285788a21de625d9252b2. --- Cargo.lock | 47 +- Cargo.toml | 3 +- pallets/parachain-staking/Cargo.toml | 49 - pallets/parachain-staking/README.md | 30 - pallets/parachain-staking/migrations.md | 42 - .../parachain-staking/src/auto_compound.rs | 368 - pallets/parachain-staking/src/benchmarks.rs | 1483 ---- .../src/delegation_requests.rs | 653 -- pallets/parachain-staking/src/inflation.rs | 208 - pallets/parachain-staking/src/lib.rs | 2011 ----- pallets/parachain-staking/src/migrations.rs | 17 - pallets/parachain-staking/src/mock.rs | 1008 --- pallets/parachain-staking/src/set.rs | 89 - pallets/parachain-staking/src/tests.rs | 6934 ----------------- pallets/parachain-staking/src/traits.rs | 66 - pallets/parachain-staking/src/types.rs | 1627 ---- pallets/parachain-staking/src/weights.rs | 1418 ---- 17 files changed, 3 insertions(+), 16050 deletions(-) delete mode 100644 pallets/parachain-staking/Cargo.toml delete mode 100644 pallets/parachain-staking/README.md delete mode 100644 pallets/parachain-staking/migrations.md delete mode 100644 pallets/parachain-staking/src/auto_compound.rs delete mode 100644 pallets/parachain-staking/src/benchmarks.rs delete mode 100644 pallets/parachain-staking/src/delegation_requests.rs delete mode 100644 pallets/parachain-staking/src/inflation.rs delete mode 100644 pallets/parachain-staking/src/lib.rs delete mode 100644 pallets/parachain-staking/src/migrations.rs delete mode 100644 pallets/parachain-staking/src/mock.rs delete mode 100644 pallets/parachain-staking/src/set.rs delete mode 100644 pallets/parachain-staking/src/tests.rs delete mode 100644 pallets/parachain-staking/src/traits.rs delete mode 100644 pallets/parachain-staking/src/types.rs delete mode 100644 pallets/parachain-staking/src/weights.rs diff --git a/Cargo.lock b/Cargo.lock index 07b6234cd..2faa2f1ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -755,17 +755,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" -[[package]] -name = "bstr" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" -dependencies = [ - "lazy_static", - "memchr", - "regex-automata 0.1.10", -] - [[package]] name = "bstr" version = "1.6.0" @@ -3342,7 +3331,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1391ab1f92ffcc08911957149833e682aa3fe252b9f45f966d2ef972274c97df" dependencies = [ "aho-corasick", - "bstr 1.6.0", + "bstr", "fnv", "log", "regex", @@ -6240,23 +6229,17 @@ dependencies = [ [[package]] name = "pallet-parachain-staking" version = "3.0.0" +source = "git+https://gitlab.com/Omegabit/stake-patch?branch=0.9.42#a9b481bf9f658f45db37fa9c8e26f31d41550518" dependencies = [ "frame-benchmarking", "frame-support", "frame-system", "log", - "pallet-aura", "pallet-authorship", - "pallet-balances", "pallet-session", - "pallet-timestamp", "parity-scale-codec", "scale-info", "serde", - "similar-asserts", - "sp-consensus-aura", - "sp-core", - "sp-io", "sp-runtime", "sp-staking", "sp-std", @@ -11130,26 +11113,6 @@ dependencies = [ "wide", ] -[[package]] -name = "similar" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" -dependencies = [ - "bstr 0.2.17", - "unicode-segmentation", -] - -[[package]] -name = "similar-asserts" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbf644ad016b75129f01a34a355dcb8d66a5bc803e417c7a77cc5d5ee9fa0f18" -dependencies = [ - "console", - "similar", -] - [[package]] name = "siphasher" version = "0.3.10" @@ -13049,12 +13012,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - [[package]] name = "unicode-width" version = "0.1.10" diff --git a/Cargo.toml b/Cargo.toml index 2bb3e5a8c..f63ca7de0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,14 +46,13 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran # Internal pallets (with default disabled) pallet-funding = { path = "pallets/funding", default-features = false } pallet-sandbox = { path = "pallets/sandbox", default-features = false } -pallet-parachain-staking = { path = "pallets/parachain-staking", default-features = false} +pallet-parachain-staking = { git = "https://gitlab.com/Omegabit/stake-patch", default-features = false, branch = "0.9.42"} # Internal support (with default disabled) shared-configuration = { path = "runtimes/shared-configuration", default-features = false } # External support (with default disabled) -substrate-fixed = { git = "https://github.com/encointer/substrate-fixed", default-features = false } # dip-support = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } # kilt-support = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } # kilt-dip-support = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } diff --git a/pallets/parachain-staking/Cargo.toml b/pallets/parachain-staking/Cargo.toml deleted file mode 100644 index ef13ae5e2..000000000 --- a/pallets/parachain-staking/Cargo.toml +++ /dev/null @@ -1,49 +0,0 @@ -[package] -name = "pallet-parachain-staking" -description = "parachain staking pallet for collator selection and reward distribution" -edition = "2021" -version = "3.0.0" - -[dependencies] -serde = { version = "1", default-features = false, optional = true } -log = "0.4" - -# Substrate -frame-benchmarking = { workspace = true, optional = true } -frame-support.workspace = true -frame-system.workspace = true -parity-scale-codec.workspace = true -scale-info.workspace = true -sp-runtime.workspace = true -sp-std.workspace = true -substrate-fixed.workspace = true -sp-staking.workspace = true -pallet-authorship.workspace = true -pallet-session.workspace = true - -[dev-dependencies] -pallet-balances.workspace = true -pallet-aura.workspace = true -pallet-timestamp.workspace = true -similar-asserts = "1.1.0" -sp-core.workspace = true -sp-io.workspace = true -sp-consensus-aura.workspace = true - -[features] -default = ["std"] -std = [ - "frame-benchmarking?/std", - "frame-support/std", - "frame-system/std", - "parity-scale-codec/std", - "scale-info/std", - "serde/std", - "sp-runtime/std", - "sp-std/std", - "sp-staking/std", - "pallet-authorship/std", - "pallet-session/std", -] -runtime-benchmarks = ["frame-benchmarking"] -try-runtime = ["frame-support/try-runtime"] diff --git a/pallets/parachain-staking/README.md b/pallets/parachain-staking/README.md deleted file mode 100644 index 78afd35c0..000000000 --- a/pallets/parachain-staking/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# DPoS Pallet for Parachain Staking - -## Polimec Changes - - - -## Formatting Rules - -- dependencies in alphabetical order in the `Cargo.toml` and at the top of each file -- prefer explicit imports to glob import syntax i.e. prefer `use::crate::{Ex1, Ex2, ..};` to `use super::*;` - -## Description - -Implements Delegated Proof of Stake to - -1. select the active set of eligible block producers -2. reward block authors -3. enable delegators and collators to participate in inflationary rewards - -Links: - -- [Rust Documentation](https://purestake.github.io/moonbeam/pallet_parachain_staking/index.html) -- [Unofficial Documentation](https://meta5.world/parachain-staking-docs/) -- [(Outdated) Blog Post with Justification](https://meta5.world/posts/parachain-staking) - -## History - -Since January 2021, Moonbeam's team has maintained this Delegated Proof of Stake (DPoS) pallet designed specifically for parachains. - -Since April 2021, the development of this pallet has been supported by [a Web3 Foundation grant](https://github.com/w3f/Grants-Program/pull/389). The [first milestone](https://github.com/w3f/Grant-Milestone-Delivery/pull/218) was approved in June 2021. diff --git a/pallets/parachain-staking/migrations.md b/pallets/parachain-staking/migrations.md deleted file mode 100644 index d2277ffcd..000000000 --- a/pallets/parachain-staking/migrations.md +++ /dev/null @@ -1,42 +0,0 @@ -# Migration History - -## Calculate outgoing rewards based on pending revoke and decrease changes - -- [Migration PR `#1408`](https://github.com/PureStake/moonbeam/pull/1408) - -## Patch delegations total mismatch - -- [Migration PR `#1291`](https://github.com/PureStake/moonbeam/pull/1291) - -## Split candidate state for PoV optimization - -- [Migration PR `#1117`](https://github.com/PureStake/moonbeam/pull/1117) - -## Increase max delegations per candidate - -- [Migration PR `#1096`](https://github.com/PureStake/moonbeam/pull/1096) -- [Migratio bugfix `#1112`](https://github.com/PureStake/moonbeam/pull/1112) - -## Manual Exits and Patch Lack of Delay for bond\_{more, less} - -- [Migration PR `#810`](https://github.com/PureStake/moonbeam/pull/810) -- [Migration Removal PR `#?`]() - -## Purge Stale Storage - -- [Migration PR `#970`](https://github.com/PureStake/moonbeam/pull/970) - -## Delay nominator exits by changing NominatorState and ExitQueue - -- [Migration PR `#610`](https://github.com/PureStake/moonbeam/pull/610) -- [Migration Removal PR `#662`](https://github.com/PureStake/moonbeam/pull/662) - -## Patch nomination DOS attack vector by changing CollatorState - -- [Migration PR `#505`](https://github.com/PureStake/moonbeam/pull/505) -- [Migration Removal PR `#553`](https://github.com/PureStake/moonbeam/pull/553) - -## Patch underflow bug and correct Total storage item - -- [Migration PR `#502`](https://github.com/PureStake/moonbeam/pull/502) -- [Migration Removal PR `#553`](https://github.com/PureStake/moonbeam/pull/553) diff --git a/pallets/parachain-staking/src/auto_compound.rs b/pallets/parachain-staking/src/auto_compound.rs deleted file mode 100644 index 830c4c077..000000000 --- a/pallets/parachain-staking/src/auto_compound.rs +++ /dev/null @@ -1,368 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam 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. - -// Moonbeam 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 Moonbeam. If not, see . - -//! Auto-compounding functionality for staking rewards - -use crate::{ - pallet::{ - AddGet, AutoCompoundingDelegations as AutoCompoundingDelegationsStorage, BalanceOf, - CandidateInfo, Config, DelegatorState, Error, Event, Pallet, Total, - }, - types::{Bond, BondAdjust, Delegator}, -}; -use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, traits::Get, RuntimeDebug}; -use parity_scale_codec::{Decode, Encode}; -use scale_info::TypeInfo; -use sp_runtime::{traits::Saturating, BoundedVec, Percent}; -use sp_std::prelude::*; - -/// Represents the auto-compounding amount for a delegation. -#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, PartialOrd, Ord)] -pub struct AutoCompoundConfig { - pub delegator: AccountId, - pub value: Percent, -} - -/// Represents the auto-compounding [Delegations] for `T: Config` -#[derive(Clone, Eq, PartialEq, RuntimeDebug)] -pub struct AutoCompoundDelegations( - BoundedVec< - AutoCompoundConfig, - AddGet, - >, -); - -impl AutoCompoundDelegations -where - T: Config, -{ - /// Creates a new instance of [AutoCompoundingDelegations] from a vector of sorted_delegations. - /// This is used for testing purposes only. - #[cfg(test)] - pub fn new( - sorted_delegations: BoundedVec< - AutoCompoundConfig, - AddGet, - >, - ) -> Self { - Self(sorted_delegations) - } - - /// Retrieves an instance of [AutoCompoundingDelegations] storage as [AutoCompoundDelegations]. - pub fn get_storage(candidate: &T::AccountId) -> Self { - Self(>::get(candidate)) - } - - /// Inserts the current state to [AutoCompoundingDelegations] storage. - pub fn set_storage(self, candidate: &T::AccountId) { - >::insert(candidate, self.0) - } - - /// Retrieves the auto-compounding value for a delegation. The `delegations_config` must be a - /// sorted vector for binary_search to work. - pub fn get_for_delegator(&self, delegator: &T::AccountId) -> Option { - match self.0.binary_search_by(|d| d.delegator.cmp(delegator)) { - Ok(index) => Some(self.0[index].value), - Err(_) => None, - } - } - - /// Sets the auto-compounding value for a delegation. The `delegations_config` must be a sorted - /// vector for binary_search to work. - pub fn set_for_delegator( - &mut self, - delegator: T::AccountId, - value: Percent, - ) -> Result> { - match self.0.binary_search_by(|d| d.delegator.cmp(&delegator)) { - Ok(index) => - if self.0[index].value == value { - Ok(false) - } else { - self.0[index].value = value; - Ok(true) - }, - Err(index) => { - self.0 - .try_insert(index, AutoCompoundConfig { delegator, value }) - .map_err(|_| Error::::ExceedMaxDelegationsPerDelegator)?; - Ok(true) - }, - } - } - - /// Removes the auto-compounding value for a delegation. - /// Returns `true` if the entry was removed, `false` otherwise. The `delegations_config` must be a - /// sorted vector for binary_search to work. - pub fn remove_for_delegator(&mut self, delegator: &T::AccountId) -> bool { - match self.0.binary_search_by(|d| d.delegator.cmp(delegator)) { - Ok(index) => { - self.0.remove(index); - true - }, - Err(_) => false, - } - } - - /// Returns the length of the inner vector. - pub fn len(&self) -> u32 { - self.0.len() as u32 - } - - /// Returns a reference to the inner vector. - #[cfg(test)] - pub fn inner( - &self, - ) -> &BoundedVec< - AutoCompoundConfig, - AddGet, - > { - &self.0 - } - - /// Converts the [AutoCompoundDelegations] into the inner vector. - #[cfg(test)] - pub fn into_inner( - self, - ) -> BoundedVec< - AutoCompoundConfig, - AddGet, - > { - self.0 - } - - // -- pallet functions -- - - /// Delegates and sets the auto-compounding config. The function skips inserting auto-compound - /// storage and validation, if the auto-compound value is 0%. - pub(crate) fn delegate_with_auto_compound( - candidate: T::AccountId, - delegator: T::AccountId, - amount: BalanceOf, - auto_compound: Percent, - candidate_delegation_count_hint: u32, - candidate_auto_compounding_delegation_count_hint: u32, - delegation_count_hint: u32, - ) -> DispatchResultWithPostInfo { - // check that caller can lock the amount before any changes to storage - ensure!( - >::get_delegator_stakable_free_balance(&delegator) >= amount, - Error::::InsufficientBalance - ); - - let mut delegator_state = if let Some(mut state) = >::get(&delegator) { - // delegation after first - ensure!(amount >= T::MinDelegation::get(), Error::::DelegationBelowMin); - ensure!( - delegation_count_hint >= state.delegations.0.len() as u32, - Error::::TooLowDelegationCountToDelegate - ); - ensure!( - (state.delegations.0.len() as u32) < T::MaxDelegationsPerDelegator::get(), - Error::::ExceedMaxDelegationsPerDelegator - ); - ensure!( - state.add_delegation(Bond { owner: candidate.clone(), amount }), - Error::::AlreadyDelegatedCandidate - ); - state - } else { - // first delegation - ensure!(amount >= T::MinDelegatorStk::get(), Error::::DelegatorBondBelowMin); - ensure!(!>::is_candidate(&delegator), Error::::CandidateExists); - Delegator::new(delegator.clone(), candidate.clone(), amount) - }; - let mut candidate_state = - >::get(&candidate).ok_or(Error::::CandidateDNE)?; - ensure!( - candidate_delegation_count_hint >= candidate_state.delegation_count, - Error::::TooLowCandidateDelegationCountToDelegate - ); - - let auto_compounding_state = if !auto_compound.is_zero() { - let auto_compounding_state = Self::get_storage(&candidate); - ensure!( - auto_compounding_state.len() <= candidate_auto_compounding_delegation_count_hint, - >::TooLowCandidateAutoCompoundingDelegationCountToDelegate, - ); - Some(auto_compounding_state) - } else { - None - }; - - // add delegation to candidate - let (delegator_position, less_total_staked) = candidate_state - .add_delegation::(&candidate, Bond { owner: delegator.clone(), amount })?; - - // lock delegator amount - delegator_state.adjust_bond_lock::(BondAdjust::Increase(amount))?; - - // adjust total locked, - // only is_some if kicked the lowest bottom as a consequence of this new delegation - let net_total_increase = - if let Some(less) = less_total_staked { amount.saturating_sub(less) } else { amount }; - let new_total_locked = >::get().saturating_add(net_total_increase); - - // maybe set auto-compound config, state is Some if the percent is non-zero - if let Some(mut state) = auto_compounding_state { - state.set_for_delegator(delegator.clone(), auto_compound)?; - state.set_storage(&candidate); - } - - >::put(new_total_locked); - >::insert(&candidate, candidate_state); - >::insert(&delegator, delegator_state); - >::deposit_event(Event::Delegation { - delegator, - locked_amount: amount, - candidate, - delegator_position, - auto_compound, - }); - - Ok(().into()) - } - - /// Sets the auto-compounding value for a delegation. The config is removed if value is zero. - pub(crate) fn set_auto_compound( - candidate: T::AccountId, - delegator: T::AccountId, - value: Percent, - candidate_auto_compounding_delegation_count_hint: u32, - delegation_count_hint: u32, - ) -> DispatchResultWithPostInfo { - let delegator_state = - >::get(&delegator).ok_or(>::DelegatorDNE)?; - ensure!( - delegator_state.delegations.0.len() <= delegation_count_hint as usize, - >::TooLowDelegationCountToAutoCompound, - ); - ensure!( - delegator_state.delegations.0.iter().any(|b| b.owner == candidate), - >::DelegationDNE, - ); - - let mut auto_compounding_state = Self::get_storage(&candidate); - ensure!( - auto_compounding_state.len() <= candidate_auto_compounding_delegation_count_hint, - >::TooLowCandidateAutoCompoundingDelegationCountToAutoCompound, - ); - let state_updated = if value.is_zero() { - auto_compounding_state.remove_for_delegator(&delegator) - } else { - auto_compounding_state.set_for_delegator(delegator.clone(), value)? - }; - if state_updated { - auto_compounding_state.set_storage(&candidate); - } - - >::deposit_event(Event::AutoCompoundSet { candidate, delegator, value }); - - Ok(().into()) - } - - /// Removes the auto-compounding value for a delegation. This should be called when the - /// delegation is revoked to cleanup storage. Storage is only written iff the entry existed. - pub(crate) fn remove_auto_compound(candidate: &T::AccountId, delegator: &T::AccountId) { - let mut auto_compounding_state = Self::get_storage(candidate); - if auto_compounding_state.remove_for_delegator(delegator) { - auto_compounding_state.set_storage(candidate); - } - } - - /// Returns the value of auto-compound, if it exists for a given delegation, zero otherwise. - pub(crate) fn auto_compound(candidate: &T::AccountId, delegator: &T::AccountId) -> Percent { - let delegations_config = Self::get_storage(candidate); - delegations_config.get_for_delegator(delegator).unwrap_or_else(Percent::zero) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::mock::Test; - - #[test] - fn test_set_for_delegator_inserts_config_and_returns_true_if_entry_missing() { - let mut delegations_config = - AutoCompoundDelegations::::new(vec![].try_into().expect("must succeed")); - assert_eq!( - true, - delegations_config - .set_for_delegator(1, Percent::from_percent(50)) - .expect("must succeed") - ); - assert_eq!( - vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(50) }], - delegations_config.into_inner().into_inner(), - ); - } - - #[test] - fn test_set_for_delegator_updates_config_and_returns_true_if_entry_changed() { - let mut delegations_config = AutoCompoundDelegations::::new( - vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(10) }] - .try_into() - .expect("must succeed"), - ); - assert_eq!( - true, - delegations_config - .set_for_delegator(1, Percent::from_percent(50)) - .expect("must succeed") - ); - assert_eq!( - vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(50) }], - delegations_config.into_inner().into_inner(), - ); - } - - #[test] - fn test_set_for_delegator_updates_config_and_returns_false_if_entry_unchanged() { - let mut delegations_config = AutoCompoundDelegations::::new( - vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(10) }] - .try_into() - .expect("must succeed"), - ); - assert_eq!( - false, - delegations_config - .set_for_delegator(1, Percent::from_percent(10)) - .expect("must succeed") - ); - assert_eq!( - vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(10) }], - delegations_config.into_inner().into_inner(), - ); - } - - #[test] - fn test_remove_for_delegator_returns_false_if_entry_was_missing() { - let mut delegations_config = - AutoCompoundDelegations::::new(vec![].try_into().expect("must succeed")); - assert_eq!(false, delegations_config.remove_for_delegator(&1),); - } - - #[test] - fn test_remove_delegation_config_returns_true_if_entry_existed() { - let mut delegations_config = AutoCompoundDelegations::::new( - vec![AutoCompoundConfig { delegator: 1, value: Percent::from_percent(10) }] - .try_into() - .expect("must succeed"), - ); - assert_eq!(true, delegations_config.remove_for_delegator(&1)); - } -} diff --git a/pallets/parachain-staking/src/benchmarks.rs b/pallets/parachain-staking/src/benchmarks.rs deleted file mode 100644 index 0f8ba8ad6..000000000 --- a/pallets/parachain-staking/src/benchmarks.rs +++ /dev/null @@ -1,1483 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam 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. - -// Moonbeam 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 Moonbeam. If not, see . - -#![cfg(feature = "runtime-benchmarks")] - -//! Benchmarking -use crate::{ - AwardedPts, BalanceOf, Call, CandidateBondLessRequest, Config, DelegationAction, Pallet, - ParachainBondConfig, ParachainBondInfo, Points, Range, RewardPayment, Round, ScheduledRequest, - Staked, TopDelegations, -}; -use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, vec}; -use frame_support::traits::{Currency, Get, OnFinalize, OnInitialize}; -use frame_system::RawOrigin; -use sp_runtime::{Perbill, Percent}; -use sp_std::vec::Vec; - -/// Minimum collator candidate stake -fn min_candidate_stk() -> BalanceOf { - <::MinCandidateStk as Get>>::get() -} - -/// Minimum delegator stake -fn min_delegator_stk() -> BalanceOf { - <::MinDelegatorStk as Get>>::get() -} - -/// Create a funded user. -/// Extra + min_candidate_stk is total minted funds -/// Returns tuple (id, balance) -fn create_funded_user( - string: &'static str, - n: u32, - extra: BalanceOf, -) -> (T::AccountId, BalanceOf) { - const SEED: u32 = 0; - let user = account(string, n, SEED); - let min_candidate_stk = min_candidate_stk::(); - let total = min_candidate_stk + extra; - T::Currency::make_free_balance_be(&user, total); - T::Currency::issue(total); - (user, total) -} - -/// Create a funded delegator. -fn create_funded_delegator( - string: &'static str, - n: u32, - extra: BalanceOf, - collator: T::AccountId, - min_bond: bool, - collator_delegator_count: u32, -) -> Result { - let (user, total) = create_funded_user::(string, n, extra); - let bond = if min_bond { min_delegator_stk::() } else { total }; - Pallet::::delegate( - RawOrigin::Signed(user.clone()).into(), - collator, - bond, - collator_delegator_count, - 0u32, // first delegation for all calls - )?; - Ok(user) -} - -/// Create a funded collator. -fn create_funded_collator( - string: &'static str, - n: u32, - extra: BalanceOf, - min_bond: bool, - candidate_count: u32, -) -> Result { - let (user, total) = create_funded_user::(string, n, extra); - let bond = if min_bond { min_candidate_stk::() } else { total }; - Pallet::::join_candidates(RawOrigin::Signed(user.clone()).into(), bond, candidate_count)?; - Ok(user) -} - -// Simulate staking on finalize by manually setting points -fn parachain_staking_on_finalize(author: T::AccountId) { - let now = >::get().current; - let score_plus_20 = >::get(now, &author).saturating_add(20); - >::insert(now, author, score_plus_20); - >::mutate(now, |x| *x = x.saturating_add(20)); -} - -/// Run to end block and author -fn roll_to_and_author(round_delay: u32, author: T::AccountId) { - let total_rounds = round_delay + 1u32; - let round_length: T::BlockNumber = Pallet::::round().length.into(); - let mut now = >::block_number() + 1u32.into(); - let end = Pallet::::round().first + (round_length * total_rounds.into()); - while now < end { - parachain_staking_on_finalize::(author.clone()); - >::on_finalize(>::block_number()); - >::set_block_number( - >::block_number() + 1u32.into(), - ); - >::on_initialize(>::block_number()); - Pallet::::on_initialize(>::block_number()); - now += 1u32.into(); - } -} - -const USER_SEED: u32 = 999666; -struct Seed { - pub inner: u32, -} -impl Seed { - fn new() -> Self { - Seed { inner: USER_SEED } - } - - pub fn take(&mut self) -> u32 { - let v = self.inner; - self.inner += 1; - v - } -} - -benchmarks! { - // MONETARY ORIGIN DISPATCHABLES - set_staking_expectations { - let stake_range: Range> = Range { - min: 100u32.into(), - ideal: 200u32.into(), - max: 300u32.into(), - }; - }: _(RawOrigin::Root, stake_range) - verify { - assert_eq!(Pallet::::inflation_config().expect, stake_range); - } - - set_inflation { - let inflation_range: Range = Range { - min: Perbill::from_perthousand(1), - ideal: Perbill::from_perthousand(2), - max: Perbill::from_perthousand(3), - }; - - }: _(RawOrigin::Root, inflation_range) - verify { - assert_eq!(Pallet::::inflation_config().annual, inflation_range); - } - - set_parachain_bond_account { - let parachain_bond_account: T::AccountId = account("TEST", 0u32, USER_SEED); - }: _(RawOrigin::Root, parachain_bond_account.clone()) - verify { - assert_eq!(Pallet::::parachain_bond_info().account, parachain_bond_account); - } - - set_parachain_bond_reserve_percent { - }: _(RawOrigin::Root, Percent::from_percent(33)) - verify { - assert_eq!(Pallet::::parachain_bond_info().percent, Percent::from_percent(33)); - } - - // ROOT DISPATCHABLES - - set_total_selected { - Pallet::::set_blocks_per_round(RawOrigin::Root.into(), 101u32)?; - }: _(RawOrigin::Root, 100u32) - verify { - assert_eq!(Pallet::::total_selected(), 100u32); - } - - set_collator_commission {}: _(RawOrigin::Root, Perbill::from_percent(33)) - verify { - assert_eq!(Pallet::::collator_commission(), Perbill::from_percent(33)); - } - - set_blocks_per_round {}: _(RawOrigin::Root, 1200u32) - verify { - assert_eq!(Pallet::::round().length, 1200u32); - } - - // USER DISPATCHABLES - - join_candidates { - let x in 3..1_000; - // Worst Case Complexity is insertion into an ordered list so \exists full list before call - let mut candidate_count = 1u32; - for i in 2..x { - let seed = USER_SEED - i; - let collator = create_funded_collator::( - "collator", - seed, - 0u32.into(), - true, - candidate_count - )?; - candidate_count += 1u32; - } - let (caller, min_candidate_stk) = create_funded_user::("caller", USER_SEED, 0u32.into()); - }: _(RawOrigin::Signed(caller.clone()), min_candidate_stk, candidate_count) - verify { - assert!(Pallet::::is_candidate(&caller)); - } - - // This call schedules the collator's exit and removes them from the candidate pool - // -> it retains the self-bond and delegator bonds - schedule_leave_candidates { - let x in 3..1_000; - // Worst Case Complexity is removal from an ordered list so \exists full list before call - let mut candidate_count = 1u32; - for i in 2..x { - let seed = USER_SEED - i; - let collator = create_funded_collator::( - "collator", - seed, - 0u32.into(), - true, - candidate_count - )?; - candidate_count += 1u32; - } - let caller: T::AccountId = create_funded_collator::( - "caller", - USER_SEED, - 0u32.into(), - true, - candidate_count, - )?; - candidate_count += 1u32; - }: _(RawOrigin::Signed(caller.clone()), candidate_count) - verify { - assert!(Pallet::::candidate_info(&caller).expect("must exist").is_leaving()); - } - - execute_leave_candidates { - // x is total number of delegations for the candidate - let x in 2..(<::MaxTopDelegationsPerCandidate as Get>::get() - + <::MaxBottomDelegationsPerCandidate as Get>::get()); - let candidate: T::AccountId = create_funded_collator::( - "unique_caller", - USER_SEED - 100, - 0u32.into(), - true, - 1u32, - )?; - // 2nd delegation required for all delegators to ensure DelegatorState updated not removed - let second_candidate: T::AccountId = create_funded_collator::( - "unique__caller", - USER_SEED - 99, - 0u32.into(), - true, - 2u32, - )?; - let mut delegators: Vec = Vec::new(); - let mut col_del_count = 0u32; - for i in 1..x { - let seed = USER_SEED + i; - let delegator = create_funded_delegator::( - "delegator", - seed, - min_delegator_stk::(), - candidate.clone(), - true, - col_del_count, - )?; - Pallet::::delegate( - RawOrigin::Signed(delegator.clone()).into(), - second_candidate.clone(), - min_delegator_stk::(), - col_del_count, - 1u32, - )?; - Pallet::::schedule_revoke_delegation( - RawOrigin::Signed(delegator.clone()).into(), - candidate.clone() - )?; - delegators.push(delegator); - col_del_count += 1u32; - } - Pallet::::schedule_leave_candidates( - RawOrigin::Signed(candidate.clone()).into(), - 3u32 - )?; - roll_to_and_author::(2, candidate.clone()); - }: _(RawOrigin::Signed(candidate.clone()), candidate.clone(), col_del_count) - verify { - assert!(Pallet::::candidate_info(&candidate).is_none()); - assert!(Pallet::::candidate_info(&second_candidate).is_some()); - for delegator in delegators { - assert!(Pallet::::is_delegator(&delegator)); - } - } - - cancel_leave_candidates { - let x in 3..1_000; - // Worst Case Complexity is removal from an ordered list so \exists full list before call - let mut candidate_count = 1u32; - for i in 2..x { - let seed = USER_SEED - i; - let collator = create_funded_collator::( - "collator", - seed, - 0u32.into(), - true, - candidate_count - )?; - candidate_count += 1u32; - } - let caller: T::AccountId = create_funded_collator::( - "caller", - USER_SEED, - 0u32.into(), - true, - candidate_count, - )?; - candidate_count += 1u32; - Pallet::::schedule_leave_candidates( - RawOrigin::Signed(caller.clone()).into(), - candidate_count - )?; - candidate_count -= 1u32; - }: _(RawOrigin::Signed(caller.clone()), candidate_count) - verify { - assert!(Pallet::::candidate_info(&caller).expect("must exist").is_active()); - } - - go_offline { - let caller: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - }: _(RawOrigin::Signed(caller.clone())) - verify { - assert!(!Pallet::::candidate_info(&caller).expect("must exist").is_active()); - } - - go_online { - let caller: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - Pallet::::go_offline(RawOrigin::Signed(caller.clone()).into())?; - }: _(RawOrigin::Signed(caller.clone())) - verify { - assert!(Pallet::::candidate_info(&caller).expect("must exist").is_active()); - } - - candidate_bond_more { - let more = min_candidate_stk::(); - let caller: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - more, - true, - 1u32, - )?; - }: _(RawOrigin::Signed(caller.clone()), more) - verify { - let expected_bond = more * 2u32.into(); - assert_eq!( - Pallet::::candidate_info(&caller).expect("candidate was created, qed").bond, - expected_bond, - ); - } - - schedule_candidate_bond_less { - let min_candidate_stk = min_candidate_stk::(); - let caller: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - min_candidate_stk, - false, - 1u32, - )?; - }: _(RawOrigin::Signed(caller.clone()), min_candidate_stk) - verify { - let state = Pallet::::candidate_info(&caller).expect("request bonded less so exists"); - assert_eq!( - state.request, - Some(CandidateBondLessRequest { - amount: min_candidate_stk, - when_executable: 3, - }) - ); - } - - execute_candidate_bond_less { - let min_candidate_stk = min_candidate_stk::(); - let caller: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - min_candidate_stk, - false, - 1u32, - )?; - Pallet::::schedule_candidate_bond_less( - RawOrigin::Signed(caller.clone()).into(), - min_candidate_stk - )?; - roll_to_and_author::(2, caller.clone()); - }: { - Pallet::::execute_candidate_bond_less( - RawOrigin::Signed(caller.clone()).into(), - caller.clone() - )?; - } verify { - assert_eq!( - Pallet::::candidate_info(&caller).expect("candidate was created, qed").bond, - min_candidate_stk, - ); - } - - cancel_candidate_bond_less { - let min_candidate_stk = min_candidate_stk::(); - let caller: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - min_candidate_stk, - false, - 1u32, - )?; - Pallet::::schedule_candidate_bond_less( - RawOrigin::Signed(caller.clone()).into(), - min_candidate_stk - )?; - }: { - Pallet::::cancel_candidate_bond_less( - RawOrigin::Signed(caller.clone()).into(), - )?; - } verify { - assert!( - Pallet::::candidate_info(&caller).expect("must exist").request.is_none() - ); - } - - delegate { - let x in 3..<::MaxDelegationsPerDelegator as Get>::get(); - let y in 2..<::MaxTopDelegationsPerCandidate as Get>::get(); - // Worst Case is full of delegations before calling `delegate` - let mut collators: Vec = Vec::new(); - // Initialize MaxDelegationsPerDelegator collator candidates - for i in 2..x { - let seed = USER_SEED - i; - let collator = create_funded_collator::( - "collator", - seed, - 0u32.into(), - true, - collators.len() as u32 + 1u32, - )?; - collators.push(collator.clone()); - } - let bond = <::MinDelegatorStk as Get>>::get(); - let extra = if (bond * (collators.len() as u32 + 1u32).into()) > min_candidate_stk::() { - (bond * (collators.len() as u32 + 1u32).into()) - min_candidate_stk::() - } else { - 0u32.into() - }; - let (caller, _) = create_funded_user::("caller", USER_SEED, extra.into()); - // Delegation count - let mut del_del_count = 0u32; - // Nominate MaxDelegationsPerDelegators collator candidates - for col in collators.clone() { - Pallet::::delegate( - RawOrigin::Signed(caller.clone()).into(), col, bond, 0u32, del_del_count - )?; - del_del_count += 1u32; - } - // Last collator to be delegated - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - collators.len() as u32 + 1u32, - )?; - // Worst Case Complexity is insertion into an almost full collator - let mut col_del_count = 0u32; - for i in 1..y { - let seed = USER_SEED + i; - let _ = create_funded_delegator::( - "delegator", - seed, - 0u32.into(), - collator.clone(), - true, - col_del_count, - )?; - col_del_count += 1u32; - } - }: _(RawOrigin::Signed(caller.clone()), collator, bond, col_del_count, del_del_count) - verify { - assert!(Pallet::::is_delegator(&caller)); - } - - schedule_leave_delegators { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); - let bond = <::MinDelegatorStk as Get>>::get(); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - bond, - 0u32, - 0u32 - )?; - }: _(RawOrigin::Signed(caller.clone())) - verify { - assert!( - Pallet::::delegation_scheduled_requests(&collator) - .iter() - .any(|r| r.delegator == caller && matches!(r.action, DelegationAction::Revoke(_))) - ); - } - - execute_leave_delegators { - let x in 2..<::MaxDelegationsPerDelegator as Get>::get(); - // Worst Case is full of delegations before execute exit - let mut collators: Vec = Vec::new(); - // Initialize MaxDelegationsPerDelegator collator candidates - for i in 1..x { - let seed = USER_SEED - i; - let collator = create_funded_collator::( - "collator", - seed, - 0u32.into(), - true, - collators.len() as u32 + 1u32 - )?; - collators.push(collator.clone()); - } - let bond = <::MinDelegatorStk as Get>>::get(); - let need = bond * (collators.len() as u32).into(); - let default_minted = min_candidate_stk::(); - let need: BalanceOf = if need > default_minted { - need - default_minted - } else { - 0u32.into() - }; - // Fund the delegator - let (caller, _) = create_funded_user::("caller", USER_SEED, need); - // Delegation count - let mut delegation_count = 0u32; - let author = collators[0].clone(); - // Nominate MaxDelegationsPerDelegators collator candidates - for col in collators { - Pallet::::delegate( - RawOrigin::Signed(caller.clone()).into(), - col, - bond, - 0u32, - delegation_count - )?; - delegation_count += 1u32; - } - Pallet::::schedule_leave_delegators(RawOrigin::Signed(caller.clone()).into())?; - roll_to_and_author::(2, author); - }: _(RawOrigin::Signed(caller.clone()), caller.clone(), delegation_count) - verify { - assert!(Pallet::::delegator_state(&caller).is_none()); - } - - cancel_leave_delegators { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); - let bond = <::MinDelegatorStk as Get>>::get(); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - bond, - 0u32, - 0u32 - )?; - Pallet::::schedule_leave_delegators(RawOrigin::Signed(caller.clone()).into())?; - }: _(RawOrigin::Signed(caller.clone())) - verify { - assert!(Pallet::::delegator_state(&caller).expect("must exist").is_active()); - } - - schedule_revoke_delegation { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); - let bond = <::MinDelegatorStk as Get>>::get(); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - bond, - 0u32, - 0u32 - )?; - }: _(RawOrigin::Signed(caller.clone()), collator.clone()) - verify { - assert_eq!( - Pallet::::delegation_scheduled_requests(&collator), - vec![ScheduledRequest { - delegator: caller, - when_executable: 3, - action: DelegationAction::Revoke(bond), - }], - ); - } - - delegator_bond_more { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); - let bond = <::MinDelegatorStk as Get>>::get(); - Pallet::::delegate( - RawOrigin::Signed(caller.clone()).into(), - collator.clone(), - bond, - 0u32, - 0u32 - )?; - }: _(RawOrigin::Signed(caller.clone()), collator.clone(), bond) - verify { - let expected_bond = bond * 2u32.into(); - assert_eq!( - Pallet::::delegator_state(&caller).expect("candidate was created, qed").total, - expected_bond, - ); - } - - schedule_delegator_bond_less { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, total) = create_funded_user::("caller", USER_SEED, 0u32.into()); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - total, - 0u32, - 0u32 - )?; - let bond_less = <::MinDelegatorStk as Get>>::get(); - }: _(RawOrigin::Signed(caller.clone()), collator.clone(), bond_less) - verify { - let state = Pallet::::delegator_state(&caller) - .expect("just request bonded less so exists"); - assert_eq!( - Pallet::::delegation_scheduled_requests(&collator), - vec![ScheduledRequest { - delegator: caller, - when_executable: 3, - action: DelegationAction::Decrease(bond_less), - }], - ); - } - - execute_revoke_delegation { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); - let bond = <::MinDelegatorStk as Get>>::get(); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - bond, - 0u32, - 0u32 - )?; - Pallet::::schedule_revoke_delegation(RawOrigin::Signed( - caller.clone()).into(), - collator.clone() - )?; - roll_to_and_author::(2, collator.clone()); - }: { - Pallet::::execute_delegation_request( - RawOrigin::Signed(caller.clone()).into(), - caller.clone(), - collator.clone() - )?; - } verify { - assert!( - !Pallet::::is_delegator(&caller) - ); - } - - execute_delegator_bond_less { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, total) = create_funded_user::("caller", USER_SEED, 0u32.into()); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - total, - 0u32, - 0u32 - )?; - let bond_less = <::MinDelegatorStk as Get>>::get(); - Pallet::::schedule_delegator_bond_less( - RawOrigin::Signed(caller.clone()).into(), - collator.clone(), - bond_less - )?; - roll_to_and_author::(2, collator.clone()); - }: { - Pallet::::execute_delegation_request( - RawOrigin::Signed(caller.clone()).into(), - caller.clone(), - collator.clone() - )?; - } verify { - let expected = total - bond_less; - assert_eq!( - Pallet::::delegator_state(&caller).expect("candidate was created, qed").total, - expected, - ); - } - - cancel_revoke_delegation { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, _) = create_funded_user::("caller", USER_SEED, 0u32.into()); - let bond = <::MinDelegatorStk as Get>>::get(); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - bond, - 0u32, - 0u32 - )?; - Pallet::::schedule_revoke_delegation( - RawOrigin::Signed(caller.clone()).into(), - collator.clone() - )?; - }: { - Pallet::::cancel_delegation_request( - RawOrigin::Signed(caller.clone()).into(), - collator.clone() - )?; - } verify { - assert!( - !Pallet::::delegation_scheduled_requests(&collator) - .iter() - .any(|x| &x.delegator == &caller) - ); - } - - cancel_delegator_bond_less { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let (caller, total) = create_funded_user::("caller", USER_SEED, 0u32.into()); - Pallet::::delegate(RawOrigin::Signed( - caller.clone()).into(), - collator.clone(), - total, - 0u32, - 0u32 - )?; - let bond_less = <::MinDelegatorStk as Get>>::get(); - Pallet::::schedule_delegator_bond_less( - RawOrigin::Signed(caller.clone()).into(), - collator.clone(), - bond_less - )?; - roll_to_and_author::(2, collator.clone()); - }: { - Pallet::::cancel_delegation_request( - RawOrigin::Signed(caller.clone()).into(), - collator.clone() - )?; - } verify { - assert!( - !Pallet::::delegation_scheduled_requests(&collator) - .iter() - .any(|x| &x.delegator == &caller) - ); - } - - // ON_INITIALIZE - - prepare_staking_payouts { - let reward_delay = <::RewardPaymentDelay as Get>::get(); - let round = reward_delay + 2u32; - let payout_round = round - reward_delay; - // may need: - // > - // > - // > - // ensure parachain bond account exists so that deposit_into_existing succeeds - >::insert(payout_round, 100); - >::insert(payout_round, min_candidate_stk::()); - - // set an account in the bond config so that we will measure the payout to it - let account = create_funded_user::( - "parachain_bond", - 0, - min_candidate_stk::(), - ).0; - >::put(ParachainBondConfig { - account, - percent: Percent::from_percent(50), - }); - - }: { Pallet::::prepare_staking_payouts(round); } - verify { - } - - get_rewardable_delegators { - let y in 0..<::MaxDelegationsPerDelegator as Get>::get(); // num delegators - - let high_inflation: Range = Range { - min: Perbill::one(), - ideal: Perbill::one(), - max: Perbill::one(), - }; - Pallet::::set_inflation(RawOrigin::Root.into(), high_inflation.clone())?; - Pallet::::set_blocks_per_round(RawOrigin::Root.into(), 101u32)?; - Pallet::::set_total_selected(RawOrigin::Root.into(), 100u32)?; - - let collator = create_funded_collator::( - "collator", - 0, - min_candidate_stk::() * 1_000_000u32.into(), - true, - 1, - )?; - - // create delegators - for i in 0..y { - let seed = USER_SEED + i + 1; - let delegator = create_funded_delegator::( - "delegator", - seed, - min_candidate_stk::() * 1_000_000u32.into(), - collator.clone(), - true, - i, - )?; - } - - let mut _results = None; - - }: { _results = Some(Pallet::::get_rewardable_delegators(&collator)); } - verify { - let counted_delegations = _results.expect("get_rewardable_delegators returned some results"); - assert!(counted_delegations.uncounted_stake == 0u32.into()); - assert!(counted_delegations.rewardable_delegations.len() as u32 == y); - let top_delegations = >::get(collator.clone()) - .expect("delegations were set for collator through delegate() calls"); - assert!(top_delegations.delegations.len() as u32 == y); - } - - select_top_candidates { - let x in 0..50; // num collators - let y in 0..<::MaxDelegationsPerDelegator as Get>::get(); // num delegators - - let high_inflation: Range = Range { - min: Perbill::one(), - ideal: Perbill::one(), - max: Perbill::one(), - }; - Pallet::::set_inflation(RawOrigin::Root.into(), high_inflation.clone())?; - Pallet::::set_blocks_per_round(RawOrigin::Root.into(), 101u32)?; - Pallet::::set_total_selected(RawOrigin::Root.into(), 100u32)?; - - let mut seed = USER_SEED + 1; - - for _ in 0..x { - let collator = create_funded_collator::( - "collator", - seed, - min_candidate_stk::() * 1_000_000u32.into(), - true, - 999999, - )?; - seed += 1; - - // create delegators - for _ in 0..y { - let delegator = create_funded_delegator::( - "delegator", - seed, - min_candidate_stk::() * 1_000_000u32.into(), - collator.clone(), - true, - 9999999, - )?; - seed += 1; - } - } - - }: { Pallet::::select_top_candidates(1); } - verify { - } - - pay_one_collator_reward { - // y controls number of delegations, its maximum per collator is the max top delegations - let y in 0..<::MaxTopDelegationsPerCandidate as Get>::get(); - - // must come after 'let foo in 0..` statements for macro - use crate::{ - DelayedPayout, DelayedPayouts, AtStake, CollatorSnapshot, BondWithAutoCompound, Points, - AwardedPts, - }; - - let before_running_round_index = Pallet::::round().current; - let initial_stake_amount = min_candidate_stk::() * 1_000_000u32.into(); - - let mut total_staked = 0u32.into(); - - // initialize our single collator - let sole_collator = create_funded_collator::( - "collator", - 0, - initial_stake_amount, - true, - 1u32, - )?; - total_staked += initial_stake_amount; - - // generate funded collator accounts - let mut delegators: Vec = Vec::new(); - for i in 0..y { - let seed = USER_SEED + i; - let delegator = create_funded_delegator::( - "delegator", - seed, - initial_stake_amount, - sole_collator.clone(), - true, - delegators.len() as u32, - )?; - delegators.push(delegator); - total_staked += initial_stake_amount; - } - - // rather than roll through rounds in order to initialize the storage we want, we set it - // directly and then call pay_one_collator_reward directly. - - let round_for_payout = 5; - >::insert(&round_for_payout, DelayedPayout { - // NOTE: round_issuance is not correct here, but it doesn't seem to cause problems - round_issuance: 1000u32.into(), - total_staking_reward: total_staked, - collator_commission: Perbill::from_rational(1u32, 100u32), - }); - - let mut delegations: Vec>> = Vec::new(); - for delegator in &delegators { - delegations.push(BondWithAutoCompound { - owner: delegator.clone(), - amount: 100u32.into(), - auto_compound: Percent::zero(), - }); - } - - >::insert(round_for_payout, &sole_collator, CollatorSnapshot { - bond: 1_000u32.into(), - delegations, - total: 1_000_000u32.into(), - }); - - >::insert(round_for_payout, 100); - >::insert(round_for_payout, &sole_collator, 20); - - }: { - let round_for_payout = 5; - // TODO: this is an extra read right here (we should whitelist it?) - let payout_info = Pallet::::delayed_payouts(round_for_payout).expect("payout expected"); - let result = Pallet::::pay_one_collator_reward(round_for_payout, payout_info); - // TODO: how to keep this in scope so it can be done in verify block? - assert!(matches!(result.0, RewardPayment::Paid)); - } - verify { - // collator should have been paid - assert!( - T::Currency::free_balance(&sole_collator) > initial_stake_amount, - "collator should have been paid in pay_one_collator_reward" - ); - // nominators should have been paid - for delegator in &delegators { - assert!( - T::Currency::free_balance(&delegator) > initial_stake_amount, - "delegator should have been paid in pay_one_collator_reward" - ); - } - } - - base_on_initialize { - let collator: T::AccountId = create_funded_collator::( - "collator", - USER_SEED, - 0u32.into(), - true, - 1u32 - )?; - let start = >::block_number(); - parachain_staking_on_finalize::(collator.clone()); - >::on_finalize(start); - >::set_block_number( - start + 1u32.into() - ); - let end = >::block_number(); - >::on_initialize(end); - }: { Pallet::::on_initialize(end); } - verify { - // Round transitions - assert_eq!(start + 1u32.into(), end); - } - - set_auto_compound { - // x controls number of distinct auto-compounding delegations the prime collator will have - // y controls number of distinct delegations the prime delegator will have - let x in 0..<::MaxTopDelegationsPerCandidate as Get>::get(); - let y in 0..<::MaxDelegationsPerDelegator as Get>::get(); - - use crate::auto_compound::AutoCompoundDelegations; - - let min_candidate_stake = min_candidate_stk::(); - let min_delegator_stake = min_delegator_stk::(); - let mut seed = Seed::new(); - - // initialize the prime collator - let prime_candidate = create_funded_collator::( - "collator", - seed.take(), - min_candidate_stake, - true, - 1, - )?; - - // initialize the prime delegator - let prime_delegator = create_funded_delegator::( - "delegator", - seed.take(), - min_delegator_stake * (y+1).into(), - prime_candidate.clone(), - true, - 0, - )?; - - // have x-1 distinct auto-compounding delegators delegate to prime collator - // we directly set the storage, since benchmarks don't work when the same extrinsic is - // called from within the benchmark. - let mut auto_compounding_state = >::get_storage(&prime_candidate); - for i in 1..x { - let delegator = create_funded_delegator::( - "delegator", - seed.take(), - min_delegator_stake, - prime_candidate.clone(), - true, - i, - )?; - auto_compounding_state.set_for_delegator( - delegator, - Percent::from_percent(100), - ).expect("must succeed"); - } - auto_compounding_state.set_storage(&prime_candidate); - - // delegate to y-1 distinct collators from the prime delegator - for i in 1..y { - let collator = create_funded_collator::( - "collator", - seed.take(), - min_candidate_stake, - true, - i+1, - )?; - Pallet::::delegate( - RawOrigin::Signed(prime_delegator.clone()).into(), - collator, - min_delegator_stake, - 0, - i, - )?; - } - }: { - Pallet::::set_auto_compound( - RawOrigin::Signed(prime_delegator.clone()).into(), - prime_candidate.clone(), - Percent::from_percent(50), - x, - y+1, - )?; - } - verify { - let actual_auto_compound = >::get_storage(&prime_candidate) - .get_for_delegator(&prime_delegator); - let expected_auto_compound = Some(Percent::from_percent(50)); - assert_eq!( - expected_auto_compound, - actual_auto_compound, - "delegation must have an auto-compound entry", - ); - } - - delegate_with_auto_compound { - // x controls number of distinct delegations the prime collator will have - // y controls number of distinct auto-compounding delegations the prime collator will have - // z controls number of distinct delegations the prime delegator will have - let x in 0..(<::MaxTopDelegationsPerCandidate as Get>::get() - + <::MaxBottomDelegationsPerCandidate as Get>::get()); - let y in 0..<::MaxTopDelegationsPerCandidate as Get>::get() - + <::MaxBottomDelegationsPerCandidate as Get>::get(); - let z in 0..<::MaxDelegationsPerDelegator as Get>::get(); - - use crate::auto_compound::AutoCompoundDelegations; - - let min_candidate_stake = min_candidate_stk::(); - let min_delegator_stake = min_delegator_stk::(); - let mut seed = Seed::new(); - - // initialize the prime collator - let prime_candidate = create_funded_collator::( - "collator", - seed.take(), - min_candidate_stake, - true, - 1, - )?; - - // initialize the future delegator - let (prime_delegator, _) = create_funded_user::( - "delegator", - seed.take(), - min_delegator_stake * (z+1).into(), - ); - - // have x-1 distinct delegators delegate to prime collator, of which y are auto-compounding. - // we can directly set the storage here. - let auto_compound_z = x * y / 100; - for i in 1..x { - let delegator = create_funded_delegator::( - "delegator", - seed.take(), - min_delegator_stake, - prime_candidate.clone(), - true, - i, - )?; - if i <= y { - Pallet::::set_auto_compound( - RawOrigin::Signed(delegator.clone()).into(), - prime_candidate.clone(), - Percent::from_percent(100), - i+1, - i, - )?; - } - } - - // delegate to z-1 distinct collators from the prime delegator - for i in 1..z { - let collator = create_funded_collator::( - "collator", - seed.take(), - min_candidate_stake, - true, - i+1, - )?; - Pallet::::delegate( - RawOrigin::Signed(prime_delegator.clone()).into(), - collator, - min_delegator_stake, - 0, - i, - )?; - } - }: { - Pallet::::delegate_with_auto_compound( - RawOrigin::Signed(prime_delegator.clone()).into(), - prime_candidate.clone(), - min_delegator_stake, - Percent::from_percent(50), - x, - y, - z, - )?; - } - verify { - assert!(Pallet::::is_delegator(&prime_delegator)); - let actual_auto_compound = >::get_storage(&prime_candidate) - .get_for_delegator(&prime_delegator); - let expected_auto_compound = Some(Percent::from_percent(50)); - assert_eq!( - expected_auto_compound, - actual_auto_compound, - "delegation must have an auto-compound entry", - ); - } - - mint_collator_reward { - let mut seed = Seed::new(); - let collator = create_funded_collator::( - "collator", - seed.take(), - 0u32.into(), - true, - 1, - )?; - let original_free_balance = T::Currency::free_balance(&collator); - }: { - Pallet::::mint_collator_reward(1u32.into(), collator.clone(), 50u32.into()) - } - verify { - assert_eq!(T::Currency::free_balance(&collator), original_free_balance + 50u32.into()); - } -} - -#[cfg(test)] -mod tests { - use crate::{benchmarks::*, mock::Test}; - use frame_support::assert_ok; - use sp_io::TestExternalities; - - pub fn new_test_ext() -> TestExternalities { - let t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - TestExternalities::new(t) - } - - #[test] - fn bench_set_staking_expectations() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_staking_expectations()); - }); - } - - #[test] - fn bench_set_inflation() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_inflation()); - }); - } - - #[test] - fn bench_set_parachain_bond_account() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_parachain_bond_account()); - }); - } - - #[test] - fn bench_set_parachain_bond_reserve_percent() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_parachain_bond_reserve_percent()); - }); - } - - #[test] - fn bench_set_total_selected() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_total_selected()); - }); - } - - #[test] - fn bench_set_collator_commission() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_collator_commission()); - }); - } - - #[test] - fn bench_set_blocks_per_round() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_set_blocks_per_round()); - }); - } - - #[test] - fn bench_join_candidates() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_join_candidates()); - }); - } - - #[test] - fn bench_schedule_leave_candidates() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_schedule_leave_candidates()); - }); - } - - #[test] - fn bench_execute_leave_candidates() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_execute_leave_candidates()); - }); - } - - #[test] - fn bench_cancel_leave_candidates() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_cancel_leave_candidates()); - }); - } - - #[test] - fn bench_go_offline() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_go_offline()); - }); - } - - #[test] - fn bench_go_online() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_go_online()); - }); - } - - #[test] - fn bench_candidate_bond_more() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_candidate_bond_more()); - }); - } - - #[test] - fn bench_schedule_candidate_bond_less() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_schedule_candidate_bond_less()); - }); - } - - #[test] - fn bench_execute_candidate_bond_less() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_execute_candidate_bond_less()); - }); - } - - #[test] - fn bench_cancel_candidate_bond_less() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_cancel_candidate_bond_less()); - }); - } - - #[test] - fn bench_delegate() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_delegate()); - }); - } - - #[test] - fn bench_schedule_leave_delegators() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_schedule_leave_delegators()); - }); - } - - #[test] - fn bench_execute_leave_delegators() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_execute_leave_delegators()); - }); - } - - #[test] - fn bench_cancel_leave_delegators() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_cancel_leave_delegators()); - }); - } - - #[test] - fn bench_schedule_revoke_delegation() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_schedule_revoke_delegation()); - }); - } - - #[test] - fn bench_delegator_bond_more() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_delegator_bond_more()); - }); - } - - #[test] - fn bench_schedule_delegator_bond_less() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_schedule_delegator_bond_less()); - }); - } - - #[test] - fn bench_execute_revoke_delegation() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_execute_revoke_delegation()); - }); - } - - #[test] - fn bench_execute_delegator_bond_less() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_execute_delegator_bond_less()); - }); - } - - #[test] - fn bench_cancel_revoke_delegation() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_cancel_revoke_delegation()); - }); - } - - #[test] - fn bench_cancel_delegator_bond_less() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_cancel_delegator_bond_less()); - }); - } - - #[test] - fn bench_base_on_initialize() { - new_test_ext().execute_with(|| { - assert_ok!(Pallet::::test_benchmark_base_on_initialize()); - }); - } -} - -impl_benchmark_test_suite!(Pallet, crate::benchmarks::tests::new_test_ext(), crate::mock::Test); diff --git a/pallets/parachain-staking/src/delegation_requests.rs b/pallets/parachain-staking/src/delegation_requests.rs deleted file mode 100644 index c1beb3d80..000000000 --- a/pallets/parachain-staking/src/delegation_requests.rs +++ /dev/null @@ -1,653 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam 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. - -// Moonbeam 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 Moonbeam. If not, see . - -//! Scheduled requests functionality for delegators - -use crate::{ - auto_compound::AutoCompoundDelegations, - pallet::{ - BalanceOf, CandidateInfo, Config, DelegationScheduledRequests, DelegatorState, Error, - Event, Pallet, Round, RoundIndex, Total, - }, - Delegator, DelegatorStatus, -}; -use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, traits::Get, RuntimeDebug}; -use parity_scale_codec::{Decode, Encode}; -use scale_info::TypeInfo; -use sp_runtime::traits::Saturating; -use sp_std::{vec, vec::Vec}; - -/// An action that can be performed upon a delegation -#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, PartialOrd, Ord)] -pub enum DelegationAction { - Revoke(Balance), - Decrease(Balance), -} - -impl DelegationAction { - /// Returns the wrapped amount value. - pub fn amount(&self) -> Balance { - match self { - DelegationAction::Revoke(amount) => *amount, - DelegationAction::Decrease(amount) => *amount, - } - } -} - -/// Represents a scheduled request that define a [DelegationAction]. The request is executable -/// iff the provided [RoundIndex] is achieved. -#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo, PartialOrd, Ord)] -pub struct ScheduledRequest { - pub delegator: AccountId, - pub when_executable: RoundIndex, - pub action: DelegationAction, -} - -/// Represents a cancelled scheduled request for emitting an event. -#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] -pub struct CancelledScheduledRequest { - pub when_executable: RoundIndex, - pub action: DelegationAction, -} - -impl From> for CancelledScheduledRequest { - fn from(request: ScheduledRequest) -> Self { - CancelledScheduledRequest { - when_executable: request.when_executable, - action: request.action, - } - } -} - -impl Pallet { - /// Schedules a [DelegationAction::Revoke] for the delegator, towards a given collator. - pub(crate) fn delegation_schedule_revoke( - collator: T::AccountId, - delegator: T::AccountId, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - let mut scheduled_requests = >::get(&collator); - - ensure!( - !scheduled_requests.iter().any(|req| req.delegator == delegator), - >::PendingDelegationRequestAlreadyExists, - ); - - let bonded_amount = state.get_bond_amount(&collator).ok_or(>::DelegationDNE)?; - let now = >::get().current; - let when = now.saturating_add(T::RevokeDelegationDelay::get()); - scheduled_requests.push(ScheduledRequest { - delegator: delegator.clone(), - action: DelegationAction::Revoke(bonded_amount), - when_executable: when, - }); - state.less_total = state.less_total.saturating_add(bonded_amount); - >::insert(collator.clone(), scheduled_requests); - >::insert(delegator.clone(), state); - - Self::deposit_event(Event::DelegationRevocationScheduled { - round: now, - delegator, - candidate: collator, - scheduled_exit: when, - }); - Ok(().into()) - } - - /// Schedules a [DelegationAction::Decrease] for the delegator, towards a given collator. - pub(crate) fn delegation_schedule_bond_decrease( - collator: T::AccountId, - delegator: T::AccountId, - decrease_amount: BalanceOf, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - let mut scheduled_requests = >::get(&collator); - - ensure!( - !scheduled_requests.iter().any(|req| req.delegator == delegator), - >::PendingDelegationRequestAlreadyExists, - ); - - let bonded_amount = state.get_bond_amount(&collator).ok_or(>::DelegationDNE)?; - ensure!(bonded_amount > decrease_amount, >::DelegatorBondBelowMin); - let new_amount: BalanceOf = bonded_amount - decrease_amount; - ensure!(new_amount >= T::MinDelegation::get(), >::DelegationBelowMin); - - // Net Total is total after pending orders are executed - let net_total = state.total().saturating_sub(state.less_total); - // Net Total is always >= MinDelegatorStk - let max_subtracted_amount = net_total.saturating_sub(T::MinDelegatorStk::get()); - ensure!(decrease_amount <= max_subtracted_amount, >::DelegatorBondBelowMin); - - let now = >::get().current; - let when = now.saturating_add(T::RevokeDelegationDelay::get()); - scheduled_requests.push(ScheduledRequest { - delegator: delegator.clone(), - action: DelegationAction::Decrease(decrease_amount), - when_executable: when, - }); - state.less_total = state.less_total.saturating_add(decrease_amount); - >::insert(collator.clone(), scheduled_requests); - >::insert(delegator.clone(), state); - - Self::deposit_event(Event::DelegationDecreaseScheduled { - delegator, - candidate: collator, - amount_to_decrease: decrease_amount, - execute_round: when, - }); - Ok(().into()) - } - - /// Cancels the delegator's existing [ScheduledRequest] towards a given collator. - pub(crate) fn delegation_cancel_request( - collator: T::AccountId, - delegator: T::AccountId, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - let mut scheduled_requests = >::get(&collator); - - let request = - Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests) - .ok_or(>::PendingDelegationRequestDNE)?; - - >::insert(collator.clone(), scheduled_requests); - >::insert(delegator.clone(), state); - - Self::deposit_event(Event::CancelledDelegationRequest { - delegator, - collator, - cancelled_request: request.into(), - }); - Ok(().into()) - } - - fn cancel_request_with_state( - delegator: &T::AccountId, - state: &mut Delegator>, - scheduled_requests: &mut Vec>>, - ) -> Option>> { - let request_idx = scheduled_requests.iter().position(|req| &req.delegator == delegator)?; - - let request = scheduled_requests.remove(request_idx); - let amount = request.action.amount(); - state.less_total = state.less_total.saturating_sub(amount); - Some(request) - } - - /// Executes the delegator's existing [ScheduledRequest] towards a given collator. - pub(crate) fn delegation_execute_scheduled_request( - collator: T::AccountId, - delegator: T::AccountId, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - let mut scheduled_requests = >::get(&collator); - let request_idx = scheduled_requests - .iter() - .position(|req| req.delegator == delegator) - .ok_or(>::PendingDelegationRequestDNE)?; - let request = &scheduled_requests[request_idx]; - - let now = >::get().current; - ensure!(request.when_executable <= now, >::PendingDelegationRequestNotDueYet); - - match request.action { - DelegationAction::Revoke(amount) => { - // revoking last delegation => leaving set of delegators - let leaving = if state.delegations.0.len() == 1usize { - true - } else { - ensure!( - state.total().saturating_sub(T::MinDelegatorStk::get()) >= amount, - >::DelegatorBondBelowMin - ); - false - }; - - // remove from pending requests - let amount = scheduled_requests.remove(request_idx).action.amount(); - state.less_total = state.less_total.saturating_sub(amount); - - // remove delegation from delegator state - state.rm_delegation::(&collator); - - // remove delegation from auto-compounding info - >::remove_auto_compound(&collator, &delegator); - - // remove delegation from collator state delegations - Self::delegator_leaves_candidate(collator.clone(), delegator.clone(), amount)?; - Self::deposit_event(Event::DelegationRevoked { - delegator: delegator.clone(), - candidate: collator.clone(), - unstaked_amount: amount, - }); - - >::insert(collator, scheduled_requests); - if leaving { - >::remove(&delegator); - Self::deposit_event(Event::DelegatorLeft { - delegator, - unstaked_amount: amount, - }); - } else { - >::insert(&delegator, state); - } - Ok(().into()) - }, - DelegationAction::Decrease(_) => { - // remove from pending requests - let amount = scheduled_requests.remove(request_idx).action.amount(); - state.less_total = state.less_total.saturating_sub(amount); - - // decrease delegation - for bond in &mut state.delegations.0 { - if bond.owner == collator { - return if bond.amount > amount { - let amount_before: BalanceOf = bond.amount; - bond.amount = bond.amount.saturating_sub(amount); - let mut collator_info = >::get(&collator) - .ok_or(>::CandidateDNE)?; - - state.total_sub_if::(amount, |total| { - let new_total: BalanceOf = total; - ensure!( - new_total >= T::MinDelegation::get(), - >::DelegationBelowMin - ); - ensure!( - new_total >= T::MinDelegatorStk::get(), - >::DelegatorBondBelowMin - ); - - Ok(()) - })?; - - // need to go into decrease_delegation - let in_top = collator_info.decrease_delegation::( - &collator, - delegator.clone(), - amount_before, - amount, - )?; - >::insert(&collator, collator_info); - let new_total_staked = >::get().saturating_sub(amount); - >::put(new_total_staked); - - >::insert( - collator.clone(), - scheduled_requests, - ); - >::insert(delegator.clone(), state); - Self::deposit_event(Event::DelegationDecreased { - delegator, - candidate: collator.clone(), - amount, - in_top, - }); - Ok(().into()) - } else { - // must rm entire delegation if bond.amount <= less or cancel request - Err(>::DelegationBelowMin.into()) - } - } - } - Err(>::DelegationDNE.into()) - }, - } - } - - /// Schedules [DelegationAction::Revoke] for the delegator, towards all delegated collator. - /// The last fulfilled request causes the delegator to leave the set of delegators. - pub(crate) fn delegator_schedule_revoke_all( - delegator: T::AccountId, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - let mut updated_scheduled_requests = vec![]; - let now = >::get().current; - let when = now.saturating_add(T::LeaveDelegatorsDelay::get()); - - // lazy migration for DelegatorStatus::Leaving - #[allow(deprecated)] - if matches!(state.status, DelegatorStatus::Leaving(_)) { - state.status = DelegatorStatus::Active; - >::insert(delegator.clone(), state.clone()); - } - - // it is assumed that a multiple delegations to the same collator does not exist, else this - // will cause a bug - the last duplicate delegation update will be the only one applied. - let mut existing_revoke_count = 0; - for bond in state.delegations.0.clone() { - let collator = bond.owner; - let bonded_amount = bond.amount; - let mut scheduled_requests = >::get(&collator); - - // cancel any existing requests - let request = - Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests); - let request = match request { - Some(revoke_req) if matches!(revoke_req.action, DelegationAction::Revoke(_)) => { - existing_revoke_count += 1; - revoke_req // re-insert the same Revoke request - }, - _ => ScheduledRequest { - delegator: delegator.clone(), - action: DelegationAction::Revoke(bonded_amount), - when_executable: when, - }, - }; - - scheduled_requests.push(request); - state.less_total = state.less_total.saturating_add(bonded_amount); - updated_scheduled_requests.push((collator, scheduled_requests)); - } - - if existing_revoke_count == state.delegations.0.len() { - return Err(>::DelegatorAlreadyLeaving.into()) - } - - updated_scheduled_requests - .into_iter() - .for_each(|(collator, scheduled_requests)| { - >::insert(collator, scheduled_requests); - }); - - >::insert(delegator.clone(), state); - Self::deposit_event(Event::DelegatorExitScheduled { - round: now, - delegator, - scheduled_exit: when, - }); - Ok(().into()) - } - - /// Cancels every [DelegationAction::Revoke] request for a delegator towards a collator. - /// Each delegation must have a [DelegationAction::Revoke] scheduled that must be allowed to be - /// executed in the current round, for this function to succeed. - pub(crate) fn delegator_cancel_scheduled_revoke_all( - delegator: T::AccountId, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - let mut updated_scheduled_requests = vec![]; - - // backwards compatible handling for DelegatorStatus::Leaving - #[allow(deprecated)] - if matches!(state.status, DelegatorStatus::Leaving(_)) { - state.status = DelegatorStatus::Active; - >::insert(delegator.clone(), state.clone()); - Self::deposit_event(Event::DelegatorExitCancelled { delegator }); - return Ok(().into()) - } - - // pre-validate that all delegations have a Revoke request. - for bond in &state.delegations.0 { - let collator = bond.owner.clone(); - let scheduled_requests = >::get(&collator); - scheduled_requests - .iter() - .find(|req| { - req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) - }) - .ok_or(>::DelegatorNotLeaving)?; - } - - // cancel all requests - for bond in state.delegations.0.clone() { - let collator = bond.owner.clone(); - let mut scheduled_requests = >::get(&collator); - Self::cancel_request_with_state(&delegator, &mut state, &mut scheduled_requests); - updated_scheduled_requests.push((collator, scheduled_requests)); - } - - updated_scheduled_requests - .into_iter() - .for_each(|(collator, scheduled_requests)| { - >::insert(collator, scheduled_requests); - }); - - >::insert(delegator.clone(), state); - Self::deposit_event(Event::DelegatorExitCancelled { delegator }); - - Ok(().into()) - } - - /// Executes every [DelegationAction::Revoke] request for a delegator towards a collator. - /// Each delegation must have a [DelegationAction::Revoke] scheduled that must be allowed to be - /// executed in the current round, for this function to succeed. - pub(crate) fn delegator_execute_scheduled_revoke_all( - delegator: T::AccountId, - delegation_count: u32, - ) -> DispatchResultWithPostInfo { - let mut state = >::get(&delegator).ok_or(>::DelegatorDNE)?; - ensure!( - delegation_count >= (state.delegations.0.len() as u32), - Error::::TooLowDelegationCountToLeaveDelegators - ); - let now = >::get().current; - - // backwards compatible handling for DelegatorStatus::Leaving - #[allow(deprecated)] - if let DelegatorStatus::Leaving(when) = state.status { - ensure!(>::get().current >= when, Error::::DelegatorCannotLeaveYet); - - for bond in state.delegations.0.clone() { - if let Err(error) = Self::delegator_leaves_candidate( - bond.owner.clone(), - delegator.clone(), - bond.amount, - ) { - log::warn!( - "STORAGE CORRUPTED \nDelegator leaving collator failed with error: {:?}", - error - ); - } - - Self::delegation_remove_request_with_state(&bond.owner, &delegator, &mut state); - >::remove_auto_compound(&bond.owner, &delegator); - } - >::remove(&delegator); - Self::deposit_event(Event::DelegatorLeft { delegator, unstaked_amount: state.total }); - return Ok(().into()) - } - - let mut validated_scheduled_requests = vec![]; - // pre-validate that all delegations have a Revoke request that can be executed now. - for bond in &state.delegations.0 { - let scheduled_requests = >::get(&bond.owner); - let request_idx = scheduled_requests - .iter() - .position(|req| { - req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) - }) - .ok_or(>::DelegatorNotLeaving)?; - let request = &scheduled_requests[request_idx]; - - ensure!(request.when_executable <= now, >::DelegatorCannotLeaveYet); - - validated_scheduled_requests.push((bond.clone(), scheduled_requests, request_idx)) - } - - let mut updated_scheduled_requests = vec![]; - // we do not update the delegator state, since the it will be completely removed - for (bond, mut scheduled_requests, request_idx) in validated_scheduled_requests { - let collator = bond.owner; - - if let Err(error) = - Self::delegator_leaves_candidate(collator.clone(), delegator.clone(), bond.amount) - { - log::warn!( - "STORAGE CORRUPTED \nDelegator {:?} leaving collator failed with error: {:?}", - delegator, - error - ); - } - - // remove the scheduled request, since it is fulfilled - scheduled_requests.remove(request_idx).action.amount(); - updated_scheduled_requests.push((collator.clone(), scheduled_requests)); - - // remove the auto-compounding entry for the delegation - >::remove_auto_compound(&collator, &delegator); - } - - // set state.total so that state.adjust_bond_lock will remove lock - let unstaked_amount = state.total(); - state.total_sub::(unstaked_amount)?; - - updated_scheduled_requests - .into_iter() - .for_each(|(collator, scheduled_requests)| { - >::insert(collator, scheduled_requests); - }); - - Self::deposit_event(Event::DelegatorLeft { delegator: delegator.clone(), unstaked_amount }); - >::remove(&delegator); - - Ok(().into()) - } - - /// Removes the delegator's existing [ScheduledRequest] towards a given collator, if exists. - /// The state needs to be persisted by the caller of this function. - pub(crate) fn delegation_remove_request_with_state( - collator: &T::AccountId, - delegator: &T::AccountId, - state: &mut Delegator>, - ) { - let mut scheduled_requests = >::get(collator); - - let maybe_request_idx = - scheduled_requests.iter().position(|req| &req.delegator == delegator); - - if let Some(request_idx) = maybe_request_idx { - let request = scheduled_requests.remove(request_idx); - let amount = request.action.amount(); - state.less_total = state.less_total.saturating_sub(amount); - >::insert(collator, scheduled_requests); - } - } - - /// Returns true if a [ScheduledRequest] exists for a given delegation - pub fn delegation_request_exists(collator: &T::AccountId, delegator: &T::AccountId) -> bool { - >::get(collator) - .iter() - .any(|req| &req.delegator == delegator) - } - - /// Returns true if a [DelegationAction::Revoke] [ScheduledRequest] exists for a given delegation - pub fn delegation_request_revoke_exists( - collator: &T::AccountId, - delegator: &T::AccountId, - ) -> bool { - >::get(collator).iter().any(|req| { - &req.delegator == delegator && matches!(req.action, DelegationAction::Revoke(_)) - }) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{mock::Test, set::OrderedSet, Bond}; - - #[test] - fn test_cancel_request_with_state_removes_request_for_correct_delegator_and_updates_state() { - let mut state = Delegator { - id: 1, - delegations: OrderedSet::from(vec![Bond { amount: 100, owner: 2 }]), - total: 100, - less_total: 100, - status: crate::DelegatorStatus::Active, - }; - let mut scheduled_requests = vec![ - ScheduledRequest { - delegator: 1, - when_executable: 1, - action: DelegationAction::Revoke(100), - }, - ScheduledRequest { - delegator: 2, - when_executable: 1, - action: DelegationAction::Decrease(50), - }, - ]; - let removed_request = - >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); - - assert_eq!( - removed_request, - Some(ScheduledRequest { - delegator: 1, - when_executable: 1, - action: DelegationAction::Revoke(100), - }) - ); - assert_eq!( - scheduled_requests, - vec![ScheduledRequest { - delegator: 2, - when_executable: 1, - action: DelegationAction::Decrease(50), - },] - ); - assert_eq!( - state, - Delegator { - id: 1, - delegations: OrderedSet::from(vec![Bond { amount: 100, owner: 2 }]), - total: 100, - less_total: 0, - status: crate::DelegatorStatus::Active, - } - ); - } - - #[test] - fn test_cancel_request_with_state_does_nothing_when_request_does_not_exist() { - let mut state = Delegator { - id: 1, - delegations: OrderedSet::from(vec![Bond { amount: 100, owner: 2 }]), - total: 100, - less_total: 100, - status: crate::DelegatorStatus::Active, - }; - let mut scheduled_requests = vec![ScheduledRequest { - delegator: 2, - when_executable: 1, - action: DelegationAction::Decrease(50), - }]; - let removed_request = - >::cancel_request_with_state(&1, &mut state, &mut scheduled_requests); - - assert_eq!(removed_request, None,); - assert_eq!( - scheduled_requests, - vec![ScheduledRequest { - delegator: 2, - when_executable: 1, - action: DelegationAction::Decrease(50), - },] - ); - assert_eq!( - state, - Delegator { - id: 1, - delegations: OrderedSet::from(vec![Bond { amount: 100, owner: 2 }]), - total: 100, - less_total: 100, - status: crate::DelegatorStatus::Active, - } - ); - } -} diff --git a/pallets/parachain-staking/src/inflation.rs b/pallets/parachain-staking/src/inflation.rs deleted file mode 100644 index e6c6778d7..000000000 --- a/pallets/parachain-staking/src/inflation.rs +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam 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. - -// Moonbeam 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 Moonbeam. If not, see . - -//! Helper methods for computing issuance based on inflation -use crate::pallet::{BalanceOf, Config, Pallet}; -use frame_support::traits::Currency; -use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; -use scale_info::TypeInfo; -#[cfg(feature = "std")] -use serde::{Deserialize, Serialize}; -use sp_runtime::{PerThing, Perbill, RuntimeDebug}; -use substrate_fixed::{transcendental::pow as floatpow, types::I64F64}; - -const SECONDS_PER_YEAR: u32 = 31557600; -const SECONDS_PER_BLOCK: u32 = 12; -pub const BLOCKS_PER_YEAR: u32 = SECONDS_PER_YEAR / SECONDS_PER_BLOCK; - -fn rounds_per_year() -> u32 { - let blocks_per_round = >::round().length; - BLOCKS_PER_YEAR / blocks_per_round -} - -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[derive( - Eq, PartialEq, Clone, Copy, Encode, Decode, Default, RuntimeDebug, MaxEncodedLen, TypeInfo, -)] -pub struct Range { - pub min: T, - pub ideal: T, - pub max: T, -} - -impl Range { - pub fn is_valid(&self) -> bool { - self.max >= self.ideal && self.ideal >= self.min - } -} - -impl From for Range { - fn from(other: T) -> Range { - Range { min: other, ideal: other, max: other } - } -} -/// Convert an annual inflation to a round inflation -/// round = (1+annual)^(1/rounds_per_year) - 1 -pub fn perbill_annual_to_perbill_round( - annual: Range, - rounds_per_year: u32, -) -> Range { - let exponent = I64F64::from_num(1) / I64F64::from_num(rounds_per_year); - let annual_to_round = |annual: Perbill| -> Perbill { - let x = I64F64::from_num(annual.deconstruct()) / I64F64::from_num(Perbill::ACCURACY); - let y: I64F64 = floatpow(I64F64::from_num(1) + x, exponent) - .expect("Cannot overflow since rounds_per_year is u32 so worst case 0; QED"); - Perbill::from_parts( - ((y - I64F64::from_num(1)) * I64F64::from_num(Perbill::ACCURACY)) - .ceil() - .to_num::(), - ) - }; - Range { - min: annual_to_round(annual.min), - ideal: annual_to_round(annual.ideal), - max: annual_to_round(annual.max), - } -} -/// Convert annual inflation rate range to round inflation range -pub fn annual_to_round(annual: Range) -> Range { - let periods = rounds_per_year::(); - perbill_annual_to_perbill_round(annual, periods) -} - -/// Compute round issuance range from round inflation range and current total issuance -pub fn round_issuance_range(round: Range) -> Range> { - let circulating = T::Currency::total_issuance(); - Range { - min: round.min * circulating, - ideal: round.ideal * circulating, - max: round.max * circulating, - } -} - -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[derive(Eq, PartialEq, Clone, Encode, Decode, Default, RuntimeDebug, TypeInfo)] -pub struct InflationInfo { - /// Staking expectations - pub expect: Range, - /// Annual inflation range - pub annual: Range, - /// Round inflation range - pub round: Range, -} - -impl InflationInfo { - pub fn new( - annual: Range, - expect: Range, - ) -> InflationInfo { - InflationInfo { expect, annual, round: annual_to_round::(annual) } - } - /// Set round inflation range according to input annual inflation range - pub fn set_round_from_annual(&mut self, new: Range) { - self.round = annual_to_round::(new); - } - /// Reset round inflation rate based on changes to round length - pub fn reset_round(&mut self, new_length: u32) { - let periods = BLOCKS_PER_YEAR / new_length; - self.round = perbill_annual_to_perbill_round(self.annual, periods); - } - /// Set staking expectations - pub fn set_expectations(&mut self, expect: Range) { - self.expect = expect; - } -} - -#[cfg(test)] -mod tests { - use super::*; - fn mock_annual_to_round(annual: Range, rounds_per_year: u32) -> Range { - perbill_annual_to_perbill_round(annual, rounds_per_year) - } - fn mock_round_issuance_range( - // Total circulating before minting - circulating: u128, - // Round inflation range - round: Range, - ) -> Range { - Range { - min: round.min * circulating, - ideal: round.ideal * circulating, - max: round.max * circulating, - } - } - #[test] - fn simple_issuance_conversion() { - // 5% inflation for 10_000_0000 = 500,000 minted over the year - // let's assume there are 10 periods in a year - // => mint 500_000 over 10 periods => 50_000 minted per period - let expected_round_issuance_range: Range = - Range { min: 48_909, ideal: 48_909, max: 48_909 }; - let schedule = Range { - min: Perbill::from_percent(5), - ideal: Perbill::from_percent(5), - max: Perbill::from_percent(5), - }; - assert_eq!( - expected_round_issuance_range, - mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 10)) - ); - } - #[test] - fn range_issuance_conversion() { - // 3-5% inflation for 10_000_0000 = 300_000-500,000 minted over the year - // let's assume there are 10 periods in a year - // => mint 300_000-500_000 over 10 periods => 30_000-50_000 minted per period - let expected_round_issuance_range: Range = - Range { min: 29_603, ideal: 39298, max: 48_909 }; - let schedule = Range { - min: Perbill::from_percent(3), - ideal: Perbill::from_percent(4), - max: Perbill::from_percent(5), - }; - assert_eq!( - expected_round_issuance_range, - mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 10)) - ); - } - #[test] - fn expected_parameterization() { - let expected_round_schedule: Range = Range { min: 45, ideal: 56, max: 56 }; - let schedule = Range { - min: Perbill::from_percent(4), - ideal: Perbill::from_percent(5), - max: Perbill::from_percent(5), - }; - assert_eq!( - expected_round_schedule, - mock_round_issuance_range(10_000_000, mock_annual_to_round(schedule, 8766)) - ); - } - #[test] - fn inflation_does_not_panic_at_round_number_limit() { - let schedule = Range { - min: Perbill::from_percent(100), - ideal: Perbill::from_percent(100), - max: Perbill::from_percent(100), - }; - mock_round_issuance_range(u32::MAX.into(), mock_annual_to_round(schedule, u32::MAX)); - mock_round_issuance_range(u64::MAX.into(), mock_annual_to_round(schedule, u32::MAX)); - mock_round_issuance_range(u128::MAX.into(), mock_annual_to_round(schedule, u32::MAX)); - mock_round_issuance_range(u32::MAX.into(), mock_annual_to_round(schedule, 1)); - mock_round_issuance_range(u64::MAX.into(), mock_annual_to_round(schedule, 1)); - mock_round_issuance_range(u128::MAX.into(), mock_annual_to_round(schedule, 1)); - } -} diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs deleted file mode 100644 index 0ed5d4e24..000000000 --- a/pallets/parachain-staking/src/lib.rs +++ /dev/null @@ -1,2011 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam 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. - -// Moonbeam 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 Moonbeam. If not, see . - -//! # Parachain Staking -//! Minimal staking pallet that implements collator selection by total backed stake. -//! The main difference between this pallet and `frame/pallet-staking` is that this pallet -//! uses direct delegation. Delegators choose exactly who they delegate and with what stake. -//! This is different from `frame/pallet-staking` where delegators approval vote and run Phragmen. -//! -//! ### Rules -//! There is a new round every `>::get().length` blocks. -//! -//! At the start of every round, -//! * issuance is calculated for collators (and their delegators) for block authoring -//! `T::RewardPaymentDelay` rounds ago -//! * a new set of collators is chosen from the candidates -//! -//! Immediately following a round change, payments are made once-per-block until all payments have -//! been made. In each such block, one collator is chosen for a rewards payment and is paid along -//! with each of its top `T::MaxTopDelegationsPerCandidate` delegators. -//! -//! To join the set of candidates, call `join_candidates` with `bond >= MinCandidateStk`. -//! To leave the set of candidates, call `schedule_leave_candidates`. If the call succeeds, -//! the collator is removed from the pool of candidates so they cannot be selected for future -//! collator sets, but they are not unbonded until their exit request is executed. Any signed -//! account may trigger the exit `T::LeaveCandidatesDelay` rounds after the round in which the -//! original request was made. -//! -//! To join the set of delegators, call `delegate` and pass in an account that is -//! already a collator candidate and `bond >= MinDelegatorStk`. Each delegator can delegate up to -//! `T::MaxDelegationsPerDelegator` collator candidates by calling `delegate`. -//! -//! To revoke a delegation, call `revoke_delegation` with the collator candidate's account. -//! To leave the set of delegators and revoke all delegations, call `leave_delegators`. - -#![cfg_attr(not(feature = "std"), no_std)] - -mod auto_compound; -mod delegation_requests; -pub mod inflation; -pub mod migrations; -pub mod traits; -pub mod types; -pub mod weights; - -#[cfg(any(test, feature = "runtime-benchmarks"))] -mod benchmarks; -#[cfg(test)] -mod mock; -mod set; -#[cfg(test)] -mod tests; - -use frame_support::pallet; -pub use inflation::{InflationInfo, Range}; -use weights::WeightInfo; - -pub use auto_compound::{AutoCompoundConfig, AutoCompoundDelegations}; -pub use delegation_requests::{CancelledScheduledRequest, DelegationAction, ScheduledRequest}; -pub use pallet::*; -pub use traits::*; -pub use types::*; -pub use RoundIndex; - -#[pallet] -pub mod pallet { - use crate::{ - delegation_requests::{CancelledScheduledRequest, DelegationAction, ScheduledRequest}, - set::OrderedSet, - traits::*, - types::*, - AutoCompoundConfig, AutoCompoundDelegations, InflationInfo, Range, WeightInfo, - }; - use frame_support::{ - pallet_prelude::*, - traits::{ - tokens::WithdrawReasons, Currency, EstimateNextSessionRotation, Get, Imbalance, - LockIdentifier, LockableCurrency, ReservableCurrency, - }, - }; - use frame_system::pallet_prelude::*; - use sp_runtime::{ - traits::{Saturating, Zero}, - Perbill, Percent, Permill, - }; - use sp_staking::SessionIndex; - use sp_std::{collections::btree_map::BTreeMap, prelude::*}; - - /// Pallet for parachain staking - #[pallet::pallet] - #[pallet::without_storage_info] - pub struct Pallet(PhantomData); - - pub type RoundIndex = u32; - type RewardPoint = u32; - pub type BalanceOf = - <::Currency as Currency<::AccountId>>::Balance; - - pub type AccountIdOf = ::AccountId; - - pub const COLLATOR_LOCK_ID: LockIdentifier = *b"stkngcol"; - pub const DELEGATOR_LOCK_ID: LockIdentifier = *b"stkngdel"; - - /// Configuration trait of this pallet. - #[pallet::config] - pub trait Config: frame_system::Config { - /// Overarching event type - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - /// The currency type - type Currency: Currency - + ReservableCurrency - + LockableCurrency; - /// The origin for monetary governance - type MonetaryGovernanceOrigin: EnsureOrigin; - /// Minimum number of blocks per round - #[pallet::constant] - type MinBlocksPerRound: Get; - /// Number of rounds that candidates remain bonded before exit request is executable - #[pallet::constant] - type LeaveCandidatesDelay: Get; - /// Number of rounds candidate requests to decrease self-bond must wait to be executable - #[pallet::constant] - type CandidateBondLessDelay: Get; - /// Number of rounds that delegators remain bonded before exit request is executable - #[pallet::constant] - type LeaveDelegatorsDelay: Get; - /// Number of rounds that delegations remain bonded before revocation request is executable - #[pallet::constant] - type RevokeDelegationDelay: Get; - /// Number of rounds that delegation less requests must wait before executable - #[pallet::constant] - type DelegationBondLessDelay: Get; - /// Number of rounds after which block authors are rewarded - #[pallet::constant] - type RewardPaymentDelay: Get; - /// Minimum number of selected candidates every round - #[pallet::constant] - type MinSelectedCandidates: Get; - /// Maximum top delegations counted per candidate - #[pallet::constant] - type MaxTopDelegationsPerCandidate: Get; - /// Maximum bottom delegations (not counted) per candidate - #[pallet::constant] - type MaxBottomDelegationsPerCandidate: Get; - /// Maximum delegations per delegator - #[pallet::constant] - type MaxDelegationsPerDelegator: Get; - /// Minimum stake required for any account to be a collator candidate - #[pallet::constant] - type MinCandidateStk: Get>; - /// Minimum stake for any registered on-chain account to delegate - #[pallet::constant] - type MinDelegation: Get>; - /// Minimum stake for any registered on-chain account to be a delegator - #[pallet::constant] - type MinDelegatorStk: Get>; - /// Get the current block author - // type BlockAuthor: Get; - /// Handler to notify the runtime when a collator is paid. - /// If you don't need it, you can specify the type `()`. - type OnCollatorPayout: OnCollatorPayout>; - /// Handler to distribute a collator's reward. - /// To use the default implementation of minting rewards, specify the type `()`. - type PayoutCollatorReward: PayoutCollatorReward; - /// Handler to notify the runtime when a new round begin. - /// If you don't need it, you can specify the type `()`. - type OnNewRound: OnNewRound; - /// Weight information for extrinsics in this pallet. - type WeightInfo: WeightInfo; - } - - #[pallet::error] - pub enum Error { - DelegatorDNE, - DelegatorDNEinTopNorBottom, - DelegatorDNEInDelegatorSet, - CandidateDNE, - DelegationDNE, - DelegatorExists, - CandidateExists, - CandidateBondBelowMin, - InsufficientBalance, - DelegatorBondBelowMin, - DelegationBelowMin, - AlreadyOffline, - AlreadyActive, - DelegatorAlreadyLeaving, - DelegatorNotLeaving, - DelegatorCannotLeaveYet, - CannotDelegateIfLeaving, - CandidateAlreadyLeaving, - CandidateNotLeaving, - CandidateCannotLeaveYet, - CannotGoOnlineIfLeaving, - ExceedMaxDelegationsPerDelegator, - AlreadyDelegatedCandidate, - InvalidSchedule, - CannotSetBelowMin, - RoundLengthMustBeGreaterThanTotalSelectedCollators, - NoWritingSameValue, - TooLowCandidateCountWeightHintJoinCandidates, - TooLowCandidateCountWeightHintCancelLeaveCandidates, - TooLowCandidateCountToLeaveCandidates, - TooLowDelegationCountToDelegate, - TooLowCandidateDelegationCountToDelegate, - TooLowCandidateDelegationCountToLeaveCandidates, - TooLowDelegationCountToLeaveDelegators, - PendingCandidateRequestsDNE, - PendingCandidateRequestAlreadyExists, - PendingCandidateRequestNotDueYet, - PendingDelegationRequestDNE, - PendingDelegationRequestAlreadyExists, - PendingDelegationRequestNotDueYet, - CannotDelegateLessThanOrEqualToLowestBottomWhenFull, - PendingDelegationRevoke, - TooLowDelegationCountToAutoCompound, - TooLowCandidateAutoCompoundingDelegationCountToAutoCompound, - TooLowCandidateAutoCompoundingDelegationCountToDelegate, - } - - #[pallet::event] - #[pallet::generate_deposit(pub(crate) fn deposit_event)] - pub enum Event { - /// Started new round. - NewRound { - starting_block: T::BlockNumber, - round: RoundIndex, - selected_collators_number: u32, - total_balance: BalanceOf, - }, - /// Account joined the set of collator candidates. - JoinedCollatorCandidates { - account: T::AccountId, - amount_locked: BalanceOf, - new_total_amt_locked: BalanceOf, - }, - /// Candidate selected for collators. Total Exposed Amount includes all delegations. - CollatorChosen { - round: RoundIndex, - collator_account: T::AccountId, - total_exposed_amount: BalanceOf, - }, - /// Candidate requested to decrease a self bond. - CandidateBondLessRequested { - candidate: T::AccountId, - amount_to_decrease: BalanceOf, - execute_round: RoundIndex, - }, - /// Candidate has increased a self bond. - CandidateBondedMore { - candidate: T::AccountId, - amount: BalanceOf, - new_total_bond: BalanceOf, - }, - /// Candidate has decreased a self bond. - CandidateBondedLess { - candidate: T::AccountId, - amount: BalanceOf, - new_bond: BalanceOf, - }, - /// Candidate temporarily leave the set of collator candidates without unbonding. - CandidateWentOffline { candidate: T::AccountId }, - /// Candidate rejoins the set of collator candidates. - CandidateBackOnline { candidate: T::AccountId }, - /// Candidate has requested to leave the set of candidates. - CandidateScheduledExit { - exit_allowed_round: RoundIndex, - candidate: T::AccountId, - scheduled_exit: RoundIndex, - }, - /// Cancelled request to leave the set of candidates. - CancelledCandidateExit { candidate: T::AccountId }, - /// Cancelled request to decrease candidate's bond. - CancelledCandidateBondLess { - candidate: T::AccountId, - amount: BalanceOf, - execute_round: RoundIndex, - }, - /// Candidate has left the set of candidates. - CandidateLeft { - ex_candidate: T::AccountId, - unlocked_amount: BalanceOf, - new_total_amt_locked: BalanceOf, - }, - /// Delegator requested to decrease a bond for the collator candidate. - DelegationDecreaseScheduled { - delegator: T::AccountId, - candidate: T::AccountId, - amount_to_decrease: BalanceOf, - execute_round: RoundIndex, - }, - // Delegation increased. - DelegationIncreased { - delegator: T::AccountId, - candidate: T::AccountId, - amount: BalanceOf, - in_top: bool, - }, - // Delegation decreased. - DelegationDecreased { - delegator: T::AccountId, - candidate: T::AccountId, - amount: BalanceOf, - in_top: bool, - }, - /// Delegator requested to leave the set of delegators. - DelegatorExitScheduled { - round: RoundIndex, - delegator: T::AccountId, - scheduled_exit: RoundIndex, - }, - /// Delegator requested to revoke delegation. - DelegationRevocationScheduled { - round: RoundIndex, - delegator: T::AccountId, - candidate: T::AccountId, - scheduled_exit: RoundIndex, - }, - /// Delegator has left the set of delegators. - DelegatorLeft { delegator: T::AccountId, unstaked_amount: BalanceOf }, - /// Delegation revoked. - DelegationRevoked { - delegator: T::AccountId, - candidate: T::AccountId, - unstaked_amount: BalanceOf, - }, - /// Delegation kicked. - DelegationKicked { - delegator: T::AccountId, - candidate: T::AccountId, - unstaked_amount: BalanceOf, - }, - /// Cancelled a pending request to exit the set of delegators. - DelegatorExitCancelled { delegator: T::AccountId }, - /// Cancelled request to change an existing delegation. - CancelledDelegationRequest { - delegator: T::AccountId, - cancelled_request: CancelledScheduledRequest>, - collator: T::AccountId, - }, - /// New delegation (increase of the existing one). - Delegation { - delegator: T::AccountId, - locked_amount: BalanceOf, - candidate: T::AccountId, - delegator_position: DelegatorAdded>, - auto_compound: Percent, - }, - /// Delegation from candidate state has been remove. - DelegatorLeftCandidate { - delegator: T::AccountId, - candidate: T::AccountId, - unstaked_amount: BalanceOf, - total_candidate_staked: BalanceOf, - }, - /// Paid the account (delegator or collator) the balance as liquid rewards. - Rewarded { account: T::AccountId, rewards: BalanceOf }, - /// Transferred to account which holds funds reserved for parachain bond. - ReservedForParachainBond { account: T::AccountId, value: BalanceOf }, - /// Account (re)set for parachain bond treasury. - ParachainBondAccountSet { old: T::AccountId, new: T::AccountId }, - /// Percent of inflation reserved for parachain bond (re)set. - ParachainBondReservePercentSet { old: Percent, new: Percent }, - /// Annual inflation input (first 3) was used to derive new per-round inflation (last 3) - InflationSet { - annual_min: Perbill, - annual_ideal: Perbill, - annual_max: Perbill, - round_min: Perbill, - round_ideal: Perbill, - round_max: Perbill, - }, - /// Staking expectations set. - StakeExpectationsSet { - expect_min: BalanceOf, - expect_ideal: BalanceOf, - expect_max: BalanceOf, - }, - /// Set total selected candidates to this value. - TotalSelectedSet { old: u32, new: u32 }, - /// Set collator commission to this value. - CollatorCommissionSet { old: Perbill, new: Perbill }, - /// Set blocks per round - BlocksPerRoundSet { - current_round: RoundIndex, - first_block: T::BlockNumber, - old: u32, - new: u32, - new_per_round_inflation_min: Perbill, - new_per_round_inflation_ideal: Perbill, - new_per_round_inflation_max: Perbill, - }, - /// Auto-compounding reward percent was set for a delegation. - AutoCompoundSet { candidate: T::AccountId, delegator: T::AccountId, value: Percent }, - /// Compounded a portion of rewards towards the delegation. - Compounded { candidate: T::AccountId, delegator: T::AccountId, amount: BalanceOf }, - } - - #[pallet::hooks] - impl Hooks> for Pallet { - fn on_initialize(n: T::BlockNumber) -> Weight { - let mut weight = T::WeightInfo::base_on_initialize(); - - let mut round = >::get(); - - if round.should_update(n) { - // mutate round - round.update(n); - // notify that new round begin - weight = weight.saturating_add(T::OnNewRound::on_new_round(round.current)); - // pay all stakers for T::RewardPaymentDelay rounds ago - weight = weight.saturating_add(Self::prepare_staking_payouts(round.current)); - // select top collator candidates for next round - let (extra_weight, collator_count, _delegation_count, total_staked) = - Self::select_top_candidates(round.current); - weight = weight.saturating_add(extra_weight); - // start next round - >::put(round); - // snapshot total stake - >::insert(round.current, >::get()); - Self::deposit_event(Event::NewRound { - starting_block: round.first, - round: round.current, - selected_collators_number: collator_count, - total_balance: total_staked, - }); - // account for Round and Staked writes - weight = weight.saturating_add(T::DbWeight::get().reads_writes(0, 2)); - } else { - weight = weight.saturating_add(Self::handle_delayed_payouts(round.current)); - } - - // add on_finalize weight - // read: Author, Points, AwardedPts - // write: Points, AwardedPts - weight = weight.saturating_add(T::DbWeight::get().reads_writes(3, 2)); - weight - } - } - - #[pallet::storage] - #[pallet::getter(fn collator_commission)] - /// Commission percent taken off of rewards for all collators - type CollatorCommission = StorageValue<_, Perbill, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn total_selected)] - /// The total candidates selected every round - pub(crate) type TotalSelected = StorageValue<_, u32, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn parachain_bond_info)] - /// Parachain bond config info { account, percent_of_inflation } - pub(crate) type ParachainBondInfo = - StorageValue<_, ParachainBondConfig, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn round)] - /// Current round index and next round scheduled transition - pub(crate) type Round = StorageValue<_, RoundInfo, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn delegator_state)] - /// Get delegator state associated with an account if account is delegating else None - pub(crate) type DelegatorState = StorageMap< - _, - Twox64Concat, - T::AccountId, - Delegator>, - OptionQuery, - >; - - #[pallet::storage] - #[pallet::getter(fn candidate_info)] - /// Get collator candidate info associated with an account if account is candidate else None - pub(crate) type CandidateInfo = - StorageMap<_, Twox64Concat, T::AccountId, CandidateMetadata>, OptionQuery>; - - /// Stores outstanding delegation requests per collator. - #[pallet::storage] - #[pallet::getter(fn delegation_scheduled_requests)] - pub(crate) type DelegationScheduledRequests = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - Vec>>, - ValueQuery, - >; - - pub struct AddGet { - _phantom: PhantomData<(T, R)>, - } - impl Get for AddGet - where - T: Get, - R: Get, - { - fn get() -> u32 { - T::get() + R::get() - } - } - - /// Stores auto-compounding configuration per collator. - #[pallet::storage] - #[pallet::getter(fn auto_compounding_delegations)] - pub(crate) type AutoCompoundingDelegations = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - BoundedVec< - AutoCompoundConfig, - AddGet, - >, - ValueQuery, - >; - - #[pallet::storage] - #[pallet::getter(fn top_delegations)] - /// Top delegations for collator candidate - pub(crate) type TopDelegations = StorageMap< - _, - Twox64Concat, - T::AccountId, - Delegations>, - OptionQuery, - >; - - #[pallet::storage] - #[pallet::getter(fn bottom_delegations)] - /// Bottom delegations for collator candidate - pub(crate) type BottomDelegations = StorageMap< - _, - Twox64Concat, - T::AccountId, - Delegations>, - OptionQuery, - >; - - #[pallet::storage] - #[pallet::getter(fn selected_candidates)] - /// The collator candidates selected for the current round - type SelectedCandidates = StorageValue<_, Vec, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn total)] - /// Total capital locked by this staking pallet - pub(crate) type Total = StorageValue<_, BalanceOf, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn candidate_pool)] - /// The pool of collator candidates, each with their total backing stake - pub(crate) type CandidatePool = - StorageValue<_, OrderedSet>>, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn at_stake)] - /// Snapshot of collator delegation stake at the start of the round - pub type AtStake = StorageDoubleMap< - _, - Twox64Concat, - RoundIndex, - Twox64Concat, - T::AccountId, - CollatorSnapshot>, - ValueQuery, - >; - - #[pallet::storage] - #[pallet::getter(fn delayed_payouts)] - /// Delayed payouts - pub type DelayedPayouts = - StorageMap<_, Twox64Concat, RoundIndex, DelayedPayout>, OptionQuery>; - - #[pallet::storage] - #[pallet::getter(fn staked)] - /// Total counted stake for selected candidates in the round - pub type Staked = StorageMap<_, Twox64Concat, RoundIndex, BalanceOf, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn inflation_config)] - /// Inflation configuration - pub type InflationConfig = StorageValue<_, InflationInfo>, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn points)] - /// Total points awarded to collators for block production in the round - pub type Points = StorageMap<_, Twox64Concat, RoundIndex, RewardPoint, ValueQuery>; - - #[pallet::storage] - #[pallet::getter(fn awarded_pts)] - /// Points for each collator per round - pub type AwardedPts = StorageDoubleMap< - _, - Twox64Concat, - RoundIndex, - Twox64Concat, - T::AccountId, - RewardPoint, - ValueQuery, - >; - - #[pallet::genesis_config] - pub struct GenesisConfig { - /// Initialize balance and register all as collators: `(collator AccountId, balance Amount)` - pub candidates: Vec<(T::AccountId, BalanceOf)>, - /// Initialize balance and make delegations: - /// `(delegator AccountId, collator AccountId, delegation Amount, auto-compounding Percent)` - pub delegations: Vec<(T::AccountId, T::AccountId, BalanceOf, Percent)>, - /// Inflation configuration - pub inflation_config: InflationInfo>, - /// Default fixed percent a collator takes off the top of due rewards - pub collator_commission: Perbill, - /// Default percent of inflation set aside for parachain bond every round - pub parachain_bond_reserve_percent: Percent, - /// Default number of blocks in a round - pub blocks_per_round: u32, - /// Number of selected candidates every round. Cannot be lower than MinSelectedCandidates - pub num_selected_candidates: u32, - } - - #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - Self { - candidates: vec![], - delegations: vec![], - inflation_config: Default::default(), - collator_commission: Default::default(), - parachain_bond_reserve_percent: Default::default(), - blocks_per_round: 1u32, - num_selected_candidates: T::MinSelectedCandidates::get(), - } - } - } - - #[pallet::genesis_build] - impl GenesisBuild for GenesisConfig { - fn build(&self) { - assert!(self.blocks_per_round > 0, "Blocks per round must be > 0"); - >::put(self.inflation_config.clone()); - let mut candidate_count = 0u32; - // Initialize the candidates - for &(ref candidate, balance) in &self.candidates { - assert!( - >::get_collator_stakable_free_balance(candidate) >= balance, - "Account does not have enough balance to bond as a candidate." - ); - if let Err(error) = >::join_candidates( - T::RuntimeOrigin::from(Some(candidate.clone()).into()), - balance, - candidate_count, - ) { - log::warn!("Join candidates failed in genesis with error {:?}", error); - } else { - candidate_count = candidate_count.saturating_add(1u32); - } - } - - let mut col_delegator_count: BTreeMap = BTreeMap::new(); - let mut col_auto_compound_delegator_count: BTreeMap = - BTreeMap::new(); - let mut del_delegation_count: BTreeMap = BTreeMap::new(); - // Initialize the delegations - for &(ref delegator, ref target, balance, auto_compound) in &self.delegations { - assert!( - >::get_delegator_stakable_free_balance(delegator) >= balance, - "Account does not have enough balance to place delegation." - ); - let cd_count = - if let Some(x) = col_delegator_count.get(target) { *x } else { 0u32 }; - let dd_count = - if let Some(x) = del_delegation_count.get(delegator) { *x } else { 0u32 }; - let cd_auto_compound_count = - col_auto_compound_delegator_count.get(target).cloned().unwrap_or_default(); - if let Err(error) = >::delegate_with_auto_compound( - T::RuntimeOrigin::from(Some(delegator.clone()).into()), - target.clone(), - balance, - auto_compound, - cd_count, - cd_auto_compound_count, - dd_count, - ) { - log::warn!("Delegate failed in genesis with error {:?}", error); - } else { - if let Some(x) = col_delegator_count.get_mut(target) { - *x = x.saturating_add(1u32); - } else { - col_delegator_count.insert(target.clone(), 1u32); - }; - if let Some(x) = del_delegation_count.get_mut(delegator) { - *x = x.saturating_add(1u32); - } else { - del_delegation_count.insert(delegator.clone(), 1u32); - }; - if !auto_compound.is_zero() { - col_auto_compound_delegator_count - .entry(target.clone()) - .and_modify(|x| *x = x.saturating_add(1)) - .or_insert(1); - } - } - } - // Set collator commission to default config - >::put(self.collator_commission); - // Set parachain bond config to default config - >::put(ParachainBondConfig { - // must be set soon; if not => due inflation will be sent to collators/delegators - account: T::AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) - .expect("infinite length input; no invalid inputs for type; qed"), - percent: self.parachain_bond_reserve_percent, - }); - // Set total selected candidates to value from config - assert!( - self.num_selected_candidates >= T::MinSelectedCandidates::get(), - "{:?}", - Error::::CannotSetBelowMin - ); - >::put(self.num_selected_candidates); - // Choose top TotalSelected collator candidates - let (_, v_count, _, total_staked) = >::select_top_candidates(1u32); - // Start Round 1 at Block 0 - let round: RoundInfo = - RoundInfo::new(1u32, 0u32.into(), self.blocks_per_round); - >::put(round); - // Snapshot total stake - >::insert(1u32, >::get()); - >::deposit_event(Event::NewRound { - starting_block: T::BlockNumber::zero(), - round: 1u32, - selected_collators_number: v_count, - total_balance: total_staked, - }); - } - } - - #[pallet::call] - impl Pallet { - /// Set the expectations for total staked. These expectations determine the issuance for - /// the round according to logic in `fn compute_issuance` - #[pallet::call_index(0)] - #[pallet::weight(::WeightInfo::set_staking_expectations())] - pub fn set_staking_expectations( - origin: OriginFor, - expectations: Range>, - ) -> DispatchResultWithPostInfo { - T::MonetaryGovernanceOrigin::ensure_origin(origin)?; - ensure!(expectations.is_valid(), Error::::InvalidSchedule); - let mut config = >::get(); - ensure!(config.expect != expectations, Error::::NoWritingSameValue); - config.set_expectations(expectations); - Self::deposit_event(Event::StakeExpectationsSet { - expect_min: config.expect.min, - expect_ideal: config.expect.ideal, - expect_max: config.expect.max, - }); - >::put(config); - Ok(().into()) - } - - /// Set the annual inflation rate to derive per-round inflation - #[pallet::call_index(1)] - #[pallet::weight(::WeightInfo::set_inflation())] - pub fn set_inflation( - origin: OriginFor, - schedule: Range, - ) -> DispatchResultWithPostInfo { - T::MonetaryGovernanceOrigin::ensure_origin(origin)?; - ensure!(schedule.is_valid(), Error::::InvalidSchedule); - let mut config = >::get(); - ensure!(config.annual != schedule, Error::::NoWritingSameValue); - config.annual = schedule; - config.set_round_from_annual::(schedule); - Self::deposit_event(Event::InflationSet { - annual_min: config.annual.min, - annual_ideal: config.annual.ideal, - annual_max: config.annual.max, - round_min: config.round.min, - round_ideal: config.round.ideal, - round_max: config.round.max, - }); - >::put(config); - Ok(().into()) - } - - /// Set the account that will hold funds set aside for parachain bond - #[pallet::call_index(2)] - #[pallet::weight(::WeightInfo::set_parachain_bond_account())] - pub fn set_parachain_bond_account( - origin: OriginFor, - new: T::AccountId, - ) -> DispatchResultWithPostInfo { - T::MonetaryGovernanceOrigin::ensure_origin(origin)?; - let ParachainBondConfig { account: old, percent } = >::get(); - ensure!(old != new, Error::::NoWritingSameValue); - >::put(ParachainBondConfig { account: new.clone(), percent }); - Self::deposit_event(Event::ParachainBondAccountSet { old, new }); - Ok(().into()) - } - - /// Set the percent of inflation set aside for parachain bond - #[pallet::call_index(3)] - #[pallet::weight(::WeightInfo::set_parachain_bond_reserve_percent())] - pub fn set_parachain_bond_reserve_percent( - origin: OriginFor, - new: Percent, - ) -> DispatchResultWithPostInfo { - T::MonetaryGovernanceOrigin::ensure_origin(origin)?; - let ParachainBondConfig { account, percent: old } = >::get(); - ensure!(old != new, Error::::NoWritingSameValue); - >::put(ParachainBondConfig { account, percent: new }); - Self::deposit_event(Event::ParachainBondReservePercentSet { old, new }); - Ok(().into()) - } - - /// Set the total number of collator candidates selected per round - /// - changes are not applied until the start of the next round - #[pallet::call_index(4)] - #[pallet::weight(::WeightInfo::set_total_selected())] - pub fn set_total_selected(origin: OriginFor, new: u32) -> DispatchResultWithPostInfo { - frame_system::ensure_root(origin)?; - ensure!(new >= T::MinSelectedCandidates::get(), Error::::CannotSetBelowMin); - let old = >::get(); - ensure!(old != new, Error::::NoWritingSameValue); - ensure!( - new < >::get().length, - Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, - ); - >::put(new); - Self::deposit_event(Event::TotalSelectedSet { old, new }); - Ok(().into()) - } - - /// Set the commission for all collators - #[pallet::call_index(5)] - #[pallet::weight(::WeightInfo::set_collator_commission())] - pub fn set_collator_commission( - origin: OriginFor, - new: Perbill, - ) -> DispatchResultWithPostInfo { - frame_system::ensure_root(origin)?; - let old = >::get(); - ensure!(old != new, Error::::NoWritingSameValue); - >::put(new); - Self::deposit_event(Event::CollatorCommissionSet { old, new }); - Ok(().into()) - } - - /// Set blocks per round - /// - if called with `new` less than length of current round, will transition immediately - /// in the next block - /// - also updates per-round inflation config - #[pallet::call_index(6)] - #[pallet::weight(::WeightInfo::set_blocks_per_round())] - pub fn set_blocks_per_round(origin: OriginFor, new: u32) -> DispatchResultWithPostInfo { - frame_system::ensure_root(origin)?; - ensure!(new >= T::MinBlocksPerRound::get(), Error::::CannotSetBelowMin); - let mut round = >::get(); - let (now, first, old) = (round.current, round.first, round.length); - ensure!(old != new, Error::::NoWritingSameValue); - ensure!( - new > >::get(), - Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, - ); - round.length = new; - // update per-round inflation given new rounds per year - let mut inflation_config = >::get(); - inflation_config.reset_round(new); - >::put(round); - Self::deposit_event(Event::BlocksPerRoundSet { - current_round: now, - first_block: first, - old, - new, - new_per_round_inflation_min: inflation_config.round.min, - new_per_round_inflation_ideal: inflation_config.round.ideal, - new_per_round_inflation_max: inflation_config.round.max, - }); - >::put(inflation_config); - Ok(().into()) - } - - /// Join the set of collator candidates - #[pallet::call_index(7)] - #[pallet::weight(::WeightInfo::join_candidates(*candidate_count))] - pub fn join_candidates( - origin: OriginFor, - bond: BalanceOf, - candidate_count: u32, - ) -> DispatchResultWithPostInfo { - let acc = ensure_signed(origin)?; - ensure!(!Self::is_candidate(&acc), Error::::CandidateExists); - ensure!(!Self::is_delegator(&acc), Error::::DelegatorExists); - ensure!(bond >= T::MinCandidateStk::get(), Error::::CandidateBondBelowMin); - let mut candidates = >::get(); - let old_count = candidates.0.len() as u32; - ensure!( - candidate_count >= old_count, - Error::::TooLowCandidateCountWeightHintJoinCandidates - ); - ensure!( - candidates.insert(Bond { owner: acc.clone(), amount: bond }), - Error::::CandidateExists - ); - ensure!( - Self::get_collator_stakable_free_balance(&acc) >= bond, - Error::::InsufficientBalance, - ); - T::Currency::set_lock(COLLATOR_LOCK_ID, &acc, bond, WithdrawReasons::all()); - let candidate = CandidateMetadata::new(bond); - >::insert(&acc, candidate); - let empty_delegations: Delegations> = Default::default(); - // insert empty top delegations - >::insert(&acc, empty_delegations.clone()); - // insert empty bottom delegations - >::insert(&acc, empty_delegations); - >::put(candidates); - let new_total = >::get().saturating_add(bond); - >::put(new_total); - Self::deposit_event(Event::JoinedCollatorCandidates { - account: acc, - amount_locked: bond, - new_total_amt_locked: new_total, - }); - Ok(().into()) - } - - /// Request to leave the set of candidates. If successful, the account is immediately - /// removed from the candidate pool to prevent selection as a collator. - #[pallet::call_index(8)] - #[pallet::weight(::WeightInfo::schedule_leave_candidates(*candidate_count))] - pub fn schedule_leave_candidates( - origin: OriginFor, - candidate_count: u32, - ) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - let (now, when) = state.schedule_leave::()?; - let mut candidates = >::get(); - ensure!( - candidate_count >= candidates.0.len() as u32, - Error::::TooLowCandidateCountToLeaveCandidates - ); - if candidates.remove(&Bond::from_owner(collator.clone())) { - >::put(candidates); - } - >::insert(&collator, state); - Self::deposit_event(Event::CandidateScheduledExit { - exit_allowed_round: now, - candidate: collator, - scheduled_exit: when, - }); - Ok(().into()) - } - - /// Execute leave candidates request - #[pallet::call_index(9)] - #[pallet::weight( - ::WeightInfo::execute_leave_candidates(*candidate_delegation_count) - )] - pub fn execute_leave_candidates( - origin: OriginFor, - candidate: T::AccountId, - candidate_delegation_count: u32, - ) -> DispatchResultWithPostInfo { - ensure_signed(origin)?; - let state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; - ensure!( - state.delegation_count <= candidate_delegation_count, - Error::::TooLowCandidateDelegationCountToLeaveCandidates - ); - state.can_leave::()?; - let return_stake = |bond: Bond>| -> DispatchResult { - // remove delegation from delegator state - let mut delegator = DelegatorState::::get(&bond.owner).expect( - "Collator state and delegator state are consistent. - Collator state has a record of this delegation. Therefore, - Delegator state also has a record. qed.", - ); - - if let Some(remaining) = delegator.rm_delegation::(&candidate) { - Self::delegation_remove_request_with_state( - &candidate, - &bond.owner, - &mut delegator, - ); - >::remove_auto_compound(&candidate, &bond.owner); - - if remaining.is_zero() { - // we do not remove the scheduled delegation requests from other collators - // since it is assumed that they were removed incrementally before only the - // last delegation was left. - >::remove(&bond.owner); - T::Currency::remove_lock(DELEGATOR_LOCK_ID, &bond.owner); - } else { - >::insert(&bond.owner, delegator); - } - } else { - // TODO: review. we assume here that this delegator has no remaining staked - // balance, so we ensure the lock is cleared - T::Currency::remove_lock(DELEGATOR_LOCK_ID, &bond.owner); - } - Ok(()) - }; - // total backing stake is at least the candidate self bond - let mut total_backing = state.bond; - // return all top delegations - let top_delegations = - >::take(&candidate).expect("CandidateInfo existence checked"); - for bond in top_delegations.delegations { - return_stake(bond)?; - } - total_backing = total_backing.saturating_add(top_delegations.total); - // return all bottom delegations - let bottom_delegations = - >::take(&candidate).expect("CandidateInfo existence checked"); - for bond in bottom_delegations.delegations { - return_stake(bond)?; - } - total_backing = total_backing.saturating_add(bottom_delegations.total); - // return stake to collator - T::Currency::remove_lock(COLLATOR_LOCK_ID, &candidate); - >::remove(&candidate); - >::remove(&candidate); - >::remove(&candidate); - >::remove(&candidate); - >::remove(&candidate); - let new_total_staked = >::get().saturating_sub(total_backing); - >::put(new_total_staked); - Self::deposit_event(Event::CandidateLeft { - ex_candidate: candidate, - unlocked_amount: total_backing, - new_total_amt_locked: new_total_staked, - }); - Ok(().into()) - } - - /// Cancel open request to leave candidates - /// - only callable by collator account - /// - result upon successful call is the candidate is active in the candidate pool - #[pallet::call_index(10)] - #[pallet::weight(::WeightInfo::cancel_leave_candidates(*candidate_count))] - pub fn cancel_leave_candidates( - origin: OriginFor, - candidate_count: u32, - ) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - ensure!(state.is_leaving(), Error::::CandidateNotLeaving); - state.go_online(); - let mut candidates = >::get(); - ensure!( - candidates.0.len() as u32 <= candidate_count, - Error::::TooLowCandidateCountWeightHintCancelLeaveCandidates - ); - ensure!( - candidates.insert(Bond { owner: collator.clone(), amount: state.total_counted }), - Error::::AlreadyActive - ); - >::put(candidates); - >::insert(&collator, state); - Self::deposit_event(Event::CancelledCandidateExit { candidate: collator }); - Ok(().into()) - } - - /// Temporarily leave the set of collator candidates without unbonding - #[pallet::call_index(11)] - #[pallet::weight(::WeightInfo::go_offline())] - pub fn go_offline(origin: OriginFor) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - ensure!(state.is_active(), Error::::AlreadyOffline); - state.go_offline(); - let mut candidates = >::get(); - if candidates.remove(&Bond::from_owner(collator.clone())) { - >::put(candidates); - } - >::insert(&collator, state); - Self::deposit_event(Event::CandidateWentOffline { candidate: collator }); - Ok(().into()) - } - - /// Rejoin the set of collator candidates if previously had called `go_offline` - #[pallet::call_index(12)] - #[pallet::weight(::WeightInfo::go_online())] - pub fn go_online(origin: OriginFor) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - ensure!(!state.is_active(), Error::::AlreadyActive); - ensure!(!state.is_leaving(), Error::::CannotGoOnlineIfLeaving); - state.go_online(); - let mut candidates = >::get(); - ensure!( - candidates.insert(Bond { owner: collator.clone(), amount: state.total_counted }), - Error::::AlreadyActive - ); - >::put(candidates); - >::insert(&collator, state); - Self::deposit_event(Event::CandidateBackOnline { candidate: collator }); - Ok(().into()) - } - - /// Increase collator candidate self bond by `more` - #[pallet::call_index(13)] - #[pallet::weight(::WeightInfo::candidate_bond_more())] - pub fn candidate_bond_more( - origin: OriginFor, - more: BalanceOf, - ) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - state.bond_more::(collator.clone(), more)?; - let (is_active, total_counted) = (state.is_active(), state.total_counted); - >::insert(&collator, state); - if is_active { - Self::update_active(collator, total_counted); - } - Ok(().into()) - } - - /// Request by collator candidate to decrease self bond by `less` - #[pallet::call_index(14)] - #[pallet::weight(::WeightInfo::schedule_candidate_bond_less())] - pub fn schedule_candidate_bond_less( - origin: OriginFor, - less: BalanceOf, - ) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - let when = state.schedule_bond_less::(less)?; - >::insert(&collator, state); - Self::deposit_event(Event::CandidateBondLessRequested { - candidate: collator, - amount_to_decrease: less, - execute_round: when, - }); - Ok(().into()) - } - - /// Execute pending request to adjust the collator candidate self bond - #[pallet::call_index(15)] - #[pallet::weight(::WeightInfo::execute_candidate_bond_less())] - pub fn execute_candidate_bond_less( - origin: OriginFor, - candidate: T::AccountId, - ) -> DispatchResultWithPostInfo { - ensure_signed(origin)?; // we may want to reward this if caller != candidate - let mut state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; - state.execute_bond_less::(candidate.clone())?; - >::insert(&candidate, state); - Ok(().into()) - } - - /// Cancel pending request to adjust the collator candidate self bond - #[pallet::call_index(16)] - #[pallet::weight(::WeightInfo::cancel_candidate_bond_less())] - pub fn cancel_candidate_bond_less(origin: OriginFor) -> DispatchResultWithPostInfo { - let collator = ensure_signed(origin)?; - let mut state = >::get(&collator).ok_or(Error::::CandidateDNE)?; - state.cancel_bond_less::(collator.clone())?; - >::insert(&collator, state); - Ok(().into()) - } - - /// If caller is not a delegator and not a collator, then join the set of delegators - /// If caller is a delegator, then makes delegation to change their delegation state - #[pallet::call_index(17)] - #[pallet::weight( - ::WeightInfo::delegate( - *candidate_delegation_count, - *delegation_count - ) - )] - pub fn delegate( - origin: OriginFor, - candidate: T::AccountId, - amount: BalanceOf, - candidate_delegation_count: u32, - delegation_count: u32, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - >::delegate_with_auto_compound( - candidate, - delegator, - amount, - Percent::zero(), - candidate_delegation_count, - 0, - delegation_count, - ) - } - - /// If caller is not a delegator and not a collator, then join the set of delegators - /// If caller is a delegator, then makes delegation to change their delegation state - /// Sets the auto-compound config for the delegation - #[pallet::call_index(18)] - #[pallet::weight( - ::WeightInfo::delegate_with_auto_compound( - *candidate_delegation_count, - *candidate_auto_compounding_delegation_count, - *delegation_count, - ) - )] - pub fn delegate_with_auto_compound( - origin: OriginFor, - candidate: T::AccountId, - amount: BalanceOf, - auto_compound: Percent, - candidate_delegation_count: u32, - candidate_auto_compounding_delegation_count: u32, - delegation_count: u32, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - >::delegate_with_auto_compound( - candidate, - delegator, - amount, - auto_compound, - candidate_delegation_count, - candidate_auto_compounding_delegation_count, - delegation_count, - ) - } - - /// DEPRECATED use batch util with schedule_revoke_delegation for all delegations - /// Request to leave the set of delegators. If successful, the caller is scheduled to be - /// allowed to exit via a [DelegationAction::Revoke] towards all existing delegations. - /// Success forbids future delegation requests until the request is invoked or cancelled. - #[pallet::call_index(19)] - #[pallet::weight(::WeightInfo::schedule_leave_delegators())] - pub fn schedule_leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - Self::delegator_schedule_revoke_all(delegator) - } - - /// DEPRECATED use batch util with execute_delegation_request for all delegations - /// Execute the right to exit the set of delegators and revoke all ongoing delegations. - #[pallet::call_index(20)] - #[pallet::weight(::WeightInfo::execute_leave_delegators(*delegation_count))] - pub fn execute_leave_delegators( - origin: OriginFor, - delegator: T::AccountId, - delegation_count: u32, - ) -> DispatchResultWithPostInfo { - ensure_signed(origin)?; - Self::delegator_execute_scheduled_revoke_all(delegator, delegation_count) - } - - /// DEPRECATED use batch util with cancel_delegation_request for all delegations - /// Cancel a pending request to exit the set of delegators. Success clears the pending exit - /// request (thereby resetting the delay upon another `leave_delegators` call). - #[pallet::call_index(21)] - #[pallet::weight(::WeightInfo::cancel_leave_delegators())] - pub fn cancel_leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - Self::delegator_cancel_scheduled_revoke_all(delegator) - } - - /// Request to revoke an existing delegation. If successful, the delegation is scheduled - /// to be allowed to be revoked via the `execute_delegation_request` extrinsic. - /// The delegation receives no rewards for the rounds while a revoke is pending. - /// A revoke may not be performed if any other scheduled request is pending. - #[pallet::call_index(22)] - #[pallet::weight(::WeightInfo::schedule_revoke_delegation())] - pub fn schedule_revoke_delegation( - origin: OriginFor, - collator: T::AccountId, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - Self::delegation_schedule_revoke(collator, delegator) - } - - /// Bond more for delegators wrt a specific collator candidate. - #[pallet::call_index(23)] - #[pallet::weight(::WeightInfo::delegator_bond_more())] - pub fn delegator_bond_more( - origin: OriginFor, - candidate: T::AccountId, - more: BalanceOf, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - let in_top = Self::delegation_bond_more_without_event( - delegator.clone(), - candidate.clone(), - more, - )?; - Pallet::::deposit_event(Event::DelegationIncreased { - delegator, - candidate, - amount: more, - in_top, - }); - - Ok(().into()) - } - - /// Request bond less for delegators wrt a specific collator candidate. The delegation's - /// rewards for rounds while the request is pending use the reduced bonded amount. - /// A bond less may not be performed if any other scheduled request is pending. - #[pallet::call_index(24)] - #[pallet::weight(::WeightInfo::schedule_delegator_bond_less())] - pub fn schedule_delegator_bond_less( - origin: OriginFor, - candidate: T::AccountId, - less: BalanceOf, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - Self::delegation_schedule_bond_decrease(candidate, delegator, less) - } - - /// Execute pending request to change an existing delegation - #[pallet::call_index(25)] - #[pallet::weight(::WeightInfo::execute_delegator_bond_less())] - pub fn execute_delegation_request( - origin: OriginFor, - delegator: T::AccountId, - candidate: T::AccountId, - ) -> DispatchResultWithPostInfo { - ensure_signed(origin)?; // we may want to reward caller if caller != delegator - Self::delegation_execute_scheduled_request(candidate, delegator) - } - - /// Cancel request to change an existing delegation. - #[pallet::call_index(26)] - #[pallet::weight(::WeightInfo::cancel_delegator_bond_less())] - pub fn cancel_delegation_request( - origin: OriginFor, - candidate: T::AccountId, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - Self::delegation_cancel_request(candidate, delegator) - } - - /// Sets the auto-compounding reward percentage for a delegation. - #[pallet::call_index(27)] - #[pallet::weight(::WeightInfo::set_auto_compound( - *candidate_auto_compounding_delegation_count_hint, - *delegation_count_hint, - ))] - pub fn set_auto_compound( - origin: OriginFor, - candidate: T::AccountId, - value: Percent, - candidate_auto_compounding_delegation_count_hint: u32, - delegation_count_hint: u32, - ) -> DispatchResultWithPostInfo { - let delegator = ensure_signed(origin)?; - >::set_auto_compound( - candidate, - delegator, - value, - candidate_auto_compounding_delegation_count_hint, - delegation_count_hint, - ) - } - - /// Hotfix to remove existing empty entries for candidates that have left. - #[pallet::call_index(28)] - #[pallet::weight( - T::DbWeight::get().reads_writes(2 * candidates.len() as u64, candidates.len() as u64) - )] - pub fn hotfix_remove_delegation_requests_exited_candidates( - origin: OriginFor, - candidates: Vec, - ) -> DispatchResult { - ensure_signed(origin)?; - ensure!(candidates.len() < 100, >::InsufficientBalance); - for candidate in &candidates { - ensure!( - >::get(candidate).is_none(), - >::CandidateNotLeaving - ); - ensure!( - >::get(candidate).is_empty(), - >::CandidateNotLeaving - ); - } - - for candidate in candidates { - >::remove(candidate); - } - - Ok(()) - } - } - - /// Represents a payout made via `pay_one_collator_reward`. - pub(crate) enum RewardPayment { - /// A collator was paid - Paid, - /// A collator was skipped for payment. This can happen if they haven't been awarded any - /// points, that is, they did not produce any blocks. - Skipped, - /// All collator payments have been processed. - Finished, - } - - impl Pallet { - pub fn is_delegator(acc: &T::AccountId) -> bool { - >::get(acc).is_some() - } - pub fn is_candidate(acc: &T::AccountId) -> bool { - >::get(acc).is_some() - } - pub fn is_selected_candidate(acc: &T::AccountId) -> bool { - >::get().binary_search(acc).is_ok() - } - /// Returns an account's free balance which is not locked in delegation staking - pub fn get_delegator_stakable_free_balance(acc: &T::AccountId) -> BalanceOf { - let mut balance = T::Currency::free_balance(acc); - if let Some(state) = >::get(acc) { - balance = balance.saturating_sub(state.total()); - } - balance - } - /// Returns an account's free balance which is not locked in collator staking - pub fn get_collator_stakable_free_balance(acc: &T::AccountId) -> BalanceOf { - let mut balance = T::Currency::free_balance(acc); - if let Some(info) = >::get(acc) { - balance = balance.saturating_sub(info.bond); - } - balance - } - /// Returns a delegations auto-compound value. - pub fn delegation_auto_compound( - candidate: &T::AccountId, - delegator: &T::AccountId, - ) -> Percent { - >::auto_compound(candidate, delegator) - } - /// Caller must ensure candidate is active before calling - pub(crate) fn update_active(candidate: T::AccountId, total: BalanceOf) { - let mut candidates = >::get(); - candidates.remove(&Bond::from_owner(candidate.clone())); - candidates.insert(Bond { owner: candidate, amount: total }); - >::put(candidates); - } - /// Compute round issuance based on total staked for the given round - fn compute_issuance(staked: BalanceOf) -> BalanceOf { - let config = >::get(); - let round_issuance = crate::inflation::round_issuance_range::(config.round); - // TODO: consider interpolation instead of bounded range - if staked < config.expect.min { - round_issuance.min - } else if staked > config.expect.max { - round_issuance.max - } else { - round_issuance.ideal - } - } - /// Remove delegation from candidate state - /// Amount input should be retrieved from delegator and it informs the storage lookups - pub(crate) fn delegator_leaves_candidate( - candidate: T::AccountId, - delegator: T::AccountId, - amount: BalanceOf, - ) -> DispatchResult { - let mut state = >::get(&candidate).ok_or(Error::::CandidateDNE)?; - state.rm_delegation_if_exists::(&candidate, delegator.clone(), amount)?; - let new_total_locked = >::get().saturating_sub(amount); - >::put(new_total_locked); - let new_total = state.total_counted; - >::insert(&candidate, state); - Self::deposit_event(Event::DelegatorLeftCandidate { - delegator, - candidate, - unstaked_amount: amount, - total_candidate_staked: new_total, - }); - Ok(()) - } - pub(crate) fn prepare_staking_payouts(now: RoundIndex) -> Weight { - // payout is now - delay rounds ago => now - delay > 0 else return early - let delay = T::RewardPaymentDelay::get(); - if now <= delay { - return Weight::zero() - } - let round_to_payout = now.saturating_sub(delay); - let total_points = >::get(round_to_payout); - if total_points.is_zero() { - return Weight::zero() - } - let total_staked = >::take(round_to_payout); - let total_issuance = Self::compute_issuance(total_staked); - let mut left_issuance = total_issuance; - // reserve portion of issuance for parachain bond account - let bond_config = >::get(); - let parachain_bond_reserve = bond_config.percent * total_issuance; - if let Ok(imb) = - T::Currency::deposit_into_existing(&bond_config.account, parachain_bond_reserve) - { - // update round issuance iff transfer succeeds - left_issuance = left_issuance.saturating_sub(imb.peek()); - Self::deposit_event(Event::ReservedForParachainBond { - account: bond_config.account, - value: imb.peek(), - }); - } - - let payout = DelayedPayout { - round_issuance: total_issuance, - total_staking_reward: left_issuance, - collator_commission: >::get(), - }; - - >::insert(round_to_payout, payout); - T::WeightInfo::prepare_staking_payouts() - } - - /// Wrapper around pay_one_collator_reward which handles the following logic: - /// * whether or not a payout needs to be made - /// * cleaning up when payouts are done - /// * returns the weight consumed by pay_one_collator_reward if applicable - fn handle_delayed_payouts(now: RoundIndex) -> Weight { - let delay = T::RewardPaymentDelay::get(); - - // don't underflow uint - if now < delay { - return Weight::from_parts(0u64, 0) - } - - let paid_for_round = now.saturating_sub(delay); - - if let Some(payout_info) = >::get(paid_for_round) { - let result = Self::pay_one_collator_reward(paid_for_round, payout_info); - - // clean up storage items that we no longer need - if matches!(result.0, RewardPayment::Finished) { - >::remove(paid_for_round); - >::remove(paid_for_round); - } - result.1 // weight consumed by pay_one_collator_reward - } else { - Weight::from_parts(0u64, 0) - } - } - - /// Payout a single collator from the given round. - /// - /// Returns an optional tuple of (Collator's AccountId, total paid) - /// or None if there were no more payouts to be made for the round. - pub(crate) fn pay_one_collator_reward( - paid_for_round: RoundIndex, - payout_info: DelayedPayout>, - ) -> (RewardPayment, Weight) { - // 'early_weight' tracks weight used for reads/writes done early in this fn before its - // early-exit codepaths. - let mut early_weight = Weight::zero(); - - // TODO: it would probably be optimal to roll Points into the DelayedPayouts storage - // item so that we do fewer reads each block - let total_points = >::get(paid_for_round); - early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 0)); - - if total_points.is_zero() { - // TODO: this case is obnoxious... it's a value query, so it could mean one of two - // different logic errors: - // 1. we removed it before we should have - // 2. we called pay_one_collator_reward when we were actually done with deferred - // payouts - log::warn!("pay_one_collator_reward called with no > for the round!"); - return (RewardPayment::Finished, early_weight) - } - - let collator_fee = payout_info.collator_commission; - let collator_issuance = collator_fee * payout_info.round_issuance; - - if let Some((collator, state)) = - >::iter_prefix(paid_for_round).drain().next() - { - // read and kill AtStake - early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); - - // Take the awarded points for the collator - let pts = >::take(paid_for_round, &collator); - // read and kill AwardedPts - early_weight = early_weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); - if pts == 0 { - return (RewardPayment::Skipped, early_weight) - } - - // 'extra_weight' tracks weight returned from fns that we delegate to which can't be - // known ahead of time. - let mut extra_weight = Weight::zero(); - let pct_due = Perbill::from_rational(pts, total_points); - let total_paid = pct_due * payout_info.total_staking_reward; - let mut amt_due = total_paid; - - let num_delegators = state.delegations.len(); - if state.delegations.is_empty() { - // solo collator with no delegators - extra_weight = extra_weight - .saturating_add(T::PayoutCollatorReward::payout_collator_reward( - paid_for_round, - collator.clone(), - amt_due, - )) - .saturating_add(T::OnCollatorPayout::on_collator_payout( - paid_for_round, - collator, - amt_due, - )); - log::warn!("💵 Solo collator reward: {:?}", amt_due); - } else { - // pay collator first; commission + due_portion - let collator_pct = Perbill::from_rational(state.bond, state.total); - let commission = pct_due * collator_issuance; - amt_due = amt_due.saturating_sub(commission); - let collator_reward = (collator_pct * amt_due).saturating_add(commission); - extra_weight = extra_weight - .saturating_add(T::PayoutCollatorReward::payout_collator_reward( - paid_for_round, - collator.clone(), - collator_reward, - )) - .saturating_add(T::OnCollatorPayout::on_collator_payout( - paid_for_round, - collator.clone(), - collator_reward, - )); - - // pay delegators due portion - for BondWithAutoCompound { owner, amount, auto_compound } in state.delegations { - let percent = Perbill::from_rational(amount, state.total); - let due = percent * amt_due; - if !due.is_zero() { - extra_weight = extra_weight.saturating_add(Self::mint_and_compound( - due, - auto_compound, - collator.clone(), - owner.clone(), - )); - } - } - } - - ( - RewardPayment::Paid, - T::WeightInfo::pay_one_collator_reward(num_delegators as u32) - .saturating_add(extra_weight), - ) - } else { - // Note that we don't clean up storage here; it is cleaned up in - // handle_delayed_payouts() - (RewardPayment::Finished, Weight::from_parts(0u64, 0)) - } - } - - /// Compute the top `TotalSelected` candidates in the CandidatePool and return - /// a vec of their AccountIds (sorted by AccountId). - /// - /// If the returned vec is empty, the previous candidates should be used. - pub fn compute_top_candidates() -> Vec { - let top_n = >::get() as usize; - if top_n == 0 { - return vec![] - } - - let mut candidates = >::get().0; - - // If the number of candidates is greater than top_n, select the candidates with higher - // amount. Otherwise, return all the candidates. - if candidates.len() > top_n { - // Partially sort candidates such that element at index `top_n - 1` is sorted, and - // all the elements in the range 0..top_n are the top n elements. - candidates.select_nth_unstable_by(top_n - 1, |a, b| { - // Order by amount, then owner. The owner is needed to ensure a stable order - // when two accounts have the same amount. - a.amount.cmp(&b.amount).then_with(|| a.owner.cmp(&b.owner)).reverse() - }); - - let mut collators = candidates - .into_iter() - .take(top_n) - .map(|x| x.owner) - .collect::>(); - - // Sort collators by AccountId - collators.sort(); - - collators - } else { - // Return all candidates - // The candidates are already sorted by AccountId, so no need to sort again - candidates.into_iter().map(|x| x.owner).collect::>() - } - } - /// Best as in most cumulatively supported in terms of stake - /// Returns [collator_count, delegation_count, total staked] - pub(crate) fn select_top_candidates(now: RoundIndex) -> (Weight, u32, u32, BalanceOf) { - let (mut collator_count, mut delegation_count, mut total) = - (0u32, 0u32, BalanceOf::::zero()); - // choose the top TotalSelected qualified candidates, ordered by stake - let collators = Self::compute_top_candidates(); - if collators.is_empty() { - // SELECTION FAILED TO SELECT >=1 COLLATOR => select collators from previous round - let last_round = now.saturating_sub(1u32); - let mut total_per_candidate: BTreeMap> = BTreeMap::new(); - // set this round AtStake to last round AtStake - for (account, snapshot) in >::iter_prefix(last_round) { - collator_count = collator_count.saturating_add(1u32); - delegation_count = - delegation_count.saturating_add(snapshot.delegations.len() as u32); - total = total.saturating_add(snapshot.total); - total_per_candidate.insert(account.clone(), snapshot.total); - >::insert(now, account, snapshot); - } - // `SelectedCandidates` remains unchanged from last round - // emit CollatorChosen event for tools that use this event - for candidate in >::get() { - let snapshot_total = total_per_candidate - .get(&candidate) - .expect("all selected candidates have snapshots"); - Self::deposit_event(Event::CollatorChosen { - round: now, - collator_account: candidate, - total_exposed_amount: *snapshot_total, - }) - } - let weight = T::WeightInfo::select_top_candidates(0, 0); - return (weight, collator_count, delegation_count, total) - } - - // snapshot exposure for round for weighting reward distribution - for account in collators.iter() { - let state = >::get(account) - .expect("all members of CandidateQ must be candidates"); - - collator_count = collator_count.saturating_add(1u32); - delegation_count = delegation_count.saturating_add(state.delegation_count); - total = total.saturating_add(state.total_counted); - let CountedDelegations { uncounted_stake, rewardable_delegations } = - Self::get_rewardable_delegators(account); - let total_counted = state.total_counted.saturating_sub(uncounted_stake); - - let auto_compounding_delegations = >::get(account) - .into_iter() - .map(|x| (x.delegator, x.value)) - .collect::>(); - let rewardable_delegations = rewardable_delegations - .into_iter() - .map(|d| BondWithAutoCompound { - owner: d.owner.clone(), - amount: d.amount, - auto_compound: auto_compounding_delegations - .get(&d.owner) - .cloned() - .unwrap_or_else(Percent::zero), - }) - .collect(); - - let snapshot = CollatorSnapshot { - bond: state.bond, - delegations: rewardable_delegations, - total: total_counted, - }; - >::insert(now, account, snapshot); - Self::deposit_event(Event::CollatorChosen { - round: now, - collator_account: account.clone(), - total_exposed_amount: state.total_counted, - }); - } - // insert canonical collator set - >::put(collators); - - let avg_delegator_count = delegation_count.checked_div(collator_count).unwrap_or(0); - let weight = T::WeightInfo::select_top_candidates(collator_count, avg_delegator_count); - (weight, collator_count, delegation_count, total) - } - - /// Apply the delegator intent for revoke and decrease in order to build the - /// effective list of delegators with their intended bond amount. - /// - /// This will: - /// - if [DelegationChange::Revoke] is outstanding, set the bond amount to 0. - /// - if [DelegationChange::Decrease] is outstanding, subtract the bond by specified amount. - /// - else, do nothing - /// - /// The intended bond amounts will be used while calculating rewards. - pub(crate) fn get_rewardable_delegators(collator: &T::AccountId) -> CountedDelegations { - let requests = >::get(collator) - .into_iter() - .map(|x| (x.delegator, x.action)) - .collect::>(); - let mut uncounted_stake = BalanceOf::::zero(); - let rewardable_delegations = >::get(collator) - .expect("all members of CandidateQ must be candidates") - .delegations - .into_iter() - .map(|mut bond| { - bond.amount = match requests.get(&bond.owner) { - None => bond.amount, - Some(DelegationAction::Revoke(_)) => { - uncounted_stake = uncounted_stake.saturating_add(bond.amount); - BalanceOf::::zero() - }, - Some(DelegationAction::Decrease(amount)) => { - uncounted_stake = uncounted_stake.saturating_add(*amount); - bond.amount.saturating_sub(*amount) - }, - }; - - bond - }) - .collect(); - CountedDelegations { uncounted_stake, rewardable_delegations } - } - - /// This function exists as a helper to delegator_bond_more & auto_compound functionality. - /// Any changes to this function must align with both user-initiated bond increases and - /// auto-compounding bond increases. - /// Any feature-specific preconditions should be validated before this function is invoked. - /// Any feature-specific events must be emitted after this function is invoked. - pub fn delegation_bond_more_without_event( - delegator: T::AccountId, - candidate: T::AccountId, - more: BalanceOf, - ) -> Result { - ensure!( - !Self::delegation_request_revoke_exists(&candidate, &delegator), - Error::::PendingDelegationRevoke - ); - let mut state = >::get(&delegator).ok_or(Error::::DelegatorDNE)?; - state.increase_delegation::(candidate, more) - } - - /// Mint a specified reward amount to the beneficiary account. Emits the [Rewarded] event. - pub fn mint(amt: BalanceOf, to: T::AccountId) { - if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&to, amt) { - Self::deposit_event(Event::Rewarded { - account: to.clone(), - rewards: amount_transferred.peek(), - }); - } - } - - /// Mint a specified reward amount to the collator's account. Emits the [Rewarded] event. - pub fn mint_collator_reward( - _paid_for_round: RoundIndex, - collator_id: T::AccountId, - amt: BalanceOf, - ) -> Weight { - if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&collator_id, amt) { - Self::deposit_event(Event::Rewarded { - account: collator_id.clone(), - rewards: amount_transferred.peek(), - }); - } - T::WeightInfo::mint_collator_reward() - } - - /// Mint and compound delegation rewards. The function mints the amount towards the - /// delegator and tries to compound a specified percent of it back towards the delegation. - /// If a scheduled delegation revoke exists, then the amount is only minted, and nothing is - /// compounded. Emits the [Compounded] event. - pub fn mint_and_compound( - amt: BalanceOf, - compound_percent: Percent, - candidate: T::AccountId, - delegator: T::AccountId, - ) -> Weight { - let mut weight = T::WeightInfo::mint_collator_reward(); - if let Ok(amount_transferred) = T::Currency::deposit_into_existing(&delegator, amt) { - Self::deposit_event(Event::Rewarded { - account: delegator.clone(), - rewards: amount_transferred.peek(), - }); - - let compound_amount = compound_percent.mul_ceil(amount_transferred.peek()); - if compound_amount.is_zero() { - return weight - } - - if let Err(err) = Self::delegation_bond_more_without_event( - delegator.clone(), - candidate.clone(), - compound_amount, - ) { - log::warn!( - "skipped compounding staking reward towards candidate '{:?}' for delegator '{:?}': {:?}", - candidate, - delegator, - err - ); - return weight - }; - weight = weight.saturating_add(T::WeightInfo::delegator_bond_more()); - - Pallet::::deposit_event(Event::Compounded { - delegator, - candidate, - amount: compound_amount, - }); - }; - - weight - } - } - - /// Add reward points to block authors: - /// * 20 points to the block producer for producing a block in the chain - impl Pallet { - fn award_points_to_block_author(author: AccountIdOf) { - let now = >::get().current; - let score_plus_20 = >::get(now, &author).saturating_add(20); - >::insert(now, author, score_plus_20); - >::mutate(now, |x| *x = x.saturating_add(20)); - } - } - - impl Get> for Pallet { - fn get() -> Vec { - Self::selected_candidates() - } - } - impl pallet_authorship::EventHandler, T::BlockNumber> for Pallet - where - T: Config + pallet_authorship::Config + pallet_session::Config, - { - /// Add reward points to block authors: - /// * 20 points to the block producer for producing a block in the chain - fn note_author(author: AccountIdOf) { - Pallet::::award_points_to_block_author(author); - } - } - - impl pallet_session::SessionManager> for Pallet { - /// 1. A new session starts. - /// 2. In hook new_session: Read the current top n candidates from the - /// TopCandidates and assign this set to author blocks for the next - /// session. - /// 3. AuRa queries the authorities from the session pallet for - /// this session and picks authors on round-robin-basis from list of - /// authorities. - fn new_session(new_index: SessionIndex) -> Option>> { - log::warn!( - "assembling new collators for new session {} at #{:?}", - new_index, - >::block_number(), - ); - - let collators = Pallet::::selected_candidates().to_vec(); - if collators.is_empty() { - // we never want to pass an empty set of collators. This would brick the chain. - log::error!("💥 keeping old session because of empty collator set!"); - None - } else { - Some(collators) - } - } - - fn end_session(_end_index: SessionIndex) { - // we too are not caring. - } - - fn start_session(_start_index: SessionIndex) { - // we too are not caring. - } - } - - impl pallet_session::ShouldEndSession for Pallet { - fn should_end_session(now: T::BlockNumber) -> bool { - let round = >::get(); - // always update when a new round should start - round.should_update(now) - } - } - - impl EstimateNextSessionRotation for Pallet { - fn average_session_length() -> T::BlockNumber { - T::BlockNumber::from(>::get().length) - } - - fn estimate_current_session_progress(now: T::BlockNumber) -> (Option, Weight) { - let round = >::get(); - let passed_blocks = now.saturating_sub(round.first); - - ( - Some(Permill::from_rational(passed_blocks, T::BlockNumber::from(round.length))), - // One read for the round info, blocknumber is read free - T::DbWeight::get().reads(1), - ) - } - - fn estimate_next_session_rotation( - _now: T::BlockNumber, - ) -> (Option, Weight) { - let round = >::get(); - - ( - Some(round.first + round.length.into()), - // One read for the round info, blocknumber is read free - T::DbWeight::get().reads(1), - ) - } - } -} diff --git a/pallets/parachain-staking/src/migrations.rs b/pallets/parachain-staking/src/migrations.rs deleted file mode 100644 index de1629368..000000000 --- a/pallets/parachain-staking/src/migrations.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam 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. - -// Moonbeam 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 Moonbeam. If not, see . - -//! # Migrations diff --git a/pallets/parachain-staking/src/mock.rs b/pallets/parachain-staking/src/mock.rs deleted file mode 100644 index 09f6906fc..000000000 --- a/pallets/parachain-staking/src/mock.rs +++ /dev/null @@ -1,1008 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam 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. - -// Moonbeam 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 Moonbeam. If not, see . - -//! Test utilities -use crate as pallet_parachain_staking; -use crate::{ - pallet, AwardedPts, Config, Event as ParachainStakingEvent, InflationInfo, Points, Range, - COLLATOR_LOCK_ID, DELEGATOR_LOCK_ID, -}; -use frame_support::{ - construct_runtime, parameter_types, - traits::{Everything, GenesisBuild, LockIdentifier, OnFinalize, OnInitialize}, - weights::{constants::RocksDbWeight, Weight}, -}; -use sp_core::H256; -use sp_io; -use sp_runtime::{ - traits::{BlakeTwo256, IdentityLookup}, - Perbill, Percent, -}; - -pub type AccountId = u64; -pub type Balance = u128; -pub type BlockNumber = u32; - -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -type Block = frame_system::mocking::MockBlock; - -// Configure a mock runtime to test the pallet. -construct_runtime!( - pub enum Test where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - Aura: pallet_aura::{Pallet, Storage}, - Session: pallet_session::{Pallet, Call, Storage, Event, Config}, - ParachainStaking: pallet_parachain_staking::{Pallet, Call, Storage, Config, Event}, - Authorship: pallet_authorship::{Pallet, Storage}, - } -); - -parameter_types! { - pub const BlockHashCount: u32 = 250; - pub const MaximumBlockWeight: Weight = Weight::from_parts(1024, 1); - pub const MaximumBlockLength: u32 = 2 * 1024; - pub const AvailableBlockRatio: Perbill = Perbill::one(); - pub const SS58Prefix: u8 = 42; -} -impl frame_system::Config for Test { - type BaseCallFilter = Everything; - type DbWeight = RocksDbWeight; - type RuntimeOrigin = RuntimeOrigin; - type Index = u64; - type BlockNumber = BlockNumber; - type RuntimeCall = RuntimeCall; - type Hash = H256; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type Header = sp_runtime::generic::Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type BlockWeights = (); - type BlockLength = (); - type SS58Prefix = SS58Prefix; - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} -parameter_types! { - pub const ExistentialDeposit: u128 = 1; -} -impl pallet_balances::Config for Test { - type MaxReserves = (); - type ReserveIdentifier = [u8; 4]; - type MaxLocks = (); - type Balance = Balance; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); - type HoldIdentifier = (); - type FreezeIdentifier = (); - type MaxHolds = (); - type MaxFreezes = (); -} -parameter_types! { - #[derive(Debug, Eq, PartialEq)] - pub const MaxCollatorCandidates: u32 = 10; -} -use sp_consensus_aura::sr25519::AuthorityId; -impl pallet_aura::Config for Test { - type AuthorityId = AuthorityId; - type DisabledValidators = (); - type MaxAuthorities = MaxCollatorCandidates; -} - -impl pallet_authorship::Config for Test { - type FindAuthor = pallet_session::FindAccountFromAuthorIndex; - type EventHandler = ParachainStaking; -} -parameter_types! { - pub const MinimumPeriod: u64 = 1; -} - -impl pallet_timestamp::Config for Test { - type Moment = u64; - type OnTimestampSet = Aura; - type MinimumPeriod = MinimumPeriod; - type WeightInfo = (); -} - -const GENESIS_BLOCKS_PER_ROUND: u32 = 5; -const GENESIS_COLLATOR_COMMISSION: Perbill = Perbill::from_percent(20); -const GENESIS_PARACHAIN_BOND_RESERVE_PERCENT: Percent = Percent::from_percent(30); -const GENESIS_NUM_SELECTED_CANDIDATES: u32 = 5; -parameter_types! { - pub const MinBlocksPerRound: u32 = 3; - pub const LeaveCandidatesDelay: u32 = 2; - pub const CandidateBondLessDelay: u32 = 2; - pub const LeaveDelegatorsDelay: u32 = 2; - pub const RevokeDelegationDelay: u32 = 2; - pub const DelegationBondLessDelay: u32 = 2; - pub const RewardPaymentDelay: u32 = 2; - pub const MinSelectedCandidates: u32 = GENESIS_NUM_SELECTED_CANDIDATES; - pub const MaxTopDelegationsPerCandidate: u32 = 4; - pub const MaxBottomDelegationsPerCandidate: u32 = 4; - pub const MaxDelegationsPerDelegator: u32 = 4; - pub const MinCandidateStk: u128 = 10; - pub const MinDelegatorStk: u128 = 5; - pub const MinDelegation: u128 = 3; -} -impl_opaque_keys! { - pub struct MockSessionKeys { - pub aura: Aura, - } -} - -parameter_types! { - pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17); -} -use sp_runtime::{ - impl_opaque_keys, - traits::{ConvertInto, OpaqueKeys}, -}; - -impl pallet_session::Config for Test { - type RuntimeEvent = RuntimeEvent; - type ValidatorId = AccountId; - type ValidatorIdOf = ConvertInto; - type ShouldEndSession = ParachainStaking; - type NextSessionRotation = ParachainStaking; - type SessionManager = ParachainStaking; - type SessionHandler = ::KeyTypeIdProviders; - type Keys = MockSessionKeys; - type WeightInfo = (); -} -impl Config for Test { - type RuntimeEvent = RuntimeEvent; - type Currency = Balances; - type MonetaryGovernanceOrigin = frame_system::EnsureRoot; - type MinBlocksPerRound = MinBlocksPerRound; - type LeaveCandidatesDelay = LeaveCandidatesDelay; - type CandidateBondLessDelay = CandidateBondLessDelay; - type LeaveDelegatorsDelay = LeaveDelegatorsDelay; - type RevokeDelegationDelay = RevokeDelegationDelay; - type DelegationBondLessDelay = DelegationBondLessDelay; - type RewardPaymentDelay = RewardPaymentDelay; - type MinSelectedCandidates = MinSelectedCandidates; - type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; - type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate; - type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator; - type MinCandidateStk = MinCandidateStk; - type MinDelegatorStk = MinDelegatorStk; - type MinDelegation = MinDelegation; - type OnCollatorPayout = (); - type PayoutCollatorReward = (); - type OnNewRound = (); - type WeightInfo = (); -} - -pub(crate) struct ExtBuilder { - // endowed accounts with balances - balances: Vec<(AccountId, Balance)>, - // [collator, amount] - collators: Vec<(AccountId, Balance)>, - // [delegator, collator, delegation_amount, auto_compound_percent] - delegations: Vec<(AccountId, AccountId, Balance, Percent)>, - // inflation config - inflation: InflationInfo, -} - -impl Default for ExtBuilder { - fn default() -> ExtBuilder { - ExtBuilder { - balances: vec![], - delegations: vec![], - collators: vec![], - inflation: InflationInfo { - expect: Range { min: 700, ideal: 700, max: 700 }, - // not used - annual: Range { - min: Perbill::from_percent(50), - ideal: Perbill::from_percent(50), - max: Perbill::from_percent(50), - }, - // unrealistically high parameterization, only for testing - round: Range { - min: Perbill::from_percent(5), - ideal: Perbill::from_percent(5), - max: Perbill::from_percent(5), - }, - }, - } - } -} - -impl ExtBuilder { - pub(crate) fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self { - self.balances = balances; - self - } - - pub(crate) fn with_candidates(mut self, collators: Vec<(AccountId, Balance)>) -> Self { - self.collators = collators; - self - } - - pub(crate) fn with_delegations( - mut self, - delegations: Vec<(AccountId, AccountId, Balance)>, - ) -> Self { - self.delegations = - delegations.into_iter().map(|d| (d.0, d.1, d.2, Percent::zero())).collect(); - self - } - - pub(crate) fn with_auto_compounding_delegations( - mut self, - delegations: Vec<(AccountId, AccountId, Balance, Percent)>, - ) -> Self { - self.delegations = delegations; - self - } - - #[allow(dead_code)] - pub(crate) fn with_inflation(mut self, inflation: InflationInfo) -> Self { - self.inflation = inflation; - self - } - - pub(crate) fn build(self) -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default() - .build_storage::() - .expect("Frame system builds valid default genesis config"); - - pallet_balances::GenesisConfig:: { balances: self.balances } - .assimilate_storage(&mut t) - .expect("Pallet balances storage can be assimilated"); - pallet_parachain_staking::GenesisConfig:: { - candidates: self.collators, - delegations: self.delegations, - inflation_config: self.inflation, - collator_commission: GENESIS_COLLATOR_COMMISSION, - parachain_bond_reserve_percent: GENESIS_PARACHAIN_BOND_RESERVE_PERCENT, - blocks_per_round: GENESIS_BLOCKS_PER_ROUND, - num_selected_candidates: GENESIS_NUM_SELECTED_CANDIDATES, - } - .assimilate_storage(&mut t) - .expect("Parachain Staking's storage can be assimilated"); - - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| System::set_block_number(1)); - ext - } -} - -/// Rolls forward one block. Returns the new block number. -fn roll_one_block() -> BlockNumber { - Balances::on_finalize(System::block_number()); - System::on_finalize(System::block_number()); - System::set_block_number(System::block_number() + 1); - System::reset_events(); - System::on_initialize(System::block_number()); - Balances::on_initialize(System::block_number()); - ParachainStaking::on_initialize(System::block_number()); - System::block_number() -} - -/// Rolls to the desired block. Returns the number of blocks played. -pub(crate) fn roll_to(n: BlockNumber) -> u32 { - let mut num_blocks = 0; - let mut block = System::block_number(); - while block < n { - block = roll_one_block(); - num_blocks += 1; - } - num_blocks -} - -/// Rolls desired number of blocks. Returns the final block. -pub(crate) fn roll_blocks(num_blocks: u32) -> BlockNumber { - let mut block = System::block_number(); - for _ in 0..num_blocks { - block = roll_one_block(); - } - block -} - -/// Rolls block-by-block to the beginning of the specified round. -/// This will complete the block in which the round change occurs. -/// Returns the number of blocks played. -pub(crate) fn roll_to_round_begin(round: BlockNumber) -> BlockNumber { - let block = (round - 1) * GENESIS_BLOCKS_PER_ROUND; - roll_to(block) -} - -/// Rolls block-by-block to the end of the specified round. -/// The block following will be the one in which the specified round change occurs. -pub(crate) fn roll_to_round_end(round: BlockNumber) -> BlockNumber { - let block = round * GENESIS_BLOCKS_PER_ROUND - 1; - roll_to(block) -} - -pub(crate) fn events() -> Vec> { - System::events() - .into_iter() - .map(|r| r.event) - .filter_map( - |e| { - if let RuntimeEvent::ParachainStaking(inner) = e { - Some(inner) - } else { - None - } - }, - ) - .collect::>() -} - -/// Asserts that some events were never emitted. -/// -/// # Example -/// -/// ``` -/// assert_no_events!(); -/// ``` -#[macro_export] -macro_rules! assert_no_events { - () => { - similar_asserts::assert_eq!(Vec::>::new(), crate::mock::events()) - }; -} - -/// Asserts that emitted events match exactly the given input. -/// -/// # Example -/// -/// ``` -/// assert_events_eq!( -/// Foo { x: 1, y: 2 }, -/// Bar { value: "test" }, -/// Baz { a: 10, b: 20 }, -/// ); -/// ``` -#[macro_export] -macro_rules! assert_events_eq { - ($event:expr) => { - similar_asserts::assert_eq!(vec![$event], crate::mock::events()); - }; - ($($events:expr,)+) => { - similar_asserts::assert_eq!(vec![$($events,)+], crate::mock::events()); - }; -} - -/// Asserts that some emitted events match the given input. -/// -/// # Example -/// -/// ``` -/// assert_events_emitted!( -/// Foo { x: 1, y: 2 }, -/// Baz { a: 10, b: 20 }, -/// ); -/// ``` -#[macro_export] -macro_rules! assert_events_emitted { - ($event:expr) => { - [$event].into_iter().for_each(|e| assert!( - crate::mock::events().into_iter().find(|x| x == &e).is_some(), - "Event {:?} was not found in events: \n{:#?}", - e, - crate::mock::events() - )); - }; - ($($events:expr,)+) => { - [$($events,)+].into_iter().for_each(|e| assert!( - crate::mock::events().into_iter().find(|x| x == &e).is_some(), - "Event {:?} was not found in events: \n{:#?}", - e, - crate::mock::events() - )); - }; -} - -/// Asserts that some events were never emitted. -/// -/// # Example -/// -/// ``` -/// assert_events_not_emitted!( -/// Foo { x: 1, y: 2 }, -/// Bar { value: "test" }, -/// ); -/// ``` -#[macro_export] -macro_rules! assert_events_not_emitted { - ($event:expr) => { - [$event].into_iter().for_each(|e| assert!( - crate::mock::events().into_iter().find(|x| x != &e).is_some(), - "Event {:?} was unexpectedly found in events: \n{:#?}", - e, - crate::mock::events() - )); - }; - ($($events:expr,)+) => { - [$($events,)+].into_iter().for_each(|e| assert!( - crate::mock::events().into_iter().find(|x| x != &e).is_some(), - "Event {:?} was unexpectedly found in events: \n{:#?}", - e, - crate::mock::events() - )); - }; -} - -/// Asserts that the emitted events are exactly equal to the input patterns. -/// -/// # Example -/// -/// ``` -/// assert_events_eq_match!( -/// Foo { x: 1, .. }, -/// Bar { .. }, -/// Baz { a: 10, b: 20 }, -/// ); -/// ``` -#[macro_export] -macro_rules! assert_events_eq_match { - ($index:expr;) => { - assert_eq!( - $index, - crate::mock::events().len(), - "Found {} extra event(s): \n{:#?}", - crate::mock::events().len()-$index, - crate::mock::events() - ); - }; - ($index:expr; $event:pat_param, $($events:pat_param,)*) => { - assert!( - matches!( - crate::mock::events().get($index), - Some($event), - ), - "Event {:#?} was not found at index {}: \n{:#?}", - stringify!($event), - $index, - crate::mock::events() - ); - assert_events_eq_match!($index+1; $($events,)*); - }; - ($event:pat_param) => { - assert_events_eq_match!(0; $event,); - }; - ($($events:pat_param,)+) => { - assert_events_eq_match!(0; $($events,)+); - }; -} - -/// Asserts that some emitted events match the input patterns. -/// -/// # Example -/// -/// ``` -/// assert_events_emitted_match!( -/// Foo { x: 1, .. }, -/// Baz { a: 10, b: 20 }, -/// ); -/// ``` -#[macro_export] -macro_rules! assert_events_emitted_match { - ($event:pat_param) => { - assert!( - crate::mock::events().into_iter().any(|x| matches!(x, $event)), - "Event {:?} was not found in events: \n{:#?}", - stringify!($event), - crate::mock::events() - ); - }; - ($event:pat_param, $($events:pat_param,)+) => { - assert_events_emitted_match!($event); - $( - assert_events_emitted_match!($events); - )+ - }; -} - -/// Asserts that the input patterns match none of the emitted events. -/// -/// # Example -/// -/// ``` -/// assert_events_not_emitted_match!( -/// Foo { x: 1, .. }, -/// Baz { a: 10, b: 20 }, -/// ); -/// ``` -#[macro_export] -macro_rules! assert_events_not_emitted_match { - ($event:pat_param) => { - assert!( - crate::mock::events().into_iter().any(|x| !matches!(x, $event)), - "Event {:?} was unexpectedly found in events: \n{:#?}", - stringify!($event), - crate::mock::events() - ); - }; - ($event:pat_param, $($events:pat_param,)+) => { - assert_events_not_emitted_match!($event); - $( - assert_events_not_emitted_match!($events); - )+ - }; -} - -// Same storage changes as ParachainStaking::on_finalize -pub(crate) fn set_author(round: BlockNumber, acc: u64, pts: u32) { - >::mutate(round, |p| *p += pts); - >::mutate(round, acc, |p| *p += pts); -} - -/// fn to query the lock amount -pub(crate) fn query_lock_amount(account_id: u64, id: LockIdentifier) -> Option { - for lock in Balances::locks(&account_id) { - if lock.id == id { - return Some(lock.amount) - } - } - None -} - -#[test] -fn geneses() { - ExtBuilder::default() - .with_balances(vec![ - (1, 1000), - (2, 300), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 9), - (9, 4), - ]) - .with_candidates(vec![(1, 500), (2, 200)]) - .with_delegations(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) - .build() - .execute_with(|| { - assert!(System::events().is_empty()); - // collators - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 500); - assert_eq!(query_lock_amount(1, COLLATOR_LOCK_ID), Some(500)); - assert!(ParachainStaking::is_candidate(&1)); - assert_eq!(query_lock_amount(2, COLLATOR_LOCK_ID), Some(200)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&2), 100); - assert!(ParachainStaking::is_candidate(&2)); - // delegators - for x in 3..7 { - assert!(ParachainStaking::is_delegator(&x)); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&x), 0); - assert_eq!(query_lock_amount(x, DELEGATOR_LOCK_ID), Some(100)); - } - // uninvolved - for x in 7..10 { - assert!(!ParachainStaking::is_delegator(&x)); - } - // no delegator staking locks - assert_eq!(query_lock_amount(7, DELEGATOR_LOCK_ID), None); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&7), 100); - assert_eq!(query_lock_amount(8, DELEGATOR_LOCK_ID), None); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&8), 9); - assert_eq!(query_lock_amount(9, DELEGATOR_LOCK_ID), None); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&9), 4); - // no collator staking locks - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&7), 100); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&8), 9); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&9), 4); - }); - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - ]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) - .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) - .build() - .execute_with(|| { - assert!(System::events().is_empty()); - // collators - for x in 1..5 { - assert!(ParachainStaking::is_candidate(&x)); - assert_eq!(query_lock_amount(x, COLLATOR_LOCK_ID), Some(20)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&x), 80); - } - assert!(ParachainStaking::is_candidate(&5)); - assert_eq!(query_lock_amount(5, COLLATOR_LOCK_ID), Some(10)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&5), 90); - // delegators - for x in 6..11 { - assert!(ParachainStaking::is_delegator(&x)); - assert_eq!(query_lock_amount(x, DELEGATOR_LOCK_ID), Some(10)); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&x), 90); - } - }); -} - -#[test] -fn roll_to_round_begin_works() { - ExtBuilder::default().build().execute_with(|| { - // these tests assume blocks-per-round of 5, as established by GENESIS_BLOCKS_PER_ROUND - assert_eq!(System::block_number(), 1); // we start on block 1 - - let num_blocks = roll_to_round_begin(1); - assert_eq!(System::block_number(), 1); // no-op, we're already on this round - assert_eq!(num_blocks, 0); - - let num_blocks = roll_to_round_begin(2); - assert_eq!(System::block_number(), 5); - assert_eq!(num_blocks, 4); - - let num_blocks = roll_to_round_begin(3); - assert_eq!(System::block_number(), 10); - assert_eq!(num_blocks, 5); - }); -} - -#[test] -fn roll_to_round_end_works() { - ExtBuilder::default().build().execute_with(|| { - // these tests assume blocks-per-round of 5, as established by GENESIS_BLOCKS_PER_ROUND - assert_eq!(System::block_number(), 1); // we start on block 1 - - let num_blocks = roll_to_round_end(1); - assert_eq!(System::block_number(), 4); - assert_eq!(num_blocks, 3); - - let num_blocks = roll_to_round_end(2); - assert_eq!(System::block_number(), 9); - assert_eq!(num_blocks, 5); - - let num_blocks = roll_to_round_end(3); - assert_eq!(System::block_number(), 14); - assert_eq!(num_blocks, 5); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_eq_fails_if_event_missing() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq!( - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 10, - }, - ); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_eq_fails_if_event_extra() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq!( - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 10, - }, - ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, - ParachainStakingEvent::Rewarded { account: 1, rewards: 200 }, - ); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_eq_fails_if_event_wrong_order() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq!( - ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 10, - }, - ); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_eq_fails_if_event_wrong_value() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq!( - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 10, - }, - ParachainStakingEvent::Rewarded { account: 1, rewards: 50 }, - ); - }); -} - -#[test] -fn test_assert_events_eq_passes_if_all_events_present_single() { - ExtBuilder::default().build().execute_with(|| { - System::deposit_event(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); - - assert_events_eq!(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); - }); -} - -#[test] -fn test_assert_events_eq_passes_if_all_events_present_multiple() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq!( - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 10, - }, - ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, - ); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_emitted_fails_if_event_missing() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_emitted!(ParachainStakingEvent::DelegatorExitScheduled { - round: 2, - delegator: 3, - scheduled_exit: 4, - }); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_emitted_fails_if_event_wrong_value() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_emitted!(ParachainStakingEvent::Rewarded { account: 1, rewards: 50 }); - }); -} - -#[test] -fn test_assert_events_emitted_passes_if_all_events_present_single() { - ExtBuilder::default().build().execute_with(|| { - System::deposit_event(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); - - assert_events_emitted!(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); - }); -} - -#[test] -fn test_assert_events_emitted_passes_if_all_events_present_multiple() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_emitted!( - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, - ); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_eq_match_fails_if_event_missing() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq_match!( - ParachainStakingEvent::CollatorChosen { .. }, - ParachainStakingEvent::NewRound { .. }, - ); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_eq_match_fails_if_event_extra() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq_match!( - ParachainStakingEvent::CollatorChosen { .. }, - ParachainStakingEvent::NewRound { .. }, - ParachainStakingEvent::Rewarded { .. }, - ParachainStakingEvent::Rewarded { .. }, - ); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_eq_match_fails_if_event_wrong_order() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq_match!( - ParachainStakingEvent::Rewarded { .. }, - ParachainStakingEvent::CollatorChosen { .. }, - ParachainStakingEvent::NewRound { .. }, - ); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_eq_match_fails_if_event_wrong_value() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq_match!( - ParachainStakingEvent::CollatorChosen { .. }, - ParachainStakingEvent::NewRound { .. }, - ParachainStakingEvent::Rewarded { rewards: 50, .. }, - ); - }); -} - -#[test] -fn test_assert_events_eq_match_passes_if_all_events_present_single() { - ExtBuilder::default().build().execute_with(|| { - System::deposit_event(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); - - assert_events_eq_match!(ParachainStakingEvent::Rewarded { account: 1, .. }); - }); -} - -#[test] -fn test_assert_events_eq_match_passes_if_all_events_present_multiple() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_eq_match!( - ParachainStakingEvent::CollatorChosen { round: 2, collator_account: 1, .. }, - ParachainStakingEvent::NewRound { starting_block: 10, .. }, - ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, - ); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_emitted_match_fails_if_event_missing() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_emitted_match!(ParachainStakingEvent::DelegatorExitScheduled { - round: 2, - .. - }); - }); -} - -#[test] -#[should_panic] -fn test_assert_events_emitted_match_fails_if_event_wrong_value() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_emitted_match!(ParachainStakingEvent::Rewarded { rewards: 50, .. }); - }); -} - -#[test] -fn test_assert_events_emitted_match_passes_if_all_events_present_single() { - ExtBuilder::default().build().execute_with(|| { - System::deposit_event(ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }); - - assert_events_emitted_match!(ParachainStakingEvent::Rewarded { rewards: 100, .. }); - }); -} - -#[test] -fn test_assert_events_emitted_match_passes_if_all_events_present_multiple() { - ExtBuilder::default().build().execute_with(|| { - inject_test_events(); - - assert_events_emitted_match!( - ParachainStakingEvent::CollatorChosen { total_exposed_amount: 10, .. }, - ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, - ); - }); -} - -fn inject_test_events() { - [ - ParachainStakingEvent::CollatorChosen { - round: 2, - collator_account: 1, - total_exposed_amount: 10, - }, - ParachainStakingEvent::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 10, - }, - ParachainStakingEvent::Rewarded { account: 1, rewards: 100 }, - ] - .into_iter() - .for_each(System::deposit_event); -} diff --git a/pallets/parachain-staking/src/set.rs b/pallets/parachain-staking/src/set.rs deleted file mode 100644 index 1f15d68ae..000000000 --- a/pallets/parachain-staking/src/set.rs +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam 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. - -// Moonbeam 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 Moonbeam. If not, see . - -/* TODO: use orml_utilities::OrderedSet without leaking substrate v2.0 dependencies*/ -use parity_scale_codec::{Decode, Encode}; -use scale_info::TypeInfo; -#[cfg(feature = "std")] -use serde::{Deserialize, Serialize}; -use sp_runtime::RuntimeDebug; -use sp_std::prelude::*; - -/// An ordered set backed by `Vec` -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -#[derive(RuntimeDebug, PartialEq, Eq, Encode, Decode, Default, Clone, TypeInfo)] -pub struct OrderedSet(pub Vec); - -impl OrderedSet { - /// Create a new empty set - pub fn new() -> Self { - Self(Vec::new()) - } - - /// Create a set from a `Vec`. - /// `v` will be sorted and dedup first. - pub fn from(mut v: Vec) -> Self { - v.sort(); - v.dedup(); - Self::from_sorted_set(v) - } - - /// Create a set from a `Vec`. - /// Assume `v` is sorted and contain unique elements. - pub fn from_sorted_set(v: Vec) -> Self { - Self(v) - } - - /// Insert an element. - /// Return true if insertion happened. - pub fn insert(&mut self, value: T) -> bool { - match self.0.binary_search(&value) { - Ok(_) => false, - Err(loc) => { - self.0.insert(loc, value); - true - }, - } - } - - /// Remove an element. - /// Return true if removal happened. - pub fn remove(&mut self, value: &T) -> bool { - match self.0.binary_search(value) { - Ok(loc) => { - self.0.remove(loc); - true - }, - Err(_) => false, - } - } - - /// Return if the set contains `value` - pub fn contains(&self, value: &T) -> bool { - self.0.binary_search(value).is_ok() - } - - /// Clear the set - pub fn clear(&mut self) { - self.0.clear(); - } -} - -impl From> for OrderedSet { - fn from(v: Vec) -> Self { - Self::from(v) - } -} diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs deleted file mode 100644 index f35fd0b91..000000000 --- a/pallets/parachain-staking/src/tests.rs +++ /dev/null @@ -1,6934 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam 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. - -// Moonbeam 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 Moonbeam. If not, see . - -//! # Staking Pallet Unit Tests -//! The unit tests are organized by the call they test. The order matches the order -//! of the calls in the `lib.rs`. -//! 1. Root -//! 2. Monetary Governance -//! 3. Public (Collator, Nominator) -//! 4. Miscellaneous Property-Based Tests - -use crate::{ - assert_events_emitted, assert_events_emitted_match, assert_events_eq, assert_no_events, - auto_compound::{AutoCompoundConfig, AutoCompoundDelegations}, - delegation_requests::{CancelledScheduledRequest, DelegationAction, ScheduledRequest}, - mock::{ - roll_blocks, roll_to, roll_to_round_begin, roll_to_round_end, set_author, Balances, - BlockNumber, ExtBuilder, ParachainStaking, RuntimeOrigin, Test, - }, - AtStake, Bond, CollatorStatus, DelegationScheduledRequests, DelegatorAdded, DelegatorState, - DelegatorStatus, Error, Event, Range, DELEGATOR_LOCK_ID, -}; -use frame_support::{assert_noop, assert_ok}; -use sp_runtime::{traits::Zero, Perbill, Percent}; - -// ~~ ROOT ~~ - -#[test] -fn invalid_root_origin_fails() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_total_selected(RuntimeOrigin::signed(45), 6u32), - sp_runtime::DispatchError::BadOrigin - ); - assert_noop!( - ParachainStaking::set_collator_commission( - RuntimeOrigin::signed(45), - Perbill::from_percent(5) - ), - sp_runtime::DispatchError::BadOrigin - ); - assert_noop!( - ParachainStaking::set_blocks_per_round(RuntimeOrigin::signed(45), 3u32), - sp_runtime::DispatchError::BadOrigin - ); - }); -} - -// SET TOTAL SELECTED - -#[test] -fn set_total_selected_event_emits_correctly() { - ExtBuilder::default().build().execute_with(|| { - // before we can bump total_selected we must bump the blocks per round - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 7u32)); - roll_blocks(1); - assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 6u32)); - assert_events_eq!(Event::TotalSelectedSet { old: 5u32, new: 6u32 }); - }); -} - -#[test] -fn set_total_selected_fails_if_above_blocks_per_round() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(ParachainStaking::round().length, 5); // test relies on this - assert_noop!( - ParachainStaking::set_total_selected(RuntimeOrigin::root(), 6u32), - Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, - ); - }); -} - -#[test] -fn set_total_selected_fails_if_equal_to_blocks_per_round() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); - assert_noop!( - ParachainStaking::set_total_selected(RuntimeOrigin::root(), 10u32), - Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, - ); - }); -} - -#[test] -fn set_total_selected_passes_if_below_blocks_per_round() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); - assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 9u32)); - }); -} - -#[test] -fn set_blocks_per_round_fails_if_below_total_selected() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 20u32)); - assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 15u32)); - assert_noop!( - ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 14u32), - Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, - ); - }); -} - -#[test] -fn set_blocks_per_round_fails_if_equal_to_total_selected() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); - assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 9u32)); - assert_noop!( - ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 9u32), - Error::::RoundLengthMustBeGreaterThanTotalSelectedCollators, - ); - }); -} - -#[test] -fn set_blocks_per_round_passes_if_above_total_selected() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(ParachainStaking::round().length, 5); // test relies on this - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); - }); -} - -#[test] -fn set_total_selected_storage_updates_correctly() { - ExtBuilder::default().build().execute_with(|| { - // round length must be >= total_selected, so update that first - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); - - assert_eq!(ParachainStaking::total_selected(), 5u32); - assert_ok!(ParachainStaking::set_total_selected(RuntimeOrigin::root(), 6u32)); - assert_eq!(ParachainStaking::total_selected(), 6u32); - }); -} - -#[test] -fn cannot_set_total_selected_to_current_total_selected() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_total_selected(RuntimeOrigin::root(), 5u32), - Error::::NoWritingSameValue - ); - }); -} - -#[test] -fn cannot_set_total_selected_below_module_min() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_total_selected(RuntimeOrigin::root(), 4u32), - Error::::CannotSetBelowMin - ); - }); -} - -// SET COLLATOR COMMISSION - -#[test] -fn set_collator_commission_event_emits_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_collator_commission( - RuntimeOrigin::root(), - Perbill::from_percent(5) - )); - assert_events_eq!(Event::CollatorCommissionSet { - old: Perbill::from_percent(20), - new: Perbill::from_percent(5), - }); - }); -} - -#[test] -fn set_collator_commission_storage_updates_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(ParachainStaking::collator_commission(), Perbill::from_percent(20)); - assert_ok!(ParachainStaking::set_collator_commission( - RuntimeOrigin::root(), - Perbill::from_percent(5) - )); - assert_eq!(ParachainStaking::collator_commission(), Perbill::from_percent(5)); - }); -} - -#[test] -fn cannot_set_collator_commission_to_current_collator_commission() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_collator_commission( - RuntimeOrigin::root(), - Perbill::from_percent(20) - ), - Error::::NoWritingSameValue - ); - }); -} - -// SET BLOCKS PER ROUND - -#[test] -fn set_blocks_per_round_event_emits_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); - assert_events_eq!(Event::BlocksPerRoundSet { - current_round: 1, - first_block: 0, - old: 5, - new: 6, - new_per_round_inflation_min: Perbill::from_parts(926), - new_per_round_inflation_ideal: Perbill::from_parts(926), - new_per_round_inflation_max: Perbill::from_parts(926), - }); - }); -} - -#[test] -fn set_blocks_per_round_storage_updates_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(ParachainStaking::round().length, 5); - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); - assert_eq!(ParachainStaking::round().length, 6); - }); -} - -#[test] -fn cannot_set_blocks_per_round_below_module_min() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 2u32), - Error::::CannotSetBelowMin - ); - }); -} - -#[test] -fn cannot_set_blocks_per_round_to_current_blocks_per_round() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 5u32), - Error::::NoWritingSameValue - ); - }); -} - -#[test] -fn round_immediately_jumps_if_current_duration_exceeds_new_blocks_per_round() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // we can't lower the blocks per round because it must be above the number of collators, - // and we can't lower the number of collators because it must be above - // MinSelectedCandidates. so we first raise blocks per round, then lower it. - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 10u32)); - - roll_to(10); - assert_events_emitted!(Event::NewRound { - starting_block: 10, - round: 2, - selected_collators_number: 1, - total_balance: 20 - },); - roll_to(17); - assert_ok!(ParachainStaking::set_blocks_per_round(RuntimeOrigin::root(), 6u32)); - roll_to(18); - assert_events_emitted!(Event::NewRound { - starting_block: 18, - round: 3, - selected_collators_number: 1, - total_balance: 20 - }); - }); -} - -// ~~ MONETARY GOVERNANCE ~~ - -#[test] -fn invalid_monetary_origin_fails() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_staking_expectations( - RuntimeOrigin::signed(45), - Range { min: 3u32.into(), ideal: 4u32.into(), max: 5u32.into() } - ), - sp_runtime::DispatchError::BadOrigin - ); - assert_noop!( - ParachainStaking::set_inflation( - RuntimeOrigin::signed(45), - Range { - min: Perbill::from_percent(3), - ideal: Perbill::from_percent(4), - max: Perbill::from_percent(5) - } - ), - sp_runtime::DispatchError::BadOrigin - ); - assert_noop!( - ParachainStaking::set_inflation( - RuntimeOrigin::signed(45), - Range { - min: Perbill::from_percent(3), - ideal: Perbill::from_percent(4), - max: Perbill::from_percent(5) - } - ), - sp_runtime::DispatchError::BadOrigin - ); - assert_noop!( - ParachainStaking::set_parachain_bond_account(RuntimeOrigin::signed(45), 11), - sp_runtime::DispatchError::BadOrigin - ); - assert_noop!( - ParachainStaking::set_parachain_bond_reserve_percent( - RuntimeOrigin::signed(45), - Percent::from_percent(2) - ), - sp_runtime::DispatchError::BadOrigin - ); - }); -} - -// SET STAKING EXPECTATIONS - -#[test] -fn set_staking_event_emits_event_correctly() { - ExtBuilder::default().build().execute_with(|| { - // valid call succeeds - assert_ok!(ParachainStaking::set_staking_expectations( - RuntimeOrigin::root(), - Range { min: 3u128, ideal: 4u128, max: 5u128 } - )); - assert_events_eq!(Event::StakeExpectationsSet { - expect_min: 3u128, - expect_ideal: 4u128, - expect_max: 5u128, - }); - }); -} - -#[test] -fn set_staking_updates_storage_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!( - ParachainStaking::inflation_config().expect, - Range { min: 700, ideal: 700, max: 700 } - ); - assert_ok!(ParachainStaking::set_staking_expectations( - RuntimeOrigin::root(), - Range { min: 3u128, ideal: 4u128, max: 5u128 } - )); - assert_eq!( - ParachainStaking::inflation_config().expect, - Range { min: 3u128, ideal: 4u128, max: 5u128 } - ); - }); -} - -#[test] -fn cannot_set_invalid_staking_expectations() { - ExtBuilder::default().build().execute_with(|| { - // invalid call fails - assert_noop!( - ParachainStaking::set_staking_expectations( - RuntimeOrigin::root(), - Range { min: 5u128, ideal: 4u128, max: 3u128 } - ), - Error::::InvalidSchedule - ); - }); -} - -#[test] -fn cannot_set_same_staking_expectations() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_staking_expectations( - RuntimeOrigin::root(), - Range { min: 3u128, ideal: 4u128, max: 5u128 } - )); - assert_noop!( - ParachainStaking::set_staking_expectations( - RuntimeOrigin::root(), - Range { min: 3u128, ideal: 4u128, max: 5u128 } - ), - Error::::NoWritingSameValue - ); - }); -} - -// SET INFLATION - -#[test] -fn set_inflation_event_emits_correctly() { - ExtBuilder::default().build().execute_with(|| { - let (min, ideal, max): (Perbill, Perbill, Perbill) = - (Perbill::from_percent(3), Perbill::from_percent(4), Perbill::from_percent(5)); - assert_ok!(ParachainStaking::set_inflation( - RuntimeOrigin::root(), - Range { min, ideal, max } - )); - assert_events_eq!(Event::InflationSet { - annual_min: min, - annual_ideal: ideal, - annual_max: max, - round_min: Perbill::from_parts(57), - round_ideal: Perbill::from_parts(75), - round_max: Perbill::from_parts(93), - }); - }); -} - -#[test] -fn set_inflation_storage_updates_correctly() { - ExtBuilder::default().build().execute_with(|| { - let (min, ideal, max): (Perbill, Perbill, Perbill) = - (Perbill::from_percent(3), Perbill::from_percent(4), Perbill::from_percent(5)); - assert_eq!( - ParachainStaking::inflation_config().annual, - Range { - min: Perbill::from_percent(50), - ideal: Perbill::from_percent(50), - max: Perbill::from_percent(50) - } - ); - assert_eq!( - ParachainStaking::inflation_config().round, - Range { - min: Perbill::from_percent(5), - ideal: Perbill::from_percent(5), - max: Perbill::from_percent(5) - } - ); - assert_ok!(ParachainStaking::set_inflation( - RuntimeOrigin::root(), - Range { min, ideal, max } - ),); - assert_eq!(ParachainStaking::inflation_config().annual, Range { min, ideal, max }); - assert_eq!( - ParachainStaking::inflation_config().round, - Range { - min: Perbill::from_parts(57), - ideal: Perbill::from_parts(75), - max: Perbill::from_parts(93) - } - ); - }); -} - -#[test] -fn cannot_set_invalid_inflation() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_inflation( - RuntimeOrigin::root(), - Range { - min: Perbill::from_percent(5), - ideal: Perbill::from_percent(4), - max: Perbill::from_percent(3) - } - ), - Error::::InvalidSchedule - ); - }); -} - -#[test] -fn cannot_set_same_inflation() { - ExtBuilder::default().build().execute_with(|| { - let (min, ideal, max): (Perbill, Perbill, Perbill) = - (Perbill::from_percent(3), Perbill::from_percent(4), Perbill::from_percent(5)); - assert_ok!(ParachainStaking::set_inflation( - RuntimeOrigin::root(), - Range { min, ideal, max } - ),); - assert_noop!( - ParachainStaking::set_inflation(RuntimeOrigin::root(), Range { min, ideal, max }), - Error::::NoWritingSameValue - ); - }); -} - -// SET PARACHAIN BOND ACCOUNT - -#[test] -fn set_parachain_bond_account_event_emits_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_parachain_bond_account(RuntimeOrigin::root(), 11)); - assert_events_eq!(Event::ParachainBondAccountSet { old: 0, new: 11 }); - }); -} - -#[test] -fn set_parachain_bond_account_storage_updates_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(ParachainStaking::parachain_bond_info().account, 0); - assert_ok!(ParachainStaking::set_parachain_bond_account(RuntimeOrigin::root(), 11)); - assert_eq!(ParachainStaking::parachain_bond_info().account, 11); - }); -} - -// SET PARACHAIN BOND RESERVE PERCENT - -#[test] -fn set_parachain_bond_reserve_percent_event_emits_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_ok!(ParachainStaking::set_parachain_bond_reserve_percent( - RuntimeOrigin::root(), - Percent::from_percent(50) - )); - assert_events_eq!(Event::ParachainBondReservePercentSet { - old: Percent::from_percent(30), - new: Percent::from_percent(50), - }); - }); -} - -#[test] -fn set_parachain_bond_reserve_percent_storage_updates_correctly() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(ParachainStaking::parachain_bond_info().percent, Percent::from_percent(30)); - assert_ok!(ParachainStaking::set_parachain_bond_reserve_percent( - RuntimeOrigin::root(), - Percent::from_percent(50) - )); - assert_eq!(ParachainStaking::parachain_bond_info().percent, Percent::from_percent(50)); - }); -} - -#[test] -fn cannot_set_same_parachain_bond_reserve_percent() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::set_parachain_bond_reserve_percent( - RuntimeOrigin::root(), - Percent::from_percent(30) - ), - Error::::NoWritingSameValue - ); - }); -} - -// ~~ PUBLIC ~~ - -// JOIN CANDIDATES - -#[test] -fn join_candidates_event_emits_correctly() { - ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); - assert_events_eq!(Event::JoinedCollatorCandidates { - account: 1, - amount_locked: 10u128, - new_total_amt_locked: 10u128, - }); - }); -} - -#[test] -fn join_candidates_reserves_balance() { - ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); - }); -} - -#[test] -fn join_candidates_increases_total_staked() { - ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { - assert_eq!(ParachainStaking::total(), 0); - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); - assert_eq!(ParachainStaking::total(), 10); - }); -} - -#[test] -fn join_candidates_creates_candidate_state() { - ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { - assert!(ParachainStaking::candidate_info(1).is_none()); - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); - let candidate_state = ParachainStaking::candidate_info(1).expect("just joined => exists"); - assert_eq!(candidate_state.bond, 10u128); - }); -} - -#[test] -fn join_candidates_adds_to_candidate_pool() { - ExtBuilder::default().with_balances(vec![(1, 10)]).build().execute_with(|| { - assert!(ParachainStaking::candidate_pool().0.is_empty()); - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 10u128, 0u32)); - let candidate_pool = ParachainStaking::candidate_pool(); - assert_eq!(candidate_pool.0[0].owner, 1); - assert_eq!(candidate_pool.0[0].amount, 10); - }); -} - -#[test] -fn cannot_join_candidates_if_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 1000)]) - .with_candidates(vec![(1, 500)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 11u128, 100u32), - Error::::CandidateExists - ); - }); -} - -#[test] -fn cannot_join_candidates_if_delegator() { - ExtBuilder::default() - .with_balances(vec![(1, 50), (2, 20)]) - .with_candidates(vec![(1, 50)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::join_candidates(RuntimeOrigin::signed(2), 10u128, 1u32), - Error::::DelegatorExists - ); - }); -} - -#[test] -fn cannot_join_candidates_without_min_bond() { - ExtBuilder::default().with_balances(vec![(1, 1000)]).build().execute_with(|| { - assert_noop!( - ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 9u128, 100u32), - Error::::CandidateBondBelowMin - ); - }); -} - -#[test] -fn cannot_join_candidates_with_more_than_available_balance() { - ExtBuilder::default().with_balances(vec![(1, 500)]).build().execute_with(|| { - assert_noop!( - ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 501u128, 100u32), - Error::::InsufficientBalance - ); - }); -} - -#[test] -fn insufficient_join_candidates_weight_hint_fails() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) - .build() - .execute_with(|| { - for i in 0..5 { - assert_noop!( - ParachainStaking::join_candidates(RuntimeOrigin::signed(6), 20, i), - Error::::TooLowCandidateCountWeightHintJoinCandidates - ); - } - }); -} - -#[test] -fn sufficient_join_candidates_weight_hint_succeeds() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 20), - (3, 20), - (4, 20), - (5, 20), - (6, 20), - (7, 20), - (8, 20), - (9, 20), - ]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) - .build() - .execute_with(|| { - let mut count = 5u32; - for i in 6..10 { - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(i), 20, count)); - count += 1u32; - } - }); -} - -// SCHEDULE LEAVE CANDIDATES - -#[test] -fn leave_candidates_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_events_eq!(Event::CandidateScheduledExit { - exit_allowed_round: 1, - candidate: 1, - scheduled_exit: 3 - }); - }); -} - -#[test] -fn leave_candidates_removes_candidate_from_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert!(ParachainStaking::candidate_pool().0.is_empty()); - }); -} - -#[test] -fn cannot_leave_candidates_if_not_candidate() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32), - Error::::CandidateDNE - ); - }); -} - -#[test] -fn cannot_leave_candidates_if_already_leaving_candidates() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_noop!( - ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32), - Error::::CandidateAlreadyLeaving - ); - }); -} - -#[test] -fn insufficient_leave_candidates_weight_hint_fails() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) - .build() - .execute_with(|| { - for i in 1..6 { - assert_noop!( - ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(i), 4u32), - Error::::TooLowCandidateCountToLeaveCandidates - ); - } - }); -} - -#[test] -fn sufficient_leave_candidates_weight_hint_succeeds() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20)]) - .build() - .execute_with(|| { - let mut count = 5u32; - for i in 1..6 { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(i), - count - )); - count -= 1u32; - } - }); -} - -// EXECUTE LEAVE CANDIDATES - -#[test] -fn execute_leave_candidates_emits_event() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert_events_emitted!(Event::CandidateLeft { - ex_candidate: 1, - unlocked_amount: 10, - new_total_amt_locked: 0 - }); - }); -} - -#[test] -fn execute_leave_candidates_callable_by_any_signed() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 1, 0)); - }); -} - -#[test] -fn execute_leave_candidates_requires_correct_weight_hint() { - ExtBuilder::default() - .with_balances(vec![(1, 10), (2, 10), (3, 10), (4, 10)]) - .with_candidates(vec![(1, 10)]) - .with_delegations(vec![(2, 1, 10), (3, 1, 10), (4, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - roll_to(10); - for i in 0..3 { - assert_noop!( - ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, i), - Error::::TooLowCandidateDelegationCountToLeaveCandidates - ); - } - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 1, 3)); - }); -} - -#[test] -fn execute_leave_candidates_unreserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); - }); -} - -#[test] -fn execute_leave_candidates_decreases_total_staked() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 10); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert_eq!(ParachainStaking::total(), 0); - }); -} - -#[test] -fn execute_leave_candidates_removes_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - // candidate state is not immediately removed - let candidate_state = - ParachainStaking::candidate_info(1).expect("just left => still exists"); - assert_eq!(candidate_state.bond, 10u128); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert!(ParachainStaking::candidate_info(1).is_none()); - }); -} - -#[test] -fn execute_leave_candidates_removes_pending_delegation_requests() { - ExtBuilder::default() - .with_balances(vec![(1, 10), (2, 15)]) - .with_candidates(vec![(1, 10)]) - .with_delegations(vec![(2, 1, 15)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - let state = ParachainStaking::delegation_scheduled_requests(&1); - assert_eq!( - state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], - ); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - // candidate state is not immediately removed - let candidate_state = - ParachainStaking::candidate_info(1).expect("just left => still exists"); - assert_eq!(candidate_state.bond, 10u128); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 1)); - assert!(ParachainStaking::candidate_info(1).is_none()); - assert!( - !ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation request not removed" - ); - assert!( - !>::contains_key(&1), - "the key was not removed from storage" - ); - }); -} - -#[test] -fn cannot_execute_leave_candidates_before_delay() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_noop!( - ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), - Error::::CandidateCannotLeaveYet - ); - roll_to(9); - assert_noop!( - ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0), - Error::::CandidateCannotLeaveYet - ); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(3), 1, 0)); - }); -} - -// CANCEL LEAVE CANDIDATES - -#[test] -fn cancel_leave_candidates_emits_event() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_events_emitted!(Event::CancelledCandidateExit { candidate: 1 }); - }); -} - -#[test] -fn cancel_leave_candidates_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); - let candidate = - ParachainStaking::candidate_info(&1).expect("just cancelled leave so exists"); - assert!(candidate.is_active()); - }); -} - -#[test] -fn cancel_leave_candidates_adds_to_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 10)]) - .with_candidates(vec![(1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1u32)); - assert_ok!(ParachainStaking::cancel_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 10); - }); -} - -// GO OFFLINE - -#[test] -fn go_offline_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert_events_eq!(Event::CandidateWentOffline { candidate: 1 }); - }); -} - -#[test] -fn go_offline_removes_candidate_from_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0.len(), 1); - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert!(ParachainStaking::candidate_pool().0.is_empty()); - }); -} - -#[test] -fn go_offline_updates_candidate_state_to_idle() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - let candidate_state = ParachainStaking::candidate_info(1).expect("is active candidate"); - assert_eq!(candidate_state.status, CollatorStatus::Active); - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - let candidate_state = - ParachainStaking::candidate_info(1).expect("is candidate, just offline"); - assert_eq!(candidate_state.status, CollatorStatus::Idle); - }); -} - -#[test] -fn cannot_go_offline_if_not_candidate() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::go_offline(RuntimeOrigin::signed(3)), - Error::::CandidateDNE - ); - }); -} - -#[test] -fn cannot_go_offline_if_already_offline() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert_noop!( - ParachainStaking::go_offline(RuntimeOrigin::signed(1)), - Error::::AlreadyOffline - ); - }); -} - -// GO ONLINE - -#[test] -fn go_online_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - roll_blocks(1); - assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); - assert_events_eq!(Event::CandidateBackOnline { candidate: 1 }); - }); -} - -#[test] -fn go_online_adds_to_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - assert!(ParachainStaking::candidate_pool().0.is_empty()); - assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); - }); -} - -#[test] -fn go_online_storage_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::go_offline(RuntimeOrigin::signed(1))); - let candidate_state = - ParachainStaking::candidate_info(1).expect("offline still exists"); - assert_eq!(candidate_state.status, CollatorStatus::Idle); - assert_ok!(ParachainStaking::go_online(RuntimeOrigin::signed(1))); - let candidate_state = ParachainStaking::candidate_info(1).expect("online so exists"); - assert_eq!(candidate_state.status, CollatorStatus::Active); - }); -} - -#[test] -fn cannot_go_online_if_not_candidate() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::go_online(RuntimeOrigin::signed(3)), - Error::::CandidateDNE - ); - }); -} - -#[test] -fn cannot_go_online_if_already_online() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::go_online(RuntimeOrigin::signed(1)), - Error::::AlreadyActive - ); - }); -} - -#[test] -fn cannot_go_online_if_leaving() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_noop!( - ParachainStaking::go_online(RuntimeOrigin::signed(1)), - Error::::CannotGoOnlineIfLeaving - ); - }); -} - -// CANDIDATE BOND MORE - -#[test] -fn candidate_bond_more_emits_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - assert_events_eq!(Event::CandidateBondedMore { - candidate: 1, - amount: 30, - new_total_bond: 50 - }); - }); -} - -#[test] -fn candidate_bond_more_reserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 30); - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); - }); -} - -#[test] -fn candidate_bond_more_increases_total() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - let mut total = ParachainStaking::total(); - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - total += 30; - assert_eq!(ParachainStaking::total(), total); - }); -} - -#[test] -fn candidate_bond_more_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 20); - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 50); - }); -} - -#[test] -fn candidate_bond_more_updates_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); - assert_ok!(ParachainStaking::candidate_bond_more(RuntimeOrigin::signed(1), 30)); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 50); - }); -} - -// SCHEDULE CANDIDATE BOND LESS - -#[test] -fn schedule_candidate_bond_less_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - assert_events_eq!(Event::CandidateBondLessRequested { - candidate: 1, - amount_to_decrease: 10, - execute_round: 3, - }); - }); -} - -#[test] -fn cannot_schedule_candidate_bond_less_if_request_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 5)); - assert_noop!( - ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 5), - Error::::PendingCandidateRequestAlreadyExists - ); - }); -} - -#[test] -fn cannot_schedule_candidate_bond_less_if_not_candidate() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(6), 50), - Error::::CandidateDNE - ); - }); -} - -#[test] -fn cannot_schedule_candidate_bond_less_if_new_total_below_min_candidate_stk() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 21), - Error::::CandidateBondBelowMin - ); - }); -} - -#[test] -fn can_schedule_candidate_bond_less_if_leaving_candidates() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - }); -} - -#[test] -fn cannot_schedule_candidate_bond_less_if_exited_candidates() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 0)); - assert_noop!( - ParachainStaking::schedule_candidate_bond_less(RuntimeOrigin::signed(1), 10), - Error::::CandidateDNE - ); - }); -} - -// 2. EXECUTE BOND LESS REQUEST - -#[test] -fn execute_candidate_bond_less_emits_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 50)]) - .with_candidates(vec![(1, 50)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 30 - )); - roll_to(10); - roll_blocks(1); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - assert_events_eq!(Event::CandidateBondedLess { - candidate: 1, - amount: 30, - new_bond: 20 - }); - }); -} - -#[test] -fn execute_candidate_bond_less_unreserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 0); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - assert_eq!(ParachainStaking::get_collator_stakable_free_balance(&1), 10); - }); -} - -#[test] -fn execute_candidate_bond_less_decreases_total() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - let mut total = ParachainStaking::total(); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - total -= 10; - assert_eq!(ParachainStaking::total(), total); - }); -} - -#[test] -fn execute_candidate_bond_less_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 30); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - let candidate_state = ParachainStaking::candidate_info(1).expect("updated => exists"); - assert_eq!(candidate_state.bond, 20); - }); -} - -#[test] -fn execute_candidate_bond_less_updates_candidate_pool() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 30); - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_candidate_bond_less(RuntimeOrigin::signed(1), 1)); - assert_eq!(ParachainStaking::candidate_pool().0[0].owner, 1); - assert_eq!(ParachainStaking::candidate_pool().0[0].amount, 20); - }); -} - -// CANCEL CANDIDATE BOND LESS REQUEST - -#[test] -fn cancel_candidate_bond_less_emits_event() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - assert_ok!(ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(1))); - assert_events_emitted!(Event::CancelledCandidateBondLess { - candidate: 1, - amount: 10, - execute_round: 3, - }); - }); -} - -#[test] -fn cancel_candidate_bond_less_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - assert_ok!(ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(1))); - assert!(ParachainStaking::candidate_info(&1).unwrap().request.is_none()); - }); -} - -#[test] -fn only_candidate_can_cancel_candidate_bond_less_request() { - ExtBuilder::default() - .with_balances(vec![(1, 30)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_candidate_bond_less( - RuntimeOrigin::signed(1), - 10 - )); - assert_noop!( - ParachainStaking::cancel_candidate_bond_less(RuntimeOrigin::signed(2)), - Error::::CandidateDNE - ); - }); -} - -// DELEGATE - -#[test] -fn delegate_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); - assert_events_eq!(Event::Delegation { - delegator: 2, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, - auto_compound: Percent::zero(), - }); - }); -} - -#[test] -fn delegate_reserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - }); -} - -#[test] -fn delegate_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert!(ParachainStaking::delegator_state(2).is_none()); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); - let delegator_state = - ParachainStaking::delegator_state(2).expect("just delegated => exists"); - assert_eq!(delegator_state.total(), 10); - assert_eq!(delegator_state.delegations.0[0].owner, 1); - assert_eq!(delegator_state.delegations.0[0].amount, 10); - }); -} - -#[test] -fn delegate_updates_collator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - let candidate_state = - ParachainStaking::candidate_info(1).expect("registered in genesis"); - assert_eq!(candidate_state.total_counted, 30); - let top_delegations = - ParachainStaking::top_delegations(1).expect("registered in genesis"); - assert!(top_delegations.delegations.is_empty()); - assert!(top_delegations.total.is_zero()); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0)); - let candidate_state = - ParachainStaking::candidate_info(1).expect("just delegated => exists"); - assert_eq!(candidate_state.total_counted, 40); - let top_delegations = - ParachainStaking::top_delegations(1).expect("just delegated => exists"); - assert_eq!(top_delegations.delegations[0].owner, 2); - assert_eq!(top_delegations.delegations[0].amount, 10); - assert_eq!(top_delegations.total, 10); - }); -} - -#[test] -fn can_delegate_immediately_after_other_join_candidates() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 20, 0)); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 20, 0, 0)); - }); -} - -#[test] -fn can_delegate_if_revoking() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 30), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 4, 10, 0, 2)); - }); -} - -#[test] -fn cannot_delegate_if_full_and_new_delegation_less_than_or_equal_lowest_bottom() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 10), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - (10, 10), - (11, 10), - ]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (2, 1, 10), - (3, 1, 10), - (4, 1, 10), - (5, 1, 10), - (6, 1, 10), - (8, 1, 10), - (9, 1, 10), - (10, 1, 10), - ]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate(RuntimeOrigin::signed(11), 1, 10, 8, 0), - Error::::CannotDelegateLessThanOrEqualToLowestBottomWhenFull - ); - }); -} - -#[test] -fn can_delegate_if_full_and_new_delegation_greater_than_lowest_bottom() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 10), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - (10, 10), - (11, 11), - ]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (2, 1, 10), - (3, 1, 10), - (4, 1, 10), - (5, 1, 10), - (6, 1, 10), - (8, 1, 10), - (9, 1, 10), - (10, 1, 10), - ]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(11), 1, 11, 8, 0)); - assert_events_emitted!(Event::DelegationKicked { - delegator: 10, - candidate: 1, - unstaked_amount: 10 - }); - assert_events_emitted!(Event::DelegatorLeft { delegator: 10, unstaked_amount: 10 }); - }); -} - -#[test] -fn can_still_delegate_if_leaving() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 20), (3, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 3, 10, 0, 1),); - }); -} - -#[test] -fn cannot_delegate_if_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 30)]) - .with_candidates(vec![(1, 20), (2, 20)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 0, 0), - Error::::CandidateExists - ); - }); -} - -#[test] -fn cannot_delegate_if_already_delegated() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 30)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 20)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 1, 1), - Error::::AlreadyDelegatedCandidate - ); - }); -} - -#[test] -fn cannot_delegate_more_than_max_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 50), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10), (2, 4, 10), (2, 5, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate(RuntimeOrigin::signed(2), 6, 10, 0, 4), - Error::::ExceedMaxDelegationsPerDelegator, - ); - }); -} - -#[test] -fn sufficient_delegate_weight_hint_succeeds() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 20), - (3, 20), - (4, 20), - (5, 20), - (6, 20), - (7, 20), - (8, 20), - (9, 20), - (10, 20), - ]) - .with_candidates(vec![(1, 20), (2, 20)]) - .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) - .build() - .execute_with(|| { - let mut count = 4u32; - for i in 7..11 { - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(i), - 1, - 10, - count, - 0u32 - )); - count += 1u32; - } - let mut count = 0u32; - for i in 3..11 { - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(i), - 2, - 10, - count, - 1u32 - )); - count += 1u32; - } - }); -} - -#[test] -fn insufficient_delegate_weight_hint_fails() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 20), - (3, 20), - (4, 20), - (5, 20), - (6, 20), - (7, 20), - (8, 20), - (9, 20), - (10, 20), - ]) - .with_candidates(vec![(1, 20), (2, 20)]) - .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) - .build() - .execute_with(|| { - let mut count = 3u32; - for i in 7..11 { - assert_noop!( - ParachainStaking::delegate(RuntimeOrigin::signed(i), 1, 10, count, 0u32), - Error::::TooLowCandidateDelegationCountToDelegate - ); - } - // to set up for next error test - count = 4u32; - for i in 7..11 { - assert_ok!(ParachainStaking::delegate( - RuntimeOrigin::signed(i), - 1, - 10, - count, - 0u32 - )); - count += 1u32; - } - count = 0u32; - for i in 3..11 { - assert_noop!( - ParachainStaking::delegate(RuntimeOrigin::signed(i), 2, 10, count, 0u32), - Error::::TooLowDelegationCountToDelegate - ); - count += 1u32; - } - }); -} - -// SCHEDULE LEAVE DELEGATORS - -#[test] -fn schedule_leave_delegators_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 1, - delegator: 2, - scheduled_exit: 3 - }); - }); -} - -#[test] -fn cannot_schedule_leave_delegators_if_already_leaving() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_noop!( - ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2)), - Error::::DelegatorAlreadyLeaving - ); - }); -} - -#[test] -fn cannot_schedule_leave_delegators_if_not_delegator() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2)), - Error::::DelegatorDNE - ); - }); -} - -// EXECUTE LEAVE DELEGATORS - -#[test] -fn execute_leave_delegators_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); - assert_events_emitted!(Event::DelegatorLeft { delegator: 2, unstaked_amount: 10 }); - }); -} - -#[test] -fn execute_leave_delegators_unreserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 00); - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); - assert_eq!(crate::mock::query_lock_amount(2, DELEGATOR_LOCK_ID), None); - }); -} - -#[test] -fn execute_leave_delegators_decreases_total_staked() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); - assert_eq!(ParachainStaking::total(), 30); - }); -} - -#[test] -fn execute_leave_delegators_removes_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert!(ParachainStaking::delegator_state(2).is_some()); - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); - assert!(ParachainStaking::delegator_state(2).is_none()); - }); -} - -#[test] -fn execute_leave_delegators_removes_pending_delegation_requests() { - ExtBuilder::default() - .with_balances(vec![(1, 10), (2, 15)]) - .with_candidates(vec![(1, 10)]) - .with_delegations(vec![(2, 1, 15)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - let state = ParachainStaking::delegation_scheduled_requests(&1); - assert_eq!( - state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], - ); - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); - assert!(ParachainStaking::delegator_state(2).is_none()); - assert!( - !ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation request not removed" - ) - }); -} - -#[test] -fn execute_leave_delegators_removes_delegations_from_collator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 20), (3, 20), (4, 20), (5, 20)]) - .with_candidates(vec![(2, 20), (3, 20), (4, 20), (5, 20)]) - .with_delegations(vec![(1, 2, 10), (1, 3, 10), (1, 4, 10), (1, 5, 10)]) - .build() - .execute_with(|| { - for i in 2..6 { - let candidate_state = - ParachainStaking::candidate_info(i).expect("initialized in ext builder"); - assert_eq!(candidate_state.total_counted, 30); - let top_delegations = - ParachainStaking::top_delegations(i).expect("initialized in ext builder"); - assert_eq!(top_delegations.delegations[0].owner, 1); - assert_eq!(top_delegations.delegations[0].amount, 10); - assert_eq!(top_delegations.total, 10); - } - assert_eq!(ParachainStaking::delegator_state(1).unwrap().delegations.0.len(), 4usize); - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(1))); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(1), 1, 10)); - for i in 2..6 { - let candidate_state = - ParachainStaking::candidate_info(i).expect("initialized in ext builder"); - assert_eq!(candidate_state.total_counted, 20); - let top_delegations = - ParachainStaking::top_delegations(i).expect("initialized in ext builder"); - assert!(top_delegations.delegations.is_empty()); - } - }); -} - -#[test] -fn cannot_execute_leave_delegators_before_delay() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_noop!( - ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1), - Error::::DelegatorCannotLeaveYet - ); - // can execute after delay - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); - }); -} - -#[test] -fn cannot_execute_leave_delegators_if_single_delegation_revoke_manually_cancelled() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 3)); - roll_to(10); - assert_noop!( - ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2), - Error::::DelegatorNotLeaving - ); - // can execute after manually scheduling revoke, and the round delay after which - // all revokes can be executed - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3)); - roll_to(20); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2)); - }); -} - -#[test] -fn insufficient_execute_leave_delegators_weight_hint_fails() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) - .build() - .execute_with(|| { - for i in 3..7 { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(i))); - } - roll_to(10); - for i in 3..7 { - assert_noop!( - ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(i), i, 0), - Error::::TooLowDelegationCountToLeaveDelegators - ); - } - }); -} - -#[test] -fn sufficient_execute_leave_delegators_weight_hint_succeeds() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(3, 1, 10), (4, 1, 10), (5, 1, 10), (6, 1, 10)]) - .build() - .execute_with(|| { - for i in 3..7 { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(i))); - } - roll_to(10); - for i in 3..7 { - assert_ok!(ParachainStaking::execute_leave_delegators( - RuntimeOrigin::signed(i), - i, - 1 - )); - } - }); -} - -// CANCEL LEAVE DELEGATORS - -#[test] -fn cancel_leave_delegators_emits_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); - assert_events_emitted!(Event::DelegatorExitCancelled { delegator: 2 }); - }); -} - -#[test] -fn cancel_leave_delegators_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); - let delegator = - ParachainStaking::delegator_state(&2).expect("just cancelled exit so exists"); - assert!(delegator.is_active()); - }); -} - -#[test] -fn cannot_cancel_leave_delegators_if_single_delegation_revoke_manually_cancelled() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 3)); - roll_to(10); - assert_noop!( - ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2)), - Error::::DelegatorNotLeaving - ); - // can execute after manually scheduling revoke, without waiting for round delay after - // which all revokes can be executed - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3)); - assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); - }); -} - -// SCHEDULE REVOKE DELEGATION - -#[test] -fn revoke_delegation_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_events_eq!(Event::DelegationRevocationScheduled { - round: 1, - delegator: 2, - candidate: 1, - scheduled_exit: 3, - }); - roll_to_round_begin(3); - roll_blocks(1); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_events_eq!( - Event::DelegatorLeftCandidate { - delegator: 2, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 30 - }, - Event::DelegationRevoked { delegator: 2, candidate: 1, unstaked_amount: 10 }, - ); - }); -} - -#[test] -fn can_revoke_delegation_if_revoking_another_delegation() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - // this is an exit implicitly because last delegation revoked - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3)); - }); -} - -#[test] -fn delegator_not_allowed_revoke_if_already_leaving() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_noop!( - ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3), - >::PendingDelegationRequestAlreadyExists, - ); - }); -} - -#[test] -fn cannot_revoke_delegation_if_not_delegator() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1), - Error::::DelegatorDNE - ); - }); -} - -#[test] -fn cannot_revoke_delegation_that_dne() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3), - Error::::DelegationDNE - ); - }); -} - -#[test] -// See `cannot_execute_revoke_delegation_below_min_delegator_stake` for where the "must be above -// MinDelegatorStk" rule is now enforced. -fn can_schedule_revoke_delegation_below_min_delegator_stake() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 8), (3, 20)]) - .with_candidates(vec![(1, 20), (3, 20)]) - .with_delegations(vec![(2, 1, 5), (2, 3, 3)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - }); -} - -// DELEGATOR BOND MORE - -#[test] -fn delegator_bond_more_reserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 5); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - }); -} - -#[test] -fn delegator_bond_more_increases_total_staked() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); - assert_eq!(ParachainStaking::total(), 45); - }); -} - -#[test] -fn delegator_bond_more_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 10); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); - assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 15); - }); -} - -#[test] -fn delegator_bond_more_updates_candidate_state_top_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); - assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 10); - assert_eq!(ParachainStaking::top_delegations(1).unwrap().total, 10); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); - assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); - assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 15); - assert_eq!(ParachainStaking::top_delegations(1).unwrap().total, 15); - }); -} - -#[test] -fn delegator_bond_more_updates_candidate_state_bottom_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10), (3, 1, 20), (4, 1, 20), (5, 1, 20), (6, 1, 20)]) - .build() - .execute_with(|| { - assert_eq!( - ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].owner, - 2 - ); - assert_eq!( - ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].amount, - 10 - ); - assert_eq!(ParachainStaking::bottom_delegations(1).unwrap().total, 10); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); - assert_events_eq!(Event::DelegationIncreased { - delegator: 2, - candidate: 1, - amount: 5, - in_top: false - }); - assert_eq!( - ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].owner, - 2 - ); - assert_eq!( - ParachainStaking::bottom_delegations(1).expect("exists").delegations[0].amount, - 15 - ); - assert_eq!(ParachainStaking::bottom_delegations(1).unwrap().total, 15); - }); -} - -#[test] -fn delegator_bond_more_increases_total() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); - assert_eq!(ParachainStaking::total(), 45); - }); -} - -#[test] -fn can_delegator_bond_more_for_leaving_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); - }); -} - -#[test] -fn delegator_bond_more_disallowed_when_revoke_scheduled() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_noop!( - ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5), - >::PendingDelegationRevoke - ); - }); -} - -#[test] -fn delegator_bond_more_allowed_when_bond_decrease_scheduled() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 15)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5, - )); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 1, 5)); - }); -} - -// DELEGATOR BOND LESS - -#[test] -fn delegator_bond_less_event_emits_correctly() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - assert_events_eq!(Event::DelegationDecreaseScheduled { - delegator: 2, - candidate: 1, - amount_to_decrease: 5, - execute_round: 3, - }); - }); -} - -#[test] -fn delegator_bond_less_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - let state = ParachainStaking::delegation_scheduled_requests(&1); - assert_eq!( - state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], - ); - }); -} - -#[test] -fn delegator_not_allowed_bond_less_if_leaving() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 1), - >::PendingDelegationRequestAlreadyExists, - ); - }); -} - -#[test] -fn cannot_delegator_bond_less_if_revoking() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 1), - Error::::PendingDelegationRequestAlreadyExists - ); - }); -} - -#[test] -fn cannot_delegator_bond_less_if_not_delegator() { - ExtBuilder::default().build().execute_with(|| { - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 5), - Error::::DelegatorDNE - ); - }); -} - -#[test] -fn cannot_delegator_bond_less_if_candidate_dne() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 3, 5), - Error::::DelegationDNE - ); - }); -} - -#[test] -fn cannot_delegator_bond_less_if_delegation_dne() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 3, 5), - Error::::DelegationDNE - ); - }); -} - -#[test] -fn cannot_delegator_bond_less_below_min_collator_stk() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 6), - Error::::DelegatorBondBelowMin - ); - }); -} - -#[test] -fn cannot_delegator_bond_less_more_than_total_delegation() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 11), - Error::::DelegatorBondBelowMin - ); - }); -} - -#[test] -fn cannot_delegator_bond_less_below_min_delegation() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 8), - Error::::DelegationBelowMin - ); - }); -} - -// EXECUTE PENDING DELEGATION REQUEST - -// 1. REVOKE DELEGATION - -#[test] -fn execute_revoke_delegation_emits_exit_event_if_exit_happens() { - // last delegation is revocation - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_events_emitted!(Event::DelegatorLeftCandidate { - delegator: 2, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 30 - }); - assert_events_emitted!(Event::DelegatorLeft { delegator: 2, unstaked_amount: 10 }); - }); -} - -#[test] -fn cannot_execute_revoke_delegation_below_min_delegator_stake() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 8), (3, 20)]) - .with_candidates(vec![(1, 20), (3, 20)]) - .with_delegations(vec![(2, 1, 5), (2, 3, 3)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_noop!( - ParachainStaking::execute_delegation_request(RuntimeOrigin::signed(2), 2, 1), - Error::::DelegatorBondBelowMin - ); - // but delegator can cancel the request and request to leave instead: - assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - roll_to(20); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2)); - }); -} - -#[test] -fn revoke_delegation_executes_exit_if_last_delegation() { - // last delegation is revocation - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_events_emitted!(Event::DelegatorLeftCandidate { - delegator: 2, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 30 - }); - assert_events_emitted!(Event::DelegatorLeft { delegator: 2, unstaked_amount: 10 }); - }); -} - -#[test] -fn execute_revoke_delegation_emits_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_events_emitted!(Event::DelegatorLeftCandidate { - delegator: 2, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 30 - }); - }); -} - -#[test] -fn execute_revoke_delegation_unreserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); - }); -} - -#[test] -fn execute_revoke_delegation_adds_revocation_to_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert!(!ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2)); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert!(ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2)); - }); -} - -#[test] -fn execute_revoke_delegation_removes_revocation_from_delegator_state_upon_execution() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!(!ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2)); - }); -} - -#[test] -fn execute_revoke_delegation_removes_revocation_from_state_for_single_delegation_leave() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!( - !ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation was not removed" - ); - }); -} - -#[test] -fn execute_revoke_delegation_decreases_total_staked() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!(ParachainStaking::total(), 30); - }); -} - -#[test] -fn execute_revoke_delegation_for_last_delegation_removes_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert!(ParachainStaking::delegator_state(2).is_some()); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - // this will be confusing for people - // if status is leaving, then execute_delegation_request works if last delegation - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!(ParachainStaking::delegator_state(2).is_none()); - }); -} - -#[test] -fn execute_revoke_delegation_removes_delegation_from_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::candidate_info(1).expect("exists").delegation_count, 1u32); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!(ParachainStaking::candidate_info(1) - .expect("exists") - .delegation_count - .is_zero()); - }); -} - -#[test] -fn can_execute_revoke_delegation_for_leaving_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - // can execute delegation request for leaving candidate - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - }); -} - -#[test] -fn can_execute_leave_candidates_if_revoking_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - // revocation executes during execute leave candidates (callable by anyone) - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 1)); - assert!(!ParachainStaking::is_delegator(&2)); - assert_eq!(Balances::reserved_balance(&2), 0); - assert_eq!(Balances::free_balance(&2), 10); - }); -} - -#[test] -fn delegator_bond_more_after_revoke_delegation_does_not_effect_exit() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 30), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(2), 3, 10)); - roll_to(100); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!(ParachainStaking::is_delegator(&2)); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); - }); -} - -#[test] -fn delegator_bond_less_after_revoke_delegation_does_not_effect_exit() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 30), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_events_eq!(Event::DelegationRevocationScheduled { - round: 1, - delegator: 2, - candidate: 1, - scheduled_exit: 3, - }); - assert_noop!( - ParachainStaking::schedule_delegator_bond_less(RuntimeOrigin::signed(2), 1, 2), - Error::::PendingDelegationRequestAlreadyExists - ); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 3, - 2 - )); - roll_to(10); - roll_blocks(1); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 3 - )); - assert_events_eq!( - Event::DelegatorLeftCandidate { - delegator: 2, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 30, - }, - Event::DelegationRevoked { delegator: 2, candidate: 1, unstaked_amount: 10 }, - Event::DelegationDecreased { delegator: 2, candidate: 3, amount: 2, in_top: true }, - ); - assert!(ParachainStaking::is_delegator(&2)); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 22); - }); -} - -// 2. EXECUTE BOND LESS - -#[test] -fn execute_delegator_bond_less_unreserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 5); - }); -} - -#[test] -fn execute_delegator_bond_less_decreases_total_staked() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!(ParachainStaking::total(), 35); - }); -} - -#[test] -fn execute_delegator_bond_less_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 10); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!(ParachainStaking::delegator_state(2).expect("exists").total(), 5); - }); -} - -#[test] -fn execute_delegator_bond_less_updates_candidate_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); - assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 10); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].owner, 2); - assert_eq!(ParachainStaking::top_delegations(1).unwrap().delegations[0].amount, 5); - }); -} - -#[test] -fn execute_delegator_bond_less_decreases_total() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::total(), 40); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!(ParachainStaking::total(), 35); - }); -} - -#[test] -fn execute_delegator_bond_less_updates_just_bottom_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 10), (3, 11), (4, 12), (5, 14), (6, 15)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 10), (3, 1, 11), (4, 1, 12), (5, 1, 14), (6, 1, 15)]) - .build() - .execute_with(|| { - let pre_call_candidate_info = - ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let pre_call_top_delegations = - ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); - let pre_call_bottom_delegations = - ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 2 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - let post_call_candidate_info = - ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let post_call_top_delegations = - ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); - let post_call_bottom_delegations = - ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); - let mut not_equal = false; - for Bond { owner, amount } in pre_call_bottom_delegations.delegations { - for Bond { owner: post_owner, amount: post_amount } in - &post_call_bottom_delegations.delegations - { - if &owner == post_owner { - if &amount != post_amount { - not_equal = true; - break - } - } - } - } - assert!(not_equal); - let mut equal = true; - for Bond { owner, amount } in pre_call_top_delegations.delegations { - for Bond { owner: post_owner, amount: post_amount } in - &post_call_top_delegations.delegations - { - if &owner == post_owner { - if &amount != post_amount { - equal = false; - break - } - } - } - } - assert!(equal); - assert_eq!( - pre_call_candidate_info.total_counted, - post_call_candidate_info.total_counted - ); - }); -} - -#[test] -fn execute_delegator_bond_less_does_not_delete_bottom_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 10), (3, 11), (4, 12), (5, 14), (6, 15)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 10), (3, 1, 11), (4, 1, 12), (5, 1, 14), (6, 1, 15)]) - .build() - .execute_with(|| { - let pre_call_candidate_info = - ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let pre_call_top_delegations = - ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); - let pre_call_bottom_delegations = - ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(6), - 1, - 4 - )); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(6), - 6, - 1 - )); - let post_call_candidate_info = - ParachainStaking::candidate_info(&1).expect("delegated by all so exists"); - let post_call_top_delegations = - ParachainStaking::top_delegations(&1).expect("delegated by all so exists"); - let post_call_bottom_delegations = - ParachainStaking::bottom_delegations(&1).expect("delegated by all so exists"); - let mut equal = true; - for Bond { owner, amount } in pre_call_bottom_delegations.delegations { - for Bond { owner: post_owner, amount: post_amount } in - &post_call_bottom_delegations.delegations - { - if &owner == post_owner { - if &amount != post_amount { - equal = false; - break - } - } - } - } - assert!(equal); - let mut not_equal = false; - for Bond { owner, amount } in pre_call_top_delegations.delegations { - for Bond { owner: post_owner, amount: post_amount } in - &post_call_top_delegations.delegations - { - if &owner == post_owner { - if &amount != post_amount { - not_equal = true; - break - } - } - } - } - assert!(not_equal); - assert_eq!( - pre_call_candidate_info.total_counted - 4, - post_call_candidate_info.total_counted - ); - }); -} - -#[test] -fn can_execute_delegator_bond_less_for_leaving_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 15)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 1)); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - roll_to(10); - // can execute bond more delegation request for leaving candidate - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - }); -} - -// CANCEL PENDING DELEGATION REQUEST -// 1. CANCEL REVOKE DELEGATION - -#[test] -fn cancel_revoke_delegation_emits_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); - assert_events_emitted!(Event::CancelledDelegationRequest { - delegator: 2, - collator: 1, - cancelled_request: CancelledScheduledRequest { - when_executable: 3, - action: DelegationAction::Revoke(10), - }, - }); - }); -} - -#[test] -fn cancel_revoke_delegation_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - let state = ParachainStaking::delegation_scheduled_requests(&1); - assert_eq!( - state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Revoke(10), - }], - ); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 10 - ); - assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); - assert!(!ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2)); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 0 - ); - }); -} - -// 2. CANCEL DELEGATOR BOND LESS - -#[test] -fn cancel_delegator_bond_less_correct_event() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 15)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); - assert_events_emitted!(Event::CancelledDelegationRequest { - delegator: 2, - collator: 1, - cancelled_request: CancelledScheduledRequest { - when_executable: 3, - action: DelegationAction::Decrease(5), - }, - }); - }); -} - -#[test] -fn cancel_delegator_bond_less_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 15)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 15)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 5 - )); - let state = ParachainStaking::delegation_scheduled_requests(&1); - assert_eq!( - state, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], - ); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 5 - ); - assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); - assert!(!ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2)); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 0 - ); - }); -} - -// ~~ PROPERTY-BASED TESTS ~~ - -#[test] -fn delegator_schedule_revocation_total() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20), (5, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20), (5, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10), (2, 4, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 10 - ); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 0 - ); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 5, 10, 0, 2)); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 3)); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 4)); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 20, - ); - roll_to(20); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 3 - )); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 10, - ); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 4 - )); - assert_eq!( - ParachainStaking::delegator_state(&2) - .map(|x| x.less_total) - .expect("delegator state must exist"), - 0 - ); - }); -} - -#[ignore] -#[test] -fn parachain_bond_inflation_reserve_matches_config() { - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - (11, 1), - ]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) - .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) - .build() - .execute_with(|| { - assert_eq!(Balances::free_balance(&11), 1); - // set parachain bond account so DefaultParachainBondReservePercent = 30% of inflation - // is allocated to this account hereafter - assert_ok!(ParachainStaking::set_parachain_bond_account(RuntimeOrigin::root(), 11)); - assert_events_eq!(Event::ParachainBondAccountSet { old: 0, new: 11 }); - roll_to_round_begin(2); - // chooses top TotalSelectedCandidates (5), in order - assert_events_eq!( - Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 2, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 5, - total_balance: 140, - }, - ); - assert_eq!(Balances::free_balance(&11), 1); - // ~ set block author as 1 for all blocks this round - set_author(2, 1, 100); - roll_to_round_begin(4); - // distribute total issuance to collator 1 and its delegators 6, 7, 19 - assert_eq!(Balances::free_balance(&11), 16); - // ~ set block author as 1 for all blocks this round - set_author(3, 1, 100); - set_author(4, 1, 100); - set_author(5, 1, 100); - // 1. ensure delegators are paid for 2 rounds after they leave - assert_noop!( - ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(66)), - Error::::DelegatorDNE - ); - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(6))); - assert_events_eq!( - Event::ReservedForParachainBond { account: 11, value: 15 }, - Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 4, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 4, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 4, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 5, - total_balance: 140, - }, - Event::DelegatorExitScheduled { round: 4, delegator: 6, scheduled_exit: 6 }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 20 }, - Event::Rewarded { account: 6, rewards: 5 }, - Event::Rewarded { account: 7, rewards: 5 }, - Event::Rewarded { account: 10, rewards: 5 }, - ); - // fast forward to block in which delegator 6 exit executes - roll_to_round_begin(5); - assert_events_eq!( - Event::ReservedForParachainBond { account: 11, value: 16 }, - Event::CollatorChosen { round: 5, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 5, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 5, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 5, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 5, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 20, - round: 5, - selected_collators_number: 5, - total_balance: 140, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 21 }, - Event::Rewarded { account: 6, rewards: 5 }, - Event::Rewarded { account: 7, rewards: 5 }, - Event::Rewarded { account: 10, rewards: 5 }, - ); - roll_to_round_begin(6); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(6), 6, 10)); - assert_events_eq!( - Event::ReservedForParachainBond { account: 11, value: 16 }, - Event::CollatorChosen { round: 6, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 6, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 25, - round: 6, - selected_collators_number: 5, - total_balance: 140, - }, - Event::DelegatorLeftCandidate { - delegator: 6, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 40, - }, - Event::DelegatorLeft { delegator: 6, unstaked_amount: 10 }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 22 }, - Event::Rewarded { account: 6, rewards: 6 }, - Event::Rewarded { account: 7, rewards: 6 }, - Event::Rewarded { account: 10, rewards: 6 }, - ); - roll_to_round_begin(7); - assert_events_eq!( - Event::ReservedForParachainBond { account: 11, value: 17 }, - Event::CollatorChosen { round: 7, collator_account: 1, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 7, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 7, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 7, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 7, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 30, - round: 7, - selected_collators_number: 5, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 26 }, - Event::Rewarded { account: 7, rewards: 7 }, - Event::Rewarded { account: 10, rewards: 7 }, - ); - assert_eq!(Balances::free_balance(&11), 65); - roll_blocks(1); - assert_ok!(ParachainStaking::set_parachain_bond_reserve_percent( - RuntimeOrigin::root(), - Percent::from_percent(50) - )); - assert_events_eq!(Event::ParachainBondReservePercentSet { - old: Percent::from_percent(30), - new: Percent::from_percent(50), - }); - // 6 won't be paid for this round because they left already - set_author(6, 1, 100); - roll_to_round_begin(8); - // keep paying 6 - assert_events_eq!( - Event::ReservedForParachainBond { account: 11, value: 30 }, - Event::CollatorChosen { round: 8, collator_account: 1, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 8, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 8, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 8, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 8, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 35, - round: 8, - selected_collators_number: 5, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 21 }, - Event::Rewarded { account: 7, rewards: 5 }, - Event::Rewarded { account: 10, rewards: 5 }, - ); - assert_eq!(Balances::free_balance(&11), 95); - set_author(7, 1, 100); - roll_to_round_begin(9); - // no more paying 6 - assert_events_eq!( - Event::ReservedForParachainBond { account: 11, value: 32 }, - Event::CollatorChosen { round: 9, collator_account: 1, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 9, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 9, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 9, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 9, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 40, - round: 9, - selected_collators_number: 5, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 22 }, - Event::Rewarded { account: 7, rewards: 5 }, - Event::Rewarded { account: 10, rewards: 5 }, - ); - assert_eq!(Balances::free_balance(&11), 127); - set_author(8, 1, 100); - roll_blocks(1); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(8), 1, 10, 10, 10)); - assert_events_eq!(Event::Delegation { - delegator: 8, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, - auto_compound: Percent::zero(), - }); - roll_to_round_begin(10); - // new delegation is not rewarded yet - assert_events_eq!( - Event::ReservedForParachainBond { account: 11, value: 33 }, - Event::CollatorChosen { round: 10, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 10, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 10, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 10, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 10, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 45, - round: 10, - selected_collators_number: 5, - total_balance: 140, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 23 }, - Event::Rewarded { account: 7, rewards: 5 }, - Event::Rewarded { account: 10, rewards: 5 }, - ); - assert_eq!(Balances::free_balance(&11), 160); - set_author(9, 1, 100); - set_author(10, 1, 100); - roll_to_round_begin(11); - // new delegation is still not rewarded yet - assert_events_eq!( - Event::ReservedForParachainBond { account: 11, value: 35 }, - Event::CollatorChosen { round: 11, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 11, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 11, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 11, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 11, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 50, - round: 11, - selected_collators_number: 5, - total_balance: 140, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 24 }, - Event::Rewarded { account: 7, rewards: 5 }, - Event::Rewarded { account: 10, rewards: 5 }, - ); - assert_eq!(Balances::free_balance(&11), 195); - roll_to_round_begin(12); - // new delegation is rewarded, 2 rounds after joining (`RewardPaymentDelay` is 2) - assert_events_eq!( - Event::ReservedForParachainBond { account: 11, value: 37 }, - Event::CollatorChosen { round: 12, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 12, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 12, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 12, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 12, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 55, - round: 12, - selected_collators_number: 5, - total_balance: 140, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 24 }, - Event::Rewarded { account: 7, rewards: 4 }, - Event::Rewarded { account: 10, rewards: 4 }, - Event::Rewarded { account: 8, rewards: 4 }, - ); - assert_eq!(Balances::free_balance(&11), 232); - }); -} - -#[test] -fn paid_collator_commission_matches_config() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (6, 100)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 10), (3, 1, 10)]) - .build() - .execute_with(|| { - roll_to_round_begin(2); - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(4), 20u128, 100u32)); - assert_events_eq!( - Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 40 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 1, - total_balance: 40, - }, - Event::JoinedCollatorCandidates { - account: 4, - amount_locked: 20, - new_total_amt_locked: 60, - }, - ); - - roll_blocks(1); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(5), 4, 10, 10, 10)); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(6), 4, 10, 10, 10)); - assert_events_eq!( - Event::Delegation { - delegator: 5, - locked_amount: 10, - candidate: 4, - delegator_position: DelegatorAdded::AddedToTop { new_total: 30 }, - auto_compound: Percent::zero(), - }, - Event::Delegation { - delegator: 6, - locked_amount: 10, - candidate: 4, - delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, - auto_compound: Percent::zero(), - }, - ); - - roll_to_round_begin(3); - assert_events_eq!( - Event::CollatorChosen { round: 3, collator_account: 1, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 3, collator_account: 4, total_exposed_amount: 40 }, - Event::NewRound { - starting_block: 10, - round: 3, - selected_collators_number: 2, - total_balance: 80, - }, - ); - // only reward author with id 4 - set_author(3, 4, 100); - roll_to_round_begin(5); - // 20% of 10 is commission + due_portion (0) = 2 + 4 = 6 - // all delegator payouts are 10-2 = 8 * stake_pct - assert_events_eq!( - Event::CollatorChosen { round: 5, collator_account: 1, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 5, collator_account: 4, total_exposed_amount: 40 }, - Event::NewRound { - starting_block: 20, - round: 5, - selected_collators_number: 2, - total_balance: 80, - }, - ); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { account: 4, rewards: 18 }, - Event::Rewarded { account: 5, rewards: 6 }, - Event::Rewarded { account: 6, rewards: 6 }, - ); - }); -} - -#[test] -fn collator_exit_executes_after_delay() { - ExtBuilder::default() - .with_balances(vec![ - (1, 1000), - (2, 300), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 9), - (9, 4), - ]) - .with_candidates(vec![(1, 500), (2, 200)]) - .with_delegations(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) - .build() - .execute_with(|| { - roll_to(11); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(2), 2)); - assert_events_eq!(Event::CandidateScheduledExit { - exit_allowed_round: 3, - candidate: 2, - scheduled_exit: 5, - }); - let info = ParachainStaking::candidate_info(&2).unwrap(); - assert_eq!(info.status, CollatorStatus::Leaving(5)); - roll_to(21); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 2, 2)); - // we must exclude leaving collators from rewards while - // holding them retroactively accountable for previous faults - // (within the last T::SlashingWindow blocks) - assert_events_eq!(Event::CandidateLeft { - ex_candidate: 2, - unlocked_amount: 400, - new_total_amt_locked: 700, - },); - }); -} - -#[test] -fn collator_selection_chooses_top_candidates() { - ExtBuilder::default() - .with_balances(vec![ - (1, 1000), - (2, 1000), - (3, 1000), - (4, 1000), - (5, 1000), - (6, 1000), - (7, 33), - (8, 33), - (9, 33), - ]) - .with_candidates(vec![(1, 100), (2, 90), (3, 80), (4, 70), (5, 60), (6, 50)]) - .build() - .execute_with(|| { - roll_to_round_begin(2); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(6), 6)); - // should choose top TotalSelectedCandidates (5), in order - assert_events_eq!( - Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 100 }, - Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 90 }, - Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 80 }, - Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 70 }, - Event::CollatorChosen { round: 2, collator_account: 5, total_exposed_amount: 60 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 5, - total_balance: 400, - }, - Event::CandidateScheduledExit { - exit_allowed_round: 2, - candidate: 6, - scheduled_exit: 4 - }, - ); - roll_to_round_begin(4); - roll_blocks(1); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(6), 6, 0)); - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(6), 69u128, 100u32)); - assert_events_eq!( - Event::CandidateLeft { - ex_candidate: 6, - unlocked_amount: 50, - new_total_amt_locked: 400, - }, - Event::JoinedCollatorCandidates { - account: 6, - amount_locked: 69u128, - new_total_amt_locked: 469u128, - }, - ); - roll_to_round_begin(6); - // should choose top TotalSelectedCandidates (5), in order - assert_events_eq!( - Event::CollatorChosen { round: 6, collator_account: 1, total_exposed_amount: 100 }, - Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 90 }, - Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 80 }, - Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 70 }, - Event::CollatorChosen { round: 6, collator_account: 6, total_exposed_amount: 69 }, - Event::NewRound { - starting_block: 25, - round: 6, - selected_collators_number: 5, - total_balance: 409, - }, - ); - }); -} - -#[test] -fn payout_distribution_to_solo_collators() { - ExtBuilder::default() - .with_balances(vec![(1, 1000), (2, 1000), (3, 1000), (4, 1000), (7, 33), (8, 33), (9, 33)]) - .with_candidates(vec![(1, 100), (2, 90), (3, 80), (4, 70)]) - .build() - .execute_with(|| { - roll_to_round_begin(2); - // should choose top TotalCandidatesSelected (5), in order - assert_events_eq!( - Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 100 }, - Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 90 }, - Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 80 }, - Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 70 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 4, - total_balance: 340, - }, - ); - // ~ set block author as 1 for all blocks this round - set_author(2, 1, 100); - roll_to_round_begin(4); - assert_events_eq!( - Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 100 }, - Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 90 }, - Event::CollatorChosen { round: 4, collator_account: 3, total_exposed_amount: 80 }, - Event::CollatorChosen { round: 4, collator_account: 4, total_exposed_amount: 70 }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 4, - total_balance: 340, - }, - ); - // pay total issuance to 1 at 2nd block - roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 205 }); - // ~ set block author as 1 for 3 blocks this round - set_author(4, 1, 60); - // ~ set block author as 2 for 2 blocks this round - set_author(4, 2, 40); - roll_to_round_begin(6); - // pay 60% total issuance to 1 and 40% total issuance to 2 - assert_events_eq!( - Event::CollatorChosen { round: 6, collator_account: 1, total_exposed_amount: 100 }, - Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 90 }, - Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 80 }, - Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 70 }, - Event::NewRound { - starting_block: 25, - round: 6, - selected_collators_number: 4, - total_balance: 340, - }, - ); - roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 129 }); - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 2, rewards: 86 },); - // ~ each collator produces 1 block this round - set_author(6, 1, 20); - set_author(6, 2, 20); - set_author(6, 3, 20); - set_author(6, 4, 20); - roll_to_round_begin(8); - // pay 20% issuance for all collators - assert_events_eq!( - Event::CollatorChosen { round: 8, collator_account: 1, total_exposed_amount: 100 }, - Event::CollatorChosen { round: 8, collator_account: 2, total_exposed_amount: 90 }, - Event::CollatorChosen { round: 8, collator_account: 3, total_exposed_amount: 80 }, - Event::CollatorChosen { round: 8, collator_account: 4, total_exposed_amount: 70 }, - Event::NewRound { - starting_block: 35, - round: 8, - selected_collators_number: 4, - total_balance: 340, - }, - ); - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 3, rewards: 56 }); - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 4, rewards: 56 }); - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 56 }); - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 2, rewards: 56 }); - // check that distributing rewards clears awarded pts - assert!(ParachainStaking::awarded_pts(1, 1).is_zero()); - assert!(ParachainStaking::awarded_pts(4, 1).is_zero()); - assert!(ParachainStaking::awarded_pts(4, 2).is_zero()); - assert!(ParachainStaking::awarded_pts(6, 1).is_zero()); - assert!(ParachainStaking::awarded_pts(6, 2).is_zero()); - assert!(ParachainStaking::awarded_pts(6, 3).is_zero()); - assert!(ParachainStaking::awarded_pts(6, 4).is_zero()); - }); -} - -#[test] -fn multiple_delegations() { - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - ]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) - .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) - .build() - .execute_with(|| { - roll_to_round_begin(2); - // chooses top TotalSelectedCandidates (5), in order - assert_events_eq!( - Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 2, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 5, - total_balance: 140, - }, - ); - roll_blocks(1); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(6), 2, 10, 10, 10)); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(6), 3, 10, 10, 10)); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(6), 4, 10, 10, 10)); - assert_events_eq!( - Event::Delegation { - delegator: 6, - locked_amount: 10, - candidate: 2, - delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, - auto_compound: Percent::zero(), - }, - Event::Delegation { - delegator: 6, - locked_amount: 10, - candidate: 3, - delegator_position: DelegatorAdded::AddedToTop { new_total: 30 }, - auto_compound: Percent::zero(), - }, - Event::Delegation { - delegator: 6, - locked_amount: 10, - candidate: 4, - delegator_position: DelegatorAdded::AddedToTop { new_total: 30 }, - auto_compound: Percent::zero(), - }, - ); - roll_to_round_begin(6); - roll_blocks(1); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(7), 2, 80, 10, 10)); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(10), 2, 10, 10, 10)); - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(2), 5)); - assert_events_eq!( - Event::Delegation { - delegator: 7, - locked_amount: 80, - candidate: 2, - delegator_position: DelegatorAdded::AddedToTop { new_total: 130 }, - auto_compound: Percent::zero(), - }, - Event::Delegation { - delegator: 10, - locked_amount: 10, - candidate: 2, - delegator_position: DelegatorAdded::AddedToBottom, - auto_compound: Percent::zero(), - }, - Event::CandidateScheduledExit { - exit_allowed_round: 6, - candidate: 2, - scheduled_exit: 8 - }, - ); - roll_to_round_begin(7); - assert_events_eq!( - Event::CollatorChosen { round: 7, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 7, collator_account: 3, total_exposed_amount: 30 }, - Event::CollatorChosen { round: 7, collator_account: 4, total_exposed_amount: 30 }, - Event::CollatorChosen { round: 7, collator_account: 5, total_exposed_amount: 10 }, - Event::NewRound { - starting_block: 30, - round: 7, - selected_collators_number: 4, - total_balance: 120, - }, - ); - // verify that delegations are removed after collator leaves, not before - assert_eq!(ParachainStaking::delegator_state(7).unwrap().total(), 90); - assert_eq!(ParachainStaking::delegator_state(7).unwrap().delegations.0.len(), 2usize); - assert_eq!(ParachainStaking::delegator_state(6).unwrap().total(), 40); - assert_eq!(ParachainStaking::delegator_state(6).unwrap().delegations.0.len(), 4usize); - assert_eq!(Balances::locks(&6)[0].amount, 40); - assert_eq!(Balances::locks(&7)[0].amount, 90); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&6), 60); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&7), 10); - roll_to_round_begin(8); - roll_blocks(1); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 2, 5)); - assert_events_eq!(Event::CandidateLeft { - ex_candidate: 2, - unlocked_amount: 140, - new_total_amt_locked: 120, - }); - assert_eq!(ParachainStaking::delegator_state(7).unwrap().total(), 10); - assert_eq!(ParachainStaking::delegator_state(6).unwrap().total(), 30); - assert_eq!(ParachainStaking::delegator_state(7).unwrap().delegations.0.len(), 1usize); - assert_eq!(ParachainStaking::delegator_state(6).unwrap().delegations.0.len(), 3usize); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&6), 70); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&7), 90); - }); -} - -#[test] -// The test verifies that the pending revoke request is removed by 2's exit so there is no dangling -// revoke request after 2 exits -fn execute_leave_candidate_removes_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100)]) - .with_candidates(vec![(1, 20), (2, 20)]) - .with_delegations(vec![(3, 1, 10), (3, 2, 10), (4, 1, 10), (4, 2, 10)]) - .build() - .execute_with(|| { - // Verifies the revocation request is initially empty - assert!(!ParachainStaking::delegation_scheduled_requests(&2) - .iter() - .any(|x| x.delegator == 3)); - - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(2), 2)); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(3), 2)); - // Verifies the revocation request is present - assert!(ParachainStaking::delegation_scheduled_requests(&2) - .iter() - .any(|x| x.delegator == 3)); - - roll_to(16); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(2), 2, 2)); - // Verifies the revocation request is again empty - assert!(!ParachainStaking::delegation_scheduled_requests(&2) - .iter() - .any(|x| x.delegator == 3)); - }); -} - -#[test] -fn payouts_follow_delegation_changes() { - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - ]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) - .build() - .execute_with(|| { - roll_to_round_begin(2); - // chooses top TotalSelectedCandidates (5), in order - assert_events_eq!( - Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 2, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 4, - total_balance: 130, - }, - ); - // ~ set block author as 1 for all blocks this round - set_author(2, 1, 100); - roll_to_round_begin(4); - // distribute total issuance to collator 1 and its delegators 6, 7, 19 - assert_events_eq!( - Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 4, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 4, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 4, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 23 }, - Event::Rewarded { account: 6, rewards: 7 }, - Event::Rewarded { account: 7, rewards: 7 }, - Event::Rewarded { account: 10, rewards: 7 }, - ); - // ~ set block author as 1 for all blocks this round - set_author(3, 1, 100); - set_author(4, 1, 100); - set_author(5, 1, 100); - set_author(6, 1, 100); - - roll_blocks(1); - // 1. ensure delegators are paid for 2 rounds after they leave - assert_noop!( - ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(66)), - Error::::DelegatorDNE - ); - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(6))); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 4, - delegator: 6, - scheduled_exit: 6, - }); - // fast forward to block in which delegator 6 exit executes - roll_to_round_begin(5); - assert_events_eq!( - Event::CollatorChosen { round: 5, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 5, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 5, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 5, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 20, - round: 5, - selected_collators_number: 4, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 24 }, - Event::Rewarded { account: 6, rewards: 8 }, - Event::Rewarded { account: 7, rewards: 8 }, - Event::Rewarded { account: 10, rewards: 8 }, - ); - // keep paying 6 (note: inflation is in terms of total issuance so that's why 1 is 21) - roll_to_round_begin(6); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(6), 6, 10)); - assert_events_eq!( - Event::CollatorChosen { round: 6, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 6, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 6, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 6, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 25, - round: 6, - selected_collators_number: 4, - total_balance: 130, - }, - Event::DelegatorLeftCandidate { - delegator: 6, - candidate: 1, - unstaked_amount: 10, - total_candidate_staked: 40, - }, - Event::DelegatorLeft { delegator: 6, unstaked_amount: 10 }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 26 }, - Event::Rewarded { account: 6, rewards: 8 }, - Event::Rewarded { account: 7, rewards: 8 }, - Event::Rewarded { account: 10, rewards: 8 }, - ); - // 6 won't be paid for this round because they left already - set_author(7, 1, 100); - roll_to_round_begin(7); - // keep paying 6 - assert_events_eq!( - Event::CollatorChosen { round: 7, collator_account: 1, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 7, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 7, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 7, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 30, - round: 7, - selected_collators_number: 4, - total_balance: 120, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 31 }, - Event::Rewarded { account: 7, rewards: 10 }, - Event::Rewarded { account: 10, rewards: 10 }, - ); - roll_to_round_begin(8); - assert_events_eq!( - Event::CollatorChosen { round: 8, collator_account: 1, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 8, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 8, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 8, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 35, - round: 8, - selected_collators_number: 4, - total_balance: 120, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 33 }, - Event::Rewarded { account: 7, rewards: 11 }, - Event::Rewarded { account: 10, rewards: 11 }, - ); - set_author(8, 1, 100); - roll_to_round_begin(9); - // no more paying 6 - assert_events_eq!( - Event::CollatorChosen { round: 9, collator_account: 1, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 9, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 9, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 9, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 40, - round: 9, - selected_collators_number: 4, - total_balance: 120, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 34 }, - Event::Rewarded { account: 7, rewards: 11 }, - Event::Rewarded { account: 10, rewards: 11 }, - ); - roll_blocks(1); - set_author(9, 1, 100); - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(8), 1, 10, 10, 10)); - assert_events_eq!(Event::Delegation { - delegator: 8, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, - auto_compound: Percent::zero(), - }); - - roll_to_round_begin(10); - // new delegation is not rewarded yet - assert_events_eq!( - Event::CollatorChosen { round: 10, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 10, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 10, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 10, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 45, - round: 10, - selected_collators_number: 4, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 36 }, - Event::Rewarded { account: 7, rewards: 12 }, - Event::Rewarded { account: 10, rewards: 12 }, - ); - set_author(10, 1, 100); - roll_to_round_begin(11); - // new delegation not rewarded yet - assert_events_eq!( - Event::CollatorChosen { round: 11, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 11, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 11, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 11, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 50, - round: 11, - selected_collators_number: 4, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 38 }, - Event::Rewarded { account: 7, rewards: 12 }, - Event::Rewarded { account: 10, rewards: 12 }, - ); - roll_to_round_begin(12); - // new delegation is rewarded for first time - // 2 rounds after joining (`RewardPaymentDelay` = 2) - assert_events_eq!( - Event::CollatorChosen { round: 12, collator_account: 1, total_exposed_amount: 50 }, - Event::CollatorChosen { round: 12, collator_account: 2, total_exposed_amount: 40 }, - Event::CollatorChosen { round: 12, collator_account: 3, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 12, collator_account: 4, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 55, - round: 12, - selected_collators_number: 4, - total_balance: 130, - }, - ); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 34 }, - Event::Rewarded { account: 7, rewards: 11 }, - Event::Rewarded { account: 10, rewards: 11 }, - Event::Rewarded { account: 8, rewards: 11 }, - ); - }); -} - -#[test] -fn bottom_delegations_are_empty_when_top_delegations_not_full() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 10), (3, 10), (4, 10), (5, 10)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // no top delegators => no bottom delegators - let top_delegations = ParachainStaking::top_delegations(1).unwrap(); - let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); - assert!(top_delegations.delegations.is_empty()); - assert!(bottom_delegations.delegations.is_empty()); - // 1 delegator => 1 top delegator, 0 bottom delegators - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 10, 10)); - let top_delegations = ParachainStaking::top_delegations(1).unwrap(); - let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); - assert_eq!(top_delegations.delegations.len(), 1usize); - assert!(bottom_delegations.delegations.is_empty()); - // 2 delegators => 2 top delegators, 0 bottom delegators - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(3), 1, 10, 10, 10)); - let top_delegations = ParachainStaking::top_delegations(1).unwrap(); - let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); - assert_eq!(top_delegations.delegations.len(), 2usize); - assert!(bottom_delegations.delegations.is_empty()); - // 3 delegators => 3 top delegators, 0 bottom delegators - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(4), 1, 10, 10, 10)); - let top_delegations = ParachainStaking::top_delegations(1).unwrap(); - let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); - assert_eq!(top_delegations.delegations.len(), 3usize); - assert!(bottom_delegations.delegations.is_empty()); - // 4 delegators => 4 top delegators, 0 bottom delegators - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(5), 1, 10, 10, 10)); - let top_delegations = ParachainStaking::top_delegations(1).unwrap(); - let bottom_delegations = ParachainStaking::bottom_delegations(1).unwrap(); - assert_eq!(top_delegations.delegations.len(), 4usize); - assert!(bottom_delegations.delegations.is_empty()); - }); -} - -#[test] -fn candidate_pool_updates_when_total_counted_changes() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (3, 19), - (4, 20), - (5, 21), - (6, 22), - (7, 15), - (8, 16), - (9, 17), - (10, 18), - ]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (3, 1, 11), - (4, 1, 12), - (5, 1, 13), - (6, 1, 14), - (7, 1, 15), - (8, 1, 16), - (9, 1, 17), - (10, 1, 18), - ]) - .build() - .execute_with(|| { - fn is_candidate_pool_bond(account: u64, bond: u128) { - let pool = ParachainStaking::candidate_pool(); - for candidate in pool.0 { - if candidate.owner == account { - assert_eq!( - candidate.amount, bond, - "Candidate Bond {:?} is Not Equal to Expected: {:?}", - candidate.amount, bond - ); - } - } - } - // 15 + 16 + 17 + 18 + 20 = 86 (top 4 + self bond) - is_candidate_pool_bond(1, 86); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(3), 1, 8)); - // 3: 11 -> 19 => 3 is in top, bumps out 7 - // 16 + 17 + 18 + 19 + 20 = 90 (top 4 + self bond) - is_candidate_pool_bond(1, 90); - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(4), 1, 8)); - // 4: 12 -> 20 => 4 is in top, bumps out 8 - // 17 + 18 + 19 + 20 + 20 = 94 (top 4 + self bond) - is_candidate_pool_bond(1, 94); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(10), - 1, - 3 - )); - roll_to(30); - // 10: 18 -> 15 => 10 bumped to bottom, 8 bumped to top (- 18 + 16 = -2 for count) - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(10), - 10, - 1 - )); - // 16 + 17 + 19 + 20 + 20 = 92 (top 4 + self bond) - is_candidate_pool_bond(1, 92); - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(9), - 1, - 4 - )); - roll_to(40); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(9), - 9, - 1 - )); - // 15 + 16 + 19 + 20 + 20 = 90 (top 4 + self bond) - is_candidate_pool_bond(1, 90); - }); -} - -#[test] -fn only_top_collators_are_counted() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (3, 19), - (4, 20), - (5, 21), - (6, 22), - (7, 15), - (8, 16), - (9, 17), - (10, 18), - ]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (3, 1, 11), - (4, 1, 12), - (5, 1, 13), - (6, 1, 14), - (7, 1, 15), - (8, 1, 16), - (9, 1, 17), - (10, 1, 18), - ]) - .build() - .execute_with(|| { - // sanity check that 3-10 are delegators immediately - for i in 3..11 { - assert!(ParachainStaking::is_delegator(&i)); - } - let collator_state = ParachainStaking::candidate_info(1).unwrap(); - // 15 + 16 + 17 + 18 + 20 = 86 (top 4 + self bond) - assert_eq!(collator_state.total_counted, 86); - // bump bottom to the top - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(3), 1, 8)); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 3, - candidate: 1, - amount: 8, - in_top: true, - }); - let collator_state = ParachainStaking::candidate_info(1).unwrap(); - // 16 + 17 + 18 + 19 + 20 = 90 (top 4 + self bond) - assert_eq!(collator_state.total_counted, 90); - // bump bottom to the top - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(4), 1, 8)); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 4, - candidate: 1, - amount: 8, - in_top: true, - }); - let collator_state = ParachainStaking::candidate_info(1).unwrap(); - // 17 + 18 + 19 + 20 + 20 = 94 (top 4 + self bond) - assert_eq!(collator_state.total_counted, 94); - // bump bottom to the top - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(5), 1, 8)); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 5, - candidate: 1, - amount: 8, - in_top: true, - }); - let collator_state = ParachainStaking::candidate_info(1).unwrap(); - // 18 + 19 + 20 + 21 + 20 = 98 (top 4 + self bond) - assert_eq!(collator_state.total_counted, 98); - // bump bottom to the top - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(6), 1, 8)); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 6, - candidate: 1, - amount: 8, - in_top: true, - }); - let collator_state = ParachainStaking::candidate_info(1).unwrap(); - // 19 + 20 + 21 + 22 + 20 = 102 (top 4 + self bond) - assert_eq!(collator_state.total_counted, 102); - }); -} - -#[test] -fn delegation_events_convey_correct_position() { - ExtBuilder::default() - .with_balances(vec![ - (1, 100), - (2, 100), - (3, 100), - (4, 100), - (5, 100), - (6, 100), - (7, 100), - (8, 100), - (9, 100), - (10, 100), - ]) - .with_candidates(vec![(1, 20), (2, 20)]) - .with_delegations(vec![(3, 1, 11), (4, 1, 12), (5, 1, 13), (6, 1, 14)]) - .build() - .execute_with(|| { - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 11 + 12 + 13 + 14 + 20 = 70 (top 4 + self bond) - assert_eq!(collator1_state.total_counted, 70); - // Top delegations are full, new highest delegation is made - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(7), 1, 15, 10, 10)); - assert_events_emitted!(Event::Delegation { - delegator: 7, - locked_amount: 15, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 74 }, - auto_compound: Percent::zero(), - }); - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 12 + 13 + 14 + 15 + 20 = 70 (top 4 + self bond) - assert_eq!(collator1_state.total_counted, 74); - // New delegation is added to the bottom - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(8), 1, 10, 10, 10)); - assert_events_emitted!(Event::Delegation { - delegator: 8, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToBottom, - auto_compound: Percent::zero(), - }); - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 12 + 13 + 14 + 15 + 20 = 70 (top 4 + self bond) - assert_eq!(collator1_state.total_counted, 74); - // 8 increases delegation to the top - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(8), 1, 3)); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 8, - candidate: 1, - amount: 3, - in_top: true, - }); - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 13 + 13 + 14 + 15 + 20 = 75 (top 4 + self bond) - assert_eq!(collator1_state.total_counted, 75); - // 3 increases delegation but stays in bottom - assert_ok!(ParachainStaking::delegator_bond_more(RuntimeOrigin::signed(3), 1, 1)); - assert_events_emitted!(Event::DelegationIncreased { - delegator: 3, - candidate: 1, - amount: 1, - in_top: false, - }); - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 13 + 13 + 14 + 15 + 20 = 75 (top 4 + self bond) - assert_eq!(collator1_state.total_counted, 75); - // 6 decreases delegation but stays in top - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(6), - 1, - 2 - )); - assert_events_emitted!(Event::DelegationDecreaseScheduled { - delegator: 6, - candidate: 1, - amount_to_decrease: 2, - execute_round: 3, - }); - roll_to(30); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(6), - 6, - 1 - )); - assert_events_emitted!(Event::DelegationDecreased { - delegator: 6, - candidate: 1, - amount: 2, - in_top: true, - }); - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 12 + 13 + 13 + 15 + 20 = 73 (top 4 + self bond)ƒ - assert_eq!(collator1_state.total_counted, 73); - // 6 decreases delegation and is bumped to bottom - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(6), - 1, - 1 - )); - assert_events_emitted!(Event::DelegationDecreaseScheduled { - delegator: 6, - candidate: 1, - amount_to_decrease: 1, - execute_round: 9, - }); - roll_to(40); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(6), - 6, - 1 - )); - assert_events_emitted!(Event::DelegationDecreased { - delegator: 6, - candidate: 1, - amount: 1, - in_top: false, - }); - let collator1_state = ParachainStaking::candidate_info(1).unwrap(); - // 12 + 13 + 13 + 15 + 20 = 73 (top 4 + self bond) - assert_eq!(collator1_state.total_counted, 73); - }); -} - -#[test] -fn no_rewards_paid_until_after_reward_payment_delay() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20)]) - .build() - .execute_with(|| { - roll_to_round_begin(2); - // payouts for round 1 - set_author(1, 1, 1); - set_author(1, 2, 1); - set_author(1, 2, 1); - set_author(1, 3, 1); - set_author(1, 3, 1); - assert_events_eq!( - Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 2, collator_account: 3, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 3, - total_balance: 60, - }, - ); - - roll_to_round_begin(3); - assert_events_eq!( - Event::CollatorChosen { round: 3, collator_account: 1, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 3, collator_account: 2, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 3, collator_account: 3, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 10, - round: 3, - selected_collators_number: 3, - total_balance: 60, - }, - ); - - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 3, rewards: 1 }); - - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 1 }); - - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 2, rewards: 1 }); - - // there should be no more payments in this round... - let num_blocks_rolled = roll_to_round_end(3); - assert_no_events!(); - assert_eq!(num_blocks_rolled, 1); - }); -} - -#[test] -fn deferred_payment_storage_items_are_cleaned_up() { - use crate::*; - - // this test sets up two collators, gives them points in round one, and focuses on the - // storage over the next several blocks to show that it is properly cleaned up - - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20)]) - .with_candidates(vec![(1, 20), (2, 20)]) - .build() - .execute_with(|| { - set_author(1, 1, 1); - set_author(1, 2, 1); - - // reflects genesis? - assert!(>::contains_key(1, 1)); - assert!(>::contains_key(1, 2)); - - roll_to_round_begin(2); - assert_events_eq!( - Event::CollatorChosen { round: 2, collator_account: 1, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 2, collator_account: 2, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 5, - round: 2, - selected_collators_number: 2, - total_balance: 40, - }, - ); - - // we should have AtStake snapshots as soon as we start a round... - assert!(>::contains_key(2, 1)); - assert!(>::contains_key(2, 2)); - // ...and it should persist until the round is fully paid out - assert!(>::contains_key(1, 1)); - assert!(>::contains_key(1, 2)); - - assert!( - !>::contains_key(1), - "DelayedPayouts shouldn't be populated until after RewardPaymentDelay" - ); - assert!( - >::contains_key(1), - "Points should be populated during current round" - ); - assert!( - >::contains_key(1), - "Staked should be populated when round changes" - ); - - assert!( - !>::contains_key(2), - "Points should not be populated until author noted" - ); - assert!( - >::contains_key(2), - "Staked should be populated when round changes" - ); - - // first payout occurs in round 3 - roll_to_round_begin(3); - assert_events_eq!( - Event::CollatorChosen { round: 3, collator_account: 1, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 3, collator_account: 2, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 10, - round: 3, - selected_collators_number: 2, - total_balance: 40, - }, - ); - - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 1 },); - - // payouts should exist for past rounds that haven't been paid out yet.. - assert!(>::contains_key(3, 1)); - assert!(>::contains_key(3, 2)); - assert!(>::contains_key(2, 1)); - assert!(>::contains_key(2, 2)); - - assert!( - >::contains_key(1), - "DelayedPayouts should be populated after RewardPaymentDelay" - ); - assert!(>::contains_key(1)); - assert!( - !>::contains_key(1), - "Staked should be cleaned up after round change" - ); - - assert!(!>::contains_key(2)); - assert!(!>::contains_key(2), "We never rewarded points for round 2"); - assert!(>::contains_key(2)); - - assert!(!>::contains_key(3)); - assert!(!>::contains_key(3), "We never awarded points for round 3"); - assert!(>::contains_key(3)); - - // collator 1 has been paid in this last block and associated storage cleaned up - assert!(!>::contains_key(1, 1)); - assert!(!>::contains_key(1, 1)); - - // but collator 2 hasn't been paid - assert!(>::contains_key(1, 2)); - assert!(>::contains_key(1, 2)); - - // second payout occurs in next block - roll_blocks(1); - assert_events_eq!(Event::Rewarded { account: 2, rewards: 1 },); - - roll_to_round_begin(4); - assert_events_eq!( - Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 20 }, - Event::CollatorChosen { round: 4, collator_account: 2, total_exposed_amount: 20 }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 2, - total_balance: 40, - }, - ); - - // collators have both been paid and storage fully cleaned up for round 1 - assert!(!>::contains_key(1, 2)); - assert!(!>::contains_key(1, 2)); - assert!(!>::contains_key(1)); - assert!(!>::contains_key(1)); // points should be cleaned up - assert!(!>::contains_key(1)); - - roll_to_round_end(4); - - // no more events expected - assert_no_events!(); - }); -} - -#[test] -fn deferred_payment_and_at_stake_storage_items_cleaned_up_for_candidates_not_producing_blocks() { - use crate::*; - - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 20), (2, 20), (3, 20)]) - .build() - .execute_with(|| { - // candidate 3 will not produce blocks - set_author(1, 1, 1); - set_author(1, 2, 1); - - // reflects genesis? - assert!(>::contains_key(1, 1)); - assert!(>::contains_key(1, 2)); - - roll_to_round_begin(2); - assert!(>::contains_key(1, 1)); - assert!(>::contains_key(1, 2)); - assert!(>::contains_key(1, 3)); - assert!(>::contains_key(1, 1)); - assert!(>::contains_key(1, 2)); - assert!(!>::contains_key(1, 3)); - assert!(>::contains_key(1)); - assert!(>::contains_key(1)); - roll_to_round_begin(3); - assert!(>::contains_key(1)); - - // all storage items must be cleaned up - roll_to_round_begin(4); - assert!(!>::contains_key(1, 1)); - assert!(!>::contains_key(1, 2)); - assert!(!>::contains_key(1, 3)); - assert!(!>::contains_key(1, 1)); - assert!(!>::contains_key(1, 2)); - assert!(!>::contains_key(1, 3)); - assert!(!>::contains_key(1)); - assert!(!>::contains_key(1)); - assert!(!>::contains_key(1)); - }); -} - -#[test] -fn deferred_payment_steady_state_event_flow() { - use frame_support::traits::{Currency, ExistenceRequirement, WithdrawReasons}; - - // this test "flows" through a number of rounds, asserting that certain things do/don't happen - // once the staking pallet is in a "steady state" (specifically, once we are past the first few - // rounds to clear RewardPaymentDelay) - - ExtBuilder::default() - .with_balances(vec![ - // collators - (1, 200), - (2, 200), - (3, 200), - (4, 200), - // delegators - (11, 200), - (22, 200), - (33, 200), - (44, 200), - // burn account, see `reset_issuance()` - (111, 1000), - ]) - .with_candidates(vec![(1, 200), (2, 200), (3, 200), (4, 200)]) - .with_delegations(vec![ - // delegator 11 delegates 100 to 1 and 2 - (11, 1, 100), - (11, 2, 100), - // delegator 22 delegates 100 to 2 and 3 - (22, 2, 100), - (22, 3, 100), - // delegator 33 delegates 100 to 3 and 4 - (33, 3, 100), - (33, 4, 100), - // delegator 44 delegates 100 to 4 and 1 - (44, 4, 100), - (44, 1, 100), - ]) - .build() - .execute_with(|| { - // convenience to set the round points consistently - let set_round_points = |round: BlockNumber| { - set_author(round as BlockNumber, 1, 1); - set_author(round as BlockNumber, 2, 1); - set_author(round as BlockNumber, 3, 1); - set_author(round as BlockNumber, 4, 1); - }; - - // grab initial issuance -- we will reset it before round issuance is calculated so that - // it is consistent every round - let initial_issuance = Balances::total_issuance(); - let reset_issuance = || { - let new_issuance = Balances::total_issuance(); - let diff = new_issuance - initial_issuance; - let burned = Balances::burn(diff); - Balances::settle( - &111, - burned, - WithdrawReasons::FEE, - ExistenceRequirement::AllowDeath, - ) - .expect("Account can absorb burn"); - }; - - // fn to roll through the first RewardPaymentDelay rounds. returns new round index - let roll_through_initial_rounds = |mut round: BlockNumber| -> BlockNumber { - while round < crate::mock::RewardPaymentDelay::get() + 1 { - set_round_points(round); - - roll_to_round_end(round); - round += 1; - } - - reset_issuance(); - - round - }; - - // roll through a "steady state" round and make all of our assertions - // returns new round index - let roll_through_steady_state_round = |round: BlockNumber| -> BlockNumber { - let num_rounds_rolled = roll_to_round_begin(round); - assert!(num_rounds_rolled <= 1, "expected to be at round begin already"); - - assert_events_eq!( - Event::CollatorChosen { - round: round as u32, - collator_account: 1, - total_exposed_amount: 400, - }, - Event::CollatorChosen { - round: round as u32, - collator_account: 2, - total_exposed_amount: 400, - }, - Event::CollatorChosen { - round: round as u32, - collator_account: 3, - total_exposed_amount: 400, - }, - Event::CollatorChosen { - round: round as u32, - collator_account: 4, - total_exposed_amount: 400, - }, - Event::NewRound { - starting_block: (round - 1) * 5, - round: round as u32, - selected_collators_number: 4, - total_balance: 1600, - }, - ); - - set_round_points(round); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { account: 3, rewards: 19 }, - Event::Rewarded { account: 22, rewards: 6 }, - Event::Rewarded { account: 33, rewards: 6 }, - ); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { account: 4, rewards: 19 }, - Event::Rewarded { account: 33, rewards: 6 }, - Event::Rewarded { account: 44, rewards: 6 }, - ); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 19 }, - Event::Rewarded { account: 11, rewards: 6 }, - Event::Rewarded { account: 44, rewards: 6 }, - ); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { account: 2, rewards: 19 }, - Event::Rewarded { account: 11, rewards: 6 }, - Event::Rewarded { account: 22, rewards: 6 }, - ); - - roll_blocks(1); - // Since we defer first deferred staking payout, this test have the maximum amout of - // supported collators. This eman that the next round is trigerred one block after - // the last reward. - //assert_no_events!(); - - let num_rounds_rolled = roll_to_round_end(round); - assert_eq!(num_rounds_rolled, 0, "expected to be at round end already"); - - reset_issuance(); - - round + 1 - }; - - let mut round = 1; - round = roll_through_initial_rounds(round); // we should be at RewardPaymentDelay - for _ in 1..2 { - round = roll_through_steady_state_round(round); - } - }); -} - -#[test] -fn delegation_kicked_from_bottom_removes_pending_request() { - ExtBuilder::default() - .with_balances(vec![ - (1, 30), - (2, 29), - (3, 20), - (4, 20), - (5, 20), - (6, 20), - (7, 20), - (8, 20), - (9, 20), - (10, 20), - (11, 30), - ]) - .with_candidates(vec![(1, 30), (11, 30)]) - .with_delegations(vec![ - (2, 1, 19), - (2, 11, 10), // second delegation so not left after first is kicked - (3, 1, 20), - (4, 1, 20), - (5, 1, 20), - (6, 1, 20), - (7, 1, 20), - (8, 1, 20), - (9, 1, 20), - ]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - // 10 delegates to full 1 => kicks lowest delegation (2, 19) - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(10), 1, 20, 8, 0)); - // check the event - assert_events_emitted!(Event::DelegationKicked { - delegator: 2, - candidate: 1, - unstaked_amount: 19, - }); - // ensure request DNE - assert!(!ParachainStaking::delegation_scheduled_requests(&1) - .iter() - .any(|x| x.delegator == 2)); - }); -} - -#[test] -fn no_selected_candidates_defaults_to_last_round_collators() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 30), (3, 30), (4, 30), (5, 30)]) - .with_candidates(vec![(1, 30), (2, 30), (3, 30), (4, 30), (5, 30)]) - .build() - .execute_with(|| { - roll_to_round_begin(1); - // schedule to leave - for i in 1..6 { - assert_ok!(ParachainStaking::schedule_leave_candidates( - RuntimeOrigin::signed(i), - 5 - )); - } - let old_round = ParachainStaking::round().current; - let old_selected_candidates = ParachainStaking::selected_candidates(); - let mut old_at_stake_snapshots = Vec::new(); - for account in old_selected_candidates.clone() { - old_at_stake_snapshots.push(>::get(old_round, account)); - } - roll_to_round_begin(3); - // execute leave - for i in 1..6 { - assert_ok!(ParachainStaking::execute_leave_candidates( - RuntimeOrigin::signed(i), - i, - 0, - )); - } - // next round - roll_to_round_begin(4); - let new_round = ParachainStaking::round().current; - // check AtStake matches previous - let new_selected_candidates = ParachainStaking::selected_candidates(); - assert_eq!(old_selected_candidates, new_selected_candidates); - let mut index = 0usize; - for account in new_selected_candidates { - assert_eq!(old_at_stake_snapshots[index], >::get(new_round, account)); - index += 1usize; - } - }); -} - -#[test] -fn test_delegator_scheduled_for_revoke_is_rewarded_for_previous_rounds_but_not_for_future() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - // preset rewards for rounds 1, 2 and 3 - (1..=3).for_each(|round| set_author(round, 1, 1)); - - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_events_eq!(Event::DelegationRevocationScheduled { - round: 1, - delegator: 2, - candidate: 1, - scheduled_exit: 3, - }); - let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); - assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); - - roll_to_round_begin(3); - assert_events_emitted_match!(Event::NewRound { round: 3, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 4 }, - Event::Rewarded { account: 2, rewards: 1 }, - ); - - roll_to_round_begin(4); - assert_events_emitted_match!(Event::NewRound { round: 4, .. }); - roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); - assert_eq!( - 1, - collator_snapshot.delegations.len(), - "collator snapshot's delegator count was reduced unexpectedly" - ); - assert_eq!( - 20, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); - }); -} - -#[test] -fn test_delegator_scheduled_for_revoke_is_rewarded_when_request_cancelled() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - // preset rewards for rounds 2, 3 and 4 - (2..=4).for_each(|round| set_author(round, 1, 1)); - - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_events_eq!(Event::DelegationRevocationScheduled { - round: 1, - delegator: 2, - candidate: 1, - scheduled_exit: 3, - }); - let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); - assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); - - roll_to_round_begin(2); - assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); - - roll_to_round_begin(4); - assert_events_emitted_match!(Event::NewRound { round: 4, .. }); - roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); - assert_eq!( - 1, - collator_snapshot.delegations.len(), - "collator snapshot's delegator count was reduced unexpectedly" - ); - assert_eq!( - 30, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); - - roll_to_round_begin(5); - assert_events_emitted_match!(Event::NewRound { round: 5, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 4 }, - Event::Rewarded { account: 2, rewards: 1 }, - ); - }); -} - -#[test] -fn test_delegator_scheduled_for_bond_decrease_is_rewarded_for_previous_rounds_but_less_for_future() -{ - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 20), (2, 3, 10)]) - .build() - .execute_with(|| { - // preset rewards for rounds 1, 2 and 3 - (1..=3).for_each(|round| set_author(round, 1, 1)); - - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 10, - )); - assert_events_eq!(Event::DelegationDecreaseScheduled { - execute_round: 3, - delegator: 2, - candidate: 1, - amount_to_decrease: 10, - }); - let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); - assert_eq!(40, collator.total_counted, "collator's total was reduced unexpectedly"); - - roll_to_round_begin(3); - assert_events_emitted_match!(Event::NewRound { round: 3, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 3 }, - Event::Rewarded { account: 2, rewards: 2 }, - ); - - roll_to_round_begin(4); - assert_events_emitted_match!(Event::NewRound { round: 4, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 4 }, - Event::Rewarded { account: 2, rewards: 1 }, - ); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); - assert_eq!( - 1, - collator_snapshot.delegations.len(), - "collator snapshot's delegator count was reduced unexpectedly" - ); - assert_eq!( - 30, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); - }); -} - -#[test] -fn test_delegator_scheduled_for_bond_decrease_is_rewarded_when_request_cancelled() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 20), (2, 3, 10)]) - .build() - .execute_with(|| { - // preset rewards for rounds 2, 3 and 4 - (2..=4).for_each(|round| set_author(round, 1, 1)); - - assert_ok!(ParachainStaking::schedule_delegator_bond_less( - RuntimeOrigin::signed(2), - 1, - 10, - )); - assert_events_eq!(Event::DelegationDecreaseScheduled { - execute_round: 3, - delegator: 2, - candidate: 1, - amount_to_decrease: 10, - }); - let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); - assert_eq!(40, collator.total_counted, "collator's total was reduced unexpectedly"); - - roll_to_round_begin(2); - assert_ok!(ParachainStaking::cancel_delegation_request(RuntimeOrigin::signed(2), 1)); - - roll_to_round_begin(4); - assert_events_emitted_match!(Event::NewRound { round: 4, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 4 }, - Event::Rewarded { account: 2, rewards: 1 }, - ); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); - assert_eq!( - 1, - collator_snapshot.delegations.len(), - "collator snapshot's delegator count was reduced unexpectedly" - ); - assert_eq!( - 40, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); - - roll_to_round_begin(5); - assert_events_emitted_match!(Event::NewRound { round: 5, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 3 }, - Event::Rewarded { account: 2, rewards: 2 }, - ); - }); -} - -#[test] -fn test_delegator_scheduled_for_leave_is_rewarded_for_previous_rounds_but_not_for_future() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - // preset rewards for rounds 1, 2 and 3 - (1..=3).for_each(|round| set_author(round, 1, 1)); - - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2),)); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 1, - delegator: 2, - scheduled_exit: 3, - }); - let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); - assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); - - roll_to_round_begin(3); - assert_events_emitted_match!(Event::NewRound { round: 3, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 4 }, - Event::Rewarded { account: 2, rewards: 1 }, - ); - - roll_to_round_begin(4); - assert_events_emitted_match!(Event::NewRound { round: 4, .. }); - roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); - assert_eq!( - 1, - collator_snapshot.delegations.len(), - "collator snapshot's delegator count was reduced unexpectedly" - ); - assert_eq!( - 20, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); - }); -} - -#[test] -fn test_delegator_scheduled_for_leave_is_rewarded_when_request_cancelled() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - // preset rewards for rounds 2, 3 and 4 - (2..=4).for_each(|round| set_author(round, 1, 1)); - - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 1, - delegator: 2, - scheduled_exit: 3, - }); - let collator = ParachainStaking::candidate_info(1).expect("candidate must exist"); - assert_eq!( - 1, collator.delegation_count, - "collator's delegator count was reduced unexpectedly" - ); - assert_eq!(30, collator.total_counted, "collator's total was reduced unexpectedly"); - - roll_to_round_begin(2); - assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); - - roll_to_round_begin(4); - assert_events_emitted_match!(Event::NewRound { round: 4, .. }); - roll_blocks(3); - assert_events_eq!(Event::Rewarded { account: 1, rewards: 5 },); - let collator_snapshot = - ParachainStaking::at_stake(ParachainStaking::round().current, 1); - assert_eq!( - 1, - collator_snapshot.delegations.len(), - "collator snapshot's delegator count was reduced unexpectedly" - ); - assert_eq!( - 30, collator_snapshot.total, - "collator snapshot's total was reduced unexpectedly", - ); - - roll_to_round_begin(5); - assert_events_emitted_match!(Event::NewRound { round: 5, .. }); - roll_blocks(3); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 4 }, - Event::Rewarded { account: 2, rewards: 1 }, - ); - }); -} - -#[test] -fn test_delegation_request_exists_returns_false_when_nothing_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert!(!ParachainStaking::delegation_request_exists(&1, &2)); - }); -} - -#[test] -fn test_delegation_request_exists_returns_true_when_decrease_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::insert( - 1, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], - ); - assert!(ParachainStaking::delegation_request_exists(&1, &2)); - }); -} - -#[test] -fn test_delegation_request_exists_returns_true_when_revoke_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::insert( - 1, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Revoke(5), - }], - ); - assert!(ParachainStaking::delegation_request_exists(&1, &2)); - }); -} - -#[test] -fn test_delegation_request_revoke_exists_returns_false_when_nothing_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert!(!ParachainStaking::delegation_request_revoke_exists(&1, &2)); - }); -} - -#[test] -fn test_delegation_request_revoke_exists_returns_false_when_decrease_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::insert( - 1, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Decrease(5), - }], - ); - assert!(!ParachainStaking::delegation_request_revoke_exists(&1, &2)); - }); -} - -#[test] -fn test_delegation_request_revoke_exists_returns_true_when_revoke_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::insert( - 1, - vec![ScheduledRequest { - delegator: 2, - when_executable: 3, - action: DelegationAction::Revoke(5), - }], - ); - assert!(ParachainStaking::delegation_request_revoke_exists(&1, &2)); - }); -} - -#[test] -fn test_hotfix_remove_delegation_requests_exited_candidates_cleans_up() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // invalid state - >::insert( - 2, - Vec::>::new(), - ); - >::insert( - 3, - Vec::>::new(), - ); - assert_ok!(ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( - RuntimeOrigin::signed(1), - vec![2, 3, 4] // 4 does not exist, but is OK for idempotency - )); - - assert!(!>::contains_key(2)); - assert!(!>::contains_key(3)); - }); -} - -#[test] -fn test_hotfix_remove_delegation_requests_exited_candidates_cleans_up_only_specified_keys() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // invalid state - >::insert( - 2, - Vec::>::new(), - ); - >::insert( - 3, - Vec::>::new(), - ); - assert_ok!(ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( - RuntimeOrigin::signed(1), - vec![2] - )); - - assert!(!>::contains_key(2)); - assert!(>::contains_key(3)); - }); -} - -#[test] -fn test_hotfix_remove_delegation_requests_exited_candidates_errors_when_requests_not_empty() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // invalid state - >::insert( - 2, - Vec::>::new(), - ); - >::insert( - 3, - vec![ScheduledRequest { - delegator: 10, - when_executable: 1, - action: DelegationAction::Revoke(10), - }], - ); - - assert_noop!( - ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( - RuntimeOrigin::signed(1), - vec![2, 3] - ), - >::CandidateNotLeaving, - ); - }); -} - -#[test] -fn test_hotfix_remove_delegation_requests_exited_candidates_errors_when_candidate_not_exited() { - ExtBuilder::default() - .with_balances(vec![(1, 20)]) - .with_candidates(vec![(1, 20)]) - .build() - .execute_with(|| { - // invalid state - >::insert( - 1, - Vec::>::new(), - ); - assert_noop!( - ParachainStaking::hotfix_remove_delegation_requests_exited_candidates( - RuntimeOrigin::signed(1), - vec![1] - ), - >::CandidateNotLeaving, - ); - }); -} - -#[test] -fn locking_zero_amount_is_ignored() { - use frame_support::traits::{LockableCurrency, WithdrawReasons}; - - // this test demonstrates the behavior of pallet Balance's `LockableCurrency` implementation of - // `set_locks()` when an amount of 0 is provided: it is a no-op - - ExtBuilder::default().with_balances(vec![(1, 100)]).build().execute_with(|| { - assert_eq!(crate::mock::query_lock_amount(1, DELEGATOR_LOCK_ID), None); - - Balances::set_lock(DELEGATOR_LOCK_ID, &1, 1, WithdrawReasons::all()); - assert_eq!(crate::mock::query_lock_amount(1, DELEGATOR_LOCK_ID), Some(1)); - - Balances::set_lock(DELEGATOR_LOCK_ID, &1, 0, WithdrawReasons::all()); - // Note that we tried to call `set_lock(0)` and it ignored it, we still have our lock - assert_eq!(crate::mock::query_lock_amount(1, DELEGATOR_LOCK_ID), Some(1)); - }); -} - -#[test] -fn revoke_last_removes_lock() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 100), (3, 100)]) - .with_candidates(vec![(1, 25), (2, 25)]) - .with_delegations(vec![(3, 1, 30), (3, 2, 25)]) - .build() - .execute_with(|| { - assert_eq!(crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), Some(55)); - - // schedule and remove one... - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(3), 1)); - roll_to_round_begin(3); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(3), - 3, - 1 - )); - assert_eq!(crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), Some(25)); - - // schedule and remove the other... - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(3), 2)); - roll_to_round_begin(5); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(3), - 3, - 2 - )); - assert_eq!(crate::mock::query_lock_amount(3, DELEGATOR_LOCK_ID), None); - }); -} - -#[allow(deprecated)] -#[test] -fn test_delegator_with_deprecated_status_leaving_can_schedule_leave_delegators_as_fix() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::mutate(2, |value| { - value.as_mut().map(|mut state| { - state.status = DelegatorStatus::Leaving(2); - }) - }); - let state = >::get(2); - assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); - - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert!(>::get(1) - .iter() - .any(|r| r.delegator == 2 && matches!(r.action, DelegationAction::Revoke(_)))); - assert_events_eq!(Event::DelegatorExitScheduled { - round: 1, - delegator: 2, - scheduled_exit: 3 - }); - - let state = >::get(2); - assert!(matches!(state.unwrap().status, DelegatorStatus::Active)); - }); -} - -#[allow(deprecated)] -#[test] -fn test_delegator_with_deprecated_status_leaving_can_cancel_leave_delegators_as_fix() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::mutate(2, |value| { - value.as_mut().map(|mut state| { - state.status = DelegatorStatus::Leaving(2); - }) - }); - let state = >::get(2); - assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); - - assert_ok!(ParachainStaking::cancel_leave_delegators(RuntimeOrigin::signed(2))); - assert_events_eq!(Event::DelegatorExitCancelled { delegator: 2 }); - - let state = >::get(2); - assert!(matches!(state.unwrap().status, DelegatorStatus::Active)); - }); -} - -#[allow(deprecated)] -#[test] -fn test_delegator_with_deprecated_status_leaving_can_execute_leave_delegators_as_fix() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::mutate(2, |value| { - value.as_mut().map(|mut state| { - state.status = DelegatorStatus::Leaving(2); - }) - }); - let state = >::get(2); - assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); - - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1)); - assert_events_emitted!(Event::DelegatorLeft { delegator: 2, unstaked_amount: 10 }); - - let state = >::get(2); - assert!(state.is_none()); - }); -} - -#[allow(deprecated)] -#[test] -fn test_delegator_with_deprecated_status_leaving_cannot_execute_leave_delegators_early_no_fix() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 40)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::mutate(2, |value| { - value.as_mut().map(|mut state| { - state.status = DelegatorStatus::Leaving(2); - }) - }); - let state = >::get(2); - assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_))); - - assert_noop!( - ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 1), - Error::::DelegatorCannotLeaveYet - ); - }); -} - -#[test] -fn test_set_auto_compound_fails_if_invalid_delegation_hint() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - let candidate_auto_compounding_delegation_count_hint = 0; - let delegation_hint = 0; // is however, 1 - - assert_noop!( - ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - candidate_auto_compounding_delegation_count_hint, - delegation_hint, - ), - >::TooLowDelegationCountToAutoCompound, - ); - }); -} - -#[test] -fn test_set_auto_compound_fails_if_invalid_candidate_auto_compounding_hint() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::new( - vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(10) }] - .try_into() - .expect("must succeed"), - ) - .set_storage(&1); - let candidate_auto_compounding_delegation_count_hint = 0; // is however, 1 - let delegation_hint = 1; - - assert_noop!( - ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - candidate_auto_compounding_delegation_count_hint, - delegation_hint, - ), - >::TooLowCandidateAutoCompoundingDelegationCountToAutoCompound, - ); - }); -} - -#[test] -fn test_set_auto_compound_inserts_if_not_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 1, - )); - assert_events_emitted!(Event::AutoCompoundSet { - candidate: 1, - delegator: 2, - value: Percent::from_percent(50), - }); - assert_eq!( - vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(50) }], - ParachainStaking::auto_compounding_delegations(&1).into_inner(), - ); - }); -} - -#[test] -fn test_set_auto_compound_updates_if_existing() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::new( - vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(10) }] - .try_into() - .expect("must succeed"), - ) - .set_storage(&1); - - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 1, - 1, - )); - assert_events_emitted!(Event::AutoCompoundSet { - candidate: 1, - delegator: 2, - value: Percent::from_percent(50), - }); - assert_eq!( - vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(50) }], - ParachainStaking::auto_compounding_delegations(&1).into_inner(), - ); - }); -} - -#[test] -fn test_set_auto_compound_removes_if_auto_compound_zero_percent() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - >::new( - vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(10) }] - .try_into() - .expect("must succeed"), - ) - .set_storage(&1); - - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::zero(), - 1, - 1, - )); - assert_events_emitted!(Event::AutoCompoundSet { - candidate: 1, - delegator: 2, - value: Percent::zero(), - }); - assert_eq!(0, ParachainStaking::auto_compounding_delegations(&1).len(),); - }); -} - -#[test] -fn test_execute_revoke_delegation_removes_auto_compounding_from_state_for_delegation_revoke() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 30), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 2, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 3, - Percent::from_percent(50), - 0, - 2, - )); - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to(10); - assert_ok!(ParachainStaking::execute_delegation_request( - RuntimeOrigin::signed(2), - 2, - 1 - )); - assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - assert!( - ParachainStaking::auto_compounding_delegations(&3) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was erroneously removed" - ); - }); -} - -#[test] -fn test_execute_leave_delegators_removes_auto_compounding_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 2, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 3, - Percent::from_percent(50), - 0, - 2, - )); - - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2,)); - - assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - assert!( - !ParachainStaking::auto_compounding_delegations(&3) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - }); -} - -#[allow(deprecated)] -#[test] -fn test_execute_leave_delegators_with_deprecated_status_leaving_removes_auto_compounding_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 2, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 3, - Percent::from_percent(50), - 0, - 2, - )); - - >::mutate(2, |value| { - value.as_mut().map(|mut state| { - state.status = DelegatorStatus::Leaving(2); - }) - }); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_delegators(RuntimeOrigin::signed(2), 2, 2,)); - - assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - assert!( - !ParachainStaking::auto_compounding_delegations(&3) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - }); -} - -#[test] -fn test_execute_leave_candidates_removes_auto_compounding_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 30), (3, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 2, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 3, - Percent::from_percent(50), - 0, - 2, - )); - - assert_ok!(ParachainStaking::schedule_leave_candidates(RuntimeOrigin::signed(1), 2)); - roll_to(10); - assert_ok!(ParachainStaking::execute_leave_candidates(RuntimeOrigin::signed(1), 1, 1,)); - - assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - assert!( - ParachainStaking::auto_compounding_delegations(&3) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was erroneously removed" - ); - }); -} - -#[test] -fn test_delegation_kicked_from_bottom_delegation_removes_auto_compounding_state() { - ExtBuilder::default() - .with_balances(vec![ - (1, 30), - (2, 29), - (3, 20), - (4, 20), - (5, 20), - (6, 20), - (7, 20), - (8, 20), - (9, 20), - (10, 20), - (11, 30), - ]) - .with_candidates(vec![(1, 30), (11, 30)]) - .with_delegations(vec![ - (2, 11, 10), // extra delegation to avoid leaving the delegator set - (2, 1, 19), - (3, 1, 20), - (4, 1, 20), - (5, 1, 20), - (6, 1, 20), - (7, 1, 20), - (8, 1, 20), - (9, 1, 20), - ]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 2, - )); - - // kicks lowest delegation (2, 19) - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(10), 1, 20, 8, 0)); - - assert!( - !ParachainStaking::auto_compounding_delegations(&1) - .iter() - .any(|x| x.delegator == 2), - "delegation auto-compound config was not removed" - ); - }); -} - -#[test] -fn test_rewards_do_not_auto_compound_on_payment_if_delegation_scheduled_revoke_exists() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 200), (3, 200)]) - .with_candidates(vec![(1, 100)]) - .with_delegations(vec![(2, 1, 200), (3, 1, 200)]) - .build() - .execute_with(|| { - (2..=5).for_each(|round| set_author(round, 1, 1)); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(50), - 0, - 1, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(3), - 1, - Percent::from_percent(50), - 1, - 1, - )); - roll_to_round_begin(3); - - // schedule revoke for delegator 2; no rewards should be compounded - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - roll_to_round_begin(4); - - assert_events_eq!( - Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 500 }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 1, - total_balance: 500, - }, - ); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 9 }, - // no compound since revoke request exists - Event::Rewarded { account: 2, rewards: 8 }, - // 50% - Event::Rewarded { account: 3, rewards: 8 }, - Event::Compounded { candidate: 1, delegator: 3, amount: 4 }, - ); - }); -} - -#[test] -fn test_rewards_auto_compound_on_payment_as_per_auto_compound_config() { - ExtBuilder::default() - .with_balances(vec![(1, 100), (2, 200), (3, 200), (4, 200), (5, 200)]) - .with_candidates(vec![(1, 100)]) - .with_delegations(vec![(2, 1, 200), (3, 1, 200), (4, 1, 200), (5, 1, 200)]) - .build() - .execute_with(|| { - (2..=6).for_each(|round| set_author(round, 1, 1)); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(2), - 1, - Percent::from_percent(0), - 0, - 1, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(3), - 1, - Percent::from_percent(50), - 1, - 1, - )); - assert_ok!(ParachainStaking::set_auto_compound( - RuntimeOrigin::signed(4), - 1, - Percent::from_percent(100), - 2, - 1, - )); - roll_to_round_begin(4); - - assert_events_eq!( - Event::CollatorChosen { round: 4, collator_account: 1, total_exposed_amount: 900 }, - Event::NewRound { - starting_block: 15, - round: 4, - selected_collators_number: 1, - total_balance: 900, - }, - ); - - roll_blocks(1); - assert_events_eq!( - Event::Rewarded { account: 1, rewards: 13 }, - // 0% - Event::Rewarded { account: 2, rewards: 8 }, - // 50% - Event::Rewarded { account: 3, rewards: 8 }, - Event::Compounded { candidate: 1, delegator: 3, amount: 4 }, - // 100% - Event::Rewarded { account: 4, rewards: 8 }, - Event::Compounded { candidate: 1, delegator: 4, amount: 8 }, - // no-config - Event::Rewarded { account: 5, rewards: 8 }, - ); - }); -} - -#[test] -fn test_delegate_with_auto_compound_fails_if_invalid_delegation_hint() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25), (3, 30)]) - .with_candidates(vec![(1, 30), (3, 30)]) - .with_delegations(vec![(2, 3, 10)]) - .build() - .execute_with(|| { - let candidate_delegation_count_hint = 0; - let candidate_auto_compounding_delegation_count_hint = 0; - let delegation_hint = 0; // is however, 1 - - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - candidate_delegation_count_hint, - candidate_auto_compounding_delegation_count_hint, - delegation_hint, - ), - >::TooLowDelegationCountToDelegate, - ); - }); -} - -#[test] -fn test_delegate_with_auto_compound_fails_if_invalid_candidate_delegation_count_hint() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25), (3, 30)]) - .with_candidates(vec![(1, 30)]) - .with_delegations(vec![(3, 1, 10)]) - .build() - .execute_with(|| { - let candidate_delegation_count_hint = 0; // is however, 1 - let candidate_auto_compounding_delegation_count_hint = 0; - let delegation_hint = 0; - - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - candidate_delegation_count_hint, - candidate_auto_compounding_delegation_count_hint, - delegation_hint, - ), - >::TooLowCandidateDelegationCountToDelegate, - ); - }); -} - -#[test] -fn test_delegate_with_auto_compound_fails_if_invalid_candidate_auto_compounding_delegations_hint() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25), (3, 30)]) - .with_candidates(vec![(1, 30)]) - .with_auto_compounding_delegations(vec![(3, 1, 10, Percent::from_percent(10))]) - .build() - .execute_with(|| { - let candidate_delegation_count_hint = 1; - let candidate_auto_compounding_delegation_count_hint = 0; // is however, 1 - let delegation_hint = 0; - - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - candidate_delegation_count_hint, - candidate_auto_compounding_delegation_count_hint, - delegation_hint, - ), - >::TooLowCandidateAutoCompoundingDelegationCountToDelegate, - ); - }); -} - -#[test] -fn test_delegate_with_auto_compound_sets_auto_compound_config() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 25)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - 0, - 0, - 0, - )); - assert_events_emitted!(Event::Delegation { - delegator: 2, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, - auto_compound: Percent::from_percent(50), - }); - assert_eq!( - vec![AutoCompoundConfig { delegator: 2, value: Percent::from_percent(50) }], - ParachainStaking::auto_compounding_delegations(&1).into_inner(), - ); - }); -} - -#[test] -fn test_delegate_with_auto_compound_skips_storage_but_emits_event_for_zero_auto_compound() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::zero(), - 0, - 0, - 0, - )); - assert_eq!(0, ParachainStaking::auto_compounding_delegations(&1).len(),); - assert_events_eq!(Event::Delegation { - delegator: 2, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 40 }, - auto_compound: Percent::zero(), - }); - }); -} - -#[test] -fn test_delegate_with_auto_compound_reserves_balance() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 10); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - 0, - 0, - 0, - )); - assert_eq!(ParachainStaking::get_delegator_stakable_free_balance(&2), 0); - }); -} - -#[test] -fn test_delegate_with_auto_compound_updates_delegator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - assert!(ParachainStaking::delegator_state(2).is_none()); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - 0, - 0, - 0 - )); - let delegator_state = - ParachainStaking::delegator_state(2).expect("just delegated => exists"); - assert_eq!(delegator_state.total(), 10); - assert_eq!(delegator_state.delegations.0[0].owner, 1); - assert_eq!(delegator_state.delegations.0[0].amount, 10); - }); -} - -#[test] -fn test_delegate_with_auto_compound_updates_collator_state() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 10)]) - .with_candidates(vec![(1, 30)]) - .build() - .execute_with(|| { - let candidate_state = - ParachainStaking::candidate_info(1).expect("registered in genesis"); - assert_eq!(candidate_state.total_counted, 30); - let top_delegations = - ParachainStaking::top_delegations(1).expect("registered in genesis"); - assert!(top_delegations.delegations.is_empty()); - assert!(top_delegations.total.is_zero()); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - 0, - 0, - 0 - )); - let candidate_state = - ParachainStaking::candidate_info(1).expect("just delegated => exists"); - assert_eq!(candidate_state.total_counted, 40); - let top_delegations = - ParachainStaking::top_delegations(1).expect("just delegated => exists"); - assert_eq!(top_delegations.delegations[0].owner, 2); - assert_eq!(top_delegations.delegations[0].amount, 10); - assert_eq!(top_delegations.total, 10); - }); -} - -#[test] -fn test_delegate_with_auto_compound_can_delegate_immediately_after_other_join_candidates() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::join_candidates(RuntimeOrigin::signed(1), 20, 0)); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 20, - Percent::from_percent(50), - 0, - 0, - 0 - )); - }); -} - -#[test] -fn test_delegate_with_auto_compound_can_delegate_to_other_if_revoking() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 30), (3, 20), (4, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_revoke_delegation(RuntimeOrigin::signed(2), 1)); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 4, - 10, - Percent::from_percent(50), - 0, - 0, - 2 - )); - }); -} - -#[test] -fn test_delegate_with_auto_compound_cannot_delegate_if_less_than_or_equal_lowest_bottom() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 10), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - (10, 10), - (11, 10), - ]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (2, 1, 10), - (3, 1, 10), - (4, 1, 10), - (5, 1, 10), - (6, 1, 10), - (8, 1, 10), - (9, 1, 10), - (10, 1, 10), - ]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(11), - 1, - 10, - Percent::from_percent(50), - 8, - 0, - 0 - ), - Error::::CannotDelegateLessThanOrEqualToLowestBottomWhenFull - ); - }); -} - -#[test] -fn test_delegate_with_auto_compound_can_delegate_if_greater_than_lowest_bottom() { - ExtBuilder::default() - .with_balances(vec![ - (1, 20), - (2, 10), - (3, 10), - (4, 10), - (5, 10), - (6, 10), - (7, 10), - (8, 10), - (9, 10), - (10, 10), - (11, 11), - ]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![ - (2, 1, 10), - (3, 1, 10), - (4, 1, 10), - (5, 1, 10), - (6, 1, 10), - (8, 1, 10), - (9, 1, 10), - (10, 1, 10), - ]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(11), - 1, - 11, - Percent::from_percent(50), - 8, - 0, - 0 - )); - assert_events_emitted!(Event::DelegationKicked { - delegator: 10, - candidate: 1, - unstaked_amount: 10 - }); - assert_events_emitted!(Event::DelegatorLeft { delegator: 10, unstaked_amount: 10 }); - }); -} - -#[test] -fn test_delegate_with_auto_compound_can_still_delegate_to_other_if_leaving() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 20), (3, 20)]) - .with_candidates(vec![(1, 20), (3, 20)]) - .with_delegations(vec![(2, 1, 10)]) - .build() - .execute_with(|| { - assert_ok!(ParachainStaking::schedule_leave_delegators(RuntimeOrigin::signed(2))); - assert_ok!(ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 3, - 10, - Percent::from_percent(50), - 0, - 0, - 1 - ),); - }); -} - -#[test] -fn test_delegate_with_auto_compound_cannot_delegate_if_candidate() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 30)]) - .with_candidates(vec![(1, 20), (2, 20)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - 0, - 0, - 0 - ), - Error::::CandidateExists - ); - }); -} - -#[test] -fn test_delegate_with_auto_compound_cannot_delegate_if_already_delegated() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 30)]) - .with_candidates(vec![(1, 20)]) - .with_delegations(vec![(2, 1, 20)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 1, - 10, - Percent::from_percent(50), - 0, - 1, - 1 - ), - Error::::AlreadyDelegatedCandidate - ); - }); -} - -#[test] -fn test_delegate_with_auto_compound_cannot_delegate_more_than_max_delegations() { - ExtBuilder::default() - .with_balances(vec![(1, 20), (2, 50), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_candidates(vec![(1, 20), (3, 20), (4, 20), (5, 20), (6, 20)]) - .with_delegations(vec![(2, 1, 10), (2, 3, 10), (2, 4, 10), (2, 5, 10)]) - .build() - .execute_with(|| { - assert_noop!( - ParachainStaking::delegate_with_auto_compound( - RuntimeOrigin::signed(2), - 6, - 10, - Percent::from_percent(50), - 0, - 0, - 4 - ), - Error::::ExceedMaxDelegationsPerDelegator, - ); - }); -} - -#[test] -fn test_delegate_skips_auto_compound_storage_but_emits_event_for_zero_auto_compound() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 20), (3, 30)]) - .with_candidates(vec![(1, 30)]) - .with_auto_compounding_delegations(vec![(3, 1, 10, Percent::from_percent(50))]) - .build() - .execute_with(|| { - // We already have an auto-compounding delegation from 3 -> 1, so the hint validation - // would cause a failure if the auto-compounding isn't skipped properly. - assert_ok!(ParachainStaking::delegate(RuntimeOrigin::signed(2), 1, 10, 1, 0,)); - assert_eq!(1, ParachainStaking::auto_compounding_delegations(&1).len(),); - assert_events_eq!(Event::Delegation { - delegator: 2, - locked_amount: 10, - candidate: 1, - delegator_position: DelegatorAdded::AddedToTop { new_total: 50 }, - auto_compound: Percent::zero(), - }); - }); -} - -#[test] -fn test_on_initialize_weights() { - use crate::{ - mock::System, - weights::{SubstrateWeight as PalletWeights, WeightInfo}, - *, - }; - use frame_support::{pallet_prelude::*, weights::constants::RocksDbWeight}; - - // generate balance, candidate, and delegation vecs to "fill" out delegations - let mut balances = Vec::new(); - let mut candidates = Vec::new(); - let mut delegations = Vec::new(); - - for collator in 1..30 { - balances.push((collator, 100)); - candidates.push((collator, 10)); - let starting_delegator = collator * 1000; - for delegator in starting_delegator..starting_delegator + 300 { - balances.push((delegator, 100)); - delegations.push((delegator, collator, 10)); - } - } - - ExtBuilder::default() - .with_balances(balances) - .with_candidates(candidates) - .with_delegations(delegations) - .build() - .execute_with(|| { - let weight = ParachainStaking::on_initialize(1); - - // TODO: build this with proper db reads/writes - assert_eq!(Weight::from_parts(277065000, 0), weight); - - // roll to the end of the round, then run on_init again, we should see round change... - roll_to_round_end(3); - set_author(2, 1, 100); // must set some points for prepare_staking_payouts - let block = System::block_number() + 1; - let weight = ParachainStaking::on_initialize(block); - - // the total on_init weight during our round change. this number is taken from running - // the fn with a given weights.rs benchmark, so will need to be updated as benchmarks - // change. - // - // following this assertion, we add individual weights together to show that we can - // derive this number independently. - let expected_on_init = 2479994997; - assert_eq!(Weight::from_parts(expected_on_init, 186592), weight); - - // assemble weight manually to ensure it is well understood - let mut expected_weight = 0u64; - expected_weight += PalletWeights::::base_on_initialize().ref_time(); - expected_weight += PalletWeights::::prepare_staking_payouts().ref_time(); - - // TODO: this should be the same as >. I believe this relates to - // genesis building - let num_avg_delegations = 8; - expected_weight += PalletWeights::::select_top_candidates( - >::get(), - num_avg_delegations, - ) - .ref_time(); - // Round and Staked writes, done in on-round-change code block inside on_initialize() - expected_weight += RocksDbWeight::get().reads_writes(0, 2).ref_time(); - // more reads/writes manually accounted for for on_finalize - expected_weight += RocksDbWeight::get().reads_writes(3, 2).ref_time(); - - assert_eq!(Weight::from_parts(expected_weight, 186592), weight); - assert_eq!(expected_on_init, expected_weight); // magic number == independent accounting - }); -} - -#[test] -fn test_compute_top_candidates_is_stable() { - ExtBuilder::default() - .with_balances(vec![(1, 30), (2, 30), (3, 30), (4, 30), (5, 30), (6, 30)]) - .with_candidates(vec![(1, 30), (2, 30), (3, 30), (4, 30), (5, 30), (6, 30)]) - .build() - .execute_with(|| { - // There are 6 candidates with equal amount, but only 5 can be selected - assert_eq!(ParachainStaking::candidate_pool().0.len(), 6); - assert_eq!(ParachainStaking::total_selected(), 5); - // Returns the 5 candidates with greater AccountId, because they are iterated in reverse - assert_eq!(ParachainStaking::compute_top_candidates(), vec![2, 3, 4, 5, 6]); - }); -} diff --git a/pallets/parachain-staking/src/traits.rs b/pallets/parachain-staking/src/traits.rs deleted file mode 100644 index 2b30b04cc..000000000 --- a/pallets/parachain-staking/src/traits.rs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam 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. - -// Moonbeam 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 Moonbeam. If not, see . - -//! traits for parachain-staking - -use frame_support::pallet_prelude::Weight; - -pub trait OnCollatorPayout { - fn on_collator_payout( - for_round: crate::RoundIndex, - collator_id: AccountId, - amount: Balance, - ) -> Weight; -} -impl OnCollatorPayout for () { - fn on_collator_payout( - _for_round: crate::RoundIndex, - _collator_id: AccountId, - _amount: Balance, - ) -> Weight { - Weight::zero() - } -} - -pub trait OnNewRound { - fn on_new_round(round_index: crate::RoundIndex) -> Weight; -} -impl OnNewRound for () { - fn on_new_round(_round_index: crate::RoundIndex) -> Weight { - Weight::zero() - } -} - -/// Defines the behavior to payout the collator's reward. -pub trait PayoutCollatorReward { - fn payout_collator_reward( - round_index: crate::RoundIndex, - collator_id: Runtime::AccountId, - amount: crate::BalanceOf, - ) -> Weight; -} - -/// Defines the default behavior for paying out the collator's reward. The amount is directly -/// deposited into the collator's account. -impl PayoutCollatorReward for () { - fn payout_collator_reward( - for_round: crate::RoundIndex, - collator_id: Runtime::AccountId, - amount: crate::BalanceOf, - ) -> Weight { - crate::Pallet::::mint_collator_reward(for_round, collator_id, amount) - } -} diff --git a/pallets/parachain-staking/src/types.rs b/pallets/parachain-staking/src/types.rs deleted file mode 100644 index 1ef686b2f..000000000 --- a/pallets/parachain-staking/src/types.rs +++ /dev/null @@ -1,1627 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam 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. - -// Moonbeam 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 Moonbeam. If not, see . - -//! Types for parachain-staking - -use crate::{ - auto_compound::AutoCompoundDelegations, set::OrderedSet, BalanceOf, BottomDelegations, - CandidateInfo, Config, DelegatorState, Error, Event, Pallet, Round, RoundIndex, TopDelegations, - Total, COLLATOR_LOCK_ID, DELEGATOR_LOCK_ID, -}; -use frame_support::{ - pallet_prelude::*, - traits::{tokens::WithdrawReasons, LockableCurrency}, -}; -use parity_scale_codec::{Decode, Encode}; -use sp_runtime::{ - traits::{AtLeast32BitUnsigned, Saturating, Zero}, - Perbill, Percent, RuntimeDebug, -}; -use sp_std::{cmp::Ordering, collections::btree_map::BTreeMap, prelude::*}; - -pub struct CountedDelegations { - pub uncounted_stake: BalanceOf, - pub rewardable_delegations: Vec>>, -} - -#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] -pub struct Bond { - pub owner: AccountId, - pub amount: Balance, -} - -impl Default for Bond { - fn default() -> Bond { - Bond { - owner: A::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) - .expect("infinite length input; no invalid inputs for type; qed"), - amount: B::default(), - } - } -} - -impl Bond { - pub fn from_owner(owner: A) -> Self { - Bond { owner, amount: B::default() } - } -} - -impl Eq for Bond {} - -impl Ord for Bond { - fn cmp(&self, other: &Self) -> Ordering { - self.owner.cmp(&other.owner) - } -} - -impl PartialOrd for Bond { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl PartialEq for Bond { - fn eq(&self, other: &Self) -> bool { - self.owner == other.owner - } -} - -#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] -/// The activity status of the collator -#[derive(Default)] -pub enum CollatorStatus { - /// Committed to be online and producing valid blocks (not equivocating) - #[default] - Active, - /// Temporarily inactive and excused for inactivity - Idle, - /// Bonded until the inner round - Leaving(RoundIndex), -} - -#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] -pub struct BondWithAutoCompound { - pub owner: AccountId, - pub amount: Balance, - pub auto_compound: Percent, -} - -impl Default for BondWithAutoCompound { - fn default() -> BondWithAutoCompound { - BondWithAutoCompound { - owner: A::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) - .expect("infinite length input; no invalid inputs for type; qed"), - amount: B::default(), - auto_compound: Percent::zero(), - } - } -} - -#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] -/// Snapshot of collator state at the start of the round for which they are selected -pub struct CollatorSnapshot { - /// The total value locked by the collator. - pub bond: Balance, - - /// The rewardable delegations. This list is a subset of total delegators, where certain - /// delegators are adjusted based on their scheduled - /// [DelegationChange::Revoke] or [DelegationChange::Decrease] action. - pub delegations: Vec>, - - /// The total counted value locked for the collator, including the self bond + total staked by - /// top delegators. - pub total: Balance, -} - -impl PartialEq for CollatorSnapshot { - fn eq(&self, other: &Self) -> bool { - let must_be_true = self.bond == other.bond && self.total == other.total; - if !must_be_true { - return false - } - for ( - BondWithAutoCompound { owner: o1, amount: a1, auto_compound: c1 }, - BondWithAutoCompound { owner: o2, amount: a2, auto_compound: c2 }, - ) in self.delegations.iter().zip(other.delegations.iter()) - { - if o1 != o2 || a1 != a2 || c1 != c2 { - return false - } - } - true - } -} - -impl Default for CollatorSnapshot { - fn default() -> CollatorSnapshot { - CollatorSnapshot { bond: B::default(), delegations: Vec::new(), total: B::default() } - } -} - -#[derive(Default, Encode, Decode, RuntimeDebug, TypeInfo)] -/// Info needed to make delayed payments to stakers after round end -pub struct DelayedPayout { - /// Total round reward (result of compute_issuance() at round end) - pub round_issuance: Balance, - /// The total inflation paid this round to stakers (e.g. less parachain bond fund) - pub total_staking_reward: Balance, - /// Snapshot of collator commission rate at the end of the round - pub collator_commission: Perbill, -} - -#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] -/// DEPRECATED -/// Collator state with commission fee, bonded stake, and delegations -pub struct Collator2 { - /// The account of this collator - pub id: AccountId, - /// This collator's self stake. - pub bond: Balance, - /// Set of all nominator AccountIds (to prevent >1 nomination per AccountId) - pub nominators: OrderedSet, - /// Top T::MaxDelegatorsPerCollator::get() nominators, ordered greatest to least - pub top_nominators: Vec>, - /// Bottom nominators (unbounded), ordered least to greatest - pub bottom_nominators: Vec>, - /// Sum of top delegations + self.bond - pub total_counted: Balance, - /// Sum of all delegations + self.bond = (total_counted + uncounted) - pub total_backing: Balance, - /// Current status of the collator - pub state: CollatorStatus, -} - -impl From> for CollatorCandidate { - fn from(other: Collator2) -> CollatorCandidate { - CollatorCandidate { - id: other.id, - bond: other.bond, - delegators: other.nominators, - top_delegations: other.top_nominators, - bottom_delegations: other.bottom_nominators, - total_counted: other.total_counted, - total_backing: other.total_backing, - request: None, - state: other.state, - } - } -} - -#[derive(PartialEq, Clone, Copy, Encode, Decode, RuntimeDebug, TypeInfo)] -/// Request scheduled to change the collator candidate self-bond -pub struct CandidateBondLessRequest { - pub amount: Balance, - pub when_executable: RoundIndex, -} - -#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] -/// DEPRECATED, replaced by `CandidateMetadata` and two storage instances of `Delegations` -/// Collator candidate state with self bond + delegations -pub struct CollatorCandidate { - /// The account of this collator - pub id: AccountId, - /// This collator's self stake. - pub bond: Balance, - /// Set of all delegator AccountIds (to prevent >1 delegation per AccountId) - pub delegators: OrderedSet, - /// Top T::MaxDelegatorsPerCollator::get() delegations, ordered greatest to least - pub top_delegations: Vec>, - /// Bottom delegations (unbounded), ordered least to greatest - pub bottom_delegations: Vec>, - /// Sum of top delegations + self.bond - pub total_counted: Balance, - /// Sum of all delegations + self.bond = (total_counted + uncounted) - pub total_backing: Balance, - /// Maximum 1 pending request to decrease candidate self bond at any given time - pub request: Option>, - /// Current status of the collator - pub state: CollatorStatus, -} - -#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] -/// Type for top and bottom delegation storage item -pub struct Delegations { - pub delegations: Vec>, - pub total: Balance, -} - -impl Default for Delegations { - fn default() -> Delegations { - Delegations { delegations: Vec::new(), total: B::default() } - } -} - -impl - Delegations -{ - pub fn sort_greatest_to_least(&mut self) { - self.delegations.sort_by(|a, b| b.amount.cmp(&a.amount)); - } - /// Insert sorted greatest to least and increase .total accordingly - /// Insertion respects first come first serve so new delegations are pushed after existing - /// delegations if the amount is the same - pub fn insert_sorted_greatest_to_least(&mut self, delegation: Bond) { - self.total = self.total.saturating_add(delegation.amount); - // if delegations nonempty && last_element == delegation.amount => push input and return - if !self.delegations.is_empty() { - // if last_element == delegation.amount => push the delegation and return early - if self.delegations[self.delegations.len() - 1].amount == delegation.amount { - self.delegations.push(delegation); - // early return - return - } - } - // else binary search insertion - match self.delegations.binary_search_by(|x| delegation.amount.cmp(&x.amount)) { - // sorted insertion on sorted vec - // enforces first come first serve for equal bond amounts - Ok(i) => { - let mut new_index = i + 1; - while new_index <= (self.delegations.len() - 1) { - if self.delegations[new_index].amount == delegation.amount { - new_index = new_index.saturating_add(1); - } else { - self.delegations.insert(new_index, delegation); - return - } - } - self.delegations.push(delegation) - }, - Err(i) => self.delegations.insert(i, delegation), - } - } - /// Return the capacity status for top delegations - pub fn top_capacity(&self) -> CapacityStatus { - match &self.delegations { - x if x.len() as u32 >= T::MaxTopDelegationsPerCandidate::get() => CapacityStatus::Full, - x if x.is_empty() => CapacityStatus::Empty, - _ => CapacityStatus::Partial, - } - } - /// Return the capacity status for bottom delegations - pub fn bottom_capacity(&self) -> CapacityStatus { - match &self.delegations { - x if x.len() as u32 >= T::MaxBottomDelegationsPerCandidate::get() => - CapacityStatus::Full, - x if x.is_empty() => CapacityStatus::Empty, - _ => CapacityStatus::Partial, - } - } - /// Return last delegation amount without popping the delegation - pub fn lowest_delegation_amount(&self) -> Balance { - self.delegations.last().map(|x| x.amount).unwrap_or(Balance::zero()) - } - /// Return highest delegation amount - pub fn highest_delegation_amount(&self) -> Balance { - self.delegations.first().map(|x| x.amount).unwrap_or(Balance::zero()) - } -} - -#[derive(PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] -/// Capacity status for top or bottom delegations -pub enum CapacityStatus { - /// Reached capacity - Full, - /// Empty aka contains no delegations - Empty, - /// Partially full (nonempty and not full) - Partial, -} - -#[derive(Encode, Decode, RuntimeDebug, TypeInfo)] -/// All candidate info except the top and bottom delegations -pub struct CandidateMetadata { - /// This candidate's self bond amount - pub bond: Balance, - /// Total number of delegations to this candidate - pub delegation_count: u32, - /// Self bond + sum of top delegations - pub total_counted: Balance, - /// The smallest top delegation amount - pub lowest_top_delegation_amount: Balance, - /// The highest bottom delegation amount - pub highest_bottom_delegation_amount: Balance, - /// The smallest bottom delegation amount - pub lowest_bottom_delegation_amount: Balance, - /// Capacity status for top delegations - pub top_capacity: CapacityStatus, - /// Capacity status for bottom delegations - pub bottom_capacity: CapacityStatus, - /// Maximum 1 pending request to decrease candidate self bond at any given time - pub request: Option>, - /// Current status of the collator - pub status: CollatorStatus, -} - -impl< - Balance: Copy - + Zero - + PartialOrd - + sp_std::ops::AddAssign - + sp_std::ops::SubAssign - + sp_std::ops::Sub - + sp_std::fmt::Debug - + Saturating, - > CandidateMetadata -{ - pub fn new(bond: Balance) -> Self { - CandidateMetadata { - bond, - delegation_count: 0u32, - total_counted: bond, - lowest_top_delegation_amount: Zero::zero(), - highest_bottom_delegation_amount: Zero::zero(), - lowest_bottom_delegation_amount: Zero::zero(), - top_capacity: CapacityStatus::Empty, - bottom_capacity: CapacityStatus::Empty, - request: None, - status: CollatorStatus::Active, - } - } - pub fn is_active(&self) -> bool { - matches!(self.status, CollatorStatus::Active) - } - pub fn is_leaving(&self) -> bool { - matches!(self.status, CollatorStatus::Leaving(_)) - } - pub fn schedule_leave(&mut self) -> Result<(RoundIndex, RoundIndex), DispatchError> { - ensure!(!self.is_leaving(), Error::::CandidateAlreadyLeaving); - let now = >::get().current; - let when = now + T::LeaveCandidatesDelay::get(); - self.status = CollatorStatus::Leaving(when); - Ok((now, when)) - } - pub fn can_leave(&self) -> DispatchResult { - if let CollatorStatus::Leaving(when) = self.status { - ensure!(>::get().current >= when, Error::::CandidateCannotLeaveYet); - Ok(()) - } else { - Err(Error::::CandidateNotLeaving.into()) - } - } - pub fn go_offline(&mut self) { - self.status = CollatorStatus::Idle; - } - pub fn go_online(&mut self) { - self.status = CollatorStatus::Active; - } - pub fn bond_more(&mut self, who: T::AccountId, more: Balance) -> DispatchResult - where - BalanceOf: From, - { - ensure!( - >::get_collator_stakable_free_balance(&who) >= more.into(), - Error::::InsufficientBalance - ); - let new_total = >::get().saturating_add(more.into()); - >::put(new_total); - self.bond = self.bond.saturating_add(more); - T::Currency::set_lock(COLLATOR_LOCK_ID, &who, self.bond.into(), WithdrawReasons::all()); - self.total_counted = self.total_counted.saturating_add(more); - >::deposit_event(Event::CandidateBondedMore { - candidate: who, - amount: more.into(), - new_total_bond: self.bond.into(), - }); - Ok(()) - } - /// Schedule executable decrease of collator candidate self bond - /// Returns the round at which the collator can execute the pending request - pub fn schedule_bond_less( - &mut self, - less: Balance, - ) -> Result - where - BalanceOf: Into, - { - // ensure no pending request - ensure!(self.request.is_none(), Error::::PendingCandidateRequestAlreadyExists); - // ensure bond above min after decrease - ensure!(self.bond > less, Error::::CandidateBondBelowMin); - ensure!( - self.bond - less >= T::MinCandidateStk::get().into(), - Error::::CandidateBondBelowMin - ); - let when_executable = >::get().current + T::CandidateBondLessDelay::get(); - self.request = Some(CandidateBondLessRequest { amount: less, when_executable }); - Ok(when_executable) - } - /// Execute pending request to decrease the collator self bond - /// Returns the event to be emitted - pub fn execute_bond_less(&mut self, who: T::AccountId) -> DispatchResult - where - BalanceOf: From, - { - let request = self.request.ok_or(Error::::PendingCandidateRequestsDNE)?; - ensure!( - request.when_executable <= >::get().current, - Error::::PendingCandidateRequestNotDueYet - ); - let new_total_staked = >::get().saturating_sub(request.amount.into()); - >::put(new_total_staked); - // Arithmetic assumptions are self.bond > less && self.bond - less > CollatorMinBond - // (assumptions enforced by `schedule_bond_less`; if storage corrupts, must re-verify) - self.bond = self.bond.saturating_sub(request.amount); - T::Currency::set_lock(COLLATOR_LOCK_ID, &who, self.bond.into(), WithdrawReasons::all()); - self.total_counted = self.total_counted.saturating_sub(request.amount); - let event = Event::CandidateBondedLess { - candidate: who.clone(), - amount: request.amount.into(), - new_bond: self.bond.into(), - }; - // reset s.t. no pending request - self.request = None; - // update candidate pool value because it must change if self bond changes - if self.is_active() { - Pallet::::update_active(who, self.total_counted.into()); - } - Pallet::::deposit_event(event); - Ok(()) - } - /// Cancel candidate bond less request - pub fn cancel_bond_less(&mut self, who: T::AccountId) -> DispatchResult - where - BalanceOf: From, - { - let request = self.request.ok_or(Error::::PendingCandidateRequestsDNE)?; - let event = Event::CancelledCandidateBondLess { - candidate: who, - amount: request.amount.into(), - execute_round: request.when_executable, - }; - self.request = None; - Pallet::::deposit_event(event); - Ok(()) - } - /// Reset top delegations metadata - pub fn reset_top_data( - &mut self, - candidate: T::AccountId, - top_delegations: &Delegations>, - ) where - BalanceOf: Into + From, - { - self.lowest_top_delegation_amount = top_delegations.lowest_delegation_amount().into(); - self.top_capacity = top_delegations.top_capacity::(); - let old_total_counted = self.total_counted; - self.total_counted = self.bond.saturating_add(top_delegations.total.into()); - // CandidatePool value for candidate always changes if top delegations total changes - // so we moved the update into this function to deduplicate code and patch a bug that - // forgot to apply the update when increasing top delegation - if old_total_counted != self.total_counted && self.is_active() { - Pallet::::update_active(candidate, self.total_counted.into()); - } - } - /// Reset bottom delegations metadata - pub fn reset_bottom_data( - &mut self, - bottom_delegations: &Delegations>, - ) where - BalanceOf: Into, - { - self.lowest_bottom_delegation_amount = bottom_delegations.lowest_delegation_amount().into(); - self.highest_bottom_delegation_amount = - bottom_delegations.highest_delegation_amount().into(); - self.bottom_capacity = bottom_delegations.bottom_capacity::(); - } - /// Add delegation - /// Returns whether delegator was added and an optional negative total counted remainder - /// for if a bottom delegation was kicked - /// MUST ensure no delegation exists for this candidate in the `DelegatorState` before call - pub fn add_delegation( - &mut self, - candidate: &T::AccountId, - delegation: Bond>, - ) -> Result<(DelegatorAdded, Option), DispatchError> - where - BalanceOf: Into + From, - { - let mut less_total_staked = None; - let delegator_added = match self.top_capacity { - CapacityStatus::Full => { - // top is full, insert into top iff the lowest_top < amount - if self.lowest_top_delegation_amount < delegation.amount.into() { - // bumps lowest top to the bottom inside this function call - less_total_staked = self.add_top_delegation::(candidate, delegation); - DelegatorAdded::AddedToTop { new_total: self.total_counted } - } else { - // if bottom is full, only insert if greater than lowest bottom (which will - // be bumped out) - if matches!(self.bottom_capacity, CapacityStatus::Full) { - ensure!( - delegation.amount.into() > self.lowest_bottom_delegation_amount, - Error::::CannotDelegateLessThanOrEqualToLowestBottomWhenFull - ); - // need to subtract from total staked - less_total_staked = Some(self.lowest_bottom_delegation_amount); - } - // insert into bottom - self.add_bottom_delegation::(false, candidate, delegation); - DelegatorAdded::AddedToBottom - } - }, - // top is either empty or partially full - _ => { - self.add_top_delegation::(candidate, delegation); - DelegatorAdded::AddedToTop { new_total: self.total_counted } - }, - }; - Ok((delegator_added, less_total_staked)) - } - /// Add delegation to top delegation - /// Returns Option - /// Only call if lowest top delegation is less than delegation.amount || !top_full - pub fn add_top_delegation( - &mut self, - candidate: &T::AccountId, - delegation: Bond>, - ) -> Option - where - BalanceOf: Into + From, - { - let mut less_total_staked = None; - let mut top_delegations = >::get(candidate) - .expect("CandidateInfo existence => TopDelegations existence"); - let max_top_delegations_per_candidate = T::MaxTopDelegationsPerCandidate::get(); - if top_delegations.delegations.len() as u32 == max_top_delegations_per_candidate { - // pop lowest top delegation - let new_bottom_delegation = top_delegations.delegations.pop().expect(""); - top_delegations.total = - top_delegations.total.saturating_sub(new_bottom_delegation.amount); - if matches!(self.bottom_capacity, CapacityStatus::Full) { - less_total_staked = Some(self.lowest_bottom_delegation_amount); - } - self.add_bottom_delegation::(true, candidate, new_bottom_delegation); - } - // insert into top - top_delegations.insert_sorted_greatest_to_least(delegation); - // update candidate info - self.reset_top_data::(candidate.clone(), &top_delegations); - if less_total_staked.is_none() { - // only increment delegation count if we are not kicking a bottom delegation - self.delegation_count = self.delegation_count.saturating_add(1u32); - } - >::insert(candidate, top_delegations); - less_total_staked - } - /// Add delegation to bottom delegations - /// Check before call that if capacity is full, inserted delegation is higher than lowest - /// bottom delegation (and if so, need to adjust the total storage item) - /// CALLER MUST ensure(lowest_bottom_to_be_kicked.amount < delegation.amount) - pub fn add_bottom_delegation( - &mut self, - bumped_from_top: bool, - candidate: &T::AccountId, - delegation: Bond>, - ) where - BalanceOf: Into + From, - { - let mut bottom_delegations = >::get(candidate) - .expect("CandidateInfo existence => BottomDelegations existence"); - // if bottom is full, kick the lowest bottom (which is expected to be lower than input - // as per check) - let increase_delegation_count = if bottom_delegations.delegations.len() as u32 == - T::MaxBottomDelegationsPerCandidate::get() - { - let lowest_bottom_to_be_kicked = bottom_delegations - .delegations - .pop() - .expect("if at full capacity (>0), then >0 bottom delegations exist; qed"); - // EXPECT lowest_bottom_to_be_kicked.amount < delegation.amount enforced by caller - // if lowest_bottom_to_be_kicked.amount == delegation.amount, we will still kick - // the lowest bottom to enforce first come first served - bottom_delegations.total = - bottom_delegations.total.saturating_sub(lowest_bottom_to_be_kicked.amount); - // update delegator state - // total staked is updated via propagation of lowest bottom delegation amount prior - // to call - let mut delegator_state = >::get(&lowest_bottom_to_be_kicked.owner) - .expect("Delegation existence => DelegatorState existence"); - let leaving = delegator_state.delegations.0.len() == 1usize; - delegator_state.rm_delegation::(candidate); - >::delegation_remove_request_with_state( - candidate, - &lowest_bottom_to_be_kicked.owner, - &mut delegator_state, - ); - >::remove_auto_compound( - candidate, - &lowest_bottom_to_be_kicked.owner, - ); - - Pallet::::deposit_event(Event::DelegationKicked { - delegator: lowest_bottom_to_be_kicked.owner.clone(), - candidate: candidate.clone(), - unstaked_amount: lowest_bottom_to_be_kicked.amount, - }); - if leaving { - >::remove(&lowest_bottom_to_be_kicked.owner); - Pallet::::deposit_event(Event::DelegatorLeft { - delegator: lowest_bottom_to_be_kicked.owner, - unstaked_amount: lowest_bottom_to_be_kicked.amount, - }); - } else { - >::insert(&lowest_bottom_to_be_kicked.owner, delegator_state); - } - false - } else { - !bumped_from_top - }; - // only increase delegation count if new bottom delegation (1) doesn't come from top && - // (2) doesn't pop the lowest delegation from the bottom - if increase_delegation_count { - self.delegation_count = self.delegation_count.saturating_add(1u32); - } - bottom_delegations.insert_sorted_greatest_to_least(delegation); - self.reset_bottom_data::(&bottom_delegations); - >::insert(candidate, bottom_delegations); - } - /// Remove delegation - /// Removes from top if amount is above lowest top or top is not full - /// Return Ok(if_total_counted_changed) - pub fn rm_delegation_if_exists( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - amount: Balance, - ) -> Result - where - BalanceOf: Into + From, - { - let amount_geq_lowest_top = amount >= self.lowest_top_delegation_amount; - let top_is_not_full = !matches!(self.top_capacity, CapacityStatus::Full); - let lowest_top_eq_highest_bottom = - self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; - let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); - if top_is_not_full || (amount_geq_lowest_top && !lowest_top_eq_highest_bottom) { - self.rm_top_delegation::(candidate, delegator) - } else if amount_geq_lowest_top && lowest_top_eq_highest_bottom { - let result = self.rm_top_delegation::(candidate, delegator.clone()); - if result == Err(delegation_dne_err) { - // worst case removal - self.rm_bottom_delegation::(candidate, delegator) - } else { - result - } - } else { - self.rm_bottom_delegation::(candidate, delegator) - } - } - /// Remove top delegation, bumps top bottom delegation if exists - pub fn rm_top_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - ) -> Result - where - BalanceOf: Into + From, - { - let old_total_counted = self.total_counted; - // remove top delegation - let mut top_delegations = >::get(candidate) - .expect("CandidateInfo exists => TopDelegations exists"); - let mut actual_amount_option: Option> = None; - top_delegations.delegations = top_delegations - .delegations - .clone() - .into_iter() - .filter(|d| { - if d.owner != delegator { - true - } else { - actual_amount_option = Some(d.amount); - false - } - }) - .collect(); - let actual_amount = actual_amount_option.ok_or(Error::::DelegationDNE)?; - top_delegations.total = top_delegations.total.saturating_sub(actual_amount); - // if bottom nonempty => bump top bottom to top - if !matches!(self.bottom_capacity, CapacityStatus::Empty) { - let mut bottom_delegations = - >::get(candidate).expect("bottom is nonempty as just checked"); - // expect already stored greatest to least by bond amount - let highest_bottom_delegation = bottom_delegations.delegations.remove(0); - bottom_delegations.total = - bottom_delegations.total.saturating_sub(highest_bottom_delegation.amount); - self.reset_bottom_data::(&bottom_delegations); - >::insert(candidate, bottom_delegations); - // insert highest bottom into top delegations - top_delegations.insert_sorted_greatest_to_least(highest_bottom_delegation); - } - // update candidate info - self.reset_top_data::(candidate.clone(), &top_delegations); - self.delegation_count = self.delegation_count.saturating_sub(1u32); - >::insert(candidate, top_delegations); - // return whether total counted changed - Ok(old_total_counted == self.total_counted) - } - /// Remove bottom delegation - /// Returns if_total_counted_changed: bool - pub fn rm_bottom_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - ) -> Result - where - BalanceOf: Into, - { - // remove bottom delegation - let mut bottom_delegations = >::get(candidate) - .expect("CandidateInfo exists => BottomDelegations exists"); - let mut actual_amount_option: Option> = None; - bottom_delegations.delegations = bottom_delegations - .delegations - .clone() - .into_iter() - .filter(|d| { - if d.owner != delegator { - true - } else { - actual_amount_option = Some(d.amount); - false - } - }) - .collect(); - let actual_amount = actual_amount_option.ok_or(Error::::DelegationDNE)?; - bottom_delegations.total = bottom_delegations.total.saturating_sub(actual_amount); - // update candidate info - self.reset_bottom_data::(&bottom_delegations); - self.delegation_count = self.delegation_count.saturating_sub(1u32); - >::insert(candidate, bottom_delegations); - Ok(false) - } - /// Increase delegation amount - pub fn increase_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - bond: BalanceOf, - more: BalanceOf, - ) -> Result - where - BalanceOf: Into + From, - { - let lowest_top_eq_highest_bottom = - self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; - let bond_geq_lowest_top = bond.into() >= self.lowest_top_delegation_amount; - let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); - if bond_geq_lowest_top && !lowest_top_eq_highest_bottom { - // definitely in top - self.increase_top_delegation::(candidate, delegator, more) - } else if bond_geq_lowest_top && lowest_top_eq_highest_bottom { - // update top but if error then update bottom (because could be in bottom because - // lowest_top_eq_highest_bottom) - let result = self.increase_top_delegation::(candidate, delegator.clone(), more); - if result == Err(delegation_dne_err) { - self.increase_bottom_delegation::(candidate, delegator, bond, more) - } else { - result - } - } else { - self.increase_bottom_delegation::(candidate, delegator, bond, more) - } - } - /// Increase top delegation - pub fn increase_top_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - more: BalanceOf, - ) -> Result - where - BalanceOf: Into + From, - { - let mut top_delegations = >::get(candidate) - .expect("CandidateInfo exists => TopDelegations exists"); - let mut in_top = false; - top_delegations.delegations = top_delegations - .delegations - .clone() - .into_iter() - .map(|d| { - if d.owner != delegator { - d - } else { - in_top = true; - let new_amount = d.amount.saturating_add(more); - Bond { owner: d.owner, amount: new_amount } - } - }) - .collect(); - ensure!(in_top, Error::::DelegationDNE); - top_delegations.total = top_delegations.total.saturating_add(more); - top_delegations.sort_greatest_to_least(); - self.reset_top_data::(candidate.clone(), &top_delegations); - >::insert(candidate, top_delegations); - Ok(true) - } - /// Increase bottom delegation - pub fn increase_bottom_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - bond: BalanceOf, - more: BalanceOf, - ) -> Result - where - BalanceOf: Into + From, - { - let mut bottom_delegations = - >::get(candidate).ok_or(Error::::CandidateDNE)?; - let mut delegation_option: Option>> = None; - let in_top_after = if (bond.saturating_add(more)).into() > self.lowest_top_delegation_amount - { - // bump it from bottom - bottom_delegations.delegations = bottom_delegations - .delegations - .clone() - .into_iter() - .filter(|d| { - if d.owner != delegator { - true - } else { - delegation_option = Some(Bond { - owner: d.owner.clone(), - amount: d.amount.saturating_add(more), - }); - false - } - }) - .collect(); - let delegation = delegation_option.ok_or(Error::::DelegationDNE)?; - bottom_delegations.total = bottom_delegations.total.saturating_sub(bond); - // add it to top - let mut top_delegations = >::get(candidate) - .expect("CandidateInfo existence => TopDelegations existence"); - // if top is full, pop lowest top - if matches!(top_delegations.top_capacity::(), CapacityStatus::Full) { - // pop lowest top delegation - let new_bottom_delegation = top_delegations - .delegations - .pop() - .expect("Top capacity full => Exists at least 1 top delegation"); - top_delegations.total = - top_delegations.total.saturating_sub(new_bottom_delegation.amount); - bottom_delegations.insert_sorted_greatest_to_least(new_bottom_delegation); - } - // insert into top - top_delegations.insert_sorted_greatest_to_least(delegation); - self.reset_top_data::(candidate.clone(), &top_delegations); - >::insert(candidate, top_delegations); - true - } else { - let mut in_bottom = false; - // just increase the delegation - bottom_delegations.delegations = bottom_delegations - .delegations - .clone() - .into_iter() - .map(|d| { - if d.owner != delegator { - d - } else { - in_bottom = true; - Bond { owner: d.owner, amount: d.amount.saturating_add(more) } - } - }) - .collect(); - ensure!(in_bottom, Error::::DelegationDNE); - bottom_delegations.total = bottom_delegations.total.saturating_add(more); - bottom_delegations.sort_greatest_to_least(); - false - }; - self.reset_bottom_data::(&bottom_delegations); - >::insert(candidate, bottom_delegations); - Ok(in_top_after) - } - /// Decrease delegation - pub fn decrease_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - bond: Balance, - less: BalanceOf, - ) -> Result - where - BalanceOf: Into + From, - { - let lowest_top_eq_highest_bottom = - self.lowest_top_delegation_amount == self.highest_bottom_delegation_amount; - let bond_geq_lowest_top = bond >= self.lowest_top_delegation_amount; - let delegation_dne_err: DispatchError = Error::::DelegationDNE.into(); - if bond_geq_lowest_top && !lowest_top_eq_highest_bottom { - // definitely in top - self.decrease_top_delegation::(candidate, delegator, bond.into(), less) - } else if bond_geq_lowest_top && lowest_top_eq_highest_bottom { - // update top but if error then update bottom (because could be in bottom because - // lowest_top_eq_highest_bottom) - let result = - self.decrease_top_delegation::(candidate, delegator.clone(), bond.into(), less); - if result == Err(delegation_dne_err) { - self.decrease_bottom_delegation::(candidate, delegator, less) - } else { - result - } - } else { - self.decrease_bottom_delegation::(candidate, delegator, less) - } - } - /// Decrease top delegation - pub fn decrease_top_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - bond: BalanceOf, - less: BalanceOf, - ) -> Result - where - BalanceOf: Into + From, - { - // The delegation after the `decrease-delegation` will be strictly less than the - // highest bottom delegation - let bond_after_less_than_highest_bottom = - bond.saturating_sub(less).into() < self.highest_bottom_delegation_amount; - // The top delegations is full and the bottom delegations has at least one delegation - let full_top_and_nonempty_bottom = matches!(self.top_capacity, CapacityStatus::Full) && - !matches!(self.bottom_capacity, CapacityStatus::Empty); - let mut top_delegations = - >::get(candidate).ok_or(Error::::CandidateDNE)?; - let in_top_after = if bond_after_less_than_highest_bottom && full_top_and_nonempty_bottom { - let mut delegation_option: Option>> = None; - // take delegation from top - top_delegations.delegations = top_delegations - .delegations - .clone() - .into_iter() - .filter(|d| { - if d.owner != delegator { - true - } else { - top_delegations.total = top_delegations.total.saturating_sub(d.amount); - delegation_option = Some(Bond { - owner: d.owner.clone(), - amount: d.amount.saturating_sub(less), - }); - false - } - }) - .collect(); - let delegation = delegation_option.ok_or(Error::::DelegationDNE)?; - // pop highest bottom by reverse and popping - let mut bottom_delegations = >::get(candidate) - .expect("CandidateInfo existence => BottomDelegations existence"); - let highest_bottom_delegation = bottom_delegations.delegations.remove(0); - bottom_delegations.total = - bottom_delegations.total.saturating_sub(highest_bottom_delegation.amount); - // insert highest bottom into top - top_delegations.insert_sorted_greatest_to_least(highest_bottom_delegation); - // insert previous top into bottom - bottom_delegations.insert_sorted_greatest_to_least(delegation); - self.reset_bottom_data::(&bottom_delegations); - >::insert(candidate, bottom_delegations); - false - } else { - // keep it in the top - let mut is_in_top = false; - top_delegations.delegations = top_delegations - .delegations - .clone() - .into_iter() - .map(|d| { - if d.owner != delegator { - d - } else { - is_in_top = true; - Bond { owner: d.owner, amount: d.amount.saturating_sub(less) } - } - }) - .collect(); - ensure!(is_in_top, Error::::DelegationDNE); - top_delegations.total = top_delegations.total.saturating_sub(less); - top_delegations.sort_greatest_to_least(); - true - }; - self.reset_top_data::(candidate.clone(), &top_delegations); - >::insert(candidate, top_delegations); - Ok(in_top_after) - } - /// Decrease bottom delegation - pub fn decrease_bottom_delegation( - &mut self, - candidate: &T::AccountId, - delegator: T::AccountId, - less: BalanceOf, - ) -> Result - where - BalanceOf: Into, - { - let mut bottom_delegations = >::get(candidate) - .expect("CandidateInfo exists => BottomDelegations exists"); - let mut in_bottom = false; - bottom_delegations.delegations = bottom_delegations - .delegations - .clone() - .into_iter() - .map(|d| { - if d.owner != delegator { - d - } else { - in_bottom = true; - Bond { owner: d.owner, amount: d.amount.saturating_sub(less) } - } - }) - .collect(); - ensure!(in_bottom, Error::::DelegationDNE); - bottom_delegations.sort_greatest_to_least(); - self.reset_bottom_data::(&bottom_delegations); - >::insert(candidate, bottom_delegations); - Ok(false) - } -} - -// Temporary manual implementation for migration testing purposes -impl PartialEq for CollatorCandidate { - fn eq(&self, other: &Self) -> bool { - let must_be_true = self.id == other.id && - self.bond == other.bond && - self.total_counted == other.total_counted && - self.total_backing == other.total_backing && - self.request == other.request && - self.state == other.state; - if !must_be_true { - return false - } - for (x, y) in self.delegators.0.iter().zip(other.delegators.0.iter()) { - if x != y { - return false - } - } - for (Bond { owner: o1, amount: a1 }, Bond { owner: o2, amount: a2 }) in - self.top_delegations.iter().zip(other.top_delegations.iter()) - { - if o1 != o2 || a1 != a2 { - return false - } - } - for (Bond { owner: o1, amount: a1 }, Bond { owner: o2, amount: a2 }) in - self.bottom_delegations.iter().zip(other.bottom_delegations.iter()) - { - if o1 != o2 || a1 != a2 { - return false - } - } - true - } -} - -/// Convey relevant information describing if a delegator was added to the top or bottom -/// Delegations added to the top yield a new total -#[derive(Clone, Copy, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] -pub enum DelegatorAdded { - AddedToTop { new_total: B }, - AddedToBottom, -} - -impl< - A: Ord + Clone + sp_std::fmt::Debug, - B: AtLeast32BitUnsigned - + Ord - + Copy - + sp_std::ops::AddAssign - + sp_std::ops::SubAssign - + sp_std::fmt::Debug, - > CollatorCandidate -{ - pub fn is_active(&self) -> bool { - self.state == CollatorStatus::Active - } -} - -impl From> for CollatorSnapshot { - fn from(other: CollatorCandidate) -> CollatorSnapshot { - CollatorSnapshot { - bond: other.bond, - delegations: other - .top_delegations - .into_iter() - .map(|d| BondWithAutoCompound { - owner: d.owner, - amount: d.amount, - auto_compound: Percent::zero(), - }) - .collect(), - total: other.total_counted, - } - } -} - -#[allow(deprecated)] -#[derive(Clone, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] -pub enum DelegatorStatus { - /// Active with no scheduled exit - Active, - /// Schedule exit to revoke all ongoing delegations - #[deprecated(note = "must only be used for backwards compatibility reasons")] - Leaving(RoundIndex), -} - -#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] -/// Delegator state -pub struct Delegator { - /// Delegator account - pub id: AccountId, - /// All current delegations - pub delegations: OrderedSet>, - /// Total balance locked for this delegator - pub total: Balance, - /// Sum of pending revocation amounts + bond less amounts - pub less_total: Balance, - /// Status for this delegator - pub status: DelegatorStatus, -} - -// Temporary manual implementation for migration testing purposes -impl PartialEq for Delegator { - fn eq(&self, other: &Self) -> bool { - let must_be_true = self.id == other.id && - self.total == other.total && - self.less_total == other.less_total && - self.status == other.status; - if !must_be_true { - return false - } - for (Bond { owner: o1, amount: a1 }, Bond { owner: o2, amount: a2 }) in - self.delegations.0.iter().zip(other.delegations.0.iter()) - { - if o1 != o2 || a1 != a2 { - return false - } - } - true - } -} - -impl< - AccountId: Ord + Clone, - Balance: Copy - + sp_std::ops::AddAssign - + sp_std::ops::Add - + sp_std::ops::SubAssign - + sp_std::ops::Sub - + Ord - + Zero - + Default - + Saturating, - > Delegator -{ - pub fn new(id: AccountId, collator: AccountId, amount: Balance) -> Self { - Delegator { - id, - delegations: OrderedSet::from(vec![Bond { owner: collator, amount }]), - total: amount, - less_total: Balance::zero(), - status: DelegatorStatus::Active, - } - } - - pub fn default_with_total(id: AccountId, amount: Balance) -> Self { - Delegator { - id, - total: amount, - delegations: OrderedSet::from(vec![]), - less_total: Balance::zero(), - status: DelegatorStatus::Active, - } - } - - pub fn total(&self) -> Balance { - self.total - } - - pub fn total_sub_if(&mut self, amount: Balance, check: F) -> DispatchResult - where - T: Config, - T::AccountId: From, - BalanceOf: From, - F: Fn(Balance) -> DispatchResult, - { - let total = self.total.saturating_sub(amount); - check(total)?; - self.total = total; - self.adjust_bond_lock::(BondAdjust::Decrease)?; - Ok(()) - } - - pub fn total_add(&mut self, amount: Balance) -> DispatchResult - where - T: Config, - T::AccountId: From, - BalanceOf: From, - { - self.total = self.total.saturating_add(amount); - self.adjust_bond_lock::(BondAdjust::Increase(amount))?; - Ok(()) - } - - pub fn total_sub(&mut self, amount: Balance) -> DispatchResult - where - T: Config, - T::AccountId: From, - BalanceOf: From, - { - self.total = self.total.saturating_sub(amount); - self.adjust_bond_lock::(BondAdjust::Decrease)?; - Ok(()) - } - - pub fn is_active(&self) -> bool { - matches!(self.status, DelegatorStatus::Active) - } - - pub fn add_delegation(&mut self, bond: Bond) -> bool { - let amt = bond.amount; - if self.delegations.insert(bond) { - self.total = self.total.saturating_add(amt); - true - } else { - false - } - } - // Return Some(remaining balance), must be more than MinDelegatorStk - // Return None if delegation not found - pub fn rm_delegation(&mut self, collator: &AccountId) -> Option - where - BalanceOf: From, - T::AccountId: From, - { - let mut amt: Option = None; - let delegations = self - .delegations - .0 - .iter() - .filter_map(|x| { - if &x.owner == collator { - amt = Some(x.amount); - None - } else { - Some(x.clone()) - } - }) - .collect(); - if let Some(balance) = amt { - self.delegations = OrderedSet::from(delegations); - self.total_sub::(balance).expect("Decreasing lock cannot fail, qed"); - Some(self.total) - } else { - None - } - } - - /// Increases the delegation amount and returns `true` if the delegation is part of the - /// TopDelegations set, `false` otherwise. - pub fn increase_delegation( - &mut self, - candidate: AccountId, - amount: Balance, - ) -> Result - where - BalanceOf: From, - T::AccountId: From, - Delegator>: From>, - { - let delegator_id: T::AccountId = self.id.clone().into(); - let candidate_id: T::AccountId = candidate.clone().into(); - let balance_amt: BalanceOf = amount.into(); - // increase delegation - for x in &mut self.delegations.0 { - if x.owner == candidate { - let before_amount: BalanceOf = x.amount.into(); - x.amount = x.amount.saturating_add(amount); - self.total = self.total.saturating_add(amount); - self.adjust_bond_lock::(BondAdjust::Increase(amount))?; - - // update collator state delegation - let mut collator_state = - >::get(&candidate_id).ok_or(Error::::CandidateDNE)?; - let before = collator_state.total_counted; - let in_top = collator_state.increase_delegation::( - &candidate_id, - delegator_id.clone(), - before_amount, - balance_amt, - )?; - let after = collator_state.total_counted; - if collator_state.is_active() && (before != after) { - Pallet::::update_active(candidate_id.clone(), after); - } - >::insert(&candidate_id, collator_state); - let new_total_staked = >::get().saturating_add(balance_amt); - >::put(new_total_staked); - let nom_st: Delegator> = self.clone().into(); - >::insert(&delegator_id, nom_st); - return Ok(in_top) - } - } - Err(Error::::DelegationDNE.into()) - } - - /// Updates the bond locks for this delegator. - /// - /// This will take the current self.total and ensure that a lock of the same amount is applied - /// and when increasing the bond lock will also ensure that the account has enough free balance. - /// - /// `additional_required_balance` should reflect the change to the amount that should be locked if - /// positive, 0 otherwise (e.g. `min(0, change_in_total_bond)`). This is necessary because it is - /// not possible to query the amount that is locked for a given lock id. - pub fn adjust_bond_lock( - &mut self, - additional_required_balance: BondAdjust, - ) -> DispatchResult - where - BalanceOf: From, - T::AccountId: From, - { - match additional_required_balance { - BondAdjust::Increase(amount) => { - ensure!( - >::get_delegator_stakable_free_balance(&self.id.clone().into()) >= - amount.into(), - Error::::InsufficientBalance, - ); - - // additional sanity check: shouldn't ever want to lock more than total - if amount > self.total { - log::warn!("LOGIC ERROR: request to reserve more than bond total"); - return Err(DispatchError::Other("Invalid additional_required_balance")) - } - }, - BondAdjust::Decrease => (), // do nothing on decrease - }; - - if self.total.is_zero() { - T::Currency::remove_lock(DELEGATOR_LOCK_ID, &self.id.clone().into()); - } else { - T::Currency::set_lock( - DELEGATOR_LOCK_ID, - &self.id.clone().into(), - self.total.into(), - WithdrawReasons::all(), - ); - } - Ok(()) - } - - /// Retrieves the bond amount that a delegator has provided towards a collator. - /// Returns `None` if missing. - pub fn get_bond_amount(&self, collator: &AccountId) -> Option { - self.delegations.0.iter().find(|b| &b.owner == collator).map(|b| b.amount) - } -} - -pub mod deprecated { - #![allow(deprecated)] - - use super::*; - - #[deprecated(note = "use DelegationAction")] - #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] - /// Changes requested by the delegator - /// - limit of 1 ongoing change per delegation - pub enum DelegationChange { - Revoke, - Decrease, - } - - #[deprecated(note = "use ScheduledRequest")] - #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] - pub struct DelegationRequest { - pub collator: AccountId, - pub amount: Balance, - pub when_executable: RoundIndex, - pub action: DelegationChange, - } - - #[deprecated(note = "use DelegationScheduledRequests storage item")] - #[derive(Clone, Encode, PartialEq, Decode, RuntimeDebug, TypeInfo)] - /// Pending requests to mutate delegations for each delegator - pub struct PendingDelegationRequests { - /// Number of pending revocations (necessary for determining whether revoke is exit) - pub revocations_count: u32, - /// Map from collator -> Request (enforces at most 1 pending request per delegation) - pub requests: BTreeMap>, - /// Sum of pending revocation amounts + bond less amounts - pub less_total: Balance, - } - - impl Default for PendingDelegationRequests { - fn default() -> PendingDelegationRequests { - PendingDelegationRequests { - revocations_count: 0u32, - requests: BTreeMap::new(), - less_total: B::zero(), - } - } - } - - impl< - A: Ord + Clone, - B: Zero - + Ord - + Copy - + Clone - + sp_std::ops::AddAssign - + sp_std::ops::Add - + sp_std::ops::SubAssign - + sp_std::ops::Sub - + Saturating, - > PendingDelegationRequests - { - /// New default (empty) pending requests - pub fn new() -> Self { - Self::default() - } - } - - #[deprecated(note = "use new crate::types::Delegator struct")] - #[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] - /// Delegator state - pub struct Delegator { - /// Delegator account - pub id: AccountId, - /// All current delegations - pub delegations: OrderedSet>, - /// Total balance locked for this delegator - pub total: Balance, - /// Requests to change delegations, relevant iff active - pub requests: PendingDelegationRequests, - /// Status for this delegator - pub status: DelegatorStatus, - } - - // CollatorSnapshot - - #[deprecated(note = "use CollatorSnapshot with BondWithAutoCompound delegations")] - #[derive(Encode, Decode, RuntimeDebug, TypeInfo)] - /// Snapshot of collator state at the start of the round for which they are selected - pub struct CollatorSnapshot { - /// The total value locked by the collator. - pub bond: Balance, - - /// The rewardable delegations. This list is a subset of total delegators, where certain - /// delegators are adjusted based on their scheduled - /// [DelegationChange::Revoke] or [DelegationChange::Decrease] action. - pub delegations: Vec>, - - /// The total counted value locked for the collator, including the self bond + total staked by - /// top delegators. - pub total: Balance, - } - - impl PartialEq for CollatorSnapshot { - fn eq(&self, other: &Self) -> bool { - let must_be_true = self.bond == other.bond && self.total == other.total; - if !must_be_true { - return false - } - for (Bond { owner: o1, amount: a1 }, Bond { owner: o2, amount: a2 }) in - self.delegations.iter().zip(other.delegations.iter()) - { - if o1 != o2 || a1 != a2 { - return false - } - } - true - } - } - - impl Default for CollatorSnapshot { - fn default() -> CollatorSnapshot { - CollatorSnapshot { bond: B::default(), delegations: Vec::new(), total: B::default() } - } - } -} - -#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)] -/// DEPRECATED in favor of Delegator -/// Nominator state -pub struct Nominator2 { - /// All current delegations - pub delegations: OrderedSet>, - /// Delegations scheduled to be revoked - pub revocations: OrderedSet, - /// Total balance locked for this nominator - pub total: Balance, - /// Total number of revocations scheduled to be executed - pub scheduled_revocations_count: u32, - /// Total amount to be unbonded once revocations are executed - pub scheduled_revocations_total: Balance, - /// Status for this nominator - pub status: DelegatorStatus, -} - -// /// Temporary function to migrate state -// pub(crate) fn migrate_nominator_to_delegator_state( -// id: T::AccountId, -// nominator: Nominator2>, -// ) -> Delegator> { -// Delegator { -// id, -// delegations: nominator.delegations, -// total: nominator.total, -// requests: PendingDelegationRequests::new(), -// status: nominator.status, -// } -// } - -#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] -/// The current round index and transition information -pub struct RoundInfo { - /// Current round index - pub current: RoundIndex, - /// The first block of the current round - pub first: BlockNumber, - /// The length of the current round in number of blocks - pub length: u32, -} -impl< - B: Copy + sp_std::ops::Add + sp_std::ops::Sub + From + PartialOrd, - > RoundInfo -{ - pub fn new(current: RoundIndex, first: B, length: u32) -> RoundInfo { - RoundInfo { current, first, length } - } - /// Check if the round should be updated - pub fn should_update(&self, now: B) -> bool { - now - self.first >= self.length.into() - } - /// New round - pub fn update(&mut self, now: B) { - self.current = self.current.saturating_add(1u32); - self.first = now; - } -} -impl< - B: Copy + sp_std::ops::Add + sp_std::ops::Sub + From + PartialOrd, - > Default for RoundInfo -{ - fn default() -> RoundInfo { - RoundInfo::new(1u32, 1u32.into(), 20u32) - } -} - -#[derive(Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] -/// Reserve information { account, percent_of_inflation } -pub struct ParachainBondConfig { - /// Account which receives funds intended for parachain bond - pub account: AccountId, - /// Percent of inflation set aside for parachain bond account - pub percent: Percent, -} -impl Default for ParachainBondConfig { - fn default() -> ParachainBondConfig { - ParachainBondConfig { - account: A::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) - .expect("infinite length input; no invalid inputs for type; qed"), - percent: Percent::zero(), - } - } -} - -pub enum BondAdjust { - Increase(Balance), - Decrease, -} diff --git a/pallets/parachain-staking/src/weights.rs b/pallets/parachain-staking/src/weights.rs deleted file mode 100644 index ac72c2bb6..000000000 --- a/pallets/parachain-staking/src/weights.rs +++ /dev/null @@ -1,1418 +0,0 @@ -// Copyright 2019-2022 PureStake Inc. -// This file is part of Moonbeam. - -// Moonbeam 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. - -// Moonbeam 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 Moonbeam. If not, see . - - -//! Autogenerated weights for parachain_staking -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-04-28, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `benchmarker`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024 - -// Executed Command: -// ./target/release/moonbeam -// benchmark -// pallet -// --execution=wasm -// --wasm-execution=compiled -// --pallet -// * -// --extrinsic -// * -// --steps -// 50 -// --repeat -// 20 -// --template=./benchmarking/frame-weight-template.hbs -// --json-file -// raw.json -// --output -// weights/ - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use sp_std::marker::PhantomData; - -/// Weight functions needed for parachain_staking. -pub trait WeightInfo { - fn set_staking_expectations() -> Weight; - fn set_inflation() -> Weight; - fn set_parachain_bond_account() -> Weight; - fn set_parachain_bond_reserve_percent() -> Weight; - fn set_total_selected() -> Weight; - fn set_collator_commission() -> Weight; - fn set_blocks_per_round() -> Weight; - fn join_candidates(x: u32, ) -> Weight; - fn schedule_leave_candidates(x: u32, ) -> Weight; - fn execute_leave_candidates(x: u32, ) -> Weight; - fn cancel_leave_candidates(x: u32, ) -> Weight; - fn go_offline() -> Weight; - fn go_online() -> Weight; - fn candidate_bond_more() -> Weight; - fn schedule_candidate_bond_less() -> Weight; - fn execute_candidate_bond_less() -> Weight; - fn cancel_candidate_bond_less() -> Weight; - fn delegate(x: u32, y: u32, ) -> Weight; - fn schedule_leave_delegators() -> Weight; - fn execute_leave_delegators(x: u32, ) -> Weight; - fn cancel_leave_delegators() -> Weight; - fn schedule_revoke_delegation() -> Weight; - fn delegator_bond_more() -> Weight; - fn schedule_delegator_bond_less() -> Weight; - fn execute_revoke_delegation() -> Weight; - fn execute_delegator_bond_less() -> Weight; - fn cancel_revoke_delegation() -> Weight; - fn cancel_delegator_bond_less() -> Weight; - fn prepare_staking_payouts() -> Weight; - fn get_rewardable_delegators(y: u32, ) -> Weight; - fn select_top_candidates(x: u32, y: u32, ) -> Weight; - fn pay_one_collator_reward(y: u32, ) -> Weight; - fn base_on_initialize() -> Weight; - fn set_auto_compound(x: u32, y: u32, ) -> Weight; - fn delegate_with_auto_compound(x: u32, y: u32, z: u32, ) -> Weight; - fn mint_collator_reward() -> Weight; -} - -/// Weights for parachain_staking using the Substrate node and recommended hardware. -pub struct SubstrateWeight(PhantomData); -impl WeightInfo for SubstrateWeight { - /// Storage: ParachainStaking InflationConfig (r:1 w:1) - /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) - fn set_staking_expectations() -> Weight { - // Proof Size summary in bytes: - // Measured: `88` - // Estimated: `1573` - // Minimum execution time: 18_070_000 picoseconds. - Weight::from_parts(18_325_000, 1573) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: ParachainStaking InflationConfig (r:1 w:1) - /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) - fn set_inflation() -> Weight { - // Proof Size summary in bytes: - // Measured: `88` - // Estimated: `1573` - // Minimum execution time: 47_600_000 picoseconds. - Weight::from_parts(48_094_000, 1573) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: ParachainStaking ParachainBondInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking ParachainBondInfo (max_values: Some(1), max_size: None, mode: Measured) - fn set_parachain_bond_account() -> Weight { - // Proof Size summary in bytes: - // Measured: `6` - // Estimated: `1491` - // Minimum execution time: 15_818_000 picoseconds. - Weight::from_parts(16_256_000, 1491) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: ParachainStaking ParachainBondInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking ParachainBondInfo (max_values: Some(1), max_size: None, mode: Measured) - fn set_parachain_bond_reserve_percent() -> Weight { - // Proof Size summary in bytes: - // Measured: `6` - // Estimated: `1491` - // Minimum execution time: 15_327_000 picoseconds. - Weight::from_parts(15_488_000, 1491) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: ParachainStaking TotalSelected (r:1 w:1) - /// Proof Skipped: ParachainStaking TotalSelected (max_values: Some(1), max_size: None, mode: Measured) - fn set_total_selected() -> Weight { - // Proof Size summary in bytes: - // Measured: `28` - // Estimated: `1513` - // Minimum execution time: 16_629_000 picoseconds. - Weight::from_parts(17_245_000, 1513) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: ParachainStaking CollatorCommission (r:1 w:1) - /// Proof Skipped: ParachainStaking CollatorCommission (max_values: Some(1), max_size: None, mode: Measured) - fn set_collator_commission() -> Weight { - // Proof Size summary in bytes: - // Measured: `27` - // Estimated: `1512` - // Minimum execution time: 15_586_000 picoseconds. - Weight::from_parts(16_060_000, 1512) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: ParachainStaking TotalSelected (r:1 w:0) - /// Proof Skipped: ParachainStaking TotalSelected (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking InflationConfig (r:1 w:1) - /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) - fn set_blocks_per_round() -> Weight { - // Proof Size summary in bytes: - // Measured: `116` - // Estimated: `3202` - // Minimum execution time: 52_085_000 picoseconds. - Weight::from_parts(52_439_000, 3202) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegatorState (r:1 w:0) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking TopDelegations (r:0 w:1) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking BottomDelegations (r:0 w:1) - /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) - /// The range of component `x` is `[3, 1000]`. - fn join_candidates(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1821 + x * (37 ±0)` - // Estimated: `27743 + x * (228 ±0)` - // Minimum execution time: 62_721_000 picoseconds. - Weight::from_parts(59_951_661, 27743) - // Standard Error: 1_080 - .saturating_add(Weight::from_parts(83_856, 0).saturating_mul(x.into())) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) - .saturating_add(Weight::from_parts(0, 228).saturating_mul(x.into())) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `x` is `[3, 1000]`. - fn schedule_leave_candidates(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `865 + x * (36 ±0)` - // Estimated: `6542 + x * (74 ±0)` - // Minimum execution time: 29_088_000 picoseconds. - Weight::from_parts(23_948_090, 6542) - // Standard Error: 1_107 - .saturating_add(Weight::from_parts(72_705, 0).saturating_mul(x.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - .saturating_add(Weight::from_parts(0, 74).saturating_mul(x.into())) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking TopDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegatorState (r:349 w:349) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: Balances Locks (r:350 w:350) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: System Account (r:350 w:350) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking BottomDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `x` is `[2, 350]`. - fn execute_leave_candidates(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `979 + x * (431 ±0)` - // Estimated: `30725 + x * (11823 ±0)` - // Minimum execution time: 102_273_000 picoseconds. - Weight::from_parts(102_546_000, 30725) - // Standard Error: 76_720 - .saturating_add(Weight::from_parts(33_831_394, 0).saturating_mul(x.into())) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().reads((3_u64).saturating_mul(x.into()))) - .saturating_add(T::DbWeight::get().writes(5_u64)) - .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(x.into()))) - .saturating_add(Weight::from_parts(0, 11823).saturating_mul(x.into())) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `x` is `[3, 1000]`. - fn cancel_leave_candidates(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `833 + x * (36 ±0)` - // Estimated: `6478 + x * (74 ±0)` - // Minimum execution time: 28_142_000 picoseconds. - Weight::from_parts(22_767_262, 6478) - // Standard Error: 1_102 - .saturating_add(Weight::from_parts(73_806, 0).saturating_mul(x.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - .saturating_add(Weight::from_parts(0, 74).saturating_mul(x.into())) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - fn go_offline() -> Weight { - // Proof Size summary in bytes: - // Measured: `271` - // Estimated: `5492` - // Minimum execution time: 27_523_000 picoseconds. - Weight::from_parts(27_792_000, 5492) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - fn go_online() -> Weight { - // Proof Size summary in bytes: - // Measured: `234` - // Estimated: `5418` - // Minimum execution time: 27_667_000 picoseconds. - Weight::from_parts(27_972_000, 5418) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - fn candidate_bond_more() -> Weight { - // Proof Size summary in bytes: - // Measured: `527` - // Estimated: `16349` - // Minimum execution time: 56_424_000 picoseconds. - Weight::from_parts(57_028_000, 16349) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - fn schedule_candidate_bond_less() -> Weight { - // Proof Size summary in bytes: - // Measured: `171` - // Estimated: `3636` - // Minimum execution time: 22_764_000 picoseconds. - Weight::from_parts(23_511_000, 3636) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - fn execute_candidate_bond_less() -> Weight { - // Proof Size summary in bytes: - // Measured: `547` - // Estimated: `16409` - // Minimum execution time: 55_133_000 picoseconds. - Weight::from_parts(55_704_000, 16409) - .saturating_add(T::DbWeight::get().reads(5_u64)) - .saturating_add(T::DbWeight::get().writes(5_u64)) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - fn cancel_candidate_bond_less() -> Weight { - // Proof Size summary in bytes: - // Measured: `191` - // Estimated: `3656` - // Minimum execution time: 20_773_000 picoseconds. - Weight::from_parts(21_485_000, 3656) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking TopDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `x` is `[3, 100]`. - /// The range of component `y` is `[2, 300]`. - fn delegate(x: u32, y: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `2479 + x * (79 ±0) + y * (38 ±0)` - // Estimated: `32988 + x * (405 ±0) + y * (195 ±0)` - // Minimum execution time: 94_976_000 picoseconds. - Weight::from_parts(83_764_148, 32988) - // Standard Error: 1_433 - .saturating_add(Weight::from_parts(154_670, 0).saturating_mul(x.into())) - // Standard Error: 470 - .saturating_add(Weight::from_parts(48_242, 0).saturating_mul(y.into())) - .saturating_add(T::DbWeight::get().reads(7_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) - .saturating_add(Weight::from_parts(0, 405).saturating_mul(x.into())) - .saturating_add(Weight::from_parts(0, 195).saturating_mul(y.into())) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - fn schedule_leave_delegators() -> Weight { - // Proof Size summary in bytes: - // Measured: `107` - // Estimated: `7144` - // Minimum execution time: 28_255_000 picoseconds. - Weight::from_parts(28_539_000, 7144) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:99 w:99) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidateInfo (r:99 w:99) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking TopDelegations (r:99 w:99) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking AutoCompoundingDelegations (r:99 w:0) - /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// The range of component `x` is `[2, 100]`. - fn execute_leave_delegators(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `824 + x * (376 ±0)` - // Estimated: `34626 + x * (12238 ±1)` - // Minimum execution time: 88_582_000 picoseconds. - Weight::from_parts(88_972_000, 34626) - // Standard Error: 40_214 - .saturating_add(Weight::from_parts(30_393_572, 0).saturating_mul(x.into())) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(x.into()))) - .saturating_add(T::DbWeight::get().writes(2_u64)) - .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(x.into()))) - .saturating_add(Weight::from_parts(0, 12238).saturating_mul(x.into())) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - fn cancel_leave_delegators() -> Weight { - // Proof Size summary in bytes: - // Measured: `173` - // Estimated: `7276` - // Minimum execution time: 30_396_000 picoseconds. - Weight::from_parts(30_758_000, 7276) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - fn schedule_revoke_delegation() -> Weight { - // Proof Size summary in bytes: - // Measured: `107` - // Estimated: `7144` - // Minimum execution time: 27_434_000 picoseconds. - Weight::from_parts(27_725_000, 7144) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking TopDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - fn delegator_bond_more() -> Weight { - // Proof Size summary in bytes: - // Measured: `843` - // Estimated: `30221` - // Minimum execution time: 76_944_000 picoseconds. - Weight::from_parts(77_695_000, 30221) - .saturating_add(T::DbWeight::get().reads(8_u64)) - .saturating_add(T::DbWeight::get().writes(7_u64)) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - fn schedule_delegator_bond_less() -> Weight { - // Proof Size summary in bytes: - // Measured: `107` - // Estimated: `7144` - // Minimum execution time: 27_633_000 picoseconds. - Weight::from_parts(27_950_000, 7144) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) - /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking TopDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - fn execute_revoke_delegation() -> Weight { - // Proof Size summary in bytes: - // Measured: `964` - // Estimated: `35376` - // Minimum execution time: 92_054_000 picoseconds. - Weight::from_parts(93_161_000, 35376) - .saturating_add(T::DbWeight::get().reads(9_u64)) - .saturating_add(T::DbWeight::get().writes(8_u64)) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: ParachainStaking TopDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - fn execute_delegator_bond_less() -> Weight { - // Proof Size summary in bytes: - // Measured: `909` - // Estimated: `30617` - // Minimum execution time: 77_509_000 picoseconds. - Weight::from_parts(78_070_000, 30617) - .saturating_add(T::DbWeight::get().reads(8_u64)) - .saturating_add(T::DbWeight::get().writes(8_u64)) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - fn cancel_revoke_delegation() -> Weight { - // Proof Size summary in bytes: - // Measured: `173` - // Estimated: `7276` - // Minimum execution time: 27_469_000 picoseconds. - Weight::from_parts(28_047_000, 7276) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - fn cancel_delegator_bond_less() -> Weight { - // Proof Size summary in bytes: - // Measured: `173` - // Estimated: `7276` - // Minimum execution time: 28_572_000 picoseconds. - Weight::from_parts(28_806_000, 7276) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(2_u64)) - } - /// Storage: ParachainStaking Points (r:1 w:0) - /// Proof Skipped: ParachainStaking Points (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking Staked (r:1 w:1) - /// Proof Skipped: ParachainStaking Staked (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking InflationConfig (r:1 w:0) - /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking ParachainBondInfo (r:1 w:0) - /// Proof Skipped: ParachainStaking ParachainBondInfo (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: ParachainStaking CollatorCommission (r:1 w:0) - /// Proof Skipped: ParachainStaking CollatorCommission (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking DelayedPayouts (r:0 w:1) - /// Proof Skipped: ParachainStaking DelayedPayouts (max_values: None, max_size: None, mode: Measured) - fn prepare_staking_payouts() -> Weight { - // Proof Size summary in bytes: - // Measured: `380` - // Estimated: `17246` - // Minimum execution time: 43_338_000 picoseconds. - Weight::from_parts(43_786_000, 17246) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - } - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking TopDelegations (r:1 w:0) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// The range of component `y` is `[0, 100]`. - fn get_rewardable_delegators(y: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `73 + y * (36 ±0)` - // Estimated: `7074 + y * (72 ±0)` - // Minimum execution time: 8_392_000 picoseconds. - Weight::from_parts(9_785_180, 7074) - // Standard Error: 388 - .saturating_add(Weight::from_parts(24_123, 0).saturating_mul(y.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(Weight::from_parts(0, 72).saturating_mul(y.into())) - } - /// Storage: ParachainStaking TotalSelected (r:1 w:0) - /// Proof Skipped: ParachainStaking TotalSelected (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:0) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidateInfo (r:51 w:0) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:51 w:0) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking TopDelegations (r:51 w:0) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking AutoCompoundingDelegations (r:51 w:0) - /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking SelectedCandidates (r:0 w:1) - /// Proof Skipped: ParachainStaking SelectedCandidates (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking AtStake (r:0 w:51) - /// Proof Skipped: ParachainStaking AtStake (max_values: None, max_size: None, mode: Measured) - /// The range of component `x` is `[0, 50]`. - /// The range of component `y` is `[0, 100]`. - fn select_top_candidates(x: u32, y: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0 + x * (3816 ±0) + y * (1800 ±0)` - // Estimated: `18950 + x * (21900 ±39) + y * (5112 ±19)` - // Minimum execution time: 32_303_000 picoseconds. - Weight::from_parts(32_680_000, 18950) - // Standard Error: 82_316 - .saturating_add(Weight::from_parts(23_158_353, 0).saturating_mul(x.into())) - // Standard Error: 41_048 - .saturating_add(Weight::from_parts(1_334_029, 0).saturating_mul(y.into())) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(x.into()))) - .saturating_add(T::DbWeight::get().writes(2_u64)) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(x.into()))) - .saturating_add(Weight::from_parts(0, 21900).saturating_mul(x.into())) - .saturating_add(Weight::from_parts(0, 5112).saturating_mul(y.into())) - } - /// Storage: ParachainStaking DelayedPayouts (r:1 w:0) - /// Proof Skipped: ParachainStaking DelayedPayouts (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking Points (r:1 w:0) - /// Proof Skipped: ParachainStaking Points (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking AtStake (r:2 w:1) - /// Proof Skipped: ParachainStaking AtStake (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking AwardedPts (r:1 w:1) - /// Proof Skipped: ParachainStaking AwardedPts (max_values: None, max_size: None, mode: Measured) - /// Storage: MoonbeamOrbiters OrbiterPerRound (r:1 w:0) - /// Proof Skipped: MoonbeamOrbiters OrbiterPerRound (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:301 w:301) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// The range of component `y` is `[0, 300]`. - fn pay_one_collator_reward(y: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1132 + y * (160 ±0)` - // Estimated: `28331 + y * (3396 ±0)` - // Minimum execution time: 58_105_000 picoseconds. - Weight::from_parts(53_052_308, 28331) - // Standard Error: 6_526 - .saturating_add(Weight::from_parts(19_017_961, 0).saturating_mul(y.into())) - .saturating_add(T::DbWeight::get().reads(7_u64)) - .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(y.into()))) - .saturating_add(T::DbWeight::get().writes(3_u64)) - .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(y.into()))) - .saturating_add(Weight::from_parts(0, 3396).saturating_mul(y.into())) - } - fn base_on_initialize() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 2_008_000 picoseconds. - Weight::from_parts(2_065_000, 0) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:0) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) - /// The range of component `x` is `[0, 300]`. - /// The range of component `y` is `[0, 100]`. - fn set_auto_compound(x: u32, y: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `671 + x * (22 ±0) + y * (36 ±0)` - // Estimated: `8054 + x * (46 ±0) + y * (72 ±0)` - // Minimum execution time: 29_102_000 picoseconds. - Weight::from_parts(26_155_259, 8054) - // Standard Error: 278 - .saturating_add(Weight::from_parts(49_717, 0).saturating_mul(x.into())) - // Standard Error: 833 - .saturating_add(Weight::from_parts(48_123, 0).saturating_mul(y.into())) - .saturating_add(T::DbWeight::get().reads(2_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_parts(0, 46).saturating_mul(x.into())) - .saturating_add(Weight::from_parts(0, 72).saturating_mul(y.into())) - } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking BottomDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking TopDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `x` is `[0, 350]`. - /// The range of component `y` is `[0, 350]`. - /// The range of component `z` is `[0, 100]`. - fn delegate_with_auto_compound(x: u32, y: u32, z: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0 + x * (58 ±0) + y * (21 ±0) + z * (41 ±0)` - // Estimated: `59323 + x * (145 ±0) + y * (132 ±0) + z * (873144491150315 ±3)` - // Minimum execution time: 100_647_000 picoseconds. - Weight::from_parts(84_809_337, 59323) - // Standard Error: 1_211 - .saturating_add(Weight::from_parts(15_186, 0).saturating_mul(x.into())) - // Standard Error: 1_211 - .saturating_add(Weight::from_parts(30_270, 0).saturating_mul(y.into())) - // Standard Error: 4_227 - .saturating_add(Weight::from_parts(173_069, 0).saturating_mul(z.into())) - .saturating_add(T::DbWeight::get().reads(8_u64)) - .saturating_add(T::DbWeight::get().writes(8_u64)) - .saturating_add(Weight::from_parts(0, 145).saturating_mul(x.into())) - .saturating_add(Weight::from_parts(0, 132).saturating_mul(y.into())) - .saturating_add(Weight::from_parts(0, 307).saturating_mul(z.into())) - } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - fn mint_collator_reward() -> Weight { - // Proof Size summary in bytes: - // Measured: `128` - // Estimated: `3581` - // Minimum execution time: 24_224_000 picoseconds. - Weight::from_parts(24_514_000, 3581) - .saturating_add(T::DbWeight::get().reads(1_u64)) - .saturating_add(T::DbWeight::get().writes(1_u64)) - } -} - -// For backwards compatibility and tests -impl WeightInfo for () { - /// Storage: ParachainStaking InflationConfig (r:1 w:1) - /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) - fn set_staking_expectations() -> Weight { - // Proof Size summary in bytes: - // Measured: `88` - // Estimated: `1573` - // Minimum execution time: 18_070_000 picoseconds. - Weight::from_parts(18_325_000, 1573) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: ParachainStaking InflationConfig (r:1 w:1) - /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) - fn set_inflation() -> Weight { - // Proof Size summary in bytes: - // Measured: `88` - // Estimated: `1573` - // Minimum execution time: 47_600_000 picoseconds. - Weight::from_parts(48_094_000, 1573) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: ParachainStaking ParachainBondInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking ParachainBondInfo (max_values: Some(1), max_size: None, mode: Measured) - fn set_parachain_bond_account() -> Weight { - // Proof Size summary in bytes: - // Measured: `6` - // Estimated: `1491` - // Minimum execution time: 15_818_000 picoseconds. - Weight::from_parts(16_256_000, 1491) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: ParachainStaking ParachainBondInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking ParachainBondInfo (max_values: Some(1), max_size: None, mode: Measured) - fn set_parachain_bond_reserve_percent() -> Weight { - // Proof Size summary in bytes: - // Measured: `6` - // Estimated: `1491` - // Minimum execution time: 15_327_000 picoseconds. - Weight::from_parts(15_488_000, 1491) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: ParachainStaking TotalSelected (r:1 w:1) - /// Proof Skipped: ParachainStaking TotalSelected (max_values: Some(1), max_size: None, mode: Measured) - fn set_total_selected() -> Weight { - // Proof Size summary in bytes: - // Measured: `28` - // Estimated: `1513` - // Minimum execution time: 16_629_000 picoseconds. - Weight::from_parts(17_245_000, 1513) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: ParachainStaking CollatorCommission (r:1 w:1) - /// Proof Skipped: ParachainStaking CollatorCommission (max_values: Some(1), max_size: None, mode: Measured) - fn set_collator_commission() -> Weight { - // Proof Size summary in bytes: - // Measured: `27` - // Estimated: `1512` - // Minimum execution time: 15_586_000 picoseconds. - Weight::from_parts(16_060_000, 1512) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: ParachainStaking TotalSelected (r:1 w:0) - /// Proof Skipped: ParachainStaking TotalSelected (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking InflationConfig (r:1 w:1) - /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) - fn set_blocks_per_round() -> Weight { - // Proof Size summary in bytes: - // Measured: `116` - // Estimated: `3202` - // Minimum execution time: 52_085_000 picoseconds. - Weight::from_parts(52_439_000, 3202) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegatorState (r:1 w:0) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking TopDelegations (r:0 w:1) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking BottomDelegations (r:0 w:1) - /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) - /// The range of component `x` is `[3, 1000]`. - fn join_candidates(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1821 + x * (37 ±0)` - // Estimated: `27743 + x * (228 ±0)` - // Minimum execution time: 62_721_000 picoseconds. - Weight::from_parts(59_951_661, 27743) - // Standard Error: 1_080 - .saturating_add(Weight::from_parts(83_856, 0).saturating_mul(x.into())) - .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) - .saturating_add(Weight::from_parts(0, 228).saturating_mul(x.into())) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `x` is `[3, 1000]`. - fn schedule_leave_candidates(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `865 + x * (36 ±0)` - // Estimated: `6542 + x * (74 ±0)` - // Minimum execution time: 29_088_000 picoseconds. - Weight::from_parts(23_948_090, 6542) - // Standard Error: 1_107 - .saturating_add(Weight::from_parts(72_705, 0).saturating_mul(x.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - .saturating_add(Weight::from_parts(0, 74).saturating_mul(x.into())) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking TopDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegatorState (r:349 w:349) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: Balances Locks (r:350 w:350) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: System Account (r:350 w:350) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking BottomDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `x` is `[2, 350]`. - fn execute_leave_candidates(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `979 + x * (431 ±0)` - // Estimated: `30725 + x * (11823 ±0)` - // Minimum execution time: 102_273_000 picoseconds. - Weight::from_parts(102_546_000, 30725) - // Standard Error: 76_720 - .saturating_add(Weight::from_parts(33_831_394, 0).saturating_mul(x.into())) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().reads((3_u64).saturating_mul(x.into()))) - .saturating_add(RocksDbWeight::get().writes(5_u64)) - .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(x.into()))) - .saturating_add(Weight::from_parts(0, 11823).saturating_mul(x.into())) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `x` is `[3, 1000]`. - fn cancel_leave_candidates(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `833 + x * (36 ±0)` - // Estimated: `6478 + x * (74 ±0)` - // Minimum execution time: 28_142_000 picoseconds. - Weight::from_parts(22_767_262, 6478) - // Standard Error: 1_102 - .saturating_add(Weight::from_parts(73_806, 0).saturating_mul(x.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - .saturating_add(Weight::from_parts(0, 74).saturating_mul(x.into())) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - fn go_offline() -> Weight { - // Proof Size summary in bytes: - // Measured: `271` - // Estimated: `5492` - // Minimum execution time: 27_523_000 picoseconds. - Weight::from_parts(27_792_000, 5492) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - fn go_online() -> Weight { - // Proof Size summary in bytes: - // Measured: `234` - // Estimated: `5418` - // Minimum execution time: 27_667_000 picoseconds. - Weight::from_parts(27_972_000, 5418) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - fn candidate_bond_more() -> Weight { - // Proof Size summary in bytes: - // Measured: `527` - // Estimated: `16349` - // Minimum execution time: 56_424_000 picoseconds. - Weight::from_parts(57_028_000, 16349) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - fn schedule_candidate_bond_less() -> Weight { - // Proof Size summary in bytes: - // Measured: `171` - // Estimated: `3636` - // Minimum execution time: 22_764_000 picoseconds. - Weight::from_parts(23_511_000, 3636) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - fn execute_candidate_bond_less() -> Weight { - // Proof Size summary in bytes: - // Measured: `547` - // Estimated: `16409` - // Minimum execution time: 55_133_000 picoseconds. - Weight::from_parts(55_704_000, 16409) - .saturating_add(RocksDbWeight::get().reads(5_u64)) - .saturating_add(RocksDbWeight::get().writes(5_u64)) - } - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - fn cancel_candidate_bond_less() -> Weight { - // Proof Size summary in bytes: - // Measured: `191` - // Estimated: `3656` - // Minimum execution time: 20_773_000 picoseconds. - Weight::from_parts(21_485_000, 3656) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking TopDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `x` is `[3, 100]`. - /// The range of component `y` is `[2, 300]`. - fn delegate(x: u32, y: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `2479 + x * (79 ±0) + y * (38 ±0)` - // Estimated: `32988 + x * (405 ±0) + y * (195 ±0)` - // Minimum execution time: 94_976_000 picoseconds. - Weight::from_parts(83_764_148, 32988) - // Standard Error: 1_433 - .saturating_add(Weight::from_parts(154_670, 0).saturating_mul(x.into())) - // Standard Error: 470 - .saturating_add(Weight::from_parts(48_242, 0).saturating_mul(y.into())) - .saturating_add(RocksDbWeight::get().reads(7_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) - .saturating_add(Weight::from_parts(0, 405).saturating_mul(x.into())) - .saturating_add(Weight::from_parts(0, 195).saturating_mul(y.into())) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - fn schedule_leave_delegators() -> Weight { - // Proof Size summary in bytes: - // Measured: `107` - // Estimated: `7144` - // Minimum execution time: 28_255_000 picoseconds. - Weight::from_parts(28_539_000, 7144) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:99 w:99) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidateInfo (r:99 w:99) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking TopDelegations (r:99 w:99) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking AutoCompoundingDelegations (r:99 w:0) - /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// The range of component `x` is `[2, 100]`. - fn execute_leave_delegators(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `824 + x * (376 ±0)` - // Estimated: `34626 + x * (12238 ±1)` - // Minimum execution time: 88_582_000 picoseconds. - Weight::from_parts(88_972_000, 34626) - // Standard Error: 40_214 - .saturating_add(Weight::from_parts(30_393_572, 0).saturating_mul(x.into())) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(x.into()))) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - .saturating_add(RocksDbWeight::get().writes((3_u64).saturating_mul(x.into()))) - .saturating_add(Weight::from_parts(0, 12238).saturating_mul(x.into())) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - fn cancel_leave_delegators() -> Weight { - // Proof Size summary in bytes: - // Measured: `173` - // Estimated: `7276` - // Minimum execution time: 30_396_000 picoseconds. - Weight::from_parts(30_758_000, 7276) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - fn schedule_revoke_delegation() -> Weight { - // Proof Size summary in bytes: - // Measured: `107` - // Estimated: `7144` - // Minimum execution time: 27_434_000 picoseconds. - Weight::from_parts(27_725_000, 7144) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking TopDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - fn delegator_bond_more() -> Weight { - // Proof Size summary in bytes: - // Measured: `843` - // Estimated: `30221` - // Minimum execution time: 76_944_000 picoseconds. - Weight::from_parts(77_695_000, 30221) - .saturating_add(RocksDbWeight::get().reads(8_u64)) - .saturating_add(RocksDbWeight::get().writes(7_u64)) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - fn schedule_delegator_bond_less() -> Weight { - // Proof Size summary in bytes: - // Measured: `107` - // Estimated: `7144` - // Minimum execution time: 27_633_000 picoseconds. - Weight::from_parts(27_950_000, 7144) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:0) - /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking TopDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - fn execute_revoke_delegation() -> Weight { - // Proof Size summary in bytes: - // Measured: `964` - // Estimated: `35376` - // Minimum execution time: 92_054_000 picoseconds. - Weight::from_parts(93_161_000, 35376) - .saturating_add(RocksDbWeight::get().reads(9_u64)) - .saturating_add(RocksDbWeight::get().writes(8_u64)) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: ParachainStaking TopDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - fn execute_delegator_bond_less() -> Weight { - // Proof Size summary in bytes: - // Measured: `909` - // Estimated: `30617` - // Minimum execution time: 77_509_000 picoseconds. - Weight::from_parts(78_070_000, 30617) - .saturating_add(RocksDbWeight::get().reads(8_u64)) - .saturating_add(RocksDbWeight::get().writes(8_u64)) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - fn cancel_revoke_delegation() -> Weight { - // Proof Size summary in bytes: - // Measured: `173` - // Estimated: `7276` - // Minimum execution time: 27_469_000 picoseconds. - Weight::from_parts(28_047_000, 7276) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - fn cancel_delegator_bond_less() -> Weight { - // Proof Size summary in bytes: - // Measured: `173` - // Estimated: `7276` - // Minimum execution time: 28_572_000 picoseconds. - Weight::from_parts(28_806_000, 7276) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - } - /// Storage: ParachainStaking Points (r:1 w:0) - /// Proof Skipped: ParachainStaking Points (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking Staked (r:1 w:1) - /// Proof Skipped: ParachainStaking Staked (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking InflationConfig (r:1 w:0) - /// Proof Skipped: ParachainStaking InflationConfig (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking ParachainBondInfo (r:1 w:0) - /// Proof Skipped: ParachainStaking ParachainBondInfo (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: ParachainStaking CollatorCommission (r:1 w:0) - /// Proof Skipped: ParachainStaking CollatorCommission (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking DelayedPayouts (r:0 w:1) - /// Proof Skipped: ParachainStaking DelayedPayouts (max_values: None, max_size: None, mode: Measured) - fn prepare_staking_payouts() -> Weight { - // Proof Size summary in bytes: - // Measured: `380` - // Estimated: `17246` - // Minimum execution time: 43_338_000 picoseconds. - Weight::from_parts(43_786_000, 17246) - .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - /// Storage: ParachainStaking DelegationScheduledRequests (r:1 w:0) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking TopDelegations (r:1 w:0) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// The range of component `y` is `[0, 100]`. - fn get_rewardable_delegators(y: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `73 + y * (36 ±0)` - // Estimated: `7074 + y * (72 ±0)` - // Minimum execution time: 8_392_000 picoseconds. - Weight::from_parts(9_785_180, 7074) - // Standard Error: 388 - .saturating_add(Weight::from_parts(24_123, 0).saturating_mul(y.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(Weight::from_parts(0, 72).saturating_mul(y.into())) - } - /// Storage: ParachainStaking TotalSelected (r:1 w:0) - /// Proof Skipped: ParachainStaking TotalSelected (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:0) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidateInfo (r:51 w:0) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking DelegationScheduledRequests (r:51 w:0) - /// Proof Skipped: ParachainStaking DelegationScheduledRequests (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking TopDelegations (r:51 w:0) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking AutoCompoundingDelegations (r:51 w:0) - /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking SelectedCandidates (r:0 w:1) - /// Proof Skipped: ParachainStaking SelectedCandidates (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking AtStake (r:0 w:51) - /// Proof Skipped: ParachainStaking AtStake (max_values: None, max_size: None, mode: Measured) - /// The range of component `x` is `[0, 50]`. - /// The range of component `y` is `[0, 100]`. - fn select_top_candidates(x: u32, y: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0 + x * (3816 ±0) + y * (1800 ±0)` - // Estimated: `18950 + x * (21900 ±39) + y * (5112 ±19)` - // Minimum execution time: 32_303_000 picoseconds. - Weight::from_parts(32_680_000, 18950) - // Standard Error: 82_316 - .saturating_add(Weight::from_parts(23_158_353, 0).saturating_mul(x.into())) - // Standard Error: 41_048 - .saturating_add(Weight::from_parts(1_334_029, 0).saturating_mul(y.into())) - .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().reads((4_u64).saturating_mul(x.into()))) - .saturating_add(RocksDbWeight::get().writes(2_u64)) - .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(x.into()))) - .saturating_add(Weight::from_parts(0, 21900).saturating_mul(x.into())) - .saturating_add(Weight::from_parts(0, 5112).saturating_mul(y.into())) - } - /// Storage: ParachainStaking DelayedPayouts (r:1 w:0) - /// Proof Skipped: ParachainStaking DelayedPayouts (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking Points (r:1 w:0) - /// Proof Skipped: ParachainStaking Points (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking AtStake (r:2 w:1) - /// Proof Skipped: ParachainStaking AtStake (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking AwardedPts (r:1 w:1) - /// Proof Skipped: ParachainStaking AwardedPts (max_values: None, max_size: None, mode: Measured) - /// Storage: MoonbeamOrbiters OrbiterPerRound (r:1 w:0) - /// Proof Skipped: MoonbeamOrbiters OrbiterPerRound (max_values: None, max_size: None, mode: Measured) - /// Storage: System Account (r:301 w:301) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// The range of component `y` is `[0, 300]`. - fn pay_one_collator_reward(y: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1132 + y * (160 ±0)` - // Estimated: `28331 + y * (3396 ±0)` - // Minimum execution time: 58_105_000 picoseconds. - Weight::from_parts(53_052_308, 28331) - // Standard Error: 6_526 - .saturating_add(Weight::from_parts(19_017_961, 0).saturating_mul(y.into())) - .saturating_add(RocksDbWeight::get().reads(7_u64)) - .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(y.into()))) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - .saturating_add(RocksDbWeight::get().writes((1_u64).saturating_mul(y.into()))) - .saturating_add(Weight::from_parts(0, 3396).saturating_mul(y.into())) - } - fn base_on_initialize() -> Weight { - // Proof Size summary in bytes: - // Measured: `0` - // Estimated: `0` - // Minimum execution time: 2_008_000 picoseconds. - Weight::from_parts(2_065_000, 0) - } - /// Storage: ParachainStaking DelegatorState (r:1 w:0) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) - /// The range of component `x` is `[0, 300]`. - /// The range of component `y` is `[0, 100]`. - fn set_auto_compound(x: u32, y: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `671 + x * (22 ±0) + y * (36 ±0)` - // Estimated: `8054 + x * (46 ±0) + y * (72 ±0)` - // Minimum execution time: 29_102_000 picoseconds. - Weight::from_parts(26_155_259, 8054) - // Standard Error: 278 - .saturating_add(Weight::from_parts(49_717, 0).saturating_mul(x.into())) - // Standard Error: 833 - .saturating_add(Weight::from_parts(48_123, 0).saturating_mul(y.into())) - .saturating_add(RocksDbWeight::get().reads(2_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - .saturating_add(Weight::from_parts(0, 46).saturating_mul(x.into())) - .saturating_add(Weight::from_parts(0, 72).saturating_mul(y.into())) - } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - /// Storage: ParachainStaking DelegatorState (r:1 w:1) - /// Proof Skipped: ParachainStaking DelegatorState (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidateInfo (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidateInfo (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking AutoCompoundingDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking AutoCompoundingDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking BottomDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking BottomDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: Balances Locks (r:1 w:1) - /// Proof: Balances Locks (max_values: None, max_size: Some(1287), added: 3762, mode: MaxEncodedLen) - /// Storage: ParachainStaking Total (r:1 w:1) - /// Proof Skipped: ParachainStaking Total (max_values: Some(1), max_size: None, mode: Measured) - /// Storage: ParachainStaking TopDelegations (r:1 w:1) - /// Proof Skipped: ParachainStaking TopDelegations (max_values: None, max_size: None, mode: Measured) - /// Storage: ParachainStaking CandidatePool (r:1 w:1) - /// Proof Skipped: ParachainStaking CandidatePool (max_values: Some(1), max_size: None, mode: Measured) - /// The range of component `x` is `[0, 350]`. - /// The range of component `y` is `[0, 350]`. - /// The range of component `z` is `[0, 100]`. - fn delegate_with_auto_compound(x: u32, y: u32, z: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `0 + x * (58 ±0) + y * (21 ±0) + z * (41 ±0)` - // Estimated: `59323 + x * (145 ±0) + y * (132 ±0) + z * (873144491150315 ±3)` - // Minimum execution time: 100_647_000 picoseconds. - Weight::from_parts(84_809_337, 59323) - // Standard Error: 1_211 - .saturating_add(Weight::from_parts(15_186, 0).saturating_mul(x.into())) - // Standard Error: 1_211 - .saturating_add(Weight::from_parts(30_270, 0).saturating_mul(y.into())) - // Standard Error: 4_227 - .saturating_add(Weight::from_parts(173_069, 0).saturating_mul(z.into())) - .saturating_add(RocksDbWeight::get().reads(8_u64)) - .saturating_add(RocksDbWeight::get().writes(8_u64)) - .saturating_add(Weight::from_parts(0, 145).saturating_mul(x.into())) - .saturating_add(Weight::from_parts(0, 132).saturating_mul(y.into())) - .saturating_add(Weight::from_parts(0, 307).saturating_mul(z.into())) - } - /// Storage: System Account (r:1 w:1) - /// Proof: System Account (max_values: None, max_size: Some(116), added: 2591, mode: MaxEncodedLen) - fn mint_collator_reward() -> Weight { - // Proof Size summary in bytes: - // Measured: `128` - // Estimated: `3581` - // Minimum execution time: 24_224_000 picoseconds. - Weight::from_parts(24_514_000, 3581) - .saturating_add(RocksDbWeight::get().reads(1_u64)) - .saturating_add(RocksDbWeight::get().writes(1_u64)) - } -} \ No newline at end of file From 384b203ff3e73fdd34689a7ed1236b338fbe9947 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:50:56 +0200 Subject: [PATCH 57/80] Revert "feat: update to 0.9.42" This reverts commit cc1cb23429bb67967110a3738ebd47dc334c7c36. --- .maintain/frame-weight-template.hbs | 60 +- Cargo.lock | 1713 +++++++---------- Cargo.toml | 233 +-- README.md | 4 +- integration-tests/modified-penpal/Cargo.toml | 2 +- integration-tests/modified-penpal/src/lib.rs | 39 +- .../modified-penpal/src/xcm_config.rs | 46 +- integration-tests/src/lib.rs | 501 +++-- nodes/parachain/Cargo.toml | 1 - nodes/parachain/src/chain_spec.rs | 2 +- nodes/parachain/src/command.rs | 3 +- nodes/parachain/src/service.rs | 71 +- nodes/standalone/Cargo.toml | 5 +- nodes/standalone/src/chain_spec.rs | 2 +- nodes/standalone/src/command.rs | 33 +- nodes/standalone/src/service.rs | 86 +- pallets/funding/src/lib.rs | 5 +- pallets/funding/src/mock.rs | 4 - pallets/sandbox/src/mock.rs | 4 - runtimes/base/src/lib.rs | 21 +- runtimes/base/src/xcm_config.rs | 5 +- .../shared-configuration/src/weights/mod.rs | 1 - runtimes/standalone/Cargo.toml | 4 - runtimes/standalone/src/lib.rs | 116 +- runtimes/testnet/src/lib.rs | 63 +- runtimes/testnet/src/xcm_config.rs | 9 +- rust-toolchain.toml | 2 +- 27 files changed, 1340 insertions(+), 1695 deletions(-) diff --git a/.maintain/frame-weight-template.hbs b/.maintain/frame-weight-template.hbs index 5db697617..09a7fe280 100644 --- a/.maintain/frame-weight-template.hbs +++ b/.maintain/frame-weight-template.hbs @@ -20,10 +20,9 @@ //! Autogenerated weights for {{pallet}} //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION {{version}} -//! DATE: {{date}}, STEPS: `{{cmd.steps}}`, REPEAT: `{{cmd.repeat}}`, LOW RANGE: `{{cmd.lowest_range_values}}`, HIGH RANGE: `{{cmd.highest_range_values}}` -//! WORST CASE MAP SIZE: `{{cmd.worst_case_map_values}}` +//! DATE: {{date}}, STEPS: `{{cmd.steps}}`, REPEAT: {{cmd.repeat}}, LOW RANGE: `{{cmd.lowest_range_values}}`, HIGH RANGE: `{{cmd.highest_range_values}}` //! HOSTNAME: `{{hostname}}`, CPU: `{{cpuname}}` -//! EXECUTION: `{{cmd.execution}}`, WASM-EXECUTION: `{{cmd.wasm_execution}}`, CHAIN: `{{cmd.chain}}`, DB CACHE: `{{cmd.db_cache}}` +//! EXECUTION: {{cmd.execution}}, WASM-EXECUTION: {{cmd.wasm_execution}}, CHAIN: {{cmd.chain}}, DB CACHE: {{cmd.db_cache}} // Executed Command: {{#each args as |arg|}} @@ -33,10 +32,9 @@ #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] -#![allow(missing_docs)] use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use core::marker::PhantomData; +use sp_std::marker::PhantomData; /// Weight functions needed for {{pallet}}. pub trait WeightInfo { @@ -58,7 +56,7 @@ impl WeightInfo for SubstrateWeight { {{/if}} {{#each benchmarks as |benchmark|}} {{#each benchmark.comments as |comment|}} - /// {{comment}} + // {{comment}} {{/each}} {{#each benchmark.component_ranges as |range|}} /// The range of component `{{range.name}}` is `[{{range.min}}, {{range.max}}]`. @@ -68,29 +66,59 @@ impl WeightInfo for SubstrateWeight { {{~#each benchmark.components as |c| ~}} {{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}} ) -> Weight { - // Proof Size summary in bytes: - // Measured: `{{benchmark.base_recorded_proof_size}}{{#each benchmark.component_recorded_proof_size as |cp|}} + {{cp.name}} * ({{cp.slope}} ±{{underscore cp.error}}){{/each}}` - // Estimated: `{{benchmark.base_calculated_proof_size}}{{#each benchmark.component_calculated_proof_size as |cp|}} + {{cp.name}} * ({{cp.slope}} ±{{underscore cp.error}}){{/each}}` - // Minimum execution time: {{underscore benchmark.min_execution_time}}_000 picoseconds. - Weight::from_parts({{underscore benchmark.base_weight}}, {{benchmark.base_calculated_proof_size}}) + // Minimum execution time: {{underscore benchmark.min_execution_time}} nanoseconds. + Weight::from_ref_time({{underscore benchmark.base_weight}}) {{#each benchmark.component_weight as |cw|}} // Standard Error: {{underscore cw.error}} - .saturating_add(Weight::from_parts({{underscore cw.slope}}, 0).saturating_mul({{cw.name}}.into())) + .saturating_add(Weight::from_ref_time({{underscore cw.slope}}).saturating_mul({{cw.name}}.into())) {{/each}} {{#if (ne benchmark.base_reads "0")}} - .saturating_add(T::DbWeight::get().reads({{benchmark.base_reads}}_u64)) + .saturating_add(T::DbWeight::get().reads({{benchmark.base_reads}})) {{/if}} {{#each benchmark.component_reads as |cr|}} .saturating_add(T::DbWeight::get().reads(({{cr.slope}}_u64).saturating_mul({{cr.name}}.into()))) {{/each}} {{#if (ne benchmark.base_writes "0")}} - .saturating_add(T::DbWeight::get().writes({{benchmark.base_writes}}_u64)) + .saturating_add(T::DbWeight::get().writes({{benchmark.base_writes}})) {{/if}} {{#each benchmark.component_writes as |cw|}} .saturating_add(T::DbWeight::get().writes(({{cw.slope}}_u64).saturating_mul({{cw.name}}.into()))) {{/each}} - {{#each benchmark.component_calculated_proof_size as |cp|}} - .saturating_add(Weight::from_parts(0, {{cp.slope}}).saturating_mul({{cp.name}}.into())) + } + {{/each}} +} + +// For backwards compatibility and tests +impl WeightInfo for () { + {{#each benchmarks as |benchmark|}} + {{#each benchmark.comments as |comment|}} + // {{comment}} + {{/each}} + {{#each benchmark.component_ranges as |range|}} + /// The range of component `{{range.name}}` is `[{{range.min}}, {{range.max}}]`. + {{/each}} + fn {{benchmark.name~}} + ( + {{~#each benchmark.components as |c| ~}} + {{~#if (not c.is_used)}}_{{/if}}{{c.name}}: u32, {{/each~}} + ) -> Weight { + // Minimum execution time: {{underscore benchmark.min_execution_time}} nanoseconds. + Weight::from_ref_time({{underscore benchmark.base_weight}}) + {{#each benchmark.component_weight as |cw|}} + // Standard Error: {{underscore cw.error}} + .saturating_add(Weight::from_ref_time({{underscore cw.slope}}).saturating_mul({{cw.name}}.into())) + {{/each}} + {{#if (ne benchmark.base_reads "0")}} + .saturating_add(RocksDbWeight::get().reads({{benchmark.base_reads}})) + {{/if}} + {{#each benchmark.component_reads as |cr|}} + .saturating_add(RocksDbWeight::get().reads(({{cr.slope}}_u64).saturating_mul({{cr.name}}.into()))) + {{/each}} + {{#if (ne benchmark.base_writes "0")}} + .saturating_add(RocksDbWeight::get().writes({{benchmark.base_writes}})) + {{/if}} + {{#each benchmark.component_writes as |cw|}} + .saturating_add(RocksDbWeight::get().writes(({{cw.slope}}_u64).saturating_mul({{cw.name}}.into()))) {{/each}} } {{/each}} diff --git a/Cargo.lock b/Cargo.lock index 2faa2f1ea..9949fb987 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -388,37 +388,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" -[[package]] -name = "assets-common" -version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" -dependencies = [ - "cumulus-primitives-core", - "frame-support", - "log", - "pallet-xcm", - "parachains-common", - "parity-scale-codec", - "scale-info", - "sp-api", - "sp-std", - "substrate-wasm-builder", - "xcm", - "xcm-builder", - "xcm-executor", -] - -[[package]] -name = "async-channel" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener", - "futures-core", -] - [[package]] name = "async-io" version = "1.13.0" @@ -448,17 +417,6 @@ dependencies = [ "event-listener", ] -[[package]] -name = "async-recursion" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.25", -] - [[package]] name = "async-trait" version = "0.1.71" @@ -534,10 +492,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" [[package]] -name = "base16ct" +name = "base58" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" [[package]] name = "base64" @@ -566,10 +524,63 @@ dependencies = [ "serde", ] +[[package]] +name = "beefy-gadget" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +dependencies = [ + "array-bytes 4.2.0", + "async-trait", + "fnv", + "futures", + "log", + "parity-scale-codec", + "parking_lot 0.12.1", + "sc-client-api", + "sc-consensus", + "sc-keystore", + "sc-network", + "sc-network-common", + "sc-network-gossip", + "sc-utils", + "sp-api", + "sp-application-crypto", + "sp-arithmetic", + "sp-beefy", + "sp-blockchain", + "sp-consensus", + "sp-core", + "sp-keystore", + "sp-mmr-primitives", + "sp-runtime", + "substrate-prometheus-endpoint", + "thiserror", + "wasm-timer", +] + +[[package]] +name = "beefy-gadget-rpc" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +dependencies = [ + "beefy-gadget", + "futures", + "jsonrpsee", + "log", + "parity-scale-codec", + "parking_lot 0.12.1", + "sc-rpc", + "serde", + "sp-beefy", + "sp-core", + "sp-runtime", + "thiserror", +] + [[package]] name = "binary-merkle-tree" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "hash-db", "log", @@ -832,9 +843,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.3" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" +checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" dependencies = [ "serde", ] @@ -1093,19 +1104,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "console" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" -dependencies = [ - "encode_unicode", - "lazy_static", - "libc", - "unicode-width", - "windows-sys 0.45.0", -] - [[package]] name = "const-oid" version = "0.9.4" @@ -1377,18 +1375,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "crypto-bigint" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4c2f4e1afd912bc40bfd6fed5d9dc1f288e0ba01bfcc835cc5bc3eb13efe15" -dependencies = [ - "generic-array 0.14.7", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - [[package]] name = "crypto-common" version = "0.1.6" @@ -1441,7 +1427,7 @@ dependencies = [ [[package]] name = "cumulus-client-cli" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "clap", "parity-scale-codec", @@ -1456,7 +1442,7 @@ dependencies = [ [[package]] name = "cumulus-client-collator" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "cumulus-client-consensus-common", "cumulus-client-network", @@ -1479,7 +1465,7 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-aura" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "async-trait", "cumulus-client-consensus-common", @@ -1508,7 +1494,7 @@ dependencies = [ [[package]] name = "cumulus-client-consensus-common" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "async-trait", "cumulus-client-pov-recovery", @@ -1532,7 +1518,7 @@ dependencies = [ [[package]] name = "cumulus-client-network" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "async-trait", "cumulus-relay-chain-interface", @@ -1555,7 +1541,7 @@ dependencies = [ [[package]] name = "cumulus-client-pov-recovery" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -1579,7 +1565,7 @@ dependencies = [ [[package]] name = "cumulus-client-service" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "cumulus-client-cli", "cumulus-client-collator", @@ -1591,11 +1577,11 @@ dependencies = [ "cumulus-relay-chain-interface", "cumulus-relay-chain-minimal-node", "futures", + "parking_lot 0.12.1", "polkadot-primitives", "sc-client-api", "sc-consensus", "sc-network", - "sc-network-sync", "sc-network-transactions", "sc-rpc", "sc-service", @@ -1614,7 +1600,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-aura-ext" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "frame-support", "frame-system", @@ -1630,7 +1616,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-dmp-queue" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -1647,7 +1633,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-parachain-system" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "bytes", "cumulus-pallet-parachain-system-proc-macro", @@ -1676,18 +1662,18 @@ dependencies = [ [[package]] name = "cumulus-pallet-parachain-system-proc-macro" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.25", + "syn 1.0.109", ] [[package]] name = "cumulus-pallet-session-benchmarking" version = "3.0.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "frame-benchmarking", "frame-support", @@ -1701,7 +1687,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcm" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -1717,7 +1703,7 @@ dependencies = [ [[package]] name = "cumulus-pallet-xcmp-queue" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "cumulus-primitives-core", "frame-benchmarking", @@ -1738,13 +1724,12 @@ dependencies = [ [[package]] name = "cumulus-primitives-core" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "parity-scale-codec", "polkadot-core-primitives", "polkadot-parachain", "polkadot-primitives", - "scale-info", "sp-api", "sp-runtime", "sp-std", @@ -1755,7 +1740,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-parachain-inherent" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -1778,7 +1763,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-timestamp" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "cumulus-primitives-core", "futures", @@ -1791,7 +1776,7 @@ dependencies = [ [[package]] name = "cumulus-primitives-utility" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -1809,7 +1794,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-inprocess-interface" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -1834,7 +1819,7 @@ dependencies = [ [[package]] name = "cumulus-relay-chain-interface" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -1842,17 +1827,19 @@ dependencies = [ "jsonrpsee-core", "parity-scale-codec", "polkadot-overseer", + "polkadot-service", "sc-client-api", "sp-api", "sp-blockchain", "sp-state-machine", "thiserror", + "tokio", ] [[package]] name = "cumulus-relay-chain-minimal-node" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "array-bytes 6.1.0", "async-trait", @@ -1861,23 +1848,24 @@ dependencies = [ "cumulus-relay-chain-rpc-interface", "futures", "lru 0.9.0", - "polkadot-availability-recovery", - "polkadot-collator-protocol", "polkadot-core-primitives", "polkadot-network-bridge", - "polkadot-node-collation-generation", - "polkadot-node-core-runtime-api", "polkadot-node-network-protocol", "polkadot-node-subsystem-util", "polkadot-overseer", "polkadot-primitives", + "polkadot-service", "sc-authority-discovery", "sc-client-api", + "sc-consensus", + "sc-keystore", "sc-network", "sc-network-common", "sc-service", + "sc-telemetry", "sc-tracing", - "sc-utils", + "sc-transaction-pool", + "sc-transaction-pool-api", "sp-api", "sp-blockchain", "sp-consensus", @@ -1885,12 +1873,13 @@ dependencies = [ "sp-runtime", "tokio", "tracing", + "url", ] [[package]] name = "cumulus-relay-chain-rpc-interface" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "async-trait", "cumulus-primitives-core", @@ -1900,10 +1889,9 @@ dependencies = [ "jsonrpsee", "lru 0.9.0", "parity-scale-codec", - "polkadot-overseer", + "polkadot-service", "sc-client-api", "sc-rpc-api", - "sc-service", "serde", "serde_json", "sp-api", @@ -1920,7 +1908,7 @@ dependencies = [ [[package]] name = "cumulus-test-relay-sproof-builder" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "cumulus-primitives-core", "parity-scale-codec", @@ -2086,16 +2074,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "der" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946" -dependencies = [ - "const-oid", - "zeroize", -] - [[package]] name = "der-parser" version = "7.0.0" @@ -2221,7 +2199,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", - "const-oid", "crypto-common", "subtle", ] @@ -2329,24 +2306,10 @@ version = "0.14.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" dependencies = [ - "der 0.6.1", - "elliptic-curve 0.12.3", - "rfc6979 0.3.1", - "signature 1.6.4", -] - -[[package]] -name = "ecdsa" -version = "0.16.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428" -dependencies = [ - "der 0.7.7", - "digest 0.10.7", - "elliptic-curve 0.13.5", - "rfc6979 0.4.0", - "signature 2.1.0", - "spki 0.7.2", + "der", + "elliptic-curve", + "rfc6979", + "signature", ] [[package]] @@ -2355,7 +2318,7 @@ version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" dependencies = [ - "signature 1.6.4", + "signature", ] [[package]] @@ -2398,47 +2361,22 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" dependencies = [ - "base16ct 0.1.1", - "crypto-bigint 0.4.9", - "der 0.6.1", + "base16ct", + "crypto-bigint", + "der", "digest 0.10.7", - "ff 0.12.1", + "ff", "generic-array 0.14.7", - "group 0.12.1", + "group", "hkdf", "pem-rfc7468", - "pkcs8 0.9.0", + "pkcs8", "rand_core 0.6.4", - "sec1 0.3.0", + "sec1", "subtle", "zeroize", ] -[[package]] -name = "elliptic-curve" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" -dependencies = [ - "base16ct 0.2.0", - "crypto-bigint 0.5.2", - "digest 0.10.7", - "ff 0.13.0", - "generic-array 0.14.7", - "group 0.13.0", - "pkcs8 0.10.2", - "rand_core 0.6.4", - "sec1 0.7.2", - "subtle", - "zeroize", -] - -[[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - [[package]] name = "enum-as-inner" version = "0.5.1" @@ -2573,18 +2511,6 @@ name = "expander" version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3774182a5df13c3d1690311ad32fbe913feef26baba609fa2dd5f72042bd2ab6" -dependencies = [ - "blake2", - "fs-err", - "proc-macro2", - "quote", -] - -[[package]] -name = "expander" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f360349150728553f92e4c997a16af8915f418d3a0f21b440d34c5632f16ed84" dependencies = [ "blake2", "fs-err", @@ -2593,19 +2519,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "expander" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f86a749cf851891866c10515ef6c299b5c69661465e9c3bbe7e07a2b77fb0f7" -dependencies = [ - "blake2", - "fs-err", - "proc-macro2", - "quote", - "syn 2.0.25", -] - [[package]] name = "fake-simd" version = "0.1.2" @@ -2671,16 +2584,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "ff" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "fiat-crypto" version = "0.1.20" @@ -2772,7 +2675,7 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "fork-tree" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", ] @@ -2795,7 +2698,7 @@ checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" [[package]] name = "frame-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "frame-support-procedural", @@ -2820,7 +2723,7 @@ dependencies = [ [[package]] name = "frame-benchmarking-cli" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "Inflector", "array-bytes 4.2.0", @@ -2867,18 +2770,18 @@ dependencies = [ [[package]] name = "frame-election-provider-solution-type" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.25", + "syn 1.0.109", ] [[package]] name = "frame-election-provider-support" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-election-provider-solution-type", "frame-support", @@ -2895,7 +2798,7 @@ dependencies = [ [[package]] name = "frame-executive" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "frame-system", @@ -2924,19 +2827,15 @@ dependencies = [ [[package]] name = "frame-remote-externalities" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ - "async-recursion", "futures", - "indicatif", - "jsonrpsee", "log", "parity-scale-codec", "serde", "sp-core", "sp-io", "sp-runtime", - "spinners", "substrate-rpc-client", "tokio", ] @@ -2944,10 +2843,9 @@ dependencies = [ [[package]] name = "frame-support" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "bitflags 1.3.2", - "environmental", "frame-metadata", "frame-support-procedural", "impl-trait-for-tuples", @@ -2977,45 +2875,44 @@ dependencies = [ [[package]] name = "frame-support-procedural" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "Inflector", "cfg-expr", "derive-syn-parse", "frame-support-procedural-tools", "itertools", - "proc-macro-warning", "proc-macro2", "quote", - "syn 2.0.25", + "syn 1.0.109", ] [[package]] name = "frame-support-procedural-tools" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support-procedural-tools-derive", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.25", + "syn 1.0.109", ] [[package]] name = "frame-support-procedural-tools-derive" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 1.0.109", ] [[package]] name = "frame-system" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "log", @@ -3033,7 +2930,7 @@ dependencies = [ [[package]] name = "frame-system-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -3048,7 +2945,7 @@ dependencies = [ [[package]] name = "frame-system-rpc-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "sp-api", @@ -3057,7 +2954,7 @@ dependencies = [ [[package]] name = "frame-try-runtime" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "parity-scale-codec", @@ -3082,16 +2979,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "fs4" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eeb4ed9e12f43b7fa0baae3f9cdda28352770132ef2e09a23760c29cae8bd47" -dependencies = [ - "rustix 0.38.4", - "windows-sys 0.48.0", -] - [[package]] name = "funty" version = "2.0.0" @@ -3246,7 +3133,6 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum 1.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "version_check", - "zeroize", ] [[package]] @@ -3343,18 +3229,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" dependencies = [ - "ff 0.12.1", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff 0.13.0", + "ff", "rand_core 0.6.4", "subtle", ] @@ -3394,9 +3269,9 @@ dependencies = [ [[package]] name = "hash-db" -version = "0.16.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e7d7786361d7425ae2fe4f9e407eb0efaa0840f5212d109cc018c40c35c6ab4" +checksum = "d23bd4e7b5eda0d0f3a307e8b381fdc8ba9000f26fbe912250c0a4cc3956364a" [[package]] name = "hash256-std-hasher" @@ -3464,12 +3339,6 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" -[[package]] -name = "hex-literal" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" - [[package]] name = "hkdf" version = "0.12.3" @@ -3613,7 +3482,6 @@ dependencies = [ "rustls-native-certs", "tokio", "tokio-rustls", - "webpki-roots", ] [[package]] @@ -3745,19 +3613,6 @@ dependencies = [ "hashbrown 0.14.0", ] -[[package]] -name = "indicatif" -version = "0.17.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ff8cc23a7393a397ed1d7f56e6365cba772aba9f9912ab968b03043c395d057" -dependencies = [ - "console", - "instant", - "number_prefix", - "portable-atomic", - "unicode-width", -] - [[package]] name = "inout" version = "0.1.3" @@ -3928,7 +3783,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d291e3a5818a2384645fd9756362e6d89cf0541b0b916fa7702ea4a9833608e" dependencies = [ "jsonrpsee-core", - "jsonrpsee-http-client", "jsonrpsee-proc-macros", "jsonrpsee-server", "jsonrpsee-types", @@ -3985,25 +3839,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "jsonrpsee-http-client" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc345b0a43c6bc49b947ebeb936e886a419ee3d894421790c969cc56040542ad" -dependencies = [ - "async-trait", - "hyper", - "hyper-rustls", - "jsonrpsee-core", - "jsonrpsee-types", - "rustc-hash", - "serde", - "serde_json", - "thiserror", - "tokio", - "tracing", -] - [[package]] name = "jsonrpsee-proc-macros" version = "0.16.2" @@ -4067,14 +3902,13 @@ dependencies = [ [[package]] name = "k256" -version = "0.13.1" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" +checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" dependencies = [ "cfg-if", - "ecdsa 0.16.7", - "elliptic-curve 0.13.5", - "once_cell", + "ecdsa", + "elliptic-curve", "sha2 0.10.7", ] @@ -4089,8 +3923,8 @@ dependencies = [ [[package]] name = "kusama-runtime" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "bitvec", "frame-benchmarking", @@ -4101,7 +3935,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "kusama-runtime-constants", "log", "pallet-authority-discovery", @@ -4163,9 +3997,9 @@ dependencies = [ "sp-api", "sp-arithmetic", "sp-authority-discovery", + "sp-beefy", "sp-block-builder", "sp-consensus-babe", - "sp-consensus-beefy", "sp-core", "sp-inherents", "sp-io", @@ -4187,8 +4021,8 @@ dependencies = [ [[package]] name = "kusama-runtime-constants" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "frame-support", "polkadot-primitives", @@ -4220,9 +4054,9 @@ dependencies = [ [[package]] name = "kvdb-rocksdb" -version = "0.18.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe7a749456510c45f795e8b04a6a3e0976d0139213ecbf465843830ad55e2217" +checksum = "2182b8219fee6bd83aacaab7344e840179ae079d5216aa4e249b4d704646a844" dependencies = [ "kvdb", "num_cpus", @@ -4331,7 +4165,7 @@ dependencies = [ "prost-build", "rand 0.8.5", "rw-stream-sink", - "sec1 0.3.0", + "sec1", "sha2 0.10.7", "smallvec", "thiserror", @@ -4727,9 +4561,9 @@ dependencies = [ [[package]] name = "librocksdb-sys" -version = "0.10.0+7.9.2" +version = "0.8.3+7.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fe4d5874f5ff2bc616e55e8c6086d478fcda13faf9495768a4aa1c22042d30b" +checksum = "557b255ff04123fcc176162f56ed0c9cd42d8f357cf55b3fabeb60f7413741b3" dependencies = [ "bindgen", "bzip2-sys", @@ -4922,12 +4756,6 @@ dependencies = [ "libc", ] -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - [[package]] name = "match_cfg" version = "0.1.0" @@ -5001,6 +4829,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" +dependencies = [ + "autocfg", +] + [[package]] name = "memoffset" version = "0.9.0" @@ -5012,11 +4849,12 @@ dependencies = [ [[package]] name = "memory-db" -version = "0.32.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808b50db46293432a45e63bc15ea51e0ab4c0a1647b8eb114e31a3e698dd6fbe" +checksum = "5e0c7cba9ce19ac7ffd2053ac9f49843bbd3f4318feedfd74e85c19d5fb0ba66" dependencies = [ "hash-db", + "hashbrown 0.12.3", ] [[package]] @@ -5077,7 +4915,7 @@ dependencies = [ [[package]] name = "mmr-gadget" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "futures", "log", @@ -5085,9 +4923,9 @@ dependencies = [ "sc-client-api", "sc-offchain", "sp-api", + "sp-beefy", "sp-blockchain", "sp-consensus", - "sp-consensus-beefy", "sp-core", "sp-mmr-primitives", "sp-runtime", @@ -5096,7 +4934,7 @@ dependencies = [ [[package]] name = "mmr-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "anyhow", "jsonrpsee", @@ -5366,6 +5204,20 @@ dependencies = [ "memoffset 0.6.5", ] +[[package]] +name = "nix" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "memoffset 0.7.1", + "pin-utils", + "static_assertions", +] + [[package]] name = "nohash-hasher" version = "0.2.0" @@ -5459,12 +5311,6 @@ dependencies = [ "libc", ] -[[package]] -name = "number_prefix" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" - [[package]] name = "object" version = "0.29.0" @@ -5530,9 +5376,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "orchestra" -version = "0.0.5" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "227585216d05ba65c7ab0a0450a3cf2cbd81a98862a54c4df8e14d5ac6adb015" +checksum = "17e7d5b6bb115db09390bed8842c94180893dd83df3dfce7354f2a2aa090a4ee" dependencies = [ "async-trait", "dyn-clonable", @@ -5547,9 +5393,9 @@ dependencies = [ [[package]] name = "orchestra-proc-macro" -version = "0.0.5" +version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2871aadd82a2c216ee68a69837a526dfe788ecbe74c4c5038a6acdbff6653066" +checksum = "c2af4dabb2286b0be0e9711d2d24e25f6217048b71210cffd3daddc3b5c84e1f" dependencies = [ "expander 0.0.6", "itertools", @@ -5575,8 +5421,8 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" dependencies = [ - "ecdsa 0.14.8", - "elliptic-curve 0.12.3", + "ecdsa", + "elliptic-curve", "sha2 0.10.7", ] @@ -5586,8 +5432,8 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa" dependencies = [ - "ecdsa 0.14.8", - "elliptic-curve 0.12.3", + "ecdsa", + "elliptic-curve", "sha2 0.10.7", ] @@ -5604,7 +5450,7 @@ dependencies = [ [[package]] name = "pallet-asset-tx-payment" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -5622,7 +5468,7 @@ dependencies = [ [[package]] name = "pallet-assets" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -5637,7 +5483,7 @@ dependencies = [ [[package]] name = "pallet-aura" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "frame-system", @@ -5653,7 +5499,7 @@ dependencies = [ [[package]] name = "pallet-authority-discovery" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "frame-system", @@ -5669,7 +5515,7 @@ dependencies = [ [[package]] name = "pallet-authorship" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "frame-system", @@ -5683,7 +5529,7 @@ dependencies = [ [[package]] name = "pallet-babe" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -5696,7 +5542,7 @@ dependencies = [ "scale-info", "sp-application-crypto", "sp-consensus-babe", - "sp-core", + "sp-consensus-vrf", "sp-io", "sp-runtime", "sp-session", @@ -5707,7 +5553,7 @@ dependencies = [ [[package]] name = "pallet-bags-list" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -5727,7 +5573,7 @@ dependencies = [ [[package]] name = "pallet-balances" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -5742,7 +5588,7 @@ dependencies = [ [[package]] name = "pallet-beefy" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "frame-system", @@ -5751,7 +5597,7 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "sp-consensus-beefy", + "sp-beefy", "sp-runtime", "sp-session", "sp-staking", @@ -5761,7 +5607,7 @@ dependencies = [ [[package]] name = "pallet-beefy-mmr" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "array-bytes 4.2.0", "binary-merkle-tree", @@ -5775,7 +5621,7 @@ dependencies = [ "scale-info", "serde", "sp-api", - "sp-consensus-beefy", + "sp-beefy", "sp-core", "sp-io", "sp-runtime", @@ -5785,7 +5631,7 @@ dependencies = [ [[package]] name = "pallet-bounties" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -5803,7 +5649,7 @@ dependencies = [ [[package]] name = "pallet-child-bounties" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -5822,7 +5668,7 @@ dependencies = [ [[package]] name = "pallet-collator-selection" version = "3.0.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "frame-benchmarking", "frame-support", @@ -5841,7 +5687,7 @@ dependencies = [ [[package]] name = "pallet-collective" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -5858,7 +5704,7 @@ dependencies = [ [[package]] name = "pallet-conviction-voting" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "assert_matches", "frame-benchmarking", @@ -5875,7 +5721,7 @@ dependencies = [ [[package]] name = "pallet-democracy" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -5893,7 +5739,7 @@ dependencies = [ [[package]] name = "pallet-election-provider-multi-phase" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -5916,7 +5762,7 @@ dependencies = [ [[package]] name = "pallet-election-provider-support-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -5929,7 +5775,7 @@ dependencies = [ [[package]] name = "pallet-elections-phragmen" version = "5.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -5947,7 +5793,7 @@ dependencies = [ [[package]] name = "pallet-fast-unstake" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -5984,7 +5830,7 @@ dependencies = [ [[package]] name = "pallet-grandpa" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -5995,8 +5841,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "sp-application-crypto", - "sp-consensus-grandpa", "sp-core", + "sp-finality-grandpa", "sp-io", "sp-runtime", "sp-session", @@ -6007,7 +5853,7 @@ dependencies = [ [[package]] name = "pallet-identity" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "enumflags2", "frame-benchmarking", @@ -6023,7 +5869,7 @@ dependencies = [ [[package]] name = "pallet-im-online" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6043,7 +5889,7 @@ dependencies = [ [[package]] name = "pallet-indices" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6060,7 +5906,7 @@ dependencies = [ [[package]] name = "pallet-insecure-randomness-collective-flip" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "frame-system", @@ -6074,7 +5920,7 @@ dependencies = [ [[package]] name = "pallet-membership" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6091,7 +5937,7 @@ dependencies = [ [[package]] name = "pallet-mmr" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6108,7 +5954,7 @@ dependencies = [ [[package]] name = "pallet-multisig" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6124,7 +5970,7 @@ dependencies = [ [[package]] name = "pallet-nis" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6140,7 +5986,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools" version = "1.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "frame-system", @@ -6157,7 +6003,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-benchmarking" version = "1.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -6177,7 +6023,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-runtime-api" version = "1.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "pallet-nomination-pools", "parity-scale-codec", @@ -6188,7 +6034,7 @@ dependencies = [ [[package]] name = "pallet-offences" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "frame-system", @@ -6205,7 +6051,7 @@ dependencies = [ [[package]] name = "pallet-offences-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -6229,7 +6075,7 @@ dependencies = [ [[package]] name = "pallet-parachain-staking" version = "3.0.0" -source = "git+https://gitlab.com/Omegabit/stake-patch?branch=0.9.42#a9b481bf9f658f45db37fa9c8e26f31d41550518" +source = "git+https://gitlab.com/Omegabit/stake-patch#28a788327c7dbf408060cbe0b1f0109bd8533260" dependencies = [ "frame-benchmarking", "frame-support", @@ -6249,7 +6095,7 @@ dependencies = [ [[package]] name = "pallet-preimage" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6266,7 +6112,7 @@ dependencies = [ [[package]] name = "pallet-proxy" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6281,7 +6127,7 @@ dependencies = [ [[package]] name = "pallet-ranked-collective" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6299,7 +6145,7 @@ dependencies = [ [[package]] name = "pallet-recovery" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6314,7 +6160,7 @@ dependencies = [ [[package]] name = "pallet-referenda" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "assert_matches", "frame-benchmarking", @@ -6355,7 +6201,7 @@ dependencies = [ [[package]] name = "pallet-scheduler" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6372,7 +6218,7 @@ dependencies = [ [[package]] name = "pallet-session" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "frame-system", @@ -6393,7 +6239,7 @@ dependencies = [ [[package]] name = "pallet-session-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6409,7 +6255,7 @@ dependencies = [ [[package]] name = "pallet-society" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "frame-system", @@ -6423,7 +6269,7 @@ dependencies = [ [[package]] name = "pallet-staking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -6446,18 +6292,18 @@ dependencies = [ [[package]] name = "pallet-staking-reward-curve" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.25", + "syn 1.0.109", ] [[package]] name = "pallet-staking-reward-fn" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "log", "sp-arithmetic", @@ -6466,7 +6312,7 @@ dependencies = [ [[package]] name = "pallet-staking-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "sp-api", @@ -6475,7 +6321,7 @@ dependencies = [ [[package]] name = "pallet-state-trie-migration" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6492,7 +6338,7 @@ dependencies = [ [[package]] name = "pallet-sudo" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "frame-system", @@ -6506,7 +6352,7 @@ dependencies = [ [[package]] name = "pallet-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6524,7 +6370,7 @@ dependencies = [ [[package]] name = "pallet-tips" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6543,7 +6389,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-support", "frame-system", @@ -6559,7 +6405,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "jsonrpsee", "pallet-transaction-payment-rpc-runtime-api", @@ -6575,7 +6421,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "pallet-transaction-payment", "parity-scale-codec", @@ -6587,7 +6433,7 @@ dependencies = [ [[package]] name = "pallet-treasury" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6604,7 +6450,7 @@ dependencies = [ [[package]] name = "pallet-uniques" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6619,7 +6465,7 @@ dependencies = [ [[package]] name = "pallet-utility" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6635,7 +6481,7 @@ dependencies = [ [[package]] name = "pallet-vesting" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6650,7 +6496,7 @@ dependencies = [ [[package]] name = "pallet-whitelist" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-benchmarking", "frame-support", @@ -6664,8 +6510,8 @@ dependencies = [ [[package]] name = "pallet-xcm" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "bounded-collections", "frame-benchmarking", @@ -6685,8 +6531,8 @@ dependencies = [ [[package]] name = "pallet-xcm-benchmarks" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "frame-benchmarking", "frame-support", @@ -6705,7 +6551,7 @@ dependencies = [ [[package]] name = "parachain-info" version = "0.1.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "cumulus-primitives-core", "frame-support", @@ -6717,7 +6563,7 @@ dependencies = [ [[package]] name = "parachains-common" version = "1.0.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ "cumulus-primitives-utility", "frame-support", @@ -6922,7 +6768,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.3.4", + "hex-literal", "log", "pallet-asset-tx-payment", "pallet-assets", @@ -7065,18 +6911,8 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" dependencies = [ - "der 0.6.1", - "spki 0.6.0", -] - -[[package]] -name = "pkcs8" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der 0.7.7", - "spki 0.7.2", + "der", + "spki", ] [[package]] @@ -7117,7 +6953,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.3.4", + "hex-literal", "log", "pallet-aura", "pallet-authorship", @@ -7174,7 +7010,7 @@ dependencies = [ "cumulus-relay-chain-minimal-node", "frame-benchmarking", "frame-benchmarking-cli", - "hex-literal 0.3.4", + "hex-literal", "jsonrpsee", "log", "pallet-transaction-payment-rpc", @@ -7192,7 +7028,6 @@ dependencies = [ "sc-executor", "sc-network", "sc-network-common", - "sc-network-sync", "sc-rpc", "sc-rpc-api", "sc-service", @@ -7242,7 +7077,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.3.4", + "hex-literal", "log", "pallet-asset-tx-payment", "pallet-assets", @@ -7313,8 +7148,8 @@ dependencies = [ "sc-client-api", "sc-consensus", "sc-consensus-aura", - "sc-consensus-grandpa", "sc-executor", + "sc-finality-grandpa", "sc-keystore", "sc-rpc", "sc-rpc-api", @@ -7328,8 +7163,8 @@ dependencies = [ "sp-blockchain", "sp-consensus", "sp-consensus-aura", - "sp-consensus-grandpa", "sp-core", + "sp-finality-grandpa", "sp-inherents", "sp-keyring", "sp-runtime", @@ -7350,7 +7185,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.3.4", + "hex-literal", "pallet-assets", "pallet-aura", "pallet-authorship", @@ -7372,11 +7207,9 @@ dependencies = [ "pallet-vesting", "parity-scale-codec", "scale-info", - "shared-configuration", "sp-api", "sp-block-builder", "sp-consensus-aura", - "sp-consensus-grandpa", "sp-core", "sp-inherents", "sp-offchain", @@ -7390,11 +7223,10 @@ dependencies = [ [[package]] name = "polkadot-approval-distribution" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "futures", - "polkadot-node-jaeger", "polkadot-node-metrics", "polkadot-node-network-protocol", "polkadot-node-primitives", @@ -7406,8 +7238,8 @@ dependencies = [ [[package]] name = "polkadot-availability-bitfield-distribution" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "futures", "polkadot-node-network-protocol", @@ -7420,8 +7252,8 @@ dependencies = [ [[package]] name = "polkadot-availability-distribution" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "derive_more", "fatality", @@ -7443,8 +7275,8 @@ dependencies = [ [[package]] name = "polkadot-availability-recovery" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "fatality", "futures", @@ -7464,15 +7296,15 @@ dependencies = [ [[package]] name = "polkadot-cli" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "clap", "frame-benchmarking-cli", "futures", "log", "polkadot-client", - "polkadot-node-core-pvf-worker", + "polkadot-node-core-pvf", "polkadot-node-metrics", "polkadot-performance-test", "polkadot-service", @@ -7485,7 +7317,6 @@ dependencies = [ "sp-core", "sp-io", "sp-keyring", - "sp-maybe-compressed-blob", "substrate-build-script-utils", "thiserror", "try-runtime-cli", @@ -7493,8 +7324,8 @@ dependencies = [ [[package]] name = "polkadot-client" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "async-trait", "frame-benchmarking", @@ -7515,13 +7346,13 @@ dependencies = [ "sc-service", "sp-api", "sp-authority-discovery", + "sp-beefy", "sp-block-builder", "sp-blockchain", "sp-consensus", "sp-consensus-babe", - "sp-consensus-beefy", - "sp-consensus-grandpa", "sp-core", + "sp-finality-grandpa", "sp-inherents", "sp-keyring", "sp-mmr-primitives", @@ -7535,8 +7366,8 @@ dependencies = [ [[package]] name = "polkadot-collator-protocol" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "always-assert", "bitvec", @@ -7557,8 +7388,8 @@ dependencies = [ [[package]] name = "polkadot-core-primitives" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "parity-scale-codec", "scale-info", @@ -7569,8 +7400,8 @@ dependencies = [ [[package]] name = "polkadot-dispute-distribution" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "derive_more", "fatality", @@ -7594,8 +7425,8 @@ dependencies = [ [[package]] name = "polkadot-erasure-coding" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "parity-scale-codec", "polkadot-node-primitives", @@ -7608,8 +7439,8 @@ dependencies = [ [[package]] name = "polkadot-gossip-support" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "futures", "futures-timer", @@ -7628,8 +7459,8 @@ dependencies = [ [[package]] name = "polkadot-network-bridge" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "always-assert", "async-trait", @@ -7644,6 +7475,7 @@ dependencies = [ "polkadot-overseer", "polkadot-primitives", "sc-network", + "sc-network-common", "sp-consensus", "thiserror", "tracing-gum", @@ -7651,8 +7483,8 @@ dependencies = [ [[package]] name = "polkadot-node-collation-generation" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "futures", "parity-scale-codec", @@ -7669,8 +7501,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-approval-voting" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "bitvec", "derive_more", @@ -7698,8 +7530,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-av-store" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "bitvec", "futures", @@ -7719,8 +7551,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-backing" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "bitvec", "fatality", @@ -7738,8 +7570,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-bitfield-signing" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "futures", "polkadot-node-subsystem", @@ -7753,8 +7585,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-candidate-validation" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "async-trait", "futures", @@ -7773,8 +7605,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-api" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "futures", "polkadot-node-metrics", @@ -7788,8 +7620,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-selection" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "futures", "futures-timer", @@ -7805,8 +7637,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-dispute-coordinator" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "fatality", "futures", @@ -7824,8 +7656,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-parachains-inherent" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "async-trait", "futures", @@ -7841,8 +7673,8 @@ dependencies = [ [[package]] name = "polkadot-node-core-provisioner" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "bitvec", "fatality", @@ -7859,10 +7691,12 @@ dependencies = [ [[package]] name = "polkadot-node-core-pvf" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "always-assert", + "assert_matches", + "cpu-time", "futures", "futures-timer", "libc", @@ -7874,20 +7708,27 @@ dependencies = [ "polkadot-parachain", "polkadot-primitives", "rand 0.8.5", + "rayon", + "sc-executor", + "sc-executor-common", + "sc-executor-wasmtime", "slotmap", "sp-core", + "sp-externalities", + "sp-io", "sp-maybe-compressed-blob", "sp-tracing", "sp-wasm-interface", - "substrate-build-script-utils", + "tempfile", + "tikv-jemalloc-ctl", "tokio", "tracing-gum", ] [[package]] name = "polkadot-node-core-pvf-checker" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "futures", "polkadot-node-primitives", @@ -7900,39 +7741,10 @@ dependencies = [ "tracing-gum", ] -[[package]] -name = "polkadot-node-core-pvf-worker" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" -dependencies = [ - "assert_matches", - "cpu-time", - "futures", - "libc", - "parity-scale-codec", - "polkadot-node-core-pvf", - "polkadot-parachain", - "polkadot-primitives", - "rayon", - "sc-executor", - "sc-executor-common", - "sc-executor-wasmtime", - "sp-core", - "sp-externalities", - "sp-io", - "sp-maybe-compressed-blob", - "sp-tracing", - "substrate-build-script-utils", - "tempfile", - "tikv-jemalloc-ctl", - "tokio", - "tracing-gum", -] - [[package]] name = "polkadot-node-core-runtime-api" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "futures", "lru 0.9.0", @@ -7946,8 +7758,8 @@ dependencies = [ [[package]] name = "polkadot-node-jaeger" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "lazy_static", "log", @@ -7964,8 +7776,8 @@ dependencies = [ [[package]] name = "polkadot-node-metrics" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "bs58", "futures", @@ -7983,8 +7795,8 @@ dependencies = [ [[package]] name = "polkadot-node-network-protocol" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "async-trait", "derive_more", @@ -7998,6 +7810,7 @@ dependencies = [ "rand 0.8.5", "sc-authority-discovery", "sc-network", + "sc-network-common", "strum", "thiserror", "tracing-gum", @@ -8005,8 +7818,8 @@ dependencies = [ [[package]] name = "polkadot-node-primitives" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "bounded-vec", "futures", @@ -8017,18 +7830,19 @@ dependencies = [ "serde", "sp-application-crypto", "sp-consensus-babe", + "sp-consensus-vrf", "sp-core", "sp-keystore", "sp-maybe-compressed-blob", "sp-runtime", "thiserror", - "zstd 0.11.2+zstd.1.5.2", + "zstd", ] [[package]] name = "polkadot-node-subsystem" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "polkadot-node-jaeger", "polkadot-node-subsystem-types", @@ -8037,8 +7851,8 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-types" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "async-trait", "derive_more", @@ -8060,8 +7874,8 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-util" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "async-trait", "derive_more", @@ -8093,8 +7907,8 @@ dependencies = [ [[package]] name = "polkadot-overseer" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "async-trait", "futures", @@ -8116,8 +7930,8 @@ dependencies = [ [[package]] name = "polkadot-parachain" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "bounded-collections", "derive_more", @@ -8133,29 +7947,27 @@ dependencies = [ [[package]] name = "polkadot-performance-test" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "env_logger 0.9.3", "kusama-runtime", "log", "polkadot-erasure-coding", - "polkadot-node-core-pvf-worker", + "polkadot-node-core-pvf", "polkadot-node-primitives", "polkadot-primitives", "quote", - "sc-executor-common", - "sp-maybe-compressed-blob", "thiserror", ] [[package]] name = "polkadot-primitives" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "bitvec", - "hex-literal 0.4.1", + "hex-literal", "parity-scale-codec", "polkadot-core-primitives", "polkadot-parachain", @@ -8177,9 +7989,11 @@ dependencies = [ [[package]] name = "polkadot-rpc" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ + "beefy-gadget", + "beefy-gadget-rpc", "jsonrpsee", "mmr-rpc", "pallet-transaction-payment-rpc", @@ -8188,11 +8002,9 @@ dependencies = [ "sc-client-api", "sc-consensus-babe", "sc-consensus-babe-rpc", - "sc-consensus-beefy", - "sc-consensus-beefy-rpc", "sc-consensus-epochs", - "sc-consensus-grandpa", - "sc-consensus-grandpa-rpc", + "sc-finality-grandpa", + "sc-finality-grandpa-rpc", "sc-rpc", "sc-sync-state-rpc", "sc-transaction-pool-api", @@ -8209,8 +8021,8 @@ dependencies = [ [[package]] name = "polkadot-runtime" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "bitvec", "frame-benchmarking", @@ -8221,7 +8033,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "log", "pallet-authority-discovery", "pallet-authorship", @@ -8231,7 +8043,6 @@ dependencies = [ "pallet-bounties", "pallet-child-bounties", "pallet-collective", - "pallet-conviction-voting", "pallet-democracy", "pallet-election-provider-multi-phase", "pallet-election-provider-support-benchmarking", @@ -8250,7 +8061,6 @@ dependencies = [ "pallet-offences-benchmarking", "pallet-preimage", "pallet-proxy", - "pallet-referenda", "pallet-scheduler", "pallet-session", "pallet-session-benchmarking", @@ -8264,7 +8074,6 @@ dependencies = [ "pallet-treasury", "pallet-utility", "pallet-vesting", - "pallet-whitelist", "pallet-xcm", "parity-scale-codec", "polkadot-primitives", @@ -8277,11 +8086,10 @@ dependencies = [ "serde_derive", "smallvec", "sp-api", - "sp-arithmetic", "sp-authority-discovery", + "sp-beefy", "sp-block-builder", "sp-consensus-babe", - "sp-consensus-beefy", "sp-core", "sp-inherents", "sp-io", @@ -8303,8 +8111,8 @@ dependencies = [ [[package]] name = "polkadot-runtime-common" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "bitvec", "frame-benchmarking", @@ -8317,6 +8125,7 @@ dependencies = [ "pallet-authorship", "pallet-babe", "pallet-balances", + "pallet-beefy-mmr", "pallet-election-provider-multi-phase", "pallet-fast-unstake", "pallet-session", @@ -8335,6 +8144,7 @@ dependencies = [ "serde_derive", "slot-range-helper", "sp-api", + "sp-beefy", "sp-core", "sp-inherents", "sp-io", @@ -8349,8 +8159,8 @@ dependencies = [ [[package]] name = "polkadot-runtime-constants" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "frame-support", "polkadot-primitives", @@ -8363,8 +8173,8 @@ dependencies = [ [[package]] name = "polkadot-runtime-metrics" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "bs58", "parity-scale-codec", @@ -8375,8 +8185,8 @@ dependencies = [ [[package]] name = "polkadot-runtime-parachains" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "bitflags 1.3.2", "bitvec", @@ -8419,15 +8229,16 @@ dependencies = [ [[package]] name = "polkadot-service" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "async-trait", + "beefy-gadget", "frame-benchmarking-cli", "frame-support", "frame-system-rpc-runtime-api", "futures", - "hex-literal 0.4.1", + "hex-literal", "kusama-runtime", "kvdb", "kvdb-rocksdb", @@ -8483,14 +8294,12 @@ dependencies = [ "sc-client-db", "sc-consensus", "sc-consensus-babe", - "sc-consensus-beefy", - "sc-consensus-grandpa", "sc-consensus-slots", "sc-executor", + "sc-finality-grandpa", "sc-keystore", "sc-network", "sc-network-common", - "sc-network-sync", "sc-offchain", "sc-service", "sc-sync-state-rpc", @@ -8501,13 +8310,13 @@ dependencies = [ "serde_json", "sp-api", "sp-authority-discovery", + "sp-beefy", "sp-block-builder", "sp-blockchain", "sp-consensus", "sp-consensus-babe", - "sp-consensus-beefy", - "sp-consensus-grandpa", "sp-core", + "sp-finality-grandpa", "sp-inherents", "sp-io", "sp-keystore", @@ -8528,8 +8337,8 @@ dependencies = [ [[package]] name = "polkadot-statement-distribution" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "arrayvec 0.5.2", "fatality", @@ -8549,8 +8358,8 @@ dependencies = [ [[package]] name = "polkadot-statement-table" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "parity-scale-codec", "polkadot-primitives", @@ -8608,12 +8417,6 @@ dependencies = [ "universal-hash 0.5.1", ] -[[package]] -name = "portable-atomic" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d220334a184db82b31b83f5ff093e3315280fb2b6bbc032022b2304a509aab7a" - [[package]] name = "ppv-lite86" version = "0.2.17" @@ -8723,17 +8526,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-warning" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e99670bafb56b9a106419397343bdbc8b8742c3cc449fec6345f86173f47cd4" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.25", -] - [[package]] name = "proc-macro2" version = "1.0.64" @@ -9194,21 +8986,11 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" dependencies = [ - "crypto-bigint 0.4.9", + "crypto-bigint", "hmac 0.12.1", "zeroize", ] -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac 0.12.1", - "subtle", -] - [[package]] name = "ring" version = "0.16.20" @@ -9226,9 +9008,9 @@ dependencies = [ [[package]] name = "rocksdb" -version = "0.20.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "015439787fce1e75d55f279078d33ff14b4af5d93d995e8838ee4631301c8a99" +checksum = "7e9562ea1d70c0cc63a34a22d977753b50cca91cc6b6527750463bd5dd8697bc" dependencies = [ "libc", "librocksdb-sys", @@ -9236,8 +9018,8 @@ dependencies = [ [[package]] name = "rococo-runtime" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "binary-merkle-tree", "frame-benchmarking", @@ -9247,7 +9029,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "log", "pallet-authority-discovery", "pallet-authorship", @@ -9299,9 +9081,9 @@ dependencies = [ "smallvec", "sp-api", "sp-authority-discovery", + "sp-beefy", "sp-block-builder", "sp-consensus-babe", - "sp-consensus-beefy", "sp-core", "sp-inherents", "sp-io", @@ -9322,8 +9104,8 @@ dependencies = [ [[package]] name = "rococo-runtime-constants" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "frame-support", "polkadot-primitives", @@ -9366,7 +9148,7 @@ dependencies = [ "log", "netlink-packet-route", "netlink-proto", - "nix", + "nix 0.24.3", "thiserror", "tokio", ] @@ -9580,7 +9362,7 @@ dependencies = [ [[package]] name = "sc-allocator" version = "4.1.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "log", "sp-core", @@ -9591,7 +9373,7 @@ dependencies = [ [[package]] name = "sc-authority-discovery" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "futures", @@ -9604,7 +9386,6 @@ dependencies = [ "prost-build", "rand 0.8.5", "sc-client-api", - "sc-network", "sc-network-common", "sp-api", "sp-authority-discovery", @@ -9619,7 +9400,7 @@ dependencies = [ [[package]] name = "sc-basic-authorship" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "futures", "futures-timer", @@ -9642,7 +9423,7 @@ dependencies = [ [[package]] name = "sc-block-builder" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "sc-client-api", @@ -9652,42 +9433,39 @@ dependencies = [ "sp-core", "sp-inherents", "sp-runtime", + "sp-state-machine", ] [[package]] name = "sc-chain-spec" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "memmap2", "sc-chain-spec-derive", - "sc-client-api", - "sc-executor", - "sc-network", + "sc-network-common", "sc-telemetry", "serde", "serde_json", - "sp-blockchain", "sp-core", "sp-runtime", - "sp-state-machine", ] [[package]] name = "sc-chain-spec-derive" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.25", + "syn 1.0.109", ] [[package]] name = "sc-cli" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "array-bytes 4.2.0", "chrono", @@ -9727,7 +9505,7 @@ dependencies = [ [[package]] name = "sc-client-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "fnv", "futures", @@ -9753,7 +9531,7 @@ dependencies = [ [[package]] name = "sc-client-db" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "hash-db", "kvdb", @@ -9779,7 +9557,7 @@ dependencies = [ [[package]] name = "sc-consensus" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "futures", @@ -9804,7 +9582,7 @@ dependencies = [ [[package]] name = "sc-consensus-aura" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "futures", @@ -9833,12 +9611,13 @@ dependencies = [ [[package]] name = "sc-consensus-babe" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "fork-tree", "futures", "log", + "merlin", "num-bigint", "num-rational", "num-traits", @@ -9851,6 +9630,7 @@ dependencies = [ "sc-keystore", "sc-telemetry", "scale-info", + "schnorrkel", "sp-api", "sp-application-crypto", "sp-block-builder", @@ -9858,6 +9638,7 @@ dependencies = [ "sp-consensus", "sp-consensus-babe", "sp-consensus-slots", + "sp-consensus-vrf", "sp-core", "sp-inherents", "sp-keystore", @@ -9869,7 +9650,7 @@ dependencies = [ [[package]] name = "sc-consensus-babe-rpc" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "futures", "jsonrpsee", @@ -9888,64 +9669,10 @@ dependencies = [ "thiserror", ] -[[package]] -name = "sc-consensus-beefy" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" -dependencies = [ - "array-bytes 4.2.0", - "async-trait", - "fnv", - "futures", - "log", - "parity-scale-codec", - "parking_lot 0.12.1", - "sc-client-api", - "sc-consensus", - "sc-keystore", - "sc-network", - "sc-network-common", - "sc-network-gossip", - "sc-network-sync", - "sc-utils", - "sp-api", - "sp-application-crypto", - "sp-arithmetic", - "sp-blockchain", - "sp-consensus", - "sp-consensus-beefy", - "sp-core", - "sp-keystore", - "sp-mmr-primitives", - "sp-runtime", - "substrate-prometheus-endpoint", - "thiserror", - "wasm-timer", -] - -[[package]] -name = "sc-consensus-beefy-rpc" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" -dependencies = [ - "futures", - "jsonrpsee", - "log", - "parity-scale-codec", - "parking_lot 0.12.1", - "sc-consensus-beefy", - "sc-rpc", - "serde", - "sp-consensus-beefy", - "sp-core", - "sp-runtime", - "thiserror", -] - [[package]] name = "sc-consensus-epochs" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "fork-tree", "parity-scale-codec", @@ -9955,70 +9682,10 @@ dependencies = [ "sp-runtime", ] -[[package]] -name = "sc-consensus-grandpa" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" -dependencies = [ - "ahash 0.8.3", - "array-bytes 4.2.0", - "async-trait", - "dyn-clone", - "finality-grandpa", - "fork-tree", - "futures", - "futures-timer", - "log", - "parity-scale-codec", - "parking_lot 0.12.1", - "rand 0.8.5", - "sc-block-builder", - "sc-chain-spec", - "sc-client-api", - "sc-consensus", - "sc-network", - "sc-network-common", - "sc-network-gossip", - "sc-telemetry", - "sc-utils", - "serde_json", - "sp-api", - "sp-application-crypto", - "sp-arithmetic", - "sp-blockchain", - "sp-consensus", - "sp-consensus-grandpa", - "sp-core", - "sp-keystore", - "sp-runtime", - "substrate-prometheus-endpoint", - "thiserror", -] - -[[package]] -name = "sc-consensus-grandpa-rpc" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" -dependencies = [ - "finality-grandpa", - "futures", - "jsonrpsee", - "log", - "parity-scale-codec", - "sc-client-api", - "sc-consensus-grandpa", - "sc-rpc", - "serde", - "sp-blockchain", - "sp-core", - "sp-runtime", - "thiserror", -] - [[package]] name = "sc-consensus-slots" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "futures", @@ -10041,7 +9708,7 @@ dependencies = [ [[package]] name = "sc-executor" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "lru 0.8.1", "parity-scale-codec", @@ -10065,7 +9732,7 @@ dependencies = [ [[package]] name = "sc-executor-common" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "sc-allocator", "sp-maybe-compressed-blob", @@ -10078,7 +9745,7 @@ dependencies = [ [[package]] name = "sc-executor-wasmi" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "log", "sc-allocator", @@ -10091,7 +9758,7 @@ dependencies = [ [[package]] name = "sc-executor-wasmtime" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "anyhow", "cfg-if", @@ -10106,17 +9773,76 @@ dependencies = [ "wasmtime", ] +[[package]] +name = "sc-finality-grandpa" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +dependencies = [ + "ahash 0.8.3", + "array-bytes 4.2.0", + "async-trait", + "dyn-clone", + "finality-grandpa", + "fork-tree", + "futures", + "futures-timer", + "log", + "parity-scale-codec", + "parking_lot 0.12.1", + "rand 0.8.5", + "sc-block-builder", + "sc-chain-spec", + "sc-client-api", + "sc-consensus", + "sc-network", + "sc-network-common", + "sc-network-gossip", + "sc-telemetry", + "sc-utils", + "serde_json", + "sp-api", + "sp-application-crypto", + "sp-arithmetic", + "sp-blockchain", + "sp-consensus", + "sp-core", + "sp-finality-grandpa", + "sp-keystore", + "sp-runtime", + "substrate-prometheus-endpoint", + "thiserror", +] + +[[package]] +name = "sc-finality-grandpa-rpc" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +dependencies = [ + "finality-grandpa", + "futures", + "jsonrpsee", + "log", + "parity-scale-codec", + "sc-client-api", + "sc-finality-grandpa", + "sc-rpc", + "serde", + "sp-blockchain", + "sp-core", + "sp-runtime", + "thiserror", +] + [[package]] name = "sc-informant" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "ansi_term", "futures", "futures-timer", "log", "sc-client-api", - "sc-network", "sc-network-common", "sp-blockchain", "sp-runtime", @@ -10125,7 +9851,7 @@ dependencies = [ [[package]] name = "sc-keystore" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "array-bytes 4.2.0", "async-trait", @@ -10140,12 +9866,12 @@ dependencies = [ [[package]] name = "sc-network" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "array-bytes 4.2.0", - "async-channel", "async-trait", "asynchronous-codec", + "backtrace", "bytes", "either", "fnv", @@ -10153,7 +9879,6 @@ dependencies = [ "futures-timer", "ip_network", "libp2p", - "linked_hash_set", "log", "lru 0.8.1", "mockall", @@ -10170,7 +9895,6 @@ dependencies = [ "serde", "serde_json", "smallvec", - "snow", "sp-arithmetic", "sp-blockchain", "sp-consensus", @@ -10185,7 +9909,7 @@ dependencies = [ [[package]] name = "sc-network-bitswap" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "cid", "futures", @@ -10194,7 +9918,6 @@ dependencies = [ "prost", "prost-build", "sc-client-api", - "sc-network", "sc-network-common", "sp-blockchain", "sp-runtime", @@ -10205,35 +9928,33 @@ dependencies = [ [[package]] name = "sc-network-common" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ - "array-bytes 4.2.0", "async-trait", "bitflags 1.3.2", "bytes", "futures", "futures-timer", "libp2p", + "linked_hash_set", "parity-scale-codec", "prost-build", "sc-consensus", "sc-peerset", - "sc-utils", "serde", "smallvec", "sp-blockchain", "sp-consensus", - "sp-consensus-grandpa", + "sp-finality-grandpa", "sp-runtime", "substrate-prometheus-endpoint", "thiserror", - "zeroize", ] [[package]] name = "sc-network-gossip" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "ahash 0.8.3", "futures", @@ -10241,7 +9962,6 @@ dependencies = [ "libp2p", "log", "lru 0.8.1", - "sc-network", "sc-network-common", "sc-peerset", "sp-runtime", @@ -10252,7 +9972,7 @@ dependencies = [ [[package]] name = "sc-network-light" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "array-bytes 4.2.0", "futures", @@ -10262,7 +9982,6 @@ dependencies = [ "prost", "prost-build", "sc-client-api", - "sc-network", "sc-network-common", "sc-peerset", "sp-blockchain", @@ -10274,13 +9993,12 @@ dependencies = [ [[package]] name = "sc-network-sync" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "array-bytes 4.2.0", "async-trait", "fork-tree", "futures", - "futures-timer", "libp2p", "log", "lru 0.8.1", @@ -10290,7 +10008,6 @@ dependencies = [ "prost-build", "sc-client-api", "sc-consensus", - "sc-network", "sc-network-common", "sc-peerset", "sc-utils", @@ -10298,8 +10015,8 @@ dependencies = [ "sp-arithmetic", "sp-blockchain", "sp-consensus", - "sp-consensus-grandpa", "sp-core", + "sp-finality-grandpa", "sp-runtime", "substrate-prometheus-endpoint", "thiserror", @@ -10308,7 +10025,7 @@ dependencies = [ [[package]] name = "sc-network-transactions" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "array-bytes 4.2.0", "futures", @@ -10316,7 +10033,6 @@ dependencies = [ "log", "parity-scale-codec", "pin-project", - "sc-network", "sc-network-common", "sc-peerset", "sc-utils", @@ -10328,7 +10044,7 @@ dependencies = [ [[package]] name = "sc-offchain" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "array-bytes 4.2.0", "bytes", @@ -10344,7 +10060,6 @@ dependencies = [ "parking_lot 0.12.1", "rand 0.8.5", "sc-client-api", - "sc-network", "sc-network-common", "sc-peerset", "sc-utils", @@ -10359,7 +10074,7 @@ dependencies = [ [[package]] name = "sc-peerset" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "futures", "libp2p", @@ -10372,7 +10087,7 @@ dependencies = [ [[package]] name = "sc-proposer-metrics" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "log", "substrate-prometheus-endpoint", @@ -10381,7 +10096,7 @@ dependencies = [ [[package]] name = "sc-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "futures", "jsonrpsee", @@ -10411,7 +10126,7 @@ dependencies = [ [[package]] name = "sc-rpc-api" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -10430,7 +10145,7 @@ dependencies = [ [[package]] name = "sc-rpc-server" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "http", "jsonrpsee", @@ -10445,7 +10160,7 @@ dependencies = [ [[package]] name = "sc-rpc-spec-v2" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "array-bytes 4.2.0", "futures", @@ -10471,7 +10186,7 @@ dependencies = [ [[package]] name = "sc-service" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "directories", @@ -10537,7 +10252,7 @@ dependencies = [ [[package]] name = "sc-state-db" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "log", "parity-scale-codec", @@ -10548,12 +10263,12 @@ dependencies = [ [[package]] name = "sc-storage-monitor" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "clap", - "fs4", "futures", "log", + "nix 0.26.2", "sc-client-db", "sc-utils", "sp-core", @@ -10564,7 +10279,7 @@ dependencies = [ [[package]] name = "sc-sync-state-rpc" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -10572,7 +10287,7 @@ dependencies = [ "sc-client-api", "sc-consensus-babe", "sc-consensus-epochs", - "sc-consensus-grandpa", + "sc-finality-grandpa", "serde", "serde_json", "sp-blockchain", @@ -10583,7 +10298,7 @@ dependencies = [ [[package]] name = "sc-sysinfo" version = "6.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "futures", "libc", @@ -10602,7 +10317,7 @@ dependencies = [ [[package]] name = "sc-telemetry" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "chrono", "futures", @@ -10621,7 +10336,7 @@ dependencies = [ [[package]] name = "sc-tracing" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "ansi_term", "atty", @@ -10652,18 +10367,18 @@ dependencies = [ [[package]] name = "sc-tracing-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.25", + "syn 1.0.109", ] [[package]] name = "sc-transaction-pool" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "futures", @@ -10690,7 +10405,7 @@ dependencies = [ [[package]] name = "sc-transaction-pool-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "futures", @@ -10704,16 +10419,15 @@ dependencies = [ [[package]] name = "sc-utils" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ - "async-channel", + "backtrace", "futures", "futures-timer", "lazy_static", "log", "parking_lot 0.12.1", "prometheus", - "sp-arithmetic", ] [[package]] @@ -10830,24 +10544,10 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" dependencies = [ - "base16ct 0.1.1", - "der 0.6.1", + "base16ct", + "der", "generic-array 0.14.7", - "pkcs8 0.9.0", - "subtle", - "zeroize", -] - -[[package]] -name = "sec1" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e" -dependencies = [ - "base16ct 0.2.0", - "der 0.7.7", - "generic-array 0.14.7", - "pkcs8 0.10.2", + "pkcs8", "subtle", "zeroize", ] @@ -10966,15 +10666,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_spanned" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" -dependencies = [ - "serde", -] - [[package]] name = "sha-1" version = "0.9.8" @@ -11090,16 +10781,6 @@ dependencies = [ "rand_core 0.6.4", ] -[[package]] -name = "signature" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] - [[package]] name = "simba" version = "0.8.1" @@ -11136,8 +10817,8 @@ checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" [[package]] name = "slot-range-helper" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "enumn", "parity-scale-codec", @@ -11224,15 +10905,13 @@ dependencies = [ [[package]] name = "sp-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "hash-db", "log", "parity-scale-codec", - "scale-info", "sp-api-proc-macro", "sp-core", - "sp-metadata-ir", "sp-runtime", "sp-state-machine", "sp-std", @@ -11244,21 +10923,19 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ - "Inflector", "blake2", - "expander 1.0.0", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.25", + "syn 1.0.109", ] [[package]] name = "sp-application-crypto" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "scale-info", @@ -11271,7 +10948,7 @@ dependencies = [ [[package]] name = "sp-arithmetic" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "integer-sqrt", "num-traits", @@ -11285,7 +10962,7 @@ dependencies = [ [[package]] name = "sp-authority-discovery" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "scale-info", @@ -11295,10 +10972,29 @@ dependencies = [ "sp-std", ] +[[package]] +name = "sp-beefy" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +dependencies = [ + "lazy_static", + "parity-scale-codec", + "scale-info", + "serde", + "sp-api", + "sp-application-crypto", + "sp-core", + "sp-io", + "sp-mmr-primitives", + "sp-runtime", + "sp-std", + "strum", +] + [[package]] name = "sp-block-builder" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "sp-api", @@ -11310,7 +11006,7 @@ dependencies = [ [[package]] name = "sp-blockchain" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "futures", "log", @@ -11328,22 +11024,25 @@ dependencies = [ [[package]] name = "sp-consensus" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "futures", "log", + "parity-scale-codec", "sp-core", "sp-inherents", "sp-runtime", "sp-state-machine", + "sp-std", + "sp-version", "thiserror", ] [[package]] name = "sp-consensus-aura" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "parity-scale-codec", @@ -11361,9 +11060,10 @@ dependencies = [ [[package]] name = "sp-consensus-babe" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", + "merlin", "parity-scale-codec", "scale-info", "serde", @@ -11371,6 +11071,7 @@ dependencies = [ "sp-application-crypto", "sp-consensus", "sp-consensus-slots", + "sp-consensus-vrf", "sp-core", "sp-inherents", "sp-keystore", @@ -11380,64 +11081,40 @@ dependencies = [ ] [[package]] -name = "sp-consensus-beefy" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +name = "sp-consensus-slots" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ - "lazy_static", "parity-scale-codec", "scale-info", "serde", - "sp-api", - "sp-application-crypto", - "sp-core", - "sp-io", - "sp-mmr-primitives", - "sp-runtime", "sp-std", - "strum", + "sp-timestamp", ] [[package]] -name = "sp-consensus-grandpa" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +name = "sp-consensus-vrf" +version = "0.10.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ - "finality-grandpa", - "log", "parity-scale-codec", "scale-info", - "serde", - "sp-api", - "sp-application-crypto", + "schnorrkel", "sp-core", - "sp-keystore", "sp-runtime", "sp-std", ] -[[package]] -name = "sp-consensus-slots" -version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" -dependencies = [ - "parity-scale-codec", - "scale-info", - "serde", - "sp-std", - "sp-timestamp", -] - [[package]] name = "sp-core" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "array-bytes 4.2.0", + "base58", "bitflags 1.3.2", "blake2", "bounded-collections", - "bs58", "dyn-clonable", "ed25519-zebra", "futures", @@ -11450,7 +11127,6 @@ dependencies = [ "merlin", "parity-scale-codec", "parking_lot 0.12.1", - "paste", "primitive-types", "rand 0.8.5", "regex", @@ -11475,9 +11151,9 @@ dependencies = [ [[package]] name = "sp-core-hashing" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ - "blake2b_simd", + "blake2", "byteorder", "digest 0.10.7", "sha2 0.10.7", @@ -11489,18 +11165,18 @@ dependencies = [ [[package]] name = "sp-core-hashing-proc-macro" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "proc-macro2", "quote", "sp-core-hashing", - "syn 2.0.25", + "syn 1.0.109", ] [[package]] name = "sp-database" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "kvdb", "parking_lot 0.12.1", @@ -11509,17 +11185,17 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 1.0.109", ] [[package]] name = "sp-externalities" version = "0.13.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "environmental", "parity-scale-codec", @@ -11527,10 +11203,28 @@ dependencies = [ "sp-storage", ] +[[package]] +name = "sp-finality-grandpa" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +dependencies = [ + "finality-grandpa", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-api", + "sp-application-crypto", + "sp-core", + "sp-keystore", + "sp-runtime", + "sp-std", +] + [[package]] name = "sp-inherents" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "impl-trait-for-tuples", @@ -11545,7 +11239,7 @@ dependencies = [ [[package]] name = "sp-io" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "bytes", "ed25519", @@ -11554,7 +11248,6 @@ dependencies = [ "libsecp256k1", "log", "parity-scale-codec", - "rustversion", "secp256k1", "sp-core", "sp-externalities", @@ -11571,7 +11264,7 @@ dependencies = [ [[package]] name = "sp-keyring" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "lazy_static", "sp-core", @@ -11582,11 +11275,14 @@ dependencies = [ [[package]] name = "sp-keystore" version = "0.13.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ + "async-trait", "futures", + "merlin", "parity-scale-codec", "parking_lot 0.12.1", + "schnorrkel", "serde", "sp-core", "sp-externalities", @@ -11596,27 +11292,16 @@ dependencies = [ [[package]] name = "sp-maybe-compressed-blob" version = "4.1.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "thiserror", - "zstd 0.12.3+zstd.1.5.2", -] - -[[package]] -name = "sp-metadata-ir" -version = "0.1.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" -dependencies = [ - "frame-metadata", - "parity-scale-codec", - "scale-info", - "sp-std", + "zstd", ] [[package]] name = "sp-mmr-primitives" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "ckb-merkle-mountain-range", "log", @@ -11634,7 +11319,7 @@ dependencies = [ [[package]] name = "sp-npos-elections" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "scale-info", @@ -11648,7 +11333,7 @@ dependencies = [ [[package]] name = "sp-offchain" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "sp-api", "sp-core", @@ -11658,7 +11343,7 @@ dependencies = [ [[package]] name = "sp-panic-handler" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "backtrace", "lazy_static", @@ -11668,7 +11353,7 @@ dependencies = [ [[package]] name = "sp-rpc" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "rustc-hash", "serde", @@ -11678,7 +11363,7 @@ dependencies = [ [[package]] name = "sp-runtime" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "either", "hash256-std-hasher", @@ -11700,7 +11385,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -11718,19 +11403,19 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "Inflector", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.25", + "syn 1.0.109", ] [[package]] name = "sp-serializer" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "serde", "serde_json", @@ -11739,7 +11424,7 @@ dependencies = [ [[package]] name = "sp-session" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "scale-info", @@ -11753,11 +11438,10 @@ dependencies = [ [[package]] name = "sp-staking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "scale-info", - "serde", "sp-core", "sp-runtime", "sp-std", @@ -11766,7 +11450,7 @@ dependencies = [ [[package]] name = "sp-state-machine" version = "0.13.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "hash-db", "log", @@ -11786,12 +11470,12 @@ dependencies = [ [[package]] name = "sp-std" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" [[package]] name = "sp-storage" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "impl-serde", "parity-scale-codec", @@ -11804,7 +11488,7 @@ dependencies = [ [[package]] name = "sp-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "futures-timer", @@ -11819,7 +11503,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "sp-std", @@ -11831,7 +11515,7 @@ dependencies = [ [[package]] name = "sp-transaction-pool" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "sp-api", "sp-runtime", @@ -11840,7 +11524,7 @@ dependencies = [ [[package]] name = "sp-transaction-storage-proof" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "log", @@ -11856,11 +11540,11 @@ dependencies = [ [[package]] name = "sp-trie" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "ahash 0.8.3", "hash-db", - "hashbrown 0.13.2", + "hashbrown 0.12.3", "lazy_static", "memory-db", "nohash-hasher", @@ -11879,7 +11563,7 @@ dependencies = [ [[package]] name = "sp-version" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "impl-serde", "parity-scale-codec", @@ -11896,18 +11580,18 @@ dependencies = [ [[package]] name = "sp-version-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.25", + "syn 1.0.109", ] [[package]] name = "sp-wasm-interface" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -11921,7 +11605,7 @@ dependencies = [ [[package]] name = "sp-weights" version = "4.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "parity-scale-codec", "scale-info", @@ -11939,17 +11623,6 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -[[package]] -name = "spinners" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08615eea740067d9899969bc2891c68a19c315cb1f66640af9a9ecb91b13bcab" -dependencies = [ - "lazy_static", - "maplit", - "strum", -] - [[package]] name = "spki" version = "0.6.0" @@ -11957,17 +11630,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" dependencies = [ "base64ct", - "der 0.6.1", -] - -[[package]] -name = "spki" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" -dependencies = [ - "base64ct", - "der 0.7.7", + "der", ] [[package]] @@ -11994,9 +11657,8 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "statemint-runtime" version = "1.0.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.42#f603a61ff370fc33740c9373833c3c6ba1486846" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" dependencies = [ - "assets-common", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -12012,7 +11674,7 @@ dependencies = [ "frame-system", "frame-system-benchmarking", "frame-system-rpc-runtime-api", - "hex-literal 0.4.1", + "hex-literal", "log", "pallet-asset-tx-payment", "pallet-assets", @@ -12050,7 +11712,6 @@ dependencies = [ "sp-std", "sp-transaction-pool", "sp-version", - "sp-weights", "substrate-wasm-builder", "xcm", "xcm-builder", @@ -12179,7 +11840,7 @@ dependencies = [ [[package]] name = "substrate-build-script-utils" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "platforms 2.0.0", ] @@ -12197,7 +11858,7 @@ dependencies = [ [[package]] name = "substrate-frame-rpc-system" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "frame-system-rpc-runtime-api", "futures", @@ -12216,7 +11877,7 @@ dependencies = [ [[package]] name = "substrate-prometheus-endpoint" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "hyper", "log", @@ -12228,7 +11889,7 @@ dependencies = [ [[package]] name = "substrate-rpc-client" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "jsonrpsee", @@ -12241,7 +11902,7 @@ dependencies = [ [[package]] name = "substrate-state-trie-migration-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "jsonrpsee", "log", @@ -12260,7 +11921,7 @@ dependencies = [ [[package]] name = "substrate-wasm-builder" version = "5.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "ansi_term", "build-helper", @@ -12269,7 +11930,7 @@ dependencies = [ "sp-maybe-compressed-blob", "strum", "tempfile", - "toml 0.7.6", + "toml", "walkdir", "wasm-opt", ] @@ -12624,26 +12285,11 @@ dependencies = [ "serde", ] -[[package]] -name = "toml" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - [[package]] name = "toml_datetime" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" -dependencies = [ - "serde", -] [[package]] name = "toml_edit" @@ -12652,8 +12298,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78" dependencies = [ "indexmap 2.0.0", - "serde", - "serde_spanned", "toml_datetime", "winnow", ] @@ -12745,8 +12389,8 @@ dependencies = [ [[package]] name = "tracing-gum" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "polkadot-node-jaeger", "polkadot-primitives", @@ -12756,14 +12400,14 @@ dependencies = [ [[package]] name = "tracing-gum-proc-macro" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ - "expander 2.0.0", + "expander 0.0.6", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.25", + "syn 1.0.109", ] [[package]] @@ -12812,9 +12456,9 @@ dependencies = [ [[package]] name = "trie-db" -version = "0.27.1" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "767abe6ffed88a1889671a102c2861ae742726f52e0a5a425b92c9fbfa7e9c85" +checksum = "3390c0409daaa6027d6681393316f4ccd3ff82e1590a1e4725014e3ae2bf1920" dependencies = [ "hash-db", "hashbrown 0.13.2", @@ -12825,9 +12469,9 @@ dependencies = [ [[package]] name = "trie-root" -version = "0.18.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4ed310ef5ab98f5fa467900ed906cb9232dd5376597e00fd4cba2a449d06c0b" +checksum = "9a36c5ca3911ed3c9a5416ee6c679042064b93fc637ded67e25f92e68d783891" dependencies = [ "hash-db", ] @@ -12887,7 +12531,7 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "try-runtime-cli" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", "clap", @@ -12918,7 +12562,7 @@ dependencies = [ "sp-version", "sp-weights", "substrate-rpc-client", - "zstd 0.12.3+zstd.1.5.2", + "zstd", ] [[package]] @@ -13391,9 +13035,9 @@ dependencies = [ "rustix 0.36.15", "serde", "sha2 0.10.7", - "toml 0.5.11", + "toml", "windows-sys 0.42.0", - "zstd 0.11.2+zstd.1.5.2", + "zstd", ] [[package]] @@ -13628,7 +13272,7 @@ dependencies = [ "ccm", "curve25519-dalek 3.2.0", "der-parser 8.2.0", - "elliptic-curve 0.12.3", + "elliptic-curve", "hkdf", "hmac 0.12.1", "log", @@ -13640,11 +13284,11 @@ dependencies = [ "rcgen 0.9.3", "ring", "rustls 0.19.1", - "sec1 0.3.0", + "sec1", "serde", "sha1", "sha2 0.10.7", - "signature 1.6.4", + "signature", "subtle", "thiserror", "tokio", @@ -13759,7 +13403,7 @@ dependencies = [ "lazy_static", "libc", "log", - "nix", + "nix 0.24.3", "rand 0.8.5", "thiserror", "tokio", @@ -13768,8 +13412,8 @@ dependencies = [ [[package]] name = "westend-runtime" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "bitvec", "frame-benchmarking", @@ -13780,7 +13424,7 @@ dependencies = [ "frame-system-benchmarking", "frame-system-rpc-runtime-api", "frame-try-runtime", - "hex-literal 0.4.1", + "hex-literal", "log", "pallet-authority-discovery", "pallet-authorship", @@ -13836,9 +13480,9 @@ dependencies = [ "smallvec", "sp-api", "sp-authority-discovery", + "sp-beefy", "sp-block-builder", "sp-consensus-babe", - "sp-consensus-beefy", "sp-core", "sp-inherents", "sp-io", @@ -13860,8 +13504,8 @@ dependencies = [ [[package]] name = "westend-runtime-constants" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "frame-support", "polkadot-primitives", @@ -14218,8 +13862,8 @@ dependencies = [ [[package]] name = "xcm" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "bounded-collections", "derivative", @@ -14234,8 +13878,8 @@ dependencies = [ [[package]] name = "xcm-builder" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "frame-support", "frame-system", @@ -14256,7 +13900,7 @@ dependencies = [ [[package]] name = "xcm-emulator" version = "0.1.0" -source = "git+https://github.com/shaunxw/xcm-simulator?rev=d011e5ca62b93e8f688c2042c1f92cdbafc5d1d0#d011e5ca62b93e8f688c2042c1f92cdbafc5d1d0" +source = "git+https://github.com/shaunxw/xcm-simulator?rev=aa13dce47596e150806dfc3af99096dae6ffc65e#aa13dce47596e150806dfc3af99096dae6ffc65e" dependencies = [ "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -14281,8 +13925,8 @@ dependencies = [ [[package]] name = "xcm-executor" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "environmental", "frame-benchmarking", @@ -14301,13 +13945,13 @@ dependencies = [ [[package]] name = "xcm-procedural" -version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.25", + "syn 1.0.109", ] [[package]] @@ -14359,16 +14003,7 @@ version = "0.11.2+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" dependencies = [ - "zstd-safe 5.0.2+zstd.1.5.2", -] - -[[package]] -name = "zstd" -version = "0.12.3+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76eea132fb024e0e13fd9c2f5d5d595d8a967aa72382ac2f9d39fcc95afd0806" -dependencies = [ - "zstd-safe 6.0.5+zstd.1.5.4", + "zstd-safe", ] [[package]] @@ -14381,16 +14016,6 @@ dependencies = [ "zstd-sys", ] -[[package]] -name = "zstd-safe" -version = "6.0.5+zstd.1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56d9e60b4b1758206c238a10165fbcae3ca37b01744e394c463463f6529d23b" -dependencies = [ - "libc", - "zstd-sys", -] - [[package]] name = "zstd-sys" version = "2.0.8+zstd.1.5.5" diff --git a/Cargo.toml b/Cargo.toml index f63ca7de0..f71ec117a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,12 +41,12 @@ overflow-checks = true [workspace.dependencies] # Build deps -substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } # Internal pallets (with default disabled) pallet-funding = { path = "pallets/funding", default-features = false } pallet-sandbox = { path = "pallets/sandbox", default-features = false } -pallet-parachain-staking = { git = "https://gitlab.com/Omegabit/stake-patch", default-features = false, branch = "0.9.42"} +pallet-parachain-staking = { git = "https://gitlab.com/Omegabit/stake-patch", default-features = false } # Internal support (with default disabled) @@ -76,133 +76,134 @@ smallvec = "1.10.0" log = "0.4.17" # Emulations -# TODO: Replace it from the one in the Cumulus Repo -xcm-emulator = { git = "https://github.com/shaunxw/xcm-simulator", default-features = false, rev = "d011e5ca62b93e8f688c2042c1f92cdbafc5d1d0" } +xcm-emulator = { git = "https://github.com/shaunxw/xcm-simulator", default-features = false, rev = "aa13dce47596e150806dfc3af99096dae6ffc65e" } +dip-provider-runtime-template = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } +kilt-runtime-common = { package = "runtime-common", default-features = false, git = "https://github.com/KILTprotocol/kilt-node", branch = "aa/dip" } # Substrate (with default disabled) -frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -frame-try-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-arithmetic = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-blockchain = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-consensus-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-block-builder = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-offchain = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-trie = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -sp-consensus-grandpa = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -try-runtime-cli = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +frame-try-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +sp-staking = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +sp-arithmetic = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +sp-consensus-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +sp-block-builder = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +sp-offchain = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +sp-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +sp-trie = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +try-runtime-cli = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } # FRAME -pallet-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-assets = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-asset-tx-payment = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-collective = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-democracy = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-scheduler = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-treasury = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-utility = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-membership = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-multisig = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-preimage = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-grandpa = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } -pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-assets = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-asset-tx-payment = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-collective = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-democracy = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-scheduler = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-treasury = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-utility = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-membership = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-multisig = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-preimage = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-grandpa = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } +pallet-vesting = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } # Polkadot (with default disabled) -pallet-xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } -polkadot-parachain = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } -polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } -polkadot-core-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } -xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } -xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } -xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } -xcm-simulator = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } -polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } -polkadot-runtime = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } -polkadot-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42" } +pallet-xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } +polkadot-core-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } +xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } +xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } +xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } +xcm-simulator = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } +polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } +polkadot-runtime = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.39" } # Cumulus (with default disabled) -cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } -cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } -cumulus-pallet-solo-to-para = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } -cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } -cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } -cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } -cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } -cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } -cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } -pallet-collator-selection = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } -parachain-info = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } -parachains-common = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } -statemint-runtime = { git = 'https://github.com/paritytech/cumulus', default-features = false, branch = 'polkadot-v0.9.42' } +cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } +cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } +cumulus-pallet-solo-to-para = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } +cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } +cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } +cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } +cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } +cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } +pallet-collator-selection = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } +parachain-info = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } +parachains-common = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } +statemint-runtime = { git = 'https://github.com/paritytech/cumulus', default-features = false, branch = 'polkadot-v0.9.39' } # Client-only (with default enabled) -cumulus-client-cli = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } -cumulus-client-consensus-aura = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } -cumulus-client-consensus-common = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } -cumulus-client-network = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } -cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } -cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } -cumulus-relay-chain-interface = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } -cumulus-relay-chain-inprocess-interface = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } -cumulus-relay-chain-minimal-node = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42" } -polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.42" } -polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.42" } -sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sc-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sc-network-sync = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sp-serializer = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sc-sysinfo = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sc-network-common = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -sc-consensus-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } -substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +cumulus-client-cli = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.39" } +cumulus-client-consensus-aura = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.39" } +cumulus-client-consensus-common = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.39" } +cumulus-client-network = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.39" } +cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.39" } +cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.39" } +cumulus-relay-chain-interface = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.39" } +cumulus-relay-chain-inprocess-interface = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.39" } +cumulus-relay-chain-minimal-node = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.39" } +polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.39" } +polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.39" } +sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sc-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sc-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sc-executor = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sp-serializer = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sp-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sc-finality-grandpa = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sc-service = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sc-sysinfo = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +sc-network-common = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } + +substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } +substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } # Benchmarking (with default disabled) -cumulus-pallet-session-benchmarking = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.42" } -frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +cumulus-pallet-session-benchmarking = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.39" } +frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.39" } # Runtimes polimec-parachain-runtime = { path = "runtimes/testnet" } diff --git a/README.md b/README.md index cb326bbcd..cf6ebf1f6 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ ### Step 1: Compile the relay chain and add it to $PATH - Clone the [Polkadot Repository](https://github.com/paritytech/polkadot) -- Checkout the `release-v0.9.42` branch +- Checkout the `release-v0.9.39` branch - Compile it using `cargo b -r -p polkadot` - Add the binary to your $PATH, e.g. `cp target/release/polkadot ~/.local/bin/polkadot` @@ -48,7 +48,7 @@ $ cargo run --release -- --dev You can use [srtool](https://github.com/paritytech/srtool) to compile the runtime and generate the WASM blob. -> TODO: Rust 1.69.0 broke `srtool` and `polkadot-v0.9.42` - we need to wait `polkadot-v0.9.42`. [src](https://github.com/paritytech/srtool/issues/62) +> TODO: Rust 1.69.0 broke `srtool` and `polkadot-v0.9.39` - we need to wait `polkadot-v0.9.42`. [src](https://github.com/paritytech/srtool/issues/62) ``` == Compact diff --git a/integration-tests/modified-penpal/Cargo.toml b/integration-tests/modified-penpal/Cargo.toml index ed71efba0..790852360 100644 --- a/integration-tests/modified-penpal/Cargo.toml +++ b/integration-tests/modified-penpal/Cargo.toml @@ -12,7 +12,7 @@ edition = "2021" targets = ["x86_64-unknown-linux-gnu"] [build-dependencies] -substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42" } +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } [dependencies] parity-scale-codec = { version = "3.0.0", default-features = false, features = ["derive"] } diff --git a/integration-tests/modified-penpal/src/lib.rs b/integration-tests/modified-penpal/src/lib.rs index 0ca13534b..e320f5376 100644 --- a/integration-tests/modified-penpal/src/lib.rs +++ b/integration-tests/modified-penpal/src/lib.rs @@ -123,14 +123,12 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; -pub type Migrations = - (pallet_balances::migration::MigrateToTrackInactive,); +pub type Migrations = (pallet_balances::migration::MigrateToTrackInactive,); /// Executive: handles dispatch to the various modules. pub type Executive = frame_executive::Executive< @@ -246,7 +244,10 @@ const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts( /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { - NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } } parameter_types! { @@ -360,10 +361,6 @@ impl pallet_balances::Config for Runtime { type WeightInfo = pallet_balances::weights::SubstrateWeight; type MaxReserves = ConstU32<50>; type ReserveIdentifier = [u8; 8]; - type HoldIdentifier = (); - type FreezeIdentifier = (); - type MaxHolds = ConstU32<0>; - type MaxFreezes = ConstU32<0>; } parameter_types! { @@ -607,14 +604,6 @@ impl_runtime_apis! { fn metadata() -> OpaqueMetadata { OpaqueMetadata::new(Runtime::metadata().into()) } - - fn metadata_at_version(version: u32) -> Option { - Runtime::metadata_at_version(version) - } - - fn metadata_versions() -> sp_std::vec::Vec { - Runtime::metadata_versions() - } } impl sp_block_builder::BlockBuilder for Runtime { @@ -797,20 +786,18 @@ struct CheckInherents; impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { fn check_inherents( - block: &Block, - relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, + block: &Block, relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, ) -> sp_inherents::CheckInherentsResult { let relay_chain_slot = relay_state_proof .read_slot() .expect("Could not read the relay chain slot from the proof"); - let inherent_data = - cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( - relay_chain_slot, - sp_std::time::Duration::from_secs(6), - ) - .create_inherent_data() - .expect("Could not create the timestamp inherent data"); + let inherent_data = cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( + relay_chain_slot, + sp_std::time::Duration::from_secs(6), + ) + .create_inherent_data() + .expect("Could not create the timestamp inherent data"); inherent_data.check_extrinsics(block) } diff --git a/integration-tests/modified-penpal/src/xcm_config.rs b/integration-tests/modified-penpal/src/xcm_config.rs index 436ed023b..7810eb65b 100644 --- a/integration-tests/modified-penpal/src/xcm_config.rs +++ b/integration-tests/modified-penpal/src/xcm_config.rs @@ -22,15 +22,14 @@ //! with statemine as the reserve. At present no derivative tokens are minted on receipt of a //! ReserveAssetTransferDeposited message but that will but the intension will be to support this soon. use super::{ - AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Assets, Balance, Balances, - EnsureRoot, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, - RuntimeOrigin, WeightToFee, XcmpQueue, + AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Assets, Balance, Balances, ParachainInfo, + ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, }; use core::marker::PhantomData; use frame_support::{ match_types, parameter_types, traits::{ - fungibles::{self, Balanced, Credit}, + fungibles::{self, Balanced, CreditOf}, ConstU32, Contains, ContainsPair, Everything, Get, Nothing, }, weights::Weight, @@ -43,13 +42,11 @@ use polkadot_runtime_common::impls::ToAuthor; use sp_runtime::traits::Zero; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, - AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, - ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, FungiblesAdapter, - IsConcrete, LocalMint, NativeAsset, ParentIsPreset, RelayChainAsNative, - SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, - WithComputedOrigin, + AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, + FixedWeightBounds, FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, ParentIsPreset, RelayChainAsNative, + SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, WithComputedOrigin, }; use xcm_executor::{traits::JustTry, XcmExecutor}; @@ -161,10 +158,7 @@ pub type Barrier = DenyThenTry< // If the message is one that immediately attemps to pay for execution, then allow it. AllowTopLevelPaidExecutionFrom, // Common Good Assets parachain, parent and its exec plurality get free execution - AllowExplicitUnpaidExecutionFrom<( - CommonGoodAssetsParachain, - ParentOrParentsExecutivePlurality, - )>, + AllowExplicitUnpaidExecutionFrom<(CommonGoodAssetsParachain, ParentOrParentsExecutivePlurality)>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, ), @@ -182,8 +176,8 @@ pub struct AssetsFrom(PhantomData); impl> ContainsPair for AssetsFrom { fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool { let loc = T::get(); - &loc == origin && - matches!(asset, MultiAsset { id: AssetId::Concrete(asset_loc), fun: Fungible(_a) } + &loc == origin + && matches!(asset, MultiAsset { id: AssetId::Concrete(asset_loc), fun: Fungible(_a) } if asset_loc.match_and_split(&loc).is_some()) } } @@ -208,7 +202,7 @@ where R: pallet_authorship::Config + pallet_assets::Config, AccountIdOf: From + Into, { - fn handle_credit(credit: Credit, pallet_assets::Pallet>) { + fn handle_credit(credit: CreditOf, pallet_assets::Pallet>) { if let Some(author) = pallet_authorship::Pallet::::author() { // In case of error: Will drop the result triggering the `OnDrop` of the imbalance. let _ = pallet_assets::Pallet::::resolve(&author, credit); @@ -246,7 +240,7 @@ impl ContainsPair for MultiNativeAsset { fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool { if let Some(ref reserve) = asset.reserve() { if reserve == origin { - return true + return true; } } false @@ -268,8 +262,8 @@ impl ContainsPair for StatemintAssets { // location must be the statemint parachain let loc = MultiLocation::new(1, X1(Parachain(1000))); // asset must be either a fungible asset from `pallet_assets` or the native token of the relay chain - &loc == origin && - match asset { + &loc == origin + && match asset { MultiAsset { id: Concrete(MultiLocation { @@ -279,7 +273,11 @@ impl ContainsPair for StatemintAssets { .. } => true, MultiAsset { - id: Concrete(MultiLocation { parents: 1, interior: Here }), .. + id: Concrete(MultiLocation { + parents: 1, + interior: Here, + }), + .. } => true, _ => false, @@ -301,8 +299,7 @@ impl xcm_executor::Config for XcmConfig { type UniversalLocation = UniversalLocation; type Barrier = Barrier; type Weigher = FixedWeightBounds; - type Trader = - UsingComponents>; + type Trader = UsingComponents>; type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; type AssetClaims = PolkadotXcm; @@ -360,7 +357,6 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<8>; type WeightInfo = pallet_xcm::TestWeightInfo; - type AdminOrigin = EnsureRoot; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; } diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs index fa5b321ee..4a5e6dfde 100644 --- a/integration-tests/src/lib.rs +++ b/integration-tests/src/lib.rs @@ -24,8 +24,8 @@ use sp_core::{ecdsa, ed25519, sr25519, Pair}; use sp_runtime::{traits::AccountIdConversion, AccountId32 as RuntimeAccountId32}; use xcm::{v3::prelude::*, VersionedMultiAssets, VersionedMultiLocation, VersionedXcm}; use xcm_emulator::{ - cumulus_pallet_xcmp_queue, decl_test_network, decl_test_parachain, decl_test_relay_chain, - polkadot_primitives, TestExt, + cumulus_pallet_xcmp_queue, decl_test_network, decl_test_parachain, decl_test_relay_chain, polkadot_primitives, + TestExt, }; const RELAY_ASSET_ID: u32 = 0; @@ -124,10 +124,8 @@ impl ParachainAccounts { } fn default_parachains_host_configuration( -) -> polkadot_runtime_parachains::configuration::HostConfiguration< - polkadot_primitives::v4::BlockNumber, -> { - use polkadot_primitives::v4::{MAX_CODE_SIZE, MAX_POV_SIZE}; +) -> polkadot_runtime_parachains::configuration::HostConfiguration { + use polkadot_primitives::v2::{MAX_CODE_SIZE, MAX_POV_SIZE}; polkadot_runtime_parachains::configuration::HostConfiguration { minimum_validation_upgrade_delay: 5, @@ -169,7 +167,9 @@ fn default_parachains_host_configuration( pub fn polkadot_ext() -> sp_io::TestExternalities { use polkadot_runtime::{Runtime, System}; - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let mut t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); pallet_balances::GenesisConfig:: { balances: vec![ @@ -188,12 +188,10 @@ pub fn polkadot_ext() -> sp_io::TestExternalities { .assimilate_storage(&mut t) .unwrap(); - let xcm_config = pallet_xcm::GenesisConfig { safe_xcm_version: Some(3) }; - >::assimilate_storage( - &xcm_config, - &mut t, - ) - .unwrap(); + let xcm_config = pallet_xcm::GenesisConfig { + safe_xcm_version: Some(3), + }; + >::assimilate_storage(&xcm_config, &mut t).unwrap(); let mut ext = sp_io::TestExternalities::new(t); ext.execute_with(|| System::set_block_number(1)); @@ -203,22 +201,21 @@ pub fn polkadot_ext() -> sp_io::TestExternalities { pub fn polimec_ext(para_id: u32) -> sp_io::TestExternalities { use polimec_runtime::{Runtime, System}; - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let mut t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); - let parachain_info_config = parachain_info::GenesisConfig { parachain_id: para_id.into() }; + let parachain_info_config = parachain_info::GenesisConfig { + parachain_id: para_id.into(), + }; - >::assimilate_storage( - ¶chain_info_config, - &mut t, - ) - .unwrap(); + >::assimilate_storage(¶chain_info_config, &mut t) + .unwrap(); - let xcm_config = pallet_xcm::GenesisConfig { safe_xcm_version: Some(3) }; - >::assimilate_storage( - &xcm_config, - &mut t, - ) - .unwrap(); + let xcm_config = pallet_xcm::GenesisConfig { + safe_xcm_version: Some(3), + }; + >::assimilate_storage(&xcm_config, &mut t).unwrap(); pallet_balances::GenesisConfig:: { balances: vec![ @@ -257,22 +254,21 @@ pub fn polimec_ext(para_id: u32) -> sp_io::TestExternalities { pub fn statemint_ext(para_id: u32) -> sp_io::TestExternalities { use statemint_runtime::{Runtime, System}; - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let mut t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); - let parachain_info_config = parachain_info::GenesisConfig { parachain_id: para_id.into() }; + let parachain_info_config = parachain_info::GenesisConfig { + parachain_id: para_id.into(), + }; - >::assimilate_storage( - ¶chain_info_config, - &mut t, - ) - .unwrap(); + >::assimilate_storage(¶chain_info_config, &mut t) + .unwrap(); - let xcm_config = pallet_xcm::GenesisConfig { safe_xcm_version: Some(3) }; - >::assimilate_storage( - &xcm_config, - &mut t, - ) - .unwrap(); + let xcm_config = pallet_xcm::GenesisConfig { + safe_xcm_version: Some(3), + }; + >::assimilate_storage(&xcm_config, &mut t).unwrap(); pallet_balances::GenesisConfig:: { balances: vec![ @@ -292,21 +288,20 @@ pub fn statemint_ext(para_id: u32) -> sp_io::TestExternalities { pub fn penpal_ext(para_id: u32) -> sp_io::TestExternalities { use penpal_runtime::{Runtime, System}; - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let mut t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); - let parachain_info_config = parachain_info::GenesisConfig { parachain_id: para_id.into() }; - >::assimilate_storage( - ¶chain_info_config, - &mut t, - ) - .unwrap(); + let parachain_info_config = parachain_info::GenesisConfig { + parachain_id: para_id.into(), + }; + >::assimilate_storage(¶chain_info_config, &mut t) + .unwrap(); - let xcm_config = pallet_xcm::GenesisConfig { safe_xcm_version: Some(3) }; - >::assimilate_storage( - &xcm_config, - &mut t, - ) - .unwrap(); + let xcm_config = pallet_xcm::GenesisConfig { + safe_xcm_version: Some(3), + }; + >::assimilate_storage(&xcm_config, &mut t).unwrap(); pallet_balances::GenesisConfig:: { balances: vec![ @@ -343,8 +338,7 @@ pub mod shortcuts { pub type PenpalBalances = pallet_balances::Pallet; pub type PolkadotAssets = pallet_assets::Pallet; - pub type PolimecAssets = - pallet_assets::Pallet; + pub type PolimecAssets = pallet_assets::Pallet; pub type StatemintAssets = pallet_assets::Pallet; pub type PenpalAssets = pallet_assets::Pallet; @@ -381,13 +375,13 @@ mod network_tests { Here, Parachain(polimec_id()), Xcm(vec![ - UnpaidExecution { weight_limit: WeightLimit::Unlimited, check_origin: None }, + UnpaidExecution { + weight_limit: WeightLimit::Unlimited, + check_origin: None + }, Transact { origin_kind: OriginKind::SovereignAccount, - require_weight_at_most: Weight::from_parts( - INITIAL_BALANCE as u64, - 1024 * 1024 - ), + require_weight_at_most: Weight::from_parts(INITIAL_BALANCE as u64, 1024 * 1024), call: remark.encode().into(), } ]), @@ -408,29 +402,31 @@ mod network_tests { fn ump() { Network::reset(); - let burn_transfer = - PolkadotCall::Balances(pallet_balances::Call::::transfer { - dest: PolkadotAccountId::from([0u8; 32]).into(), - value: 1_000, - }); + let burn_transfer = PolkadotCall::Balances(pallet_balances::Call::::transfer { + dest: PolkadotAccountId::from([0u8; 32]).into(), + value: 1_000, + }); let here_asset: MultiAsset = (MultiLocation::here(), INITIAL_BALANCE / 2).into(); PolimecNet::execute_with(|| { - assert_ok!(PolimecXcmPallet::force_default_xcm_version(PolimecOrigin::root(), Some(3))); + assert_ok!(PolimecXcmPallet::force_default_xcm_version( + PolimecOrigin::root(), + Some(3) + )); assert_ok!(PolimecXcmPallet::send_xcm( Here, Parent, Xcm(vec![ WithdrawAsset(vec![here_asset.clone()].into()), - BuyExecution { fees: here_asset.clone(), weight_limit: Unlimited }, + BuyExecution { + fees: here_asset.clone(), + weight_limit: Unlimited + }, Transact { origin_kind: OriginKind::SovereignAccount, - require_weight_at_most: Weight::from_parts( - INITIAL_BALANCE as u64, - 1024 * 1024 - ), + require_weight_at_most: Weight::from_parts(INITIAL_BALANCE as u64, 1024 * 1024), call: burn_transfer.encode().into(), } ]), @@ -454,11 +450,10 @@ mod network_tests { fn xcmp() { Network::reset(); - let burn_transfer = - PolimecCall::Balances(pallet_balances::Call::::transfer { - dest: PolimecAccountId::from([0u8; 32]).into(), - value: 1_000, - }); + let burn_transfer = PolimecCall::Balances(pallet_balances::Call::::transfer { + dest: PolimecAccountId::from([0u8; 32]).into(), + value: 1_000, + }); let here_asset: MultiAsset = (MultiLocation::here(), INITIAL_BALANCE / 2).into(); @@ -468,13 +463,13 @@ mod network_tests { MultiLocation::new(1, X1(Parachain(polimec_id()))), Xcm(vec![ WithdrawAsset(vec![here_asset.clone()].into()), - BuyExecution { fees: here_asset.clone(), weight_limit: Unlimited }, + BuyExecution { + fees: here_asset.clone(), + weight_limit: Unlimited + }, Transact { origin_kind: OriginKind::SovereignAccount, - require_weight_at_most: Weight::from_parts( - INITIAL_BALANCE as u64, - 1024 * 1024 - ), + require_weight_at_most: Weight::from_parts(INITIAL_BALANCE as u64, 1024 * 1024), call: burn_transfer.encode().into(), } ]), @@ -519,17 +514,14 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let ( - statemint_prev_alice_dot_balance, - statemint_prev_polimec_dot_balance, - statemint_prev_dot_issuance, - ) = StatemintNet::execute_with(|| { - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::free_balance(ParachainAccounts::polimec_child_account()), - StatemintBalances::total_issuance(), - ) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_polimec_dot_balance, statemint_prev_dot_issuance) = + StatemintNet::execute_with(|| { + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::free_balance(ParachainAccounts::polimec_child_account()), + StatemintBalances::total_issuance(), + ) + }); // do the transfer StatemintNet::execute_with(|| { @@ -576,32 +568,25 @@ mod reserve_backed_transfers { }); // check Statemint's post transfer balances and issuance - let ( - statemint_post_alice_dot_balance, - statemint_post_polimec_dot_balance, - statemint_post_dot_issuance, - ) = StatemintNet::execute_with(|| { - statemint_runtime::System::reset_events(); - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::free_balance(ParachainAccounts::polimec_child_account()), - StatemintBalances::total_issuance(), - ) - }); + let (statemint_post_alice_dot_balance, statemint_post_polimec_dot_balance, statemint_post_dot_issuance) = + StatemintNet::execute_with(|| { + statemint_runtime::System::reset_events(); + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::free_balance(ParachainAccounts::polimec_child_account()), + StatemintBalances::total_issuance(), + ) + }); - let polimec_delta_alice_dot_balance = - polimec_post_alice_dot_balance - polimec_prev_alice_dot_balance; + let polimec_delta_alice_dot_balance = polimec_post_alice_dot_balance - polimec_prev_alice_dot_balance; let polimec_delta_dot_issuance = polimec_post_dot_issuance - polimec_prev_dot_issuance; - let polimec_delta_alice_plmc_balance = - polimec_post_alice_plmc_balance - polimec_prev_alice_plmc_balance; + let polimec_delta_alice_plmc_balance = polimec_post_alice_plmc_balance - polimec_prev_alice_plmc_balance; let polimec_delta_plmc_issuance = polimec_post_plmc_issuance - polimec_prev_plmc_issuance; - let statemint_delta_alice_dot_balance = - statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; + let statemint_delta_alice_dot_balance = statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; let statemint_delta_polimec_dot_balance = statemint_post_polimec_dot_balance - statemint_prev_polimec_dot_balance; - let statemint_delta_dot_issuance = - statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; assert!( polimec_delta_alice_dot_balance >= RESERVE_TRANSFER_AMOUNT - polimec_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) && @@ -637,7 +622,10 @@ mod reserve_backed_transfers { "Polimec ALICE PLMC balance should not have changed" ); - assert_eq!(polimec_delta_plmc_issuance, 0, "Polimec PLMC issuance should not have changed"); + assert_eq!( + polimec_delta_plmc_issuance, 0, + "Polimec PLMC issuance should not have changed" + ); } #[test] @@ -664,15 +652,20 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = - StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = StatemintNet::execute_with(|| { + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::total_issuance(), + ) + }); // construct the XCM to transfer from Polimec to Statemint's reserve let transfer_xcm: Xcm = Xcm(vec![ WithdrawAsset(vec![dot.clone()].into()), - BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, + BuyExecution { + fees: execution_dot.clone(), + weight_limit: Limited(MAX_XCM_WEIGHT), + }, InitiateReserveWithdraw { assets: All.into(), reserve: MultiLocation::new(1, X1(Parachain(statemint_id()))), @@ -685,7 +678,10 @@ mod reserve_backed_transfers { assets: All.into(), beneficiary: MultiLocation::new( 0, - AccountId32 { network: None, id: ALICE.into() }, + AccountId32 { + network: None, + id: ALICE.into(), + }, ), }, ]), @@ -727,22 +723,20 @@ mod reserve_backed_transfers { }); // check Statemint's post transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = - StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = StatemintNet::execute_with(|| { + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::total_issuance(), + ) + }); let polimec_delta_dot_issuance = polimec_prev_dot_issuance - polimec_post_dot_issuance; let polimec_delta_plmc_issuance = polimec_prev_plmc_issuance - polimec_post_plmc_issuance; - let polimec_delta_alice_dot_balance = - polimec_prev_alice_dot_balance - polimec_post_alice_dot_balance; - let polimec_delta_alice_plmc_balance = - polimec_prev_alice_plmc_balance - polimec_post_alice_plmc_balance; + let polimec_delta_alice_dot_balance = polimec_prev_alice_dot_balance - polimec_post_alice_dot_balance; + let polimec_delta_alice_plmc_balance = polimec_prev_alice_plmc_balance - polimec_post_alice_plmc_balance; - let statemint_delta_dot_issuance = - statemint_prev_dot_issuance - statemint_post_dot_issuance; - let statemint_delta_alice_dot_balance = - statemint_post_alice_dot_balance - statemint_prev_alice_dot_balance; + let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = statemint_post_alice_dot_balance - statemint_prev_alice_dot_balance; assert_eq!( polimec_delta_alice_dot_balance, RESERVE_TRANSFER_AMOUNT, @@ -755,7 +749,10 @@ mod reserve_backed_transfers { ); assert_eq!(polimec_delta_plmc_issuance, 0, "Polimec's PLMC issuance should not change, since all xcm token transfer are done in DOT, and no fees are burnt since no extrinsics are dispatched"); - assert_eq!(polimec_delta_alice_plmc_balance, 0, "Polimec's Alice PLMC should not change"); + assert_eq!( + polimec_delta_alice_plmc_balance, 0, + "Polimec's Alice PLMC should not change" + ); assert!( statemint_delta_alice_dot_balance @@ -779,22 +776,17 @@ mod reserve_backed_transfers { // check Penpal's pre transfer balances and issuance let (penpal_prev_alice_dot_balance, penpal_prev_dot_issuance) = - PenpalNet::execute_with(|| { - (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) - }); + PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); // check Statemint's pre transfer balances and issuance - let ( - statemint_prev_alice_dot_balance, - statemint_prev_penpal_dot_balance, - statemint_prev_dot_issuance, - ) = StatemintNet::execute_with(|| { - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::free_balance(ParachainAccounts::penpal_child_account()), - StatemintBalances::total_issuance(), - ) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_penpal_dot_balance, statemint_prev_dot_issuance) = + StatemintNet::execute_with(|| { + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::free_balance(ParachainAccounts::penpal_child_account()), + StatemintBalances::total_issuance(), + ) + }); // do the transfer StatemintNet::execute_with(|| { @@ -825,36 +817,28 @@ mod reserve_backed_transfers { }); // check Penpal's post transfer balances and issuance - let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = - PenpalNet::execute_with(|| { - penpal_runtime::System::reset_events(); - (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) - }); + let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = PenpalNet::execute_with(|| { + penpal_runtime::System::reset_events(); + (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) + }); // check Statemint's post transfer balances and issuance - let ( - statemint_post_alice_dot_balance, - statemint_post_penpal_dot_balance, - statemint_post_dot_issuance, - ) = StatemintNet::execute_with(|| { - statemint_runtime::System::reset_events(); - ( - StatemintBalances::free_balance(ALICE), - StatemintBalances::free_balance(ParachainAccounts::penpal_child_account()), - StatemintBalances::total_issuance(), - ) - }); + let (statemint_post_alice_dot_balance, statemint_post_penpal_dot_balance, statemint_post_dot_issuance) = + StatemintNet::execute_with(|| { + statemint_runtime::System::reset_events(); + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::free_balance(ParachainAccounts::penpal_child_account()), + StatemintBalances::total_issuance(), + ) + }); - let penpal_delta_alice_dot_balance = - penpal_post_alice_dot_balance - penpal_prev_alice_dot_balance; + let penpal_delta_alice_dot_balance = penpal_post_alice_dot_balance - penpal_prev_alice_dot_balance; let penpal_delta_dot_issuance = penpal_post_dot_issuance - penpal_prev_dot_issuance; - let statemint_delta_alice_dot_balance = - statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; - let statemint_delta_penpal_dot_balance = - statemint_post_penpal_dot_balance - statemint_prev_penpal_dot_balance; - let statemint_delta_dot_issuance = - statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; + let statemint_delta_penpal_dot_balance = statemint_post_penpal_dot_balance - statemint_prev_penpal_dot_balance; + let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; assert!( penpal_delta_alice_dot_balance >= RESERVE_TRANSFER_AMOUNT - penpal_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) && @@ -895,20 +879,23 @@ mod reserve_backed_transfers { // check Penpal's pre transfer balances and issuance let (penpal_prev_alice_dot_balance, penpal_prev_dot_issuance) = - PenpalNet::execute_with(|| { - (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) - }); + PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = - StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = StatemintNet::execute_with(|| { + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::total_issuance(), + ) + }); // construct the XCM to transfer from Penpal to Statemint's reserve let transfer_xcm: Xcm = Xcm(vec![ WithdrawAsset(vec![dot.clone()].into()), - BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, + BuyExecution { + fees: execution_dot.clone(), + weight_limit: Limited(MAX_XCM_WEIGHT), + }, InitiateReserveWithdraw { assets: All.into(), reserve: MultiLocation::new(1, X1(Parachain(statemint_id()))), @@ -921,7 +908,10 @@ mod reserve_backed_transfers { assets: All.into(), beneficiary: MultiLocation::new( 0, - AccountId32 { network: None, id: ALICE.into() }, + AccountId32 { + network: None, + id: ALICE.into(), + }, ), }, ]), @@ -949,24 +939,21 @@ mod reserve_backed_transfers { // check Penpal's post transfer balances and issuance let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = - PenpalNet::execute_with(|| { - (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) - }); + PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); // check Statemint's post transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = - StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = StatemintNet::execute_with(|| { + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::total_issuance(), + ) + }); let penpal_delta_dot_issuance = penpal_prev_dot_issuance - penpal_post_dot_issuance; - let penpal_delta_alice_dot_balance = - penpal_prev_alice_dot_balance - penpal_post_alice_dot_balance; + let penpal_delta_alice_dot_balance = penpal_prev_alice_dot_balance - penpal_post_alice_dot_balance; - let statemint_delta_dot_issuance = - statemint_prev_dot_issuance - statemint_post_dot_issuance; - let statemint_delta_alice_dot_balance = - statemint_post_alice_dot_balance - statemint_prev_alice_dot_balance; + let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = statemint_post_alice_dot_balance - statemint_prev_alice_dot_balance; assert_eq!( penpal_delta_alice_dot_balance, RESERVE_TRANSFER_AMOUNT, @@ -1001,7 +988,10 @@ mod reserve_backed_transfers { let transfer_xcm: Xcm = Xcm(vec![ WithdrawAsset(vec![dot.clone()].into()), - BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, + BuyExecution { + fees: execution_dot.clone(), + weight_limit: Limited(MAX_XCM_WEIGHT), + }, InitiateReserveWithdraw { assets: All.into(), reserve: MultiLocation::new(1, X1(Parachain(statemint_id()))), @@ -1020,8 +1010,11 @@ mod reserve_backed_transfers { }, DepositAsset { assets: All.into(), - beneficiary: X1(AccountId32 { network: None, id: ALICE.into() }) - .into(), + beneficiary: X1(AccountId32 { + network: None, + id: ALICE.into(), + }) + .into(), }, ]), }, @@ -1045,16 +1038,16 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = - StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = StatemintNet::execute_with(|| { + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::total_issuance(), + ) + }); // check Penpal's pre transfer balances and issuance let (penpal_prev_alice_dot_balance, penpal_prev_dot_issuance) = - PenpalNet::execute_with(|| { - (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) - }); + PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); // send the XCM message PolimecNet::execute_with(|| { @@ -1099,36 +1092,31 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = - StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = StatemintNet::execute_with(|| { + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::total_issuance(), + ) + }); // check Penpal's pre transfer balances and issuance let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = - PenpalNet::execute_with(|| { - (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) - }); + PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); let penpal_delta_dot_issuance = penpal_post_dot_issuance - penpal_prev_dot_issuance; - let penpal_delta_alice_dot_balance = - penpal_post_alice_dot_balance - penpal_prev_alice_dot_balance; + let penpal_delta_alice_dot_balance = penpal_post_alice_dot_balance - penpal_prev_alice_dot_balance; let polimec_delta_dot_issuance = polimec_prev_dot_issuance - polimec_post_dot_issuance; - let polimec_delta_alice_dot_balance = - polimec_prev_alice_dot_balance - polimec_post_alice_dot_balance; + let polimec_delta_alice_dot_balance = polimec_prev_alice_dot_balance - polimec_post_alice_dot_balance; let polimec_delta_plmc_issuance = polimec_prev_plmc_issuance - polimec_post_plmc_issuance; - let polimec_delta_alice_plmc_balance = - polimec_prev_alice_plmc_balance - polimec_post_alice_plmc_balance; + let polimec_delta_alice_plmc_balance = polimec_prev_alice_plmc_balance - polimec_post_alice_plmc_balance; - let statemint_delta_dot_issuance = - statemint_prev_dot_issuance - statemint_post_dot_issuance; - let statemint_delta_alice_dot_balance = - statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; + let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; assert!( - penpal_delta_alice_dot_balance > RESERVE_TRANSFER_AMOUNT - MAX_XCM_FEE * 3 && - penpal_delta_alice_dot_balance < RESERVE_TRANSFER_AMOUNT, + penpal_delta_alice_dot_balance > RESERVE_TRANSFER_AMOUNT - MAX_XCM_FEE * 3 + && penpal_delta_alice_dot_balance < RESERVE_TRANSFER_AMOUNT, "Expected funds are not received by Alice on Penpal" ); @@ -1162,7 +1150,10 @@ mod reserve_backed_transfers { "Polimec ALICE PLMC balance should not have changed" ); - assert_eq!(polimec_delta_plmc_issuance, 0, "Polimec PLMC issuance should not have changed"); + assert_eq!( + polimec_delta_plmc_issuance, 0, + "Polimec PLMC issuance should not have changed" + ); } #[test] @@ -1174,7 +1165,10 @@ mod reserve_backed_transfers { let transfer_xcm: Xcm = Xcm(vec![ WithdrawAsset(vec![dot.clone()].into()), - BuyExecution { fees: execution_dot.clone(), weight_limit: Limited(MAX_XCM_WEIGHT) }, + BuyExecution { + fees: execution_dot.clone(), + weight_limit: Limited(MAX_XCM_WEIGHT), + }, InitiateReserveWithdraw { assets: All.into(), reserve: MultiLocation::new(1, X1(Parachain(statemint_id()))), @@ -1193,8 +1187,11 @@ mod reserve_backed_transfers { }, DepositAsset { assets: All.into(), - beneficiary: X1(AccountId32 { network: None, id: ALICE.into() }) - .into(), + beneficiary: X1(AccountId32 { + network: None, + id: ALICE.into(), + }) + .into(), }, ]), }, @@ -1218,16 +1215,16 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = - StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_prev_alice_dot_balance, statemint_prev_dot_issuance) = StatemintNet::execute_with(|| { + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::total_issuance(), + ) + }); // check Penpal's pre transfer balances and issuance let (penpal_prev_alice_dot_balance, penpal_prev_dot_issuance) = - PenpalNet::execute_with(|| { - (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) - }); + PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); // send the XCM message PenpalNet::execute_with(|| { @@ -1272,36 +1269,31 @@ mod reserve_backed_transfers { }); // check Statemint's pre transfer balances and issuance - let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = - StatemintNet::execute_with(|| { - (StatemintBalances::free_balance(ALICE), StatemintBalances::total_issuance()) - }); + let (statemint_post_alice_dot_balance, statemint_post_dot_issuance) = StatemintNet::execute_with(|| { + ( + StatemintBalances::free_balance(ALICE), + StatemintBalances::total_issuance(), + ) + }); // check Penpal's pre transfer balances and issuance let (penpal_post_alice_dot_balance, penpal_post_dot_issuance) = - PenpalNet::execute_with(|| { - (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance()) - }); + PenpalNet::execute_with(|| (PenpalBalances::free_balance(ALICE), PenpalBalances::total_issuance())); let penpal_delta_dot_issuance = penpal_prev_dot_issuance - penpal_post_dot_issuance; - let penpal_delta_alice_dot_balance = - penpal_prev_alice_dot_balance - penpal_post_alice_dot_balance; + let penpal_delta_alice_dot_balance = penpal_prev_alice_dot_balance - penpal_post_alice_dot_balance; let polimec_delta_dot_issuance = polimec_post_dot_issuance - polimec_prev_dot_issuance; - let polimec_delta_alice_dot_balance = - polimec_post_alice_dot_balance - polimec_prev_alice_dot_balance; + let polimec_delta_alice_dot_balance = polimec_post_alice_dot_balance - polimec_prev_alice_dot_balance; let polimec_delta_plmc_issuance = polimec_post_plmc_issuance - polimec_prev_plmc_issuance; - let polimec_delta_alice_plmc_balance = - polimec_post_alice_plmc_balance - polimec_prev_alice_plmc_balance; + let polimec_delta_alice_plmc_balance = polimec_post_alice_plmc_balance - polimec_prev_alice_plmc_balance; - let statemint_delta_dot_issuance = - statemint_prev_dot_issuance - statemint_post_dot_issuance; - let statemint_delta_alice_dot_balance = - statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; + let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; + let statemint_delta_alice_dot_balance = statemint_prev_alice_dot_balance - statemint_post_alice_dot_balance; assert!( - polimec_delta_alice_dot_balance > RESERVE_TRANSFER_AMOUNT - MAX_XCM_FEE * 3 && - polimec_delta_alice_dot_balance < RESERVE_TRANSFER_AMOUNT, + polimec_delta_alice_dot_balance > RESERVE_TRANSFER_AMOUNT - MAX_XCM_FEE * 3 + && polimec_delta_alice_dot_balance < RESERVE_TRANSFER_AMOUNT, "Expected funds are not received by Alice on Polimec" ); @@ -1335,6 +1327,9 @@ mod reserve_backed_transfers { "Polimec ALICE PLMC balance should not have changed" ); - assert_eq!(polimec_delta_plmc_issuance, 0, "Polimec PLMC issuance should not have changed"); + assert_eq!( + polimec_delta_plmc_issuance, 0, + "Polimec PLMC issuance should not have changed" + ); } -} +} \ No newline at end of file diff --git a/nodes/parachain/Cargo.toml b/nodes/parachain/Cargo.toml index 8a1316d20..e564a5e40 100644 --- a/nodes/parachain/Cargo.toml +++ b/nodes/parachain/Cargo.toml @@ -42,7 +42,6 @@ sc-telemetry.workspace = true sc-tracing.workspace = true sc-transaction-pool.workspace = true sc-transaction-pool-api.workspace = true -sc-network-sync.workspace = true sp-api.workspace = true sp-block-builder.workspace = true sp-blockchain.workspace = true diff --git a/nodes/parachain/src/chain_spec.rs b/nodes/parachain/src/chain_spec.rs index 7c6a1dc99..c7ff83f19 100644 --- a/nodes/parachain/src/chain_spec.rs +++ b/nodes/parachain/src/chain_spec.rs @@ -18,7 +18,7 @@ use cumulus_primitives_core::ParaId; use polimec_parachain_runtime::{AccountId, Signature}; -use polkadot_primitives::v4::LOWEST_PUBLIC_ID; +use polkadot_primitives::v2::LOWEST_PUBLIC_ID; use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup}; use sc_service::Properties; use serde::{Deserialize, Serialize}; diff --git a/nodes/parachain/src/command.rs b/nodes/parachain/src/command.rs index c46e4a73c..3ce35ff93 100644 --- a/nodes/parachain/src/command.rs +++ b/nodes/parachain/src/command.rs @@ -363,7 +363,8 @@ pub fn run() -> Result<()> { let id = ParaId::from(para_id); let parachain_account = - AccountIdConversion::::into_account_truncating(&id); + AccountIdConversion::::into_account_truncating(&id); + let state_version = Cli::native_runtime_version(&config.chain_spec).state_version(); let block: Block = generate_genesis_block(&*config.chain_spec, state_version) .map_err(|e| format!("{:?}", e))?; diff --git a/nodes/parachain/src/service.rs b/nodes/parachain/src/service.rs index d21e7b66c..352435bc0 100644 --- a/nodes/parachain/src/service.rs +++ b/nodes/parachain/src/service.rs @@ -21,7 +21,7 @@ use std::{sync::Arc, time::Duration}; use cumulus_client_cli::CollatorOptions; // Local Runtime Types -use polimec_parachain_runtime::{opaque::Block, RuntimeApi}; +use polimec_parachain_runtime::{opaque::Block, Hash, RuntimeApi}; // Cumulus Imports use cumulus_client_consensus_aura::{AuraConsensus, BuildAuraConsensusParams, SlotProportion}; @@ -33,19 +33,17 @@ use cumulus_client_service::{ start_full_node, BuildNetworkParams, StartCollatorParams, StartFullNodeParams, }; use cumulus_primitives_core::ParaId; -use cumulus_relay_chain_interface::RelayChainInterface; +use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface}; // Substrate Imports use frame_benchmarking_cli::SUBSTRATE_REFERENCE_HARDWARE; use sc_consensus::ImportQueue; -use sc_executor::{ - HeapAllocStrategy, NativeElseWasmExecutor, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY, -}; -use sc_network::NetworkBlock; -use sc_network_sync::SyncingService; +use sc_executor::NativeElseWasmExecutor; +use sc_network::NetworkService; +use sc_network_common::service::NetworkBlock; use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager}; use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle}; -use sp_keystore::KeystorePtr; +use sp_keystore::SyncCryptoStorePtr; use substrate_prometheus_endpoint::Registry; /// Native executor type. @@ -75,7 +73,6 @@ type ParachainBlockImport = TParachainBlockImport, P /// /// Use this macro if you don't actually need the full service, but just the builder in order to /// be able to perform chain operations. -#[allow(clippy::type_complexity)] pub fn new_partial( config: &Configuration, ) -> Result< @@ -100,19 +97,12 @@ pub fn new_partial( }) .transpose()?; - let heap_pages = config - .default_heap_pages - .map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| HeapAllocStrategy::Static { extra_pages: h as _ }); - - let wasm = WasmExecutor::builder() - .with_execution_method(config.wasm_method) - .with_onchain_heap_alloc_strategy(heap_pages) - .with_offchain_heap_alloc_strategy(heap_pages) - .with_max_runtime_instances(config.max_runtime_instances) - .with_runtime_cache_size(config.runtime_cache_size) - .build(); - - let executor = ParachainExecutor::new_with_wasm_executor(wasm); + let executor = ParachainExecutor::new( + config.wasm_method, + config.default_heap_pages, + config.max_runtime_instances, + config.runtime_cache_size, + ); let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( @@ -188,7 +178,10 @@ async fn start_node_impl( hwbench.clone(), ) .await - .map_err(|e| sc_service::Error::Application(Box::new(e) as Box<_>))?; + .map_err(|e| match e { + RelayChainError::ServiceError(polkadot_service::Error::Sub(x)) => x, + s => s.to_string().into(), + })?; let force_authoring = parachain_config.force_authoring; let validator = parachain_config.role.is_authority(); @@ -196,7 +189,7 @@ async fn start_node_impl( let transaction_pool = params.transaction_pool.clone(); let import_queue_service = params.import_queue.service(); - let (network, system_rpc_tx, tx_handler_controller, start_network, sync_service) = + let (network, system_rpc_tx, tx_handler_controller, start_network) = build_network(BuildNetworkParams { parachain_config: ¶chain_config, client: client.clone(), @@ -238,10 +231,9 @@ async fn start_node_impl( transaction_pool: transaction_pool.clone(), task_manager: &mut task_manager, config: parachain_config, - keystore: params.keystore_container.keystore(), + keystore: params.keystore_container.sync_keystore(), backend, network: network.clone(), - sync_service: sync_service.clone(), system_rpc_tx, tx_handler_controller, telemetry: telemetry.as_mut(), @@ -269,8 +261,8 @@ async fn start_node_impl( } let announce_block = { - let sync_service = sync_service.clone(); - Arc::new(move |hash, data| sync_service.announce_block(hash, data)) + let network = network.clone(); + Arc::new(move |hash, data| network.announce_block(hash, data)) }; let relay_chain_slot_duration = Duration::from_secs(6); @@ -288,8 +280,8 @@ async fn start_node_impl( &task_manager, relay_chain_interface.clone(), transaction_pool, - sync_service.clone(), - params.keystore_container.keystore(), + network, + params.keystore_container.sync_keystore(), force_authoring, para_id, )?; @@ -308,7 +300,6 @@ async fn start_node_impl( collator_key: collator_key.expect("Command line arguments do not allow this. qed"), relay_chain_slot_duration, recovery_handle: Box::new(overseer_handle), - sync_service, }; start_collator(params).await?; @@ -322,7 +313,6 @@ async fn start_node_impl( relay_chain_slot_duration, import_queue: import_queue_service, recovery_handle: Box::new(overseer_handle), - sync_service, }; start_full_node(params)?; @@ -356,8 +346,7 @@ fn build_import_queue( create_inherent_data_providers: move |_, _| async move { let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, slot_duration, ); @@ -371,7 +360,6 @@ fn build_import_queue( .map_err(Into::into) } -#[allow(clippy::too_many_arguments)] fn build_consensus( client: Arc, block_import: ParachainBlockImport, @@ -380,8 +368,8 @@ fn build_consensus( task_manager: &TaskManager, relay_chain_interface: Arc, transaction_pool: Arc>, - sync_oracle: Arc>, - keystore: KeystorePtr, + sync_oracle: Arc>, + keystore: SyncCryptoStorePtr, force_authoring: bool, para_id: ParaId, ) -> Result>, sc_service::Error> { @@ -410,11 +398,10 @@ fn build_consensus( .await; let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); let parachain_inherent = parachain_inherent.ok_or_else(|| { Box::::from( diff --git a/nodes/standalone/Cargo.toml b/nodes/standalone/Cargo.toml index 92b409a30..b31ad7d4e 100644 --- a/nodes/standalone/Cargo.toml +++ b/nodes/standalone/Cargo.toml @@ -26,6 +26,8 @@ sc-consensus-aura.workspace = true sp-consensus-aura.workspace = true sp-consensus.workspace = true sc-consensus.workspace = true +sc-finality-grandpa.workspace = true +sp-finality-grandpa.workspace = true sc-client-api.workspace = true sp-runtime.workspace = true sp-timestamp.workspace = true @@ -34,8 +36,7 @@ sp-keyring.workspace = true frame-system.workspace = true pallet-transaction-payment.workspace = true sc-chain-spec.workspace = true -sc-consensus-grandpa.workspace = true -sp-consensus-grandpa.workspace = true + # These dependencies are used for the node's RPCs jsonrpsee = { workspace = true, features = ["server"] } sc-rpc.workspace = true diff --git a/nodes/standalone/src/chain_spec.rs b/nodes/standalone/src/chain_spec.rs index ec044fd58..6db1a7883 100644 --- a/nodes/standalone/src/chain_spec.rs +++ b/nodes/standalone/src/chain_spec.rs @@ -20,8 +20,8 @@ use polimec_standalone_runtime::{ }; use sc_service::{ChainType, Properties}; use sp_consensus_aura::sr25519::AuthorityId as AuraId; -use sp_consensus_grandpa::AuthorityId as GrandpaId; use sp_core::{sr25519, Pair, Public}; +use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_runtime::traits::{IdentifyAccount, Verify}; // The URL for the telemetry server. diff --git a/nodes/standalone/src/command.rs b/nodes/standalone/src/command.rs index 892c41ce5..7b4d488f6 100644 --- a/nodes/standalone/src/command.rs +++ b/nodes/standalone/src/command.rs @@ -1,3 +1,19 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + use crate::{ benchmarking::{inherent_benchmark_data, RemarkBuilder, TransferKeepAliveBuilder}, chain_spec, @@ -10,9 +26,6 @@ use sc_cli::{ChainSpec, RuntimeVersion, SubstrateCli}; use sc_service::PartialComponents; use sp_keyring::Sr25519Keyring; -#[cfg(feature = "try-runtime")] -use try_runtime_cli::block_building_info::timestamp_with_aura_info; - impl SubstrateCli for Cli { fn impl_name() -> String { "Substrate Node".into() @@ -102,7 +115,7 @@ pub fn run() -> sc_cli::Result<()> { let PartialComponents { client, task_manager, backend, .. } = service::new_partial(&config)?; let aux_revert = Box::new(|client, _, blocks| { - sc_consensus_grandpa::revert(client, blocks)?; + sc_finality_grandpa::revert(client, blocks)?; Ok(()) }); Ok((cmd.run(client, backend, Some(aux_revert)), task_manager)) @@ -177,8 +190,6 @@ pub fn run() -> sc_cli::Result<()> { }, #[cfg(feature = "try-runtime")] Some(Subcommand::TryRuntime(cmd)) => { - use crate::service::ExecutorDispatch; - use sc_executor::{sp_wasm_interface::ExtendedHostFunctions, NativeExecutionDispatch}; let runner = cli.create_runner(cmd)?; runner.async_run(|config| { // we don't need any of the components of new_partial, just a runtime, or a task @@ -187,15 +198,7 @@ pub fn run() -> sc_cli::Result<()> { let task_manager = sc_service::TaskManager::new(config.tokio_handle.clone(), registry) .map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?; - let info_provider = timestamp_with_aura_info(6000); - - Ok(( - cmd.run::::ExtendHostFunctions, - >, _>(Some(info_provider)), - task_manager, - )) + Ok((cmd.run::(config), task_manager)) }) }, #[cfg(not(feature = "try-runtime"))] diff --git a/nodes/standalone/src/service.rs b/nodes/standalone/src/service.rs index 0ce896d35..b92c2e81d 100644 --- a/nodes/standalone/src/service.rs +++ b/nodes/standalone/src/service.rs @@ -19,8 +19,9 @@ use polimec_standalone_runtime::{self, opaque::Block, RuntimeApi}; use sc_client_api::BlockBackend; use sc_consensus_aura::{ImportQueueParams, SlotProportion, StartAuraParams}; -use sc_consensus_grandpa::SharedVoterState; pub use sc_executor::NativeElseWasmExecutor; +use sc_finality_grandpa::SharedVoterState; +use sc_keystore::LocalKeystore; use sc_service::{error::Error as ServiceError, Configuration, TaskManager, WarpSyncParams}; use sc_telemetry::{Telemetry, TelemetryWorker}; use sp_consensus_aura::sr25519::AuthorityPair as AuraPair; @@ -61,18 +62,22 @@ pub fn new_partial( sc_consensus::DefaultImportQueue, sc_transaction_pool::FullPool, ( - sc_consensus_grandpa::GrandpaBlockImport< + sc_finality_grandpa::GrandpaBlockImport< FullBackend, Block, FullClient, FullSelectChain, >, - sc_consensus_grandpa::LinkHalf, + sc_finality_grandpa::LinkHalf, Option, ), >, ServiceError, > { + if config.keystore_remote.is_some() { + return Err(ServiceError::Other("Remote Keystores are not supported.".into())) + } + let telemetry = config .telemetry_endpoints .clone() @@ -84,7 +89,12 @@ pub fn new_partial( }) .transpose()?; - let executor = sc_service::new_native_or_wasm_executor(&config); + let executor = NativeElseWasmExecutor::::new( + config.wasm_method, + config.default_heap_pages, + config.max_runtime_instances, + config.runtime_cache_size, + ); let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( @@ -109,7 +119,7 @@ pub fn new_partial( client.clone(), ); - let (grandpa_block_import, grandpa_link) = sc_consensus_grandpa::block_import( + let (grandpa_block_import, grandpa_link) = sc_finality_grandpa::block_import( client.clone(), &(client.clone() as Arc<_>), select_chain.clone(), @@ -126,11 +136,10 @@ pub fn new_partial( create_inherent_data_providers: move |_, ()| async move { let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); Ok((slot, timestamp)) }, @@ -153,6 +162,13 @@ pub fn new_partial( }) } +fn remote_keystore(_url: &String) -> Result, &'static str> { + // FIXME: here would the concrete keystore be built, + // must return a concrete type (NOT `LocalKeystore`) that + // implements `CryptoStore` and `SyncCryptoStore` + Err("Remote Keystore not supported.") +} + /// Builds a new service for a full client. pub fn new_full(mut config: Configuration) -> Result { let sc_service::PartialComponents { @@ -160,13 +176,23 @@ pub fn new_full(mut config: Configuration) -> Result backend, mut task_manager, import_queue, - keystore_container, + mut keystore_container, select_chain, transaction_pool, other: (block_import, grandpa_link, mut telemetry), } = new_partial(&config)?; - let grandpa_protocol_name = sc_consensus_grandpa::protocol_standard_name( + if let Some(url) = &config.keystore_remote { + match remote_keystore(url) { + Ok(k) => keystore_container.set_remote_keystore(k), + Err(e) => + return Err(ServiceError::Other(format!( + "Error hooking up remote keystore for {}: {}", + url, e + ))), + }; + } + let grandpa_protocol_name = sc_finality_grandpa::protocol_standard_name( &client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"), &config.chain_spec, ); @@ -174,14 +200,14 @@ pub fn new_full(mut config: Configuration) -> Result config .network .extra_sets - .push(sc_consensus_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone())); - let warp_sync = Arc::new(sc_consensus_grandpa::warp_proof::NetworkProvider::new( + .push(sc_finality_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone())); + let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), Vec::default(), )); - let (network, system_rpc_tx, tx_handler_controller, network_starter, sync_service) = + let (network, system_rpc_tx, tx_handler_controller, network_starter) = sc_service::build_network(sc_service::BuildNetworkParams { config: &config, client: client.clone(), @@ -222,14 +248,13 @@ pub fn new_full(mut config: Configuration) -> Result let _rpc_handlers = sc_service::spawn_tasks(sc_service::SpawnTasksParams { network: network.clone(), client: client.clone(), - keystore: keystore_container.keystore(), + keystore: keystore_container.sync_keystore(), task_manager: &mut task_manager, transaction_pool: transaction_pool.clone(), rpc_builder: rpc_extensions_builder, backend, system_rpc_tx, tx_handler_controller, - sync_service: sync_service.clone(), config, telemetry: telemetry.as_mut(), })?; @@ -255,19 +280,18 @@ pub fn new_full(mut config: Configuration) -> Result create_inherent_data_providers: move |_, ()| async move { let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = - sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( - *timestamp, - slot_duration, - ); + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *timestamp, + slot_duration, + ); Ok((slot, timestamp)) }, force_authoring, backoff_authoring_blocks, - keystore: keystore_container.keystore(), - sync_oracle: sync_service.clone(), - justification_sync_link: sync_service.clone(), + keystore: keystore_container.sync_keystore(), + sync_oracle: network.clone(), + justification_sync_link: network.clone(), block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), max_block_proposal_slot_portion: None, telemetry: telemetry.as_ref().map(|x| x.handle()), @@ -285,9 +309,10 @@ pub fn new_full(mut config: Configuration) -> Result if enable_grandpa { // if the node isn't actively participating in consensus then it doesn't // need a keystore, regardless of which protocol we use below. - let keystore = if role.is_authority() { Some(keystore_container.keystore()) } else { None }; + let keystore = + if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None }; - let grandpa_config = sc_consensus_grandpa::Config { + let grandpa_config = sc_finality_grandpa::Config { // FIXME #1578 make this available through chainspec gossip_duration: Duration::from_millis(333), justification_period: 512, @@ -305,12 +330,11 @@ pub fn new_full(mut config: Configuration) -> Result // and vote data availability than the observer. The observer has not // been tested extensively yet and having most nodes in a network run it // could lead to finality stalls. - let grandpa_config = sc_consensus_grandpa::GrandpaParams { + let grandpa_config = sc_finality_grandpa::GrandpaParams { config: grandpa_config, link: grandpa_link, network, - sync: Arc::new(sync_service), - voting_rule: sc_consensus_grandpa::VotingRulesBuilder::default().build(), + voting_rule: sc_finality_grandpa::VotingRulesBuilder::default().build(), prometheus_registry, shared_voter_state: SharedVoterState::empty(), telemetry: telemetry.as_ref().map(|x| x.handle()), @@ -321,7 +345,7 @@ pub fn new_full(mut config: Configuration) -> Result task_manager.spawn_essential_handle().spawn_blocking( "grandpa-voter", None, - sc_consensus_grandpa::run_grandpa_voter(grandpa_config)?, + sc_finality_grandpa::run_grandpa_voter(grandpa_config)?, ); } diff --git a/pallets/funding/src/lib.rs b/pallets/funding/src/lib.rs index 41202a2dc..1729100ea 100644 --- a/pallets/funding/src/lib.rs +++ b/pallets/funding/src/lib.rs @@ -202,7 +202,7 @@ use frame_support::{ pallet_prelude::ValueQuery, traits::{ tokens::{ - fungibles::{metadata::Mutate as MetadataMutate, Create, Mutate}, + fungibles::{metadata::Mutate as MetadataMutate, Create, InspectMetadata, Mutate}, Balance, }, Currency as CurrencyT, Get, NamedReservableCurrency, Randomness, ReservableCurrency, @@ -298,7 +298,8 @@ pub mod pallet { /// The currency used for minting contribution tokens as fungible assets (i.e pallet-assets) type ContributionTokenCurrency: Create> + Mutate - + MetadataMutate; + + MetadataMutate + + InspectMetadata; /// Unique identifier for any bid in the system. type BidId: Parameter + Copy + Saturating + One + Default; diff --git a/pallets/funding/src/mock.rs b/pallets/funding/src/mock.rs index 9459da70c..6ec9516ee 100644 --- a/pallets/funding/src/mock.rs +++ b/pallets/funding/src/mock.rs @@ -103,10 +103,6 @@ impl pallet_balances::Config for TestRuntime { type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; type WeightInfo = (); - type MaxHolds = ConstU32<1024>; - type MaxFreezes = (); - type HoldIdentifier = BondType; - type FreezeIdentifier = (); } impl pallet_insecure_randomness_collective_flip::Config for TestRuntime {} diff --git a/pallets/sandbox/src/mock.rs b/pallets/sandbox/src/mock.rs index 4bcc626da..278414096 100644 --- a/pallets/sandbox/src/mock.rs +++ b/pallets/sandbox/src/mock.rs @@ -101,10 +101,6 @@ impl pallet_balances::Config for TestRuntime { type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; type WeightInfo = (); - type HoldIdentifier = pallet_funding::BondType; - type FreezeIdentifier = pallet_funding::BondType; - type MaxHolds = (); - type MaxFreezes = (); } impl pallet_insecure_randomness_collective_flip::Config for TestRuntime {} diff --git a/runtimes/base/src/lib.rs b/runtimes/base/src/lib.rs index 701846e13..63fb89b54 100644 --- a/runtimes/base/src/lib.rs +++ b/runtimes/base/src/lib.rs @@ -239,18 +239,14 @@ impl pallet_authorship::Config for Runtime { } impl pallet_balances::Config for Runtime { - type MaxLocks = MaxLocks; type Balance = Balance; - type RuntimeEvent = RuntimeEvent; type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type MaxLocks = MaxLocks; type MaxReserves = MaxReserves; - type MaxHolds = MaxLocks; - type MaxFreezes = MaxReserves; - type HoldIdentifier = (); - type FreezeIdentifier = (); - type ReserveIdentifier = [u8; 8]; + type ReserveIdentifier = (); type WeightInfo = (); } @@ -418,13 +414,6 @@ impl_runtime_apis! { fn metadata() -> OpaqueMetadata { OpaqueMetadata::new(Runtime::metadata().into()) } - fn metadata_at_version(version: u32) -> Option { - Runtime::metadata_at_version(version) - } - - fn metadata_versions() -> sp_std::vec::Vec { - Runtime::metadata_versions() - } } impl sp_block_builder::BlockBuilder for Runtime { @@ -495,6 +484,7 @@ impl_runtime_apis! { ) -> pallet_transaction_payment::FeeDetails { TransactionPayment::query_fee_details(uxt, len) } + fn query_weight_to_fee(weight: Weight) -> Balance { TransactionPayment::weight_to_fee(weight) } @@ -518,6 +508,7 @@ impl_runtime_apis! { ) -> pallet_transaction_payment::FeeDetails { TransactionPayment::query_call_fee_details(call, len) } + fn query_weight_to_fee(weight: Weight) -> Balance { TransactionPayment::weight_to_fee(weight) } @@ -545,6 +536,8 @@ impl_runtime_apis! { signature_check: bool, select: frame_try_runtime::TryStateSelect, ) -> Weight { + // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to + // have a backtrace here. Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap() } } diff --git a/runtimes/base/src/xcm_config.rs b/runtimes/base/src/xcm_config.rs index ab1307a1b..ea8c1a842 100644 --- a/runtimes/base/src/xcm_config.rs +++ b/runtimes/base/src/xcm_config.rs @@ -15,8 +15,8 @@ // along with this program. If not, see . use super::{ - AccountId, AllPalletsWithSystem, Balances, EnsureRoot, ParachainInfo, ParachainSystem, - PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, + AccountId, AllPalletsWithSystem, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, + Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, }; use frame_support::{ match_types, parameter_types, @@ -169,7 +169,6 @@ parameter_types! { } impl pallet_xcm::Config for Runtime { - type AdminOrigin = EnsureRoot; type RuntimeEvent = RuntimeEvent; type SendXcmOrigin = EnsureXcmOrigin; type XcmRouter = XcmRouter; diff --git a/runtimes/shared-configuration/src/weights/mod.rs b/runtimes/shared-configuration/src/weights/mod.rs index ea1fd8720..68cc6b5f3 100644 --- a/runtimes/shared-configuration/src/weights/mod.rs +++ b/runtimes/shared-configuration/src/weights/mod.rs @@ -59,6 +59,5 @@ parameter_types! { pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * RuntimeBlockWeights::get().max_block; - pub MaxCollectivesProposalWeight: Weight = Perbill::from_percent(50) * RuntimeBlockWeights::get().max_block; pub const MaxScheduledPerBlock: u32 = 50; } diff --git a/runtimes/standalone/Cargo.toml b/runtimes/standalone/Cargo.toml index 1287744a3..9faf0e20e 100644 --- a/runtimes/standalone/Cargo.toml +++ b/runtimes/standalone/Cargo.toml @@ -31,7 +31,6 @@ sp-session.workspace = true sp-std.workspace = true sp-transaction-pool.workspace = true sp-version.workspace = true -sp-consensus-grandpa.workspace = true # FRAME pallet-aura.workspace = true @@ -67,7 +66,6 @@ hex-literal = { workspace = true, optional = true } # Local Dependencies pallet-funding.workspace = true -shared-configuration.workspace = true [build-dependencies] substrate-wasm-builder.workspace = true @@ -114,8 +112,6 @@ std = [ "pallet-authorship/std", "pallet-insecure-randomness-collective-flip/std", "pallet-vesting/std", - "shared-configuration/std", - "sp-consensus-grandpa/std" ] runtime-benchmarks = [ diff --git a/runtimes/standalone/src/lib.rs b/runtimes/standalone/src/lib.rs index 646c294fe..039fd3a3b 100644 --- a/runtimes/standalone/src/lib.rs +++ b/runtimes/standalone/src/lib.rs @@ -42,7 +42,9 @@ use frame_system::EnsureSigned; pub use frame_system::{Call as SystemCall, EnsureRoot}; pub use pallet_balances::Call as BalancesCall; use pallet_funding::{BondType, Multiplier as FundingMultiplier}; -use pallet_grandpa::AuthorityId as GrandpaId; +use pallet_grandpa::{ + fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, +}; pub use pallet_timestamp::Call as TimestampCall; use pallet_transaction_payment::{ConstFeeMultiplier, CurrencyAdapter, Multiplier}; use sp_api::impl_runtime_apis; @@ -65,16 +67,6 @@ use sp_std::prelude::*; use sp_version::NativeVersion; use sp_version::RuntimeVersion; -pub use shared_configuration::{ - assets::*, - currency::{vesting::*, *}, - fee::*, - funding::*, - governance::*, - staking::*, - weights::*, -}; - // Make the WASM binary available. #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); @@ -264,35 +256,46 @@ impl pallet_aura::Config for Runtime { impl pallet_grandpa::Config for Runtime { type RuntimeEvent = RuntimeEvent; + type KeyOwnerProofSystem = (); + + type KeyOwnerProof = + >::Proof; + + type KeyOwnerIdentification = >::IdentificationTuple; + + type HandleEquivocation = (); + type WeightInfo = (); type MaxAuthorities = ConstU32<32>; - type MaxSetIdSessionEntries = ConstU64<0>; - - type KeyOwnerProof = sp_core::Void; - type EquivocationReportSystem = (); + type MaxSetIdSessionEntries = (); } impl pallet_timestamp::Config for Runtime { + /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - type MinimumPeriod = MinimumPeriod; + type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; type WeightInfo = (); } +/// Existential deposit. +pub const EXISTENTIAL_DEPOSIT: u128 = 500; + impl pallet_balances::Config for Runtime { - type MaxLocks = MaxLocks; + type MaxLocks = ConstU32<50>; + type MaxReserves = ConstU32<50>; + type ReserveIdentifier = BondType; + /// The type for recording an account's balance. type Balance = Balance; + /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; type DustRemoval = (); - type ExistentialDeposit = ExistentialDeposit; + type ExistentialDeposit = ConstU128; type AccountStore = System; - type MaxReserves = MaxReserves; - type MaxHolds = MaxLocks; - type MaxFreezes = MaxReserves; - type HoldIdentifier = (); - type FreezeIdentifier = (); - type ReserveIdentifier = BondType; - type WeightInfo = (); + type WeightInfo = pallet_balances::weights::SubstrateWeight; } parameter_types! { @@ -313,6 +316,25 @@ impl pallet_sudo::Config for Runtime { type RuntimeCall = RuntimeCall; } +pub const fn deposit(items: u32, bytes: u32) -> Balance { + items as Balance * 15 * MICRO_PLMC + (bytes as Balance) * 6 * MICRO_PLMC +} + +pub const fn free_deposit() -> Balance { + 0 * MICRO_PLMC +} + +parameter_types! { + pub const AssetDeposit: Balance = PLMC; // 1 UNIT deposit to create asset + pub const ApprovalDeposit: Balance = EXISTENTIAL_DEPOSIT; + pub const AssetAccountDeposit: Balance = deposit(1, 16); + pub const AssetsStringLimit: u32 = 50; + /// Key = 32 bytes, Value = 36 bytes (32+1+1+1+1) + // https://github.com/paritytech/substrate/blob/069917b/frame/assets/src/lib.rs#L257L271 + pub const MetadataDepositBase: Balance = free_deposit(); + pub const MetadataDepositPerByte: Balance = free_deposit(); +} + impl pallet_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; @@ -324,7 +346,7 @@ impl pallet_assets::Config for Runtime { type AssetDeposit = AssetDeposit; type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type ApprovalDeposit = ExistentialDeposit; + type ApprovalDeposit = ApprovalDeposit; type StringLimit = AssetsStringLimit; type Freezer = (); type Extra = (); @@ -406,7 +428,6 @@ impl pallet_collective::Config for Runtime { type DefaultVote = pallet_collective::PrimeDefaultVote; type WeightInfo = pallet_collective::weights::SubstrateWeight; type SetMembersOrigin = EnsureRoot; - type MaxProposalWeight = MaxCollectivesProposalWeight; } parameter_types! { @@ -426,7 +447,6 @@ impl pallet_collective::Config for Runtime { type DefaultVote = pallet_collective::PrimeDefaultVote; type WeightInfo = pallet_collective::weights::SubstrateWeight; type SetMembersOrigin = EnsureRoot; - type MaxProposalWeight = MaxCollectivesProposalWeight; } parameter_types! { @@ -663,14 +683,6 @@ impl_runtime_apis! { fn metadata() -> OpaqueMetadata { OpaqueMetadata::new(Runtime::metadata().into()) } - - fn metadata_at_version(version: u32) -> Option { - Runtime::metadata_at_version(version) - } - - fn metadata_versions() -> sp_std::vec::Vec { - Runtime::metadata_versions() - } } impl sp_block_builder::BlockBuilder for Runtime { @@ -732,29 +744,29 @@ impl_runtime_apis! { } } - impl sp_consensus_grandpa::GrandpaApi for Runtime { - fn grandpa_authorities() -> sp_consensus_grandpa::AuthorityList { + impl fg_primitives::GrandpaApi for Runtime { + fn grandpa_authorities() -> GrandpaAuthorityList { Grandpa::grandpa_authorities() } - fn current_set_id() -> sp_consensus_grandpa::SetId { + fn current_set_id() -> fg_primitives::SetId { Grandpa::current_set_id() } fn submit_report_equivocation_unsigned_extrinsic( - _equivocation_proof: sp_consensus_grandpa::EquivocationProof< + _equivocation_proof: fg_primitives::EquivocationProof< ::Hash, NumberFor, >, - _key_owner_proof: sp_consensus_grandpa::OpaqueKeyOwnershipProof, + _key_owner_proof: fg_primitives::OpaqueKeyOwnershipProof, ) -> Option<()> { None } fn generate_key_ownership_proof( - _set_id: sp_consensus_grandpa::SetId, + _set_id: fg_primitives::SetId, _authority_id: GrandpaId, - ) -> Option { + ) -> Option { // NOTE: this is the only implementation possible since we've // defined our key owner proof type as a bottom type (i.e. a type // with no values). @@ -818,10 +830,9 @@ impl_runtime_apis! { Vec, Vec, ) { - use frame_benchmarking::{baseline, Benchmarking, BenchmarkList}; + use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; - use baseline::Pallet as BaselineBench; let mut list = Vec::::new(); list_benchmarks!(list, extra); @@ -837,7 +848,6 @@ impl_runtime_apis! { use frame_benchmarking::{baseline, Benchmarking, BenchmarkBatch, TrackedStorageKey}; use frame_system_benchmarking::Pallet as SystemBench; - use baseline::Pallet as BaselineBench; impl frame_system_benchmarking::Config for Runtime {} impl baseline::Config for Runtime {} @@ -853,35 +863,37 @@ impl_runtime_apis! { } } + #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { - fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { + fn on_runtime_upgrade() -> (Weight, Weight) { // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to // have a backtrace here. If any of the pre/post migration checks fail, we shall stop // right here and right now. - let weight = Executive::try_runtime_upgrade(checks).unwrap(); + let weight = Executive::try_runtime_upgrade().unwrap(); (weight, BlockWeights::get().max_block) } fn execute_block( block: Block, state_root_check: bool, - signature_check: bool, select: frame_try_runtime::TryStateSelect ) -> Weight { // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to // have a backtrace here. - Executive::try_execute_block(block, state_root_check, signature_check, select).expect("execute-block failed") + Executive::try_execute_block(block, state_root_check, select).expect("execute-block failed") } } } #[cfg(test)] mod tests { - use super::*; + use std::collections::HashSet; + use frame_support::traits::WhitelistedStorageKeys; use sp_core::hexdisplay::HexDisplay; - use std::collections::HashSet; + + use super::*; #[test] fn check_whitelist() { diff --git a/runtimes/testnet/src/lib.rs b/runtimes/testnet/src/lib.rs index d1b240b85..7531aa8c2 100644 --- a/runtimes/testnet/src/lib.rs +++ b/runtimes/testnet/src/lib.rs @@ -218,17 +218,13 @@ impl pallet_authorship::Config for Runtime { } impl pallet_balances::Config for Runtime { - type MaxLocks = MaxLocks; type Balance = Balance; + type DustRemoval = Treasury; type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type MaxLocks = MaxLocks; type MaxReserves = MaxReserves; - type MaxHolds = MaxLocks; - type MaxFreezes = MaxReserves; - type HoldIdentifier = (); - type FreezeIdentifier = (); type ReserveIdentifier = BondType; type WeightInfo = (); } @@ -377,7 +373,6 @@ impl pallet_collective::Config for Runtime { type DefaultVote = pallet_collective::PrimeDefaultVote; type WeightInfo = pallet_collective::weights::SubstrateWeight; type SetMembersOrigin = EnsureRoot; - type MaxProposalWeight = MaxCollectivesProposalWeight; } type TechnicalCollective = pallet_collective::Instance2; @@ -391,7 +386,6 @@ impl pallet_collective::Config for Runtime { type DefaultVote = pallet_collective::PrimeDefaultVote; type WeightInfo = pallet_collective::weights::SubstrateWeight; type SetMembersOrigin = EnsureRoot; - type MaxProposalWeight = MaxCollectivesProposalWeight; } impl pallet_democracy::Config for Runtime { @@ -671,13 +665,6 @@ impl_runtime_apis! { fn metadata() -> OpaqueMetadata { OpaqueMetadata::new(Runtime::metadata().into()) } - fn metadata_at_version(version: u32) -> Option { - Runtime::metadata_at_version(version) - } - - fn metadata_versions() -> sp_std::vec::Vec { - Runtime::metadata_versions() - } } impl sp_block_builder::BlockBuilder for Runtime { @@ -748,9 +735,11 @@ impl_runtime_apis! { ) -> pallet_transaction_payment::FeeDetails { TransactionPayment::query_fee_details(uxt, len) } + fn query_weight_to_fee(weight: Weight) -> Balance { TransactionPayment::weight_to_fee(weight) } + fn query_length_to_fee(length: u32) -> Balance { TransactionPayment::length_to_fee(length) } @@ -771,12 +760,15 @@ impl_runtime_apis! { ) -> pallet_transaction_payment::FeeDetails { TransactionPayment::query_call_fee_details(call, len) } + fn query_weight_to_fee(weight: Weight) -> Balance { TransactionPayment::weight_to_fee(weight) } + fn query_length_to_fee(length: u32) -> Balance { TransactionPayment::length_to_fee(length) } + } impl cumulus_primitives_core::CollectCollationInfo for Runtime { @@ -787,18 +779,21 @@ impl_runtime_apis! { #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { - fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { - let weight = Executive::try_runtime_upgrade(checks).unwrap(); + fn on_runtime_upgrade() -> (Weight, Weight) { + log::info!("try-runtime::on_runtime_upgrade statemine."); + let weight = Executive::try_runtime_upgrade().unwrap(); (weight, RuntimeBlockWeights::get().max_block) } - fn execute_block( - block: Block, - state_root_check: bool, - signature_check: bool, - select: frame_try_runtime::TryStateSelect, - ) -> Weight { - Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap() + fn execute_block(block: Block, state_root_check: bool, select: frame_try_runtime::TryStateSelect) -> Weight { + log::info!( + target: "runtime::statemine", "try-runtime: executing block #{} ({:?}) / root checks: {:?} / sanity-checks: {:?}", + block.header.number, + block.header.hash(), + state_root_check, + select, + ); + Executive::try_execute_block(block, state_root_check, select).expect("try_execute_block failed") } } @@ -808,6 +803,7 @@ impl_runtime_apis! { Vec, Vec, ) { + use frame_benchmarking::{Benchmarking, BenchmarkList}; use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; @@ -823,7 +819,7 @@ impl_runtime_apis! { fn dispatch_benchmark( config: frame_benchmarking::BenchmarkConfig ) -> Result, sp_runtime::RuntimeString> { - use frame_benchmarking::{Benchmarking, BenchmarkBatch}; + use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey}; use frame_system_benchmarking::Pallet as SystemBench; impl frame_system_benchmarking::Config for Runtime {} @@ -831,14 +827,25 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} - use frame_support::traits::WhitelistedStorageKeys; - let whitelist = AllPalletsWithSystem::whitelisted_storage_keys(); + let whitelist: Vec = vec![ + // Block Number + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), + // Total Issuance + hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(), + // Execution Phase + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(), + // Event Count + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(), + // System Events + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(), + //TODO: use from relay_well_known_keys::ACTIVE_CONFIG + hex_literal::hex!("06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385").to_vec().into(), + ]; let mut batches = Vec::::new(); let params = (&config, &whitelist); add_benchmarks!(params, batches); - if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } Ok(batches) } } diff --git a/runtimes/testnet/src/xcm_config.rs b/runtimes/testnet/src/xcm_config.rs index 75b876ee7..b450763d1 100644 --- a/runtimes/testnet/src/xcm_config.rs +++ b/runtimes/testnet/src/xcm_config.rs @@ -26,7 +26,7 @@ use core::marker::PhantomData; use frame_support::{ match_types, parameter_types, traits::{ - fungibles::{self, Balanced, Credit}, + fungibles::{self, Balanced, CreditOf}, ConstU32, Contains, ContainsPair, Everything, Get, Nothing, }, weights::Weight, @@ -53,7 +53,7 @@ use xcm_executor::{ }; use super::{ - AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Balance, Balances, EnsureRoot, + AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Balance, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, StatemintAssets, WeightToFee, XcmpQueue, }; @@ -154,7 +154,7 @@ impl< ConvertedConcreteId::::matches_fungibles( a, ) - .map_err(|_| Error::AssetNotHandled) + .map_err(|_| Error::AssetNotFound) } } @@ -303,7 +303,7 @@ where R: pallet_authorship::Config + pallet_assets::Config, AccountIdOf: From + Into, { - fn handle_credit(credit: Credit, pallet_assets::Pallet>) { + fn handle_credit(credit: CreditOf, pallet_assets::Pallet>) { if let Some(author) = pallet_authorship::Pallet::::author() { // In case of error: Will drop the result triggering the `OnDrop` of the imbalance. let _ = pallet_assets::Pallet::::resolve(&author, credit); @@ -437,7 +437,6 @@ impl pallet_xcm::Config for Runtime { type SovereignAccountOf = LocationToAccountId; type MaxLockers = ConstU32<8>; type WeightInfo = pallet_xcm::TestWeightInfo; - type AdminOrigin = EnsureRoot; #[cfg(feature = "runtime-benchmarks")] type ReachableDest = ReachableDest; } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 084fd8d11..f805bace5 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.69.0" +channel = "nightly-2022-11-15" components = [ "rustfmt", "clippy" ] targets = [ "wasm32-unknown-unknown" ] \ No newline at end of file From 15371ac7c0828dff88eb68a533b2da0ba9289824 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:50:57 +0200 Subject: [PATCH 58/80] Revert "make integration tests compile" This reverts commit edb84f6c2574c0d8a4964657a18d3b4d959e28ee. --- integration-tests/src/lib.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs index 4a5e6dfde..09b481930 100644 --- a/integration-tests/src/lib.rs +++ b/integration-tests/src/lib.rs @@ -97,6 +97,9 @@ fn statemint_id() -> u32 { fn penpal_id() -> u32 { _para_ids()[2] } +fn provider_id() -> u32 { + _para_ids()[3] +} // Helper functions to calculate chain accounts struct ParachainAccounts; @@ -121,6 +124,9 @@ impl ParachainAccounts { fn penpal_sibling_account() -> RuntimeAccountId32 { SiblingId::from(penpal_id()).into_account_truncating() } + fn provider_sibling_account() -> RuntimeAccountId32 { + SiblingId::from(provider_id()).into_account_truncating() + } } fn default_parachains_host_configuration( @@ -223,6 +229,7 @@ pub fn polimec_ext(para_id: u32) -> sp_io::TestExternalities { (DISPATCHER_ACCOUNT, INITIAL_BALANCE), (ParachainAccounts::penpal_sibling_account(), INITIAL_BALANCE), (ParachainAccounts::statemint_sibling_account(), INITIAL_BALANCE), + (ParachainAccounts::provider_sibling_account(), INITIAL_BALANCE), ], } .assimilate_storage(&mut t) @@ -236,12 +243,7 @@ pub fn polimec_ext(para_id: u32) -> sp_io::TestExternalities { 12, )], accounts: vec![(RELAY_ASSET_ID, ALICE, INITIAL_BALANCE)], - assets: vec![( - RELAY_ASSET_ID, - frame_support::PalletId(*b"assetsid").into_account_truncating(), - false, - 1_0_000_000_000, - )], + ..Default::default() } .assimilate_storage(&mut t) .unwrap(); From b6ee734a1dd39716b58ec455af7e2af9b8f2045d Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:50:58 +0200 Subject: [PATCH 59/80] Revert "feat: the big cleanup" This reverts commit ebc45aff9ba07db3f56af71856e4c3e24c7a2d07. --- Cargo.lock | 1390 ++++++++--------- Cargo.toml | 32 +- integration-tests/Cargo.toml | 16 +- integration-tests/src/lib.rs | 176 ++- nodes/parachain/Cargo.toml | 1 - nodes/parachain/src/chain_spec.rs | 6 +- nodes/parachain/src/chain_spec/base.rs | 197 ++- nodes/parachain/src/chain_spec/testnet.rs | 350 +++-- nodes/parachain/src/cli.rs | 9 +- nodes/parachain/src/command.rs | 110 +- nodes/parachain/src/rpc.rs | 10 +- nodes/parachain/src/service.rs | 136 +- nodes/standalone/src/benchmarking.rs | 5 +- nodes/standalone/src/chain_spec.rs | 12 +- nodes/standalone/src/command.rs | 104 +- nodes/standalone/src/rpc.rs | 10 +- nodes/standalone/src/service.rs | 128 +- pallets/funding/Cargo.toml | 2 + pallets/funding/src/benchmarking.rs | 16 +- pallets/funding/src/functions.rs | 315 ++-- pallets/funding/src/lib.rs | 128 +- pallets/funding/src/mock.rs | 13 +- pallets/funding/src/tests.rs | 429 +++-- pallets/funding/src/types.rs | 107 +- pallets/sandbox/Cargo.toml | 2 + pallets/sandbox/src/lib.rs | 15 +- pallets/sandbox/src/mock.rs | 13 +- pallets/sandbox/src/tests.rs | 46 +- polimec-skeleton/pallets/funding/src/mock.rs | 1 + primitives/xcm/Cargo.toml | 18 + primitives/xcm/src/lib.rs | 63 + runtimes/base/Cargo.toml | 9 +- runtimes/base/src/currency.rs | 14 + runtimes/base/src/lib.rs | 320 +++- .../src/weights/block_weights.rs | 2 +- .../src/weights/extrinsic_weights.rs | 2 +- .../src/lib.rs => base/src/weights/mod.rs} | 19 +- .../src/weights/paritydb_weights.rs | 0 .../src/weights/rocksdb_weights.rs | 0 runtimes/base/src/xcm_config.rs | 16 +- runtimes/shared-configuration/Cargo.toml | 28 - runtimes/shared-configuration/src/currency.rs | 64 - runtimes/shared-configuration/src/fee.rs | 48 - runtimes/shared-configuration/src/funding.rs | 64 - .../shared-configuration/src/governance.rs | 105 -- runtimes/shared-configuration/src/staking.rs | 38 - .../shared-configuration/src/weights/mod.rs | 63 - runtimes/standalone/Cargo.toml | 4 + runtimes/standalone/src/lib.rs | 103 +- runtimes/testnet/Cargo.toml | 20 +- runtimes/testnet/src/dip.rs | 169 ++ runtimes/testnet/src/lib.rs | 457 ++++-- runtimes/testnet/src/weights/block_weights.rs | 53 + .../testnet/src/weights/extrinsic_weights.rs | 52 + .../assets.rs => testnet/src/weights/mod.rs} | 25 +- .../testnet/src/weights/pallet_funding.rs | 202 +++ .../testnet/src/weights/paritydb_weights.rs | 62 + .../testnet/src/weights/rocksdb_weights.rs | 62 + runtimes/testnet/src/xcm_config.rs | 59 +- rustfmt.toml | 30 +- traits/Cargo.toml | 42 + traits/src/lib.rs | 83 + 62 files changed, 3440 insertions(+), 2635 deletions(-) create mode 100644 primitives/xcm/Cargo.toml create mode 100644 primitives/xcm/src/lib.rs create mode 100644 runtimes/base/src/currency.rs rename runtimes/{shared-configuration => base}/src/weights/block_weights.rs (94%) rename runtimes/{shared-configuration => base}/src/weights/extrinsic_weights.rs (94%) rename runtimes/{shared-configuration/src/lib.rs => base/src/weights/mod.rs} (67%) rename runtimes/{shared-configuration => base}/src/weights/paritydb_weights.rs (100%) rename runtimes/{shared-configuration => base}/src/weights/rocksdb_weights.rs (100%) delete mode 100644 runtimes/shared-configuration/Cargo.toml delete mode 100644 runtimes/shared-configuration/src/currency.rs delete mode 100644 runtimes/shared-configuration/src/fee.rs delete mode 100644 runtimes/shared-configuration/src/funding.rs delete mode 100644 runtimes/shared-configuration/src/governance.rs delete mode 100644 runtimes/shared-configuration/src/staking.rs delete mode 100644 runtimes/shared-configuration/src/weights/mod.rs create mode 100644 runtimes/testnet/src/dip.rs create mode 100644 runtimes/testnet/src/weights/block_weights.rs create mode 100644 runtimes/testnet/src/weights/extrinsic_weights.rs rename runtimes/{shared-configuration/src/assets.rs => testnet/src/weights/mod.rs} (59%) create mode 100644 runtimes/testnet/src/weights/pallet_funding.rs create mode 100644 runtimes/testnet/src/weights/paritydb_weights.rs create mode 100644 runtimes/testnet/src/weights/rocksdb_weights.rs create mode 100644 traits/Cargo.toml create mode 100644 traits/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 9949fb987..cb0864f2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,11 +23,11 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.20.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" dependencies = [ - "gimli 0.27.3", + "gimli 0.27.2", ] [[package]] @@ -90,9 +90,9 @@ dependencies = [ [[package]] name = "aes" -version = "0.8.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241" dependencies = [ "cfg-if", "cipher 0.4.4", @@ -120,7 +120,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "209b47e8954a928e1d72e86eca7000ebb6655fe1436d33eefc2201cad027e237" dependencies = [ "aead 0.5.2", - "aes 0.8.3", + "aes 0.8.2", "cipher 0.4.4", "ctr 0.9.2", "ghash 0.5.0", @@ -153,7 +153,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.9", "once_cell", "version_check", ] @@ -165,31 +165,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ "cfg-if", - "getrandom 0.2.10", + "getrandom 0.2.9", "once_cell", "version_check", ] [[package]] name = "aho-corasick" -version = "1.0.2" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] [[package]] -name = "always-assert" -version = "0.1.3" +name = "aho-corasick" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4436e0292ab1bb631b42973c61205e704475fe8126af845c8d923c0996328127" +checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +dependencies = [ + "memchr", +] [[package]] -name = "android-tzdata" -version = "0.1.1" +name = "always-assert" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" +checksum = "4436e0292ab1bb631b42973c61205e704475fe8126af845c8d923c0996328127" [[package]] name = "android_system_properties" @@ -226,15 +229,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" +checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" [[package]] name = "anstyle-parse" -version = "0.2.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" dependencies = [ "utf8parse", ] @@ -305,9 +308,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" [[package]] name = "asn1-rs" @@ -322,7 +325,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.23", + "time 0.3.21", ] [[package]] @@ -338,7 +341,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.23", + "time 0.3.21", ] [[package]] @@ -402,9 +405,9 @@ dependencies = [ "log", "parking", "polling", - "rustix 0.37.23", + "rustix 0.37.19", "slab", - "socket2 0.4.9", + "socket2", "waker-fn", ] @@ -419,13 +422,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.71" +version = "0.1.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a564d521dd56509c4c47480d00b80ee55f7e385ae48db5744c67ad50c92d2ebf" +checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.16", ] [[package]] @@ -438,7 +441,7 @@ dependencies = [ "futures-sink", "futures-util", "memchr", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.9", ] [[package]] @@ -466,16 +469,16 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.68" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" dependencies = [ - "addr2line 0.20.0", + "addr2line 0.19.0", "cc", "cfg-if", "libc", - "miniz_oxide", - "object 0.31.1", + "miniz_oxide 0.6.2", + "object 0.30.3", "rustc-demangle", ] @@ -505,9 +508,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.2" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "3f1e31e207a6b8fb791a38ea3105e6cb541f55e4d029902d3039a4ad07cc4105" [[package]] name = "base64ct" @@ -601,7 +604,7 @@ version = "0.64.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" dependencies = [ - "bitflags 1.3.2", + "bitflags", "cexpr", "clang-sys", "lazy_static", @@ -621,12 +624,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bitflags" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" - [[package]] name = "bitvec" version = "1.0.1" @@ -655,8 +652,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc" dependencies = [ "arrayref", - "arrayvec 0.7.4", - "constant_time_eq 0.2.6", + "arrayvec 0.7.2", + "constant_time_eq", ] [[package]] @@ -666,21 +663,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6637f448b9e61dfadbdcbae9a885fadee1f3eaffb1f8d3c1965d3ade8bdfd44f" dependencies = [ "arrayref", - "arrayvec 0.7.4", - "constant_time_eq 0.2.6", + "arrayvec 0.7.2", + "constant_time_eq", ] [[package]] name = "blake3" -version = "1.4.1" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "199c42ab6972d92c9f8995f086273d25c42fc0f7b2a1fcefba465c1352d25ba5" +checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef" dependencies = [ "arrayref", - "arrayvec 0.7.4", + "arrayvec 0.7.2", "cc", "cfg-if", - "constant_time_eq 0.3.0", + "constant_time_eq", "digest 0.10.7", ] @@ -741,9 +738,9 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "bounded-collections" -version = "0.1.8" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b05133427c07c4776906f673ccf36c21b102c9829c641a5b56bd151d44fd6" +checksum = "07fbd1d11282a1eb134d3c3b7cf8ce213b5161c6e5f73fb1b98618482c606b64" dependencies = [ "log", "parity-scale-codec", @@ -768,9 +765,9 @@ checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] name = "bstr" -version = "1.6.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" +checksum = "a246e68bb43f6cd9db24bea052a53e40405417c5fb372e3d1a8a7f770a564ef5" dependencies = [ "memchr", "serde", @@ -834,9 +831,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.6" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" +checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" dependencies = [ "serde", ] @@ -941,13 +938,13 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" dependencies = [ - "android-tzdata", "iana-time-zone", "js-sys", + "num-integer", "num-traits", "time 0.1.45", "wasm-bindgen", @@ -1017,9 +1014,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.11" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1640e5cc7fb47dbb8338fd471b105e7ed6c3cb2aeb00c2e067127ffd3764a05d" +checksum = "93aae7a4192245f70fe75dd9157fc7b4a5bf53e88d30bd4396f7d8f9284d5acc" dependencies = [ "clap_builder", "clap_derive", @@ -1028,26 +1025,27 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.3.11" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c59138d527eeaf9b53f35a77fcc1fad9d883116070c63d5de1c7dc7b00c72b" +checksum = "4f423e341edefb78c9caba2d9c7f7687d0e72e89df3ce3394554754393ac3990" dependencies = [ "anstream", "anstyle", + "bitflags", "clap_lex", "strsim", ] [[package]] name = "clap_derive" -version = "4.3.2" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" +checksum = "191d9573962933b4027f932c600cd252ce27a8ad5979418fe78e43c07996f27b" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.16", ] [[package]] @@ -1086,9 +1084,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "comfy-table" -version = "6.2.0" +version = "6.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e959d788268e3bf9d35ace83e81b124190378e4c91c9067524675e33394b8ba" +checksum = "6e7b787b0dc42e8111badfdbe4c3059158ccb2db8780352fa1b01e8ccf45cc4d" dependencies = [ "strum", "strum_macros", @@ -1106,21 +1104,15 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" - -[[package]] -name = "constant_time_eq" -version = "0.2.6" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" +checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" [[package]] name = "constant_time_eq" -version = "0.3.0" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +checksum = "13418e745008f7349ec7e449155f419a61b92b58a99cc3616942b926825ec76b" [[package]] name = "convert_case" @@ -1174,9 +1166,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" dependencies = [ "libc", ] @@ -1196,7 +1188,7 @@ version = "0.93.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "253531aca9b6f56103c9420369db3263e784df39aa1c90685a1f69cfbba0623e" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.2", "bumpalo", "cranelift-bforest", "cranelift-codegen-meta", @@ -1327,14 +1319,14 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", - "memoffset 0.9.0", + "memoffset 0.8.0", "scopeguard", ] @@ -1350,9 +1342,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" dependencies = [ "cfg-if", ] @@ -1383,7 +1375,7 @@ checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ "generic-array 0.14.7", "rand_core 0.6.4", - "typenum 1.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum", ] [[package]] @@ -1424,6 +1416,26 @@ dependencies = [ "cipher 0.4.4", ] +[[package]] +name = "ctype" +version = "1.11.0-dev" +source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "kilt-support", + "log", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-keystore", + "sp-runtime", + "sp-std", +] + [[package]] name = "cumulus-client-cli" version = "0.1.0" @@ -1960,9 +1972,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.100" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e928d50d5858b744d1ea920b790641129c347a770d1530c3a85b77705a5ee031" +checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" dependencies = [ "cc", "cxxbridge-flags", @@ -1972,9 +1984,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.100" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8332ba63f8a8040ca479de693150129067304a3496674477fff6d0c372cc34ae" +checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" dependencies = [ "cc", "codespan-reporting", @@ -1982,24 +1994,24 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.25", + "syn 2.0.16", ] [[package]] name = "cxxbridge-flags" -version = "1.0.100" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5966a5a87b6e9bb342f5fab7170a93c77096efe199872afffc4b477cfeb86957" +checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" [[package]] name = "cxxbridge-macro" -version = "1.0.100" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b2dab6991c7ab1572fea8cb049db819b1aeea1e2dac74c0869f244d9f21a7c" +checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.16", ] [[package]] @@ -2168,6 +2180,26 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "did" +version = "1.11.0-dev" +source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" +dependencies = [ + "ctype", + "frame-support", + "frame-system", + "kilt-support", + "log", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-keystore", + "sp-runtime", + "sp-std", +] + [[package]] name = "difflib" version = "0.4.0" @@ -2203,6 +2235,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "dip-support" +version = "1.11.0-dev" +source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" +dependencies = [ + "frame-support", + "parity-scale-codec", + "scale-info", +] + [[package]] name = "directories" version = "4.0.1" @@ -2252,7 +2294,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.16", ] [[package]] @@ -2269,9 +2311,9 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" [[package]] name = "dtoa" -version = "1.0.8" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "519b83cd10f5f6e969625a409f735182bea5558cd8b64c655806ceaae36f1999" +checksum = "65d09067bfacaa79114679b279d7f5885b53295b1e2cfb4e79c8e4bd3d633169" [[package]] name = "dyn-clonable" @@ -2406,18 +2448,18 @@ checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.16", ] [[package]] name = "enumn" -version = "0.1.10" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9838a970f5de399d3070ae1739e131986b2f5dcc223c7423ca0927e3a878522" +checksum = "48016319042fb7c87b78d2993084a831793a897a5cd1a2a67cab9d1eeb4b7d76" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.16", ] [[package]] @@ -2452,12 +2494,6 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - [[package]] name = "errno" version = "0.3.1" @@ -2557,7 +2593,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5aa1e3ae159e592ad222dc90c5acbad632b527779ba88486abe92782ab268bd" dependencies = [ "expander 0.0.4", - "indexmap 1.9.3", + "indexmap", "proc-macro-crate", "proc-macro2", "quote", @@ -2654,7 +2690,7 @@ checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" dependencies = [ "crc32fast", "libz-sys", - "miniz_oxide", + "miniz_oxide 0.7.1", ] [[package]] @@ -2682,9 +2718,9 @@ dependencies = [ [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ "percent-encoding", ] @@ -2845,7 +2881,7 @@ name = "frame-support" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ - "bitflags 1.3.2", + "bitflags", "frame-metadata", "frame-support-procedural", "impl-trait-for-tuples", @@ -3045,7 +3081,7 @@ dependencies = [ "futures-io", "memchr", "parking", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.9", "waker-fn", ] @@ -3057,7 +3093,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.16", ] [[package]] @@ -3102,7 +3138,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.9", "pin-utils", "slab", ] @@ -3122,7 +3158,7 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" dependencies = [ - "typenum 1.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum", ] [[package]] @@ -3131,7 +3167,7 @@ version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ - "typenum 1.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum", "version_check", ] @@ -3158,9 +3194,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" dependencies = [ "cfg-if", "libc", @@ -3184,7 +3220,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" dependencies = [ "opaque-debug 0.3.0", - "polyval 0.6.1", + "polyval 0.6.0", ] [[package]] @@ -3194,15 +3230,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" dependencies = [ "fallible-iterator", - "indexmap 1.9.3", + "indexmap", "stable_deref_trait", ] [[package]] name = "gimli" -version = "0.27.3" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" [[package]] name = "glob" @@ -3212,11 +3248,11 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.11" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1391ab1f92ffcc08911957149833e682aa3fe252b9f45f966d2ef972274c97df" +checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ - "aho-corasick", + "aho-corasick 0.7.20", "bstr", "fnv", "log", @@ -3236,9 +3272,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.20" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" dependencies = [ "bytes", "fnv", @@ -3246,7 +3282,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap", "slab", "tokio", "tokio-util", @@ -3300,12 +3336,6 @@ dependencies = [ "ahash 0.8.3", ] -[[package]] -name = "hashbrown" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" - [[package]] name = "heck" version = "0.4.1" @@ -3323,9 +3353,18 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" [[package]] name = "hex" @@ -3418,7 +3457,7 @@ checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", "http", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.9", ] [[package]] @@ -3447,9 +3486,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" dependencies = [ "bytes", "futures-channel", @@ -3461,8 +3500,8 @@ dependencies = [ "httparse", "httpdate", "itoa", - "pin-project-lite 0.2.10", - "socket2 0.4.9", + "pin-project-lite 0.2.9", + "socket2", "tokio", "tower-service", "tracing", @@ -3486,9 +3525,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3526,9 +3565,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -3603,16 +3642,6 @@ dependencies = [ "serde", ] -[[package]] -name = "indexmap" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" -dependencies = [ - "equivalent", - "hashbrown 0.14.0", -] - [[package]] name = "inout" version = "0.1.3" @@ -3646,38 +3675,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "integration-tests" -version = "0.1.0" -dependencies = [ - "cumulus-pallet-xcm", - "cumulus-primitives-core", - "frame-support", - "frame-system", - "pallet-assets", - "pallet-balances", - "pallet-xcm", - "parachain-info", - "parity-scale-codec", - "penpal-runtime", - "polimec-parachain-runtime", - "polkadot-core-primitives", - "polkadot-parachain", - "polkadot-runtime", - "polkadot-runtime-parachains", - "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", - "statemint-runtime", - "substrate-wasm-builder", - "xcm", - "xcm-builder", - "xcm-emulator", - "xcm-executor", -] - [[package]] name = "interceptor" version = "0.8.2" @@ -3699,11 +3696,11 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.11" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi 0.3.1", "libc", "windows-sys 0.48.0", ] @@ -3716,30 +3713,31 @@ checksum = "aa2f047c0a98b2f299aa5d6d7088443570faae494e9ae1305e48be000c9e0eb1" [[package]] name = "ipconfig" -version = "0.3.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +checksum = "bd302af1b90f2463a98fa5ad469fc212c8e3175a41c3068601bfa2727591c5be" dependencies = [ - "socket2 0.5.3", + "socket2", "widestring", - "windows-sys 0.48.0", + "winapi", "winreg", ] [[package]] name = "ipnet" -version = "2.8.0" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ - "hermit-abi 0.3.2", - "rustix 0.38.4", + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix 0.37.19", "windows-sys 0.48.0", ] @@ -3754,9 +3752,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.8" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "jobserver" @@ -3769,9 +3767,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" dependencies = [ "wasm-bindgen", ] @@ -3818,7 +3816,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4e70b4439a751a5de7dd5ed55eacff78ebf4ffe0fc009cb1ebb11417f5b536b" dependencies = [ "anyhow", - "arrayvec 0.7.4", + "arrayvec 0.7.2", "async-lock", "async-trait", "beef", @@ -3909,7 +3907,7 @@ dependencies = [ "cfg-if", "ecdsa", "elliptic-curve", - "sha2 0.10.7", + "sha2 0.10.6", ] [[package]] @@ -3921,6 +3919,39 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "kilt-dip-support" +version = "1.11.0-dev" +source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" +dependencies = [ + "did", + "frame-support", + "frame-system", + "pallet-dip-consumer", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std", + "sp-trie", +] + +[[package]] +name = "kilt-support" +version = "1.11.0-dev" +source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" +dependencies = [ + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-runtime", + "sp-std", +] + [[package]] name = "kusama-runtime" version = "0.9.39-1" @@ -4080,9 +4111,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" [[package]] name = "libloading" @@ -4115,7 +4146,7 @@ dependencies = [ "bytes", "futures", "futures-timer", - "getrandom 0.2.10", + "getrandom 0.2.9", "instant", "libp2p-core 0.38.0", "libp2p-dns", @@ -4166,7 +4197,7 @@ dependencies = [ "rand 0.8.5", "rw-stream-sink", "sec1", - "sha2 0.10.7", + "sha2 0.10.6", "smallvec", "thiserror", "unsigned-varint", @@ -4250,7 +4281,7 @@ dependencies = [ "multihash 0.17.0", "quick-protobuf", "rand 0.8.5", - "sha2 0.10.7", + "sha2 0.10.6", "thiserror", "zeroize", ] @@ -4261,7 +4292,7 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2766dcd2be8c87d5e1f35487deb22d765f49c6ae1251b3633efe3b25698bd3d2" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.2", "asynchronous-codec", "bytes", "either", @@ -4275,7 +4306,7 @@ dependencies = [ "prost", "prost-build", "rand 0.8.5", - "sha2 0.10.7", + "sha2 0.10.6", "smallvec", "thiserror", "uint", @@ -4297,7 +4328,7 @@ dependencies = [ "log", "rand 0.8.5", "smallvec", - "socket2 0.4.9", + "socket2", "tokio", "trust-dns-proto", "void", @@ -4350,7 +4381,7 @@ dependencies = [ "prost", "prost-build", "rand 0.8.5", - "sha2 0.10.7", + "sha2 0.10.6", "snow", "static_assertions", "thiserror", @@ -4458,7 +4489,7 @@ dependencies = [ "libc", "libp2p-core 0.38.0", "log", - "socket2 0.4.9", + "socket2", "tokio", ] @@ -4590,7 +4621,7 @@ dependencies = [ "rand 0.8.5", "serde", "sha2 0.9.9", - "typenum 1.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum", ] [[package]] @@ -4635,9 +4666,9 @@ dependencies = [ [[package]] name = "link-cplusplus" -version = "1.0.9" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" dependencies = [ "cc", ] @@ -4659,9 +4690,9 @@ dependencies = [ [[package]] name = "linregress" -version = "0.5.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4de0b5f52a9f84544d268f5fabb71b38962d6aa3c6600b8bcd27d44ccf9c9c45" +checksum = "475015a7f8f017edb28d2e69813be23500ad4b32cfe3421c4148efc97324ee52" dependencies = [ "nalgebra", ] @@ -4678,17 +4709,11 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" -[[package]] -name = "linux-raw-sys" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" - [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", @@ -4696,9 +4721,12 @@ dependencies = [ [[package]] name = "log" -version = "0.4.19" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] [[package]] name = "lru" @@ -4768,7 +4796,7 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" dependencies = [ - "regex-automata 0.1.10", + "regex-automata", ] [[package]] @@ -4808,7 +4836,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffc89ccdc6e10d6907450f753537ebc5c5d3460d2e4e62ea74bd571db62c0f9e" dependencies = [ - "rustix 0.37.23", + "rustix 0.37.19", ] [[package]] @@ -4840,9 +4868,9 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.9.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" dependencies = [ "autocfg", ] @@ -4892,6 +4920,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + [[package]] name = "miniz_oxide" version = "0.7.1" @@ -4903,13 +4940,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ "libc", + "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", + "windows-sys 0.45.0", ] [[package]] @@ -5034,7 +5072,7 @@ dependencies = [ "core2", "digest 0.10.7", "multihash-derive", - "sha2 0.10.7", + "sha2 0.10.6", "sha3", "unsigned-varint", ] @@ -5086,9 +5124,9 @@ dependencies = [ [[package]] name = "nalgebra" -version = "0.32.3" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307ed9b18cc2423f29e83f84fd23a8e73628727990181f18641a8b5dc2ab1caa" +checksum = "d68d47bba83f9e2006d117a9a33af1524e655516b8919caac694427a6fb1e511" dependencies = [ "approx", "matrixmultiply", @@ -5097,14 +5135,14 @@ dependencies = [ "num-rational", "num-traits", "simba", - "typenum 1.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum", ] [[package]] name = "nalgebra-macros" -version = "0.2.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91761aed67d03ad966ef783ae962ef9bbaca728d2dd7ceb7939ec110fffad998" +checksum = "d232c68884c0c99810a5a4d333ef7e47689cfd0edc85efc9e54e1e6bf5212766" dependencies = [ "proc-macro2", "quote", @@ -5145,7 +5183,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9ea4302b9759a7a88242299225ea3688e63c85ea136371bb6cf94fd674efaab" dependencies = [ "anyhow", - "bitflags 1.3.2", + "bitflags", "byteorder", "libc", "netlink-packet-core", @@ -5198,7 +5236,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ - "bitflags 1.3.2", + "bitflags", "cfg-if", "libc", "memoffset 0.6.5", @@ -5210,7 +5248,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" dependencies = [ - "bitflags 1.3.2", + "bitflags", "cfg-if", "libc", "memoffset 0.7.1", @@ -5266,7 +5304,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.2", "itoa", ] @@ -5303,11 +5341,11 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.16.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi 0.2.6", "libc", ] @@ -5319,15 +5357,15 @@ checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ "crc32fast", "hashbrown 0.12.3", - "indexmap 1.9.3", + "indexmap", "memchr", ] [[package]] name = "object" -version = "0.31.1" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" dependencies = [ "memchr", ] @@ -5352,9 +5390,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.18.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "opaque-debug" @@ -5423,7 +5461,7 @@ checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" dependencies = [ "ecdsa", "elliptic-curve", - "sha2 0.10.7", + "sha2 0.10.6", ] [[package]] @@ -5434,7 +5472,7 @@ checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa" dependencies = [ "ecdsa", "elliptic-curve", - "sha2 0.10.7", + "sha2 0.10.6", ] [[package]] @@ -5736,6 +5774,45 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-did-lookup" +version = "1.11.0-dev" +source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" +dependencies = [ + "base58", + "blake2", + "frame-benchmarking", + "frame-support", + "frame-system", + "hex", + "kilt-support", + "libsecp256k1", + "log", + "parity-scale-codec", + "scale-info", + "serde", + "sha3", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + +[[package]] +name = "pallet-dip-consumer" +version = "1.11.0-dev" +source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" +dependencies = [ + "cumulus-pallet-xcm", + "dip-support", + "frame-support", + "frame-system", + "kilt-support", + "parity-scale-codec", + "scale-info", + "sp-std", +] + [[package]] name = "pallet-election-provider-multi-phase" version = "4.0.0-dev" @@ -5819,6 +5896,7 @@ dependencies = [ "pallet-balances", "pallet-insecure-randomness-collective-flip", "parity-scale-codec", + "polimec-traits", "scale-info", "sp-arithmetic", "sp-core", @@ -6072,26 +6150,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-parachain-staking" -version = "3.0.0" -source = "git+https://gitlab.com/Omegabit/stake-patch#28a788327c7dbf408060cbe0b1f0109bd8533260" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "log", - "pallet-authorship", - "pallet-session", - "parity-scale-codec", - "scale-info", - "serde", - "sp-runtime", - "sp-staking", - "sp-std", - "substrate-fixed", -] - [[package]] name = "pallet-preimage" version = "4.0.0-dev" @@ -6189,6 +6247,7 @@ dependencies = [ "pallet-insecure-randomness-collective-flip", "parachains-common", "parity-scale-codec", + "polimec-traits", "scale-info", "serde", "sp-arithmetic", @@ -6447,21 +6506,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-uniques" -version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "log", - "parity-scale-codec", - "scale-info", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-utility" version = "4.0.0-dev" @@ -6589,9 +6633,9 @@ dependencies = [ [[package]] name = "parity-db" -version = "0.4.9" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dab3ac198341b2f0fec6e7f8a6eeed07a41201d98a124260611598c142e76df" +checksum = "4890dcb9556136a4ec2b0c51fa4a08c8b733b829506af8fff2e853f3a065985b" dependencies = [ "blake2", "crc32fast", @@ -6609,11 +6653,11 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.3" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "756d439303e94fae44f288ba881ad29670c65b0c4b0e05674ca81061bb65f2c5" +checksum = "5ddb756ca205bd108aee3c62c6d3c994e1df84a59b9d6d4a5ea42ee1fd5a9a28" dependencies = [ - "arrayvec 0.7.4", + "arrayvec 0.7.2", "bitvec", "byte-slice-cast", "bytes", @@ -6624,9 +6668,9 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.3" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d884d78fcf214d70b1e239fcd1c6e5e95aa3be1881918da2e488cc946c7a476" +checksum = "86b26a931f824dd4eca30b3e43bb4f31cd5f0d3a403c5f5ff27106b805bfde7b" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -6670,7 +6714,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.8", + "parking_lot_core 0.9.7", ] [[package]] @@ -6689,135 +6733,76 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", + "redox_syscall 0.2.16", "smallvec", - "windows-targets 0.48.1", + "windows-sys 0.45.0", ] [[package]] name = "paste" -version = "1.0.13" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4b27ab7be369122c218afc2079489cdcb4b517c0a3fc386ff11e1fedfcc2b35" - -[[package]] -name = "pbkdf2" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" -dependencies = [ - "crypto-mac 0.11.1", -] - -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - -[[package]] -name = "pem" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" -dependencies = [ - "base64 0.13.1", -] - -[[package]] -name = "pem-rfc7468" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac" -dependencies = [ - "base64ct", -] - -[[package]] -name = "penpal-runtime" -version = "0.9.27" -dependencies = [ - "cumulus-pallet-aura-ext", - "cumulus-pallet-dmp-queue", - "cumulus-pallet-parachain-system", - "cumulus-pallet-session-benchmarking", - "cumulus-pallet-xcm", - "cumulus-pallet-xcmp-queue", - "cumulus-primitives-core", - "cumulus-primitives-timestamp", - "cumulus-primitives-utility", - "frame-benchmarking", - "frame-executive", - "frame-support", - "frame-system", - "frame-system-benchmarking", - "frame-system-rpc-runtime-api", - "frame-try-runtime", - "hex-literal", - "log", - "pallet-asset-tx-payment", - "pallet-assets", - "pallet-aura", - "pallet-authorship", - "pallet-balances", - "pallet-collator-selection", - "pallet-session", - "pallet-sudo", - "pallet-timestamp", - "pallet-transaction-payment", - "pallet-transaction-payment-rpc-runtime-api", - "pallet-xcm", - "parachain-info", - "parachains-common", - "parity-scale-codec", - "polkadot-parachain", - "polkadot-primitives", - "polkadot-runtime-common", - "scale-info", - "smallvec", - "sp-api", - "sp-block-builder", - "sp-consensus-aura", - "sp-core", - "sp-inherents", - "sp-offchain", - "sp-runtime", - "sp-session", - "sp-std", - "sp-transaction-pool", - "sp-version", - "substrate-wasm-builder", - "xcm", - "xcm-builder", - "xcm-executor", +checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" + +[[package]] +name = "pbkdf2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" +dependencies = [ + "crypto-mac 0.11.1", +] + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "pem" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +dependencies = [ + "base64 0.13.1", +] + +[[package]] +name = "pem-rfc7468" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac" +dependencies = [ + "base64ct", ] [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.7.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73935e4d55e2abf7f130186537b19e7a4abc886a0252380b59248af473a3fc9" +checksum = "e68e84bfb01f0507134eac1e9b410a12ba379d064eab48c50ba4ce329a527b70" dependencies = [ "thiserror", "ucd-trie", @@ -6825,9 +6810,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef623c9bbfa0eedf5a0efba11a5ee83209c326653ca31ff019bec3a95bfff2b" +checksum = "6b79d4c71c865a25a4322296122e3924d30bc8ee0834c8bfc8b95f7f054afbfb" dependencies = [ "pest", "pest_generator", @@ -6835,26 +6820,26 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e8cba4ec22bada7fc55ffe51e2deb6a0e0db2d0b7ab0b103acc80d2510c190" +checksum = "6c435bf1076437b851ebc8edc3a18442796b30f1728ffea6262d59bbe28b077e" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.16", ] [[package]] name = "pest_meta" -version = "2.7.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01f71cb40bd8bb94232df14b946909e14660e33fc05db3e50ae2a82d7ea0ca0" +checksum = "745a452f8eb71e39ffd8ee32b3c5f51d03845f99786fa9b68db6ff509c505411" dependencies = [ "once_cell", "pest", - "sha2 0.10.7", + "sha2 0.10.6", ] [[package]] @@ -6864,27 +6849,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ "fixedbitset", - "indexmap 1.9.3", + "indexmap", ] [[package]] name = "pin-project" -version = "1.1.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" +checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" +checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.16", ] [[package]] @@ -6895,9 +6880,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.10" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -6958,7 +6943,6 @@ dependencies = [ "pallet-aura", "pallet-authorship", "pallet-balances", - "pallet-parachain-staking", "pallet-session", "pallet-sudo", "pallet-timestamp", @@ -6973,10 +6957,8 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-common", "scale-info", - "shared-configuration", "smallvec", "sp-api", - "sp-arithmetic", "sp-block-builder", "sp-consensus-aura", "sp-core", @@ -7010,7 +6992,6 @@ dependencies = [ "cumulus-relay-chain-minimal-node", "frame-benchmarking", "frame-benchmarking-cli", - "hex-literal", "jsonrpsee", "log", "pallet-transaction-payment-rpc", @@ -7070,6 +7051,7 @@ dependencies = [ "cumulus-primitives-core", "cumulus-primitives-timestamp", "cumulus-primitives-utility", + "did", "frame-benchmarking", "frame-executive", "frame-support", @@ -7078,6 +7060,7 @@ dependencies = [ "frame-system-rpc-runtime-api", "frame-try-runtime", "hex-literal", + "kilt-dip-support", "log", "pallet-asset-tx-payment", "pallet-assets", @@ -7086,10 +7069,11 @@ dependencies = [ "pallet-balances", "pallet-collective", "pallet-democracy", + "pallet-did-lookup", + "pallet-dip-consumer", "pallet-funding", "pallet-insecure-randomness-collective-flip", "pallet-multisig", - "pallet-parachain-staking", "pallet-preimage", "pallet-scheduler", "pallet-session", @@ -7104,12 +7088,12 @@ dependencies = [ "parachain-info", "parachains-common", "parity-scale-codec", + "polimec-traits", "polkadot-parachain", "polkadot-primitives", "polkadot-runtime-common", "scale-info", "serde", - "shared-configuration", "smallvec", "sp-api", "sp-block-builder", @@ -7127,6 +7111,7 @@ dependencies = [ "xcm", "xcm-builder", "xcm-executor", + "xcm-primitives", ] [[package]] @@ -7206,6 +7191,7 @@ dependencies = [ "pallet-utility", "pallet-vesting", "parity-scale-codec", + "polimec-traits", "scale-info", "sp-api", "sp-block-builder", @@ -7221,6 +7207,22 @@ dependencies = [ "substrate-wasm-builder", ] +[[package]] +name = "polimec-traits" +version = "0.1.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "polkadot-approval-distribution" version = "0.9.39-1" @@ -7407,7 +7409,7 @@ dependencies = [ "fatality", "futures", "futures-timer", - "indexmap 1.9.3", + "indexmap", "lru 0.9.0", "parity-scale-codec", "polkadot-erasure-coding", @@ -8188,7 +8190,7 @@ name = "polkadot-runtime-parachains" version = "0.9.39-1" source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" dependencies = [ - "bitflags 1.3.2", + "bitflags", "bitvec", "derive_more", "frame-benchmarking", @@ -8343,7 +8345,7 @@ dependencies = [ "arrayvec 0.5.2", "fatality", "futures", - "indexmap 1.9.3", + "indexmap", "parity-scale-codec", "polkadot-node-network-protocol", "polkadot-node-primitives", @@ -8373,12 +8375,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" dependencies = [ "autocfg", - "bitflags 1.3.2", + "bitflags", "cfg-if", "concurrent-queue", "libc", "log", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.9", "windows-sys 0.48.0", ] @@ -8407,9 +8409,9 @@ dependencies = [ [[package]] name = "polyval" -version = "0.6.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" +checksum = "7ef234e08c11dfcb2e56f79fd70f6f2eb7f025c0ce2333e82f4f0518ecad30c6" dependencies = [ "cfg-if", "cpufeatures", @@ -8528,9 +8530,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.64" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" +checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8" dependencies = [ "unicode-ident", ] @@ -8694,9 +8696,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.29" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" dependencies = [ "proc-macro2", ] @@ -8766,7 +8768,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.9", ] [[package]] @@ -8823,7 +8825,7 @@ checksum = "6413f3de1edee53342e6138e75b56d32e7bc6e332b3bd62d497b1929d4cfbcdd" dependencies = [ "pem", "ring", - "time 0.3.23", + "time 0.3.21", "x509-parser 0.13.2", "yasna", ] @@ -8836,7 +8838,7 @@ checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" dependencies = [ "pem", "ring", - "time 0.3.23", + "time 0.3.21", "yasna", ] @@ -8846,7 +8848,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags 1.3.2", + "bitflags", ] [[package]] @@ -8855,7 +8857,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags 1.3.2", + "bitflags", ] [[package]] @@ -8864,7 +8866,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.9", "redox_syscall 0.2.16", "thiserror", ] @@ -8884,22 +8886,22 @@ dependencies = [ [[package]] name = "ref-cast" -version = "1.0.18" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1641819477c319ef452a075ac34a4be92eb9ba09f6841f62d594d50fdcf0bf6b" +checksum = "f43faa91b1c8b36841ee70e97188a869d37ae21759da6846d4be66de5bf7b12c" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.18" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68bf53dad9b6086826722cdc99140793afd9f62faa14a1ad07eb4f955e7a7216" +checksum = "8d2275aab483050ab2a7364c1a46604865ee7d6906684e08db0f090acf74f9e7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.16", ] [[package]] @@ -8916,14 +8918,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +checksum = "d1a59b5d8e97dee33696bf13c5ba8ab85341c002922fba050069326b9c498974" dependencies = [ - "aho-corasick", + "aho-corasick 1.0.1", "memchr", - "regex-automata 0.3.3", - "regex-syntax 0.7.4", + "regex-syntax 0.7.2", ] [[package]] @@ -8935,17 +8936,6 @@ dependencies = [ "regex-syntax 0.6.29", ] -[[package]] -name = "regex-automata" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.7.4", -] - [[package]] name = "regex-syntax" version = "0.6.29" @@ -8954,9 +8944,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.4" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" [[package]] name = "region" @@ -8964,7 +8954,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e" dependencies = [ - "bitflags 1.3.2", + "bitflags", "libc", "mach", "winapi", @@ -9224,11 +9214,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.36.15" +version = "0.36.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c37f1bd5ef1b5422177b7646cba67430579cfe2ace80f284fee876bca52ad941" +checksum = "14e4d67015953998ad0eb82887a0eb0129e18a7e2f3b7b0f6c422fddcd503d62" dependencies = [ - "bitflags 1.3.2", + "bitflags", "errno", "io-lifetimes", "libc", @@ -9238,11 +9228,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.23" +version = "0.37.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" +checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" dependencies = [ - "bitflags 1.3.2", + "bitflags", "errno", "io-lifetimes", "libc", @@ -9250,19 +9240,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "rustix" -version = "0.38.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" -dependencies = [ - "bitflags 2.3.3", - "errno", - "libc", - "linux-raw-sys 0.4.3", - "windows-sys 0.48.0", -] - [[package]] name = "rustls" version = "0.19.1" @@ -9290,9 +9267,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.6.3" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" dependencies = [ "openssl-probe", "rustls-pemfile", @@ -9302,18 +9279,18 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" dependencies = [ - "base64 0.21.2", + "base64 0.21.1", ] [[package]] name = "rustversion" -version = "1.0.13" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc31bd9b61a32c31f9650d18add92aa83a49ba979c143eefd27fe7177b05bd5f" +checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" [[package]] name = "rw-stream-sink" @@ -9328,9 +9305,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.14" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "safe-mix" @@ -9343,9 +9320,9 @@ dependencies = [ [[package]] name = "safe_arch" -version = "0.7.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62a7484307bd40f8f7ccbacccac730108f2cae119a3b11c74485b48aa9ea650f" +checksum = "794821e4ccb0d9f979512f9c1973480123f9bd62a90d74ab0f9426fcf8f4a529" dependencies = [ "bytemuck", ] @@ -9765,7 +9742,7 @@ dependencies = [ "libc", "log", "once_cell", - "rustix 0.36.15", + "rustix 0.36.14", "sc-allocator", "sc-executor-common", "sp-runtime-interface", @@ -9931,7 +9908,7 @@ version = "0.10.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" dependencies = [ "async-trait", - "bitflags 1.3.2", + "bitflags", "bytes", "futures", "futures-timer", @@ -10432,9 +10409,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.9.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0a159d0c45c12b20c5a844feb1fe4bea86e28f17b92a5f0c42193634d3782" +checksum = "b569c32c806ec3abdf3b5869fb8bf1e0d275a7c1c9b0b05603d9464632649edf" dependencies = [ "bitvec", "cfg-if", @@ -10446,9 +10423,9 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.9.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "912e55f6d20e0e80d63733872b40e1227c0bce1e1ab81ba67d696339bfd7fd29" +checksum = "53012eae69e5aa5c14671942a5dd47de59d4cdcff8532a6dd0e081faf1119482" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -10458,11 +10435,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.42.0", ] [[package]] @@ -10502,9 +10479,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scratch" -version = "1.0.6" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "764cad9e7e1ca5fe15b552859ff5d96a314e6ed2934f2260168cd5dfa5891409" +checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" [[package]] name = "sct" @@ -10585,7 +10562,7 @@ version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" dependencies = [ - "bitflags 1.3.2", + "bitflags", "core-foundation", "core-foundation-sys", "libc", @@ -10637,29 +10614,29 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.171" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30e27d1e4fd7659406c492fd6cfaf2066ba8773de45ca75e855590f856dc34a9" +checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.171" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389894603bd18c46fa56231694f8d827779c0951a667087194cf9de94ed24682" +checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.16", ] [[package]] name = "serde_json" -version = "1.0.102" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5062a995d481b2308b6064e9af76011f2921c35f97b0468811ed9f6cd91dfed" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" dependencies = [ "itoa", "ryu", @@ -10717,9 +10694,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if", "cpufeatures", @@ -10745,17 +10722,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "shared-configuration" -version = "0.1.0" -dependencies = [ - "frame-support", - "frame-system", - "parachains-common", - "smallvec", - "sp-arithmetic", -] - [[package]] name = "shlex" version = "1.1.0" @@ -10838,9 +10804,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "snap" @@ -10861,7 +10827,7 @@ dependencies = [ "rand_core 0.6.4", "ring", "rustc_version 0.4.0", - "sha2 0.10.7", + "sha2 0.10.6", "subtle", ] @@ -10875,16 +10841,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "socket2" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" -dependencies = [ - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "soketto" version = "0.7.1" @@ -11112,7 +11068,7 @@ source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c dependencies = [ "array-bytes 4.2.0", "base58", - "bitflags 1.3.2", + "bitflags", "blake2", "bounded-collections", "dyn-clonable", @@ -11156,7 +11112,7 @@ dependencies = [ "blake2", "byteorder", "digest 0.10.7", - "sha2 0.10.7", + "sha2 0.10.6", "sha3", "sp-std", "twox-hash", @@ -11635,9 +11591,9 @@ dependencies = [ [[package]] name = "ss58-registry" -version = "1.41.0" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfc443bad666016e012538782d9e3006213a7db43e9fb1dda91657dc06a6fa08" +checksum = "eb47a8ad42e5fc72d5b1eb104a5546937eaf39843499948bb666d6e93c62423b" dependencies = [ "Inflector", "num-format", @@ -11654,70 +11610,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "statemint-runtime" -version = "1.0.0" -source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" -dependencies = [ - "cumulus-pallet-aura-ext", - "cumulus-pallet-dmp-queue", - "cumulus-pallet-parachain-system", - "cumulus-pallet-session-benchmarking", - "cumulus-pallet-xcm", - "cumulus-pallet-xcmp-queue", - "cumulus-primitives-core", - "cumulus-primitives-timestamp", - "cumulus-primitives-utility", - "frame-benchmarking", - "frame-executive", - "frame-support", - "frame-system", - "frame-system-benchmarking", - "frame-system-rpc-runtime-api", - "hex-literal", - "log", - "pallet-asset-tx-payment", - "pallet-assets", - "pallet-aura", - "pallet-authorship", - "pallet-balances", - "pallet-collator-selection", - "pallet-multisig", - "pallet-proxy", - "pallet-session", - "pallet-timestamp", - "pallet-transaction-payment", - "pallet-transaction-payment-rpc-runtime-api", - "pallet-uniques", - "pallet-utility", - "pallet-xcm", - "pallet-xcm-benchmarks", - "parachain-info", - "parachains-common", - "parity-scale-codec", - "polkadot-core-primitives", - "polkadot-parachain", - "polkadot-runtime-common", - "polkadot-runtime-constants", - "scale-info", - "smallvec", - "sp-api", - "sp-block-builder", - "sp-consensus-aura", - "sp-core", - "sp-inherents", - "sp-offchain", - "sp-runtime", - "sp-session", - "sp-std", - "sp-transaction-pool", - "sp-version", - "substrate-wasm-builder", - "xcm", - "xcm-builder", - "xcm-executor", -] - [[package]] name = "static_assertions" version = "1.1.0" @@ -11742,7 +11634,7 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a2a1c578e98c1c16fc3b8ec1328f7659a500737d7a0c6d625e73e830ff9c1f6" dependencies = [ - "bitflags 1.3.2", + "bitflags", "cfg_aliases", "libc", "parking_lot 0.11.2", @@ -11845,16 +11737,6 @@ dependencies = [ "platforms 2.0.0", ] -[[package]] -name = "substrate-fixed" -version = "0.5.9" -source = "git+https://github.com/encointer/substrate-fixed#a4fb461aae6205ffc55bed51254a40c52be04e5d" -dependencies = [ - "parity-scale-codec", - "scale-info", - "typenum 1.16.0 (git+https://github.com/encointer/typenum?tag=v1.16.0)", -] - [[package]] name = "substrate-frame-rpc-system" version = "4.0.0-dev" @@ -11963,9 +11845,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.25" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e3fc8c0c74267e2df136e5e5fb656a464158aa57624053375eb9c8c6e25ae2" +checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" dependencies = [ "proc-macro2", "quote", @@ -11990,7 +11872,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ - "bitflags 1.3.2", + "bitflags", "core-foundation", "system-configuration-sys", ] @@ -12013,22 +11895,21 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.12.9" +version = "0.12.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8e77cb757a61f51b947ec4a7e3646efd825b73561db1c232a8ccb639e611a0" +checksum = "fd1ba337640d60c3e96bc6f0638a939b9c9a7f2c316a1598c279828b3d1dc8c5" [[package]] name = "tempfile" -version = "3.6.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" dependencies = [ - "autocfg", "cfg-if", "fastrand", "redox_syscall 0.3.5", - "rustix 0.37.23", - "windows-sys 0.48.0", + "rustix 0.37.19", + "windows-sys 0.45.0", ] [[package]] @@ -12048,22 +11929,22 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "thiserror" -version = "1.0.43" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.43" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.16", ] [[package]] @@ -12138,9 +12019,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.23" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" +checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc" dependencies = [ "itoa", "serde", @@ -12156,9 +12037,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" -version = "0.2.10" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4" +checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" dependencies = [ "time-core", ] @@ -12175,7 +12056,7 @@ dependencies = [ "pbkdf2 0.11.0", "rand 0.8.5", "rustc-hash", - "sha2 0.10.7", + "sha2 0.10.6", "thiserror", "unicode-normalization", "wasm-bindgen", @@ -12209,20 +12090,19 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105" dependencies = [ "autocfg", - "backtrace", "bytes", "libc", "mio", "num_cpus", "parking_lot 0.12.1", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.9", "signal-hook-registry", - "socket2 0.4.9", + "socket2", "tokio-macros", "windows-sys 0.48.0", ] @@ -12235,7 +12115,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.16", ] [[package]] @@ -12256,7 +12136,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" dependencies = [ "futures-core", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.9", "tokio", "tokio-util", ] @@ -12271,7 +12151,7 @@ dependencies = [ "futures-core", "futures-io", "futures-sink", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.9", "tokio", "tracing", ] @@ -12287,17 +12167,17 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" [[package]] name = "toml_edit" -version = "0.19.12" +version = "0.19.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78" +checksum = "92d964908cec0d030b812013af25a0e57fddfadb1e066ecc6681d86253129d4f" dependencies = [ - "indexmap 2.0.0", + "indexmap", "toml_datetime", "winnow", ] @@ -12319,14 +12199,14 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" dependencies = [ - "bitflags 1.3.2", + "bitflags", "bytes", "futures-core", "futures-util", "http", "http-body", "http-range-header", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.9", "tower-layer", "tower-service", ] @@ -12351,20 +12231,20 @@ checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", "log", - "pin-project-lite 0.2.10", + "pin-project-lite 0.2.9", "tracing-attributes", "tracing-core", ] [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.16", ] [[package]] @@ -12494,7 +12374,7 @@ dependencies = [ "lazy_static", "rand 0.8.5", "smallvec", - "socket2 0.4.9", + "socket2", "thiserror", "tinyvec", "tokio", @@ -12608,20 +12488,11 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" -[[package]] -name = "typenum" -version = "1.16.0" -source = "git+https://github.com/encointer/typenum?tag=v1.16.0#4c8dddaa8bdd13130149e43b4085ad14e960617f" -dependencies = [ - "parity-scale-codec", - "scale-info", -] - [[package]] name = "ucd-trie" -version = "0.1.6" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" [[package]] name = "uint" @@ -12643,9 +12514,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.10" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" [[package]] name = "unicode-normalization" @@ -12708,12 +12579,12 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.4.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", - "idna 0.4.0", + "idna 0.3.0", "percent-encoding", ] @@ -12725,11 +12596,11 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.4.0" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d023da39d1fde5a8a3fe1f3e01ca9632ada0a63e9797de55a879d6e2236277be" +checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.9", ] [[package]] @@ -12783,10 +12654,11 @@ dependencies = [ [[package]] name = "want" -version = "0.3.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" dependencies = [ + "log", "try-lock", ] @@ -12810,9 +12682,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -12820,24 +12692,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.16", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" dependencies = [ "cfg-if", "js-sys", @@ -12847,9 +12719,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -12857,22 +12729,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.16", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" [[package]] name = "wasm-instrument" @@ -12979,7 +12851,7 @@ version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64b20236ab624147dfbb62cf12a19aaf66af0e41b8398838b66e997d07d269d4" dependencies = [ - "indexmap 1.9.3", + "indexmap", "url", ] @@ -12992,7 +12864,7 @@ dependencies = [ "anyhow", "bincode", "cfg-if", - "indexmap 1.9.3", + "indexmap", "libc", "log", "object 0.29.0", @@ -13032,9 +12904,9 @@ dependencies = [ "directories-next", "file-per-thread-logger", "log", - "rustix 0.36.15", + "rustix 0.36.14", "serde", - "sha2 0.10.7", + "sha2 0.10.6", "toml", "windows-sys 0.42.0", "zstd", @@ -13070,7 +12942,7 @@ dependencies = [ "anyhow", "cranelift-entity", "gimli 0.26.2", - "indexmap 1.9.3", + "indexmap", "log", "object 0.29.0", "serde", @@ -13112,7 +12984,7 @@ checksum = "eed41cbcbf74ce3ff6f1d07d1b707888166dc408d1a880f651268f4f7c9194b2" dependencies = [ "object 0.29.0", "once_cell", - "rustix 0.36.15", + "rustix 0.36.14", ] [[package]] @@ -13135,7 +13007,7 @@ dependencies = [ "anyhow", "cc", "cfg-if", - "indexmap 1.9.3", + "indexmap", "libc", "log", "mach", @@ -13143,7 +13015,7 @@ dependencies = [ "memoffset 0.6.5", "paste", "rand 0.8.5", - "rustix 0.36.15", + "rustix 0.36.14", "wasmtime-asm-macros", "wasmtime-environ", "wasmtime-jit-debug", @@ -13164,9 +13036,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" dependencies = [ "js-sys", "wasm-bindgen", @@ -13224,10 +13096,10 @@ dependencies = [ "sdp", "serde", "serde_json", - "sha2 0.10.7", + "sha2 0.10.6", "stun", "thiserror", - "time 0.3.23", + "time 0.3.21", "tokio", "turn", "url", @@ -13287,7 +13159,7 @@ dependencies = [ "sec1", "serde", "sha1", - "sha2 0.10.7", + "sha2 0.10.6", "signature", "subtle", "thiserror", @@ -13329,7 +13201,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f08dfd7a6e3987e255c4dbe710dde5d94d0f0574f8a21afa95d171376c143106" dependencies = [ "log", - "socket2 0.4.9", + "socket2", "thiserror", "tokio", "webrtc-util", @@ -13396,7 +13268,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f1db1727772c05cf7a2cfece52c3aca8045ca1e176cd517d323489aa3c6d87" dependencies = [ "async-trait", - "bitflags 1.3.2", + "bitflags", "bytes", "cc", "ipnet", @@ -13529,9 +13401,9 @@ dependencies = [ [[package]] name = "wide" -version = "0.7.11" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa469ffa65ef7e0ba0f164183697b89b854253fd31aeb92358b7b6155177d62f" +checksum = "5cd0496a71f3cc6bc4bf0ed91346426a5099e93d89807e663162dc5a1069ff65" dependencies = [ "bytemuck", "safe_arch", @@ -13539,9 +13411,9 @@ dependencies = [ [[package]] name = "widestring" -version = "1.0.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" +checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" [[package]] name = "winapi" @@ -13593,7 +13465,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.0", ] [[package]] @@ -13626,7 +13498,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.0", ] [[package]] @@ -13646,9 +13518,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" dependencies = [ "windows_aarch64_gnullvm 0.48.0", "windows_aarch64_msvc 0.48.0", @@ -13775,21 +13647,20 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.4.9" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a2094c43cc94775293eaa0e499fbc30048a6d824ac82c0351a8c0bf9112529" +checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699" dependencies = [ "memchr", ] [[package]] name = "winreg" -version = "0.50.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ - "cfg-if", - "windows-sys 0.48.0", + "winapi", ] [[package]] @@ -13839,7 +13710,7 @@ dependencies = [ "ring", "rusticata-macros", "thiserror", - "time 0.3.23", + "time 0.3.21", ] [[package]] @@ -13857,7 +13728,7 @@ dependencies = [ "oid-registry 0.6.1", "rusticata-macros", "thiserror", - "time 0.3.23", + "time 0.3.21", ] [[package]] @@ -13897,32 +13768,6 @@ dependencies = [ "xcm-executor", ] -[[package]] -name = "xcm-emulator" -version = "0.1.0" -source = "git+https://github.com/shaunxw/xcm-simulator?rev=aa13dce47596e150806dfc3af99096dae6ffc65e#aa13dce47596e150806dfc3af99096dae6ffc65e" -dependencies = [ - "cumulus-pallet-dmp-queue", - "cumulus-pallet-parachain-system", - "cumulus-pallet-xcmp-queue", - "cumulus-primitives-core", - "cumulus-primitives-parachain-inherent", - "cumulus-test-relay-sproof-builder", - "frame-support", - "frame-system", - "parachain-info", - "parity-scale-codec", - "paste", - "polkadot-primitives", - "polkadot-runtime-parachains", - "quote", - "sp-arithmetic", - "sp-io", - "sp-std", - "xcm", - "xcm-executor", -] - [[package]] name = "xcm-executor" version = "0.9.39-1" @@ -13943,6 +13788,15 @@ dependencies = [ "xcm", ] +[[package]] +name = "xcm-primitives" +version = "0.0.1" +dependencies = [ + "sp-std", + "xcm", + "xcm-executor", +] + [[package]] name = "xcm-procedural" version = "0.9.39-1" @@ -13974,7 +13828,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" dependencies = [ - "time 0.3.23", + "time 0.3.21", ] [[package]] @@ -13994,7 +13848,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.25", + "syn 2.0.16", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index f71ec117a..ebb8ca791 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,9 @@ [workspace] -members = [ - "nodes/*", - "pallets/*", - "runtimes/*", - "integration-tests" +members = [ "nodes/*", + "pallets/*", + "runtimes/*", + "traits", + # "integration-tests" ] [workspace.package] @@ -46,21 +46,21 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", bran # Internal pallets (with default disabled) pallet-funding = { path = "pallets/funding", default-features = false } pallet-sandbox = { path = "pallets/sandbox", default-features = false } -pallet-parachain-staking = { git = "https://gitlab.com/Omegabit/stake-patch", default-features = false } - # Internal support (with default disabled) -shared-configuration = { path = "runtimes/shared-configuration", default-features = false } +polimec-traits = { path = "traits", default-features = false } +xcm-primitives = { path = "primitives/xcm", default-features = false } # External support (with default disabled) -# dip-support = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } -# kilt-support = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } -# kilt-dip-support = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } -# did = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } -# pallet-did-lookup = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } -# pallet-dip-provider = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } -# pallet-dip-consumer = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } - +dip-support = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } +kilt-support = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } +kilt-dip-support = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } +did = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } +pallet-did-lookup = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } +pallet-dip-provider = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } +pallet-dip-consumer = { git = "https://github.com/KILTprotocol/kilt-node", default-features = false, branch = "aa/dip" } +# Internal runtime API (with default disabled) +kilt-runtime-api-staking = { path = "runtime-api/staking", default-features = false } # External (without extra features and with default disabled if necessary) parity-scale-codec = { version = "3.3.0", default-features = false } diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index 4776bedfa..2b641803c 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -46,14 +46,14 @@ polkadot-runtime.workspace = true statemint-runtime.workspace = true polimec-parachain-runtime.workspace = true penpal-runtime.workspace = true -# dip-provider-runtime-template = { workspace = true, features = ["std"] } -# did = { workspace = true, features = ["std"] } -# kilt-support = { workspace = true, features = ["std"] } -# pallet-did-lookup = { workspace = true, features = ["std"] } -# dip-support = { workspace = true, features = ["std"] } -# runtime-common = { workspace = true, features = ["std"] } -# kilt-dip-support = { workspace = true, features = ["std"] } -# kilt-runtime-common = { workspace = true, features = ["std"] } +dip-provider-runtime-template = { workspace = true, features = ["std"] } +did = { workspace = true, features = ["std"] } +kilt-support = { workspace = true, features = ["std"] } +pallet-did-lookup = { workspace = true, features = ["std"] } +dip-support = { workspace = true, features = ["std"] } +runtime-common = { workspace = true, features = ["std"] } +kilt-dip-support = { workspace = true, features = ["std"] } +kilt-runtime-common = { workspace = true, features = ["std"] } [features] default = ["std"] diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs index 09b481930..dd2f3374f 100644 --- a/integration-tests/src/lib.rs +++ b/integration-tests/src/lib.rs @@ -28,6 +28,11 @@ use xcm_emulator::{ TestExt, }; +// DIP +use did::did_details::{DidDetails, DidEncryptionKey, DidVerificationKey}; +use dip_provider_runtime_template::DidIdentifier; +use kilt_support::deposit::Deposit; + const RELAY_ASSET_ID: u32 = 0; const RESERVE_TRANSFER_AMOUNT: u128 = 10_0_000_000_000; //10 UNITS when 10 decimals pub const INITIAL_BALANCE: u128 = 100_0_000_000_000; @@ -76,6 +81,16 @@ decl_test_parachain! { } } +decl_test_parachain! { + pub struct ProviderParachain { + Runtime = dip_provider_runtime_template::Runtime, + RuntimeOrigin = dip_provider_runtime_template::RuntimeOrigin, + XcmpMessageHandler = dip_provider_runtime_template::XcmpQueue, + DmpMessageHandler = dip_provider_runtime_template::DmpQueue, + new_ext = provider_ext(provider_id()), + } +} + decl_test_network! { pub struct Network { relay_chain = PolkadotNet, @@ -83,6 +98,7 @@ decl_test_network! { (2000u32, PolimecNet), (1000u32, StatemintNet), (3000u32, PenpalNet), + (2001u32, ProviderParachain), ], } } @@ -236,6 +252,12 @@ pub fn polimec_ext(para_id: u32) -> sp_io::TestExternalities { .unwrap(); pallet_assets::GenesisConfig:: { + assets: vec![( + RELAY_ASSET_ID, + polimec_runtime::AssetsPalletId::get().into_account_truncating(), + false, + 1_0_000_000_000, + )], metadata: vec![( RELAY_ASSET_ID, "Local DOT".as_bytes().to_vec(), @@ -243,7 +265,6 @@ pub fn polimec_ext(para_id: u32) -> sp_io::TestExternalities { 12, )], accounts: vec![(RELAY_ASSET_ID, ALICE, INITIAL_BALANCE)], - ..Default::default() } .assimilate_storage(&mut t) .unwrap(); @@ -320,6 +341,55 @@ pub fn penpal_ext(para_id: u32) -> sp_io::TestExternalities { ext } +pub fn provider_ext(para_id: u32) -> sp_io::TestExternalities { + use dip_provider_runtime_template::{Runtime, System}; + + let mut t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); + + let parachain_info_config = parachain_info::GenesisConfig { + parachain_id: para_id.into(), + }; + >::assimilate_storage(¶chain_info_config, &mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + let did: DidIdentifier = did_auth_key().public().into(); + let details = generate_did_details(); + ext.execute_with(|| { + did::pallet::Did::::insert(&did, details); + System::set_block_number(1); + }); + ext +} + +pub(crate) fn did_auth_key() -> ed25519::Pair { + ed25519::Pair::from_seed(&[200u8; 32]) +} + +fn generate_did_details() -> DidDetails { + let auth_key: DidVerificationKey = did_auth_key().public().into(); + let att_key: DidVerificationKey = sr25519::Pair::from_seed(&[100u8; 32]).public().into(); + let del_key: DidVerificationKey = ecdsa::Pair::from_seed(&[101u8; 32]).public().into(); + + let mut details = DidDetails::new( + auth_key, + 0u32, + Deposit { + amount: 1u64.into(), + owner: dip_provider_runtime_template::AccountId::new([1u8; 32]), + }, + ) + .unwrap(); + details.update_attestation_key(att_key, 0u32).unwrap(); + details.update_delegation_key(del_key, 0u32).unwrap(); + details + .add_key_agreement_key(DidEncryptionKey::X25519([100u8; 32]), 0u32) + .unwrap(); + details +} + /// Shortcuts to reduce boilerplate on runtime types pub mod shortcuts { use super::*; @@ -328,6 +398,7 @@ pub mod shortcuts { pub type PolimecRuntime = polimec_runtime::Runtime; pub type StatemintRuntime = statemint_runtime::Runtime; pub type PenpalRuntime = penpal_runtime::Runtime; + pub type ProviderRuntime = dip_provider_runtime_template::Runtime; pub type PolkadotXcmPallet = polkadot_runtime::XcmPallet; pub type PolimecXcmPallet = polimec_runtime::PolkadotXcm; @@ -358,6 +429,7 @@ pub mod shortcuts { pub type PolimecAccountId = polkadot_primitives::AccountId; pub type StatemintAccountId = polkadot_primitives::AccountId; pub type PenpalAccountId = polkadot_primitives::AccountId; + pub type ProviderAccountId = dip_provider_runtime_template::AccountId; } #[cfg(test)] @@ -591,7 +663,7 @@ mod reserve_backed_transfers { let statemint_delta_dot_issuance = statemint_prev_dot_issuance - statemint_post_dot_issuance; assert!( - polimec_delta_alice_dot_balance >= RESERVE_TRANSFER_AMOUNT - polimec_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) && + polimec_delta_alice_dot_balance >= RESERVE_TRANSFER_AMOUNT - polimec_runtime::WeightToFee::::weight_to_fee(&MAX_XCM_WEIGHT) && polimec_delta_alice_dot_balance <= RESERVE_TRANSFER_AMOUNT, "Polimec ALICE DOT balance should have increased by at least the transfer amount minus the XCM execution fee" ); @@ -599,7 +671,7 @@ mod reserve_backed_transfers { assert!( polimec_delta_dot_issuance >= RESERVE_TRANSFER_AMOUNT - - polimec_runtime::WeightToFee::weight_to_fee(&MAX_XCM_WEIGHT) + - polimec_runtime::WeightToFee::::weight_to_fee(&MAX_XCM_WEIGHT) && polimec_delta_dot_issuance <= RESERVE_TRANSFER_AMOUNT, "Polimec DOT issuance should have increased by at least the transfer amount minus the XCM execution fee" ); @@ -1334,4 +1406,100 @@ mod reserve_backed_transfers { "Polimec PLMC issuance should not have changed" ); } -} \ No newline at end of file +} + +#[cfg(test)] +mod dip { + use super::*; + use did::{Did, DidSignature}; + use dip_provider_runtime_template::DipProvider; + use pallet_did_lookup::linkable_account::LinkableAccountId; + use polimec_runtime::DipConsumer; + + #[test] + fn commit_identity() { + Network::reset(); + use frame_system::RawOrigin; + use kilt_dip_support::{ + did::{MerkleEntriesAndDidSignature, TimeBoundDidSignature}, + merkle::MerkleProof, + }; + use kilt_runtime_common::dip::merkle::CompleteMerkleProof; + use kilt_runtime_common::dip::merkle::DidMerkleRootGenerator; + use polimec_parachain_runtime::{ + BlockNumber, DidLookup, Runtime as ConsumerRuntime, RuntimeCall as ConsumerRuntimeCall, RuntimeEvent, + System, + }; + use sp_runtime::traits::Zero; + + let did: DidIdentifier = did_auth_key().public().into(); + + // 1. Send identity proof from DIP provider to DIP consumer. + ProviderParachain::execute_with(|| { + assert_ok!(DipProvider::commit_identity( + RawOrigin::Signed(ProviderAccountId::from([0u8; 32])).into(), + did.clone(), + Box::new(ParentThen(X1(Parachain(polimec_id()))).into()), + Box::new((Here, 1_000_000_000).into()), + Weight::from_ref_time(4_000), + )); + }); + // 2. Verify that the proof has made it to the DIP consumer. + PolimecNet::execute_with(|| { + // 2.1 Verify that there was no XCM error. + assert!(!System::events().iter().any(|r| matches!( + r.event, + RuntimeEvent::XcmpQueue(XcmpEvent::Fail { + error: _, + message_hash: _, + weight: _ + }) + ))); + // 2.2 Verify the proof digest was stored correctly. + assert!(DipConsumer::identity_proofs(&did).is_some()); + }); + // 3. Call an extrinsic on the consumer chain with a valid proof and signature + let did_details = ProviderParachain::execute_with(|| { + Did::get(&did).expect("DID details should be stored on the provider chain.") + }); + let call = ConsumerRuntimeCall::DidLookup(pallet_did_lookup::Call::::associate_sender {}); + // 3.1 Generate a proof + let CompleteMerkleProof { proof, .. } = DidMerkleRootGenerator::::generate_proof( + &did_details, + [did_details.authentication_key].iter(), + ) + .expect("Proof generation should not fail"); + // 3.2 Generate a DID signature + let genesis_hash = + PolimecNet::execute_with(|| frame_system::Pallet::::block_hash(BlockNumber::zero())); + let system_block = PolimecNet::execute_with(frame_system::Pallet::::block_number); + let payload = (call.clone(), 0u128, DISPATCHER_ACCOUNT, system_block, genesis_hash); + let signature: DidSignature = did_auth_key().sign(&payload.encode()).into(); + // 3.3 Call the `dispatch_as` extrinsic on the consumer chain with the generated + // proof + PolimecNet::execute_with(|| { + assert_ok!(DipConsumer::dispatch_as( + RawOrigin::Signed(DISPATCHER_ACCOUNT).into(), + did.clone(), + MerkleEntriesAndDidSignature { + merkle_entries: MerkleProof { + blinded: proof.blinded, + revealed: proof.revealed, + }, + did_signature: TimeBoundDidSignature { + signature, + block_number: system_block + } + }, + Box::new(call), + )); + // Verify the account -> DID link exists and contains the right information + let linked_did = + DidLookup::connected_dids::(DISPATCHER_ACCOUNT.into()).map(|link| link.did); + assert_eq!(linked_did, Some(did.clone())); + // Verify that the details of the DID subject have been bumped + let details = DipConsumer::identity_proofs(&did).map(|entry| entry.details); + assert_eq!(details, Some(1u128)); + }); + } +} diff --git a/nodes/parachain/Cargo.toml b/nodes/parachain/Cargo.toml index e564a5e40..bcbf88b45 100644 --- a/nodes/parachain/Cargo.toml +++ b/nodes/parachain/Cargo.toml @@ -16,7 +16,6 @@ log.workspace = true parity-scale-codec = { workspace = true } serde = { workspace = true, features = ["derive"] } jsonrpsee = { workspace = true, features = ["server"] } -hex-literal.workspace = true # Local polimec-parachain-runtime.workspace = true diff --git a/nodes/parachain/src/chain_spec.rs b/nodes/parachain/src/chain_spec.rs index c7ff83f19..67fd4a24c 100644 --- a/nodes/parachain/src/chain_spec.rs +++ b/nodes/parachain/src/chain_spec.rs @@ -28,6 +28,8 @@ use sp_runtime::traits::{IdentifyAccount, Verify}; pub mod base; pub mod testnet; +// TODO: Set a proper TELEMETRY_URL +const TELEMETRY_URL: &str = "wss://tbd"; const DEFAULT_PARA_ID: ParaId = LOWEST_PUBLIC_ID; /// Helper function to generate a crypto pair from seed @@ -38,9 +40,7 @@ pub fn get_from_seed(seed: &str) -> ::Pu } /// The extensions for the [`ChainSpec`]. -#[derive( - Debug, Clone, Eq, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension, -)] +#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)] #[serde(deny_unknown_fields)] pub struct Extensions { /// The relay chain of the Parachain. diff --git a/nodes/parachain/src/chain_spec/base.rs b/nodes/parachain/src/chain_spec/base.rs index 48fa084bc..f10a85790 100644 --- a/nodes/parachain/src/chain_spec/base.rs +++ b/nodes/parachain/src/chain_spec/base.rs @@ -22,18 +22,13 @@ use crate::chain_spec::Extensions; use cumulus_primitives_core::ParaId; use polimec_base_runtime as base_runtime; use sc_service::ChainType; -use sp_core::{crypto::UncheckedInto, sr25519}; -use sp_runtime::{Perbill, Percent}; +use sp_core::sr25519; -use crate::chain_spec::{get_account_id_from_seed, get_properties, DEFAULT_PARA_ID}; +use crate::chain_spec::{get_account_id_from_seed, get_from_seed, get_properties, DEFAULT_PARA_ID}; use base_runtime::{ - pallet_parachain_staking::{ - inflation::{perbill_annual_to_perbill_round, BLOCKS_PER_YEAR}, - InflationInfo, Range, - }, - AccountId, AuraId as AuthorityId, Balance, BalancesConfig, GenesisConfig, MinCandidateStk, - ParachainInfoConfig, ParachainStakingConfig, PolkadotXcmConfig, SessionConfig, SudoConfig, - SystemConfig, PLMC, + polimec_inflation_config, staking::MinCollatorStake, AccountId, AuraId as AuthorityId, Balance, BalancesConfig, + GenesisConfig, InflationInfo, ParachainInfoConfig, ParachainStakingConfig, PolkadotXcmConfig, SessionConfig, + SudoConfig, SystemConfig, MAX_COLLATOR_STAKE, PLMC, }; /// The default XCM version to set in genesis config. @@ -42,45 +37,13 @@ const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION; /// Specialized `ChainSpec` for the shell parachain runtime. pub type ChainSpec = sc_service::GenericChainSpec; -const COLLATOR_COMMISSION: Perbill = Perbill::from_percent(30); -const PARACHAIN_BOND_RESERVE_PERCENT: Percent = Percent::from_percent(0); -const BLOCKS_PER_ROUND: u32 = 2 * 10; -const NUM_SELECTED_CANDIDATES: u32 = 5; -pub fn polimec_inflation_config() -> InflationInfo { - fn to_round_inflation(annual: Range) -> Range { - perbill_annual_to_perbill_round( - annual, - // rounds per year - BLOCKS_PER_YEAR / BLOCKS_PER_ROUND, - ) - } - - let annual = Range { - min: Perbill::from_percent(2), - ideal: Perbill::from_percent(3), - max: Perbill::from_percent(3), - }; - - InflationInfo { - // staking expectations - expect: Range { min: 100_000 * PLMC, ideal: 200_000 * PLMC, max: 500_000 * PLMC }, - // annual inflation - annual, - round: to_round_inflation(annual), - } -} - -pub fn get_base_session_keys(keys: AuthorityId) -> base_runtime::SessionKeys { - base_runtime::SessionKeys { aura: keys } -} - pub fn get_local_base_chain_spec() -> Result { let properties = get_properties("PLMC", 10, 41); let wasm = base_runtime::WASM_BINARY.ok_or("No WASM")?; Ok(ChainSpec::from_genesis( "Polimec Base Develop", - "polimec-base", + "polimec", ChainType::Local, move || { base_testnet_genesis( @@ -89,46 +52,58 @@ pub fn get_local_base_chain_spec() -> Result { ( get_account_id_from_seed::("Alice"), None, - 2 * MinCandidateStk::get(), + 2 * MinCollatorStake::get(), ), ( get_account_id_from_seed::("Bob"), None, - 2 * MinCandidateStk::get(), + 2 * MinCollatorStake::get(), ), ], polimec_inflation_config(), - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - ], + MAX_COLLATOR_STAKE, vec![ ( get_account_id_from_seed::("Alice"), - 5 * MinCandidateStk::get(), + get_from_seed::("Alice"), ), ( get_account_id_from_seed::("Bob"), - 5 * MinCandidateStk::get(), + get_from_seed::("Bob"), + ), + ], + vec![ + (get_account_id_from_seed::("Alice"), 10000000 * PLMC), + (get_account_id_from_seed::("Bob"), 10000000 * PLMC), + (get_account_id_from_seed::("Charlie"), 10000000 * PLMC), + (get_account_id_from_seed::("Dave"), 10000000 * PLMC), + (get_account_id_from_seed::("Eve"), 10000000 * PLMC), + (get_account_id_from_seed::("Ferdie"), 10000000 * PLMC), + ( + get_account_id_from_seed::("Alice//stash"), + 10000000 * PLMC, + ), + ( + get_account_id_from_seed::("Bob//stash"), + 10000000 * PLMC, ), ( - get_account_id_from_seed::("Charlie"), - 5 * MinCandidateStk::get(), + get_account_id_from_seed::("Charlie//stash"), + 10000000 * PLMC, ), ( - get_account_id_from_seed::("Dave"), - 5 * MinCandidateStk::get(), + get_account_id_from_seed::("Dave//stash"), + 10000000 * PLMC, ), ( - get_account_id_from_seed::("Eve"), - 5 * MinCandidateStk::get(), + get_account_id_from_seed::("Eve//stash"), + 10000000 * PLMC, ), ( - get_account_id_from_seed::("Ferdie"), - 5 * MinCandidateStk::get(), + get_account_id_from_seed::("Ferdie//stash"), + 10000000 * PLMC, ), ], - get_account_id_from_seed::("Alice"), DEFAULT_PARA_ID, ) }, @@ -137,42 +112,58 @@ pub fn get_local_base_chain_spec() -> Result { Some("polimec"), None, Some(properties), - Extensions { relay_chain: "rococo_local_testnet".into(), para_id: DEFAULT_PARA_ID.into() }, + Extensions { + relay_chain: "rococo_local_testnet".into(), + para_id: DEFAULT_PARA_ID.into(), + }, )) } -pub fn get_kusama_base_chain_spec() -> Result { +pub fn get_live_base_chain_spec() -> Result { let properties = get_properties("PLMC", 10, 41); let wasm = base_runtime::WASM_BINARY.ok_or("No WASM")?; // TODO: Update this after reserving a ParaId - let id: u32 = 4261; - - const PLMC_SUDO_ACC: [u8; 32] = - hex_literal::hex!["d4192a54c9caa4a38eeb3199232ed0d8568b22956cafb76c7d5a1afbf4e2dc38"]; - const PLMC_COL_ACC_1: [u8; 32] = - hex_literal::hex!["6603f63a4091ba074b4384e64c6bba1dd96f6af49331ebda686b0a0f27dd961c"]; - const PLMC_COL_ACC_2: [u8; 32] = - hex_literal::hex!["ba48ab77461ef53f9ebfdc94a12c780b57354f986e31eb2504b9e3ed580fab51"]; + let id: u32 = 2105; Ok(ChainSpec::from_genesis( - "Polimec Kusama Testnet", + "Polimec Base", "polimec", ChainType::Live, move || { base_testnet_genesis( wasm, + // TODO: Update stakers vec![ - (PLMC_COL_ACC_1.into(), None, 2 * MinCandidateStk::get()), - (PLMC_COL_ACC_2.into(), None, 2 * MinCandidateStk::get()), + ( + get_account_id_from_seed::("Alice"), + None, + 2 * MinCollatorStake::get(), + ), + ( + get_account_id_from_seed::("Bob"), + None, + 2 * MinCollatorStake::get(), + ), ], polimec_inflation_config(), - vec![(PLMC_COL_ACC_1.into()), (PLMC_COL_ACC_2.into())], + MAX_COLLATOR_STAKE, + // TODO: Update initial authorities vec![ - (PLMC_COL_ACC_1.into(), 3 * MinCandidateStk::get()), - (PLMC_COL_ACC_2.into(), 3 * MinCandidateStk::get()), + ( + get_account_id_from_seed::("Alice"), + get_from_seed::("Alice"), + ), + ( + get_account_id_from_seed::("Bob"), + get_from_seed::("Bob"), + ), + ], + // TODO: Update initial balances + vec![ + (get_account_id_from_seed::("Alice"), 10000000 * PLMC), + (get_account_id_from_seed::("Bob"), 10000000 * PLMC), ], - PLMC_SUDO_ACC.into(), id.into(), ) }, @@ -181,34 +172,35 @@ pub fn get_kusama_base_chain_spec() -> Result { Some("polimec"), None, Some(properties), - Extensions { relay_chain: "kusama".into(), para_id: id }, + Extensions { + relay_chain: "polkadot".into(), + para_id: id, + }, )) } fn base_testnet_genesis( - wasm_binary: &[u8], - stakers: Vec<(AccountId, Option, Balance)>, - inflation_config: InflationInfo, - initial_authorities: Vec, - endowed_accounts: Vec<(AccountId, Balance)>, - sudo_account: AccountId, - id: ParaId, + wasm_binary: &[u8], stakers: Vec<(AccountId, Option, Balance)>, inflation_config: InflationInfo, + max_candidate_stake: Balance, initial_authorities: Vec<(AccountId, AuthorityId)>, + endowed_accounts: Vec<(AccountId, Balance)>, id: ParaId, ) -> GenesisConfig { + let accounts = endowed_accounts + .iter() + .map(|(account, _)| account.clone()) + .collect::>(); + GenesisConfig { - system: SystemConfig { code: wasm_binary.to_vec() }, - balances: BalancesConfig { balances: endowed_accounts.clone() }, + system: SystemConfig { + code: wasm_binary.to_vec(), + }, + balances: BalancesConfig { + balances: endowed_accounts.clone(), + }, parachain_info: ParachainInfoConfig { parachain_id: id }, parachain_staking: ParachainStakingConfig { - candidates: stakers - .iter() - .map(|(accunt, _, balance)| (accunt.clone(), balance.clone())) - .collect::>(), + stakers, inflation_config, - delegations: vec![], - collator_commission: COLLATOR_COMMISSION, - parachain_bond_reserve_percent: PARACHAIN_BOND_RESERVE_PERCENT, - blocks_per_round: BLOCKS_PER_ROUND, - num_selected_candidates: NUM_SELECTED_CANDIDATES, + max_candidate_stake, }, aura: Default::default(), aura_ext: Default::default(), @@ -216,17 +208,22 @@ fn base_testnet_genesis( session: SessionConfig { keys: initial_authorities .iter() - .map(|acc| { + .map(|(acc, key)| { ( acc.clone(), acc.clone(), - get_base_session_keys(Into::<[u8; 32]>::into(acc.clone()).unchecked_into()), + base_runtime::SessionKeys { aura: key.clone() }, ) }) .collect::>(), }, - polkadot_xcm: PolkadotXcmConfig { safe_xcm_version: Some(SAFE_XCM_VERSION) }, - sudo: SudoConfig { key: Some(sudo_account) }, + treasury: Default::default(), + polkadot_xcm: PolkadotXcmConfig { + safe_xcm_version: Some(SAFE_XCM_VERSION), + }, + sudo: SudoConfig { + key: Some(accounts.first().expect("").to_owned()), + }, transaction_payment: Default::default(), } } diff --git a/nodes/parachain/src/chain_spec/testnet.rs b/nodes/parachain/src/chain_spec/testnet.rs index d71f3cb6a..0e13db10b 100644 --- a/nodes/parachain/src/chain_spec/testnet.rs +++ b/nodes/parachain/src/chain_spec/testnet.rs @@ -20,23 +20,19 @@ use cumulus_primitives_core::ParaId; use polimec_parachain_runtime::{ - pallet_parachain_staking::{ - inflation::{perbill_annual_to_perbill_round, BLOCKS_PER_YEAR}, - InflationInfo, Range, - }, - AuraId as AuthorityId, MinCandidateStk, ParachainStakingConfig, PLMC, + polimec_inflation_config, AuraId as AuthorityId, MinCollatorStake, MAX_COLLATOR_STAKE, PLMC, }; use polimec_parachain_runtime::{ - AccountId, Balance, BalancesConfig, CouncilConfig, GenesisConfig, ParachainInfoConfig, - PolkadotXcmConfig, SessionConfig, SudoConfig, SystemConfig, TechnicalCommitteeConfig, - VestingConfig, + AccountId, Balance, BalancesConfig, CouncilConfig, CredentialsConfig, GenesisConfig, InflationInfo, + ParachainInfoConfig, PolkadotXcmConfig, SessionConfig, SessionKeys, SudoConfig, SystemConfig, + TechnicalCommitteeConfig, VestingConfig, WASM_BINARY, }; use sc_service::ChainType; -use sp_core::{crypto::UncheckedInto, sr25519}; -use sp_runtime::{Perbill, Percent}; +use sc_telemetry::TelemetryEndpoints; +use sp_core::sr25519; -use crate::chain_spec::{get_account_id_from_seed, DEFAULT_PARA_ID}; +use crate::chain_spec::{get_account_id_from_seed, get_from_seed, DEFAULT_PARA_ID, TELEMETRY_URL}; use super::{get_properties, Extensions}; @@ -45,41 +41,9 @@ const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION; /// Specialized `ChainSpec` for the normal parachain runtime. pub type ChainSpec = sc_service::GenericChainSpec; -const COLLATOR_COMMISSION: Perbill = Perbill::from_percent(30); -const PARACHAIN_BOND_RESERVE_PERCENT: Percent = Percent::from_percent(0); -const BLOCKS_PER_ROUND: u32 = 2 * 10; -const NUM_SELECTED_CANDIDATES: u32 = 5; -pub fn polimec_inflation_config() -> InflationInfo { - fn to_round_inflation(annual: Range) -> Range { - perbill_annual_to_perbill_round( - annual, - // rounds per year - BLOCKS_PER_YEAR / BLOCKS_PER_ROUND, - ) - } - - let annual = Range { - min: Perbill::from_percent(2), - ideal: Perbill::from_percent(3), - max: Perbill::from_percent(3), - }; - - InflationInfo { - // staking expectations - expect: Range { min: 100_000 * PLMC, ideal: 200_000 * PLMC, max: 500_000 * PLMC }, - // annual inflation - annual, - round: to_round_inflation(annual), - } -} - -pub fn get_testnet_session_keys(keys: AuthorityId) -> polimec_parachain_runtime::SessionKeys { - polimec_parachain_runtime::SessionKeys { aura: keys } -} - pub fn get_chain_spec_dev() -> Result { let properties = get_properties("PLMC", 10, 41); - let wasm = polimec_parachain_runtime::WASM_BINARY.ok_or("No WASM")?; + let wasm = WASM_BINARY.ok_or("No WASM")?; Ok(ChainSpec::from_genesis( "Polimec Develop", @@ -92,46 +56,58 @@ pub fn get_chain_spec_dev() -> Result { ( get_account_id_from_seed::("Alice"), None, - 2 * MinCandidateStk::get(), + 2 * MinCollatorStake::get(), ), ( get_account_id_from_seed::("Bob"), None, - 2 * MinCandidateStk::get(), + 2 * MinCollatorStake::get(), ), ], polimec_inflation_config(), - vec![ - get_account_id_from_seed::("Alice"), - get_account_id_from_seed::("Bob"), - ], + MAX_COLLATOR_STAKE, vec![ ( get_account_id_from_seed::("Alice"), - 5 * MinCandidateStk::get(), + get_from_seed::("Alice"), ), ( get_account_id_from_seed::("Bob"), - 5 * MinCandidateStk::get(), + get_from_seed::("Bob"), ), + ], + vec![ + (get_account_id_from_seed::("Alice"), 10000000 * PLMC), + (get_account_id_from_seed::("Bob"), 10000000 * PLMC), + (get_account_id_from_seed::("Charlie"), 10000000 * PLMC), + (get_account_id_from_seed::("Dave"), 10000000 * PLMC), + (get_account_id_from_seed::("Eve"), 10000000 * PLMC), + (get_account_id_from_seed::("Ferdie"), 10000000 * PLMC), ( - get_account_id_from_seed::("Charlie"), - 5 * MinCandidateStk::get(), + get_account_id_from_seed::("Alice//stash"), + 10000000 * PLMC, ), ( - get_account_id_from_seed::("Dave"), - 5 * MinCandidateStk::get(), + get_account_id_from_seed::("Bob//stash"), + 10000000 * PLMC, ), ( - get_account_id_from_seed::("Eve"), - 5 * MinCandidateStk::get(), + get_account_id_from_seed::("Charlie//stash"), + 10000000 * PLMC, ), ( - get_account_id_from_seed::("Ferdie"), - 5 * MinCandidateStk::get(), + get_account_id_from_seed::("Dave//stash"), + 10000000 * PLMC, + ), + ( + get_account_id_from_seed::("Eve//stash"), + 10000000 * PLMC, + ), + ( + get_account_id_from_seed::("Ferdie//stash"), + 10000000 * PLMC, ), ], - get_account_id_from_seed::("Alice"), DEFAULT_PARA_ID, ) }, @@ -140,110 +116,252 @@ pub fn get_chain_spec_dev() -> Result { None, None, Some(properties), - Extensions { relay_chain: "rococo-local".into(), para_id: DEFAULT_PARA_ID.into() }, + Extensions { + relay_chain: "rococo-local".into(), + para_id: DEFAULT_PARA_ID.into(), + }, )) } pub fn get_prod_chain_spec() -> Result { let properties = get_properties("PLMC", 10, 41); - let wasm = polimec_parachain_runtime::WASM_BINARY.ok_or("No WASM")?; + let wasm = WASM_BINARY.ok_or("No WASM")?; + let id: ParaId = 2105.into(); - // TODO: Update this after reserving a ParaId - let id: u32 = 4261; + Ok(ChainSpec::from_genesis( + "Polimec", + "polimec", + ChainType::Live, + move || { + testnet_genesis( + wasm, + vec![ + ( + get_account_id_from_seed::("Alice"), + None, + 2 * MinCollatorStake::get(), + ), + ( + get_account_id_from_seed::("Bob"), + None, + 2 * MinCollatorStake::get(), + ), + ], + polimec_inflation_config(), + MAX_COLLATOR_STAKE, + vec![ + ( + get_account_id_from_seed::("Alice"), + get_from_seed::("Alice"), + ), + ( + get_account_id_from_seed::("Bob"), + get_from_seed::("Bob"), + ), + ], + vec![ + (get_account_id_from_seed::("Alice"), 10000000 * PLMC), + (get_account_id_from_seed::("Bob"), 10000000 * PLMC), + (get_account_id_from_seed::("Charlie"), 10000000 * PLMC), + (get_account_id_from_seed::("Dave"), 10000000 * PLMC), + (get_account_id_from_seed::("Eve"), 10000000 * PLMC), + (get_account_id_from_seed::("Ferdie"), 10000000 * PLMC), + ( + get_account_id_from_seed::("Alice//stash"), + 10000000 * PLMC, + ), + ( + get_account_id_from_seed::("Bob//stash"), + 10000000 * PLMC, + ), + ( + get_account_id_from_seed::("Charlie//stash"), + 10000000 * PLMC, + ), + ( + get_account_id_from_seed::("Dave//stash"), + 10000000 * PLMC, + ), + ( + get_account_id_from_seed::("Eve//stash"), + 10000000 * PLMC, + ), + ( + get_account_id_from_seed::("Ferdie//stash"), + 10000000 * PLMC, + ), + ], + id, + ) + }, + vec![], + Some( + TelemetryEndpoints::new(vec![(TELEMETRY_URL.to_string(), 0)]).expect("Polimec telemetry url is valid; qed"), + ), + Some("polimec"), + None, + Some(properties), + Extensions { + relay_chain: "polkadot".into(), + para_id: id.into(), + }, + )) +} - const PLMC_SUDO_ACC: [u8; 32] = - hex_literal::hex!["d4192a54c9caa4a38eeb3199232ed0d8568b22956cafb76c7d5a1afbf4e2dc38"]; - const PLMC_COL_ACC_1: [u8; 32] = - hex_literal::hex!["6603f63a4091ba074b4384e64c6bba1dd96f6af49331ebda686b0a0f27dd961c"]; - const PLMC_COL_ACC_2: [u8; 32] = - hex_literal::hex!["ba48ab77461ef53f9ebfdc94a12c780b57354f986e31eb2504b9e3ed580fab51"]; +pub fn get_local_prod_chain_spec() -> Result { + let properties = get_properties("PLMC", 10, 41); + let wasm = WASM_BINARY.ok_or("No WASM")?; + let id: ParaId = 2000.into(); Ok(ChainSpec::from_genesis( - "Polimec Kusama Testnet", + "Polimec", "polimec", ChainType::Live, move || { testnet_genesis( wasm, vec![ - (PLMC_COL_ACC_1.into(), None, 2 * MinCandidateStk::get()), - (PLMC_COL_ACC_2.into(), None, 2 * MinCandidateStk::get()), + ( + get_account_id_from_seed::("Alice"), + None, + 2 * MinCollatorStake::get(), + ), + ( + get_account_id_from_seed::("Bob"), + None, + 2 * MinCollatorStake::get(), + ), ], polimec_inflation_config(), - vec![(PLMC_COL_ACC_1.into()), (PLMC_COL_ACC_2.into())], + MAX_COLLATOR_STAKE, + vec![ + ( + get_account_id_from_seed::("Alice"), + get_from_seed::("Alice"), + ), + ( + get_account_id_from_seed::("Bob"), + get_from_seed::("Bob"), + ), + ], vec![ - (PLMC_COL_ACC_1.into(), 3 * MinCandidateStk::get()), - (PLMC_COL_ACC_2.into(), 3 * MinCandidateStk::get()), + (get_account_id_from_seed::("Alice"), 10000000 * PLMC), + (get_account_id_from_seed::("Bob"), 10000000 * PLMC), + (get_account_id_from_seed::("Charlie"), 10000000 * PLMC), + (get_account_id_from_seed::("Dave"), 10000000 * PLMC), + (get_account_id_from_seed::("Eve"), 10000000 * PLMC), + (get_account_id_from_seed::("Ferdie"), 10000000 * PLMC), + ( + get_account_id_from_seed::("Alice//stash"), + 10000000 * PLMC, + ), + ( + get_account_id_from_seed::("Bob//stash"), + 10000000 * PLMC, + ), + ( + get_account_id_from_seed::("Charlie//stash"), + 10000000 * PLMC, + ), + ( + get_account_id_from_seed::("Dave//stash"), + 10000000 * PLMC, + ), + ( + get_account_id_from_seed::("Eve//stash"), + 10000000 * PLMC, + ), + ( + get_account_id_from_seed::("Ferdie//stash"), + 10000000 * PLMC, + ), ], - PLMC_SUDO_ACC.into(), - id.into(), + id, ) }, vec![], - None, + Some( + TelemetryEndpoints::new(vec![(TELEMETRY_URL.to_string(), 0)]).expect("Polimec telemetry url is valid; qed"), + ), Some("polimec"), None, Some(properties), - Extensions { relay_chain: "polkadot".into(), para_id: id }, + Extensions { + relay_chain: "rococo-local".into(), + para_id: id.into(), + }, )) } #[allow(clippy::too_many_arguments)] fn testnet_genesis( - wasm_binary: &[u8], - stakers: Vec<(AccountId, Option, Balance)>, - inflation_config: InflationInfo, - initial_authorities: Vec, - endowed_accounts: Vec<(AccountId, Balance)>, - sudo_account: AccountId, - id: ParaId, + wasm_binary: &[u8], _stakers: Vec<(AccountId, Option, Balance)>, _inflation_config: InflationInfo, + _max_candidate_stake: Balance, initial_authorities: Vec<(AccountId, AuthorityId)>, + endowed_accounts: Vec<(AccountId, Balance)>, id: ParaId, ) -> GenesisConfig { - let accounts = endowed_accounts.iter().map(|(account, _)| account.clone()).collect::>(); + // type VestingPeriod = BlockNumber; + // type LockingPeriod = BlockNumber; + + // // vesting and locks as initially designed + // let claimable_accounts_json = &include_bytes!("../../res/genesis/claimable-accounts.json")[..]; + // let claimable_accounts: Vec<(AccountId, Balance, VestingPeriod, LockingPeriod)> = + // serde_json::from_slice(claimable_accounts_json) + // .expect("The file genesis_accounts.json exists and is valid; qed"); + + // // botlabs account should not be migrated but some have vesting + // let owned_accounts_json = &include_bytes!("../../res/genesis/owned-accounts.json")[..]; + // let owned_accounts: Vec<(AccountId, Balance, VestingPeriod, LockingPeriod)> = + // serde_json::from_slice(owned_accounts_json) + // .expect("The file botlabs_accounts.json exists and is valid; qed"); + + let accounts = endowed_accounts + .iter() + .map(|(account, _)| account.clone()) + .collect::>(); GenesisConfig { - system: SystemConfig { code: wasm_binary.to_vec() }, - balances: BalancesConfig { balances: endowed_accounts.clone() }, - parachain_info: ParachainInfoConfig { parachain_id: id }, - parachain_staking: ParachainStakingConfig { - candidates: stakers - .iter() - .map(|(accunt, _, balance)| (accunt.clone(), balance.clone())) - .collect::>(), - inflation_config, - delegations: vec![], - collator_commission: COLLATOR_COMMISSION, - parachain_bond_reserve_percent: PARACHAIN_BOND_RESERVE_PERCENT, - blocks_per_round: BLOCKS_PER_ROUND, - num_selected_candidates: NUM_SELECTED_CANDIDATES, + system: SystemConfig { + code: wasm_binary.to_vec(), + }, + balances: BalancesConfig { + balances: endowed_accounts.clone(), }, + parachain_info: ParachainInfoConfig { parachain_id: id }, + parachain_staking: Default::default(), // no need to pass anything to aura, in fact it will panic if we do. Session will take care // of this. aura: Default::default(), aura_ext: Default::default(), parachain_system: Default::default(), + credentials: CredentialsConfig { + issuers: accounts.clone(), + retails: accounts.clone(), + professionals: accounts.clone(), + institutionals: accounts.clone(), + }, session: SessionConfig { keys: initial_authorities .iter() - .map(|acc| { - ( - acc.clone(), - acc.clone(), - get_testnet_session_keys( - Into::<[u8; 32]>::into(acc.clone()).unchecked_into(), - ), - ) - }) + .map(|(acc, key)| (acc.clone(), acc.clone(), SessionKeys { aura: key.clone() })) .collect::>(), }, - polkadot_xcm: PolkadotXcmConfig { safe_xcm_version: Some(SAFE_XCM_VERSION) }, + polkadot_xcm: PolkadotXcmConfig { + safe_xcm_version: Some(SAFE_XCM_VERSION), + }, treasury: Default::default(), - sudo: SudoConfig { key: Some(sudo_account) }, - council: CouncilConfig { members: accounts.clone(), phantom: Default::default() }, + sudo: SudoConfig { + key: Some(accounts.first().expect("").to_owned()), + }, + council: CouncilConfig { + members: initial_authorities.iter().map(|(acc, _)| acc).cloned().collect(), + phantom: Default::default(), + }, technical_committee: TechnicalCommitteeConfig { - members: accounts.clone(), + members: initial_authorities.iter().map(|(acc, _)| acc).cloned().collect(), phantom: Default::default(), }, democracy: Default::default(), + did_lookup: Default::default(), vesting: VestingConfig { vesting: vec![] }, } } diff --git a/nodes/parachain/src/cli.rs b/nodes/parachain/src/cli.rs index e99d6dc94..8e2d1efa7 100644 --- a/nodes/parachain/src/cli.rs +++ b/nodes/parachain/src/cli.rs @@ -103,12 +103,15 @@ pub struct RelayChainCli { impl RelayChainCli { /// Parse the relay chain CLI parameters using the para chain `Configuration`. pub fn new<'a>( - para_config: &sc_service::Configuration, - relay_chain_args: impl Iterator, + para_config: &sc_service::Configuration, relay_chain_args: impl Iterator, ) -> Self { let extension = crate::chain_spec::Extensions::try_get(&*para_config.chain_spec); let chain_id = extension.map(|e| e.relay_chain.clone()); let base_path = para_config.base_path.as_ref().map(|x| x.path().join("polkadot")); - Self { base_path, chain_id, base: clap::Parser::parse_from(relay_chain_args) } + Self { + base_path, + chain_id, + base: clap::Parser::parse_from(relay_chain_args), + } } } diff --git a/nodes/parachain/src/command.rs b/nodes/parachain/src/command.rs index 3ce35ff93..1451df942 100644 --- a/nodes/parachain/src/command.rs +++ b/nodes/parachain/src/command.rs @@ -23,8 +23,8 @@ use log::{info, warn}; use parity_scale_codec::Encode; use polimec_parachain_runtime::Block; use sc_cli::{ - ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, - NetworkParams, Result, RuntimeVersion, SharedParams, SubstrateCli, + ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, NetworkParams, Result, + RuntimeVersion, SharedParams, SubstrateCli, }; use sc_service::config::{BasePath, PrometheusConfig}; use sp_core::hexdisplay::HexDisplay; @@ -65,8 +65,8 @@ impl RuntimeResolver for PathBuf { let file = std::fs::File::open(self).expect("Failed to open file"); let reader = std::io::BufReader::new(file); - let chain_spec: EmptyChainSpecWithId = sp_serializer::from_reader(reader) - .expect("Failed to read 'json' file with ChainSpec configuration"); + let chain_spec: EmptyChainSpecWithId = + sp_serializer::from_reader(reader).expect("Failed to read 'json' file with ChainSpec configuration"); runtime(&chain_spec.id) } } @@ -92,17 +92,16 @@ fn load_spec(id: &str) -> std::result::Result, String> { Ok(match id { // Base runtime "base-rococo-local" => Box::new(chain_spec::base::get_local_base_chain_spec()?), - "base-kusama" => Box::new(chain_spec::base::get_kusama_base_chain_spec()?), + "base-polkadot" => Box::new(chain_spec::base::get_live_base_chain_spec()?), // Testnet runtime "polimec-rococo-local" => Box::new(chain_spec::testnet::get_chain_spec_dev()?), "polimec-polkadot" => Box::new(chain_spec::testnet::get_prod_chain_spec()?), + "polimec-polkadot-local" => Box::new(chain_spec::testnet::get_local_prod_chain_spec()?), // -- Fallback (generic chainspec) "" => { - log::warn!( - "No ChainSpec.id specified, so using default one, based on polimec-rococo-local" - ); + log::warn!("No ChainSpec.id specified, so using default one, based on polimec-rococo-local"); Box::new(chain_spec::testnet::get_chain_spec_dev()?) - }, + } // A custom chainspec path path => { let path: PathBuf = path.into(); @@ -111,7 +110,7 @@ fn load_spec(id: &str) -> std::result::Result, String> { Runtime::Testnet => Box::new(chain_spec::testnet::ChainSpec::from_json_file(path)?), Runtime::Base => Box::new(chain_spec::base::ChainSpec::from_json_file(path)?), } - }, + } }) } @@ -214,51 +213,46 @@ pub fn run() -> Result<()> { Some(Subcommand::BuildSpec(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) - }, + } Some(Subcommand::CheckBlock(cmd)) => { construct_async_run!(|components, cli, cmd, config| { Ok(cmd.run(components.client, components.import_queue)) }) - }, + } Some(Subcommand::ExportBlocks(cmd)) => { - construct_async_run!(|components, cli, cmd, config| Ok( - cmd.run(components.client, config.database) - )) - }, + construct_async_run!(|components, cli, cmd, config| Ok(cmd.run(components.client, config.database))) + } Some(Subcommand::ExportState(cmd)) => { - construct_async_run!(|components, cli, cmd, config| Ok( - cmd.run(components.client, config.chain_spec) - )) - }, + construct_async_run!(|components, cli, cmd, config| Ok(cmd.run(components.client, config.chain_spec))) + } Some(Subcommand::ImportBlocks(cmd)) => { construct_async_run!(|components, cli, cmd, config| { Ok(cmd.run(components.client, components.import_queue)) }) - }, + } Some(Subcommand::Revert(cmd)) => { construct_async_run!(|components, cli, cmd, config| { Ok(cmd.run(components.client, components.backend, None)) }) - }, + } Some(Subcommand::PurgeChain(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| { let polkadot_cli = RelayChainCli::new( &config, - [RelayChainCli::executable_name()].iter().chain(cli.relay_chain_args.iter()), + [RelayChainCli::executable_name()] + .iter() + .chain(cli.relay_chain_args.iter()), ); - let polkadot_config = SubstrateCli::create_configuration( - &polkadot_cli, - &polkadot_cli, - config.tokio_handle.clone(), - ) - .map_err(|err| format!("Relay chain argument error: {}", err))?; + let polkadot_config = + SubstrateCli::create_configuration(&polkadot_cli, &polkadot_cli, config.tokio_handle.clone()) + .map_err(|err| format!("Relay chain argument error: {}", err))?; cmd.run(config, polkadot_config) }) - }, + } Some(Subcommand::ExportGenesisState(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|_config| { @@ -266,38 +260,40 @@ pub fn run() -> Result<()> { let state_version = Cli::native_runtime_version(&spec).state_version(); cmd.run::(&*spec, state_version) }) - }, + } Some(Subcommand::ExportGenesisWasm(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|_config| { let spec = cli.load_spec(&cmd.shared_params.chain.clone().unwrap_or_default())?; cmd.run(&*spec) }) - }, + } Some(Subcommand::Benchmark(cmd)) => { let runner = cli.create_runner(cmd)?; // Switch on the concrete benchmark sub-command- match cmd { - BenchmarkCmd::Pallet(cmd) => + BenchmarkCmd::Pallet(cmd) => { if cfg!(feature = "runtime-benchmarks") { runner.sync_run(|config| cmd.run::(config)) } else { Err("Benchmarking wasn't enabled when building the node. \ You can enable it with `--features runtime-benchmarks`." .into()) - }, + } + } BenchmarkCmd::Block(cmd) => runner.sync_run(|config| { let partials = new_partial(&config)?; cmd.run(partials.client) }), #[cfg(not(feature = "runtime-benchmarks"))] - BenchmarkCmd::Storage(_) => + BenchmarkCmd::Storage(_) => { return Err(sc_cli::Error::Input( "Compile with --features=runtime-benchmarks \ to enable storage benchmarks." .into(), ) - .into()), + .into()) + } #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { let partials = new_partial(&config)?; @@ -305,14 +301,15 @@ pub fn run() -> Result<()> { let storage = partials.backend.expose_storage(); cmd.run(config, partials.client.clone(), db, storage) }), - BenchmarkCmd::Machine(cmd) => - runner.sync_run(|config| cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone())), + BenchmarkCmd::Machine(cmd) => { + runner.sync_run(|config| cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone())) + } // NOTE: this allows the Client to leniently implement // new benchmark commands without requiring a companion MR. #[allow(unreachable_patterns)] _ => Err("Benchmarking sub-command unsupported".into()), } - }, + } #[cfg(feature = "try-runtime")] Some(Subcommand::TryRuntime(cmd)) => { let runner = cli.create_runner(cmd)?; @@ -325,14 +322,16 @@ pub fn run() -> Result<()> { // grab the task manager. let registry = &runner.config().prometheus_config.as_ref().map(|cfg| &cfg.registry); - let task_manager = - sc_service::TaskManager::new(runner.config().tokio_handle.clone(), *registry) - .map_err(|e| format!("Error: {:?}", e))?; + let task_manager = sc_service::TaskManager::new(runner.config().tokio_handle.clone(), *registry) + .map_err(|e| format!("Error: {:?}", e))?; runner.async_run(|_| { - Ok((cmd.run::>(), task_manager)) + Ok(( + cmd.run::>(), + task_manager, + )) }) - }, + } #[cfg(not(feature = "try-runtime"))] Some(Subcommand::TryRuntime) => Err("Try-runtime was not enabled when building the node. \ You can enable it with `--features try-runtime`." @@ -395,7 +394,7 @@ pub fn run() -> Result<()> { .map(|r| r.0) .map_err(Into::into) }) - }, + } } } @@ -454,19 +453,13 @@ impl CliConfiguration for RelayChainCli { } fn prometheus_config( - &self, - default_listen_port: u16, - chain_spec: &Box, + &self, default_listen_port: u16, chain_spec: &Box, ) -> Result> { self.base.base.prometheus_config(default_listen_port, chain_spec) } fn init( - &self, - _support_url: &String, - _impl_version: &String, - _logger_hook: F, - _config: &sc_service::Configuration, + &self, _support_url: &String, _impl_version: &String, _logger_hook: F, _config: &sc_service::Configuration, ) -> Result<()> where F: FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration), @@ -477,7 +470,11 @@ impl CliConfiguration for RelayChainCli { fn chain_id(&self, is_dev: bool) -> Result { let chain_id = self.base.base.chain_id(is_dev)?; - Ok(if chain_id.is_empty() { self.chain_id.clone().unwrap_or_default() } else { chain_id }) + Ok(if chain_id.is_empty() { + self.chain_id.clone().unwrap_or_default() + } else { + chain_id + }) } fn role(&self, is_dev: bool) -> Result { @@ -524,10 +521,7 @@ impl CliConfiguration for RelayChainCli { self.base.base.announce_block() } - fn telemetry_endpoints( - &self, - chain_spec: &Box, - ) -> Result> { + fn telemetry_endpoints(&self, chain_spec: &Box) -> Result> { self.base.base.telemetry_endpoints(chain_spec) } diff --git a/nodes/parachain/src/rpc.rs b/nodes/parachain/src/rpc.rs index 6cff4195a..ae5a4ed96 100644 --- a/nodes/parachain/src/rpc.rs +++ b/nodes/parachain/src/rpc.rs @@ -43,9 +43,7 @@ pub struct FullDeps { } /// Instantiate all RPC extensions. -pub fn create_full( - deps: FullDeps, -) -> Result> +pub fn create_full(deps: FullDeps) -> Result> where C: ProvideRuntimeApi + HeaderBackend @@ -63,7 +61,11 @@ where use substrate_frame_rpc_system::{System, SystemApiServer}; let mut module = RpcExtension::new(()); - let FullDeps { client, pool, deny_unsafe } = deps; + let FullDeps { + client, + pool, + deny_unsafe, + } = deps; module.merge(System::new(client.clone(), pool, deny_unsafe).into_rpc())?; module.merge(TransactionPayment::new(client).into_rpc())?; diff --git a/nodes/parachain/src/service.rs b/nodes/parachain/src/service.rs index 352435bc0..49dd30d28 100644 --- a/nodes/parachain/src/service.rs +++ b/nodes/parachain/src/service.rs @@ -25,12 +25,10 @@ use polimec_parachain_runtime::{opaque::Block, Hash, RuntimeApi}; // Cumulus Imports use cumulus_client_consensus_aura::{AuraConsensus, BuildAuraConsensusParams, SlotProportion}; -use cumulus_client_consensus_common::{ - ParachainBlockImport as TParachainBlockImport, ParachainConsensus, -}; +use cumulus_client_consensus_common::{ParachainBlockImport as TParachainBlockImport, ParachainConsensus}; use cumulus_client_service::{ - build_network, build_relay_chain_interface, prepare_node_config, start_collator, - start_full_node, BuildNetworkParams, StartCollatorParams, StartFullNodeParams, + build_network, build_relay_chain_interface, prepare_node_config, start_collator, start_full_node, + BuildNetworkParams, StartCollatorParams, StartFullNodeParams, }; use cumulus_primitives_core::ParaId; use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface}; @@ -104,12 +102,11 @@ pub fn new_partial( config.runtime_cache_size, ); - let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( - config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; + let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( + config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, + )?; let client = Arc::new(client); let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle()); @@ -154,11 +151,8 @@ pub fn new_partial( /// This is the actual implementation that is abstract over the executor and the runtime api. #[sc_tracing::logging::prefix_logs_with("Parachain")] async fn start_node_impl( - parachain_config: Configuration, - polkadot_config: Configuration, - collator_options: CollatorOptions, - para_id: ParaId, - hwbench: Option, + parachain_config: Configuration, polkadot_config: Configuration, collator_options: CollatorOptions, + para_id: ParaId, hwbench: Option, ) -> sc_service::error::Result<(TaskManager, Arc)> { let parachain_config = prepare_node_config(parachain_config); @@ -189,17 +183,16 @@ async fn start_node_impl( let transaction_pool = params.transaction_pool.clone(); let import_queue_service = params.import_queue.service(); - let (network, system_rpc_tx, tx_handler_controller, start_network) = - build_network(BuildNetworkParams { - parachain_config: ¶chain_config, - client: client.clone(), - transaction_pool: transaction_pool.clone(), - para_id, - spawn_handle: task_manager.spawn_handle(), - relay_chain_interface: relay_chain_interface.clone(), - import_queue: params.import_queue, - }) - .await?; + let (network, system_rpc_tx, tx_handler_controller, start_network) = build_network(BuildNetworkParams { + parachain_config: ¶chain_config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + para_id, + spawn_handle: task_manager.spawn_handle(), + relay_chain_interface: relay_chain_interface.clone(), + import_queue: params.import_queue, + }) + .await?; if parachain_config.offchain_worker.enabled { sc_service::build_offchain_workers( @@ -245,9 +238,7 @@ async fn start_node_impl( // in there and swapping out the requirements for your own are probably a good idea. The // requirements for a para-chain are dictated by its relay-chain. if !SUBSTRATE_REFERENCE_HARDWARE.check_hardware(&hwbench) && validator { - log::warn!( - "⚠️ The hardware does not meet the minimal requirements for role 'Authority'." - ); + log::warn!("⚠️ The hardware does not meet the minimal requirements for role 'Authority'."); } if let Some(ref mut telemetry) = telemetry { @@ -325,52 +316,39 @@ async fn start_node_impl( /// Build the import queue for the parachain runtime. fn build_import_queue( - client: Arc, - block_import: ParachainBlockImport, - config: &Configuration, - telemetry: Option, - task_manager: &TaskManager, + client: Arc, block_import: ParachainBlockImport, config: &Configuration, + telemetry: Option, task_manager: &TaskManager, ) -> Result, sc_service::Error> { let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; - cumulus_client_consensus_aura::import_queue::< - sp_consensus_aura::sr25519::AuthorityPair, - _, - _, - _, - _, - _, - >(cumulus_client_consensus_aura::ImportQueueParams { - block_import, - client, - create_inherent_data_providers: move |_, _| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + cumulus_client_consensus_aura::import_queue::( + cumulus_client_consensus_aura::ImportQueueParams { + block_import, + client, + create_inherent_data_providers: move |_, _| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, slot_duration, ); - Ok((slot, timestamp)) + Ok((slot, timestamp)) + }, + registry: config.prometheus_registry(), + spawner: &task_manager.spawn_essential_handle(), + telemetry, }, - registry: config.prometheus_registry(), - spawner: &task_manager.spawn_essential_handle(), - telemetry, - }) + ) .map_err(Into::into) } fn build_consensus( - client: Arc, - block_import: ParachainBlockImport, - prometheus_registry: Option<&Registry>, - telemetry: Option, - task_manager: &TaskManager, + client: Arc, block_import: ParachainBlockImport, prometheus_registry: Option<&Registry>, + telemetry: Option, task_manager: &TaskManager, relay_chain_interface: Arc, transaction_pool: Arc>, - sync_oracle: Arc>, - keystore: SyncCryptoStorePtr, - force_authoring: bool, + sync_oracle: Arc>, keystore: SyncCryptoStorePtr, force_authoring: bool, para_id: ParaId, ) -> Result>, sc_service::Error> { let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; @@ -388,14 +366,13 @@ fn build_consensus( create_inherent_data_providers: move |_, (relay_parent, validation_data)| { let relay_chain_interface = relay_chain_interface.clone(); async move { - let parachain_inherent = - cumulus_primitives_parachain_inherent::ParachainInherentData::create_at( - relay_parent, - &relay_chain_interface, - &validation_data, - para_id, - ) - .await; + let parachain_inherent = cumulus_primitives_parachain_inherent::ParachainInherentData::create_at( + relay_parent, + &relay_chain_interface, + &validation_data, + para_id, + ) + .await; let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( @@ -404,9 +381,7 @@ fn build_consensus( ); let parachain_inherent = parachain_inherent.ok_or_else(|| { - Box::::from( - "Failed to create parachain inherent", - ) + Box::::from("Failed to create parachain inherent") })?; Ok((slot, timestamp, parachain_inherent)) } @@ -425,16 +400,21 @@ fn build_consensus( telemetry, }; - Ok(AuraConsensus::build::(params)) + Ok(AuraConsensus::build::< + sp_consensus_aura::sr25519::AuthorityPair, + _, + _, + _, + _, + _, + _, + >(params)) } /// Start a parachain node. pub async fn start_parachain_node( - parachain_config: Configuration, - polkadot_config: Configuration, - collator_options: CollatorOptions, - para_id: ParaId, - hwbench: Option, + parachain_config: Configuration, polkadot_config: Configuration, collator_options: CollatorOptions, + para_id: ParaId, hwbench: Option, ) -> sc_service::error::Result<(TaskManager, Arc)> { start_node_impl(parachain_config, polkadot_config, collator_options, para_id, hwbench).await } diff --git a/nodes/standalone/src/benchmarking.rs b/nodes/standalone/src/benchmarking.rs index 9ecb50ae6..4b4a86d95 100644 --- a/nodes/standalone/src/benchmarking.rs +++ b/nodes/standalone/src/benchmarking.rs @@ -115,10 +115,7 @@ impl frame_benchmarking_cli::ExtrinsicBuilder for TransferKeepAliveBuilder { /// /// Note: Should only be used for benchmarking. pub fn create_benchmark_extrinsic( - client: &FullClient, - sender: sp_core::sr25519::Pair, - call: runtime::RuntimeCall, - nonce: u32, + client: &FullClient, sender: sp_core::sr25519::Pair, call: runtime::RuntimeCall, nonce: u32, ) -> runtime::UncheckedExtrinsic { let genesis_hash = client.block_hash(0).ok().flatten().expect("Genesis block exists; qed"); let best_hash = client.chain_info().best_hash; diff --git a/nodes/standalone/src/chain_spec.rs b/nodes/standalone/src/chain_spec.rs index 6db1a7883..ebfc0ddee 100644 --- a/nodes/standalone/src/chain_spec.rs +++ b/nodes/standalone/src/chain_spec.rs @@ -15,7 +15,7 @@ // along with this program. If not, see . use polimec_standalone_runtime::{ - AccountId, BalancesConfig, GenesisConfig, SessionConfig, Signature, SudoConfig, SystemConfig, + AccountId, BalancesConfig, CredentialsConfig, GenesisConfig, SessionConfig, Signature, SudoConfig, SystemConfig, WASM_BINARY, }; use sc_service::{ChainType, Properties}; @@ -153,9 +153,7 @@ pub fn local_testnet_config() -> Result { /// Configure initial storage state for FRAME modules. fn testnet_genesis( - wasm_binary: &[u8], - initial_authorities: Vec<(AccountId, AuraId, GrandpaId)>, - root_key: AccountId, + wasm_binary: &[u8], initial_authorities: Vec<(AccountId, AuraId, GrandpaId)>, root_key: AccountId, endowed_accounts: Vec, ) -> GenesisConfig { GenesisConfig { @@ -177,6 +175,12 @@ fn testnet_genesis( council: Default::default(), technical_committee: Default::default(), democracy: Default::default(), + credentials: CredentialsConfig { + issuers: endowed_accounts.clone(), + retails: endowed_accounts.clone(), + professionals: endowed_accounts.clone(), + institutionals: endowed_accounts.clone(), + }, session: SessionConfig { keys: initial_authorities .iter() diff --git a/nodes/standalone/src/command.rs b/nodes/standalone/src/command.rs index 7b4d488f6..d9145c6aa 100644 --- a/nodes/standalone/src/command.rs +++ b/nodes/standalone/src/command.rs @@ -55,8 +55,7 @@ impl SubstrateCli for Cli { Ok(match id { "dev" => Box::new(chain_spec::development_config()?), "" | "local" => Box::new(chain_spec::local_testnet_config()?), - path => - Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?), + path => Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?), }) } @@ -74,53 +73,69 @@ pub fn run() -> sc_cli::Result<()> { Some(Subcommand::BuildSpec(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) - }, + } Some(Subcommand::CheckBlock(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { client, task_manager, import_queue, .. } = - service::new_partial(&config)?; + let PartialComponents { + client, + task_manager, + import_queue, + .. + } = service::new_partial(&config)?; Ok((cmd.run(client, import_queue), task_manager)) }) - }, + } Some(Subcommand::ExportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { client, task_manager, .. } = service::new_partial(&config)?; + let PartialComponents { + client, task_manager, .. + } = service::new_partial(&config)?; Ok((cmd.run(client, config.database), task_manager)) }) - }, + } Some(Subcommand::ExportState(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { client, task_manager, .. } = service::new_partial(&config)?; + let PartialComponents { + client, task_manager, .. + } = service::new_partial(&config)?; Ok((cmd.run(client, config.chain_spec), task_manager)) }) - }, + } Some(Subcommand::ImportBlocks(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { client, task_manager, import_queue, .. } = - service::new_partial(&config)?; + let PartialComponents { + client, + task_manager, + import_queue, + .. + } = service::new_partial(&config)?; Ok((cmd.run(client, import_queue), task_manager)) }) - }, + } Some(Subcommand::PurgeChain(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| cmd.run(config.database)) - }, + } Some(Subcommand::Revert(cmd)) => { let runner = cli.create_runner(cmd)?; runner.async_run(|config| { - let PartialComponents { client, task_manager, backend, .. } = - service::new_partial(&config)?; + let PartialComponents { + client, + task_manager, + backend, + .. + } = service::new_partial(&config)?; let aux_revert = Box::new(|client, _, blocks| { sc_finality_grandpa::revert(client, blocks)?; Ok(()) }); Ok((cmd.run(client, backend, Some(aux_revert)), task_manager)) }) - }, + } Some(Subcommand::Benchmark(cmd)) => { let runner = cli.create_runner(cmd)?; @@ -130,45 +145,35 @@ pub fn run() -> sc_cli::Result<()> { match cmd { BenchmarkCmd::Pallet(cmd) => { if !cfg!(feature = "runtime-benchmarks") { - return Err( - "Runtime benchmarking wasn't enabled when building the node. \ + return Err("Runtime benchmarking wasn't enabled when building the node. \ You can enable it with `--features runtime-benchmarks`." - .into(), - ) + .into()); } cmd.run::(config) - }, + } BenchmarkCmd::Block(cmd) => { let PartialComponents { client, .. } = service::new_partial(&config)?; cmd.run(client) - }, + } #[cfg(not(feature = "runtime-benchmarks"))] - BenchmarkCmd::Storage(_) => Err( - "Storage benchmarking can be enabled with `--features runtime-benchmarks`." - .into(), - ), + BenchmarkCmd::Storage(_) => { + Err("Storage benchmarking can be enabled with `--features runtime-benchmarks`.".into()) + } #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => { - let PartialComponents { client, backend, .. } = - service::new_partial(&config)?; + let PartialComponents { client, backend, .. } = service::new_partial(&config)?; let db = backend.expose_db(); let storage = backend.expose_storage(); cmd.run(config, client, db, storage) - }, + } BenchmarkCmd::Overhead(cmd) => { let PartialComponents { client, .. } = service::new_partial(&config)?; let ext_builder = RemarkBuilder::new(client.clone()); - cmd.run( - config, - client, - inherent_benchmark_data()?, - Vec::new(), - &ext_builder, - ) - }, + cmd.run(config, client, inherent_benchmark_data()?, Vec::new(), &ext_builder) + } BenchmarkCmd::Extrinsic(cmd) => { let PartialComponents { client, .. } = service::new_partial(&config)?; // Register the *Remark* and *TKA* builders. @@ -182,12 +187,11 @@ pub fn run() -> sc_cli::Result<()> { ]); cmd.run(client, inherent_benchmark_data()?, Vec::new(), &ext_factory) - }, - BenchmarkCmd::Machine(cmd) => - cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone()), + } + BenchmarkCmd::Machine(cmd) => cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone()), } }) - }, + } #[cfg(feature = "try-runtime")] Some(Subcommand::TryRuntime(cmd)) => { let runner = cli.create_runner(cmd)?; @@ -195,12 +199,11 @@ pub fn run() -> sc_cli::Result<()> { // we don't need any of the components of new_partial, just a runtime, or a task // manager to do `async_run`. let registry = config.prometheus_config.as_ref().map(|cfg| &cfg.registry); - let task_manager = - sc_service::TaskManager::new(config.tokio_handle.clone(), registry) - .map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?; + let task_manager = sc_service::TaskManager::new(config.tokio_handle.clone(), registry) + .map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?; Ok((cmd.run::(config), task_manager)) }) - }, + } #[cfg(not(feature = "try-runtime"))] Some(Subcommand::TryRuntime) => Err("TryRuntime wasn't enabled when building the node. \ You can enable it with `--features try-runtime`." @@ -208,12 +211,11 @@ pub fn run() -> sc_cli::Result<()> { Some(Subcommand::ChainInfo(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| cmd.run::(&config)) - }, + } None => { let runner = cli.create_runner(&cli.run)?; - runner.run_node_until_exit(|config| async move { - service::new_full(config).map_err(sc_cli::Error::Service) - }) - }, + runner + .run_node_until_exit(|config| async move { service::new_full(config).map_err(sc_cli::Error::Service) }) + } } } diff --git a/nodes/standalone/src/rpc.rs b/nodes/standalone/src/rpc.rs index d1cd753fd..c0051d536 100644 --- a/nodes/standalone/src/rpc.rs +++ b/nodes/standalone/src/rpc.rs @@ -43,9 +43,7 @@ pub struct FullDeps { } /// Instantiate all full RPC extensions. -pub fn create_full( - deps: FullDeps, -) -> Result, Box> +pub fn create_full(deps: FullDeps) -> Result, Box> where C: ProvideRuntimeApi, C: HeaderBackend + HeaderMetadata + 'static, @@ -59,7 +57,11 @@ where use substrate_frame_rpc_system::{System, SystemApiServer}; let mut module = RpcModule::new(()); - let FullDeps { client, pool, deny_unsafe } = deps; + let FullDeps { + client, + pool, + deny_unsafe, + } = deps; module.merge(System::new(client.clone(), pool.clone(), deny_unsafe).into_rpc())?; module.merge(TransactionPayment::new(client).into_rpc())?; diff --git a/nodes/standalone/src/service.rs b/nodes/standalone/src/service.rs index b92c2e81d..e7297d0f7 100644 --- a/nodes/standalone/src/service.rs +++ b/nodes/standalone/src/service.rs @@ -47,8 +47,7 @@ impl sc_executor::NativeExecutionDispatch for ExecutorDispatch { } } -pub(crate) type FullClient = - sc_service::TFullClient>; +pub(crate) type FullClient = sc_service::TFullClient>; type FullBackend = sc_service::TFullBackend; type FullSelectChain = sc_consensus::LongestChain; @@ -62,12 +61,7 @@ pub fn new_partial( sc_consensus::DefaultImportQueue, sc_transaction_pool::FullPool, ( - sc_finality_grandpa::GrandpaBlockImport< - FullBackend, - Block, - FullClient, - FullSelectChain, - >, + sc_finality_grandpa::GrandpaBlockImport, sc_finality_grandpa::LinkHalf, Option, ), @@ -75,7 +69,7 @@ pub fn new_partial( ServiceError, > { if config.keystore_remote.is_some() { - return Err(ServiceError::Other("Remote Keystores are not supported.".into())) + return Err(ServiceError::Other("Remote Keystores are not supported.".into())); } let telemetry = config @@ -96,12 +90,11 @@ pub fn new_partial( config.runtime_cache_size, ); - let (client, backend, keystore_container, task_manager) = - sc_service::new_full_parts::( - config, - telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), - executor, - )?; + let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( + config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, + )?; let client = Arc::new(client); let telemetry = telemetry.map(|(worker, telemetry)| { @@ -128,27 +121,26 @@ pub fn new_partial( let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - let import_queue = - sc_consensus_aura::import_queue::(ImportQueueParams { - block_import: grandpa_block_import.clone(), - justification_import: Some(Box::new(grandpa_block_import.clone())), - client: client.clone(), - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + let import_queue = sc_consensus_aura::import_queue::(ImportQueueParams { + block_import: grandpa_block_import.clone(), + justification_import: Some(Box::new(grandpa_block_import.clone())), + client: client.clone(), + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, slot_duration, ); - Ok((slot, timestamp)) - }, - spawner: &task_manager.spawn_essential_handle(), - registry: config.prometheus_registry(), - check_for_equivocation: Default::default(), - telemetry: telemetry.as_ref().map(|x| x.handle()), - compatibility_mode: Default::default(), - })?; + Ok((slot, timestamp)) + }, + spawner: &task_manager.spawn_essential_handle(), + registry: config.prometheus_registry(), + check_for_equivocation: Default::default(), + telemetry: telemetry.as_ref().map(|x| x.handle()), + compatibility_mode: Default::default(), + })?; Ok(sc_service::PartialComponents { client, @@ -185,11 +177,12 @@ pub fn new_full(mut config: Configuration) -> Result if let Some(url) = &config.keystore_remote { match remote_keystore(url) { Ok(k) => keystore_container.set_remote_keystore(k), - Err(e) => + Err(e) => { return Err(ServiceError::Other(format!( "Error hooking up remote keystore for {}: {}", url, e - ))), + ))) + } }; } let grandpa_protocol_name = sc_finality_grandpa::protocol_standard_name( @@ -200,7 +193,9 @@ pub fn new_full(mut config: Configuration) -> Result config .network .extra_sets - .push(sc_finality_grandpa::grandpa_peers_set_config(grandpa_protocol_name.clone())); + .push(sc_finality_grandpa::grandpa_peers_set_config( + grandpa_protocol_name.clone(), + )); let warp_sync = Arc::new(sc_finality_grandpa::warp_proof::NetworkProvider::new( backend.clone(), grandpa_link.shared_authority_set().clone(), @@ -219,12 +214,7 @@ pub fn new_full(mut config: Configuration) -> Result })?; if config.offchain_worker.enabled { - sc_service::build_offchain_workers( - &config, - task_manager.spawn_handle(), - client.clone(), - network.clone(), - ); + sc_service::build_offchain_workers(&config, task_manager.spawn_handle(), client.clone(), network.clone()); } let role = config.role.clone(); @@ -239,8 +229,11 @@ pub fn new_full(mut config: Configuration) -> Result let pool = transaction_pool.clone(); Box::new(move |deny_unsafe, _| { - let deps = - crate::rpc::FullDeps { client: client.clone(), pool: pool.clone(), deny_unsafe }; + let deps = crate::rpc::FullDeps { + client: client.clone(), + pool: pool.clone(), + deny_unsafe, + }; crate::rpc::create_full(deps).map_err(Into::into) }) }; @@ -270,34 +263,32 @@ pub fn new_full(mut config: Configuration) -> Result let slot_duration = sc_consensus_aura::slot_duration(&*client)?; - let aura = sc_consensus_aura::start_aura::( - StartAuraParams { - slot_duration, - client, - select_chain, - block_import, - proposer_factory, - create_inherent_data_providers: move |_, ()| async move { - let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); - - let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + let aura = sc_consensus_aura::start_aura::(StartAuraParams { + slot_duration, + client, + select_chain, + block_import, + proposer_factory, + create_inherent_data_providers: move |_, ()| async move { + let timestamp = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( *timestamp, slot_duration, ); - Ok((slot, timestamp)) - }, - force_authoring, - backoff_authoring_blocks, - keystore: keystore_container.sync_keystore(), - sync_oracle: network.clone(), - justification_sync_link: network.clone(), - block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), - max_block_proposal_slot_portion: None, - telemetry: telemetry.as_ref().map(|x| x.handle()), - compatibility_mode: Default::default(), + Ok((slot, timestamp)) }, - )?; + force_authoring, + backoff_authoring_blocks, + keystore: keystore_container.sync_keystore(), + sync_oracle: network.clone(), + justification_sync_link: network.clone(), + block_proposal_slot_portion: SlotProportion::new(2f32 / 3f32), + max_block_proposal_slot_portion: None, + telemetry: telemetry.as_ref().map(|x| x.handle()), + compatibility_mode: Default::default(), + })?; // the AURA authoring task is considered essential, i.e. if it // fails we take down the service with it. @@ -309,8 +300,11 @@ pub fn new_full(mut config: Configuration) -> Result if enable_grandpa { // if the node isn't actively participating in consensus then it doesn't // need a keystore, regardless of which protocol we use below. - let keystore = - if role.is_authority() { Some(keystore_container.sync_keystore()) } else { None }; + let keystore = if role.is_authority() { + Some(keystore_container.sync_keystore()) + } else { + None + }; let grandpa_config = sc_finality_grandpa::Config { // FIXME #1578 make this available through chainspec diff --git a/pallets/funding/Cargo.toml b/pallets/funding/Cargo.toml index 88731b9bb..1125957c9 100644 --- a/pallets/funding/Cargo.toml +++ b/pallets/funding/Cargo.toml @@ -22,6 +22,7 @@ frame-system.workspace = true sp-std.workspace = true sp-runtime.workspace = true sp-arithmetic.workspace = true +polimec-traits.workspace = true # Benchmarking dependencies frame-benchmarking = { workspace = true, optional = true } @@ -45,6 +46,7 @@ std = [ "frame-system/std", "pallet-assets/std", "pallet-balances/std", + "polimec-traits/std", "frame-benchmarking?/std", ] runtime-benchmarks = [ diff --git a/pallets/funding/src/benchmarking.rs b/pallets/funding/src/benchmarking.rs index e443e7cb3..2e789b8c7 100644 --- a/pallets/funding/src/benchmarking.rs +++ b/pallets/funding/src/benchmarking.rs @@ -68,9 +68,7 @@ fn get_events() -> frame_benchmarking::Vec<>() } -fn create_default_project( - id: Option, -) -> (T::ProjectIdParameter, T::AccountId, ProjectMetadataOf) { +fn create_default_project(id: Option) -> (T::ProjectIdParameter, T::AccountId, ProjectMetadataOf) { let issuer: T::AccountId = account::("Alice", 1, 1); let project_id_parameter = id.unwrap_or(0); let project_id = T::BenchmarkHelper::create_project_id_parameter(project_id_parameter); @@ -79,13 +77,9 @@ fn create_default_project( (project_id, issuer, project) } -fn create_default_minted_project( - id: Option, -) -> (T::ProjectIdParameter, T::AccountId) { +fn create_default_minted_project(id: Option) -> (T::ProjectIdParameter, T::AccountId) { let (project_id, issuer, project) = create_default_project::(id); - assert!( - PolimecFunding::::create(SystemOrigin::Signed(issuer.clone()).into(), project).is_ok() - ); + assert!(PolimecFunding::::create(SystemOrigin::Signed(issuer.clone()).into(), project).is_ok()); (project_id, issuer) } @@ -95,9 +89,7 @@ pub fn run_to_block(n: T::BlockNumber) { crate::Pallet::::on_finalize(frame_system::Pallet::::block_number()); frame_system::Pallet::::on_finalize(frame_system::Pallet::::block_number()); crate::Pallet::::on_idle(frame_system::Pallet::::block_number(), max_weight); - frame_system::Pallet::::set_block_number( - frame_system::Pallet::::block_number() + One::one(), - ); + frame_system::Pallet::::set_block_number(frame_system::Pallet::::block_number() + One::one()); frame_system::Pallet::::on_initialize(frame_system::Pallet::::block_number()); crate::Pallet::::on_initialize(frame_system::Pallet::::block_number()); crate::Pallet::::on_idle(frame_system::Pallet::::block_number(), max_weight); diff --git a/pallets/funding/src/functions.rs b/pallets/funding/src/functions.rs index 9c2e4e839..2e0e44c8d 100644 --- a/pallets/funding/src/functions.rs +++ b/pallets/funding/src/functions.rs @@ -48,10 +48,7 @@ impl Pallet { /// # Next step /// The issuer will call an extrinsic to start the evaluation round of the project. /// [`do_evaluation_start`](Self::do_evaluation_start) will be executed. - pub fn do_create( - issuer: T::AccountId, - project: ProjectMetadataOf, - ) -> Result<(), DispatchError> { + pub fn do_create(issuer: T::AccountId, project: ProjectMetadataOf) -> Result<(), DispatchError> { // TODO: Probably the issuers don't want to sell all of their tokens. Is there some logic for this? // also even if an issuer wants to sell all their tokens, they could target a lower amount than that to consider it a success // * Get variables * @@ -66,10 +63,9 @@ impl Pallet { if let Err(error) = project.validity_check() { return match error { ValidityError::PriceTooLow => Err(Error::::PriceTooLow.into()), - ValidityError::ParticipantsSizeError => - Err(Error::::ParticipantsSizeError.into()), + ValidityError::ParticipantsSizeError => Err(Error::::ParticipantsSizeError.into()), ValidityError::TicketSizeError => Err(Error::::TicketSizeError.into()), - } + }; } // * Calculate new variables * @@ -79,10 +75,7 @@ impl Pallet { fundraising_target, project_status: ProjectStatus::Application, phase_transition_points: PhaseTransitionPoints { - application: BlockNumberPair::new( - Some(>::block_number()), - None, - ), + application: BlockNumberPair::new(Some(>::block_number()), None), evaluation: BlockNumberPair::new(None, None), auction_initialize_period: BlockNumberPair::new(None, None), english_auction: BlockNumberPair::new(None, None), @@ -128,8 +121,7 @@ impl Pallet { /// to the next round by `on_initialize` using [`do_evaluation_end`](Self::do_evaluation_end) pub fn do_evaluation_start(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; let now = >::block_number(); @@ -139,7 +131,10 @@ impl Pallet { Error::::ProjectNotInApplicationRound ); ensure!(!project_info.is_frozen, Error::::ProjectAlreadyFrozen); - ensure!(project.offchain_information_hash.is_some(), Error::::MetadataNotProvided); + ensure!( + project.offchain_information_hash.is_some(), + Error::::MetadataNotProvided + ); // * Calculate new variables * let evaluation_end_block = now + T::EvaluationDuration::get(); @@ -196,8 +191,7 @@ impl Pallet { /// unbonds the evaluators funds. pub fn do_evaluation_end(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); let evaluation_end_block = project_info .phase_transition_points @@ -291,8 +285,7 @@ impl Pallet { /// [`do_candle_auction`](Self::do_candle_auction). pub fn do_english_auction(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); let auction_initialize_period_start_block = project_info .phase_transition_points @@ -369,8 +362,7 @@ impl Pallet { /// by calling [`do_community_funding`](Self::do_community_funding). pub fn do_candle_auction(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); let english_end_block = project_info .phase_transition_points @@ -432,8 +424,7 @@ impl Pallet { /// starts the remainder round, where anyone can buy at that price point. pub fn do_community_funding(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); let auction_candle_start_block = project_info .phase_transition_points @@ -447,27 +438,24 @@ impl Pallet { .ok_or(Error::::FieldIsNone)?; // * Validity checks * - ensure!(now > auction_candle_end_block, Error::::TooEarlyForCommunityRoundStart); + ensure!( + now > auction_candle_end_block, + Error::::TooEarlyForCommunityRoundStart + ); ensure!( project_info.project_status == ProjectStatus::AuctionRound(AuctionPhase::Candle), Error::::ProjectNotInCandleAuctionRound ); // * Calculate new variables * - let end_block = - Self::select_random_block(auction_candle_start_block, auction_candle_end_block); + let end_block = Self::select_random_block(auction_candle_start_block, auction_candle_end_block); let community_start_block = now + 1u32.into(); let community_end_block = now + T::CommunityFundingDuration::get(); // * Update Storage * - Self::calculate_weighted_average_price( - project_id, - end_block, - project_info.fundraising_target, - )?; + Self::calculate_weighted_average_price(project_id, end_block, project_info.fundraising_target)?; // Get info again after updating it with new price. - let mut project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; project_info.phase_transition_points.random_candle_ending = Some(end_block); project_info .phase_transition_points @@ -509,8 +497,7 @@ impl Pallet { /// [`do_end_funding`](Self::do_end_funding). pub fn do_remainder_funding(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); let community_end_block = project_info .phase_transition_points @@ -537,10 +524,7 @@ impl Pallet { project_info.project_status = ProjectStatus::RemainderRound; ProjectsDetails::::insert(project_id, project_info); // Schedule for automatic transition by `on_initialize` - Self::add_to_update_store( - remainder_end_block + 1u32.into(), - (&project_id, UpdateType::FundingEnd), - ); + Self::add_to_update_store(remainder_end_block + 1u32.into(), (&project_id, UpdateType::FundingEnd)); // * Emit events * Self::deposit_event(Event::::RemainderFundingStarted { project_id }); @@ -580,12 +564,10 @@ impl Pallet { /// If **unsuccessful**, users every user should have their PLMC vesting unbonded. pub fn do_end_funding(project_id: T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); // TODO: PLMC-149 Check if make sense to set the admin as T::fund_account_id(project_id) - let issuer = - ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; + let issuer = ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; let project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; let token_information = project.token_information; let remaining_cts = project_info.remaining_contribution_tokens; @@ -640,8 +622,7 @@ impl Pallet { /// WIP pub fn do_ready_to_launch(project_id: &T::ProjectIdentifier) -> Result<(), DispatchError> { // * Get variables * - let mut project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; // * Validity checks * ensure!( @@ -672,18 +653,17 @@ impl Pallet { /// * [`ProjectsDetails`] - Check that the project is not frozen /// * [`ProjectsMetadata`] - Update the metadata hash pub fn do_edit_metadata( - issuer: T::AccountId, - project_id: T::ProjectIdentifier, - project_metadata_hash: T::Hash, + issuer: T::AccountId, project_id: T::ProjectIdentifier, project_metadata_hash: T::Hash, ) -> Result<(), DispatchError> { // * Get variables * - let mut project = - ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; - let project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let mut project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; + let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; // * Validity checks * - ensure!(ProjectsIssuers::::get(project_id) == Some(issuer), Error::::NotAllowed); + ensure!( + ProjectsIssuers::::get(project_id) == Some(issuer), + Error::::NotAllowed + ); ensure!(!project_info.is_frozen, Error::::Frozen); ensure!( !Images::::contains_key(project_metadata_hash), @@ -721,15 +701,11 @@ impl Pallet { /// * [`EvaluationBonds`] - Update the storage with the evaluators bond, by either increasing an existing /// one, or appending a new bond pub fn do_evaluation_bond( - evaluator: T::AccountId, - project_id: T::ProjectIdentifier, - amount: BalanceOf, + evaluator: T::AccountId, project_id: T::ProjectIdentifier, amount: BalanceOf, ) -> Result<(), DispatchError> { // * Get variables * - let project_issuer = - ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; - let project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let project_issuer = ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; + let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; // * Validity checks * // TODO: PLMC-133. Replace this when this PR is merged: https://github.com/KILTprotocol/kilt-node/pull/448 @@ -754,7 +730,7 @@ impl Pallet { bond.amount += amount; T::NativeCurrency::reserve_named(&BondType::Evaluation, &evaluator, amount) .map_err(|_| Error::::InsufficientBalance)?; - }, + } None => { // If the user has not bonded yet, create a new bond *maybe_bond = Some(EvaluationBond { @@ -767,7 +743,7 @@ impl Pallet { // Reserve the required PLMC T::NativeCurrency::reserve_named(&BondType::Evaluation, &evaluator, amount) .map_err(|_| Error::::InsufficientBalance)?; - }, + } } Self::deposit_event(Event::::FundsBonded { project_id, @@ -778,7 +754,11 @@ impl Pallet { })?; // * Emit events * - Self::deposit_event(Event::::FundsBonded { project_id, amount, bonder: evaluator }); + Self::deposit_event(Event::::FundsBonded { + project_id, + amount, + bonder: evaluator, + }); Ok(()) } @@ -792,12 +772,10 @@ impl Pallet { /// * [`ProjectsDetails`] - Check that the project is in the evaluation failed stage /// * [`EvaluationBonds`] - Remove the bond from storage pub fn do_failed_evaluation_unbond_for( - bond: EvaluationBond, - releaser: T::AccountId, + bond: EvaluationBond, releaser: T::AccountId, ) -> Result<(), DispatchError> { // * Get variables * - let project_info = - ProjectsDetails::::get(bond.project).ok_or(Error::::ProjectInfoNotFound)?; + let project_info = ProjectsDetails::::get(bond.project).ok_or(Error::::ProjectInfoNotFound)?; // * Validity checks * ensure!( @@ -837,17 +815,12 @@ impl Pallet { /// * [`BiddingBonds`] - Update the storage with the bidder's PLMC bond for that bid /// * [`AuctionsInfo`] - Check previous bids by that user, and update the storage with the new bid pub fn do_bid( - bidder: T::AccountId, - project_id: T::ProjectIdentifier, - amount: BalanceOf, - price: BalanceOf, + bidder: T::AccountId, project_id: T::ProjectIdentifier, amount: BalanceOf, price: BalanceOf, multiplier: Option>, ) -> Result<(), DispatchError> { // * Get variables * - let project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; - let project_issuer = - ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; + let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let project_issuer = ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; let project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; let project_ticket_size = amount.saturating_mul(price); let now = >::block_number(); @@ -871,14 +844,9 @@ impl Pallet { }; // * Calculate new variables * - let (plmc_vesting_period, ct_vesting_period) = Self::calculate_vesting_periods( - bidder.clone(), - multiplier.clone(), - amount, - price, - decimals, - ) - .map_err(|_| Error::::BadMath)?; + let (plmc_vesting_period, ct_vesting_period) = + Self::calculate_vesting_periods(bidder.clone(), multiplier.clone(), amount, price, decimals) + .map_err(|_| Error::::BadMath)?; let bid_id = Self::next_bid_id(); let required_plmc_bond = plmc_vesting_period.amount; let bid = BidInfo::new( @@ -918,8 +886,13 @@ impl Pallet { // Alternative TODO: PLMC-159. The user should have the specified currency (e.g: USDC) already on Polimec user_bids.sort_by_key(|bid| Reverse(bid.price)); AuctionsInfo::::set(project_id, bidder, Some(user_bids)); - Self::deposit_event(Event::::Bid { project_id, amount, price, multiplier }); - }, + Self::deposit_event(Event::::Bid { + project_id, + amount, + price, + multiplier, + }); + } Err(_) => { // Since the bids are sorted by price, and in this branch the Vec is full, the last element is the lowest bid let lowest_bid_index: usize = (T::MaximumBidsPerUser::get() - 1) @@ -938,8 +911,13 @@ impl Pallet { user_bids.sort_by_key(|bid| Reverse(bid.price)); AuctionsInfo::::set(project_id, bidder, Some(user_bids)); // TODO: PLMC-159. Send an XCM message to Statemine to transfer amount * multiplier USDT to the PalletId Account - Self::deposit_event(Event::::Bid { project_id, amount, price, multiplier }); - }, + Self::deposit_event(Event::::Bid { + project_id, + amount, + price, + multiplier, + }); + } }; NextBidId::::set(bid_id.saturating_add(One::one())); @@ -962,29 +940,26 @@ impl Pallet { /// * [`Contributions`] - Update storage with the new contribution /// * [`T::NativeCurrency`] - Update the balance of the contributor and the project pot pub fn do_contribute( - contributor: T::AccountId, - project_id: T::ProjectIdentifier, - token_amount: BalanceOf, + contributor: T::AccountId, project_id: T::ProjectIdentifier, token_amount: BalanceOf, multiplier: Option>, ) -> Result<(), DispatchError> { // * Get variables * - let project_issuer = - ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; - let project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; + let project_issuer = ProjectsIssuers::::get(project_id).ok_or(Error::::ProjectIssuerNotFound)?; + let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let project = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; // Default should normally be multiplier of 1 let multiplier = multiplier.unwrap_or_default(); - let weighted_average_price = - project_info.weighted_average_price.ok_or(Error::::AuctionNotStarted)?; + let weighted_average_price = project_info + .weighted_average_price + .ok_or(Error::::AuctionNotStarted)?; let decimals = project.token_information.decimals; let fund_account = Self::fund_account_id(project_id); // * Validity checks * ensure!(contributor != project_issuer, Error::::ContributionToThemselves); ensure!( - project_info.project_status == ProjectStatus::CommunityRound || - project_info.project_status == ProjectStatus::RemainderRound, + project_info.project_status == ProjectStatus::CommunityRound + || project_info.project_status == ProjectStatus::RemainderRound, Error::::AuctionNotStarted ); @@ -1025,15 +1000,15 @@ impl Pallet { let bonded_plmc = ContributingBonds::::get(project_id, contributor.clone()) .map(|bond| bond.amount) .unwrap_or_else(Zero::zero); - let mut user_contributions = - Contributions::::get(project_id, contributor.clone()).unwrap_or_default(); + let mut user_contributions = Contributions::::get(project_id, contributor.clone()).unwrap_or_default(); for contribution in user_contributions.iter() { bonded_plmc.saturating_sub(contribution.plmc_vesting.amount); } required_plmc_bond.saturating_sub(bonded_plmc); - let remaining_cts_after_purchase = - project_info.remaining_contribution_tokens.saturating_sub(buyable_tokens); + let remaining_cts_after_purchase = project_info + .remaining_contribution_tokens + .saturating_sub(buyable_tokens); let now = >::block_number(); // * Update storage * @@ -1045,10 +1020,9 @@ impl Pallet { Ok(_) => { // TODO: PLMC-159. Send an XCM message to Statemint/e to transfer a `bid.market_cap` amount of USDC (or the Currency specified by the issuer) to the PalletId Account // Alternative TODO: PLMC-159. The user should have the specified currency (e.g: USDC) already on Polimec - user_contributions - .sort_by_key(|contribution| Reverse(contribution.plmc_vesting.amount)); + user_contributions.sort_by_key(|contribution| Reverse(contribution.plmc_vesting.amount)); Contributions::::set(project_id, contributor.clone(), Some(user_contributions)); - }, + } Err(_) => { // The contributions are sorted by highest PLMC bond. If the contribution vector for the user is full, we drop the lowest/last item let lowest_contribution_index: usize = (T::MaxContributionsPerUser::get() - 1) @@ -1077,8 +1051,7 @@ impl Pallet { // Update the ContributingBonds storage ContributingBonds::::mutate(project_id, contributor.clone(), |maybe_bond| { if let Some(bond) = maybe_bond { - bond.amount = - bond.amount.saturating_sub(lowest_contribution.plmc_vesting.amount); + bond.amount = bond.amount.saturating_sub(lowest_contribution.plmc_vesting.amount); } }); @@ -1086,11 +1059,10 @@ impl Pallet { user_contributions .try_push(contribution) .expect("We removed an element, so there is always space; qed"); - user_contributions - .sort_by_key(|contribution| Reverse(contribution.plmc_vesting.amount)); + user_contributions.sort_by_key(|contribution| Reverse(contribution.plmc_vesting.amount)); Contributions::::set(project_id, contributor.clone(), Some(user_contributions)); // TODO: PLMC-159. Send an XCM message to Statemine to transfer amount * multiplier USDT to the PalletId Account - }, + } }; // Transfer funds from contributor to fund account @@ -1135,9 +1107,7 @@ impl Pallet { /// * [`BiddingBonds`] - Update the bid with the new vesting period struct, reflecting this withdrawal /// * [`T::NativeCurrency`] - Unreserve the unbonded amount pub fn do_vested_plmc_bid_unbond_for( - releaser: T::AccountId, - project_id: T::ProjectIdentifier, - bidder: T::AccountId, + releaser: T::AccountId, project_id: T::ProjectIdentifier, bidder: T::AccountId, ) -> Result<(), DispatchError> { // * Get variables * let bids = AuctionsInfo::::get(project_id, &bidder).ok_or(Error::::BidNotFound)?; @@ -1150,7 +1120,7 @@ impl Pallet { // * Validity checks * // check that it is not too early to withdraw the next amount if plmc_vesting.next_withdrawal > now { - continue + continue; } // * Calculate variables * @@ -1159,7 +1129,7 @@ impl Pallet { while let Ok(amount) = plmc_vesting.calculate_next_withdrawal() { unbond_amount = unbond_amount.saturating_add(amount); if plmc_vesting.next_withdrawal > now { - break + break; } } bid.plmc_vesting_period = plmc_vesting; @@ -1170,8 +1140,7 @@ impl Pallet { // Update the new vector that will go in AuctionInfo with the updated vesting period struct new_bids.push(bid.clone()); // Update the BiddingBonds map with the reduced amount for that project-user - let mut bond = BiddingBonds::::get(bid.project, bid.bidder.clone()) - .ok_or(Error::::FieldIsNone)?; + let mut bond = BiddingBonds::::get(bid.project, bid.bidder.clone()).ok_or(Error::::FieldIsNone)?; bond.amount = bond.amount.saturating_sub(unbond_amount); // TODO: maybe the BiddingBonds map is redundant, since we can iterate over the Bids vec and calculate it ourselves BiddingBonds::::insert(bid.project, bid.bidder.clone(), bond); @@ -1206,9 +1175,7 @@ impl Pallet { /// * `AuctionsInfo` - Check if its time to mint some tokens based on the bid vesting period, and update the bid after minting. /// * `T::ContributionTokenCurrency` - Mint the tokens to the bidder pub fn do_vested_contribution_token_bid_mint_for( - releaser: T::AccountId, - project_id: T::ProjectIdentifier, - bidder: T::AccountId, + releaser: T::AccountId, project_id: T::ProjectIdentifier, bidder: T::AccountId, ) -> Result<(), DispatchError> { // * Get variables * let bids = AuctionsInfo::::get(project_id, &bidder).ok_or(Error::::BidNotFound)?; @@ -1221,7 +1188,7 @@ impl Pallet { // * Validity checks * // check that it is not too early to withdraw the next amount if ct_vesting.next_withdrawal > now { - continue + continue; } // * Calculate variables * @@ -1229,7 +1196,7 @@ impl Pallet { while let Ok(amount) = ct_vesting.calculate_next_withdrawal() { mint_amount = mint_amount.saturating_add(amount); if ct_vesting.next_withdrawal > now { - break + break; } } bid.ct_vesting_period = ct_vesting; @@ -1266,15 +1233,11 @@ impl Pallet { /// * [`BiddingBonds`] - Update the bid with the new vesting period struct, reflecting this withdrawal /// * [`T::NativeCurrency`] - Unreserve the unbonded amount pub fn do_vested_plmc_purchase_unbond_for( - releaser: T::AccountId, - project_id: T::ProjectIdentifier, - claimer: T::AccountId, + releaser: T::AccountId, project_id: T::ProjectIdentifier, claimer: T::AccountId, ) -> Result<(), DispatchError> { // * Get variables * - let project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; - let contributions = - Contributions::::get(project_id, &claimer).ok_or(Error::::BidNotFound)?; + let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; + let contributions = Contributions::::get(project_id, &claimer).ok_or(Error::::BidNotFound)?; let now = >::block_number(); let mut updated_contributions = vec![]; @@ -1297,7 +1260,7 @@ impl Pallet { // * Validity checks * // check that it is not too early to withdraw the next amount if plmc_vesting.next_withdrawal > now { - continue + continue; } // * Calculate variables * @@ -1305,7 +1268,7 @@ impl Pallet { while let Ok(amount) = plmc_vesting.calculate_next_withdrawal() { unbond_amount = unbond_amount.saturating_add(amount); if plmc_vesting.next_withdrawal > now { - break + break; } } contribution.plmc_vesting = plmc_vesting; @@ -1330,7 +1293,9 @@ impl Pallet { // Obviously also the participants of the Auction Round should be able to claim their tokens // In theory this should never fail, since we insert the same number of contributions as before let updated_contributions: BoundedVec, T::MaxContributionsPerUser> = - updated_contributions.try_into().map_err(|_| Error::::TooManyContributions)?; + updated_contributions + .try_into() + .map_err(|_| Error::::TooManyContributions)?; Contributions::::insert(project_id, &claimer, updated_contributions); Ok(()) @@ -1347,15 +1312,11 @@ impl Pallet { /// * [`Contributions`] - Check if its time to mint some tokens based on the contributions vesting periods, and update the contribution after minting. /// * [`T::ContributionTokenCurrency`] - Mint the tokens to the claimer pub fn do_vested_contribution_token_purchase_mint_for( - releaser: T::AccountId, - project_id: T::ProjectIdentifier, - claimer: T::AccountId, + releaser: T::AccountId, project_id: T::ProjectIdentifier, claimer: T::AccountId, ) -> Result<(), DispatchError> { // * Get variables * - let project_info = - ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; - let contributions = - Contributions::::get(project_id, &claimer).ok_or(Error::::BidNotFound)?; + let project_info = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; + let contributions = Contributions::::get(project_id, &claimer).ok_or(Error::::BidNotFound)?; let now = >::block_number(); let mut updated_contributions = vec![]; @@ -1378,7 +1339,7 @@ impl Pallet { // * Validity checks * // check that it is not too early to withdraw the next amount if ct_vesting.next_withdrawal > now { - continue + continue; } // * Calculate variables * @@ -1386,7 +1347,7 @@ impl Pallet { while let Ok(amount) = ct_vesting.calculate_next_withdrawal() { mint_amount = mint_amount.saturating_add(amount); if ct_vesting.next_withdrawal > now { - break + break; } } contribution.ct_vesting = ct_vesting; @@ -1411,7 +1372,9 @@ impl Pallet { // Obviously also the participants of the Auction Round should be able to claim their tokens // In theory this should never fail, since we insert the same number of contributions as before let updated_contributions: BoundedVec, T::MaxContributionsPerUser> = - updated_contributions.try_into().map_err(|_| Error::::TooManyContributions)?; + updated_contributions + .try_into() + .map_err(|_| Error::::TooManyContributions)?; Contributions::::insert(project_id, &claimer, updated_contributions); Ok(()) @@ -1430,9 +1393,7 @@ impl Pallet { } pub fn bond_bidding( - caller: T::AccountId, - project_id: T::ProjectIdentifier, - amount: BalanceOf, + caller: T::AccountId, project_id: T::ProjectIdentifier, amount: BalanceOf, ) -> Result<(), DispatchError> { let now = >::block_number(); let project_info = ProjectsDetails::::get(project_id) @@ -1450,7 +1411,7 @@ impl Pallet { bond.amount += amount; T::NativeCurrency::reserve_named(&BondType::Bidding, &caller, amount) .map_err(|_| Error::::InsufficientBalance)?; - }, + } None => { // If the user has not bonded yet, create a new bond *maybe_bond = Some(BiddingBond { @@ -1463,7 +1424,7 @@ impl Pallet { // Reserve the required PLMC T::NativeCurrency::reserve_named(&BondType::Bidding, &caller, amount) .map_err(|_| Error::::InsufficientBalance)?; - }, + } } Self::deposit_event(Event::::FundsBonded { project_id, @@ -1477,9 +1438,7 @@ impl Pallet { } pub fn bond_contributing( - caller: T::AccountId, - project_id: T::ProjectIdentifier, - amount: BalanceOf, + caller: T::AccountId, project_id: T::ProjectIdentifier, amount: BalanceOf, ) -> Result<(), DispatchError> { let now = >::block_number(); let project_info = ProjectsDetails::::get(project_id) @@ -1497,7 +1456,7 @@ impl Pallet { bond.amount += amount; T::NativeCurrency::reserve_named(&BondType::Contributing, &caller, amount) .map_err(|_| Error::::InsufficientBalance)?; - }, + } None => { // If the user has not bonded yet, create a new bond *maybe_bond = Some(ContributingBond { @@ -1509,7 +1468,7 @@ impl Pallet { // Reserve the required PLMC T::NativeCurrency::reserve_named(&BondType::Contributing, &caller, amount) .map_err(|_| Error::::InsufficientBalance)?; - }, + } } Self::deposit_event(Event::::FundsBonded { project_id, @@ -1523,10 +1482,7 @@ impl Pallet { } /// Adds a project to the ProjectsToUpdate storage, so it can be updated at some later point in time. - pub fn add_to_update_store( - block_number: T::BlockNumber, - store: (&T::ProjectIdentifier, UpdateType), - ) { + pub fn add_to_update_store(block_number: T::BlockNumber, store: (&T::ProjectIdentifier, UpdateType)) { // Try to get the project into the earliest possible block to update. // There is a limit for how many projects can update each block, so we need to make sure we don't exceed that limit let mut block_number = block_number; @@ -1536,13 +1492,10 @@ impl Pallet { } } - pub fn remove_from_update_store( - project_id: &T::ProjectIdentifier, - ) -> Result<(), DispatchError> { + pub fn remove_from_update_store(project_id: &T::ProjectIdentifier) -> Result<(), DispatchError> { let (block_position, project_index) = ProjectsToUpdate::::iter() .find_map(|(block, project_vec)| { - let project_index = - project_vec.iter().position(|(id, _update_type)| id == project_id)?; + let project_index = project_vec.iter().position(|(id, _update_type)| id == project_id)?; Some((block, project_index)) }) .ok_or(Error::::ProjectNotInUpdateStore)?; @@ -1557,13 +1510,15 @@ impl Pallet { /// Based on the amount of tokens and price to buy, a desired multiplier, and the type of investor the caller is, /// calculate the amount and vesting periods of bonded PLMC and reward CT tokens. pub fn calculate_vesting_periods( - _caller: T::AccountId, - multiplier: MultiplierOf, - token_amount: BalanceOf, - token_price: BalanceOf, + _caller: T::AccountId, multiplier: MultiplierOf, token_amount: BalanceOf, token_price: BalanceOf, decimals: u8, - ) -> Result<(Vesting>, Vesting>), ()> - { + ) -> Result< + ( + Vesting>, + Vesting>, + ), + (), + > { let plmc_start: T::BlockNumber = 0u32.into(); let ct_start: T::BlockNumber = (T::MaxProjectsToUpdatePerBlock::get() * 7).into(); // TODO: Calculate real vesting periods based on multiplier and caller type @@ -1591,9 +1546,7 @@ impl Pallet { /// Calculates the price of contribution tokens for the Community and Remainder Rounds pub fn calculate_weighted_average_price( - project_id: T::ProjectIdentifier, - end_block: T::BlockNumber, - total_allocation_size: BalanceOf, + project_id: T::ProjectIdentifier, end_block: T::BlockNumber, total_allocation_size: BalanceOf, ) -> Result<(), DispatchError> { // Get all the bids that were made before the end of the candle let mut bids = AuctionsInfo::::iter_values().flatten().collect::>(); @@ -1611,7 +1564,7 @@ impl Pallet { if bid.when > end_block { bid.status = BidStatus::Rejected(RejectionReason::AfterCandleEnd); // TODO: PLMC-147. Unlock funds. We can do this inside the "on_idle" hook, and change the `status` of the `Bid` to "Unreserved" - return bid + return bid; } let buyable_amount = total_allocation_size.saturating_sub(bid_amount_sum); if buyable_amount == 0_u32.into() { @@ -1623,8 +1576,7 @@ impl Pallet { } else { bid_amount_sum.saturating_accrue(buyable_amount); bid_value_sum.saturating_accrue(buyable_amount * bid.price); - bid.status = - BidStatus::PartiallyAccepted(buyable_amount, RejectionReason::NoTokensLeft) + bid.status = BidStatus::PartiallyAccepted(buyable_amount, RejectionReason::NoTokensLeft) // TODO: PLMC-147. Refund remaining amount } @@ -1672,10 +1624,12 @@ impl Pallet { // TODO: PLMC-150. collecting due to previous mut borrow, find a way to not collect and borrow bid on filter_map .into_iter() .filter_map(|bid| match bid.status { - BidStatus::Accepted => - Some(Perbill::from_rational(bid.amount * bid.price, bid_value_sum) * bid.price), - BidStatus::PartiallyAccepted(amount, _) => - Some(Perbill::from_rational(amount * bid.price, bid_value_sum) * bid.price), + BidStatus::Accepted => { + Some(Perbill::from_rational(bid.amount * bid.price, bid_value_sum) * bid.price) + }, + BidStatus::PartiallyAccepted(amount, _) => { + Some(Perbill::from_rational(amount * bid.price, bid_value_sum) * bid.price) + }, _ => None, }) .reduce(|a, b| a.saturating_add(b)) @@ -1685,8 +1639,7 @@ impl Pallet { ProjectsDetails::::mutate(project_id, |maybe_info| -> Result<(), DispatchError> { if let Some(info) = maybe_info { info.weighted_average_price = Some(weighted_token_price); - info.remaining_contribution_tokens = - info.remaining_contribution_tokens.saturating_sub(bid_amount_sum); + info.remaining_contribution_tokens = info.remaining_contribution_tokens.saturating_sub(bid_amount_sum); Ok(()) } else { Err(Error::::ProjectNotFound.into()) @@ -1697,8 +1650,7 @@ impl Pallet { } pub fn select_random_block( - candle_starting_block: T::BlockNumber, - candle_ending_block: T::BlockNumber, + candle_starting_block: T::BlockNumber, candle_ending_block: T::BlockNumber, ) -> T::BlockNumber { let nonce = Self::get_and_increment_nonce(); let (random_value, _known_since) = T::Randomness::random(&nonce); @@ -1719,8 +1671,7 @@ impl Pallet { // This function is kept separate from the `do_claim_contribution_tokens` for easier testing the logic #[inline(always)] pub fn calculate_claimable_tokens( - contribution_amount: BalanceOf, - weighted_average_price: BalanceOf, + contribution_amount: BalanceOf, weighted_average_price: BalanceOf, ) -> FixedU128 { FixedU128::saturating_from_rational(contribution_amount, weighted_average_price) } diff --git a/pallets/funding/src/lib.rs b/pallets/funding/src/lib.rs index 1729100ea..641dd3a33 100644 --- a/pallets/funding/src/lib.rs +++ b/pallets/funding/src/lib.rs @@ -197,6 +197,9 @@ pub mod tests; mod benchmarking; pub mod traits; +#[allow(unused_imports)] +use polimec_traits::{MemberRole, PolimecMembers}; + pub use crate::weights::WeightInfo; use frame_support::{ pallet_prelude::ValueQuery, @@ -218,11 +221,8 @@ use sp_std::prelude::*; type BalanceOf = ::Balance; -type ProjectMetadataOf = ProjectMetadata< - BoundedVec::StringLimit>, - BalanceOf, - ::Hash, ->; +type ProjectMetadataOf = + ProjectMetadata::StringLimit>, BalanceOf, ::Hash>; type ProjectDetailsOf = ProjectDetails<::BlockNumber, BalanceOf>; @@ -396,20 +396,17 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn projects)] /// A StorageMap containing the primary project information of projects - pub type ProjectsMetadata = - StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, ProjectMetadataOf>; + pub type ProjectsMetadata = StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, ProjectMetadataOf>; #[pallet::storage] #[pallet::getter(fn project_issuer)] /// StorageMap to get the issuer of a project - pub type ProjectsIssuers = - StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, T::AccountId>; + pub type ProjectsIssuers = StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, T::AccountId>; #[pallet::storage] #[pallet::getter(fn project_info)] /// StorageMap containing additional information for the projects, relevant for correctness of the protocol - pub type ProjectsDetails = - StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, ProjectDetailsOf>; + pub type ProjectsDetails = StorageMap<_, Blake2_128Concat, T::ProjectIdentifier, ProjectDetailsOf>; #[pallet::storage] #[pallet::getter(fn projects_to_update)] @@ -500,13 +497,23 @@ pub mod pallet { end_block: T::BlockNumber, }, /// The auction round of a project started. - EnglishAuctionStarted { project_id: T::ProjectIdentifier, when: T::BlockNumber }, + EnglishAuctionStarted { + project_id: T::ProjectIdentifier, + when: T::BlockNumber, + }, /// The candle auction part of the auction started for a project - CandleAuctionStarted { project_id: T::ProjectIdentifier, when: T::BlockNumber }, + CandleAuctionStarted { + project_id: T::ProjectIdentifier, + when: T::BlockNumber, + }, /// The auction round of a project ended. AuctionEnded { project_id: T::ProjectIdentifier }, /// A `bonder` bonded an `amount` of PLMC for `project_id`. - FundsBonded { project_id: T::ProjectIdentifier, amount: BalanceOf, bonder: T::AccountId }, + FundsBonded { + project_id: T::ProjectIdentifier, + amount: BalanceOf, + bonder: T::AccountId, + }, /// Someone paid for the release of a user's PLMC bond for a project. BondReleased { project_id: T::ProjectIdentifier, @@ -535,7 +542,10 @@ pub mod pallet { /// A project has now finished funding FundingEnded { project_id: T::ProjectIdentifier }, /// Something was not properly initialized. Most likely due to dev error manually calling do_* functions or updating storage - TransitionError { project_id: T::ProjectIdentifier, error: DispatchError }, + TransitionError { + project_id: T::ProjectIdentifier, + error: DispatchError, + }, /// Something terribly wrong happened where the bond could not be unbonded. Most likely a programming error FailedEvaluationUnbondFailed { error: DispatchError }, /// Contribution tokens were minted to a user @@ -668,9 +678,7 @@ pub mod pallet { /// Change the metadata hash of a project #[pallet::weight(T::WeightInfo::edit_metadata())] pub fn edit_metadata( - origin: OriginFor, - project_id: T::ProjectIdParameter, - project_metadata_hash: T::Hash, + origin: OriginFor, project_id: T::ProjectIdParameter, project_metadata_hash: T::Hash, ) -> DispatchResult { let issuer = ensure_signed(origin)?; let project_id = project_id.into(); @@ -680,10 +688,7 @@ pub mod pallet { /// Starts the evaluation round of a project. It needs to be called by the project issuer. #[pallet::weight(T::WeightInfo::start_evaluation())] - pub fn start_evaluation( - origin: OriginFor, - project_id: T::ProjectIdParameter, - ) -> DispatchResult { + pub fn start_evaluation(origin: OriginFor, project_id: T::ProjectIdParameter) -> DispatchResult { let issuer = ensure_signed(origin)?; let project_id = project_id.into(); @@ -693,7 +698,10 @@ pub mod pallet { // Error::::NotAuthorized // ); - ensure!(ProjectsIssuers::::get(project_id) == Some(issuer), Error::::NotAllowed); + ensure!( + ProjectsIssuers::::get(project_id) == Some(issuer), + Error::::NotAllowed + ); Self::do_evaluation_start(project_id) } @@ -702,10 +710,7 @@ pub mod pallet { /// institutional user can set bids for a token_amount/token_price pair. /// Any bids from this point until the candle_auction starts, will be considered as valid. #[pallet::weight(T::WeightInfo::start_auction())] - pub fn start_auction( - origin: OriginFor, - project_id: T::ProjectIdParameter, - ) -> DispatchResult { + pub fn start_auction(origin: OriginFor, project_id: T::ProjectIdParameter) -> DispatchResult { let issuer = ensure_signed(origin)?; let project_id = project_id.into(); @@ -715,7 +720,10 @@ pub mod pallet { // Error::::NotAuthorized // ); - ensure!(ProjectsIssuers::::get(project_id) == Some(issuer), Error::::NotAllowed); + ensure!( + ProjectsIssuers::::get(project_id) == Some(issuer), + Error::::NotAllowed + ); Self::do_english_auction(project_id) } @@ -723,9 +731,7 @@ pub mod pallet { /// Bond PLMC for a project in the evaluation stage #[pallet::weight(T::WeightInfo::bond())] pub fn bond_evaluation( - origin: OriginFor, - project_id: T::ProjectIdParameter, - #[pallet::compact] amount: BalanceOf, + origin: OriginFor, project_id: T::ProjectIdParameter, #[pallet::compact] amount: BalanceOf, ) -> DispatchResult { let from = ensure_signed(origin)?; let project_id = project_id.into(); @@ -735,13 +741,10 @@ pub mod pallet { /// Release the bonded PLMC for an evaluator if the project assigned to it is in the EvaluationFailed phase #[pallet::weight(T::WeightInfo::failed_evaluation_unbond_for())] pub fn failed_evaluation_unbond_for( - origin: OriginFor, - project_id: T::ProjectIdParameter, - bonder: T::AccountId, + origin: OriginFor, project_id: T::ProjectIdParameter, bonder: T::AccountId, ) -> DispatchResult { let releaser = ensure_signed(origin)?; - let bond = EvaluationBonds::::get(project_id.into(), bonder) - .ok_or(Error::::BondNotFound)?; + let bond = EvaluationBonds::::get(project_id.into(), bonder).ok_or(Error::::BondNotFound)?; Self::do_failed_evaluation_unbond_for(bond, releaser) } @@ -770,9 +773,7 @@ pub mod pallet { /// Buy tokens in the Community or Remainder round at the price set in the Auction Round #[pallet::weight(T::WeightInfo::contribute())] pub fn contribute( - origin: OriginFor, - project_id: T::ProjectIdParameter, - #[pallet::compact] amount: BalanceOf, + origin: OriginFor, project_id: T::ProjectIdParameter, #[pallet::compact] amount: BalanceOf, multiplier: Option>, ) -> DispatchResult { let contributor = ensure_signed(origin)?; @@ -783,9 +784,7 @@ pub mod pallet { /// Unbond some plmc from a contribution, after a step in the vesting period has passed. pub fn vested_plmc_bid_unbond_for( - origin: OriginFor, - project_id: T::ProjectIdParameter, - bidder: T::AccountId, + origin: OriginFor, project_id: T::ProjectIdParameter, bidder: T::AccountId, ) -> DispatchResult { // TODO: PLMC-157. Manage the fact that the CTs may not be claimed by those entitled let claimer = ensure_signed(origin)?; @@ -797,9 +796,7 @@ pub mod pallet { // TODO: PLMC-157. Manage the fact that the CTs may not be claimed by those entitled /// Mint contribution tokens after a step in the vesting period for a successful bid. pub fn vested_contribution_token_bid_mint_for( - origin: OriginFor, - project_id: T::ProjectIdParameter, - bidder: T::AccountId, + origin: OriginFor, project_id: T::ProjectIdParameter, bidder: T::AccountId, ) -> DispatchResult { let claimer = ensure_signed(origin)?; let project_id = project_id.into(); @@ -810,9 +807,7 @@ pub mod pallet { // TODO: PLMC-157. Manage the fact that the CTs may not be claimed by those entitled /// Unbond some plmc from a contribution, after a step in the vesting period has passed. pub fn vested_plmc_purchase_unbond_for( - origin: OriginFor, - project_id: T::ProjectIdParameter, - purchaser: T::AccountId, + origin: OriginFor, project_id: T::ProjectIdParameter, purchaser: T::AccountId, ) -> DispatchResult { let claimer = ensure_signed(origin)?; let project_id = project_id.into(); @@ -823,9 +818,7 @@ pub mod pallet { // TODO: PLMC-157. Manage the fact that the CTs may not be claimed by those entitled /// Mint contribution tokens after a step in the vesting period for a contribution. pub fn vested_contribution_token_purchase_mint_for( - origin: OriginFor, - project_id: T::ProjectIdParameter, - purchaser: T::AccountId, + origin: OriginFor, project_id: T::ProjectIdParameter, purchaser: T::AccountId, ) -> DispatchResult { let claimer = ensure_signed(origin)?; let project_id = project_id.into(); @@ -843,33 +836,33 @@ pub mod pallet { // EvaluationRound -> AuctionInitializePeriod | EvaluationFailed UpdateType::EvaluationEnd => { unwrap_result_or_skip!(Self::do_evaluation_end(project_id), project_id); - }, + } // AuctionInitializePeriod -> AuctionRound(AuctionPhase::English) // Only if it wasn't first handled by user extrinsic UpdateType::EnglishAuctionStart => { unwrap_result_or_skip!(Self::do_english_auction(project_id), project_id); - }, + } // AuctionRound(AuctionPhase::English) -> AuctionRound(AuctionPhase::Candle) UpdateType::CandleAuctionStart => { unwrap_result_or_skip!(Self::do_candle_auction(project_id), project_id); - }, + } // AuctionRound(AuctionPhase::Candle) -> CommunityRound UpdateType::CommunityFundingStart => { unwrap_result_or_skip!(Self::do_community_funding(project_id), project_id); - }, + } // CommunityRound -> RemainderRound UpdateType::RemainderFundingStart => { unwrap_result_or_skip!(Self::do_remainder_funding(project_id), project_id) - }, + } // CommunityRound || RemainderRound -> FundingEnded UpdateType::FundingEnd => { unwrap_result_or_skip!(Self::do_end_funding(project_id), project_id) - }, + } } } // TODO: PLMC-127. Set a proper weight @@ -877,8 +870,7 @@ pub mod pallet { } fn on_idle(_now: T::BlockNumber, max_weight: Weight) -> Weight { - let pallet_account: T::AccountId = - ::PalletId::get().into_account_truncating(); + let pallet_account: T::AccountId = ::PalletId::get().into_account_truncating(); let mut remaining_weight = max_weight; @@ -941,8 +933,14 @@ pub mod pallet { let project: ProjectMetadataOf = ProjectMetadata { total_allocation_size: 1_000_000u64.into(), minimum_price: 1__0_000_000_000_u64.into(), - ticket_size: TicketSize { minimum: Some(1u8.into()), maximum: None }, - participants_size: ParticipantsSize { minimum: Some(2), maximum: None }, + ticket_size: TicketSize { + minimum: Some(1u8.into()), + maximum: None, + }, + participants_size: ParticipantsSize { + minimum: Some(2), + maximum: None, + }, offchain_information_hash: Some(metadata_hash), ..Default::default() }; @@ -964,8 +962,8 @@ pub mod local_macros { project_id: $project_id, error: Error::::FieldIsNone.into(), }); - continue - }, + continue; + } } }; } @@ -981,8 +979,8 @@ pub mod local_macros { project_id: $project_id, error: err, }); - continue - }, + continue; + } } }; } diff --git a/pallets/funding/src/mock.rs b/pallets/funding/src/mock.rs index 6ec9516ee..602e372a3 100644 --- a/pallets/funding/src/mock.rs +++ b/pallets/funding/src/mock.rs @@ -176,12 +176,17 @@ impl pallet_funding::Config for TestRuntime { // Build genesis storage according to the mock runtime. // TODO: PLMC-161. Add some mocks projects at Genesis to simplify the tests pub fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - - GenesisConfig { balances: BalancesConfig { balances: vec![] }, ..Default::default() } - .assimilate_storage(&mut t) + let mut t = frame_system::GenesisConfig::default() + .build_storage::() .unwrap(); + GenesisConfig { + balances: BalancesConfig { balances: vec![] }, + ..Default::default() + } + .assimilate_storage(&mut t) + .unwrap(); + let mut ext = sp_io::TestExternalities::new(t); // In order to emit events the block number must be more than 0 ext.execute_with(|| System::set_block_number(1)); diff --git a/pallets/funding/src/tests.rs b/pallets/funding/src/tests.rs index a62e9b98d..e9567709d 100644 --- a/pallets/funding/src/tests.rs +++ b/pallets/funding/src/tests.rs @@ -38,10 +38,13 @@ type UserToBalance = Vec<(mock::AccountId, BalanceOf)>; // User -> token_amount, price_per_token, multiplier type UserToBid = Vec<( AccountId, - (BalanceOf, BalanceOf, Option>), + ( + BalanceOf, + BalanceOf, + Option>, + ), )>; -type UserToContribution = - Vec<(AccountId, (BalanceOf, Option>))>; +type UserToContribution = Vec<(AccountId, (BalanceOf, Option>))>; const ISSUER: AccountId = 1; const EVALUATOR_1: AccountId = 2; @@ -72,10 +75,7 @@ const METADATA: &str = r#" // } /// Remove accounts from fundings_1 that are not in fundings_2 -fn remove_missing_accounts_from_fundings( - fundings_1: UserToBalance, - fundings_2: UserToBalance, -) -> UserToBalance { +fn remove_missing_accounts_from_fundings(fundings_1: UserToBalance, fundings_2: UserToBalance) -> UserToBalance { let mut fundings_1 = fundings_1; let fundings_2 = fundings_2; fundings_1.retain(|(account, _)| { @@ -93,19 +93,18 @@ trait ProjectInstance { fn get_creator(&self) -> AccountId; fn get_project_id(&self) -> ProjectIdOf; fn get_project(&self) -> ProjectMetadataOf { - self.get_test_environment().ext_env.borrow_mut().execute_with(|| { - FundingModule::projects(self.get_project_id()).expect("Project info should exist") - }) + self.get_test_environment() + .ext_env + .borrow_mut() + .execute_with(|| FundingModule::projects(self.get_project_id()).expect("Project info should exist")) } fn get_project_info(&self) -> ProjectDetailsOf { - self.get_test_environment().ext_env.borrow_mut().execute_with(|| { - FundingModule::project_info(self.get_project_id()).expect("Project info should exist") - }) + self.get_test_environment() + .ext_env + .borrow_mut() + .execute_with(|| FundingModule::project_info(self.get_project_id()).expect("Project info should exist")) } - fn do_project_assertions( - &self, - project_assertions: impl Fn(ProjectIdOf, &TestEnvironment) -> (), - ) { + fn do_project_assertions(&self, project_assertions: impl Fn(ProjectIdOf, &TestEnvironment) -> ()) { let project_id = self.get_project_id(); let test_env = self.get_test_environment(); project_assertions(project_id, test_env); @@ -120,12 +119,13 @@ pub struct TestEnvironment { } impl TestEnvironment { pub fn new() -> Self { - Self { ext_env: RefCell::new(new_test_ext()), nonce: RefCell::new(0u64) } + Self { + ext_env: RefCell::new(new_test_ext()), + nonce: RefCell::new(0u64), + } } fn create_project( - &self, - creator: mock::AccountId, - project: ProjectMetadataOf, + &self, creator: mock::AccountId, project: ProjectMetadataOf, ) -> Result { // Create project in the externalities environment of this struct instance self.ext_env @@ -137,8 +137,7 @@ impl TestEnvironment { frame_system::Pallet::::events() .iter() .filter_map(|event| match event.event { - RuntimeEvent::FundingModule(crate::Event::Created { project_id }) => - Some(project_id), + RuntimeEvent::FundingModule(crate::Event::Created { project_id }) => Some(project_id), _ => None, }) .last() @@ -146,15 +145,18 @@ impl TestEnvironment { .clone() }); - Ok(CreatedProject { test_env: self, creator, project_id }) + Ok(CreatedProject { + test_env: self, + creator, + project_id, + }) } /// Returns the *free* fundings of the Users. #[allow(dead_code)] fn get_free_fundings(&self) -> UserToBalance { self.ext_env.borrow_mut().execute_with(|| { let mut fundings = UserToBalance::new(); - let user_keys: Vec = - frame_system::Account::::iter_keys().collect(); + let user_keys: Vec = frame_system::Account::::iter_keys().collect(); for user in user_keys { let funding = Balances::free_balance(&user); fundings.push((user, funding)); @@ -167,8 +169,7 @@ impl TestEnvironment { fn get_reserved_fundings(&self, reserve_type: BondType) -> UserToBalance { self.ext_env.borrow_mut().execute_with(|| { let mut fundings = UserToBalance::new(); - let user_keys: Vec = - frame_system::Account::::iter_keys().collect(); + let user_keys: Vec = frame_system::Account::::iter_keys().collect(); for user in user_keys { let funding = Balances::reserved_balance_named(&reserve_type, &user); fundings.push((user, funding)); @@ -190,10 +191,7 @@ impl TestEnvironment { self.ext_env.borrow_mut().execute_with(|| { for _block in 0..amount { >::on_finalize(System::block_number()); - >::on_idle( - System::block_number(), - Weight::MAX, - ); + >::on_idle(System::block_number(), Weight::MAX); System::set_block_number(System::block_number() + 1); >::on_initialize(System::block_number()); } @@ -247,13 +245,11 @@ impl<'a> CreatedProject<'a> { } // Move to next project phase - fn start_evaluation( - self, - caller: mock::AccountId, - ) -> Result, DispatchError> { - self.test_env.ext_env.borrow_mut().execute_with(|| { - FundingModule::start_evaluation(RuntimeOrigin::signed(caller), self.project_id) - })?; + fn start_evaluation(self, caller: mock::AccountId) -> Result, DispatchError> { + self.test_env + .ext_env + .borrow_mut() + .execute_with(|| FundingModule::start_evaluation(RuntimeOrigin::signed(caller), self.project_id))?; Ok(EvaluatingProject { test_env: self.test_env, @@ -293,9 +289,10 @@ impl<'a> EvaluatingProject<'a> { fn bond_for_users(&self, bonds: UserToBalance) -> Result<(), DispatchError> { let project_id = self.get_project_id(); for (account, amount) in bonds { - self.test_env.ext_env.borrow_mut().execute_with(|| { - FundingModule::bond_evaluation(RuntimeOrigin::signed(account), project_id, amount) - })?; + self.test_env + .ext_env + .borrow_mut() + .execute_with(|| FundingModule::bond_evaluation(RuntimeOrigin::signed(account), project_id, amount))?; } Ok(()) } @@ -393,14 +390,16 @@ impl<'a> AuctioningProject<'a> { .english_auction .end() .expect("English end point should exist"); - self.test_env.advance_time(english_end - self.test_env.current_block() + 1); + self.test_env + .advance_time(english_end - self.test_env.current_block() + 1); let candle_end = self .get_project_info() .phase_transition_points .candle_auction .end() .expect("Candle end point should exist"); - self.test_env.advance_time(candle_end - self.test_env.current_block() + 1); + self.test_env + .advance_time(candle_end - self.test_env.current_block() + 1); assert_eq!(self.get_project_info().project_status, ProjectStatus::CommunityRound); CommunityFundingProject { test_env: self.test_env, @@ -453,12 +452,7 @@ impl<'a> CommunityFundingProject<'a> { let project_id = self.get_project_id(); for (account, (ct_amount, multiplier)) in buys { self.test_env.ext_env.borrow_mut().execute_with(|| { - FundingModule::contribute( - RuntimeOrigin::signed(account), - project_id, - ct_amount, - multiplier, - ) + FundingModule::contribute(RuntimeOrigin::signed(account), project_id, ct_amount, multiplier) })?; } Ok(()) @@ -504,12 +498,7 @@ impl<'a> RemainderFundingProject<'a> { let project_id = self.get_project_id(); for (account, (ct_amount, multiplier)) in buys { self.test_env.ext_env.borrow_mut().execute_with(|| { - FundingModule::contribute( - RuntimeOrigin::signed(account), - project_id, - ct_amount, - multiplier, - ) + FundingModule::contribute(RuntimeOrigin::signed(account), project_id, ct_amount, multiplier) })?; } Ok(()) @@ -592,18 +581,21 @@ mod defaults { use super::*; use crate::traits::BondingRequirementCalculation; - pub fn default_project( - nonce: u64, - ) -> ProjectMetadata>, u128, sp_core::H256> { - let bounded_name = - BoundedVec::try_from("Contribution Token TEST".as_bytes().to_vec()).unwrap(); + pub fn default_project(nonce: u64) -> ProjectMetadata>, u128, sp_core::H256> { + let bounded_name = BoundedVec::try_from("Contribution Token TEST".as_bytes().to_vec()).unwrap(); let bounded_symbol = BoundedVec::try_from("CTEST".as_bytes().to_vec()).unwrap(); let metadata_hash = hashed(format!("{}-{}", METADATA, nonce)); ProjectMetadata { total_allocation_size: 1_000_000, minimum_price: 1 * PLMC, - ticket_size: TicketSize { minimum: Some(1), maximum: None }, - participants_size: ParticipantsSize { minimum: Some(2), maximum: None }, + ticket_size: TicketSize { + minimum: Some(1), + maximum: None, + }, + participants_size: ParticipantsSize { + minimum: Some(2), + maximum: None, + }, funding_thresholds: Default::default(), conversion_rate: 0, participation_currencies: Default::default(), @@ -695,9 +687,7 @@ mod defaults { .collect() } - pub fn default_community_buys_currency_reserved( - price: BalanceOf, - ) -> UserToBalance { + pub fn default_community_buys_currency_reserved(price: BalanceOf) -> UserToBalance { default_community_buys() .into_iter() .map(|(user, (amount, _multiplier))| (user, (amount * price))) @@ -718,46 +708,30 @@ mod defaults { // vec![(BUYER_1, (100 * PLMC)), (BUYER_2, (6000 * PLMC))] // } - pub fn default_creation_assertions( - project_id: ProjectIdOf, - test_env: &TestEnvironment, - ) { + pub fn default_creation_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = - FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::Application); }); } - pub fn default_evaluation_start_assertions( - project_id: ProjectIdOf, - test_env: &TestEnvironment, - ) { + pub fn default_evaluation_start_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = - FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::EvaluationRound); }); } - pub fn default_evaluation_end_assertions( - project_id: ProjectIdOf, - test_env: &TestEnvironment, - ) { + pub fn default_evaluation_end_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = - FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::AuctionInitializePeriod); }); } - pub fn default_auction_start_assertions( - project_id: ProjectIdOf, - test_env: &TestEnvironment, - ) { + pub fn default_auction_start_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = - FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!( project_info.project_status, ProjectStatus::AuctionRound(AuctionPhase::English) @@ -765,13 +739,9 @@ mod defaults { }); } - pub fn default_auction_end_assertions( - _project_id: ProjectIdOf, - test_env: &TestEnvironment, - ) { + pub fn default_auction_end_assertions(_project_id: ProjectIdOf, test_env: &TestEnvironment) { // Check that enough PLMC is bonded - test_env - .do_reserved_funds_assertions(default_auction_bids_plmc_bondings(), BondType::Bidding); + test_env.do_reserved_funds_assertions(default_auction_bids_plmc_bondings(), BondType::Bidding); // Check that the bidding currency is reserved test_env.ext_env.borrow_mut().execute_with(|| { @@ -792,8 +762,7 @@ mod defaults { // Check that free funds were reduced let mut free_funds = default_fundings(); // Remove accounts that didnt bond from free_funds - free_funds = - remove_missing_accounts_from_fundings(free_funds, default_auction_bids_plmc_bondings()); + free_funds = remove_missing_accounts_from_fundings(free_funds, default_auction_bids_plmc_bondings()); // Subtract plmc bonded bidding funds free_funds = free_funds .iter() @@ -817,8 +786,7 @@ mod defaults { } pub fn default_community_funding_start_assertions( - project_id: ProjectIdOf, - test_env: &TestEnvironment, + project_id: ProjectIdOf, test_env: &TestEnvironment, ) { // Bids that reserved bidding currency, should have that drained from their account on community round, and transfered to the pallet account test_env.ext_env.borrow_mut().execute_with(|| { @@ -831,18 +799,15 @@ mod defaults { }); // PLMC should still be reserved, since its only a bond - test_env - .do_reserved_funds_assertions(default_auction_bids_plmc_bondings(), BondType::Bidding); + test_env.do_reserved_funds_assertions(default_auction_bids_plmc_bondings(), BondType::Bidding); // Check for correct project information test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = - FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::CommunityRound); // Check correct weighted_average_price - let token_price = - project_info.weighted_average_price.expect("Token price should exist"); + let token_price = project_info.weighted_average_price.expect("Token price should exist"); assert_eq!( token_price, default_token_average_price(), @@ -864,8 +829,7 @@ mod defaults { // Check status of bids test_env.ext_env.borrow_mut().execute_with(|| { - let project_bids = crate::pallet::AuctionsInfo::::iter_prefix(project_id) - .collect::>(); + let project_bids = crate::pallet::AuctionsInfo::::iter_prefix(project_id).collect::>(); let project_info = FundingModule::project_info(project_id).unwrap(); assert!( matches!(project_info.weighted_average_price, Some(_)), @@ -873,34 +837,26 @@ mod defaults { ); assert!(project_bids .into_iter() - .find(|(_bidder, bids)| { - !bids.iter().all(|bid| bid.status == BidStatus::Accepted) - }) + .find(|(_bidder, bids)| { !bids.iter().all(|bid| bid.status == BidStatus::Accepted) }) .is_none()); }); } - pub fn default_community_funding_end_assertions( - project_id: ProjectIdOf, - test_env: &TestEnvironment, - ) { + pub fn default_community_funding_end_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { let token_price = test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = - FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); project_info.weighted_average_price.expect("Token price should exist") }); let expected_plmc_bondings = default_community_plmc_bondings(token_price); let expected_buys = default_community_buys_currency_reserved(token_price); // Check that enough PLMC is bonded - test_env - .do_reserved_funds_assertions(expected_plmc_bondings.clone(), BondType::Contributing); + test_env.do_reserved_funds_assertions(expected_plmc_bondings.clone(), BondType::Contributing); // Check that free funds were reduced let mut free_funds = default_fundings(); // Remove accounts that didnt bond from free_funds - free_funds = - remove_missing_accounts_from_fundings(free_funds, expected_plmc_bondings.clone()); + free_funds = remove_missing_accounts_from_fundings(free_funds, expected_plmc_bondings.clone()); // Subtract the amount spent on the buys from the free funds free_funds = free_funds .iter() @@ -935,33 +891,25 @@ mod defaults { .sum(); assert_eq!( project.remaining_contribution_tokens, - default_project(0).total_allocation_size - - auction_bought_tokens - - community_bought_tokens, + default_project(0).total_allocation_size - auction_bought_tokens - community_bought_tokens, "Remaining CTs are incorrect" ); }); } pub fn default_remainder_funding_start_assertions( - project_id: ProjectIdOf, - test_env: &TestEnvironment, + project_id: ProjectIdOf, test_env: &TestEnvironment, ) { test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = - FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::RemainderRound); }); } - pub fn default_project_end_assertions( - project_id: ProjectIdOf, - test_env: &TestEnvironment, - ) { + pub fn default_project_end_assertions(project_id: ProjectIdOf, test_env: &TestEnvironment) { // Check that project status is correct test_env.ext_env.borrow_mut().execute_with(|| { - let project_info = - FundingModule::project_info(project_id).expect("Project info should exist"); + let project_info = FundingModule::project_info(project_id).expect("Project info should exist"); assert_eq!(project_info.project_status, ProjectStatus::FundingEnded); }); @@ -982,10 +930,10 @@ mod defaults { .sum(); assert_eq!( project.remaining_contribution_tokens, - default_project(0).total_allocation_size - - auction_bought_tokens - - community_bought_tokens - - remainder_bought_tokens, + default_project(0).total_allocation_size + - auction_bought_tokens + - community_bought_tokens + - remainder_bought_tokens, "Remaining CTs are incorrect" ); }); @@ -1013,7 +961,11 @@ mod helper_functions { FundingModule::remove_from_update_store(&69u32).unwrap(); let stored = crate::ProjectsToUpdate::::iter_values().collect::>(); - assert_eq!(stored[2], vec![], "Vector should be empty for that block after deletion"); + assert_eq!( + stored[2], + vec![], + "Vector should be empty for that block after deletion" + ); }); } } @@ -1075,8 +1027,14 @@ mod creation_round_failure { fn price_too_low() { let wrong_project: ProjectMetadataOf = ProjectMetadata { minimum_price: 0, - ticket_size: TicketSize { minimum: Some(1), maximum: None }, - participants_size: ParticipantsSize { minimum: Some(2), maximum: None }, + ticket_size: TicketSize { + minimum: Some(1), + maximum: None, + }, + participants_size: ParticipantsSize { + minimum: Some(2), + maximum: None, + }, offchain_information_hash: Some(hashed(METADATA)), ..Default::default() }; @@ -1092,8 +1050,14 @@ mod creation_round_failure { fn participants_size_error() { let wrong_project: ProjectMetadataOf = ProjectMetadata { minimum_price: 1, - ticket_size: TicketSize { minimum: Some(1), maximum: None }, - participants_size: ParticipantsSize { minimum: None, maximum: None }, + ticket_size: TicketSize { + minimum: Some(1), + maximum: None, + }, + participants_size: ParticipantsSize { + minimum: None, + maximum: None, + }, offchain_information_hash: Some(hashed(METADATA)), ..Default::default() }; @@ -1109,8 +1073,14 @@ mod creation_round_failure { fn ticket_size_error() { let wrong_project: ProjectMetadataOf = ProjectMetadata { minimum_price: 1, - ticket_size: TicketSize { minimum: None, maximum: None }, - participants_size: ParticipantsSize { minimum: Some(1), maximum: None }, + ticket_size: TicketSize { + minimum: None, + maximum: None, + }, + participants_size: ParticipantsSize { + minimum: Some(1), + maximum: None, + }, offchain_information_hash: Some(hashed(METADATA)), ..Default::default() }; @@ -1127,8 +1097,14 @@ mod creation_round_failure { fn multiple_field_error() { let wrong_project: ProjectMetadataOf = ProjectMetadata { minimum_price: 0, - ticket_size: TicketSize { minimum: None, maximum: None }, - participants_size: ParticipantsSize { minimum: None, maximum: None }, + ticket_size: TicketSize { + minimum: None, + maximum: None, + }, + participants_size: ParticipantsSize { + minimum: None, + maximum: None, + }, ..Default::default() }; let test_env = TestEnvironment::new(); @@ -1161,8 +1137,7 @@ mod evaluation_round_success { let evaluating_project = EvaluatingProject::new_default(&test_env); evaluating_project.bond_for_users(default_evaluation_bonds()).unwrap(); let project_info = evaluating_project.get_project_info(); - test_env - .advance_time(project_info.phase_transition_points.evaluation.end().unwrap() + 1u64); + test_env.advance_time(project_info.phase_transition_points.evaluation.end().unwrap() + 1u64); let end_block = evaluating_project .get_project_info() .phase_transition_points @@ -1192,15 +1167,13 @@ mod evaluation_round_failure { .expect("Bonding should work"); // Check that enough funds are reserved - test_env - .do_reserved_funds_assertions(default_failing_evaluation_bonds(), BondType::Evaluation); + test_env.do_reserved_funds_assertions(default_failing_evaluation_bonds(), BondType::Evaluation); // Check that free funds were reduced let mut free_funds = default_fundings(); // Remove accounts that didnt bond from free_funds - free_funds = - remove_missing_accounts_from_fundings(free_funds, default_failing_evaluation_bonds()); + free_funds = remove_missing_accounts_from_fundings(free_funds, default_failing_evaluation_bonds()); free_funds = free_funds .iter() .zip(default_failing_evaluation_bonds().iter()) @@ -1278,8 +1251,8 @@ mod auction_round_success { // do one candle bid for each block until the end of candle auction with a new user let mut bidding_account = 1000; let bid_info = default_auction_bids()[0].1; - let necessary_funding = (bid_info.0 * bid_info.1) + - (bid_info + let necessary_funding = (bid_info.0 * bid_info.1) + + (bid_info .2 .unwrap_or_default() .calculate_bonding_requirement(bid_info.0 * bid_info.1) @@ -1325,8 +1298,7 @@ mod auction_round_success { for (bidder, (_amount, _price, _multiplier)) in included_bids { test_env.ext_env.borrow_mut().execute_with(|| { let pid = auctioning_project.project_id; - let stored_bid = - FundingModule::auctions_info(pid, bidder).expect("Bid should exist"); + let stored_bid = FundingModule::auctions_info(pid, bidder).expect("Bid should exist"); assert!( matches!( stored_bid[0], @@ -1348,8 +1320,7 @@ mod auction_round_success { for (bidder, (_amount, _price, _multiplier)) in excluded_bids { test_env.ext_env.borrow_mut().execute_with(|| { let pid = auctioning_project.project_id; - let stored_bid = - FundingModule::auctions_info(pid, bidder).expect("Bid should exist"); + let stored_bid = FundingModule::auctions_info(pid, bidder).expect("Bid should exist"); assert!( matches!( stored_bid[0], @@ -1510,12 +1481,12 @@ mod community_round_success { let community_funding_project = CommunityFundingProject::new_default(&test_env); const BOB: AccountId = 808; test_env.ext_env.borrow_mut().execute_with(|| { - let bob_balance = - ::NativeCurrency::reserved_balance(&BOB); + let bob_balance = ::NativeCurrency::reserved_balance(&BOB); let stop = "here"; }); - let remaining_ct = - community_funding_project.get_project_info().remaining_contribution_tokens; + let remaining_ct = community_funding_project + .get_project_info() + .remaining_contribution_tokens; let ct_price = community_funding_project .get_project_info() .weighted_average_price @@ -1541,7 +1512,12 @@ mod community_round_success { .expect("The Buyer should be able to buy the exact amount of remaining CTs"); test_env.advance_time(2u64); // Check remaining CTs is 0 - assert_eq!(community_funding_project.get_project_info().remaining_contribution_tokens, 0); + assert_eq!( + community_funding_project + .get_project_info() + .remaining_contribution_tokens, + 0 + ); // Check project is in FundingEnded state assert_eq!( @@ -1558,8 +1534,10 @@ mod community_round_success { let community_funding_project = CommunityFundingProject::new_default(&test_env); const BOB: AccountId = 808; - let remaining_ct = - community_funding_project.get_project_info().remaining_contribution_tokens + 40; // Overbuy + let remaining_ct = community_funding_project + .get_project_info() + .remaining_contribution_tokens + + 40; // Overbuy let ct_price = community_funding_project .get_project_info() .weighted_average_price @@ -1578,7 +1556,12 @@ mod community_round_success { test_env.advance_time(2u64); // Check remaining CTs is 0 - assert_eq!(community_funding_project.get_project_info().remaining_contribution_tokens, 0); + assert_eq!( + community_funding_project + .get_project_info() + .remaining_contribution_tokens, + 0 + ); // Check project is in FundingEnded state assert_eq!( @@ -1593,21 +1576,20 @@ mod community_round_success { fn contribution_is_returned_on_limit_reached_same_mult_diff_ct() { let test_env = TestEnvironment::new(); let project = CommunityFundingProject::new_default(&test_env); - let buyer_2_initial_balance = test_env.ext_env.borrow_mut().execute_with(|| { - ::NativeCurrency::free_balance(&BUYER_2) - }); + let buyer_2_initial_balance = test_env + .ext_env + .borrow_mut() + .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); let project_details = project.get_project_info(); // Create a contribution that will reach the limit of contributions for a user-project let multiplier: Option> = None; let token_amount: BalanceOf = 1; let range = 0..::MaxContributionsPerUser::get(); - let contributions: UserToContribution = - range.map(|_| (BUYER_2, (token_amount, multiplier))).collect(); + let contributions: UserToContribution = range.map(|_| (BUYER_2, (token_amount, multiplier))).collect(); // Calculate currencies being transferred and bonded - let contribution_ticket_size = - token_amount * project_details.weighted_average_price.unwrap(); + let contribution_ticket_size = token_amount * project_details.weighted_average_price.unwrap(); let plmc_bond = multiplier .unwrap_or_default() .calculate_bonding_requirement(contribution_ticket_size) @@ -1617,24 +1599,24 @@ mod community_round_success { project.buy_for_retail_users(contributions.clone()).unwrap(); // Check that the right amount of PLMC is bonded, and funding currency is transferred - let buyer_2_post_buy_balance = test_env.ext_env.borrow_mut().execute_with(|| { - ::NativeCurrency::free_balance(&BUYER_2) - }); + let buyer_2_post_buy_balance = test_env + .ext_env + .borrow_mut() + .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); assert_eq!( buyer_2_post_buy_balance, - buyer_2_initial_balance - - (contribution_ticket_size + plmc_bond) * contributions.len() as u128 + buyer_2_initial_balance - (contribution_ticket_size + plmc_bond) * contributions.len() as u128 ); - let plmc_bond_stored = test_env.ext_env.borrow_mut().execute_with(|| { - crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap() - }); + let plmc_bond_stored = test_env + .ext_env + .borrow_mut() + .execute_with(|| crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap()); assert_eq!(plmc_bond_stored.amount, plmc_bond * contributions.len() as u128); // Make a new contribution with a PLMC bond bigger than the lowest bond already in store for that account let new_multiplier: Option> = None; let new_token_amount: BalanceOf = 2; - let new_contribution: UserToContribution = - vec![(BUYER_2, (new_token_amount, new_multiplier))]; + let new_contribution: UserToContribution = vec![(BUYER_2, (new_token_amount, new_multiplier))]; let new_ticket_size = new_token_amount * project_details.weighted_average_price.unwrap(); let new_plmc_bond = new_multiplier .unwrap_or_default() @@ -1644,17 +1626,18 @@ mod community_round_success { project.buy_for_retail_users(new_contribution.clone()).unwrap(); // Check that the previous contribution returned the reserved PLMC and the transferred funding currency - let buyer_2_post_return_balance = test_env.ext_env.borrow_mut().execute_with(|| { - ::NativeCurrency::free_balance(&BUYER_2) - }); + let buyer_2_post_return_balance = test_env + .ext_env + .borrow_mut() + .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); assert_eq!( buyer_2_post_return_balance, - buyer_2_post_buy_balance + (contribution_ticket_size + plmc_bond) - - (new_ticket_size + new_plmc_bond) + buyer_2_post_buy_balance + (contribution_ticket_size + plmc_bond) - (new_ticket_size + new_plmc_bond) ); - let new_plmc_bond_stored = test_env.ext_env.borrow_mut().execute_with(|| { - crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap() - }); + let new_plmc_bond_stored = test_env + .ext_env + .borrow_mut() + .execute_with(|| crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap()); assert_eq!( new_plmc_bond_stored.amount, plmc_bond_stored.amount - plmc_bond + new_plmc_bond @@ -1665,21 +1648,20 @@ mod community_round_success { fn contribution_is_returned_on_limit_reached_diff_mult_same_ct() { let test_env = TestEnvironment::new(); let project = CommunityFundingProject::new_default(&test_env); - let buyer_2_initial_balance = test_env.ext_env.borrow_mut().execute_with(|| { - ::NativeCurrency::free_balance(&BUYER_2) - }); + let buyer_2_initial_balance = test_env + .ext_env + .borrow_mut() + .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); let project_details = project.get_project_info(); // Create a contribution that will reach the limit of contributions for a user-project let multiplier: Option> = Some(Multiplier(2)); let token_amount: BalanceOf = 1; let range = 0..::MaxContributionsPerUser::get(); - let contributions: UserToContribution = - range.map(|_| (BUYER_2, (token_amount, multiplier))).collect(); + let contributions: UserToContribution = range.map(|_| (BUYER_2, (token_amount, multiplier))).collect(); // Calculate currencies being transferred and bonded - let contribution_ticket_size = - token_amount * project_details.weighted_average_price.unwrap(); + let contribution_ticket_size = token_amount * project_details.weighted_average_price.unwrap(); let plmc_bond = multiplier .unwrap_or_default() .calculate_bonding_requirement(contribution_ticket_size) @@ -1689,24 +1671,24 @@ mod community_round_success { project.buy_for_retail_users(contributions.clone()).unwrap(); // Check that the right amount of PLMC is bonded, and funding currency is transferred - let buyer_2_post_buy_balance = test_env.ext_env.borrow_mut().execute_with(|| { - ::NativeCurrency::free_balance(&BUYER_2) - }); + let buyer_2_post_buy_balance = test_env + .ext_env + .borrow_mut() + .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); assert_eq!( buyer_2_post_buy_balance, - buyer_2_initial_balance - - (contribution_ticket_size + plmc_bond) * contributions.len() as u128 + buyer_2_initial_balance - (contribution_ticket_size + plmc_bond) * contributions.len() as u128 ); - let plmc_bond_stored = test_env.ext_env.borrow_mut().execute_with(|| { - crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap() - }); + let plmc_bond_stored = test_env + .ext_env + .borrow_mut() + .execute_with(|| crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap()); assert_eq!(plmc_bond_stored.amount, plmc_bond * contributions.len() as u128); // Make a new contribution with a PLMC bond bigger than the lowest bond already in store for that account let new_multiplier: Option> = Some(Multiplier(1)); let new_token_amount: BalanceOf = 1; - let new_contribution: UserToContribution = - vec![(BUYER_2, (new_token_amount, new_multiplier))]; + let new_contribution: UserToContribution = vec![(BUYER_2, (new_token_amount, new_multiplier))]; let new_ticket_size = new_token_amount * project_details.weighted_average_price.unwrap(); let new_plmc_bond = new_multiplier .unwrap_or_default() @@ -1716,17 +1698,18 @@ mod community_round_success { project.buy_for_retail_users(new_contribution.clone()).unwrap(); // Check that the previous contribution returned the reserved PLMC and the transferred funding currency - let buyer_2_post_return_balance = test_env.ext_env.borrow_mut().execute_with(|| { - ::NativeCurrency::free_balance(&BUYER_2) - }); + let buyer_2_post_return_balance = test_env + .ext_env + .borrow_mut() + .execute_with(|| ::NativeCurrency::free_balance(&BUYER_2)); assert_eq!( buyer_2_post_return_balance, - buyer_2_post_buy_balance + (contribution_ticket_size + plmc_bond) - - (new_ticket_size + new_plmc_bond) + buyer_2_post_buy_balance + (contribution_ticket_size + plmc_bond) - (new_ticket_size + new_plmc_bond) ); - let new_plmc_bond_stored = test_env.ext_env.borrow_mut().execute_with(|| { - crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap() - }); + let new_plmc_bond_stored = test_env + .ext_env + .borrow_mut() + .execute_with(|| crate::ContributingBonds::::get(project.project_id, BUYER_2).unwrap()); assert_eq!( new_plmc_bond_stored.amount, plmc_bond_stored.amount - plmc_bond + new_plmc_bond @@ -1787,16 +1770,14 @@ mod purchased_vesting { .unwrap_or_default() .calculate_bonding_requirement(token_amount * price) .unwrap(); - let actual_bonded_plmc = - Balances::reserved_balance_named(&BondType::Contributing, &buyer); + let actual_bonded_plmc = Balances::reserved_balance_named(&BondType::Contributing, &buyer); assert_eq!(theoretical_bonded_plmc, actual_bonded_plmc); assert_ok!(FundingModule::vested_plmc_purchase_unbond_for( RuntimeOrigin::signed(buyer), project_id, buyer )); - let actual_bonded_plmc = - Balances::reserved_balance_named(&BondType::Contributing, &buyer); + let actual_bonded_plmc = Balances::reserved_balance_named(&BondType::Contributing, &buyer); assert_eq!(actual_bonded_plmc, 0u32.into()); } }); @@ -1845,16 +1826,14 @@ mod bids_vesting { .unwrap_or_default() .calculate_bonding_requirement(amount * price) .unwrap(); - let actual_bonded_plmc = - Balances::reserved_balance_named(&BondType::Bidding, &bidder); + let actual_bonded_plmc = Balances::reserved_balance_named(&BondType::Bidding, &bidder); assert_eq!(theoretical_bonded_plmc, actual_bonded_plmc); assert_ok!(FundingModule::vested_plmc_bid_unbond_for( RuntimeOrigin::signed(bidder), project_id, bidder )); - let actual_bonded_plmc = - Balances::reserved_balance_named(&BondType::Bidding, &bidder); + let actual_bonded_plmc = Balances::reserved_balance_named(&BondType::Bidding, &bidder); assert_eq!(actual_bonded_plmc, 0u32.into()); } }); diff --git a/pallets/funding/src/types.rs b/pallets/funding/src/types.rs index 4c376e256..a0fe9ab4a 100644 --- a/pallets/funding/src/types.rs +++ b/pallets/funding/src/types.rs @@ -18,7 +18,8 @@ //! Types for Funding pallet. -use crate::{traits::BondingRequirementCalculation, BalanceOf}; +use crate::traits::BondingRequirementCalculation; +use crate::BalanceOf; use frame_support::{pallet_prelude::*, traits::tokens::Balance as BalanceT}; use sp_arithmetic::traits::Saturating; use sp_runtime::traits::CheckedDiv; @@ -75,7 +76,7 @@ impl ProjectMetadata Result<(), ValidityError> { if self.minimum_price == Balance::zero() { - return Err(ValidityError::PriceTooLow) + return Err(ValidityError::PriceTooLow); } self.ticket_size.is_valid()?; self.participants_size.is_valid()?; @@ -93,13 +94,13 @@ impl TicketSize { fn is_valid(&self) -> Result<(), ValidityError> { if self.minimum.is_some() && self.maximum.is_some() { if self.minimum < self.maximum { - return Ok(()) + return Ok(()); } else { - return Err(ValidityError::TicketSizeError) + return Err(ValidityError::TicketSizeError); } } if self.minimum.is_some() || self.maximum.is_some() { - return Ok(()) + return Ok(()); } Err(ValidityError::TicketSizeError) @@ -115,18 +116,20 @@ pub struct ParticipantsSize { impl ParticipantsSize { fn is_valid(&self) -> Result<(), ValidityError> { match (self.minimum, self.maximum) { - (Some(min), Some(max)) => + (Some(min), Some(max)) => { if min < max && min > 0 && max > 0 { Ok(()) } else { Err(ValidityError::ParticipantsSizeError) - }, - (Some(elem), None) | (None, Some(elem)) => + } + } + (Some(elem), None) | (None, Some(elem)) => { if elem > 0 { Ok(()) } else { Err(ValidityError::ParticipantsSizeError) - }, + } + } (None, None) => Err(ValidityError::ParticipantsSizeError), } } @@ -198,15 +201,7 @@ impl BlockNumberPair { } #[derive(Default, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)] -pub struct BidInfo< - BidId, - ProjectId, - Balance: BalanceT, - AccountId, - BlockNumber, - PlmcVesting, - CTVesting, -> { +pub struct BidInfo { pub bid_id: BidId, pub project: ProjectId, #[codec(compact)] @@ -230,14 +225,8 @@ impl { pub fn new( - bid_id: BidId, - project: ProjectId, - amount: Balance, - price: Balance, - when: BlockNumber, - bidder: AccountId, - plmc_vesting_period: PlmcVesting, - ct_vesting_period: CTVesting, + bid_id: BidId, project: ProjectId, amount: Balance, price: Balance, when: BlockNumber, bidder: AccountId, + plmc_vesting_period: PlmcVesting, ct_vesting_period: CTVesting, ) -> Self { let ticket_size = amount.saturating_mul(price); Self { @@ -257,32 +246,16 @@ impl sp_std::cmp::Ord - for BidInfo +impl + sp_std::cmp::Ord for BidInfo { fn cmp(&self, other: &Self) -> sp_std::cmp::Ordering { self.price.cmp(&other.price) } } -impl< - BidId: Eq, - ProjectId: Eq, - Balance: BalanceT, - AccountId: Eq, - BlockNumber: Eq, - PlmcVesting: Eq, - CTVesting: Eq, - > sp_std::cmp::PartialOrd - for BidInfo +impl + sp_std::cmp::PartialOrd for BidInfo { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) @@ -350,19 +323,7 @@ pub enum RejectionReason { } /// Enum used to identify PLMC named reserves -#[derive( - Clone, - Encode, - Decode, - Eq, - PartialEq, - RuntimeDebug, - TypeInfo, - MaxEncodedLen, - Copy, - Ord, - PartialOrd, -)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen, Copy, Ord, PartialOrd)] pub enum BondType { Evaluation, Bidding, @@ -428,19 +389,7 @@ impl< } /// Tells on_initialize what to do with the project -#[derive( - Clone, - Encode, - Decode, - Eq, - PartialEq, - RuntimeDebug, - TypeInfo, - MaxEncodedLen, - Copy, - Ord, - PartialOrd, -)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen, Copy, Ord, PartialOrd)] pub enum UpdateType { EvaluationEnd, EnglishAuctionStart, @@ -450,19 +399,7 @@ pub enum UpdateType { FundingEnd, } -#[derive( - Clone, - Encode, - Decode, - Eq, - PartialEq, - RuntimeDebug, - TypeInfo, - MaxEncodedLen, - Copy, - Ord, - PartialOrd, -)] +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen, Copy, Ord, PartialOrd)] pub struct Multiplier(pub T::Balance); impl BondingRequirementCalculation for Multiplier { fn calculate_bonding_requirement(&self, ticket_size: BalanceOf) -> Result, ()> { diff --git a/pallets/sandbox/Cargo.toml b/pallets/sandbox/Cargo.toml index a0cc28996..2fbc67cbf 100644 --- a/pallets/sandbox/Cargo.toml +++ b/pallets/sandbox/Cargo.toml @@ -23,6 +23,7 @@ frame-system.workspace = true sp-std.workspace = true sp-runtime.workspace = true sp-arithmetic.workspace = true +polimec-traits.workspace = true parachains-common.workspace = true pallet-funding.workspace = true @@ -56,6 +57,7 @@ std = [ "sp-runtime/std", "pallet-assets/std", "pallet-balances/std", + "polimec-traits/std", "frame-benchmarking?/std", "parachains-common/std", ] diff --git a/pallets/sandbox/src/lib.rs b/pallets/sandbox/src/lib.rs index a5e2961ec..97ec6cbff 100644 --- a/pallets/sandbox/src/lib.rs +++ b/pallets/sandbox/src/lib.rs @@ -27,15 +27,13 @@ pub mod pallet { /// Buy tokens for a project in the community round if it achieved at least 500k USDT funding #[pallet::weight(0)] pub fn buy_if_popular( - origin: OriginFor, - project_id: ::ProjectIdParameter, + origin: OriginFor, project_id: ::ProjectIdParameter, amount: ::Balance, ) -> DispatchResult { let retail_user = ensure_signed(origin)?; let project_id: ::ProjectIdentifier = project_id.into(); // Check project is in the community round - let project_info = funding::Pallet::::project_info(project_id) - .ok_or(Error::::ProjectNotFound)?; + let project_info = funding::Pallet::::project_info(project_id).ok_or(Error::::ProjectNotFound)?; ensure!( project_info.project_status == funding::ProjectStatus::CommunityRound, "Project is not in the community round" @@ -43,12 +41,11 @@ pub mod pallet { // Calculate how much funding was done already let project_contributions: ::Balance = - funding::Contributions::::iter_prefix_values(project_id).flatten().fold( - 0u64.into(), - |total_tokens_bought, contribution| { + funding::Contributions::::iter_prefix_values(project_id) + .flatten() + .fold(0u64.into(), |total_tokens_bought, contribution| { total_tokens_bought + contribution.contribution_amount - }, - ); + }); ensure!( project_contributions >= 500_000_0_000_000_000u64.into(), diff --git a/pallets/sandbox/src/mock.rs b/pallets/sandbox/src/mock.rs index 278414096..f23912681 100644 --- a/pallets/sandbox/src/mock.rs +++ b/pallets/sandbox/src/mock.rs @@ -173,12 +173,17 @@ impl pallet_funding::Config for TestRuntime { // TODO: PLMC-161. Add some mocks projects at Genesis to simplify the tests #[allow(dead_code)] pub fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - - GenesisConfig { balances: BalancesConfig { balances: vec![] }, ..Default::default() } - .assimilate_storage(&mut t) + let mut t = frame_system::GenesisConfig::default() + .build_storage::() .unwrap(); + GenesisConfig { + balances: BalancesConfig { balances: vec![] }, + ..Default::default() + } + .assimilate_storage(&mut t) + .unwrap(); + let mut ext = sp_io::TestExternalities::new(t); // In order to emit events the block number must be more than 0 ext.execute_with(|| System::set_block_number(1)); diff --git a/pallets/sandbox/src/tests.rs b/pallets/sandbox/src/tests.rs index 52ee116a2..c6ef58158 100644 --- a/pallets/sandbox/src/tests.rs +++ b/pallets/sandbox/src/tests.rs @@ -43,12 +43,18 @@ fn test_buy_if_popular() { >::on_initialize(System::block_number()); } - assert_ok!(FundingModule::bid(RuntimeOrigin::signed(bidder), 0, 1000, 100 * PLMC, None)); + assert_ok!(FundingModule::bid( + RuntimeOrigin::signed(bidder), + 0, + 1000, + 100 * PLMC, + None + )); // advance time - for _block in 0..(::EnglishAuctionDuration::get() + - ::CandleAuctionDuration::get() + - 5) + for _block in 0..(::EnglishAuctionDuration::get() + + ::CandleAuctionDuration::get() + + 5) { >::on_finalize(System::block_number()); >::on_idle(System::block_number(), Weight::MAX); @@ -56,11 +62,21 @@ fn test_buy_if_popular() { >::on_initialize(System::block_number()); } - assert_ok!(FundingModule::contribute(RuntimeOrigin::signed(contributor), 0, 1, None)); + assert_ok!(FundingModule::contribute( + RuntimeOrigin::signed(contributor), + 0, + 1, + None + )); assert!(Sandbox::buy_if_popular(RuntimeOrigin::signed(4), 0, 1000).is_err()); - assert_ok!(FundingModule::contribute(RuntimeOrigin::signed(contributor), 0, 10000, None)); + assert_ok!(FundingModule::contribute( + RuntimeOrigin::signed(contributor), + 0, + 10000, + None + )); assert_ok!(Sandbox::buy_if_popular(RuntimeOrigin::signed(4), 0, 1000)); }); @@ -76,17 +92,21 @@ const METADATA: &str = r#" "usage_of_founds":"ipfs_url" }"#; -pub fn default_project( - nonce: u64, -) -> ProjectMetadata>, u128, sp_core::H256> { +pub fn default_project(nonce: u64) -> ProjectMetadata>, u128, sp_core::H256> { let bounded_name = BoundedVec::try_from("Contribution Token TEST".as_bytes().to_vec()).unwrap(); let bounded_symbol = BoundedVec::try_from("CTEST".as_bytes().to_vec()).unwrap(); let metadata_hash = hashed(format!("{}-{}", METADATA, nonce)); ProjectMetadata { total_allocation_size: 1_000_000, minimum_price: 1 * PLMC, - ticket_size: TicketSize { minimum: Some(1), maximum: None }, - participants_size: ParticipantsSize { minimum: Some(2), maximum: None }, + ticket_size: TicketSize { + minimum: Some(1), + maximum: None, + }, + participants_size: ParticipantsSize { + minimum: Some(2), + maximum: None, + }, funding_thresholds: Default::default(), conversion_rate: 0, participation_currencies: Default::default(), @@ -100,7 +120,9 @@ pub fn default_project( } pub fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + let mut t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); GenesisConfig { balances: BalancesConfig { diff --git a/polimec-skeleton/pallets/funding/src/mock.rs b/polimec-skeleton/pallets/funding/src/mock.rs index 9643e64aa..052274a20 100644 --- a/polimec-skeleton/pallets/funding/src/mock.rs +++ b/polimec-skeleton/pallets/funding/src/mock.rs @@ -90,6 +90,7 @@ parameter_types! { // https://github.com/paritytech/substrate/blob/069917b/frame/assets/src/lib.rs#L257L271 pub const MetadataDepositBase: Balance = free_deposit(); pub const MetadataDepositPerByte: Balance = free_deposit(); + pub const AssetsPalletId: PalletId = PalletId(*b"assetsid"); pub const ApprovalDeposit: Balance = EXISTENTIAL_DEPOSIT; } diff --git a/primitives/xcm/Cargo.toml b/primitives/xcm/Cargo.toml new file mode 100644 index 000000000..ab131c9e8 --- /dev/null +++ b/primitives/xcm/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "xcm-primitives" +version = "0.0.1" +edition = "2021" + +[dependencies] +sp-std.workspace = true + +xcm.workspace = true +xcm-executor.workspace = true + +[features] +default = [ "std" ] +std = [ + "sp-std/std", + "xcm/std", + "xcm-executor/std" +] diff --git a/primitives/xcm/src/lib.rs b/primitives/xcm/src/lib.rs new file mode 100644 index 000000000..e653cdc4d --- /dev/null +++ b/primitives/xcm/src/lib.rs @@ -0,0 +1,63 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use sp_std::{borrow::Borrow, marker::PhantomData}; +use xcm::latest::{AssetId::Concrete, Fungibility::Fungible, MultiAsset, MultiLocation}; +use xcm_executor::traits::{Convert, Error as MatchError, MatchesFungibles}; + +pub struct AsAssetMultiLocation(PhantomData<(AssetId, AssetIdInfoGetter)>); +impl xcm_executor::traits::Convert + for AsAssetMultiLocation +where + AssetId: Clone, + AssetIdInfoGetter: AssetMultiLocationGetter, +{ + fn convert_ref(asset_multi_location: impl Borrow) -> Result { + AssetIdInfoGetter::get_asset_id(asset_multi_location.borrow().clone()).ok_or(()) + } + + fn reverse_ref(asset_id: impl Borrow) -> Result { + AssetIdInfoGetter::get_asset_multi_location(asset_id.borrow().clone()).ok_or(()) + } +} + +pub trait AssetMultiLocationGetter { + fn get_asset_multi_location(asset_id: AssetId) -> Option; + fn get_asset_id(asset_multi_location: MultiLocation) -> Option; +} + +pub struct ConvertedRegisteredAssetId( + PhantomData<(AssetId, Balance, ConvertAssetId, ConvertBalance)>, +); +impl< + AssetId: Clone, + Balance: Clone, + ConvertAssetId: Convert, + ConvertBalance: Convert, + > MatchesFungibles for ConvertedRegisteredAssetId +{ + fn matches_fungibles(a: &MultiAsset) -> Result<(AssetId, Balance), MatchError> { + let (amount, id) = match (&a.fun, &a.id) { + (Fungible(ref amount), Concrete(ref id)) => (amount, id), + _ => return Err(MatchError::AssetNotFound), + }; + let what = ConvertAssetId::convert_ref(id).map_err(|_| MatchError::AssetNotFound)?; + let amount = ConvertBalance::convert_ref(amount).map_err(|_| MatchError::AmountToBalanceConversionFailed)?; + Ok((what, amount)) + } +} diff --git a/runtimes/base/Cargo.toml b/runtimes/base/Cargo.toml index 51e0309a4..73809d8af 100644 --- a/runtimes/base/Cargo.toml +++ b/runtimes/base/Cargo.toml @@ -14,7 +14,7 @@ version.workspace = true substrate-wasm-builder.workspace = true [dependencies] -parity-scale-codec = { version = "3.3.0", default-features = false, features = [ +parity-scale-codec = { version = "3.3.0", default-features = false, features = [ "derive", ] } hex-literal = { version = "0.3.4", optional = true } @@ -25,8 +25,6 @@ scale-info = { version = "2.3.1", default-features = false, features = [ smallvec = "1.10.0" # Local -pallet-parachain-staking.workspace = true -shared-configuration.workspace = true # Substrate frame-benchmarking = { workspace = true, optional = true } @@ -45,7 +43,6 @@ pallet-sudo.workspace = true pallet-timestamp.workspace = true pallet-transaction-payment.workspace = true pallet-transaction-payment-rpc-runtime-api.workspace = true -sp-arithmetic.workspace = true sp-api.workspace = true sp-block-builder.workspace = true sp-consensus-aura.workspace = true @@ -102,8 +99,6 @@ std = [ "frame-support/std", "frame-system-rpc-runtime-api/std", "frame-system/std", - "pallet-parachain-staking/std", - "parachains-common/std", "pallet-aura/std", "pallet-authorship/std", "pallet-balances/std", @@ -117,7 +112,6 @@ std = [ "parachain-info/std", "polkadot-parachain/std", "polkadot-runtime-common/std", - "sp-arithmetic/std", "sp-api/std", "sp-block-builder/std", "sp-consensus-aura/std", @@ -128,7 +122,6 @@ std = [ "sp-session/std", "sp-std/std", "sp-transaction-pool/std", - "shared-configuration/std", "sp-version/std", "xcm-builder/std", "xcm-executor/std", diff --git a/runtimes/base/src/currency.rs b/runtimes/base/src/currency.rs new file mode 100644 index 000000000..3d89c4f25 --- /dev/null +++ b/runtimes/base/src/currency.rs @@ -0,0 +1,14 @@ +use crate::Balance; + +/// One PLMC +pub const PLMC: Balance = 10u128.pow(10); +/// 0.001 PLMC +pub const MILLI_PLMC: Balance = 10u128.pow(7); +/// 0.000_001 PLMC +pub const MICRO_PLMC: Balance = 10u128.pow(4); + +pub const EXISTENTIAL_DEPOSIT: Balance = MILLI_PLMC; + +pub const fn deposit(items: u32, bytes: u32) -> Balance { + (items as Balance * 20 * PLMC + (bytes as Balance) * 100 * MICRO_PLMC) / 100 +} \ No newline at end of file diff --git a/runtimes/base/src/lib.rs b/runtimes/base/src/lib.rs index 63fb89b54..230849198 100644 --- a/runtimes/base/src/lib.rs +++ b/runtimes/base/src/lib.rs @@ -24,11 +24,17 @@ extern crate frame_benchmarking; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use frame_support::{ - construct_runtime, parameter_types, - traits::Everything, + construct_runtime, + dispatch::DispatchClass, + parameter_types, + traits::{ConstU32, ConstU64, Everything}, weights::{ConstantMultiplier, Weight}, + PalletId, +}; +use frame_system::{ + limits::{BlockLength, BlockWeights}, + EnsureRoot, }; -use frame_system::EnsureRoot; use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; use sp_api::impl_runtime_apis; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -37,10 +43,7 @@ use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; pub use sp_runtime::BuildStorage; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{ - AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, OpaqueKeys, - Verify, - }, + traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, OpaqueKeys, Verify}, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, MultiSignature, }; @@ -49,20 +52,22 @@ use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; - // XCM Imports +use parachains_common::AVERAGE_ON_INITIALIZE_RATIO; +use parachains_common::HOURS; +use parachains_common::MAXIMUM_BLOCK_WEIGHT; +use parachains_common::NORMAL_DISPATCH_RATIO; +use parachains_common::SLOT_DURATION; +use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; +use xcm::latest::prelude::BodyId; use xcm_config::{XcmConfig, XcmOriginToTransactDispatchOrigin}; use xcm_executor::XcmExecutor; -// Polimec Shared Imports -pub use shared_configuration::{currency::*, fee::*, governance::*, staking::*, weights::*}; - -pub use pallet_parachain_staking; - // Make the WASM binary available. #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +mod weights; pub mod xcm_config; /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. @@ -112,20 +117,122 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = frame_executive::Executive< - Runtime, - Block, - frame_system::ChainContext, - Runtime, - AllPalletsWithSystem, ->; +pub type Executive = + frame_executive::Executive, Runtime, AllPalletsWithSystem>; + +pub mod fee { + use super::{currency::MICRO_PLMC, Balance, ExtrinsicBaseWeight}; + use frame_support::weights::{Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}; + use smallvec::smallvec; + use sp_arithmetic::traits::{BaseArithmetic, Unsigned}; + use sp_runtime::{Perbill, SaturatedConversion}; + + /// Handles converting a weight scalar to a fee value, based on the scale and granularity of the + /// node's balance type. + /// + /// This should typically create a mapping between the following ranges: + /// - `[0, MAXIMUM_BLOCK_WEIGHT]` + /// - `[Balance::min, Balance::max]` + /// + /// Yet, it can be used for any other sort of change to weight-fee. Some examples being: + /// - Setting it to `0` will essentially disable the weight fee. + /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. + pub struct WeightToFee; + impl frame_support::weights::WeightToFee for WeightToFee { + type Balance = Balance; + + fn weight_to_fee(weight: &Weight) -> Self::Balance { + let ref_time = Balance::saturated_from(weight.ref_time()); + let proof_size = Balance::saturated_from(weight.proof_size()); + + let ref_polynomial = RefTimeToFee::polynomial(); + let proof_polynomial = ProofSizeToFee::polynomial(); + + // Get fee amount from ref_time based on the RefTime polynomial + let ref_fee: Balance = ref_polynomial + .iter() + .fold(0, |acc, term| term.saturating_eval(acc, ref_time)); + + // Get fee amount from proof_size based on the ProofSize polynomial + let proof_fee: Balance = proof_polynomial + .iter() + .fold(0, |acc, term| term.saturating_eval(acc, proof_size)); + + // Take the maximum instead of the sum to charge by the more scarce resource. + ref_fee.max(proof_fee) + } + } + + /// Maps the Ref time component of `Weight` to a fee. + pub struct RefTimeToFee; + impl WeightToFeePolynomial for RefTimeToFee { + type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { + // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 MILLIUNIT: + // in our template, we map to 1/10 of that, or 1/10 MILLIUNIT + let p = MILLIUNIT / 10; + let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } + } + + /// Maps the proof size component of `Weight` to a fee. + pub struct ProofSizeToFee; + impl WeightToFeePolynomial for ProofSizeToFee { + type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { + // Map 10kb proof to 1 CENT. + let p = MILLIUNIT / 10; + let q = 10_000; + + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } + } + + // TODO: Refactor out this code to use `FeePolynomial` on versions using polkadot-v0.9.42 and above: + pub trait WeightCoefficientCalc { + fn saturating_eval(&self, result: Balance, x: Balance) -> Balance; + } + + impl WeightCoefficientCalc for WeightToFeeCoefficient + where + Balance: BaseArithmetic + From + Copy + Unsigned + SaturatedConversion, + { + fn saturating_eval(&self, mut result: Balance, x: Balance) -> Balance { + let power = x.saturating_pow(self.degree.into()); + + let frac = self.coeff_frac * power; // Overflow safe since coeff_frac is strictly less than 1. + let integer = self.coeff_integer.saturating_mul(power); + // Do not add them together here to avoid an underflow. + + if self.negative { + result = result.saturating_sub(frac); + result = result.saturating_sub(integer); + } else { + result = result.saturating_add(frac); + result = result.saturating_add(integer); + } + + result + } + } +} /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know /// the specifics of the runtime. They can then be made to be agnostic over specific formats @@ -165,11 +272,39 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { - NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } } parameter_types! { pub const Version: RuntimeVersion = VERSION; + + // This part is copied from Substrate's `bin/node/runtime/src/lib.rs`. + // The `RuntimeBlockLength` and `RuntimeBlockWeights` exist here because the + // `DeletionWeightLimit` and `DeletionQueueDepth` depend on those to parameterize + // the lazy contract deletion. + pub RuntimeBlockLength: BlockLength = + BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); + pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder() + .base_block(BlockExecutionWeight::get()) + .for_class(DispatchClass::all(), |weights| { + weights.base_extrinsic = ExtrinsicBaseWeight::get(); + }) + .for_class(DispatchClass::Normal, |weights| { + weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + }) + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); + // Operational transactions have some extra reserved space, so that they + // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. + weights.reserved = Some( + MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT + ); + }) + .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) + .build_or_panic(); pub const SS58Prefix: u16 = 42; } @@ -224,39 +359,58 @@ impl frame_system::Config for Runtime { type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; type MaxConsumers = frame_support::traits::ConstU32<16>; } +parameter_types! { + pub const UncleGenerations: u32 = 0; +} impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - type MinimumPeriod = MinimumPeriod; + type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; type WeightInfo = (); } impl pallet_authorship::Config for Runtime { type FindAuthor = pallet_session::FindAccountFromAuthorIndex; - type EventHandler = ParachainStaking; + type EventHandler = (); +} + +parameter_types! { + pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT; } impl pallet_balances::Config for Runtime { + type MaxLocks = ConstU32<50>; + /// The type for recording an account's balance. type Balance = Balance; - type DustRemoval = (); + /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; - type MaxLocks = MaxLocks; - type MaxReserves = MaxReserves; - type ReserveIdentifier = (); - type WeightInfo = (); + type WeightInfo = pallet_balances::weights::SubstrateWeight; + type MaxReserves = ConstU32<50>; + type ReserveIdentifier = [u8; 8]; +} + +parameter_types! { + /// Relay Chain `TransactionByteFee` / 10 + pub const TransactionByteFee: Balance = 10 * MICRO_PLMC; } impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; - type OperationalFeeMultiplier = frame_support::traits::ConstU8<5>; + type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter>; type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type OperationalFeeMultiplier = ConstU8<5>; +} + +parameter_types! { + pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); + pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); } impl cumulus_pallet_parachain_system::Config for Runtime { @@ -293,52 +447,71 @@ impl cumulus_pallet_dmp_queue::Config for Runtime { type ExecuteOverweightOrigin = EnsureRoot; } +parameter_types! { + pub const Period: u32 = 6 * HOURS; + pub const Offset: u32 = 0; +} + impl pallet_session::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ValidatorId = AccountId; type ValidatorIdOf = ConvertInto; - type ShouldEndSession = ParachainStaking; - type NextSessionRotation = ParachainStaking; - type SessionManager = ParachainStaking; + type ShouldEndSession = (); + type NextSessionRotation = (); + type SessionManager = (); type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; + // type WeightInfo = weights::pallet_session::WeightInfo; type WeightInfo = (); } impl pallet_aura::Config for Runtime { type AuthorityId = AuraId; type DisabledValidators = (); - type MaxAuthorities = MaxAuthorities; + type MaxAuthorities = ConstU32<100_000>; } -impl pallet_sudo::Config for Runtime { - type RuntimeCall = RuntimeCall; +parameter_types! { + pub const PotId: PalletId = PalletId(*b"PotStake"); + pub const MaxCandidates: u32 = 1000; + pub const MinCandidates: u32 = 5; + pub const SessionLength: BlockNumber = 6 * HOURS; + pub const MaxInvulnerables: u32 = 100; + pub const ExecutiveBody: BodyId = BodyId::Executive; +} + +parameter_types! { + pub const ProposalBond: Permill = Permill::from_percent(5); + pub const ProposalBondMinimum: Balance = 20 * PLMC; + pub const SpendPeriod: BlockNumber = runtime_common::constants::governance::SPEND_PERIOD; + pub const Burn: Permill = Permill::zero(); + pub const MaxApprovals: u32 = 100; + pub const TreasuryId: PalletId = PalletId(*b"plmc/tsy"); +} + +impl pallet_treasury::Config for Runtime { + type PalletId = TreasuryId; + type Currency = Balances; + type ApproveOrigin = EnsureRoot; + type RejectOrigin = EnsureRoot; type RuntimeEvent = RuntimeEvent; + type OnSlash = Treasury; + type ProposalBond = ProposalBond; + type ProposalBondMinimum = ProposalBondMinimum; + type ProposalBondMaximum = (); + type SpendPeriod = SpendPeriod; + type SpendOrigin = frame_support::traits::NeverEnsureOrigin; + type Burn = Burn; + type BurnDestination = (); + type SpendFunds = (); + // type WeightInfo = weights::pallet_treasury::WeightInfo; + type WeightInfo = (); + type MaxApprovals = MaxApprovals; } -impl pallet_parachain_staking::Config for Runtime { +impl pallet_sudo::Config for Runtime { + type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; - type Currency = Balances; - type MonetaryGovernanceOrigin = frame_system::EnsureRoot; - type MinBlocksPerRound = MinBlocksPerRound; - type LeaveCandidatesDelay = LeaveCandidatesDelay; - type CandidateBondLessDelay = CandidateBondLessDelay; - type LeaveDelegatorsDelay = LeaveDelegatorsDelay; - type RevokeDelegationDelay = RevokeDelegationDelay; - type DelegationBondLessDelay = DelegationBondLessDelay; - type RewardPaymentDelay = RewardPaymentDelay; - type MinSelectedCandidates = MinSelectedCandidates; - type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; - type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate; - type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator; - type MinCandidateStk = MinCandidateStk; - type MinDelegatorStk = MinDelegatorStk; - type MinDelegation = MinDelegation; - type OnCollatorPayout = (); - // We use the default implementation, so we leave () here. - type PayoutCollatorReward = (); - type OnNewRound = (); - type WeightInfo = pallet_parachain_staking::weights::SubstrateWeight; } // Create the runtime by composing the FRAME pallets that were previously configured. @@ -358,13 +531,15 @@ construct_runtime!( // Monetary stuff. Balances: pallet_balances = 10, TransactionPayment: pallet_transaction_payment = 11, + Treasury: pallet_treasury = 12, - // Collator support. the order of these 5 are important and shall not change. - Authorship: pallet_authorship::{Pallet, Storage} = 20, - Session: pallet_session::{Pallet, Call, Storage, Event, Config} = 22, - Aura: pallet_aura::{Pallet, Storage, Config} = 23, - AuraExt: cumulus_pallet_aura_ext::{Pallet, Storage, Config} = 24, - ParachainStaking: pallet_parachain_staking::{Pallet, Call, Storage, Event, Config} = 25, + // Consensus support. + // The following order MUST NOT be changed: Aura -> Session -> Staking -> Authorship -> AuraExt + // Dependencies: AuraExt on Aura, Authorship and Session on ParachainStaking + Aura: pallet_aura = 23, + Session: pallet_session = 22, + Authorship: pallet_authorship = 20, + AuraExt: cumulus_pallet_aura_ext = 24, // XCM helpers. XcmpQueue: cumulus_pallet_xcmp_queue = 30, @@ -595,13 +770,12 @@ impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { .read_slot() .expect("Could not read the relay chain slot from the proof"); - let inherent_data = - cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( - relay_chain_slot, - sp_std::time::Duration::from_secs(6), - ) - .create_inherent_data() - .expect("Could not create the timestamp inherent data"); + let inherent_data = cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( + relay_chain_slot, + sp_std::time::Duration::from_secs(6), + ) + .create_inherent_data() + .expect("Could not create the timestamp inherent data"); inherent_data.check_extrinsics(block) } diff --git a/runtimes/shared-configuration/src/weights/block_weights.rs b/runtimes/base/src/weights/block_weights.rs similarity index 94% rename from runtimes/shared-configuration/src/weights/block_weights.rs rename to runtimes/base/src/weights/block_weights.rs index f24090fb4..451c27f95 100644 --- a/runtimes/shared-configuration/src/weights/block_weights.rs +++ b/runtimes/base/src/weights/block_weights.rs @@ -23,7 +23,7 @@ pub mod constants { parameter_types! { /// Importing a block with 0 Extrinsics. pub const BlockExecutionWeight: Weight = - Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(5_000_000), 0); + Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(5_000_000)); } #[cfg(test)] diff --git a/runtimes/shared-configuration/src/weights/extrinsic_weights.rs b/runtimes/base/src/weights/extrinsic_weights.rs similarity index 94% rename from runtimes/shared-configuration/src/weights/extrinsic_weights.rs rename to runtimes/base/src/weights/extrinsic_weights.rs index 465a4c5fe..0819bab8a 100644 --- a/runtimes/shared-configuration/src/weights/extrinsic_weights.rs +++ b/runtimes/base/src/weights/extrinsic_weights.rs @@ -23,7 +23,7 @@ pub mod constants { parameter_types! { /// Executing a NO-OP `System::remarks` Extrinsic. pub const ExtrinsicBaseWeight: Weight = - Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(125_000), 0); + Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(125_000)); } #[cfg(test)] diff --git a/runtimes/shared-configuration/src/lib.rs b/runtimes/base/src/weights/mod.rs similarity index 67% rename from runtimes/shared-configuration/src/lib.rs rename to runtimes/base/src/weights/mod.rs index 01fd24175..fb04fe6e5 100644 --- a/runtimes/shared-configuration/src/lib.rs +++ b/runtimes/base/src/weights/mod.rs @@ -14,15 +14,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -#![cfg_attr(not(feature = "std"), no_std)] +//! Expose the auto generated weight files. -pub mod assets; -pub mod currency; -pub mod fee; -pub mod funding; -pub mod governance; -pub mod staking; -pub mod weights; +pub mod block_weights; +pub mod extrinsic_weights; +pub mod paritydb_weights; +pub mod rocksdb_weights; -/// Common types -pub use parachains_common::{Balance, BlockNumber, DAYS}; +pub use block_weights::constants::BlockExecutionWeight; +pub use extrinsic_weights::constants::ExtrinsicBaseWeight; +pub use paritydb_weights::constants::ParityDbWeight; +pub use rocksdb_weights::constants::RocksDbWeight; diff --git a/runtimes/shared-configuration/src/weights/paritydb_weights.rs b/runtimes/base/src/weights/paritydb_weights.rs similarity index 100% rename from runtimes/shared-configuration/src/weights/paritydb_weights.rs rename to runtimes/base/src/weights/paritydb_weights.rs diff --git a/runtimes/shared-configuration/src/weights/rocksdb_weights.rs b/runtimes/base/src/weights/rocksdb_weights.rs similarity index 100% rename from runtimes/shared-configuration/src/weights/rocksdb_weights.rs rename to runtimes/base/src/weights/rocksdb_weights.rs diff --git a/runtimes/base/src/xcm_config.rs b/runtimes/base/src/xcm_config.rs index ea8c1a842..c8d6ae879 100644 --- a/runtimes/base/src/xcm_config.rs +++ b/runtimes/base/src/xcm_config.rs @@ -15,8 +15,8 @@ // along with this program. If not, see . use super::{ - AccountId, AllPalletsWithSystem, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, - Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, + AccountId, AllPalletsWithSystem, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, + RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, }; use frame_support::{ match_types, parameter_types, @@ -29,11 +29,10 @@ use polkadot_parachain::primitives::Sibling; use polkadot_runtime_common::impls::ToAuthor; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowTopLevelPaidExecutionFrom, - CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, IsConcrete, NativeAsset, ParentIsPreset, - RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, - SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, - UsingComponents, WithComputedOrigin, + AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, + EnsureXcmOrigin, FixedWeightBounds, IsConcrete, NativeAsset, ParentIsPreset, RelayChainAsNative, + SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, WithComputedOrigin, }; use xcm_executor::XcmExecutor; @@ -134,8 +133,7 @@ impl xcm_executor::Config for XcmConfig { type UniversalLocation = UniversalLocation; type Barrier = Barrier; type Weigher = FixedWeightBounds; - type Trader = - UsingComponents>; + type Trader = UsingComponents, RelayLocation, AccountId, Balances, ToAuthor>; type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; type AssetClaims = PolkadotXcm; diff --git a/runtimes/shared-configuration/Cargo.toml b/runtimes/shared-configuration/Cargo.toml deleted file mode 100644 index f52095e35..000000000 --- a/runtimes/shared-configuration/Cargo.toml +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "shared-configuration" -description = "Chain shared configuration Polimec" -authors.workspace = true -documentation.workspace = true -edition.workspace = true -homepage.workspace = true -license-file.workspace = true -readme.workspace = true -repository.workspace = true -version.workspace = true - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -smallvec.workspace = true - -# FRAME -frame-system.workspace = true -frame-support.workspace = true -sp-arithmetic.workspace = true -parachains-common.workspace = true - -[features] -default = ["std"] -fast-gov = [] -std = ["frame-support/std", "sp-arithmetic/std", "parachains-common/std"] -runtime-benchmarks = ["frame-support/runtime-benchmarks"] diff --git a/runtimes/shared-configuration/src/currency.rs b/runtimes/shared-configuration/src/currency.rs deleted file mode 100644 index bc401318a..000000000 --- a/runtimes/shared-configuration/src/currency.rs +++ /dev/null @@ -1,64 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -use crate::Balance; -use frame_support::parameter_types; - -/// One PLMC -pub const PLMC: Balance = 10u128.pow(10); -/// 0.001 PLMC -pub const MILLI_PLMC: Balance = 10u128.pow(7); -/// 0.000_001 PLMC -pub const MICRO_PLMC: Balance = 10u128.pow(4); - -pub const EXISTENTIAL_DEPOSIT: Balance = MILLI_PLMC; - -/// Deposit that must be provided for each occupied storage item. -pub const DEPOSIT_STORAGE_ITEM: Balance = 56 * MILLI_PLMC; -/// Deposit that must be provided for each occupied storage byte. -pub const DEPOSIT_STORAGE_BYTE: Balance = 100 * MICRO_PLMC; - -pub const fn deposit(items: u32, bytes: u32) -> Balance { - (items as Balance * DEPOSIT_STORAGE_ITEM + (bytes as Balance) * DEPOSIT_STORAGE_BYTE) / 100 -} - -#[inline(always)] -pub const fn free_deposit() -> Balance { - deposit(0, 0) -} - -parameter_types! { - /// Relay Chain `TransactionByteFee` / 10 - pub const TransactionByteFee: Balance = 10 * MICRO_PLMC; - pub const DepositBase: Balance = DEPOSIT_STORAGE_ITEM; - pub const DepositFactor: Balance = DEPOSIT_STORAGE_BYTE; - pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT; - pub const MaxSignatories: u32 = 64; - pub const MaxLocks: u32 = 50; - pub const MaxReserves: u32 = 50; -} - -pub mod vesting { - use frame_support::traits::WithdrawReasons; - - use super::*; - - parameter_types! { - pub const MinVestedTransfer: Balance = 10 * PLMC; - pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons = - WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); - } -} diff --git a/runtimes/shared-configuration/src/fee.rs b/runtimes/shared-configuration/src/fee.rs deleted file mode 100644 index 2fd88b717..000000000 --- a/runtimes/shared-configuration/src/fee.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -use crate::{currency::MILLI_PLMC, Balance}; -use frame_support::{ - parameter_types, - weights::{ - constants::ExtrinsicBaseWeight, WeightToFeeCoefficient, WeightToFeeCoefficients, - WeightToFeePolynomial, - }, -}; -use parachains_common::SLOT_DURATION; -use smallvec::smallvec; -use sp_arithmetic::Perbill; - -pub struct WeightToFee; -impl WeightToFeePolynomial for WeightToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - // extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: - let p = 10 * MILLI_PLMC; - let q = Balance::from(ExtrinsicBaseWeight::get().ref_time()); - smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } -} - -parameter_types! { - pub const MinimumPeriod: u64 = SLOT_DURATION / 2; - pub const MaxAuthorities: u32 = 100_000; -} diff --git a/runtimes/shared-configuration/src/funding.rs b/runtimes/shared-configuration/src/funding.rs deleted file mode 100644 index a1bf85ad0..000000000 --- a/runtimes/shared-configuration/src/funding.rs +++ /dev/null @@ -1,64 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -use crate::{BlockNumber, DAYS}; -use frame_support::{parameter_types, PalletId}; - -#[cfg(feature = "fast-gov")] -pub const EVALUATION_DURATION: BlockNumber = 28; -#[cfg(not(feature = "fast-gov"))] -pub const EVALUATION_DURATION: BlockNumber = 28 * DAYS; - -#[cfg(feature = "fast-gov")] -pub const AUCTION_INITIALIZE_PERIOD_DURATION: BlockNumber = 7; -#[cfg(not(feature = "fast-gov"))] -pub const AUCTION_INITIALIZE_PERIOD_DURATION: BlockNumber = 7 * DAYS; - -#[cfg(feature = "fast-gov")] -pub const ENGLISH_AUCTION_DURATION: BlockNumber = 10; -#[cfg(not(feature = "fast-gov"))] -pub const ENGLISH_AUCTION_DURATION: BlockNumber = 2 * DAYS; - -#[cfg(feature = "fast-gov")] -pub const CANDLE_AUCTION_DURATION: BlockNumber = 5; -#[cfg(not(feature = "fast-gov"))] -pub const CANDLE_AUCTION_DURATION: BlockNumber = 3 * DAYS; - -#[cfg(feature = "fast-gov")] -pub const COMMUNITY_FUNDING_DURATION: BlockNumber = 10; -#[cfg(not(feature = "fast-gov"))] -pub const COMMUNITY_FUNDING_DURATION: BlockNumber = 5 * DAYS; - -#[cfg(feature = "fast-gov")] -pub const REMAINDER_FUNDING_DURATION: BlockNumber = 10; -#[cfg(not(feature = "fast-gov"))] -pub const REMAINDER_FUNDING_DURATION: BlockNumber = DAYS; - -#[cfg(feature = "fast-gov")] -pub const CONTRIBUTION_VESTING_DURATION: BlockNumber = 365; -#[cfg(not(feature = "fast-gov"))] -pub const CONTRIBUTION_VESTING_DURATION: BlockNumber = 365 * DAYS; - -parameter_types! { - pub const EvaluationDuration: BlockNumber = EVALUATION_DURATION; - pub const AuctionInitializePeriodDuration: BlockNumber = AUCTION_INITIALIZE_PERIOD_DURATION; - pub const EnglishAuctionDuration: BlockNumber = ENGLISH_AUCTION_DURATION; - pub const CandleAuctionDuration: BlockNumber = CANDLE_AUCTION_DURATION; - pub const CommunityFundingDuration: BlockNumber = COMMUNITY_FUNDING_DURATION; - pub const RemainderFundingDuration: BlockNumber = REMAINDER_FUNDING_DURATION; - pub const ContributionVestingDuration: BlockNumber = CONTRIBUTION_VESTING_DURATION; - pub const FundingPalletId: PalletId = PalletId(*b"py/cfund"); -} diff --git a/runtimes/shared-configuration/src/governance.rs b/runtimes/shared-configuration/src/governance.rs deleted file mode 100644 index 654000553..000000000 --- a/runtimes/shared-configuration/src/governance.rs +++ /dev/null @@ -1,105 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -use crate::{ - currency::{deposit, PLMC}, - Balance, -}; -use frame_support::{parameter_types, PalletId}; -use parachains_common::{BlockNumber, DAYS, HOURS}; -use sp_arithmetic::Permill; - -pub const MIN_DEPOSIT: Balance = PLMC; - -#[cfg(feature = "fast-gov")] -pub const LAUNCH_PERIOD: BlockNumber = 7 * MINUTES; -#[cfg(not(feature = "fast-gov"))] -pub const LAUNCH_PERIOD: BlockNumber = 7 * DAYS; - -#[cfg(feature = "fast-gov")] -pub const VOTING_PERIOD: BlockNumber = 7 * MINUTES; -#[cfg(not(feature = "fast-gov"))] -pub const VOTING_PERIOD: BlockNumber = 7 * DAYS; - -#[cfg(feature = "fast-gov")] -pub const FAST_TRACK_VOTING_PERIOD: BlockNumber = 3 * MINUTES; -#[cfg(not(feature = "fast-gov"))] -pub const FAST_TRACK_VOTING_PERIOD: BlockNumber = 3 * HOURS; - -#[cfg(feature = "fast-gov")] -pub const ENACTMENT_PERIOD: BlockNumber = 8 * MINUTES; -#[cfg(not(feature = "fast-gov"))] -pub const ENACTMENT_PERIOD: BlockNumber = DAYS; - -#[cfg(feature = "fast-gov")] -pub const COOLOFF_PERIOD: BlockNumber = 7 * MINUTES; -#[cfg(not(feature = "fast-gov"))] -pub const COOLOFF_PERIOD: BlockNumber = 7 * DAYS; - -#[cfg(feature = "fast-gov")] -pub const SPEND_PERIOD: BlockNumber = 6 * MINUTES; -#[cfg(not(feature = "fast-gov"))] -pub const SPEND_PERIOD: BlockNumber = 6 * DAYS; - -#[cfg(feature = "fast-gov")] -pub const ROTATION_PERIOD: BlockNumber = 80 * MINUTES; -#[cfg(not(feature = "fast-gov"))] -pub const ROTATION_PERIOD: BlockNumber = 80 * HOURS; - -#[cfg(feature = "fast-gov")] -pub const TERM_DURATION: BlockNumber = 15 * MINUTES; -#[cfg(not(feature = "fast-gov"))] -pub const TERM_DURATION: BlockNumber = DAYS; - -#[cfg(feature = "fast-gov")] -pub const COUNCIL_MOTION_DURATION: BlockNumber = 4 * MINUTES; -#[cfg(not(feature = "fast-gov"))] -pub const COUNCIL_MOTION_DURATION: BlockNumber = 3 * DAYS; - -#[cfg(feature = "fast-gov")] -pub const TECHNICAL_MOTION_DURATION: BlockNumber = 4 * MINUTES; -#[cfg(not(feature = "fast-gov"))] -pub const TECHNICAL_MOTION_DURATION: BlockNumber = 3 * DAYS; - -parameter_types! { - // Democracy Pallet - pub const LaunchPeriod: BlockNumber = LAUNCH_PERIOD; - pub const VotingPeriod: BlockNumber = VOTING_PERIOD; - pub const FastTrackVotingPeriod: BlockNumber = FAST_TRACK_VOTING_PERIOD; - pub const MinimumDeposit: Balance = MIN_DEPOSIT; - pub const EnactmentPeriod: BlockNumber = ENACTMENT_PERIOD; - pub const CooloffPeriod: BlockNumber = COOLOFF_PERIOD; - // Council Pallet - pub const CouncilMotionDuration: BlockNumber = COUNCIL_MOTION_DURATION; - pub const CouncilMaxProposals: u32 = 100; - pub const CouncilMaxMembers: u32 = 100; - // Technical Committee - pub const TechnicalMotionDuration: BlockNumber = TECHNICAL_MOTION_DURATION; - pub const TechnicalMaxProposals: u32 = 100; - pub const TechnicalMaxMembers: u32 = 100; - // Tipper Group - pub const TipperMaxMembers: u32 = 21; - // Extras - pub const PreimageBaseDeposit: Balance = deposit(2, 64); - pub const MaxProposals: u32 = 100; - //Treasury - pub const ProposalBond: Permill = Permill::from_percent(5); - pub const ProposalBondMinimum: Balance = 20 * PLMC; - pub const SpendPeriod: BlockNumber = SPEND_PERIOD; - pub const Burn: Permill = Permill::zero(); - pub const MaxApprovals: u32 = 100; - pub const TreasuryId: PalletId = PalletId(*b"plmc/tsy"); -} diff --git a/runtimes/shared-configuration/src/staking.rs b/runtimes/shared-configuration/src/staking.rs deleted file mode 100644 index 66292b5d4..000000000 --- a/runtimes/shared-configuration/src/staking.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -use crate::currency::PLMC; -use frame_support::parameter_types; - -// Since a Round is 6 hours, one week, expresses as `RoundIndex` is 4 * 7 -const WEEK_IN_ROUNDS: u32 = 4 * 7; - -parameter_types! { - pub const MinBlocksPerRound: u32 = 10; - pub const LeaveCandidatesDelay: u32 = WEEK_IN_ROUNDS; - pub const CandidateBondLessDelay: u32 = WEEK_IN_ROUNDS; - pub const LeaveDelegatorsDelay: u32 = WEEK_IN_ROUNDS; - pub const RevokeDelegationDelay: u32 = WEEK_IN_ROUNDS; - pub const DelegationBondLessDelay: u32 = WEEK_IN_ROUNDS; - pub const RewardPaymentDelay: u32 = 2; - pub const MinSelectedCandidates: u32 = 5; - pub const MaxTopDelegationsPerCandidate: u32 = 300; - pub const MaxBottomDelegationsPerCandidate: u32 = 50; - pub const MaxDelegationsPerDelegator: u32 = 100; - pub const MinCandidateStk: u128 = 20_000 * PLMC; - pub const MinDelegatorStk: u128 = 50 * PLMC; - pub const MinDelegation: u128 = 50 * PLMC; -} diff --git a/runtimes/shared-configuration/src/weights/mod.rs b/runtimes/shared-configuration/src/weights/mod.rs deleted file mode 100644 index 68cc6b5f3..000000000 --- a/runtimes/shared-configuration/src/weights/mod.rs +++ /dev/null @@ -1,63 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -//! Expose the auto generated weight files. - -pub mod block_weights; -pub mod extrinsic_weights; -pub mod paritydb_weights; -pub mod rocksdb_weights; - -pub use block_weights::constants::BlockExecutionWeight; -pub use extrinsic_weights::constants::ExtrinsicBaseWeight; -use frame_support::{dispatch::DispatchClass, parameter_types, weights::Weight}; -use parachains_common::{AVERAGE_ON_INITIALIZE_RATIO, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO}; -pub use paritydb_weights::constants::ParityDbWeight; -pub use rocksdb_weights::constants::RocksDbWeight; - -use frame_system::limits::{BlockLength, BlockWeights}; -use sp_arithmetic::Perbill; - -parameter_types! { - // This part is copied from Substrate's `bin/node/runtime/src/lib.rs`. - // The `RuntimeBlockLength` and `RuntimeBlockWeights` exist here because the - // `DeletionWeightLimit` and `DeletionQueueDepth` depend on those to parameterize - // the lazy contract deletion. - pub RuntimeBlockLength: BlockLength = - BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); - pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder() - .base_block(BlockExecutionWeight::get()) - .for_class(DispatchClass::all(), |weights| { - weights.base_extrinsic = ExtrinsicBaseWeight::get(); - }) - .for_class(DispatchClass::Normal, |weights| { - weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); - }) - .for_class(DispatchClass::Operational, |weights| { - weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); - // Operational transactions have some extra reserved space, so that they - // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. - weights.reserved = Some( - MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT - ); - }) - .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) - .build_or_panic(); - pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); - pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); - pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * RuntimeBlockWeights::get().max_block; - pub const MaxScheduledPerBlock: u32 = 50; -} diff --git a/runtimes/standalone/Cargo.toml b/runtimes/standalone/Cargo.toml index 9faf0e20e..d2b067ff1 100644 --- a/runtimes/standalone/Cargo.toml +++ b/runtimes/standalone/Cargo.toml @@ -66,6 +66,7 @@ hex-literal = { workspace = true, optional = true } # Local Dependencies pallet-funding.workspace = true +polimec-traits.workspace = true [build-dependencies] substrate-wasm-builder.workspace = true @@ -111,6 +112,7 @@ std = [ "pallet-session/std", "pallet-authorship/std", "pallet-insecure-randomness-collective-flip/std", + "polimec-traits/std", "pallet-vesting/std", ] @@ -129,6 +131,7 @@ runtime-benchmarks = [ "pallet-democracy/runtime-benchmarks", "pallet-funding/runtime-benchmarks", "pallet-scheduler/runtime-benchmarks", + "polimec-traits/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", ] try-runtime = [ @@ -150,5 +153,6 @@ try-runtime = [ "pallet-insecure-randomness-collective-flip/try-runtime", "pallet-scheduler/try-runtime", "pallet-session/try-runtime", + "polimec-traits/try-runtime", "pallet-vesting/try-runtime", ] diff --git a/runtimes/standalone/src/lib.rs b/runtimes/standalone/src/lib.rs index 039fd3a3b..9975c2faa 100644 --- a/runtimes/standalone/src/lib.rs +++ b/runtimes/standalone/src/lib.rs @@ -25,13 +25,11 @@ extern crate frame_benchmarking; pub use frame_support::{ construct_runtime, parameter_types, traits::{ - ConstU128, ConstU32, ConstU64, ConstU8, Contains, EitherOfDiverse, EqualPrivilegeOnly, - KeyOwnerProofSystem, Randomness, StorageInfo, WithdrawReasons, + ConstU128, ConstU32, ConstU64, ConstU8, Contains, EitherOfDiverse, EqualPrivilegeOnly, KeyOwnerProofSystem, + Randomness, StorageInfo, }, weights::{ - constants::{ - BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND, - }, + constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND}, IdentityFee, Weight, }, PalletId, StorageValue, @@ -42,9 +40,7 @@ use frame_system::EnsureSigned; pub use frame_system::{Call as SystemCall, EnsureRoot}; pub use pallet_balances::Call as BalancesCall; use pallet_funding::{BondType, Multiplier as FundingMultiplier}; -use pallet_grandpa::{ - fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList, -}; +use pallet_grandpa::{fg_primitives, AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList}; pub use pallet_timestamp::Call as TimestampCall; use pallet_transaction_payment::{ConstFeeMultiplier, CurrencyAdapter, Multiplier}; use sp_api::impl_runtime_apis; @@ -55,8 +51,7 @@ pub use sp_runtime::BuildStorage; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{ - AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, NumberFor, - One, OpaqueKeys, Verify, + AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, IdentifyAccount, NumberFor, One, OpaqueKeys, Verify, }, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, MultiSignature, @@ -172,7 +167,10 @@ pub const MICRO_PLMC: Balance = 10u128.pow(4); /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { - NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } } const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); @@ -258,13 +256,10 @@ impl pallet_grandpa::Config for Runtime { type KeyOwnerProofSystem = (); - type KeyOwnerProof = - >::Proof; + type KeyOwnerProof = >::Proof; - type KeyOwnerIdentification = >::IdentificationTuple; + type KeyOwnerIdentification = + >::IdentificationTuple; type HandleEquivocation = (); @@ -380,6 +375,7 @@ impl pallet_funding::Config for Runtime { type ContributionTokenCurrency = Assets; type BidId = u128; type Randomness = Random; + type HandleMembers = Credentials; type StringLimit = ConstU32<64>; type PreImageLimit = ConstU32<1024>; type EvaluationDuration = EvaluationDuration; @@ -398,6 +394,17 @@ impl pallet_funding::Config for Runtime { type WeightInfo = (); } +impl pallet_credentials::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 = (); +} + impl pallet_scheduler::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; @@ -471,26 +478,20 @@ impl pallet_democracy::Config for Runtime { type VoteLockingPeriod = EnactmentPeriod; // Same as EnactmentPeriod type MinimumDeposit = MinimumDeposit; /// A straight majority of the council can decide what their next motion is. - type ExternalOrigin = - pallet_collective::EnsureProportionAtLeast; + type ExternalOrigin = pallet_collective::EnsureProportionAtLeast; /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. - type ExternalMajorityOrigin = - pallet_collective::EnsureProportionAtLeast; + type ExternalMajorityOrigin = pallet_collective::EnsureProportionAtLeast; /// A unanimous council can have the next scheduled referendum be a straight default-carries /// (NTB) vote. - type ExternalDefaultOrigin = - pallet_collective::EnsureProportionAtLeast; + type ExternalDefaultOrigin = pallet_collective::EnsureProportionAtLeast; /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote /// be tabled immediately and with a shorter voting/enactment period. - type FastTrackOrigin = - pallet_collective::EnsureProportionAtLeast; - type InstantOrigin = - pallet_collective::EnsureProportionAtLeast; + type FastTrackOrigin = pallet_collective::EnsureProportionAtLeast; + type InstantOrigin = pallet_collective::EnsureProportionAtLeast; type InstantAllowed = frame_support::traits::ConstBool; type FastTrackVotingPeriod = FastTrackVotingPeriod; // To cancel a proposal which has been passed, 2/3 of the council must agree to it. - type CancellationOrigin = - pallet_collective::EnsureProportionAtLeast; + type CancellationOrigin = pallet_collective::EnsureProportionAtLeast; // To cancel a proposal before it has been passed, the technical committee must be unanimous or // Root must agree. type CancelProposalOrigin = EitherOfDiverse< @@ -565,20 +566,13 @@ impl pallet_utility::Config for Runtime { type WeightInfo = (); } -parameter_types! { - /// Vesting Pallet. Copied from Kusama & Polkadot runtime - pub const MinVestedTransfer: Balance = 100 * MILLI_PLMC; - pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons = - WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); -} - impl pallet_vesting::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; type BlockNumberToBalance = ConvertInto; - type MinVestedTransfer = MinVestedTransfer; + type MinVestedTransfer = runtime_common::constants::MinVestedTransfer; type WeightInfo = pallet_vesting::weights::SubstrateWeight; - type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; + type UnvestedFundsAllowedWithdrawReasons = runtime_common::constants::UnvestedFundsAllowedWithdrawReasons; // `VestingInfo` encode length is 36bytes. 28 schedules gets encoded as 1009 bytes, which is the // highest number of schedules that encodes less than 2^10. const MAX_VESTING_SCHEDULES: u32 = 28; @@ -619,6 +613,7 @@ construct_runtime!( // Include the custom logic PolimecFunding: pallet_funding, + Credentials: pallet_credentials, } ); @@ -641,18 +636,12 @@ pub type SignedExtra = ( ); /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// The payload being signed in transactions. pub type SignedPayload = generic::SignedPayload; /// Executive: handles dispatch to the various modules. -pub type Executive = frame_executive::Executive< - Runtime, - Block, - frame_system::ChainContext, - Runtime, - AllPalletsWithSystem, ->; +pub type Executive = + frame_executive::Executive, Runtime, AllPalletsWithSystem>; #[cfg(feature = "runtime-benchmarks")] mod benches { @@ -903,24 +892,14 @@ mod tests { .collect(); // Block Number - assert!( - whitelist.contains("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac") - ); + assert!(whitelist.contains("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac")); // Total Issuance - assert!( - whitelist.contains("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80") - ); + assert!(whitelist.contains("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80")); // Execution Phase - assert!( - whitelist.contains("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a") - ); + assert!(whitelist.contains("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a")); // Event Count - assert!( - whitelist.contains("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850") - ); + assert!(whitelist.contains("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850")); // System Events - assert!( - whitelist.contains("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7") - ); + assert!(whitelist.contains("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7")); } } diff --git a/runtimes/testnet/Cargo.toml b/runtimes/testnet/Cargo.toml index 42a17d71f..7cb6f4dbc 100644 --- a/runtimes/testnet/Cargo.toml +++ b/runtimes/testnet/Cargo.toml @@ -25,7 +25,16 @@ smallvec.workspace = true # Polimec specific pallet-funding.workspace = true -shared-configuration.workspace = true +polimec-traits.workspace = true + +# KILT specific +pallet-dip-consumer.workspace = true +did.workspace = true +pallet-did-lookup.workspace = true +kilt-dip-support.workspace = true + +# Primitives +xcm-primitives.workspace = true # FRAME frame-benchmarking = { workspace = true, optional = true } @@ -54,7 +63,6 @@ pallet-multisig.workspace = true pallet-preimage.workspace = true pallet-insecure-randomness-collective-flip.workspace = true pallet-vesting.workspace = true -pallet-parachain-staking.workspace = true # Substrate sp-api.workspace = true @@ -142,6 +150,7 @@ std = [ "parachain-info/std", "polkadot-parachain/std", "polkadot-runtime-common/std", + "polimec-traits/std", "sp-api/std", "sp-block-builder/std", "sp-consensus-aura/std", @@ -157,8 +166,9 @@ std = [ "xcm-builder/std", "xcm-executor/std", "xcm/std", - "shared-configuration/std", - "pallet-parachain-staking/std" + "did/std", + "pallet-dip-consumer/std", + "pallet-did-lookup/std", ] runtime-benchmarks = [ @@ -180,7 +190,7 @@ runtime-benchmarks = [ "pallet-assets/runtime-benchmarks", "pallet-collective/runtime-benchmarks", ] - +# try-runtime = [ "cumulus-pallet-aura-ext/try-runtime", "cumulus-pallet-dmp-queue/try-runtime", diff --git a/runtimes/testnet/src/dip.rs b/runtimes/testnet/src/dip.rs new file mode 100644 index 000000000..6e9b41ecb --- /dev/null +++ b/runtimes/testnet/src/dip.rs @@ -0,0 +1,169 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +use did::{did_details::DidVerificationKey, DidVerificationKeyRelationship, KeyIdOf}; +use frame_support::traits::Contains; +use kilt_dip_support::{ + did::{DidSignatureAndCallVerifier, MerkleEntriesAndDidSignature, MerkleRevealedDidSignatureVerifier}, + merkle::{DidMerkleProofVerifier, MerkleProof, ProofLeaf}, + traits::{BlockNumberProvider, DidDipOriginFilter, GenesisProvider}, + MerkleProofAndDidSignatureVerifier, +}; +use pallet_dip_consumer::traits::IdentityProofVerifier; +use sp_std::vec::Vec; + +use crate::{AccountId, BlockNumber, Hash, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin}; +use runtime_common::DidIdentifier; +use sp_runtime::traits::BlakeTwo256; +pub type Hasher = BlakeTwo256; + +pub type MerkleProofVerifier = DidMerkleProofVerifier, BlockNumber, u128, 10>; +pub type MerkleProofVerifierOutputOf = + >::VerificationResult; + +pub type MerkleDidSignatureVerifierOf = MerkleRevealedDidSignatureVerifier< + BlockNumber, + Hash, + u128, + AccountId, + MerkleProofVerifierOutputOf, + BlockNumberProvider, + // Signatures are valid for 50 blocks + 50, + GenesisProvider, + Hash, +>; + +impl pallet_dip_consumer::Config for Runtime { + type DipCallOriginFilter = PreliminaryDipOriginFilter; + type Identifier = DidIdentifier; + type IdentityDetails = u128; + type Proof = MerkleEntriesAndDidSignature>, ProofLeaf>, BlockNumber>; + type ProofDigest = Hash; + type ProofVerifier = MerkleProofAndDidSignatureVerifier< + BlockNumber, + MerkleProofVerifier, + DidSignatureAndCallVerifier, DipCallFilter>, + >; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; +} + +pub struct PreliminaryDipOriginFilter; + +impl Contains for PreliminaryDipOriginFilter { + fn contains(t: &RuntimeCall) -> bool { + matches!( + t, + RuntimeCall::DidLookup { .. } + | RuntimeCall::Utility(pallet_utility::Call::batch { .. }) + | RuntimeCall::Utility(pallet_utility::Call::batch_all { .. }) + | RuntimeCall::Utility(pallet_utility::Call::force_batch { .. }) + ) + } +} + +fn derive_verification_key_relationship(call: &RuntimeCall) -> Option { + match call { + RuntimeCall::DidLookup { .. } => Some(DidVerificationKeyRelationship::Authentication), + RuntimeCall::Utility(pallet_utility::Call::batch { calls }) => single_key_relationship(calls.iter()).ok(), + RuntimeCall::Utility(pallet_utility::Call::batch_all { calls }) => single_key_relationship(calls.iter()).ok(), + RuntimeCall::Utility(pallet_utility::Call::force_batch { calls }) => single_key_relationship(calls.iter()).ok(), + _ => None, + } +} + +// Taken and adapted from `impl +// did::DeriveDidCallAuthorizationVerificationKeyRelationship for RuntimeCall` +// in Spiritnet/Peregrine runtime. +fn single_key_relationship<'a>( + calls: impl Iterator, +) -> Result { + let mut calls = calls.peekable(); + let first_call_relationship = calls + .peek() + .and_then(|k| derive_verification_key_relationship(k)) + .ok_or(())?; + calls + .map(derive_verification_key_relationship) + .try_fold(first_call_relationship, |acc, next| { + if next == Some(acc) { + Ok(acc) + } else { + Err(()) + } + }) +} + +pub struct DipCallFilter; + +impl DidDipOriginFilter for DipCallFilter { + type Error = (); + type OriginInfo = (DidVerificationKey, DidVerificationKeyRelationship); + type Success = (); + + // Accepts only a DipOrigin for the DidLookup pallet calls. + fn check_call_origin_info(call: &RuntimeCall, info: &Self::OriginInfo) -> Result { + let key_relationship = single_key_relationship([call].into_iter())?; + if info.1 == key_relationship { + Ok(()) + } else { + Err(()) + } + } +} + +#[cfg(test)] +mod dip_call_origin_filter_tests { + use super::*; + + use frame_support::assert_err; + + #[test] + fn test_key_relationship_derivation() { + // Can call DidLookup functions with an authentication key + let did_lookup_call = RuntimeCall::DidLookup(pallet_did_lookup::Call::associate_sender {}); + assert_eq!( + single_key_relationship(vec![did_lookup_call].iter()), + Ok(DidVerificationKeyRelationship::Authentication) + ); + // Can't call System functions with a DID key (hence a DIP origin) + let system_call = RuntimeCall::System(frame_system::Call::remark { remark: vec![] }); + assert_err!(single_key_relationship(vec![system_call].iter()), ()); + // Can't call empty batch with a DID key + let empty_batch_call = RuntimeCall::Utility(pallet_utility::Call::batch_all { calls: vec![] }); + assert_err!(single_key_relationship(vec![empty_batch_call].iter()), ()); + // Can call batch with a DipLookup with an authentication key + let did_lookup_batch_call = RuntimeCall::Utility(pallet_utility::Call::batch_all { + calls: vec![pallet_did_lookup::Call::associate_sender {}.into()], + }); + assert_eq!( + single_key_relationship(vec![did_lookup_batch_call].iter()), + Ok(DidVerificationKeyRelationship::Authentication) + ); + // Can't call a batch with different required keys + let did_lookup_batch_call = RuntimeCall::Utility(pallet_utility::Call::batch_all { + calls: vec![ + // Authentication key + pallet_did_lookup::Call::associate_sender {}.into(), + // No key + frame_system::Call::remark { remark: vec![] }.into(), + ], + }); + assert_err!(single_key_relationship(vec![did_lookup_batch_call].iter()), ()); + } +} diff --git a/runtimes/testnet/src/lib.rs b/runtimes/testnet/src/lib.rs index 7531aa8c2..a36c0bdb3 100644 --- a/runtimes/testnet/src/lib.rs +++ b/runtimes/testnet/src/lib.rs @@ -24,19 +24,22 @@ extern crate frame_benchmarking; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use frame_support::{ - construct_runtime, parameter_types, + construct_runtime, + pallet_prelude::Get, + parameter_types, traits::{ - AsEnsureOriginWithArg, ConstU32, Currency, EitherOfDiverse, EqualPrivilegeOnly, Everything, + AsEnsureOriginWithArg, ConstU32, Currency, EitherOfDiverse, EqualPrivilegeOnly, Everything, Imbalance, + OnUnbalanced, }, weights::{ConstantMultiplier, Weight}, + PalletId, }; use frame_system::{EnsureRoot, EnsureSigned}; pub use parachains_common::{ - impls::DealWithFees, opaque, AccountId, AssetIdForTrustBackedAssets as AssetId, AuraId, - Balance, BlockNumber, Hash, Header, Index, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, - MAXIMUM_BLOCK_WEIGHT, MINUTES, NORMAL_DISPATCH_RATIO, SLOT_DURATION, + impls::DealWithFees, opaque, AccountId, AssetIdForTrustBackedAssets as AssetId, AuraId, Balance, BlockNumber, Hash, + Header, Index, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, MAXIMUM_BLOCK_WEIGHT, MINUTES, + NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; - // Polkadot imports use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; use sp_api::impl_runtime_apis; @@ -47,40 +50,42 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, OpaqueKeys}, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, + ApplyExtrinsicResult, Perquintill, }; pub use sp_runtime::{MultiAddress, Perbill, Permill}; use sp_std::prelude::*; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; - // XCM Imports -use xcm_config::XcmConfig; +use pallet_funding::{BondType, Multiplier as FundingMultiplier}; use xcm_executor::XcmExecutor; -mod xcm_config; -pub use crate::xcm_config::*; + +use kilt_dip_support::merkle::VerificationResult; +use pallet_dip_consumer::{DipOrigin, EnsureDipOrigin}; +use runtime_common::constants::staking::*; +pub use runtime_common::{ + constants::{ + governance::*, polimec_inflation_config, preimage::PreimageBaseDeposit, treasury::INITIAL_PERIOD_LENGTH, + InflationInfo, BLOCKS_PER_YEAR, EXISTENTIAL_DEPOSIT, MAX_COLLATOR_STAKE, MICRO_PLMC, PLMC, + }, + fees::WeightToFee, + DidIdentifier, RuntimeBlockLength, RuntimeBlockWeights, +}; +use weights::RocksDbWeight; +use xcm_config::XcmConfig; // Make the WASM binary available. #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -// Polimec Shared Imports -use pallet_funding::{BondType, Multiplier as FundingMultiplier}; -pub use pallet_parachain_staking; -pub use shared_configuration::{ - assets::*, - currency::{vesting::*, *}, - fee::*, - funding::*, - governance::*, - staking::*, - weights::*, -}; +mod dip; +mod weights; +mod xcm_config; +pub use crate::{dip::*, xcm_config::*}; -pub type NegativeImbalanceOf = as Currency< - ::AccountId, ->>::NegativeImbalance; +pub type NegativeImbalanceOf = + as Currency<::AccountId>>::NegativeImbalance; /// The address format for describing accounts. pub type Address = MultiAddress; @@ -103,24 +108,19 @@ pub type SignedExtra = ( frame_system::CheckEra, frame_system::CheckNonce, frame_system::CheckWeight, + // pallet_asset_tx_payment::ChargeAssetTxPayment, pallet_transaction_payment::ChargeTransactionPayment, ); /// Unchecked extrinsic type as expected by this runtime. -pub type UncheckedExtrinsic = - generic::UncheckedExtrinsic; +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Extrinsic type that has already been checked. pub type CheckedExtrinsic = generic::CheckedExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = frame_executive::Executive< - Runtime, - Block, - frame_system::ChainContext, - Runtime, - AllPalletsWithSystem, ->; +pub type Executive = + frame_executive::Executive, Runtime, AllPalletsWithSystem>; impl_opaque_keys! { pub struct SessionKeys { @@ -143,7 +143,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { - NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } } parameter_types! { @@ -177,7 +180,7 @@ impl frame_system::Config for Runtime { /// The lookup mechanism to get account ID from whatever is passed in dispatchers. type Lookup = AccountIdLookup; /// The header type. - type Header = Header; + type Header = runtime_common::Header; /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; /// Maximum number of block number to block hash mappings to keep (oldest pruned first). @@ -204,6 +207,10 @@ impl frame_system::Config for Runtime { type MaxConsumers = frame_support::traits::ConstU32<16>; } +parameter_types! { + pub const MinimumPeriod: u64 = SLOT_DURATION / 2; +} + impl pallet_timestamp::Config for Runtime { /// A timestamp: milliseconds since the unix epoch. type Moment = u64; @@ -212,46 +219,119 @@ impl pallet_timestamp::Config for Runtime { type WeightInfo = (); } +parameter_types! { + pub const UncleGenerations: u32 = 0; +} + impl pallet_authorship::Config for Runtime { type FindAuthor = pallet_session::FindAccountFromAuthorIndex; - type EventHandler = (ParachainStaking,); + type EventHandler = ParachainStaking; +} + +parameter_types! { + pub const MaxLocks: u32 = 50; + pub const MaxReserves: u32 = 50; + pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT; + } impl pallet_balances::Config for Runtime { + /// The type for recording an account's balance. type Balance = Balance; type DustRemoval = Treasury; + /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; + type WeightInfo = pallet_balances::weights::SubstrateWeight; type MaxLocks = MaxLocks; type MaxReserves = MaxReserves; type ReserveIdentifier = BondType; - type WeightInfo = (); } +/// Logic for the author to get a portion of fees. +pub struct ToAuthor(sp_std::marker::PhantomData); + +impl OnUnbalanced> for ToAuthor +where + R: pallet_balances::Config + pallet_authorship::Config, + ::AccountId: From, + ::AccountId: Into, + ::Balance: Into, +{ + fn on_nonzero_unbalanced(amount: NegativeImbalanceOf) { + if let Some(author) = >::author() { + >::resolve_creating(&author, amount); + } + } +} + +/// Split two Imbalances between two unbalanced handlers. +/// The first Imbalance will be split according to the given ratio. The second +/// Imbalance will be handled by the second beneficiary. +/// +/// In case of transaction payment, the first Imbalance is the fee and the +/// second imbalance the tip. +pub struct SplitFeesByRatio( + sp_std::marker::PhantomData<(R, Ratio, Beneficiary1, Beneficiary2)>, +); +impl OnUnbalanced> + for SplitFeesByRatio +where + R: pallet_balances::Config, + Beneficiary1: OnUnbalanced>, + Beneficiary2: OnUnbalanced>, + Ratio: Get<(u32, u32)>, +{ + fn on_unbalanceds(mut fees_then_tips: impl Iterator>) { + let ratio = Ratio::get(); + if let Some(fees) = fees_then_tips.next() { + let mut split = fees.ration(ratio.0, ratio.1); + if let Some(tips) = fees_then_tips.next() { + // for tips, if any, 100% to author + tips.merge_into(&mut split.1); + } + Beneficiary1::on_unbalanced(split.0); + Beneficiary2::on_unbalanced(split.1); + } + } +} + +parameter_types! { + /// Relay Chain `TransactionByteFee` / 10 + pub const TransactionByteFee: Balance = 10 * MICRO_PLMC; + pub const OperationalFeeMultiplier: u8 = 5; + pub const FeeSplitRatio: (u32, u32) = (50, 50); +} + +/// Split the fees using a preconfigured Ratio +pub type FeeSplit = SplitFeesByRatio; + impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; - type OperationalFeeMultiplier = frame_support::traits::ConstU8<5>; - type WeightToFee = WeightToFee; + type OnChargeTransaction = + pallet_transaction_payment::CurrencyAdapter>>; + type WeightToFee = WeightToFee; type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type OperationalFeeMultiplier = OperationalFeeMultiplier; } impl pallet_asset_tx_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Fungibles = StatemintAssets; type OnChargeAssetTransaction = pallet_asset_tx_payment::FungiblesAdapter< - pallet_assets::BalanceToAssetBalance< - Balances, - Runtime, - ConvertInto, - StatemintAssetsInstance, - >, + pallet_assets::BalanceToAssetBalance, xcm_config::AssetsToBlockAuthor, >; } +parameter_types! { + pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); + pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); +} + +// TODO: On Testnet only impl pallet_sudo::Config for Runtime { type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; @@ -291,6 +371,12 @@ impl cumulus_pallet_dmp_queue::Config for Runtime { type ExecuteOverweightOrigin = EnsureRoot; } +parameter_types! { + pub const Period: BlockNumber = 6 * HOURS; + pub const Offset: BlockNumber = 0; + pub const MaxAuthorities: u32 = 100_000; +} + impl pallet_session::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ValidatorId = ::AccountId; @@ -305,12 +391,117 @@ impl pallet_session::Config for Runtime { impl pallet_aura::Config for Runtime { type AuthorityId = AuraId; + // TODO: handle disabled validators type DisabledValidators = (); type MaxAuthorities = MaxAuthorities; } +parameter_types! { + /// Minimum round length is 1 hour + pub const MinBlocksPerRound: BlockNumber = MIN_BLOCKS_PER_ROUND; + /// Default length of a round/session is 2 hours + pub const DefaultBlocksPerRound: BlockNumber = DEFAULT_BLOCKS_PER_ROUND; + /// Unstaked balance can be unlocked after 7 days + pub const StakeDuration: BlockNumber = STAKE_DURATION; + /// Collator exit requests are delayed by 4 hours (2 rounds/sessions) + pub const ExitQueueDelay: u32 = 2; + /// Minimum 16 collators selected per round, default at genesis and minimum forever after + pub const MinCollators: u32 = MIN_COLLATORS; + /// At least 4 candidates which cannot leave the network if there are no other candidates. + pub const MinRequiredCollators: u32 = 4; + /// We only allow one delegation per round. + pub const MaxDelegationsPerRound: u32 = 1; + /// Maximum 25 delegators per collator at launch, might be increased later + #[derive(Debug, Eq, PartialEq)] + pub const MaxDelegatorsPerCollator: u32 = MAX_DELEGATORS_PER_COLLATOR; + /// Minimum stake required to be reserved to be a collator is 10_000 + pub const MinCollatorStake: Balance = 10_000 * PLMC; + /// Minimum stake required to be reserved to be a delegator is 1000 + pub const MinDelegatorStake: Balance = MIN_DELEGATOR_STAKE; + /// Maximum number of collator candidates + #[derive(Debug, Eq, PartialEq)] + pub const MaxCollatorCandidates: u32 = MAX_CANDIDATES; + /// Maximum number of concurrent requests to unlock unstaked balance + pub const MaxUnstakeRequests: u32 = 10; + /// The starting block number for the network rewards + pub const NetworkRewardStart: BlockNumber = INITIAL_PERIOD_LENGTH; + /// The rate in percent for the network rewards + pub const NetworkRewardRate: Perquintill = NETWORK_REWARD_RATE; +} + +impl parachain_staking::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type CurrencyBalance = Balance; + type MinBlocksPerRound = MinBlocksPerRound; + type DefaultBlocksPerRound = DefaultBlocksPerRound; + type StakeDuration = StakeDuration; + type ExitQueueDelay = ExitQueueDelay; + type MinCollators = MinCollators; + type MinRequiredCollators = MinRequiredCollators; + type MaxDelegationsPerRound = MaxDelegationsPerRound; + type MaxDelegatorsPerCollator = MaxDelegatorsPerCollator; + type MinCollatorStake = MinCollatorStake; + type MinCollatorCandidateStake = MinCollatorStake; + type MaxTopCandidates = MaxCollatorCandidates; + type MinDelegatorStake = MinDelegatorStake; + type MaxUnstakeRequests = MaxUnstakeRequests; + type NetworkRewardRate = NetworkRewardRate; + type NetworkRewardStart = NetworkRewardStart; + type NetworkRewardBeneficiary = Treasury; + type WeightInfo = (); + + const BLOCKS_PER_YEAR: Self::BlockNumber = BLOCKS_PER_YEAR; +} + impl pallet_insecure_randomness_collective_flip::Config for Runtime {} +#[cfg(feature = "fast-gov")] +pub const EVALUATION_DURATION: BlockNumber = 28; +#[cfg(not(feature = "fast-gov"))] +pub const EVALUATION_DURATION: BlockNumber = 28 * DAYS; + +#[cfg(feature = "fast-gov")] +pub const AUCTION_INITIALIZE_PERIOD_DURATION: BlockNumber = 7; +#[cfg(not(feature = "fast-gov"))] +pub const AUCTION_INITIALIZE_PERIOD_DURATION: BlockNumber = 7 * DAYS; + +#[cfg(feature = "fast-gov")] +pub const ENGLISH_AUCTION_DURATION: BlockNumber = 10; +#[cfg(not(feature = "fast-gov"))] +pub const ENGLISH_AUCTION_DURATION: BlockNumber = 2 * DAYS; + +#[cfg(feature = "fast-gov")] +pub const CANDLE_AUCTION_DURATION: BlockNumber = 5; +#[cfg(not(feature = "fast-gov"))] +pub const CANDLE_AUCTION_DURATION: BlockNumber = 3 * DAYS; + +#[cfg(feature = "fast-gov")] +pub const COMMUNITY_FUNDING_DURATION: BlockNumber = 10; +#[cfg(not(feature = "fast-gov"))] +pub const COMMUNITY_FUNDING_DURATION: BlockNumber = 5 * DAYS; + +#[cfg(feature = "fast-gov")] +pub const REMAINDER_FUNDING_DURATION: BlockNumber = 10; +#[cfg(not(feature = "fast-gov"))] +pub const REMAINDER_FUNDING_DURATION: BlockNumber = 1 * DAYS; + +#[cfg(feature = "fast-gov")] +pub const CONTRIBUTION_VESTING_DURATION: BlockNumber = 365; +#[cfg(not(feature = "fast-gov"))] +pub const CONTRIBUTION_VESTING_DURATION: BlockNumber = 365 * DAYS; + +parameter_types! { + pub const EvaluationDuration: BlockNumber = EVALUATION_DURATION; + pub const AuctionInitializePeriodDuration: BlockNumber = AUCTION_INITIALIZE_PERIOD_DURATION; + pub const EnglishAuctionDuration: BlockNumber = ENGLISH_AUCTION_DURATION; + pub const CandleAuctionDuration: BlockNumber = CANDLE_AUCTION_DURATION; + pub const CommunityFundingDuration: BlockNumber = COMMUNITY_FUNDING_DURATION; + pub const RemainderFundingDuration: BlockNumber = REMAINDER_FUNDING_DURATION; + pub const ContributionVestingDuration: BlockNumber = CONTRIBUTION_VESTING_DURATION; + pub const FundingPalletId: PalletId = PalletId(*b"py/cfund"); +} + impl pallet_funding::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ProjectIdentifier = u32; @@ -322,6 +513,7 @@ impl pallet_funding::Config for Runtime { type ContributionTokenCurrency = LocalAssets; type BidId = u128; type Randomness = Random; + type HandleMembers = Credentials; type StringLimit = ConstU32<64>; type PreImageLimit = ConstU32<1024>; type EvaluationDuration = EvaluationDuration; @@ -338,7 +530,32 @@ impl pallet_funding::Config for Runtime { type ContributionVesting = ContributionVestingDuration; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); - type WeightInfo = (); + type WeightInfo = weights::pallet_funding::WeightInfo; +} + +impl pallet_credentials::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 = (); +} + +#[cfg(feature = "fast-gov")] +pub const SPEND_PERIOD: BlockNumber = 6 * MINUTES; +#[cfg(not(feature = "fast-gov"))] +pub const SPEND_PERIOD: BlockNumber = 6 * DAYS; + +parameter_types! { + pub const ProposalBond: Permill = Permill::from_percent(5); + pub const ProposalBondMinimum: Balance = 20 * PLMC; + pub const SpendPeriod: BlockNumber = SPEND_PERIOD; + pub const Burn: Permill = Permill::zero(); + pub const MaxApprovals: u32 = 100; + pub const TreasuryPalletId: PalletId = PalletId(*b"politrea"); } impl pallet_treasury::Config for Runtime { @@ -353,7 +570,7 @@ impl pallet_treasury::Config for Runtime { type ProposalBondMaximum = (); type SpendPeriod = SpendPeriod; type Burn = Burn; - type PalletId = TreasuryId; + type PalletId = TreasuryPalletId; type BurnDestination = (); type WeightInfo = (); type SpendFunds = (); @@ -361,6 +578,12 @@ impl pallet_treasury::Config for Runtime { type SpendOrigin = frame_support::traits::NeverEnsureOrigin; } +parameter_types! { + pub const CouncilMotionDuration: BlockNumber = 5 * DAYS; + pub const CouncilMaxProposals: u32 = 100; + pub const CouncilMaxMembers: u32 = 100; +} + // TODO: VERY BASIC implementation, more work needed type CouncilCollective = pallet_collective::Instance1; impl pallet_collective::Config for Runtime { @@ -375,6 +598,12 @@ impl pallet_collective::Config for Runtime { type SetMembersOrigin = EnsureRoot; } +parameter_types! { + pub const TechnicalMotionDuration: BlockNumber = 5 * DAYS; + pub const TechnicalMaxProposals: u32 = 100; + pub const TechnicalMaxMembers: u32 = 100; +} + type TechnicalCollective = pallet_collective::Instance2; impl pallet_collective::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; @@ -408,24 +637,18 @@ impl pallet_democracy::Config for Runtime { type MaxDeposits = (); type MaxBlacklisted = (); /// A straight majority of the council can decide what their next motion is. - type ExternalOrigin = - pallet_collective::EnsureProportionAtLeast; + type ExternalOrigin = pallet_collective::EnsureProportionAtLeast; /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. - type ExternalMajorityOrigin = - pallet_collective::EnsureProportionAtLeast; + type ExternalMajorityOrigin = pallet_collective::EnsureProportionAtLeast; /// A unanimous council can have the next scheduled referendum be a straight default-carries /// (NTB) vote. - type ExternalDefaultOrigin = - pallet_collective::EnsureProportionAtLeast; + type ExternalDefaultOrigin = pallet_collective::EnsureProportionAtLeast; /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote /// be tabled immediately and with a shorter voting/enactment period. - type FastTrackOrigin = - pallet_collective::EnsureProportionAtLeast; - type InstantOrigin = - pallet_collective::EnsureProportionAtLeast; + type FastTrackOrigin = pallet_collective::EnsureProportionAtLeast; + type InstantOrigin = pallet_collective::EnsureProportionAtLeast; // To cancel a proposal which has been passed, 2/3 of the council must agree to it. - type CancellationOrigin = - pallet_collective::EnsureProportionAtLeast; + type CancellationOrigin = pallet_collective::EnsureProportionAtLeast; type BlacklistOrigin = EnsureRoot; // To cancel a proposal before it has been passed, the technical committee must be unanimous or // Root must agree. @@ -441,6 +664,11 @@ impl pallet_democracy::Config for Runtime { type SubmitOrigin = EnsureSigned; } +parameter_types! { + pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * RuntimeBlockWeights::get().max_block; + pub const MaxScheduledPerBlock: u32 = 50; +} + impl pallet_scheduler::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; @@ -461,6 +689,22 @@ impl pallet_utility::Config for Runtime { type WeightInfo = (); } +pub const fn deposit(items: u32, bytes: u32) -> Balance { + items as Balance * 15 * MICRO_PLMC + (bytes as Balance) * 6 * MICRO_PLMC +} + +pub const fn free_deposit() -> Balance { + 0 * MICRO_PLMC +} + +parameter_types! { + // One storage item; key size is 32; value is size 4+4+16+32 bytes = 56 bytes. + pub const DepositBase: Balance = deposit(1, 88); + // Additional storage item size of 32 bytes. + pub const DepositFactor: Balance = deposit(0, 32); + pub const MaxSignatories: u16 = 100; +} + impl pallet_multisig::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeCall = RuntimeCall; @@ -480,6 +724,18 @@ impl pallet_preimage::Config for Runtime { type ByteDeposit = (); } +parameter_types! { + pub const AssetDeposit: Balance = PLMC; // 1 UNIT deposit to create asset + pub const ApprovalDeposit: Balance = EXISTENTIAL_DEPOSIT; + pub const AssetAccountDeposit: Balance = deposit(1, 16); + pub const AssetsStringLimit: u32 = 50; + /// Key = 32 bytes, Value = 36 bytes (32+1+1+1+1) + // https://github.com/paritytech/substrate/blob/069917b/frame/assets/src/lib.rs#L257L271 + pub const MetadataDepositBase: Balance = free_deposit(); + pub const MetadataDepositPerByte: Balance = free_deposit(); + pub const AssetsPalletId: PalletId = PalletId(*b"assetsid"); +} + pub type LocalAssetsInstance = pallet_assets::Instance1; pub type StatemintAssetsInstance = pallet_assets::Instance2; @@ -496,7 +752,7 @@ impl pallet_assets::Config for Runtime { type AssetAccountDeposit = AssetAccountDeposit; type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type ApprovalDeposit = ExistentialDeposit; + type ApprovalDeposit = ApprovalDeposit; type StringLimit = AssetsStringLimit; type Freezer = (); type Extra = (); @@ -519,7 +775,7 @@ impl pallet_assets::Config for Runtime { type AssetAccountDeposit = AssetAccountDeposit; type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type ApprovalDeposit = ExistentialDeposit; + type ApprovalDeposit = ApprovalDeposit; type StringLimit = AssetsStringLimit; type Freezer = (); type Extra = (); @@ -529,41 +785,33 @@ impl pallet_assets::Config for Runtime { type BenchmarkHelper = (); } +impl pallet_asset_registry::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type ReserveAssetModifierOrigin = frame_system::EnsureRoot; + type Assets = StatemintAssets; + type WeightInfo = (); +} + impl pallet_vesting::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Currency = Balances; type BlockNumberToBalance = ConvertInto; - type MinVestedTransfer = MinVestedTransfer; + type MinVestedTransfer = runtime_common::constants::MinVestedTransfer; type WeightInfo = pallet_vesting::weights::SubstrateWeight; - type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; + type UnvestedFundsAllowedWithdrawReasons = runtime_common::constants::UnvestedFundsAllowedWithdrawReasons; // `VestingInfo` encode length is 36bytes. 28 schedules gets encoded as 1009 bytes, which is the // highest number of schedules that encodes less than 2^10. const MAX_VESTING_SCHEDULES: u32 = 28; } -impl pallet_parachain_staking::Config for Runtime { - type RuntimeEvent = RuntimeEvent; +impl pallet_did_lookup::Config for Runtime { type Currency = Balances; - type MonetaryGovernanceOrigin = frame_system::EnsureRoot; - type MinBlocksPerRound = MinBlocksPerRound; - type LeaveCandidatesDelay = LeaveCandidatesDelay; - type CandidateBondLessDelay = CandidateBondLessDelay; - type LeaveDelegatorsDelay = LeaveDelegatorsDelay; - type RevokeDelegationDelay = RevokeDelegationDelay; - type DelegationBondLessDelay = DelegationBondLessDelay; - type RewardPaymentDelay = RewardPaymentDelay; - type MinSelectedCandidates = MinSelectedCandidates; - type MaxTopDelegationsPerCandidate = MaxTopDelegationsPerCandidate; - type MaxBottomDelegationsPerCandidate = MaxBottomDelegationsPerCandidate; - type MaxDelegationsPerDelegator = MaxDelegationsPerDelegator; - type MinCandidateStk = MinCandidateStk; - type MinDelegatorStk = MinDelegatorStk; - type MinDelegation = MinDelegation; - type OnCollatorPayout = (); - // We use the default implementation, so we leave () here. - type PayoutCollatorReward = (); - type OnNewRound = (); - type WeightInfo = pallet_parachain_staking::weights::SubstrateWeight; + type Deposit = DepositBase; + type DidIdentifier = DidIdentifier; + type EnsureOrigin = EnsureDipOrigin>; + type OriginSuccess = DipOrigin>; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); } // Create the runtime by composing the FRAME pallets that were previously configured. @@ -586,15 +834,17 @@ construct_runtime!( AssetTxPayment: pallet_asset_tx_payment::{Pallet, Storage, Event} = 12, LocalAssets: pallet_assets::::{Pallet, Call, Storage, Event} = 13, StatemintAssets: pallet_assets::::{Pallet, Call, Storage, Event} = 14, + AssetRegistry: pallet_asset_registry::{Pallet, Call, Storage, Event} = 15, Vesting: pallet_vesting::{Pallet, Call, Storage, Event, Config} = 16, - // Collator support. the order of these 5 are important and shall not change. + // Consensus support. + // The following order MUST NOT be changed: Aura -> Session -> Staking -> Authorship -> AuraExt + // Dependencies: AuraExt on Aura, Authorship and Session on ParachainStaking + Aura: pallet_aura = 23, + Session: pallet_session = 22, + ParachainStaking: parachain_staking = 21, Authorship: pallet_authorship::{Pallet, Storage} = 20, - Session: pallet_session::{Pallet, Call, Storage, Event, Config} = 22, - Aura: pallet_aura::{Pallet, Storage, Config} = 23, - AuraExt: cumulus_pallet_aura_ext::{Pallet, Storage, Config} = 24, - ParachainStaking: pallet_parachain_staking::{Pallet, Call, Storage, Event, Config} = 25, - + AuraExt: cumulus_pallet_aura_ext = 24, // Governance Treasury: pallet_treasury = 40, @@ -604,7 +854,10 @@ construct_runtime!( Preimage: pallet_preimage::{Pallet, Call, Storage, Event} = 44, // Polimec Core + DipConsumer: pallet_dip_consumer = 50, + DidLookup: pallet_did_lookup = 51, PolimecFunding: pallet_funding::{Pallet, Call, Storage, Event} = 52, + Credentials: pallet_credentials = 53, // Utilities Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event} = 61, @@ -855,20 +1108,18 @@ struct CheckInherents; impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { fn check_inherents( - block: &Block, - relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, + block: &Block, relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, ) -> sp_inherents::CheckInherentsResult { let relay_chain_slot = relay_state_proof .read_slot() .expect("Could not read the relay chain slot from the proof"); - let inherent_data = - cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( - relay_chain_slot, - sp_std::time::Duration::from_secs(6), - ) - .create_inherent_data() - .expect("Could not create the timestamp inherent data"); + let inherent_data = cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( + relay_chain_slot, + sp_std::time::Duration::from_secs(6), + ) + .create_inherent_data() + .expect("Could not create the timestamp inherent data"); inherent_data.check_extrinsics(block) } diff --git a/runtimes/testnet/src/weights/block_weights.rs b/runtimes/testnet/src/weights/block_weights.rs new file mode 100644 index 000000000..f5dcc6ac2 --- /dev/null +++ b/runtimes/testnet/src/weights/block_weights.rs @@ -0,0 +1,53 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see .erning permissions and +// limitations under the License. + +pub mod constants { + use frame_support::{ + parameter_types, + weights::{constants, Weight}, + }; + + parameter_types! { + /// Importing a block with 0 Extrinsics. + pub const BlockExecutionWeight: Weight = + Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(5_000_000)); + } + + #[cfg(test)] + mod test_weights { + use frame_support::weights::constants; + + /// Checks that the weight exists and is sane. + // NOTE: If this test fails but you are sure that the generated values are fine, + // you can delete it. + #[test] + fn sane() { + let w = super::constants::BlockExecutionWeight::get(); + + // At least 100 µs. + assert!( + w.ref_time() >= 100u64 * constants::WEIGHT_REF_TIME_PER_MICROS, + "Weight should be at least 100 µs." + ); + // At most 50 ms. + assert!( + w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, + "Weight should be at most 50 ms." + ); + } + } +} diff --git a/runtimes/testnet/src/weights/extrinsic_weights.rs b/runtimes/testnet/src/weights/extrinsic_weights.rs new file mode 100644 index 000000000..0819bab8a --- /dev/null +++ b/runtimes/testnet/src/weights/extrinsic_weights.rs @@ -0,0 +1,52 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +pub mod constants { + use frame_support::{ + parameter_types, + weights::{constants, Weight}, + }; + + parameter_types! { + /// Executing a NO-OP `System::remarks` Extrinsic. + pub const ExtrinsicBaseWeight: Weight = + Weight::from_ref_time(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(125_000)); + } + + #[cfg(test)] + mod test_weights { + use frame_support::weights::constants; + + /// Checks that the weight exists and is sane. + // NOTE: If this test fails but you are sure that the generated values are fine, + // you can delete it. + #[test] + fn sane() { + let w = super::constants::ExtrinsicBaseWeight::get(); + + // At least 10 µs. + assert!( + w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, + "Weight should be at least 10 µs." + ); + // At most 1 ms. + assert!( + w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, + "Weight should be at most 1 ms." + ); + } + } +} diff --git a/runtimes/shared-configuration/src/assets.rs b/runtimes/testnet/src/weights/mod.rs similarity index 59% rename from runtimes/shared-configuration/src/assets.rs rename to runtimes/testnet/src/weights/mod.rs index 6568a765b..40ae41d0a 100644 --- a/runtimes/shared-configuration/src/assets.rs +++ b/runtimes/testnet/src/weights/mod.rs @@ -14,18 +14,15 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::{ - currency::{deposit, PLMC}, - Balance, -}; -use frame_support::parameter_types; +//! Expose the auto generated weight files. -parameter_types! { - pub const AssetDeposit: Balance = 10 * PLMC; - pub const AssetsStringLimit: u32 = 50; - /// Key = 32 bytes, Value = 36 bytes (32+1+1+1+1) - // https://github.com/paritytech/substrate/blob/069917b/frame/assets/src/lib.rs#L257L271 - pub const MetadataDepositBase: Balance = deposit(1, 68); - pub const MetadataDepositPerByte: Balance = deposit(0, 1); - pub const AssetAccountDeposit: Balance = deposit(1, 18); -} +pub mod block_weights; +pub mod extrinsic_weights; +pub mod pallet_funding; +pub mod paritydb_weights; +pub mod rocksdb_weights; + +pub use block_weights::constants::BlockExecutionWeight; +pub use extrinsic_weights::constants::ExtrinsicBaseWeight; +pub use paritydb_weights::constants::ParityDbWeight; +pub use rocksdb_weights::constants::RocksDbWeight; diff --git a/runtimes/testnet/src/weights/pallet_funding.rs b/runtimes/testnet/src/weights/pallet_funding.rs new file mode 100644 index 000000000..50c79d7b7 --- /dev/null +++ b/runtimes/testnet/src/weights/pallet_funding.rs @@ -0,0 +1,202 @@ + +//! Autogenerated weights for `pallet_funding` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-03-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `pop-os`, CPU: `13th Gen Intel(R) Core(TM) i9-13900K` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// target/release/polimec-standalone-node +// benchmark +// pallet +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_funding +// --extrinsic +// * +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=runtimes/testnet/src/weights/pallet_funding.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use sp_std::marker::PhantomData; + +/// Weight functions for `pallet_funding`. +pub struct WeightInfo(PhantomData); +impl pallet_funding::WeightInfo for WeightInfo { + /// Storage: PolimecFunding Images (r:0 w:1) + /// Proof Skipped: PolimecFunding Images (max_values: None, max_size: None, mode: Measured) + fn note_image() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 5_860 nanoseconds. + Weight::from_ref_time(6_343_000) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: PolimecFunding Images (r:1 w:0) + /// Proof Skipped: PolimecFunding Images (max_values: None, max_size: None, mode: Measured) + /// Storage: PolimecFunding NextProjectId (r:1 w:1) + /// Proof Skipped: PolimecFunding NextProjectId (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolimecFunding Projects (r:0 w:1) + /// Proof Skipped: PolimecFunding Projects (max_values: None, max_size: None, mode: Measured) + /// Storage: PolimecFunding ProjectsInfo (r:0 w:1) + /// Proof Skipped: PolimecFunding ProjectsInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: PolimecFunding ProjectsIssuers (r:0 w:1) + /// Proof Skipped: PolimecFunding ProjectsIssuers (max_values: None, max_size: None, mode: Measured) + fn create() -> Weight { + // Proof Size summary in bytes: + // Measured: `111` + // Estimated: `3525` + // Minimum execution time: 13_134 nanoseconds. + Weight::from_parts(13_798_000, 3525) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: PolimecFunding ProjectsIssuers (r:1 w:0) + /// Proof Skipped: PolimecFunding ProjectsIssuers (max_values: None, max_size: None, mode: Measured) + /// Storage: PolimecFunding ProjectsInfo (r:1 w:1) + /// Proof Skipped: PolimecFunding ProjectsInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: PolimecFunding ProjectsActive (r:1 w:1) + /// Proof Skipped: PolimecFunding ProjectsActive (max_values: Some(1), max_size: None, mode: Measured) + fn start_evaluation() -> Weight { + // Proof Size summary in bytes: + // Measured: `207` + // Estimated: `6066` + // Minimum execution time: 12_306 nanoseconds. + Weight::from_parts(12_756_000, 6066) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: PolimecFunding ProjectsIssuers (r:1 w:0) + /// Proof Skipped: PolimecFunding ProjectsIssuers (max_values: None, max_size: None, mode: Measured) + /// Storage: PolimecFunding ProjectsInfo (r:1 w:0) + /// Proof Skipped: PolimecFunding ProjectsInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: PolimecFunding Bonds (r:1 w:1) + /// Proof Skipped: PolimecFunding Bonds (max_values: None, max_size: None, mode: Measured) + /// Storage: Balances Locks (r:1 w:1) + /// Proof: Balances Locks (max_values: None, max_size: Some(1299), added: 3774, mode: MaxEncodedLen) + fn bond() -> Weight { + // Proof Size summary in bytes: + // Measured: `370` + // Estimated: `14912` + // Minimum execution time: 19_568 nanoseconds. + Weight::from_parts(19_897_000, 14912) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: PolimecFunding ProjectsIssuers (r:1 w:0) + /// Proof Skipped: PolimecFunding ProjectsIssuers (max_values: None, max_size: None, mode: Measured) + /// Storage: PolimecFunding Images (r:1 w:0) + /// Proof Skipped: PolimecFunding Images (max_values: None, max_size: None, mode: Measured) + /// Storage: PolimecFunding ProjectsInfo (r:1 w:0) + /// Proof Skipped: PolimecFunding ProjectsInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: PolimecFunding Projects (r:1 w:1) + /// Proof Skipped: PolimecFunding Projects (max_values: None, max_size: None, mode: Measured) + fn edit_metadata() -> Weight { + // Proof Size summary in bytes: + // Measured: `454` + // Estimated: `11716` + // Minimum execution time: 14_476 nanoseconds. + Weight::from_parts(15_071_000, 11716) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: PolimecFunding ProjectsIssuers (r:1 w:0) + /// Proof Skipped: PolimecFunding ProjectsIssuers (max_values: None, max_size: None, mode: Measured) + /// Storage: PolimecFunding ProjectsInfo (r:1 w:1) + /// Proof Skipped: PolimecFunding ProjectsInfo (max_values: None, max_size: None, mode: Measured) + fn start_auction() -> Weight { + // Proof Size summary in bytes: + // Measured: `268` + // Estimated: `5486` + // Minimum execution time: 13_427 nanoseconds. + Weight::from_parts(13_815_000, 5486) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: PolimecFunding ProjectsIssuers (r:1 w:0) + /// Proof Skipped: PolimecFunding ProjectsIssuers (max_values: None, max_size: None, mode: Measured) + /// Storage: PolimecFunding ProjectsInfo (r:1 w:0) + /// Proof Skipped: PolimecFunding ProjectsInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: PolimecFunding Projects (r:1 w:0) + /// Proof Skipped: PolimecFunding Projects (max_values: None, max_size: None, mode: Measured) + /// Storage: PolimecFunding AuctionsInfo (r:1 w:1) + /// Proof Skipped: PolimecFunding AuctionsInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + fn bid() -> Weight { + // Proof Size summary in bytes: + // Measured: `633` + // Estimated: `15035` + // Minimum execution time: 25_578 nanoseconds. + Weight::from_parts(26_100_000, 15035) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: PolimecFunding ProjectsIssuers (r:1 w:0) + /// Proof Skipped: PolimecFunding ProjectsIssuers (max_values: None, max_size: None, mode: Measured) + /// Storage: PolimecFunding ProjectsInfo (r:1 w:0) + /// Proof Skipped: PolimecFunding ProjectsInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: System Account (r:2 w:2) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + /// Storage: PolimecFunding Contributions (r:1 w:1) + /// Proof Skipped: PolimecFunding Contributions (max_values: None, max_size: None, mode: Measured) + fn contribute() -> Weight { + // Proof Size summary in bytes: + // Measured: `474` + // Estimated: `14053` + // Minimum execution time: 30_643 nanoseconds. + Weight::from_parts(31_201_000, 14053) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: PolimecFunding ProjectsInfo (r:1 w:0) + /// Proof Skipped: PolimecFunding ProjectsInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: PolimecFunding Contributions (r:1 w:1) + /// Proof Skipped: PolimecFunding Contributions (max_values: None, max_size: None, mode: Measured) + /// Storage: Assets Asset (r:1 w:1) + /// Proof: Assets Asset (max_values: None, max_size: Some(210), added: 2685, mode: MaxEncodedLen) + /// Storage: Assets Account (r:1 w:1) + /// Proof: Assets Account (max_values: None, max_size: Some(102), added: 2577, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + fn claim_contribution_tokens() -> Weight { + // Proof Size summary in bytes: + // Measured: `877` + // Estimated: `14569` + // Minimum execution time: 26_228 nanoseconds. + Weight::from_parts(27_498_000, 14569) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: PolimecFunding ProjectsActive (r:1 w:0) + /// Proof Skipped: PolimecFunding ProjectsActive (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolimecFunding ProjectsInfo (r:100 w:100) + /// Proof Skipped: PolimecFunding ProjectsInfo (max_values: None, max_size: None, mode: Measured) + /// Storage: PolimecFunding Bonds (r:200 w:0) + /// Proof Skipped: PolimecFunding Bonds (max_values: None, max_size: None, mode: Measured) + fn on_initialize() -> Weight { + // Proof Size summary in bytes: + // Measured: `15727` + // Estimated: `790176` + // Minimum execution time: 1_279_152 nanoseconds. + Weight::from_parts(1_286_826_000, 790176) + .saturating_add(T::DbWeight::get().reads(301)) + .saturating_add(T::DbWeight::get().writes(100)) + } + + fn failed_evaluation_unbond_for() -> Weight { + Weight::from_ref_time(1_000_000) + } +} diff --git a/runtimes/testnet/src/weights/paritydb_weights.rs b/runtimes/testnet/src/weights/paritydb_weights.rs new file mode 100644 index 000000000..8f380e07a --- /dev/null +++ b/runtimes/testnet/src/weights/paritydb_weights.rs @@ -0,0 +1,62 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +pub mod constants { + use frame_support::{ + parameter_types, + weights::{constants, RuntimeDbWeight}, + }; + + parameter_types! { + /// `ParityDB` can be enabled with a feature flag, but is still experimental. These weights + /// are available for brave runtime engineers who may want to try this out as default. + pub const ParityDbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 8_000 * constants::WEIGHT_REF_TIME_PER_NANOS, + write: 50_000 * constants::WEIGHT_REF_TIME_PER_NANOS, + }; + } + + #[cfg(test)] + mod test_db_weights { + use super::constants::ParityDbWeight as W; + use frame_support::weights::constants; + + /// Checks that all weights exist and have sane values. + // NOTE: If this test fails but you are sure that the generated values are fine, + // you can delete it. + #[test] + fn sane() { + // At least 1 µs. + assert!( + W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, + "Read weight should be at least 1 µs." + ); + assert!( + W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, + "Write weight should be at least 1 µs." + ); + // At most 1 ms. + assert!( + W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, + "Read weight should be at most 1 ms." + ); + assert!( + W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, + "Write weight should be at most 1 ms." + ); + } + } +} diff --git a/runtimes/testnet/src/weights/rocksdb_weights.rs b/runtimes/testnet/src/weights/rocksdb_weights.rs new file mode 100644 index 000000000..d7e720f64 --- /dev/null +++ b/runtimes/testnet/src/weights/rocksdb_weights.rs @@ -0,0 +1,62 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +pub mod constants { + use frame_support::{ + parameter_types, + weights::{constants, RuntimeDbWeight}, + }; + + parameter_types! { + /// By default, Substrate uses `RocksDB`, so this will be the weight used throughout + /// the runtime. + pub const RocksDbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 25_000 * constants::WEIGHT_REF_TIME_PER_NANOS, + write: 100_000 * constants::WEIGHT_REF_TIME_PER_NANOS, + }; + } + + #[cfg(test)] + mod test_db_weights { + use super::constants::RocksDbWeight as W; + use frame_support::weights::constants; + + /// Checks that all weights exist and have sane values. + // NOTE: If this test fails but you are sure that the generated values are fine, + // you can delete it. + #[test] + fn sane() { + // At least 1 µs. + assert!( + W::get().reads(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, + "Read weight should be at least 1 µs." + ); + assert!( + W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, + "Write weight should be at least 1 µs." + ); + // At most 1 ms. + assert!( + W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, + "Read weight should be at most 1 ms." + ); + assert!( + W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, + "Write weight should be at most 1 ms." + ); + } + } +} diff --git a/runtimes/testnet/src/xcm_config.rs b/runtimes/testnet/src/xcm_config.rs index b450763d1..5aa13b359 100644 --- a/runtimes/testnet/src/xcm_config.rs +++ b/runtimes/testnet/src/xcm_config.rs @@ -39,13 +39,11 @@ use polkadot_runtime_common::impls::ToAuthor; use sp_runtime::traits::Zero; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, - AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, - ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, - FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, ParentIsPreset, RelayChainAsNative, - SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, - SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, - WithComputedOrigin, + AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, AsPrefixedGeneralIndex, ConvertedConcreteId, CurrencyAdapter, EnsureXcmOrigin, + FixedRateOfFungible, FixedWeightBounds, FungiblesAdapter, IsConcrete, LocalMint, NativeAsset, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, WithComputedOrigin, }; use xcm_executor::{ traits::{Convert, Error, JustTry, MatchesFungibles}, @@ -53,9 +51,8 @@ use xcm_executor::{ }; use super::{ - AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Balance, Balances, - ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, - StatemintAssets, WeightToFee, XcmpQueue, + AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Balance, Balances, ParachainInfo, ParachainSystem, + PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, StatemintAssets, WeightToFee, XcmpQueue, }; const DOT_ASSET_ID: AssetId = Concrete(RelayLocation::get()); @@ -124,13 +121,19 @@ pub struct NativeToFungible; impl Convert for NativeToFungible { fn convert(asset: MultiLocation) -> Result { match asset { - MultiLocation { parents: 1, interior: Here } => Ok(AssetIdPalletAssets::from(0u32)), + MultiLocation { + parents: 1, + interior: Here, + } => Ok(AssetIdPalletAssets::from(0u32)), _ => Err(asset), } } fn reverse(value: AssetIdPalletAssets) -> Result { if value == AssetIdPalletAssets::from(0u32) { - Ok(MultiLocation { parents: 1, interior: Here }) + Ok(MultiLocation { + parents: 1, + interior: Here, + }) } else { Err(value) } @@ -151,10 +154,8 @@ impl< for NonBlockingConvertedConcreteId { fn matches_fungibles(a: &MultiAsset) -> Result<(AssetId, Balance), Error> { - ConvertedConcreteId::::matches_fungibles( - a, - ) - .map_err(|_| Error::AssetNotFound) + ConvertedConcreteId::::matches_fungibles(a) + .map_err(|_| Error::AssetNotFound) } } @@ -175,8 +176,7 @@ pub type StatemintDotTransactor = FungiblesAdapter< >; /// Means for transacting assets on this chain. -pub type AssetTransactors = - (CurrencyTransactor, StatemintDotTransactor, StatemintFungiblesTransactor); +pub type AssetTransactors = (CurrencyTransactor, StatemintDotTransactor, StatemintFungiblesTransactor); /// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, /// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can @@ -228,10 +228,7 @@ pub type Barrier = DenyThenTry< // If the message is one that immediately attemps to pay for execution, then allow it. AllowTopLevelPaidExecutionFrom, // Common Good Assets parachain, parent and its exec plurality get free execution - AllowExplicitUnpaidExecutionFrom<( - CommonGoodAssetsParachain, - ParentOrParentsExecutivePlurality, - )>, + AllowExplicitUnpaidExecutionFrom<(CommonGoodAssetsParachain, ParentOrParentsExecutivePlurality)>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, ), @@ -253,8 +250,8 @@ impl ContainsPair for StatemintAssetsFilter { // location must be the statemint parachain let loc = MultiLocation::new(1, X1(Parachain(1000))); // asset must be either a fungible asset from `pallet_assets` or the native token of the relay chain - &loc == origin && - match asset { + &loc == origin + && match asset { MultiAsset { id: Concrete(MultiLocation { @@ -264,7 +261,11 @@ impl ContainsPair for StatemintAssetsFilter { .. } => true, MultiAsset { - id: Concrete(MultiLocation { parents: 1, interior: Here }), .. + id: Concrete(MultiLocation { + parents: 1, + interior: Here, + }), + .. } => true, _ => false, @@ -275,8 +276,8 @@ impl ContainsPair for StatemintAssetsFilter { impl> ContainsPair for AssetsFrom { fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool { let loc = T::get(); - &loc == origin && - matches!(asset, MultiAsset { id: AssetId::Concrete(asset_loc), fun: Fungible(_a) } + &loc == origin + && matches!(asset, MultiAsset { id: AssetId::Concrete(asset_loc), fun: Fungible(_a) } if asset_loc.match_and_split(&loc).is_some()) } } @@ -342,7 +343,7 @@ impl ContainsPair for MultiNativeAsset { fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool { if let Some(ref reserve) = asset.reserve() { if reserve == origin { - return true + return true; } } false @@ -375,7 +376,7 @@ impl xcm_executor::Config for XcmConfig { type Weigher = FixedWeightBounds; type Trader = ( // TODO: weight to fee has to be carefully considered. For now use default - UsingComponents>, + UsingComponents, HereLocation, AccountId, Balances, ToAuthor>, FixedRateOfFungible, ); type ResponseHandler = PolkadotXcm; diff --git a/rustfmt.toml b/rustfmt.toml index 6df3a1834..402b58e25 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,24 +1,8 @@ -# Basic -hard_tabs = true -max_width = 100 -use_small_heuristics = "Max" -# Imports -imports_granularity = "Crate" -reorder_imports = true -# Consistency -newline_style = "Unix" -# Misc -chain_width = 80 -spaces_around_ranges = false -binop_separator = "Back" -reorder_impl_items = false -match_arm_leading_pipes = "Preserve" -match_arm_blocks = false -match_block_trailing_comma = true -trailing_comma = "Vertical" -trailing_semicolon = false +edition = "2021" +fn_params_layout = "Compressed" use_field_init_shorthand = true -ignore = [ - "bridges", -] -edition = "2021" \ No newline at end of file +max_width = 120 +use_small_heuristics = "Default" # This modifies `fn_call_width`, `attr_fn_like_width`, `struct_lit_width`, `struct_variant_width`, `array_width`, `chain_width`, `single_line_if_else_max_width` according to the value of `max_width` +use_try_shorthand = true +newline_style = "Unix" +hard_tabs = true \ No newline at end of file diff --git a/traits/Cargo.toml b/traits/Cargo.toml new file mode 100644 index 000000000..aa5411b7a --- /dev/null +++ b/traits/Cargo.toml @@ -0,0 +1,42 @@ +[package] +name = 'polimec-traits' +description = 'Common traits for Polimec pallets' +authors.workspace = true +documentation.workspace = true +edition.workspace = true +homepage.workspace = true +license-file.workspace = true +readme.workspace = true +repository.workspace = true +version.workspace = true + +[dependencies] +parity-scale-codec = { workspace = true, features = [ + "derive", +] } +scale-info = { workspace = true, features = ["derive"] } +serde = { workspace = true, features = ["derive"], default-features = false } +frame-benchmarking = { workspace = true, optional = true } +frame-support.workspace = true +frame-system.workspace = true +sp-std.workspace = true +sp-runtime.workspace = true + +[dev-dependencies] +sp-core.workspace = true +sp-io.workspace = true + +[features] +default = ["std"] +std = [ + "frame-benchmarking?/std", + "parity-scale-codec/std", + "sp-std/std", + "sp-runtime/std", + "frame-support/std", + "frame-system/std", + "scale-info/std", + "serde/std", +] +runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] +try-runtime = ["frame-support/try-runtime"] diff --git a/traits/src/lib.rs b/traits/src/lib.rs new file mode 100644 index 000000000..ab2269e92 --- /dev/null +++ b/traits/src/lib.rs @@ -0,0 +1,83 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use core::slice::Iter; +use frame_support::{ + pallet_prelude::{Decode, DispatchError, Encode, MaxEncodedLen, TypeInfo}, + BoundedVec, RuntimeDebug, +}; +use serde::{Deserialize, Serialize}; +use sp_std::vec::Vec; + +/// The various roles that a member can hold. +#[derive(Copy, Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen, Serialize, Deserialize)] +pub enum MemberRole { + Issuer, + Retail, + Professional, + Institutional, +} + +impl MemberRole { + pub fn iterator() -> Iter<'static, MemberRole> { + static ROLES: [MemberRole; 4] = [ + MemberRole::Issuer, + MemberRole::Retail, + MemberRole::Professional, + MemberRole::Institutional, + ]; + ROLES.iter() + } +} + +/// The various attesters on KILT. +#[derive(Copy, Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)] +pub enum Issuers { + IssuerOne, + IssuerTwo, + IssuerThree, + IssuerFour, +} + +#[derive(Copy, Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)] +pub enum Country { + Switzerland, + UnitedStates, +} + +// TODO: Set this at runtime +type MaxDomicile = frame_support::traits::ConstU32<255>; + +/// A basic "credential" representation +#[derive(Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen)] +pub struct Credential { + pub issuer: Issuers, + pub role: MemberRole, + pub domicile: BoundedVec, + pub country: Country, + // TODO: Find a way to handle the date of birth + pub date_of_birth: u32, +} + +pub trait PolimecMembers { + fn is_in(role: &MemberRole, who: &AccountId) -> bool; + fn add_member(role: &MemberRole, who: &AccountId) -> Result<(), DispatchError>; + fn initialize_members(role: &MemberRole, members: &[AccountId]); + fn get_members_of(role: &MemberRole) -> Vec; + fn get_roles_of(who: &AccountId) -> Vec; +} From 295c3dadf5c5dcc1f31a6b9d4b53d23b8fc530d3 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:50:58 +0200 Subject: [PATCH 60/80] Revert "wip" This reverts commit 485cc436035fa4285995e9ac052d0f29700da735. --- Cargo.lock | 563 +++ Cargo.toml | 11 +- pallets/asset-registry/Cargo.toml | 70 + pallets/asset-registry/src/benchmarking.rs | 69 + pallets/asset-registry/src/lib.rs | 171 + pallets/asset-registry/src/mock.rs | 124 + pallets/asset-registry/src/tests.rs | 76 + pallets/asset-registry/src/weights.rs | 76 + pallets/credentials/Cargo.toml | 58 + pallets/credentials/src/benchmarking.rs | 1 + pallets/credentials/src/lib.rs | 279 ++ pallets/credentials/src/mock.rs | 129 + pallets/credentials/src/tests.rs | 156 + pallets/funding/Cargo.toml | 2 + pallets/funding/src/lib.rs | 3 + pallets/funding/src/mock.rs | 19 + pallets/parachain-staking/Cargo.toml | 70 + pallets/parachain-staking/src/api.rs | 90 + pallets/parachain-staking/src/benchmarking.rs | 638 +++ .../parachain-staking/src/default_weights.rs | 843 ++++ pallets/parachain-staking/src/inflation.rs | 384 ++ pallets/parachain-staking/src/lib.rs | 2573 ++++++++++ pallets/parachain-staking/src/migration.rs | 17 + pallets/parachain-staking/src/mock.rs | 421 ++ pallets/parachain-staking/src/set.rs | 553 +++ pallets/parachain-staking/src/tests.rs | 4347 +++++++++++++++++ pallets/parachain-staking/src/types.rs | 321 ++ pallets/sandbox/Cargo.toml | 2 + pallets/sandbox/src/mock.rs | 19 + pallets/sandbox/src/tests.rs | 6 + runtime-api/credentials/Cargo.toml | 35 + runtime-api/staking/Cargo.toml | 23 + runtime-api/staking/src/lib.rs | 46 + runtimes/base/Cargo.toml | 8 +- runtimes/base/src/currency.rs | 14 - runtimes/base/src/lib.rs | 176 +- runtimes/common/Cargo.toml | 90 + runtimes/common/src/constants.rs | 358 ++ runtimes/common/src/fees.rs | 279 ++ runtimes/common/src/lib.rs | 184 + runtimes/common/src/xcm_config.rs | 160 + runtimes/standalone/Cargo.toml | 10 +- runtimes/testnet/Cargo.toml | 12 +- rust-toolchain.toml | 2 +- 44 files changed, 13337 insertions(+), 151 deletions(-) create mode 100644 pallets/asset-registry/Cargo.toml create mode 100644 pallets/asset-registry/src/benchmarking.rs create mode 100644 pallets/asset-registry/src/lib.rs create mode 100644 pallets/asset-registry/src/mock.rs create mode 100644 pallets/asset-registry/src/tests.rs create mode 100644 pallets/asset-registry/src/weights.rs create mode 100644 pallets/credentials/Cargo.toml create mode 100644 pallets/credentials/src/benchmarking.rs create mode 100644 pallets/credentials/src/lib.rs create mode 100644 pallets/credentials/src/mock.rs create mode 100644 pallets/credentials/src/tests.rs create mode 100644 pallets/parachain-staking/Cargo.toml create mode 100644 pallets/parachain-staking/src/api.rs create mode 100644 pallets/parachain-staking/src/benchmarking.rs create mode 100644 pallets/parachain-staking/src/default_weights.rs create mode 100644 pallets/parachain-staking/src/inflation.rs create mode 100644 pallets/parachain-staking/src/lib.rs create mode 100644 pallets/parachain-staking/src/migration.rs create mode 100644 pallets/parachain-staking/src/mock.rs create mode 100644 pallets/parachain-staking/src/set.rs create mode 100644 pallets/parachain-staking/src/tests.rs create mode 100644 pallets/parachain-staking/src/types.rs create mode 100644 runtime-api/credentials/Cargo.toml create mode 100644 runtime-api/staking/Cargo.toml create mode 100644 runtime-api/staking/src/lib.rs delete mode 100644 runtimes/base/src/currency.rs create mode 100644 runtimes/common/Cargo.toml create mode 100644 runtimes/common/src/constants.rs create mode 100644 runtimes/common/src/fees.rs create mode 100644 runtimes/common/src/lib.rs create mode 100644 runtimes/common/src/xcm_config.rs diff --git a/Cargo.lock b/Cargo.lock index cb0864f2c..b66c71d01 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -450,6 +450,26 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" +[[package]] +name = "attestation" +version = "1.11.0-dev" +source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" +dependencies = [ + "ctype", + "frame-benchmarking", + "frame-support", + "frame-system", + "kilt-support", + "log", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "atty" version = "0.2.14" @@ -2235,6 +2255,58 @@ dependencies = [ "subtle", ] +[[package]] +name = "dip-provider-runtime-template" +version = "1.11.0-dev" +source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" +dependencies = [ + "cumulus-pallet-aura-ext", + "cumulus-pallet-dmp-queue", + "cumulus-pallet-parachain-system", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "cumulus-primitives-timestamp", + "cumulus-primitives-utility", + "did", + "dip-support", + "frame-executive", + "frame-support", + "frame-system", + "frame-system-rpc-runtime-api", + "kilt-runtime-api-dip-provider", + "pallet-aura", + "pallet-authorship", + "pallet-balances", + "pallet-collator-selection", + "pallet-dip-provider", + "pallet-session", + "pallet-sudo", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-xcm", + "parachain-info", + "parity-scale-codec", + "runtime-common 1.11.0-dev", + "scale-info", + "sp-api", + "sp-block-builder", + "sp-consensus-aura", + "sp-core", + "sp-inherents", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std", + "sp-transaction-pool", + "sp-version", + "substrate-wasm-builder", + "xcm", + "xcm-builder", + "xcm-executor", +] + [[package]] name = "dip-support" version = "1.11.0-dev" @@ -3675,6 +3747,46 @@ dependencies = [ "num-traits", ] +[[package]] +name = "integration-tests" +version = "0.1.0" +dependencies = [ + "cumulus-pallet-xcm", + "cumulus-primitives-core", + "did", + "dip-provider-runtime-template", + "dip-support", + "frame-support", + "frame-system", + "kilt-dip-support", + "kilt-support", + "pallet-assets", + "pallet-balances", + "pallet-did-lookup", + "pallet-xcm", + "parachain-info", + "parity-scale-codec", + "penpal-runtime", + "polimec-parachain-runtime", + "polkadot-core-primitives", + "polkadot-parachain", + "polkadot-runtime", + "polkadot-runtime-parachains", + "runtime-common 0.1.0", + "runtime-common 1.11.0-dev", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "statemint-runtime", + "substrate-wasm-builder", + "xcm", + "xcm-builder", + "xcm-emulator", + "xcm-executor", +] + [[package]] name = "interceptor" version = "0.8.2" @@ -3919,6 +4031,22 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "kilt-asset-dids" +version = "1.11.0-dev" +source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" +dependencies = [ + "base58", + "frame-support", + "hex", + "hex-literal", + "log", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-std", +] + [[package]] name = "kilt-dip-support" version = "1.11.0-dev" @@ -3936,6 +4064,36 @@ dependencies = [ "sp-trie", ] +[[package]] +name = "kilt-runtime-api-dip-provider" +version = "1.11.0-dev" +source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" +dependencies = [ + "parity-scale-codec", + "sp-api", +] + +[[package]] +name = "kilt-runtime-api-staking" +version = "0.1.0" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-runtime", +] + +[[package]] +name = "kilt-runtime-api-staking" +version = "1.11.0-dev" +source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" +dependencies = [ + "parity-scale-codec", + "scale-info", + "sp-api", + "sp-runtime", +] + [[package]] name = "kilt-support" version = "1.11.0-dev" @@ -5485,6 +5643,37 @@ dependencies = [ "libm 0.1.4", ] +[[package]] +name = "pallet-asset-registry" +version = "0.0.1" +dependencies = [ + "cumulus-pallet-dmp-queue", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-assets", + "pallet-balances", + "pallet-xcm", + "parachain-info", + "parachains-common", + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain", + "polkadot-runtime-parachains", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "xcm", + "xcm-builder", + "xcm-executor", + "xcm-primitives", + "xcm-simulator", +] + [[package]] name = "pallet-asset-tx-payment" version = "4.0.0-dev" @@ -5756,6 +5945,23 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-credentials" +version = "0.1.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-balances", + "parity-scale-codec", + "polimec-traits", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-democracy" version = "4.0.0-dev" @@ -5813,6 +6019,20 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-dip-provider" +version = "1.11.0-dev" +source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" +dependencies = [ + "dip-support", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-std", + "xcm", +] + [[package]] name = "pallet-election-provider-multi-phase" version = "4.0.0-dev" @@ -5894,6 +6114,7 @@ dependencies = [ "frame-system", "pallet-assets", "pallet-balances", + "pallet-credentials", "pallet-insecure-randomness-collective-flip", "parity-scale-codec", "polimec-traits", @@ -6243,6 +6464,7 @@ dependencies = [ "frame-system", "pallet-assets", "pallet-balances", + "pallet-credentials", "pallet-funding", "pallet-insecure-randomness-collective-flip", "parachains-common", @@ -6506,6 +6728,21 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-uniques" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.39#8c4b84520cee2d7de53cc33cb67605ce4efefba8" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-utility" version = "4.0.0-dev" @@ -6537,6 +6774,20 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-web3-names" +version = "1.11.0-dev" +source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" +dependencies = [ + "frame-support", + "frame-system", + "kilt-support", + "parity-scale-codec", + "scale-info", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-whitelist" version = "4.0.0-dev" @@ -6604,6 +6855,53 @@ dependencies = [ "scale-info", ] +[[package]] +name = "parachain-staking" +version = "1.9.0-dev" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "kilt-runtime-api-staking 0.1.0", + "log", + "pallet-aura", + "pallet-authorship", + "pallet-balances", + "pallet-session", + "pallet-timestamp", + "parity-scale-codec", + "scale-info", + "serde", + "sp-consensus-aura", + "sp-core", + "sp-io", + "sp-runtime", + "sp-staking", + "sp-std", +] + +[[package]] +name = "parachain-staking" +version = "1.11.0-dev" +source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "kilt-runtime-api-staking 1.11.0-dev", + "kilt-support", + "log", + "pallet-authorship", + "pallet-balances", + "pallet-session", + "parity-scale-codec", + "scale-info", + "serde", + "sp-runtime", + "sp-staking", + "sp-std", +] + [[package]] name = "parachains-common" version = "1.0.0" @@ -6792,6 +7090,65 @@ dependencies = [ "base64ct", ] +[[package]] +name = "penpal-runtime" +version = "0.9.27" +dependencies = [ + "cumulus-pallet-aura-ext", + "cumulus-pallet-dmp-queue", + "cumulus-pallet-parachain-system", + "cumulus-pallet-session-benchmarking", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "cumulus-primitives-timestamp", + "cumulus-primitives-utility", + "frame-benchmarking", + "frame-executive", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "hex-literal", + "log", + "pallet-asset-tx-payment", + "pallet-assets", + "pallet-aura", + "pallet-authorship", + "pallet-balances", + "pallet-collator-selection", + "pallet-session", + "pallet-sudo", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-xcm", + "parachain-info", + "parachains-common", + "parity-scale-codec", + "polkadot-parachain", + "polkadot-primitives", + "polkadot-runtime-common", + "scale-info", + "smallvec", + "sp-api", + "sp-block-builder", + "sp-consensus-aura", + "sp-core", + "sp-inherents", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std", + "sp-transaction-pool", + "sp-version", + "substrate-wasm-builder", + "xcm", + "xcm-builder", + "xcm-executor", +] + [[package]] name = "percent-encoding" version = "2.2.0" @@ -6951,11 +7308,13 @@ dependencies = [ "pallet-treasury", "pallet-xcm", "parachain-info", + "parachain-staking 1.9.0-dev", "parachains-common", "parity-scale-codec", "polkadot-parachain", "polkadot-primitives", "polkadot-runtime-common", + "runtime-common 0.1.0", "scale-info", "smallvec", "sp-api", @@ -7062,12 +7421,14 @@ dependencies = [ "hex-literal", "kilt-dip-support", "log", + "pallet-asset-registry", "pallet-asset-tx-payment", "pallet-assets", "pallet-aura", "pallet-authorship", "pallet-balances", "pallet-collective", + "pallet-credentials", "pallet-democracy", "pallet-did-lookup", "pallet-dip-consumer", @@ -7086,12 +7447,14 @@ dependencies = [ "pallet-vesting", "pallet-xcm", "parachain-info", + "parachain-staking 1.9.0-dev", "parachains-common", "parity-scale-codec", "polimec-traits", "polkadot-parachain", "polkadot-primitives", "polkadot-runtime-common", + "runtime-common 0.1.0", "scale-info", "serde", "smallvec", @@ -7176,6 +7539,7 @@ dependencies = [ "pallet-authorship", "pallet-balances", "pallet-collective", + "pallet-credentials", "pallet-democracy", "pallet-funding", "pallet-grandpa", @@ -7192,6 +7556,7 @@ dependencies = [ "pallet-vesting", "parity-scale-codec", "polimec-traits", + "runtime-common 0.1.0", "scale-info", "sp-api", "sp-block-builder", @@ -8650,6 +9015,24 @@ dependencies = [ "cc", ] +[[package]] +name = "public-credentials" +version = "1.11.0-dev" +source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" +dependencies = [ + "ctype", + "frame-benchmarking", + "frame-support", + "frame-system", + "kilt-support", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -9167,6 +9550,79 @@ dependencies = [ "webrtc-util", ] +[[package]] +name = "runtime-common" +version = "0.1.0" +dependencies = [ + "cumulus-primitives-core", + "did", + "dip-support", + "frame-support", + "frame-system", + "log", + "pallet-authorship", + "pallet-balances", + "pallet-did-lookup", + "pallet-dip-consumer", + "pallet-dip-provider", + "pallet-membership", + "pallet-transaction-payment", + "parachain-staking 1.9.0-dev", + "parachains-common", + "parity-scale-codec", + "polkadot-parachain", + "scale-info", + "smallvec", + "sp-consensus-aura", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-trie", + "xcm", + "xcm-builder", + "xcm-executor", +] + +[[package]] +name = "runtime-common" +version = "1.11.0-dev" +source = "git+https://github.com/KILTprotocol/kilt-node?branch=aa/dip#17c587e7cfd39e79ee06c7a568271ee8beecc505" +dependencies = [ + "attestation", + "ctype", + "cumulus-primitives-core", + "did", + "frame-support", + "frame-system", + "kilt-asset-dids", + "kilt-dip-support", + "kilt-support", + "log", + "pallet-authorship", + "pallet-balances", + "pallet-dip-consumer", + "pallet-dip-provider", + "pallet-membership", + "pallet-transaction-payment", + "pallet-web3-names", + "parachain-staking 1.11.0-dev", + "parity-scale-codec", + "polkadot-parachain", + "public-credentials", + "scale-info", + "smallvec", + "sp-consensus-aura", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "sp-trie", + "xcm", + "xcm-builder", + "xcm-executor", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -11610,6 +12066,70 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "statemint-runtime" +version = "1.0.0" +source = "git+https://github.com/paritytech/cumulus?branch=polkadot-v0.9.39#d6eef144421ef5c3f339f681484d06bb729dfa82" +dependencies = [ + "cumulus-pallet-aura-ext", + "cumulus-pallet-dmp-queue", + "cumulus-pallet-parachain-system", + "cumulus-pallet-session-benchmarking", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "cumulus-primitives-timestamp", + "cumulus-primitives-utility", + "frame-benchmarking", + "frame-executive", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "hex-literal", + "log", + "pallet-asset-tx-payment", + "pallet-assets", + "pallet-aura", + "pallet-authorship", + "pallet-balances", + "pallet-collator-selection", + "pallet-multisig", + "pallet-proxy", + "pallet-session", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-uniques", + "pallet-utility", + "pallet-xcm", + "pallet-xcm-benchmarks", + "parachain-info", + "parachains-common", + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain", + "polkadot-runtime-common", + "polkadot-runtime-constants", + "scale-info", + "smallvec", + "sp-api", + "sp-block-builder", + "sp-consensus-aura", + "sp-core", + "sp-inherents", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std", + "sp-transaction-pool", + "sp-version", + "substrate-wasm-builder", + "xcm", + "xcm-builder", + "xcm-executor", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -13768,6 +14288,32 @@ dependencies = [ "xcm-executor", ] +[[package]] +name = "xcm-emulator" +version = "0.1.0" +source = "git+https://github.com/shaunxw/xcm-simulator?rev=aa13dce47596e150806dfc3af99096dae6ffc65e#aa13dce47596e150806dfc3af99096dae6ffc65e" +dependencies = [ + "cumulus-pallet-dmp-queue", + "cumulus-pallet-parachain-system", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "cumulus-primitives-parachain-inherent", + "cumulus-test-relay-sproof-builder", + "frame-support", + "frame-system", + "parachain-info", + "parity-scale-codec", + "paste", + "polkadot-primitives", + "polkadot-runtime-parachains", + "quote", + "sp-arithmetic", + "sp-io", + "sp-std", + "xcm", + "xcm-executor", +] + [[package]] name = "xcm-executor" version = "0.9.39-1" @@ -13808,6 +14354,23 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "xcm-simulator" +version = "0.9.39-1" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.39#c22e1c4173bf6966f5d1980f4299f7abe836f0c1" +dependencies = [ + "frame-support", + "parity-scale-codec", + "paste", + "polkadot-core-primitives", + "polkadot-parachain", + "polkadot-runtime-parachains", + "sp-io", + "sp-std", + "xcm", + "xcm-executor", +] + [[package]] name = "yamux" version = "0.10.2" diff --git a/Cargo.toml b/Cargo.toml index ebb8ca791..b6ca4f082 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,5 @@ [workspace] -members = [ "nodes/*", - "pallets/*", - "runtimes/*", - "traits", - # "integration-tests" -] +members = ["nodes/*", "pallets/*", "runtimes/*", "traits", "integration-tests"] [workspace.package] authors = ['Polimec Foundation '] @@ -44,10 +39,14 @@ overflow-checks = true substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } # Internal pallets (with default disabled) +parachain-staking = { path = "pallets/parachain-staking", default-features = false } +pallet-credentials = { path = "pallets/credentials", default-features = false } pallet-funding = { path = "pallets/funding", default-features = false } pallet-sandbox = { path = "pallets/sandbox", default-features = false } +pallet-asset-registry = { path = "pallets/asset-registry", default-features = false } # Internal support (with default disabled) +runtime-common = { path = "runtimes/common", default-features = false } polimec-traits = { path = "traits", default-features = false } xcm-primitives = { path = "primitives/xcm", default-features = false } diff --git a/pallets/asset-registry/Cargo.toml b/pallets/asset-registry/Cargo.toml new file mode 100644 index 000000000..bf8db0140 --- /dev/null +++ b/pallets/asset-registry/Cargo.toml @@ -0,0 +1,70 @@ +[package] +name = "pallet-asset-registry" +version = "0.0.1" +description = "Trappist pallet for XCM Asset Registry." +edition = "2021" +license = "Apache-2.0" +repository = "https://github.com/paritytech/trappist" + + +[dependencies] +scale-info = { workspace = true, features = ["derive", "serde"] } +parity-scale-codec = { workspace = true, features = [ + "derive", +] } +sp-runtime.workspace = true +sp-std.workspace = true +frame-benchmarking.workspace = true +frame-support.workspace = true +frame-system.workspace = true +pallet-assets.workspace = true +pallet-balances.workspace = true +xcm.workspace = true +xcm-primitives.workspace = true + +[dev-dependencies] +sp-core.workspace = true +sp-io.workspace = true +sp-runtime.workspace = true +xcm.workspace = true +xcm-simulator.workspace = true +xcm-executor.workspace = true +xcm-builder.workspace = true +pallet-xcm.workspace = true +polkadot-core-primitives.workspace = true +polkadot-runtime-parachains.workspace = true +polkadot-parachain.workspace = true +parachain-info.workspace = true +parachains-common.workspace = true +cumulus-pallet-dmp-queue.workspace = true +cumulus-pallet-xcmp-queue.workspace = true +cumulus-primitives-core.workspace = true + +[features] +default = ["std"] +std = [ + "parity-scale-codec/std", + "sp-runtime/std", + "sp-std/std", + "pallet-assets/std", + "pallet-balances/std", + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "scale-info/std", + "xcm-primitives/std", + "xcm/std", + "xcm-executor/std", + "xcm-builder/std", + "pallet-xcm/std", + "polkadot-core-primitives/std", + "polkadot-runtime-parachains/std", + "polkadot-parachain/std", + "parachain-info/std", + "parachains-common/std", + "cumulus-pallet-dmp-queue/std", + "cumulus-pallet-xcmp-queue/std", + "cumulus-primitives-core/std", +] +runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] +try-runtime = ["frame-support/try-runtime", "pallet-assets/try-runtime"] diff --git a/pallets/asset-registry/src/benchmarking.rs b/pallets/asset-registry/src/benchmarking.rs new file mode 100644 index 000000000..d2209faa0 --- /dev/null +++ b/pallets/asset-registry/src/benchmarking.rs @@ -0,0 +1,69 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +//! Benchmarking setup for pallet-asset-registry + +use super::*; + +#[allow(unused)] +use crate::Pallet as AssetRegistry; +use frame_benchmarking::benchmarks; +use frame_support::{assert_ok, traits::fungibles::Inspect}; +use frame_system::RawOrigin; +use xcm::opaque::latest::{ + Junction::{GeneralIndex, PalletInstance, Parachain}, + Junctions, MultiLocation, +}; + +pub const LOCAL_ASSET_ID: u32 = 10; + +benchmarks! { + where_clause { + where + T::Assets: Inspect<::AccountId, AssetId = u32>, + } + + register_reserve_asset { + let asset_multi_location = MultiLocation { + parents: 1, + interior: Junctions::X3(Parachain(Default::default()), PalletInstance(Default::default()), GeneralIndex(Default::default())) + }; + + }: _(RawOrigin::Root, LOCAL_ASSET_ID, asset_multi_location.clone()) + verify { + let read_asset_multi_location = AssetRegistry::::asset_id_multilocation(LOCAL_ASSET_ID) + .expect("error reading AssetIdMultiLocation"); + assert_eq!(read_asset_multi_location, asset_multi_location); + } + + unregister_reserve_asset { + let asset_multi_location = MultiLocation { + parents: 1, + interior: Junctions::X3(Parachain(Default::default()), PalletInstance(Default::default()), GeneralIndex(Default::default())) + }; + + assert_ok!(AssetRegistry::::register_reserve_asset(RawOrigin::Root.into(), LOCAL_ASSET_ID, asset_multi_location.clone())); + let read_asset_multi_location = AssetRegistry::::asset_id_multilocation(LOCAL_ASSET_ID) + .expect("error reading AssetIdMultiLocation"); + assert_eq!(read_asset_multi_location, asset_multi_location); + + }: _(RawOrigin::Root, LOCAL_ASSET_ID) + verify { + assert_eq!(AssetRegistry::::asset_id_multilocation(LOCAL_ASSET_ID), None); + } + + impl_benchmark_test_suite!(AssetRegistry, crate::mock::new_test_ext(), crate::mock::Test); +} diff --git a/pallets/asset-registry/src/lib.rs b/pallets/asset-registry/src/lib.rs new file mode 100644 index 000000000..673e2ed44 --- /dev/null +++ b/pallets/asset-registry/src/lib.rs @@ -0,0 +1,171 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +/// Edit this file to define custom logic or remove it if it is not needed. +/// Learn more about FRAME and the core library of Substrate FRAME pallets: +/// +pub use pallet::*; + +#[cfg(test)] +mod mock; +#[cfg(test)] +mod tests; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; +pub mod weights; +pub use weights::*; + +#[frame_support::pallet(dev_mode)] +pub mod pallet { + use super::*; + use frame_support::{pallet_prelude::*, sp_runtime::traits::Zero, traits::tokens::fungibles::Inspect}; + use frame_system::pallet_prelude::*; + + use xcm::latest::{ + Junction::{GeneralIndex, PalletInstance, Parachain}, + Junctions, MultiLocation, + }; + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); + + type AssetIdOf = <::Assets as Inspect<::AccountId>>::AssetId; + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + type ReserveAssetModifierOrigin: EnsureOrigin; + type Assets: Inspect; + type WeightInfo: WeightInfo; + } + + #[pallet::storage] + #[pallet::getter(fn asset_id_multilocation)] + pub type AssetIdMultiLocation = StorageMap<_, Blake2_128Concat, AssetIdOf, MultiLocation>; + + #[pallet::storage] + #[pallet::getter(fn asset_multilocation_id)] + pub type AssetMultiLocationId = StorageMap<_, Blake2_128Concat, MultiLocation, AssetIdOf>; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + ReserveAssetRegistered { + asset_id: AssetIdOf, + asset_multi_location: MultiLocation, + }, + ReserveAssetUnregistered { + asset_id: AssetIdOf, + asset_multi_location: MultiLocation, + }, + } + + #[pallet::error] + pub enum Error { + /// The Asset ID is already registered + AssetAlreadyRegistered, + /// The Asset ID does not exist + AssetDoesNotExist, + /// The Asset ID is not registered + AssetIsNotRegistered, + /// Invalid MultiLocation + WrongMultiLocation, + } + + #[pallet::call] + impl Pallet { + #[pallet::weight(::WeightInfo::register_reserve_asset())] + pub fn register_reserve_asset( + origin: OriginFor, asset_id: AssetIdOf, asset_multi_location: MultiLocation, + ) -> DispatchResult { + T::ReserveAssetModifierOrigin::ensure_origin(origin)?; + + // verify asset exists on pallet-assets + ensure!(Self::asset_exists(asset_id), Error::::AssetDoesNotExist); + + // verify asset is not yet registered + ensure!( + !AssetIdMultiLocation::::contains_key(asset_id), + Error::::AssetAlreadyRegistered + ); + + // verify MultiLocation is valid + let parents_multi_location_ok = { asset_multi_location.parents == 1 }; + let junctions_multi_location_ok = matches!( + asset_multi_location.interior, + Junctions::X3(Parachain(_), PalletInstance(_), GeneralIndex(_)) + ); + + ensure!( + parents_multi_location_ok && junctions_multi_location_ok, + Error::::WrongMultiLocation + ); + + // register asset + AssetIdMultiLocation::::insert(asset_id, &asset_multi_location); + AssetMultiLocationId::::insert(&asset_multi_location, asset_id); + + Self::deposit_event(Event::ReserveAssetRegistered { + asset_id, + asset_multi_location, + }); + + Ok(()) + } + + #[pallet::weight(::WeightInfo::unregister_reserve_asset())] + pub fn unregister_reserve_asset(origin: OriginFor, asset_id: AssetIdOf) -> DispatchResult { + T::ReserveAssetModifierOrigin::ensure_origin(origin)?; + + // verify asset is registered + let asset_multi_location = + AssetIdMultiLocation::::get(asset_id).ok_or(Error::::AssetIsNotRegistered)?; + + // unregister asset + AssetIdMultiLocation::::remove(asset_id); + AssetMultiLocationId::::remove(&asset_multi_location); + + Self::deposit_event(Event::ReserveAssetUnregistered { + asset_id, + asset_multi_location, + }); + Ok(()) + } + } + + impl xcm_primitives::AssetMultiLocationGetter> for Pallet { + fn get_asset_multi_location(asset_id: AssetIdOf) -> Option { + AssetIdMultiLocation::::get(asset_id) + } + + fn get_asset_id(asset_type: MultiLocation) -> Option> { + AssetMultiLocationId::::get(asset_type) + } + } + + impl Pallet { + // pallet-assets implements the fungibles::Inspect trait + // where minimum_balance(asset_id) always returns non-zero + // for existing assets, and zero for non-existing assets + fn asset_exists(asset_id: AssetIdOf) -> bool { + !T::Assets::minimum_balance(asset_id).is_zero() + } + } +} diff --git a/pallets/asset-registry/src/mock.rs b/pallets/asset-registry/src/mock.rs new file mode 100644 index 000000000..d966bd34c --- /dev/null +++ b/pallets/asset-registry/src/mock.rs @@ -0,0 +1,124 @@ +use crate as pallet_asset_registry; +use frame_support::traits::{AsEnsureOriginWithArg, ConstU16, ConstU64, GenesisBuild}; +use frame_system as system; +use sp_core::H256; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, ConstU32, IdentityLookup}, +}; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +frame_support::parameter_types! { + pub const StatemineParaIdInfo: u32 = 1000u32; + pub const StatemineAssetsInstanceInfo: u8 = 50u8; + pub const StatemineAssetIdInfo: u128 = 1u128; +} + +// Configure a mock runtime to test the pallet. +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system, + AssetRegistry: pallet_asset_registry::{Pallet, Call, Storage, Event}, + Assets: pallet_assets::{Pallet, Call, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + } +); + +impl system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = ConstU64<250>; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = ConstU16<42>; + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} + +impl pallet_asset_registry::Config for Test { + type RuntimeEvent = RuntimeEvent; + type ReserveAssetModifierOrigin = frame_system::EnsureRoot; + type Assets = Assets; + type WeightInfo = pallet_asset_registry::weights::SubstrateWeight; +} + +impl pallet_balances::Config for Test { + type Balance = u64; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ConstU64<1>; + type AccountStore = System; + type WeightInfo = (); + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; +} + +impl pallet_assets::Config for Test { + type RuntimeEvent = RuntimeEvent; + type Balance = u64; + type AssetId = u32; + type Currency = Balances; + type ForceOrigin = frame_system::EnsureRoot; + type AssetDeposit = ConstU64<1>; + type AssetAccountDeposit = ConstU64<10>; + type MetadataDepositBase = ConstU64<1>; + type MetadataDepositPerByte = ConstU64<1>; + type ApprovalDeposit = ConstU64<1>; + type StringLimit = ConstU32<50>; + type Freezer = (); + type WeightInfo = (); + type Extra = (); + type AssetIdParameter = u32; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); +} + +pub const LOCAL_ASSET_ID: u32 = 10; + +// Build genesis storage according to the mock runtime. +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut storage = system::GenesisConfig::default().build_storage::().unwrap(); + + let config: pallet_assets::GenesisConfig = pallet_assets::GenesisConfig { + assets: vec![ + // id, owner, is_sufficient, min_balance + (LOCAL_ASSET_ID, 0, true, 1), + ], + metadata: vec![ + // id, name, symbol, decimals + (LOCAL_ASSET_ID, "Token Name".into(), "TOKEN".into(), 10), + ], + accounts: vec![ + // id, account_id, balance + (LOCAL_ASSET_ID, 1, 100), + ], + }; + config.assimilate_storage(&mut storage).unwrap(); + storage.into() +} diff --git a/pallets/asset-registry/src/tests.rs b/pallets/asset-registry/src/tests.rs new file mode 100644 index 000000000..7b3029e9b --- /dev/null +++ b/pallets/asset-registry/src/tests.rs @@ -0,0 +1,76 @@ +use crate::{mock::*, Error}; +use frame_support::{assert_noop, assert_ok}; +use xcm::latest::prelude::*; + +#[test] +fn register_reserve_asset_works() { + new_test_ext().execute_with(|| { + let statemine_para_id = StatemineParaIdInfo::get(); + let statemine_assets_pallet = StatemineAssetsInstanceInfo::get(); + let statemine_asset_id = StatemineAssetIdInfo::get(); + + let statemine_asset_multi_location = MultiLocation { + parents: 1, + interior: X3( + Parachain(statemine_para_id), + PalletInstance(statemine_assets_pallet), + GeneralIndex(statemine_asset_id), + ), + }; + + assert_ok!(AssetRegistry::register_reserve_asset( + RuntimeOrigin::root(), + LOCAL_ASSET_ID, + statemine_asset_multi_location.clone(), + )); + + let read_asset_multi_location = + AssetRegistry::asset_id_multilocation(LOCAL_ASSET_ID).expect("error reading AssetIdMultiLocation"); + assert_eq!(read_asset_multi_location, statemine_asset_multi_location); + + let read_asset_id = AssetRegistry::asset_multilocation_id(&statemine_asset_multi_location) + .expect("error reading AssetMultiLocationId"); + assert_eq!(read_asset_id, LOCAL_ASSET_ID); + + assert_noop!( + AssetRegistry::register_reserve_asset( + RuntimeOrigin::root(), + LOCAL_ASSET_ID, + statemine_asset_multi_location, + ), + Error::::AssetAlreadyRegistered + ); + }); +} + +#[test] +fn unregister_reserve_asset_works() { + new_test_ext().execute_with(|| { + let statemine_para_id = StatemineParaIdInfo::get(); + let statemine_assets_pallet = StatemineAssetsInstanceInfo::get(); + let statemine_asset_id = StatemineAssetIdInfo::get(); + + let statemine_asset_multi_location = MultiLocation { + parents: 1, + interior: X3( + Parachain(statemine_para_id), + PalletInstance(statemine_assets_pallet), + GeneralIndex(statemine_asset_id), + ), + }; + + assert_ok!(AssetRegistry::register_reserve_asset( + RuntimeOrigin::root(), + LOCAL_ASSET_ID, + statemine_asset_multi_location.clone(), + )); + + assert_ok!(AssetRegistry::unregister_reserve_asset( + RuntimeOrigin::root(), + LOCAL_ASSET_ID + )); + + assert!(AssetRegistry::asset_id_multilocation(LOCAL_ASSET_ID).is_none()); + assert!(AssetRegistry::asset_multilocation_id(statemine_asset_multi_location).is_none()); + }); +} diff --git a/pallets/asset-registry/src/weights.rs b/pallets/asset-registry/src/weights.rs new file mode 100644 index 000000000..39416c719 --- /dev/null +++ b/pallets/asset-registry/src/weights.rs @@ -0,0 +1,76 @@ + +//! Autogenerated weights for `pallet_asset_registry` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-10-04, STEPS: `20`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! HOSTNAME: `bernardo-benchmarking`, CPU: `AMD EPYC 7B13` +//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// collected on a c2d-highcpu-8 of Google Cloud Platform + +// Executed Command: +// ./target/release/trappist-collator +// benchmark +// pallet +// --chain +// dev +// --pallet +// pallet_asset_registry +// --extrinsic +// * +// --steps +// 20 +// --repeat +// 10 +// --output +// pallets/asset-registry/src/weights.rs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +pub trait WeightInfo { + fn register_reserve_asset() -> Weight; + fn unregister_reserve_asset() -> Weight; +} + +/// Weight functions for `pallet_asset_registry`. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + // Storage: Assets Asset (r:1 w:0) + // Storage: AssetRegistry AssetIdMultiLocation (r:1 w:1) + // Storage: AssetRegistry AssetMultiLocationId (r:0 w:1) + fn register_reserve_asset() -> Weight { + Weight::from_ref_time(18_710_000) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + // Storage: AssetRegistry AssetIdMultiLocation (r:1 w:1) + // Storage: AssetRegistry AssetMultiLocationId (r:0 w:1) + fn unregister_reserve_asset() -> Weight { + Weight::from_ref_time(16_570_000) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(2)) + } +} + +impl WeightInfo for () { + // Storage: Assets Asset (r:1 w:0) + // Storage: AssetRegistry AssetIdMultiLocation (r:1 w:1) + // Storage: AssetRegistry AssetMultiLocationId (r:0 w:1) + fn register_reserve_asset() -> Weight { + Weight::from_ref_time(18_710_000) + .saturating_add(RocksDbWeight::get().reads(2)) + .saturating_add(RocksDbWeight::get().writes(2)) + } + // Storage: AssetRegistry AssetIdMultiLocation (r:1 w:1) + // Storage: AssetRegistry AssetMultiLocationId (r:0 w:1) + fn unregister_reserve_asset() -> Weight { + Weight::from_ref_time(16_570_000) + .saturating_add(RocksDbWeight::get().reads(1)) + .saturating_add(RocksDbWeight::get().writes(2)) + } +} diff --git a/pallets/credentials/Cargo.toml b/pallets/credentials/Cargo.toml new file mode 100644 index 000000000..9fe1014a2 --- /dev/null +++ b/pallets/credentials/Cargo.toml @@ -0,0 +1,58 @@ +[package] +name = 'pallet-credentials' +description = 'FRAME pallet handle credentials' +authors.workspace = true +documentation.workspace = true +edition.workspace = true +homepage.workspace = true +license-file.workspace = true +readme.workspace = true +repository.workspace = true +version.workspace = true + + +[dependencies] +parity-scale-codec = { workspace = true, features = [ + "derive", +] } +scale-info = { workspace = true, features = ["derive"] } + +# Benchmarking dependencies +frame-benchmarking = { workspace = true, optional = true } +# Substrate dependencies +frame-support.workspace = true +frame-system.workspace = true +sp-std.workspace = true +sp-runtime.workspace = true +polimec-traits.workspace = true + +[dev-dependencies] +sp-core.workspace = true +sp-io.workspace = true +pallet-balances.workspace = true + +[features] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", + "polimec-traits/try-runtime", +] +default = ["std"] +runtime-benchmarks = [ + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "polimec-traits/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] +std = [ + "parity-scale-codec/std", + "sp-std/std", + "sp-runtime/std", + "pallet-balances/std", + "polimec-traits/std", + "frame-support/std", + "frame-system/std", + "scale-info/std", + "frame-benchmarking?/std", +] diff --git a/pallets/credentials/src/benchmarking.rs b/pallets/credentials/src/benchmarking.rs new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/pallets/credentials/src/benchmarking.rs @@ -0,0 +1 @@ + diff --git a/pallets/credentials/src/lib.rs b/pallets/credentials/src/lib.rs new file mode 100644 index 000000000..5f3b325af --- /dev/null +++ b/pallets/credentials/src/lib.rs @@ -0,0 +1,279 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +pub use pallet::*; + +#[cfg(test)] +mod mock; + +#[cfg(test)] +mod tests; + +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + +use frame_support::{ + ensure, + pallet_prelude::DispatchResult, + traits::{ChangeMembers, InitializeMembers}, +}; +use polimec_traits::{Credential, MemberRole, PolimecMembers}; +use sp_runtime::{traits::StaticLookup, DispatchError}; + +type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; + +#[frame_support::pallet(dev_mode)] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + /// Configure the pallet by specifying the parameters and types on which it depends. + #[pallet::config] + pub trait Config: frame_system::Config { + /// The overarching event type. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// Required origin for adding a member (though can always be Root). + type AddOrigin: EnsureOrigin; + + /// Required origin for removing a member (though can always be Root). + type RemoveOrigin: EnsureOrigin; + + /// Required origin for adding and removing a member in a single action. + /// TODO: Not used ATM + type SwapOrigin: EnsureOrigin; + + /// Required origin for resetting membership. + /// TODO: Not used ATM + type ResetOrigin: EnsureOrigin; + + /// Required origin for setting or resetting the prime member. + /// TODO: Not used ATM + type PrimeOrigin: EnsureOrigin; + + /// The receiver of the signal for when the membership has been initialized. This happens + /// pre-genesis and will usually be the same as `MembershipChanged`. If you need to do + /// something different on initialization, then you can change this accordingly. + type MembershipInitialized: InitializeMembers; + + /// The receiver of the signal for when the membership has changed. + type MembershipChanged: ChangeMembers; + + // Weight information for extrinsics in this pallet. + // type WeightInfo: WeightInfo; + } + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); + + /// Maps member type to members of each type. + #[pallet::storage] + #[pallet::getter(fn members)] + pub type Members = StorageDoubleMap<_, Twox64Concat, MemberRole, Twox64Concat, T::AccountId, ()>; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// The given member was added; see the transaction for who. + MemberAdded, + /// The given member was removed; see the transaction for who. + MemberRemoved, + /// Two members were swapped; see the transaction for who. + MembersSwapped, + /// The membership was reset; see the transaction for who the new set is. + MembersReset, + /// One of the members' keys changed. + KeyChanged, + } + + #[pallet::error] + pub enum Error { + /// Already a member. + AlreadyMember, + /// Not a member. + NotMember, + } + + #[pallet::hooks] + impl Hooks> for Pallet {} + + #[pallet::genesis_config] + pub struct GenesisConfig { + pub issuers: Vec, + pub retails: Vec, + pub professionals: Vec, + pub institutionals: Vec, + } + + #[cfg(feature = "std")] + impl Default for GenesisConfig { + fn default() -> Self { + Self { + issuers: Default::default(), + retails: Default::default(), + professionals: Default::default(), + institutionals: Default::default(), + } + } + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + use sp_std::collections::btree_set::BTreeSet; + + let issuers_set: BTreeSet<_> = self.issuers.iter().collect(); + assert_eq!( + issuers_set.len(), + self.issuers.len(), + "Issuers cannot contain duplicate accounts." + ); + + let retails_set: BTreeSet<_> = self.retails.iter().collect(); + assert_eq!( + retails_set.len(), + self.retails.len(), + "Issuers cannot contain duplicate accounts." + ); + + let professionals_set: BTreeSet<_> = self.professionals.iter().collect(); + assert_eq!( + professionals_set.len(), + self.professionals.len(), + "Issuers cannot contain duplicate accounts." + ); + + let institutionals_set: BTreeSet<_> = self.institutionals.iter().collect(); + assert_eq!( + institutionals_set.len(), + self.institutionals.len(), + "Issuers cannot contain duplicate accounts." + ); + + Pallet::::initialize_members(&MemberRole::Issuer, &self.issuers); + Pallet::::initialize_members(&MemberRole::Retail, &self.retails); + Pallet::::initialize_members(&MemberRole::Professional, &self.professionals); + Pallet::::initialize_members(&MemberRole::Institutional, &self.institutionals); + } + } + + #[pallet::call] + impl Pallet { + /// Add a member `who` to the set. + /// + /// May only be called from `T::AddOrigin`. + // TODO: Set a proper weight + #[pallet::weight(1)] + pub fn add_member(origin: OriginFor, credential: Credential, who: AccountIdLookupOf) -> DispatchResult { + T::AddOrigin::ensure_origin(origin)?; + let who = T::Lookup::lookup(who)?; + + Self::do_add_member(&who, &credential)?; + Ok(()) + } + + /// Remove a member `who` from the set. + /// + /// May only be called from `T::RemoveOrigin`. + // TODO: Set a proper weight + #[pallet::weight(1)] + pub fn remove_member( + origin: OriginFor, credential: Credential, who: AccountIdLookupOf, + ) -> DispatchResult { + T::RemoveOrigin::ensure_origin(origin)?; + let who = T::Lookup::lookup(who)?; + + Self::do_remove_member(&who, &credential)?; + Ok(()) + } + } +} + +impl Pallet { + fn do_add_member(who: &T::AccountId, credential: &Credential) -> Result<(), DispatchError> { + // TODO: This is a placeholder, we still dont't know the actual structure of a `Credential` + let role = credential.role; + ensure!(!Self::is_in(&role, who), Error::::AlreadyMember); + + Self::do_add_member_with_role(&role, who)?; + Ok(()) + } + + fn do_add_member_with_role(role: &MemberRole, who: &T::AccountId) -> Result<(), DispatchError> { + Members::::insert(role, who, ()); + Self::deposit_event(Event::MemberAdded); + Ok(()) + } + + fn do_remove_member(who: &T::AccountId, credential: &Credential) -> Result<(), DispatchError> { + // TODO: This is a placeholder, we still dont't know the actual structure of a `Credential` + let role = credential.role; + ensure!(Self::is_in(&role, who), Error::::NotMember); + + Self::do_remove_member_with_role(&role, who)?; + Ok(()) + } + + fn do_remove_member_with_role(role: &MemberRole, who: &T::AccountId) -> Result<(), DispatchError> { + Members::::remove(role, who); + Self::deposit_event(Event::MemberRemoved); + Ok(()) + } +} + +use sp_std::{vec, vec::Vec}; + +impl PolimecMembers for Pallet { + /// Chech if `who` is in the `role` set + fn is_in(role: &MemberRole, who: &T::AccountId) -> bool { + >::contains_key(role, who) + } + + /// Add `who` to the `role` set + fn add_member(role: &MemberRole, who: &T::AccountId) -> Result<(), DispatchError> { + Self::do_add_member_with_role(role, who) + } + + /// Utility function to set a vector of `member` during the genesis + fn initialize_members(role: &MemberRole, members: &[T::AccountId]) { + if !members.is_empty() { + for member in members { + assert!(!Self::is_in(role, member), "Members are already initialized!"); + } + for member in members { + let _ = Self::do_add_member_with_role(role, member); + } + } + } + + fn get_members_of(role: &MemberRole) -> Vec { + >::iter_key_prefix(role).collect() + } + + fn get_roles_of(who: &T::AccountId) -> Vec { + let mut user_roles = vec![]; + for role in MemberRole::iterator() { + if let Some(()) = Members::::get(role, who) { + user_roles.push(*role) + } + } + user_roles + } +} diff --git a/pallets/credentials/src/mock.rs b/pallets/credentials/src/mock.rs new file mode 100644 index 000000000..a57d581f1 --- /dev/null +++ b/pallets/credentials/src/mock.rs @@ -0,0 +1,129 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +use crate as pallet_credentials; +use frame_support::{parameter_types, traits::ConstU16}; +use frame_system::EnsureRoot; +use sp_core::H256; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, + BuildStorage, +}; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +pub type AccountId = u64; +pub type Balance = u128; +pub type BlockNumber = u64; + +// Configure a mock runtime to test the pallet. +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system, + Balances: pallet_balances, + Credentials: pallet_credentials, + } +); + +parameter_types! { + pub const BlockHashCount: u32 = 250; +} + +impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = u64; + type BlockNumber = BlockNumber; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = ConstU16<42>; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +parameter_types! { + pub static ExistentialDeposit: Balance = 1; +} + +impl pallet_balances::Config for Test { + type MaxLocks = frame_support::traits::ConstU32<1024>; + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} + +impl pallet_credentials::Config for Test { + type RuntimeEvent = RuntimeEvent; + type AddOrigin = EnsureRoot; + type RemoveOrigin = EnsureRoot; + type SwapOrigin = EnsureRoot; + type ResetOrigin = EnsureRoot; + type PrimeOrigin = EnsureRoot; + type MembershipInitialized = (); + type MembershipChanged = (); +} + +// Build genesis storage according to the mock runtime. +// TODO: Add some mocks projects at Genesis to simplify the tests +pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + + GenesisConfig { + balances: BalancesConfig { + balances: vec![(1, 512), (2, 512), (3, 512), (4, 512), (5, 512)], + }, + credentials: CredentialsConfig { + issuers: vec![1], + retails: vec![2], + professionals: vec![3, 5], + institutionals: vec![4, 5], + }, + ..Default::default() + } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + // In order to emit events the block number must be more than 0 + ext.execute_with(|| System::set_block_number(1)); + ext +} diff --git a/pallets/credentials/src/tests.rs b/pallets/credentials/src/tests.rs new file mode 100644 index 000000000..ad6470204 --- /dev/null +++ b/pallets/credentials/src/tests.rs @@ -0,0 +1,156 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +use crate::{mock::*, Error}; +use frame_support::{assert_noop, assert_ok, error::BadOrigin, BoundedVec}; +use polimec_traits::{Country, Credential, Issuers, MemberRole, PolimecMembers}; + +pub fn last_event() -> RuntimeEvent { + frame_system::Pallet::::events() + .pop() + .expect("Event expected") + .event +} + +const ALICE: AccountId = 1; +const BOB: AccountId = 2; +const CHARLIE: AccountId = 3; +const DAVE: AccountId = 4; +const EVE: AccountId = 5; + +fn new_test_credential(role: MemberRole) -> Credential { + Credential { + issuer: Issuers::IssuerOne, + role, + domicile: BoundedVec::default(), + country: Country::Switzerland, + date_of_birth: 10, + } +} + +#[test] +fn add_during_genesis_works() { + new_test_ext().execute_with(|| { + assert!(Credentials::members(MemberRole::Issuer, ALICE).is_some()); + assert!(Credentials::is_in(&MemberRole::Issuer, &ALICE)); + + assert!(Credentials::members(MemberRole::Retail, BOB).is_some()); + assert!(Credentials::is_in(&MemberRole::Retail, &BOB)); + + assert!(Credentials::members(MemberRole::Professional, CHARLIE).is_some()); + assert!(Credentials::is_in(&MemberRole::Professional, &CHARLIE)); + + assert!(Credentials::members(MemberRole::Institutional, DAVE).is_some()); + assert!(Credentials::is_in(&MemberRole::Institutional, &DAVE)); + }) +} + +#[test] +fn add_member_works() { + new_test_ext().execute_with(|| { + let cred = new_test_credential(MemberRole::Issuer); + assert_ok!(Credentials::add_member(RuntimeOrigin::root(), cred, BOB)); + assert_eq!(last_event(), RuntimeEvent::Credentials(crate::Event::MemberAdded)); + }) +} + +#[test] +fn only_root_can_add_member() { + new_test_ext().execute_with(|| { + let cred = new_test_credential(MemberRole::Issuer); + assert_noop!( + Credentials::add_member(RuntimeOrigin::signed(ALICE), cred, BOB), + BadOrigin + ); + }) +} + +#[test] +fn cant_add_already_member() { + new_test_ext().execute_with(|| { + let cred = new_test_credential(MemberRole::Issuer); + assert_noop!( + Credentials::add_member(RuntimeOrigin::root(), cred, ALICE), + Error::::AlreadyMember + ); + }) +} + +#[test] +fn remove_member_works() { + new_test_ext().execute_with(|| { + let cred = new_test_credential(MemberRole::Issuer); + assert_ok!(Credentials::remove_member(RuntimeOrigin::root(), cred, ALICE)); + assert_eq!(last_event(), RuntimeEvent::Credentials(crate::Event::MemberRemoved)); + }) +} + +#[test] +fn only_root_can_remove_member() { + new_test_ext().execute_with(|| { + let cred = new_test_credential(MemberRole::Issuer); + assert_noop!( + Credentials::remove_member(RuntimeOrigin::signed(ALICE), cred, ALICE), + BadOrigin + ); + }) +} + +#[test] +fn cant_remove_not_a_member() { + new_test_ext().execute_with(|| { + let cred = new_test_credential(MemberRole::Issuer); + assert_noop!( + Credentials::remove_member(RuntimeOrigin::root(), cred, EVE), + Error::::NotMember + ); + }) +} + +#[test] +fn get_members_of_works() { + new_test_ext().execute_with(|| { + let issuers = Credentials::get_members_of(&MemberRole::Issuer); + assert!(issuers == vec![1]); + let cred = new_test_credential(MemberRole::Issuer); + let _ = Credentials::add_member(RuntimeOrigin::root(), cred.clone(), BOB); + let issuers = Credentials::get_members_of(&MemberRole::Issuer); + assert!(issuers == vec![1, 2]); + let _ = Credentials::remove_member(RuntimeOrigin::root(), cred, ALICE); + let issuers = Credentials::get_members_of(&MemberRole::Issuer); + assert!(issuers == vec![2]); + }) +} + +#[test] +fn get_roles_of_works() { + new_test_ext().execute_with(|| { + let roles = Credentials::get_roles_of(&EVE); + let expected_roles = vec![MemberRole::Professional, MemberRole::Institutional]; + assert!(roles.len() == 2); + assert!(roles == expected_roles); + }) +} + +#[test] +fn get_roles_of_not_user() { + new_test_ext().execute_with(|| { + let roles = Credentials::get_roles_of(&6); + let expected_roles: Vec = vec![]; + assert!(roles.is_empty()); + assert!(roles == expected_roles); + }) +} diff --git a/pallets/funding/Cargo.toml b/pallets/funding/Cargo.toml index 1125957c9..715a43d3d 100644 --- a/pallets/funding/Cargo.toml +++ b/pallets/funding/Cargo.toml @@ -33,6 +33,7 @@ sp-io.workspace = true pallet-balances.workspace = true pallet-insecure-randomness-collective-flip.workspace = true pallet-assets.workspace = true +pallet-credentials.workspace = true [features] default = ["std"] @@ -46,6 +47,7 @@ std = [ "frame-system/std", "pallet-assets/std", "pallet-balances/std", + "pallet-credentials/std", "polimec-traits/std", "frame-benchmarking?/std", ] diff --git a/pallets/funding/src/lib.rs b/pallets/funding/src/lib.rs index 641dd3a33..5e78af3bb 100644 --- a/pallets/funding/src/lib.rs +++ b/pallets/funding/src/lib.rs @@ -307,6 +307,9 @@ pub mod pallet { /// Something that provides randomness in the runtime. type Randomness: Randomness; + /// Something that provides the members of Polimec + type HandleMembers: PolimecMembers; + /// The maximum length of data stored on-chain. #[pallet::constant] type StringLimit: Get; diff --git a/pallets/funding/src/mock.rs b/pallets/funding/src/mock.rs index 602e372a3..ebf310623 100644 --- a/pallets/funding/src/mock.rs +++ b/pallets/funding/src/mock.rs @@ -55,6 +55,7 @@ frame_support::construct_runtime!( Assets: pallet_assets, Balances: pallet_balances, FundingModule: pallet_funding, + Credentials: pallet_credentials, } ); @@ -107,6 +108,17 @@ impl pallet_balances::Config for TestRuntime { impl pallet_insecure_randomness_collective_flip::Config for TestRuntime {} +impl pallet_credentials::Config for TestRuntime { + type RuntimeEvent = RuntimeEvent; + type AddOrigin = EnsureSigned; + type RemoveOrigin = EnsureSigned; + type SwapOrigin = EnsureSigned; + type ResetOrigin = EnsureSigned; + type PrimeOrigin = EnsureSigned; + type MembershipInitialized = (); + type MembershipChanged = (); +} + impl pallet_assets::Config for TestRuntime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; @@ -159,6 +171,7 @@ impl pallet_funding::Config for TestRuntime { type MaxProjectsToUpdatePerBlock = ConstU32<100>; type CommunityFundingDuration = CommunityRoundDuration; type Randomness = RandomnessCollectiveFlip; + type HandleMembers = Credentials; type PreImageLimit = ConstU32<1024>; // Low value to simplify the tests type MaximumBidsPerUser = ConstU32<4>; @@ -182,6 +195,12 @@ pub fn new_test_ext() -> sp_io::TestExternalities { GenesisConfig { balances: BalancesConfig { balances: vec![] }, + credentials: CredentialsConfig { + issuers: vec![1, 16558220937623665250], + retails: vec![2], + professionals: vec![2, 3], + institutionals: vec![4], + }, ..Default::default() } .assimilate_storage(&mut t) diff --git a/pallets/parachain-staking/Cargo.toml b/pallets/parachain-staking/Cargo.toml new file mode 100644 index 000000000..569bb1636 --- /dev/null +++ b/pallets/parachain-staking/Cargo.toml @@ -0,0 +1,70 @@ +[package] +authors = ["KILT "] +description = "Parachain parachain-staking pallet for collator delegation and selection as well as reward distribution" +edition = "2021" +name = "parachain-staking" +version = "1.9.0-dev" + +[dev-dependencies] +pallet-aura = {workspace = true, features = ["std"]} +pallet-timestamp = {workspace = true, features = ["std"]} +sp-consensus-aura = {workspace = true, features = ["std"]} +sp-core = {workspace = true, features = ["std"]} +sp-io = {workspace = true, features = ["std"]} + +[dependencies] +# External dependencies +parity-scale-codec = {workspace = true, features = ["derive"]} +log.workspace = true +scale-info = {workspace = true, features = ["derive", "serde"]} +serde = {workspace = true, optional = true} + +# Internal dependencies +kilt-runtime-api-staking.workspace = true + +# Substrate dependencies +frame-support.workspace = true +frame-system.workspace = true +pallet-authorship.workspace = true +pallet-balances.workspace = true +pallet-session.workspace = true +sp-runtime.workspace = true +sp-staking.workspace = true +sp-std.workspace = true + +# Benchmarking dependencies +frame-benchmarking = {workspace = true, optional = true} + +[features] +default = ["std"] +runtime-benchmarks = [ + "frame-benchmarking", + "frame-support/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "sp-staking/runtime-benchmarks", +] +std = [ + "parity-scale-codec/std", + "frame-benchmarking?/std", + "frame-support/std", + "frame-system/std", + "kilt-runtime-api-staking/std", + "log/std", + "pallet-authorship/std", + "pallet-balances/std", + "pallet-session/std", + "scale-info/std", + "serde", + "sp-runtime/std", + "sp-staking/std", + "sp-std/std", +] +try-runtime = [ + "frame-system/try-runtime", + "frame-support/try-runtime", + "pallet-authorship/try-runtime", + "pallet-balances/try-runtime", + "pallet-session/try-runtime", +] diff --git a/pallets/parachain-staking/src/api.rs b/pallets/parachain-staking/src/api.rs new file mode 100644 index 000000000..a7ba6a3a5 --- /dev/null +++ b/pallets/parachain-staking/src/api.rs @@ -0,0 +1,90 @@ +// KILT Blockchain – https://botlabs.org +// Copyright (C) 2019-2023 BOTLabs GmbH + +// The KILT Blockchain 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. + +// The KILT Blockchain 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 this program. If not, see . + +// If you feel like getting in touch with us, you can do so at info@botlabs.org + +use frame_support::traits::Currency; +use sp_runtime::{ + traits::{Saturating, Zero}, + Perquintill, +}; + +use crate::{ + types::BalanceOf, BlocksAuthored, BlocksRewarded, CandidatePool, Config, DelegatorState, InflationConfig, Pallet, + Rewards, TotalCollatorStake, +}; + +impl Pallet { + /// Calculates the staking rewards for a given account address. + /// + /// Subtracts the number of rewarded blocks from the number of authored + /// blocks by the collator and multiplies that with the current stake + /// as well as reward rate. + /// + /// At least used in Runtime API. + pub fn get_unclaimed_staking_rewards(acc: &T::AccountId) -> BalanceOf { + let count_rewarded = BlocksRewarded::::get(acc); + let rewards = Rewards::::get(acc); + + // delegators and collators need to be handled differently + if let Some(delegator_state) = DelegatorState::::get(acc) { + // #blocks for unclaimed staking rewards equals + // #blocks_authored_by_collator - #blocks_claimed_by_delegator + let count_unclaimed = BlocksAuthored::::get(&delegator_state.owner).saturating_sub(count_rewarded); + let stake = delegator_state.amount; + // rewards += stake * reward_count * delegator_reward_rate + rewards.saturating_add(Self::calc_block_rewards_delegator(stake, count_unclaimed.into())) + } else if Self::is_active_candidate(acc).is_some() { + // #blocks for unclaimed staking rewards equals + // #blocks_authored_by_collator - #blocks_claimed_by_collator + let count_unclaimed = BlocksAuthored::::get(acc).saturating_sub(count_rewarded); + let stake = CandidatePool::::get(acc) + .map(|state| state.stake) + .unwrap_or_else(BalanceOf::::zero); + // rewards += stake * self_count * collator_reward_rate + rewards.saturating_add(Self::calc_block_rewards_collator(stake, count_unclaimed.into())) + } else { + rewards + } + } + + /// Calculates the current staking and reward rates for collators and + /// delegators. + /// + /// At least used in Runtime API. + pub fn get_staking_rates() -> kilt_runtime_api_staking::StakingRates { + let total_issuance = T::Currency::total_issuance(); + let total_stake = TotalCollatorStake::::get(); + let inflation_config = InflationConfig::::get(); + let collator_staking_rate = Perquintill::from_rational(total_stake.collators, total_issuance); + let delegator_staking_rate = Perquintill::from_rational(total_stake.delegators, total_issuance); + let collator_reward_rate = Perquintill::from_rational( + inflation_config.collator.max_rate.deconstruct(), + collator_staking_rate.deconstruct(), + ) * inflation_config.collator.reward_rate.annual; + let delegator_reward_rate = Perquintill::from_rational( + inflation_config.delegator.max_rate.deconstruct(), + delegator_staking_rate.deconstruct(), + ) * inflation_config.delegator.reward_rate.annual; + + kilt_runtime_api_staking::StakingRates { + collator_staking_rate, + collator_reward_rate, + delegator_staking_rate, + delegator_reward_rate, + } + } +} diff --git a/pallets/parachain-staking/src/benchmarking.rs b/pallets/parachain-staking/src/benchmarking.rs new file mode 100644 index 000000000..be40ccd41 --- /dev/null +++ b/pallets/parachain-staking/src/benchmarking.rs @@ -0,0 +1,638 @@ +// KILT Blockchain – https://botlabs.org +// Copyright (C) 2019-2023 BOTLabs GmbH + +// The KILT Blockchain 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. + +// The KILT Blockchain 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 this program. If not, see . + +// If you feel like getting in touch with us, you can do so at info@botlabs.org +#![cfg(feature = "runtime-benchmarks")] + +//! Benchmarking +use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite, Zero}; +use frame_support::{ + assert_ok, + traits::{Currency, Get, OnInitialize}, +}; +use frame_system::{Pallet as System, RawOrigin}; +use pallet_session::Pallet as Session; +use sp_runtime::{ + traits::{One, SaturatedConversion, StaticLookup}, + Perquintill, +}; +use sp_std::{convert::TryInto, vec::Vec}; + +use crate::{types::RoundInfo, *}; + +const COLLATOR_ACCOUNT_SEED: u32 = 0; +const DELEGATOR_ACCOUNT_SEED: u32 = 1; + +/// Fills the candidate pool up to `num_candidates`. +fn setup_collator_candidates( + num_candidates: u32, default_amount: Option, +) -> Vec { + let current_collator_count = TopCandidates::::get().len().saturated_into::(); + let collators: Vec = (current_collator_count..num_candidates) + .map(|i| account("collator", i.saturated_into::(), COLLATOR_ACCOUNT_SEED)) + .collect(); + let amount: T::CurrencyBalance = default_amount.unwrap_or_else(T::MinCollatorCandidateStake::get); + + for acc in collators.iter() { + T::Currency::make_free_balance_be(acc, amount); + assert_ok!(Pallet::::join_candidates( + T::RuntimeOrigin::from(Some(acc.clone()).into()), + amount, + )); + assert_eq!(CandidatePool::::get(acc).unwrap().stake, amount); + } + + TopCandidates::::get() + .into_bounded_vec() + .into_inner() + .drain(..) + .map(|c| c.owner) + .collect() +} + +fn fill_delegators(num_delegators: u32, collator: T::AccountId, collator_seed: u32) -> Vec { + let state = CandidatePool::::get(&collator).unwrap(); + let current_delegators = state.delegators.len().saturated_into::(); + + let delegators: Vec = (current_delegators..num_delegators) + .map(|i| { + account( + "delegator", + i.saturated_into::(), + DELEGATOR_ACCOUNT_SEED * 1000 + collator_seed, + ) + }) + .collect(); + + for acc in delegators.iter() { + T::Currency::make_free_balance_be(acc, T::MinDelegatorStake::get()); + assert_ok!(Pallet::::join_delegators( + T::RuntimeOrigin::from(Some(acc.clone()).into()), + T::Lookup::unlookup(collator.clone()), + T::MinDelegatorStake::get(), + )); + } + + delegators +} + +// fills unstake BTreeMap by unstaked many entries of 1 +fn fill_unstaking(collator: &T::AccountId, delegator: Option<&T::AccountId>, unstaked: u64) +where + u64: Into<::BlockNumber>, +{ + let who = delegator.unwrap_or(collator); + assert_eq!(Unstaking::::get(who).len(), 0); + while System::::block_number() < unstaked.into() { + if let Some(delegator) = delegator { + assert_ok!(Pallet::::delegator_stake_less( + RawOrigin::Signed(delegator.clone()).into(), + T::CurrencyBalance::one() + )); + } else { + assert_ok!(Pallet::::candidate_stake_less( + RawOrigin::Signed(collator.clone()).into(), + T::CurrencyBalance::one() + )); + } + System::::set_block_number(System::::block_number() + T::BlockNumber::one()); + } + assert_eq!(Unstaking::::get(who).len() as u64, unstaked); + assert!(Unstaking::::get(who).len() <= T::MaxUnstakeRequests::get().try_into().unwrap()); +} + +benchmarks! { + where_clause { where u64: Into<::BlockNumber> } + + on_initialize_no_action { + assert_eq!(Round::::get().current, 0u32); + let block = T::BlockNumber::one(); + }: { Pallet::::on_initialize(block) } + verify { + assert_eq!(Round::::get().current, 0u32); + } + + on_initialize_round_update { + let round = Round::::get(); + assert_eq!(round.current, 0u32); + }: { Pallet::::on_initialize(round.length) } + verify { + assert_eq!(Round::::get().current, 1u32); + } + + on_initialize_network_rewards { + let issuance = T::Currency::total_issuance(); + // if we only add by one, we also initialize a new year + let block = T::NetworkRewardStart::get() + T::BlockNumber::one() * 2_u64.into(); + }: { Pallet::::on_initialize(block) } + verify { + let new_issuance = T::Currency::total_issuance(); + let max_col_reward = InflationConfig::::get().collator.reward_rate.per_block * MaxCollatorCandidateStake::::get() * MaxSelectedCandidates::::get().into(); + let network_block_reward = T::NetworkRewardRate::get() * max_col_reward; + assert!(new_issuance > issuance); + assert_eq!(new_issuance - issuance, network_block_reward) + } + + force_new_round { + let round = Round::::get(); + let now = System::::block_number(); + assert_eq!(round.current, 0); + assert_eq!(Session::::current_index(), 0); + assert!(!ForceNewRound::::get()); + }: _(RawOrigin::Root) + verify { + assert!(ForceNewRound::::get()); + assert_eq!(Session::::current_index(), 0); + + // jump to next block to trigger new round + let now = now + T::BlockNumber::one(); + System::::set_block_number(now); + Session::::on_initialize(now); + assert_eq!(Session::::current_index(), 1); + assert_eq!(Round::::get(), RoundInfo { + current: 1, + first: now, + length: round.length, + }); + assert!(!ForceNewRound::::get()); + } + + set_inflation { + let n in 0 .. T::MaxTopCandidates::get(); + let m in 0 .. T::MaxDelegatorsPerCollator::get(); + + let candidates = setup_collator_candidates::(n, None); + for (i, c) in candidates.iter().enumerate() { + fill_delegators::(m, c.clone(), i.saturated_into::()); + Rewards::::insert(c, T::Balance::one()); + } + + let inflation = InflationInfo::new( + T::BLOCKS_PER_YEAR.saturated_into(), + Perquintill::from_percent(10), + Perquintill::from_percent(15), + Perquintill::from_percent(40), + Perquintill::from_percent(10) + ); + }: _(RawOrigin::Root, inflation.collator.max_rate, inflation.collator.reward_rate.annual, inflation.delegator.max_rate, inflation.delegator.reward_rate.annual) + verify { + assert_eq!(InflationConfig::::get(), inflation); + candidates.into_iter().for_each(|candidate| { + assert!(!Rewards::::get(&candidate).is_zero()); + }); + } + + set_max_selected_candidates { + let n in (T::MinCollators::get()) .. T::MaxTopCandidates::get(); + let m in 0 .. T::MaxDelegatorsPerCollator::get(); + + let candidates = setup_collator_candidates::(n, None); + for (i, c) in candidates.iter().enumerate() { + fill_delegators::(m, c.clone(), i.saturated_into::()); + } + let old_candidate = candidates[0].clone(); + }: _(RawOrigin::Root, n) + verify { + assert_eq!(MaxSelectedCandidates::::get(), n); + } + + set_blocks_per_round { + let bpr: T::BlockNumber = T::MinBlocksPerRound::get() + T::BlockNumber::one(); + }: _(RawOrigin::Root, bpr) + verify { + assert_eq!(Round::::get().length, bpr); + } + + force_remove_candidate { + let n in (T::MinCollators::get() + 1) .. T::MaxTopCandidates::get(); + let m in 0 .. T::MaxDelegatorsPerCollator::get(); + + let candidates = setup_collator_candidates::(n, None); + for (i, c) in candidates.iter().enumerate() { + fill_delegators::(m, c.clone(), i.saturated_into::()); + } + let candidate = candidates[0].clone(); + let unlookup_candidate = T::Lookup::unlookup(candidate.clone()); + }: _(RawOrigin::Root, unlookup_candidate) + verify { + let candidates = TopCandidates::::get(); + assert!(!candidates.into_iter().any(|other| other.owner == candidate)); + } + + join_candidates { + let n in 1 .. T::MaxTopCandidates::get() - 1; + let m in 0 .. T::MaxDelegatorsPerCollator::get(); + + let min_candidate_stake = T::MinCollatorCandidateStake::get(); + let candidates = setup_collator_candidates::(n, None); + for (i, c) in candidates.iter().enumerate() { + fill_delegators::(m, c.clone(), i.saturated_into::()); + } + + let new_candidate = account("new_collator", u32::MAX , COLLATOR_ACCOUNT_SEED); + T::Currency::make_free_balance_be(&new_candidate, min_candidate_stake); + + let origin = RawOrigin::Signed(new_candidate.clone()); + }: _(origin, min_candidate_stake) + verify { + let candidates = TopCandidates::::get(); + assert!(candidates.into_iter().any(|other| other.owner == new_candidate)); + } + + init_leave_candidates { + let n in (T::MinCollators::get() + 1) .. T::MaxTopCandidates::get() - 1; + let m in 0 .. T::MaxDelegatorsPerCollator::get(); + + let candidates = setup_collator_candidates::(n, None); + for (i, c) in candidates.iter().enumerate() { + fill_delegators::(m, c.clone(), i.saturated_into::()); + } + + let now = Round::::get().current; + let candidate = candidates[0].clone(); + + let origin = RawOrigin::Signed(candidate.clone()); + }: _(origin) + verify { + let candidates = TopCandidates::::get(); + assert!(!candidates.into_iter().any(|other| other.owner == candidate)); + let unlocking_at = now.saturating_add(T::ExitQueueDelay::get()); + assert!(CandidatePool::::get(candidate).unwrap().can_exit(unlocking_at)); + } + + cancel_leave_candidates { + let n in (T::MinCollators::get() + 1) .. T::MaxTopCandidates::get() - 1; + let m in 0 .. T::MaxDelegatorsPerCollator::get(); + + let candidates = setup_collator_candidates::(n, None); + for (i, c) in candidates.iter().enumerate() { + fill_delegators::(m, c.clone(), i.saturated_into::()); + } + + let candidate = candidates[0].clone(); + assert_ok!(Pallet::::init_leave_candidates(RawOrigin::Signed(candidate.clone()).into())); + + let origin = RawOrigin::Signed(candidate.clone()); + }: _(origin) + verify { + let candidates = TopCandidates::::get(); + assert!(candidates.into_iter().any(|other| other.owner == candidate)); + } + + execute_leave_candidates { + let n in (T::MinCollators::get() + 1) .. T::MaxTopCandidates::get() - 1; + let m in 0 .. T::MaxDelegatorsPerCollator::get(); + + let u = T::MaxUnstakeRequests::get() - 1; + let candidates = setup_collator_candidates::(n, None); + for (i, c) in candidates.iter().enumerate() { + fill_delegators::(m, c.clone(), i.saturated_into::()); + } + let candidate = candidates[0].clone(); + + // increase stake so we can unstake, because current stake is minimum + let more_stake = T::MinCollatorCandidateStake::get(); + T::Currency::make_free_balance_be(&candidate, T::CurrencyBalance::from(u128::MAX)); + assert_ok!(Pallet::::candidate_stake_more(RawOrigin::Signed(candidate.clone()).into(), more_stake)); + + // fill unstake BTreeMap by unstaked many entries of 1 + fill_unstaking::(&candidate, None, u as u64); + + // go to block in which we can exit + assert_ok!(Pallet::::init_leave_candidates(RawOrigin::Signed(candidate.clone()).into())); + + for i in 1..=T::ExitQueueDelay::get() { + let round = Round::::get(); + let now = round.first + round.length; + System::::set_block_number(now); + Pallet::::on_initialize(now); + } + let unlookup_candidate = T::Lookup::unlookup(candidate.clone()); + + let origin = RawOrigin::Signed(candidate.clone()); + }: _(origin, unlookup_candidate) + verify { + // should have one more entry in Unstaking + assert_eq!(Unstaking::::get(&candidate).len().saturated_into::(), u.saturating_add(1u32)); + } + + candidate_stake_more { + let n in 1 .. T::MaxTopCandidates::get() - 1; + let m in 0 .. T::MaxDelegatorsPerCollator::get(); + let u in 0 .. (T::MaxUnstakeRequests::get().saturated_into::() - 1); + + let candidates = setup_collator_candidates::(n, None); + for (i, c) in candidates.iter().enumerate() { + fill_delegators::(m, c.clone(), i.saturated_into::()); + } + let candidate = candidates[0].clone(); + + let old_stake = CandidatePool::::get(&candidate).unwrap().stake; + let more_stake = T::MinCollatorCandidateStake::get(); + + // increase stake so we can unstake, because current stake is minimum + T::Currency::make_free_balance_be(&candidate, T::CurrencyBalance::from(u128::MAX)); + assert_ok!(Pallet::::candidate_stake_more(RawOrigin::Signed(candidate.clone()).into(), more_stake)); + + // fill unstake BTreeMap by unstaked many entries of 1 + fill_unstaking::(&candidate, None, u as u64); + + let origin = RawOrigin::Signed(candidate.clone()); + }: _(origin, more_stake) + verify { + let new_stake = CandidatePool::::get(&candidate).unwrap().stake; + assert!(Unstaking::::get(candidate).is_empty()); + assert_eq!(new_stake, old_stake + more_stake + more_stake - T::CurrencyBalance::from(u as u64)); + } + + candidate_stake_less { + let n in 1 .. T::MaxTopCandidates::get() - 1; + let m in 0 .. T::MaxDelegatorsPerCollator::get(); + + let candidates = setup_collator_candidates::(n, None); + for (i, c) in candidates.iter().enumerate() { + fill_delegators::(m, c.clone(), i.saturated_into::()); + } + let candidate = candidates[0].clone(); + + // increase stake of candidate to later decrease it again + let old_stake = CandidatePool::::get(&candidate).unwrap().stake; + let more_stake = T::MinCollatorCandidateStake::get(); + + T::Currency::make_free_balance_be(&candidate, T::CurrencyBalance::from(u128::MAX)); + Pallet::::candidate_stake_more(RawOrigin::Signed(candidate.clone()).into(), more_stake).expect("should increase stake"); + + let new_stake = CandidatePool::::get(&candidate).unwrap().stake; + assert_eq!(new_stake, old_stake + more_stake); + + let origin = RawOrigin::Signed(candidate.clone()); + }: _(origin, more_stake) + verify { + let new_stake = CandidatePool::::get(&candidate).unwrap().stake; + assert_eq!(new_stake, old_stake); + } + + join_delegators { + let n in 1 .. T::MaxTopCandidates::get(); + let m in 1 .. T::MaxDelegatorsPerCollator::get() - 1; + + let candidates = setup_collator_candidates::(n, None); + for (i, c) in candidates.iter().enumerate() { + fill_delegators::(m, c.clone(), i.saturated_into::()); + } + let collator = candidates[0].clone(); + let delegator = account("new-delegator", 0, DELEGATOR_ACCOUNT_SEED); + let amount = T::MinDelegatorStake::get(); + T::Currency::make_free_balance_be(&delegator, amount + amount + amount + amount); + let unlookup_collator = T::Lookup::unlookup(collator.clone()); + + + let origin = RawOrigin::Signed(delegator.clone()); + }: _(origin, unlookup_collator, amount) + verify { + let state = CandidatePool::::get(&collator).unwrap(); + assert!(state.delegators.into_iter().any(|x| x.owner == delegator)); + } + + delegator_stake_more { + // we need at least 1 collators + let n in 1 .. T::MaxTopCandidates::get(); + // we need at least 1 delegator + let m in 1 .. T::MaxDelegatorsPerCollator::get() - 1; + let u in 1 .. (T::MaxUnstakeRequests::get().saturated_into::() - 1); + + let candidates = setup_collator_candidates::(n, None); + for (i, c) in candidates.iter().enumerate() { + fill_delegators::(m, c.clone(), i.saturated_into::()); + } + let collator = candidates[0].clone(); + let amount = T::MinDelegatorStake::get(); + + // make sure delegator collated to collator + let state = CandidatePool::::get(&collator).unwrap(); + let delegator = state.delegators.into_bounded_vec()[0].owner.clone(); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, amount); + + // increase stake so we can unstake, because current stake is minimum + T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); + assert_ok!(Pallet::::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), T::CurrencyBalance::from(u as u64))); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, amount + T::CurrencyBalance::from(u as u64)); + + // fill unstake BTreeMap by unstaked many entries of 1 + fill_unstaking::(&collator, Some(&delegator), u as u64); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, amount); + + let origin = RawOrigin::Signed(delegator.clone()); + }: _(origin, amount) + verify { + let state = CandidatePool::::get(&collator).unwrap(); + assert!(state.delegators.into_iter().any(|x| x.owner == delegator)); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, amount + amount); + assert!(Unstaking::::get(&delegator).is_empty()); + } + + delegator_stake_less { + // we need at least 1 collators + let n in 1 .. T::MaxTopCandidates::get(); + // we need at least 1 delegator + let m in 1 .. T::MaxDelegatorsPerCollator::get() - 1; + + let candidates = setup_collator_candidates::(n, None); + for (i, c) in candidates.iter().enumerate() { + fill_delegators::(m, c.clone(), i.saturated_into::()); + } + let collator = candidates[0].clone(); + let amount = T::CurrencyBalance::one(); + + // make sure delegator collated to collator + let state = CandidatePool::::get(&collator).unwrap(); + let delegator = state.delegators.into_bounded_vec()[0].owner.clone(); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get()); + + // increase stake so we can unstake, because current stake is minimum + T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); + assert_ok!(Pallet::::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), amount + amount)); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount + amount); + + // decrease stake once so we have an unstaking entry for this block + assert_ok!(Pallet::::delegator_stake_less(RawOrigin::Signed(delegator.clone()).into(), amount)); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount); + assert_eq!(Unstaking::::get(&delegator).len(), 1); + + let origin = RawOrigin::Signed(delegator.clone()); + }: _(origin, amount) + verify { + let state = CandidatePool::::get(&collator).unwrap(); + assert!(state.delegators.into_iter().any(|x| x.owner == delegator)); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get()); + assert_eq!(Unstaking::::get(&delegator).len(), 2); + } + + leave_delegators { + // we need at least 1 collators + let n in 1 .. T::MaxTopCandidates::get(); + // we need at least 1 delegator + let m in 1 .. T::MaxDelegatorsPerCollator::get() - 1; + + let candidates = setup_collator_candidates::(n, None); + for (i, c) in candidates.iter().enumerate() { + fill_delegators::(m, c.clone(), i.saturated_into::()); + } + let collator = candidates[0].clone(); + let amount = T::CurrencyBalance::one(); + + // make sure delegator collated to collator + let state = CandidatePool::::get(&collator).unwrap(); + let delegator = state.delegators.into_bounded_vec()[0].owner.clone(); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get()); + + // increase stake so we can unstake, because current stake is minimum + T::Currency::make_free_balance_be(&delegator, T::CurrencyBalance::from(u128::MAX)); + assert_ok!(Pallet::::delegator_stake_more(RawOrigin::Signed(delegator.clone()).into(), amount + amount)); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount + amount); + + // decrease stake once so we have an unstaking entry for this block + assert_ok!(Pallet::::delegator_stake_less(RawOrigin::Signed(delegator.clone()).into(), amount)); + assert_eq!(DelegatorState::::get(&delegator).unwrap().amount, T::MinDelegatorStake::get() + amount); + assert_eq!(Unstaking::::get(&delegator).len(), 1); + + let origin = RawOrigin::Signed(delegator.clone()); + }: _(origin) + verify { + let state = CandidatePool::::get(&collator).unwrap(); + assert!(!state.delegators.into_iter().any(|x| x.owner == delegator)); + assert!(DelegatorState::::get(&delegator).is_none()); + assert_eq!(Unstaking::::get(&delegator).len(), 2); + } + + unlock_unstaked { + let u in 1 .. (T::MaxUnstakeRequests::get() - 1); + + let candidate = account("collator", 0u32, COLLATOR_ACCOUNT_SEED); + let free_balance = T::CurrencyBalance::from(u128::MAX); + let stake = T::MinCollatorCandidateStake::get(); + T::Currency::make_free_balance_be(&candidate, free_balance); + assert_ok!(Pallet::::join_candidates( + T::RuntimeOrigin::from(Some(candidate.clone()).into()), + stake, + )); + assert_eq!(pallet_balances::Pallet::::usable_balance(&candidate), (free_balance - T::MinCollatorCandidateStake::get()).into()); + + // increase stake so we can unstake, because current stake is minimum + assert_ok!(Pallet::::candidate_stake_more(RawOrigin::Signed(candidate.clone()).into(), stake)); + + // fill unstake BTreeMap by unstaked many entries of 1 + fill_unstaking::(&candidate, None, u as u64); + assert_eq!(CandidatePool::::get(&candidate).unwrap().stake, stake + stake - T::CurrencyBalance::from(u as u64)); + + // roll to block in which first unstake can be unlocked + System::::set_block_number(T::StakeDuration::get()); + assert_eq!(pallet_balances::Pallet::::usable_balance(&candidate), (free_balance - stake - stake).into()); + let unlookup_candidate = T::Lookup::unlookup(candidate.clone()); + + let origin = RawOrigin::Signed(candidate.clone()); + }: _(origin, unlookup_candidate) + verify { + assert_eq!(Unstaking::::get(&candidate).len().saturated_into::(), u.saturating_sub(1u32)); + assert_eq!(pallet_balances::Pallet::::usable_balance(&candidate), (free_balance - stake - stake + T::CurrencyBalance::one()).into()); + } + + set_max_candidate_stake { + let old = MaxCollatorCandidateStake::::get(); + let new = MaxCollatorCandidateStake::::get() + T::CurrencyBalance::from(10u128); + }: _(RawOrigin::Root, new) + verify { + assert_eq!(MaxCollatorCandidateStake::::get(), new); + } + + increment_delegator_rewards { + let collator = setup_collator_candidates::(1, None)[0].clone(); + let delegator = fill_delegators::(1, collator.clone(), COLLATOR_ACCOUNT_SEED)[0].clone(); + + // mock high values to compensate for tiny values in unit test env + let stake = T::CurrencyBalance::from(1_000_000_000_000_000_000u128); + DelegatorState::::insert(&delegator, crate::types::Delegator { owner: collator.clone(), amount: stake}); + BlocksAuthored::::insert(&collator, u64::MAX.into()); + + assert!(Rewards::::get(&delegator).is_zero()); + let origin = RawOrigin::Signed(delegator.clone()); + }: _(origin) + verify { + assert!(!Rewards::::get(&delegator).is_zero()); + assert_eq!(BlocksRewarded::::get(&delegator), u64::MAX.into()); + } + + increment_collator_rewards { + let collator = setup_collator_candidates::(1, None)[0].clone(); + + // mock high counter to compensate for tiny amounts in unit test env + BlocksAuthored::::insert(&collator, u64::MAX.into()); + assert!(Rewards::::get(&collator).is_zero(), "reward {:?}", Rewards::::get(&collator)); + let origin = RawOrigin::Signed(collator.clone()); + }: _(origin) + verify { + assert!(!Rewards::::get(&collator).is_zero()); + assert_eq!(BlocksRewarded::::get(&collator), u64::MAX.into()); + } + + claim_rewards { + let beneficiary = account("beneficiary", 0, 0); + let amount = T::MinCollatorCandidateStake::get(); + T::Currency::make_free_balance_be(&beneficiary, amount); + Rewards::::insert(&beneficiary, amount); + assert_eq!(pallet_balances::Pallet::::usable_balance(&beneficiary), amount.into()); + let origin = RawOrigin::Signed(beneficiary.clone()); + }: _(origin) + verify { + assert!(Rewards::::get(&beneficiary).is_zero()); + assert_eq!(pallet_balances::Pallet::::usable_balance(&beneficiary), (amount + amount).into()); + } + + execute_scheduled_reward_change { + // we need at least 1 collators + let n in 0 .. T::MaxTopCandidates::get(); + // we need at least 1 delegator + let m in 0 .. T::MaxDelegatorsPerCollator::get(); + + let candidates = setup_collator_candidates::(n, None); + for (i, c) in candidates.iter().enumerate() { + fill_delegators::(m, c.clone(), i.saturated_into::()); + } + let collator = candidates[0].clone(); + + let old = InflationConfig::::get(); + assert_eq!(LastRewardReduction::::get(), T::BlockNumber::zero()); + System::::set_block_number(T::BLOCKS_PER_YEAR + T::BlockNumber::one()); + }: _(RawOrigin::Signed(collator)) + verify { + let new = InflationConfig::::get(); + assert_eq!(LastRewardReduction::::get(), T::BlockNumber::one()); + assert_eq!(new.collator.max_rate, old.collator.max_rate); + assert_eq!(new.delegator.max_rate, old.delegator.max_rate); + assert!(new.collator.reward_rate.annual < old.collator.reward_rate.annual); + assert!(new.delegator.reward_rate.annual < old.delegator.reward_rate.annual); + } + +} + +impl_benchmark_test_suite!( + Pallet, + crate::mock::ExtBuilder::default() + .with_balances(vec![(u64::MAX, 1000 * crate::mock::MILLI_KILT)]) + .with_collators(vec![(u64::MAX, 1000 * crate::mock::MILLI_KILT)]) + .build(), + crate::mock::Test, +); diff --git a/pallets/parachain-staking/src/default_weights.rs b/pallets/parachain-staking/src/default_weights.rs new file mode 100644 index 000000000..aeb1d1081 --- /dev/null +++ b/pallets/parachain-staking/src/default_weights.rs @@ -0,0 +1,843 @@ +// KILT Blockchain – https://botlabs.org +// Copyright (C) 2019-2023 BOTLabs GmbH + +// The KILT Blockchain 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. + +// The KILT Blockchain 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 this program. If not, see . + +// If you feel like getting in touch with us, you can do so at info@botlabs.org + +//! Autogenerated weights for parachain_staking +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-02-01, STEPS: {{cmd.steps}}\, REPEAT: {{cmd.repeat}}\, LOW RANGE: {{cmd.lowest_range_values}}\, HIGH RANGE: {{cmd.highest_range_values}}\ +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/kilt-parachain +// benchmark +// pallet +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=parachain-staking +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./pallets/parachain-staking/src/default_weights.rs +// --template=.maintain/weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(clippy::unnecessary_cast)] + +use frame_support::{traits::Get, weights::{constants::RocksDbWeight, Weight}}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for parachain_staking. +pub trait WeightInfo { + fn on_initialize_no_action() -> Weight; + fn on_initialize_round_update() -> Weight; + fn on_initialize_network_rewards() -> Weight; + fn force_new_round() -> Weight; + fn set_inflation(n: u32, m: u32, ) -> Weight; + fn set_max_selected_candidates(n: u32, m: u32, ) -> Weight; + fn set_blocks_per_round() -> Weight; + fn force_remove_candidate(n: u32, m: u32, ) -> Weight; + fn join_candidates(n: u32, m: u32, ) -> Weight; + fn init_leave_candidates(n: u32, m: u32, ) -> Weight; + fn cancel_leave_candidates(n: u32, m: u32, ) -> Weight; + fn execute_leave_candidates(n: u32, m: u32, ) -> Weight; + fn candidate_stake_more(n: u32, m: u32, u: u32, ) -> Weight; + fn candidate_stake_less(n: u32, m: u32, ) -> Weight; + fn join_delegators(n: u32, m: u32, ) -> Weight; + fn delegator_stake_more(n: u32, m: u32, u: u32, ) -> Weight; + fn delegator_stake_less(n: u32, m: u32, ) -> Weight; + fn leave_delegators(n: u32, m: u32, ) -> Weight; + fn unlock_unstaked(u: u32, ) -> Weight; + fn set_max_candidate_stake() -> Weight; + fn increment_delegator_rewards() -> Weight; + fn increment_collator_rewards() -> Weight; + fn claim_rewards() -> Weight; + fn execute_scheduled_reward_change(n: u32, m: u32, ) -> Weight; +} + +/// Weights for parachain_staking using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + // Storage: ParachainStaking Round (r:1 w:0) + fn on_initialize_no_action() -> Weight { + Weight::from_ref_time(7_295_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + } + // Storage: ParachainStaking Round (r:1 w:1) + fn on_initialize_round_update() -> Weight { + Weight::from_ref_time(20_334_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking Round (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + // Storage: System Account (r:1 w:1) + fn on_initialize_network_rewards() -> Weight { + Weight::from_ref_time(53_479_000 as u64) + .saturating_add(T::DbWeight::get().reads(5 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking ForceNewRound (r:0 w:1) + fn force_new_round() -> Weight { + Weight::from_ref_time(15_272_000 as u64) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking CandidatePool (r:3 w:0) + // Storage: ParachainStaking BlocksAuthored (r:2 w:0) + // Storage: ParachainStaking BlocksRewarded (r:72 w:72) + // Storage: ParachainStaking Rewards (r:72 w:72) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:1) + // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) + /// The range of component `n` is `[0, 75]`. + /// The range of component `m` is `[0, 35]`. + fn set_inflation(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(880_206_000 as u64) + // Standard Error: 5_316_702 + .saturating_add(Weight::from_ref_time(170_934_184 as u64).saturating_mul(n as u64)) + // Standard Error: 11_414_842 + .saturating_add(Weight::from_ref_time(326_552_012 as u64).saturating_mul(m as u64)) + .saturating_add(T::DbWeight::get().reads(152 as u64)) + .saturating_add(T::DbWeight::get().reads((27 as u64).saturating_mul(n as u64))) + .saturating_add(T::DbWeight::get().reads((51 as u64).saturating_mul(m as u64))) + .saturating_add(T::DbWeight::get().writes(145 as u64)) + .saturating_add(T::DbWeight::get().writes((25 as u64).saturating_mul(n as u64))) + .saturating_add(T::DbWeight::get().writes((51 as u64).saturating_mul(m as u64))) + } + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:0) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:0) + /// The range of component `n` is `[16, 75]`. + /// The range of component `m` is `[0, 35]`. + fn set_max_selected_candidates(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(71_790_000 as u64) + // Standard Error: 27_483 + .saturating_add(Weight::from_ref_time(3_582_143 as u64).saturating_mul(n as u64)) + // Standard Error: 60_832 + .saturating_add(Weight::from_ref_time(349_083 as u64).saturating_mul(m as u64)) + .saturating_add(T::DbWeight::get().reads(3 as u64)) + .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(n as u64))) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking Round (r:1 w:1) + fn set_blocks_per_round() -> Weight { + Weight::from_ref_time(56_977_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking CandidatePool (r:17 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking BlocksAuthored (r:1 w:1) + // Storage: ParachainStaking BlocksRewarded (r:36 w:36) + // Storage: ParachainStaking Rewards (r:36 w:36) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + // Storage: ParachainStaking Unstaking (r:36 w:36) + // Storage: ParachainStaking DelegatorState (r:35 w:35) + // Storage: Session Validators (r:1 w:0) + // Storage: Session DisabledValidators (r:1 w:1) + // Storage: System Digest (r:1 w:1) + // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + /// The range of component `n` is `[17, 75]`. + /// The range of component `m` is `[0, 35]`. + fn force_remove_candidate(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(167_630_000 as u64) + // Standard Error: 33_915 + .saturating_add(Weight::from_ref_time(1_267_282 as u64).saturating_mul(n as u64)) + // Standard Error: 75_237 + .saturating_add(Weight::from_ref_time(32_352_601 as u64).saturating_mul(m as u64)) + .saturating_add(T::DbWeight::get().reads(29 as u64)) + .saturating_add(T::DbWeight::get().reads((4 as u64).saturating_mul(m as u64))) + .saturating_add(T::DbWeight::get().writes(10 as u64)) + .saturating_add(T::DbWeight::get().writes((4 as u64).saturating_mul(m as u64))) + } + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:0) + // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) + // Storage: ParachainStaking Unstaking (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) + /// The range of component `n` is `[1, 74]`. + /// The range of component `m` is `[0, 35]`. + fn join_candidates(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(74_868_992 as u64) + // Standard Error: 15_510 + .saturating_add(Weight::from_ref_time(844_907 as u64).saturating_mul(n as u64)) + // Standard Error: 32_208 + .saturating_add(Weight::from_ref_time(1_664_228 as u64).saturating_mul(m as u64)) + .saturating_add(T::DbWeight::get().reads(10 as u64)) + .saturating_add(T::DbWeight::get().writes(7 as u64)) + } + // Storage: ParachainStaking CandidatePool (r:17 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking Round (r:1 w:0) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[17, 74]`. + /// The range of component `m` is `[0, 35]`. + fn init_leave_candidates(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(102_892_381 as u64) + // Standard Error: 15_634 + .saturating_add(Weight::from_ref_time(884_087 as u64).saturating_mul(n as u64)) + // Standard Error: 25_354 + .saturating_add(Weight::from_ref_time(1_951_960 as u64).saturating_mul(m as u64)) + .saturating_add(T::DbWeight::get().reads(21 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) + } + // Storage: ParachainStaking CandidatePool (r:2 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[17, 74]`. + /// The range of component `m` is `[0, 35]`. + fn cancel_leave_candidates(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(62_163_088 as u64) + // Standard Error: 11_849 + .saturating_add(Weight::from_ref_time(470_670 as u64).saturating_mul(n as u64)) + // Standard Error: 19_216 + .saturating_add(Weight::from_ref_time(1_150_199 as u64).saturating_mul(m as u64)) + .saturating_add(T::DbWeight::get().reads(5 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) + } + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Round (r:1 w:0) + // Storage: ParachainStaking BlocksAuthored (r:1 w:1) + // Storage: ParachainStaking BlocksRewarded (r:36 w:36) + // Storage: ParachainStaking Rewards (r:36 w:36) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + // Storage: ParachainStaking Unstaking (r:36 w:36) + // Storage: ParachainStaking DelegatorState (r:35 w:35) + // Storage: Session Validators (r:1 w:0) + // Storage: Session DisabledValidators (r:1 w:1) + // Storage: System Digest (r:1 w:1) + // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) + /// The range of component `n` is `[17, 74]`. + /// The range of component `m` is `[0, 35]`. + fn execute_leave_candidates(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(101_532_000 as u64) + // Standard Error: 33_213 + .saturating_add(Weight::from_ref_time(1_131_850 as u64).saturating_mul(n as u64)) + // Standard Error: 72_738 + .saturating_add(Weight::from_ref_time(32_258_326 as u64).saturating_mul(m as u64)) + .saturating_add(T::DbWeight::get().reads(12 as u64)) + .saturating_add(T::DbWeight::get().reads((4 as u64).saturating_mul(m as u64))) + .saturating_add(T::DbWeight::get().writes(8 as u64)) + .saturating_add(T::DbWeight::get().writes((4 as u64).saturating_mul(m as u64))) + } + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking Unstaking (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking BlocksAuthored (r:1 w:0) + // Storage: ParachainStaking BlocksRewarded (r:1 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `n` is `[1, 74]`. + /// The range of component `m` is `[0, 35]`. + /// The range of component `u` is `[0, 9]`. + fn candidate_stake_more(n: u32, m: u32, u: u32) -> Weight { + Weight::from_ref_time(71_965_734 as u64) + // Standard Error: 13_893 + .saturating_add(Weight::from_ref_time(925_357 as u64).saturating_mul(n as u64)) + // Standard Error: 28_840 + .saturating_add(Weight::from_ref_time(1_887_704 as u64).saturating_mul(m as u64)) + // Standard Error: 106_831 + .saturating_add(Weight::from_ref_time(1_865_718 as u64).saturating_mul(u as u64)) + .saturating_add(T::DbWeight::get().reads(12 as u64)) + .saturating_add(T::DbWeight::get().writes(8 as u64)) + } + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Unstaking (r:1 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking BlocksAuthored (r:1 w:0) + // Storage: ParachainStaking BlocksRewarded (r:1 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `n` is `[1, 74]`. + /// The range of component `m` is `[0, 35]`. + fn candidate_stake_less(n: u32, m: u32) -> Weight { + Weight::from_ref_time(62_739_612 as u64) + // Standard Error: 16_793 + .saturating_add(Weight::from_ref_time(864_759 as u64).saturating_mul(n as u64)) + // Standard Error: 34_871 + .saturating_add(Weight::from_ref_time(1_709_617 as u64).saturating_mul(m as u64)) + .saturating_add(T::DbWeight::get().reads(9 as u64)) + .saturating_add(T::DbWeight::get().writes(6 as u64)) + } + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:2 w:1) + // Storage: ParachainStaking Unstaking (r:1 w:1) + // Storage: ParachainStaking LastDelegation (r:1 w:1) + // Storage: ParachainStaking Round (r:1 w:0) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking BlocksAuthored (r:1 w:0) + // Storage: ParachainStaking BlocksRewarded (r:0 w:1) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. + fn join_delegators(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(77_485_243 as u64) + // Standard Error: 14_703 + .saturating_add(Weight::from_ref_time(1_058_123 as u64).saturating_mul(n as u64)) + // Standard Error: 32_678 + .saturating_add(Weight::from_ref_time(2_182_817 as u64).saturating_mul(m as u64)) + .saturating_add(T::DbWeight::get().reads(12 as u64)) + .saturating_add(T::DbWeight::get().writes(9 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking Unstaking (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking BlocksAuthored (r:1 w:0) + // Storage: ParachainStaking BlocksRewarded (r:1 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. + /// The range of component `u` is `[1, 9]`. + fn delegator_stake_more(n: u32, m: u32, u: u32) -> Weight { + Weight::from_ref_time(82_500_737 as u64) + // Standard Error: 12_571 + .saturating_add(Weight::from_ref_time(971_252 as u64).saturating_mul(n as u64)) + // Standard Error: 27_929 + .saturating_add(Weight::from_ref_time(1_947_599 as u64).saturating_mul(m as u64)) + // Standard Error: 108_324 + .saturating_add(Weight::from_ref_time(1_782_476 as u64).saturating_mul(u as u64)) + .saturating_add(T::DbWeight::get().reads(12 as u64)) + .saturating_add(T::DbWeight::get().writes(9 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Unstaking (r:1 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking BlocksAuthored (r:1 w:0) + // Storage: ParachainStaking BlocksRewarded (r:1 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. + fn delegator_stake_less(n: u32, m: u32) -> Weight { + Weight::from_ref_time(72_772_464 as u64) + // Standard Error: 14_214 + .saturating_add(Weight::from_ref_time(909_175 as u64).saturating_mul(n as u64)) + // Standard Error: 31_591 + .saturating_add(Weight::from_ref_time(1_824_513 as u64).saturating_mul(m as u64)) + .saturating_add(T::DbWeight::get().reads(10 as u64)) + .saturating_add(T::DbWeight::get().writes(7 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking BlocksAuthored (r:1 w:0) + // Storage: ParachainStaking BlocksRewarded (r:1 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + // Storage: ParachainStaking Unstaking (r:1 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. + fn leave_delegators(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(80_275_828 as u64) + // Standard Error: 14_671 + .saturating_add(Weight::from_ref_time(913_421 as u64).saturating_mul(n as u64)) + // Standard Error: 32_607 + .saturating_add(Weight::from_ref_time(1_764_476 as u64).saturating_mul(m as u64)) + .saturating_add(T::DbWeight::get().reads(10 as u64)) + .saturating_add(T::DbWeight::get().writes(7 as u64)) + } + // Storage: ParachainStaking Unstaking (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + /// The range of component `u` is `[1, 9]`. + fn unlock_unstaked(u: u32, ) -> Weight { + Weight::from_ref_time(53_730_996 as u64) + // Standard Error: 18_906 + .saturating_add(Weight::from_ref_time(410_777 as u64).saturating_mul(u as u64)) + .saturating_add(T::DbWeight::get().reads(3 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) + } + // Storage: ParachainStaking MaxCollatorCandidateStake (r:0 w:1) + fn set_max_candidate_stake() -> Weight { + Weight::from_ref_time(43_109_000 as u64) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:0) + // Storage: ParachainStaking BlocksAuthored (r:1 w:0) + // Storage: ParachainStaking BlocksRewarded (r:1 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + fn increment_delegator_rewards() -> Weight { + Weight::from_ref_time(40_000_000 as u64) + .saturating_add(T::DbWeight::get().reads(6 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking CandidatePool (r:1 w:0) + // Storage: ParachainStaking BlocksAuthored (r:1 w:0) + // Storage: ParachainStaking BlocksRewarded (r:1 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + fn increment_collator_rewards() -> Weight { + Weight::from_ref_time(35_612_000 as u64) + .saturating_add(T::DbWeight::get().reads(6 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: System Account (r:1 w:1) + fn claim_rewards() -> Weight { + Weight::from_ref_time(54_273_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking LastRewardReduction (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:3 w:0) + // Storage: ParachainStaking BlocksAuthored (r:2 w:0) + // Storage: ParachainStaking BlocksRewarded (r:72 w:72) + // Storage: ParachainStaking Rewards (r:72 w:72) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) + /// The range of component `n` is `[0, 75]`. + /// The range of component `m` is `[0, 35]`. + fn execute_scheduled_reward_change(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(869_446_000 as u64) + // Standard Error: 5_211_771 + .saturating_add(Weight::from_ref_time(166_314_407 as u64).saturating_mul(n as u64)) + // Standard Error: 11_189_560 + .saturating_add(Weight::from_ref_time(321_504_163 as u64).saturating_mul(m as u64)) + .saturating_add(T::DbWeight::get().reads(153 as u64)) + .saturating_add(T::DbWeight::get().reads((27 as u64).saturating_mul(n as u64))) + .saturating_add(T::DbWeight::get().reads((51 as u64).saturating_mul(m as u64))) + .saturating_add(T::DbWeight::get().writes(146 as u64)) + .saturating_add(T::DbWeight::get().writes((25 as u64).saturating_mul(n as u64))) + .saturating_add(T::DbWeight::get().writes((51 as u64).saturating_mul(m as u64))) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + // Storage: ParachainStaking Round (r:1 w:0) + fn on_initialize_no_action() -> Weight { + Weight::from_ref_time(7_295_000 as u64) + .saturating_add(RocksDbWeight::get().reads(1 as u64)) + } + // Storage: ParachainStaking Round (r:1 w:1) + fn on_initialize_round_update() -> Weight { + Weight::from_ref_time(20_334_000 as u64) + .saturating_add(RocksDbWeight::get().reads(1 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking Round (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + // Storage: System Account (r:1 w:1) + fn on_initialize_network_rewards() -> Weight { + Weight::from_ref_time(53_479_000 as u64) + .saturating_add(RocksDbWeight::get().reads(5 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking ForceNewRound (r:0 w:1) + fn force_new_round() -> Weight { + Weight::from_ref_time(15_272_000 as u64) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking CandidatePool (r:3 w:0) + // Storage: ParachainStaking BlocksAuthored (r:2 w:0) + // Storage: ParachainStaking BlocksRewarded (r:72 w:72) + // Storage: ParachainStaking Rewards (r:72 w:72) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:1) + // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) + /// The range of component `n` is `[0, 75]`. + /// The range of component `m` is `[0, 35]`. + fn set_inflation(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(880_206_000 as u64) + // Standard Error: 5_316_702 + .saturating_add(Weight::from_ref_time(170_934_184 as u64).saturating_mul(n as u64)) + // Standard Error: 11_414_842 + .saturating_add(Weight::from_ref_time(326_552_012 as u64).saturating_mul(m as u64)) + .saturating_add(RocksDbWeight::get().reads(152 as u64)) + .saturating_add(RocksDbWeight::get().reads((27 as u64).saturating_mul(n as u64))) + .saturating_add(RocksDbWeight::get().reads((51 as u64).saturating_mul(m as u64))) + .saturating_add(RocksDbWeight::get().writes(145 as u64)) + .saturating_add(RocksDbWeight::get().writes((25 as u64).saturating_mul(n as u64))) + .saturating_add(RocksDbWeight::get().writes((51 as u64).saturating_mul(m as u64))) + } + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:0) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:0) + /// The range of component `n` is `[16, 75]`. + /// The range of component `m` is `[0, 35]`. + fn set_max_selected_candidates(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(71_790_000 as u64) + // Standard Error: 27_483 + .saturating_add(Weight::from_ref_time(3_582_143 as u64).saturating_mul(n as u64)) + // Standard Error: 60_832 + .saturating_add(Weight::from_ref_time(349_083 as u64).saturating_mul(m as u64)) + .saturating_add(RocksDbWeight::get().reads(3 as u64)) + .saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(n as u64))) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking Round (r:1 w:1) + fn set_blocks_per_round() -> Weight { + Weight::from_ref_time(56_977_000 as u64) + .saturating_add(RocksDbWeight::get().reads(1 as u64)) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking CandidatePool (r:17 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking BlocksAuthored (r:1 w:1) + // Storage: ParachainStaking BlocksRewarded (r:36 w:36) + // Storage: ParachainStaking Rewards (r:36 w:36) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + // Storage: ParachainStaking Unstaking (r:36 w:36) + // Storage: ParachainStaking DelegatorState (r:35 w:35) + // Storage: Session Validators (r:1 w:0) + // Storage: Session DisabledValidators (r:1 w:1) + // Storage: System Digest (r:1 w:1) + // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + /// The range of component `n` is `[17, 75]`. + /// The range of component `m` is `[0, 35]`. + fn force_remove_candidate(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(167_630_000 as u64) + // Standard Error: 33_915 + .saturating_add(Weight::from_ref_time(1_267_282 as u64).saturating_mul(n as u64)) + // Standard Error: 75_237 + .saturating_add(Weight::from_ref_time(32_352_601 as u64).saturating_mul(m as u64)) + .saturating_add(RocksDbWeight::get().reads(29 as u64)) + .saturating_add(RocksDbWeight::get().reads((4 as u64).saturating_mul(m as u64))) + .saturating_add(RocksDbWeight::get().writes(10 as u64)) + .saturating_add(RocksDbWeight::get().writes((4 as u64).saturating_mul(m as u64))) + } + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:0) + // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) + // Storage: ParachainStaking Unstaking (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) + /// The range of component `n` is `[1, 74]`. + /// The range of component `m` is `[0, 35]`. + fn join_candidates(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(74_868_992 as u64) + // Standard Error: 15_510 + .saturating_add(Weight::from_ref_time(844_907 as u64).saturating_mul(n as u64)) + // Standard Error: 32_208 + .saturating_add(Weight::from_ref_time(1_664_228 as u64).saturating_mul(m as u64)) + .saturating_add(RocksDbWeight::get().reads(10 as u64)) + .saturating_add(RocksDbWeight::get().writes(7 as u64)) + } + // Storage: ParachainStaking CandidatePool (r:17 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking Round (r:1 w:0) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[17, 74]`. + /// The range of component `m` is `[0, 35]`. + fn init_leave_candidates(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(102_892_381 as u64) + // Standard Error: 15_634 + .saturating_add(Weight::from_ref_time(884_087 as u64).saturating_mul(n as u64)) + // Standard Error: 25_354 + .saturating_add(Weight::from_ref_time(1_951_960 as u64).saturating_mul(m as u64)) + .saturating_add(RocksDbWeight::get().reads(21 as u64)) + .saturating_add(RocksDbWeight::get().writes(3 as u64)) + } + // Storage: ParachainStaking CandidatePool (r:2 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + /// The range of component `n` is `[17, 74]`. + /// The range of component `m` is `[0, 35]`. + fn cancel_leave_candidates(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(62_163_088 as u64) + // Standard Error: 11_849 + .saturating_add(Weight::from_ref_time(470_670 as u64).saturating_mul(n as u64)) + // Standard Error: 19_216 + .saturating_add(Weight::from_ref_time(1_150_199 as u64).saturating_mul(m as u64)) + .saturating_add(RocksDbWeight::get().reads(5 as u64)) + .saturating_add(RocksDbWeight::get().writes(3 as u64)) + } + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Round (r:1 w:0) + // Storage: ParachainStaking BlocksAuthored (r:1 w:1) + // Storage: ParachainStaking BlocksRewarded (r:36 w:36) + // Storage: ParachainStaking Rewards (r:36 w:36) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + // Storage: ParachainStaking Unstaking (r:36 w:36) + // Storage: ParachainStaking DelegatorState (r:35 w:35) + // Storage: Session Validators (r:1 w:0) + // Storage: Session DisabledValidators (r:1 w:1) + // Storage: System Digest (r:1 w:1) + // Storage: ParachainStaking CounterForCandidatePool (r:1 w:1) + /// The range of component `n` is `[17, 74]`. + /// The range of component `m` is `[0, 35]`. + fn execute_leave_candidates(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(101_532_000 as u64) + // Standard Error: 33_213 + .saturating_add(Weight::from_ref_time(1_131_850 as u64).saturating_mul(n as u64)) + // Standard Error: 72_738 + .saturating_add(Weight::from_ref_time(32_258_326 as u64).saturating_mul(m as u64)) + .saturating_add(RocksDbWeight::get().reads(12 as u64)) + .saturating_add(RocksDbWeight::get().reads((4 as u64).saturating_mul(m as u64))) + .saturating_add(RocksDbWeight::get().writes(8 as u64)) + .saturating_add(RocksDbWeight::get().writes((4 as u64).saturating_mul(m as u64))) + } + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking MaxCollatorCandidateStake (r:1 w:0) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking Unstaking (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking BlocksAuthored (r:1 w:0) + // Storage: ParachainStaking BlocksRewarded (r:1 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `n` is `[1, 74]`. + /// The range of component `m` is `[0, 35]`. + /// The range of component `u` is `[0, 9]`. + fn candidate_stake_more(n: u32, m: u32, u: u32) -> Weight { + Weight::from_ref_time(71_965_734 as u64) + // Standard Error: 13_893 + .saturating_add(Weight::from_ref_time(925_357 as u64).saturating_mul(n as u64)) + // Standard Error: 28_840 + .saturating_add(Weight::from_ref_time(1_887_704 as u64).saturating_mul(m as u64)) + // Standard Error: 106_831 + .saturating_add(Weight::from_ref_time(1_865_718 as u64).saturating_mul(u as u64)) + .saturating_add(RocksDbWeight::get().reads(12 as u64)) + .saturating_add(RocksDbWeight::get().writes(8 as u64)) + } + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Unstaking (r:1 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking BlocksAuthored (r:1 w:0) + // Storage: ParachainStaking BlocksRewarded (r:1 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `n` is `[1, 74]`. + /// The range of component `m` is `[0, 35]`. + fn candidate_stake_less(n: u32, m: u32) -> Weight { + Weight::from_ref_time(62_739_612 as u64) + // Standard Error: 16_793 + .saturating_add(Weight::from_ref_time(864_759 as u64).saturating_mul(n as u64)) + // Standard Error: 34_871 + .saturating_add(Weight::from_ref_time(1_709_617 as u64).saturating_mul(m as u64)) + .saturating_add(RocksDbWeight::get().reads(9 as u64)) + .saturating_add(RocksDbWeight::get().writes(6 as u64)) + } + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:2 w:1) + // Storage: ParachainStaking Unstaking (r:1 w:1) + // Storage: ParachainStaking LastDelegation (r:1 w:1) + // Storage: ParachainStaking Round (r:1 w:0) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking BlocksAuthored (r:1 w:0) + // Storage: ParachainStaking BlocksRewarded (r:0 w:1) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. + fn join_delegators(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(77_485_243 as u64) + // Standard Error: 14_703 + .saturating_add(Weight::from_ref_time(1_058_123 as u64).saturating_mul(n as u64)) + // Standard Error: 32_678 + .saturating_add(Weight::from_ref_time(2_182_817 as u64).saturating_mul(m as u64)) + .saturating_add(RocksDbWeight::get().reads(12 as u64)) + .saturating_add(RocksDbWeight::get().writes(9 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: System Account (r:1 w:1) + // Storage: ParachainStaking Unstaking (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking BlocksAuthored (r:1 w:0) + // Storage: ParachainStaking BlocksRewarded (r:1 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. + /// The range of component `u` is `[1, 9]`. + fn delegator_stake_more(n: u32, m: u32, u: u32) -> Weight { + Weight::from_ref_time(82_500_737 as u64) + // Standard Error: 12_571 + .saturating_add(Weight::from_ref_time(971_252 as u64).saturating_mul(n as u64)) + // Standard Error: 27_929 + .saturating_add(Weight::from_ref_time(1_947_599 as u64).saturating_mul(m as u64)) + // Standard Error: 108_324 + .saturating_add(Weight::from_ref_time(1_782_476 as u64).saturating_mul(u as u64)) + .saturating_add(RocksDbWeight::get().reads(12 as u64)) + .saturating_add(RocksDbWeight::get().writes(9 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking Unstaking (r:1 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking BlocksAuthored (r:1 w:0) + // Storage: ParachainStaking BlocksRewarded (r:1 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. + fn delegator_stake_less(n: u32, m: u32) -> Weight { + Weight::from_ref_time(72_772_464 as u64) + // Standard Error: 14_214 + .saturating_add(Weight::from_ref_time(909_175 as u64).saturating_mul(n as u64)) + // Standard Error: 31_591 + .saturating_add(Weight::from_ref_time(1_824_513 as u64).saturating_mul(m as u64)) + .saturating_add(RocksDbWeight::get().reads(10 as u64)) + .saturating_add(RocksDbWeight::get().writes(7 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:1 w:1) + // Storage: ParachainStaking BlocksAuthored (r:1 w:0) + // Storage: ParachainStaking BlocksRewarded (r:1 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + // Storage: ParachainStaking Unstaking (r:1 w:1) + // Storage: ParachainStaking TopCandidates (r:1 w:1) + // Storage: ParachainStaking MaxSelectedCandidates (r:1 w:0) + /// The range of component `n` is `[1, 75]`. + /// The range of component `m` is `[1, 34]`. + fn leave_delegators(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(80_275_828 as u64) + // Standard Error: 14_671 + .saturating_add(Weight::from_ref_time(913_421 as u64).saturating_mul(n as u64)) + // Standard Error: 32_607 + .saturating_add(Weight::from_ref_time(1_764_476 as u64).saturating_mul(m as u64)) + .saturating_add(RocksDbWeight::get().reads(10 as u64)) + .saturating_add(RocksDbWeight::get().writes(7 as u64)) + } + // Storage: ParachainStaking Unstaking (r:1 w:1) + // Storage: Balances Locks (r:1 w:1) + // Storage: System Account (r:1 w:1) + /// The range of component `u` is `[1, 9]`. + fn unlock_unstaked(u: u32, ) -> Weight { + Weight::from_ref_time(53_730_996 as u64) + // Standard Error: 18_906 + .saturating_add(Weight::from_ref_time(410_777 as u64).saturating_mul(u as u64)) + .saturating_add(RocksDbWeight::get().reads(3 as u64)) + .saturating_add(RocksDbWeight::get().writes(3 as u64)) + } + // Storage: ParachainStaking MaxCollatorCandidateStake (r:0 w:1) + fn set_max_candidate_stake() -> Weight { + Weight::from_ref_time(43_109_000 as u64) + .saturating_add(RocksDbWeight::get().writes(1 as u64)) + } + // Storage: ParachainStaking DelegatorState (r:1 w:0) + // Storage: ParachainStaking BlocksAuthored (r:1 w:0) + // Storage: ParachainStaking BlocksRewarded (r:1 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + fn increment_delegator_rewards() -> Weight { + Weight::from_ref_time(40_000_000 as u64) + .saturating_add(RocksDbWeight::get().reads(6 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking CandidatePool (r:1 w:0) + // Storage: ParachainStaking BlocksAuthored (r:1 w:0) + // Storage: ParachainStaking BlocksRewarded (r:1 w:1) + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking InflationConfig (r:1 w:0) + fn increment_collator_rewards() -> Weight { + Weight::from_ref_time(35_612_000 as u64) + .saturating_add(RocksDbWeight::get().reads(6 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking Rewards (r:1 w:1) + // Storage: System Account (r:1 w:1) + fn claim_rewards() -> Weight { + Weight::from_ref_time(54_273_000 as u64) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) + } + // Storage: ParachainStaking LastRewardReduction (r:1 w:1) + // Storage: ParachainStaking InflationConfig (r:1 w:1) + // Storage: ParachainStaking CandidatePool (r:3 w:0) + // Storage: ParachainStaking BlocksAuthored (r:2 w:0) + // Storage: ParachainStaking BlocksRewarded (r:72 w:72) + // Storage: ParachainStaking Rewards (r:72 w:72) + // Storage: ParachainStaking TotalCollatorStake (r:1 w:0) + // Storage: ParachainStaking CounterForCandidatePool (r:1 w:0) + /// The range of component `n` is `[0, 75]`. + /// The range of component `m` is `[0, 35]`. + fn execute_scheduled_reward_change(n: u32, m: u32, ) -> Weight { + Weight::from_ref_time(869_446_000 as u64) + // Standard Error: 5_211_771 + .saturating_add(Weight::from_ref_time(166_314_407 as u64).saturating_mul(n as u64)) + // Standard Error: 11_189_560 + .saturating_add(Weight::from_ref_time(321_504_163 as u64).saturating_mul(m as u64)) + .saturating_add(RocksDbWeight::get().reads(153 as u64)) + .saturating_add(RocksDbWeight::get().reads((27 as u64).saturating_mul(n as u64))) + .saturating_add(RocksDbWeight::get().reads((51 as u64).saturating_mul(m as u64))) + .saturating_add(RocksDbWeight::get().writes(146 as u64)) + .saturating_add(RocksDbWeight::get().writes((25 as u64).saturating_mul(n as u64))) + .saturating_add(RocksDbWeight::get().writes((51 as u64).saturating_mul(m as u64))) + } +} diff --git a/pallets/parachain-staking/src/inflation.rs b/pallets/parachain-staking/src/inflation.rs new file mode 100644 index 000000000..170e4d89c --- /dev/null +++ b/pallets/parachain-staking/src/inflation.rs @@ -0,0 +1,384 @@ +// KILT Blockchain – https://botlabs.org +// Copyright (C) 2019-2023 BOTLabs GmbH + +// The KILT Blockchain 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. + +// The KILT Blockchain 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 this program. If not, see . + +// If you feel like getting in touch with us, you can do so at info@botlabs.org + +//! Helper methods for computing issuance based on inflation +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +#[cfg(feature = "std")] +use serde::{Deserialize, Serialize}; +use sp_runtime::{traits::Saturating, Perquintill, RuntimeDebug}; + +use crate::{pallet::Config, types::BalanceOf}; + +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Eq, PartialEq, Clone, Encode, Decode, Default, RuntimeDebug, TypeInfo)] +pub struct RewardRate { + pub annual: Perquintill, + pub per_block: Perquintill, +} + +impl MaxEncodedLen for RewardRate { + fn max_encoded_len() -> usize { + // Perquintill is at most u128 + u128::max_encoded_len().saturating_add(u128::max_encoded_len()) + } +} + +/// Convert annual reward rate to per_block. +fn annual_to_per_block(blocks_per_year: u64, rate: Perquintill) -> Perquintill { + rate / blocks_per_year.max(1) +} + +impl RewardRate { + pub fn new(blocks_per_year: u64, rate: Perquintill) -> Self { + RewardRate { + annual: rate, + per_block: annual_to_per_block(blocks_per_year, rate), + } + } +} + +/// Staking info (staking rate and reward rate) for collators and delegators. +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Eq, PartialEq, Clone, Encode, Decode, Default, RuntimeDebug, TypeInfo)] +pub struct StakingInfo { + /// Maximum staking rate. + pub max_rate: Perquintill, + /// Reward rate annually and per_block. + pub reward_rate: RewardRate, +} + +impl MaxEncodedLen for StakingInfo { + fn max_encoded_len() -> usize { + // Perquintill is at most u128 + RewardRate::max_encoded_len().saturating_add(u128::max_encoded_len()) + } +} + +impl StakingInfo { + pub fn new(blocks_per_year: u64, max_rate: Perquintill, annual_reward_rate: Perquintill) -> Self { + StakingInfo { + max_rate, + reward_rate: RewardRate::new(blocks_per_year, annual_reward_rate), + } + } + + /// Calculate newly minted rewards on coinbase, e.g., + /// reward = rewards_per_block * staking_rate. + /// + /// NOTE: If we exceed the max staking rate, the reward will be reduced by + /// max_rate / current_rate. + pub fn compute_reward( + &self, stake: BalanceOf, current_staking_rate: Perquintill, authors_per_round: BalanceOf, + ) -> BalanceOf { + // Perquintill automatically bounds to [0, 100]% in case staking_rate is greater + // than self.max_rate + let reduction = Perquintill::from_rational(self.max_rate.deconstruct(), current_staking_rate.deconstruct()); + // multiplication with perbill cannot overflow + let reward = (self.reward_rate.per_block * stake).saturating_mul(authors_per_round); + reduction * reward + } +} + +#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] +#[derive(Eq, PartialEq, Clone, Encode, Decode, Default, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct InflationInfo { + pub collator: StakingInfo, + pub delegator: StakingInfo, +} + +impl InflationInfo { + /// Create a new inflation info from the max staking rates and annual reward + /// rates for collators and delegators. + /// + /// Example: InflationInfo::new(Perquintill_from_percent(10), ...) + pub fn new( + blocks_per_year: u64, collator_max_rate_percentage: Perquintill, + collator_annual_reward_rate_percentage: Perquintill, delegator_max_rate_percentage: Perquintill, + delegator_annual_reward_rate_percentage: Perquintill, + ) -> Self { + Self { + collator: StakingInfo::new( + blocks_per_year, + collator_max_rate_percentage, + collator_annual_reward_rate_percentage, + ), + delegator: StakingInfo::new( + blocks_per_year, + delegator_max_rate_percentage, + delegator_annual_reward_rate_percentage, + ), + } + } + + /// Check whether the annual reward rate is approx. the per_block reward + /// rate multiplied with the number of blocks per year + pub fn is_valid(&self, blocks_per_year: u64) -> bool { + self.collator.reward_rate.annual + >= Perquintill::from_parts( + self.collator + .reward_rate + .per_block + .deconstruct() + .saturating_mul(blocks_per_year), + ) && self.delegator.reward_rate.annual + >= Perquintill::from_parts( + self.delegator + .reward_rate + .per_block + .deconstruct() + .saturating_mul(blocks_per_year), + ) + } +} + +#[cfg(test)] +mod tests { + use sp_runtime::Perbill; + + use crate::mock::{almost_equal, ExtBuilder, Test, DECIMALS, MAX_COLLATOR_STAKE}; + + use super::*; + + #[test] + fn perquintill() { + assert_eq!( + Perquintill::from_percent(100) * Perquintill::from_percent(50), + Perquintill::from_percent(50) + ); + } + + #[test] + fn annual_to_block_rate() { + let rate = Perquintill::one(); + assert!(almost_equal( + rate * 10_000_000_000u128, + Perquintill::from_parts( + annual_to_per_block(::BLOCKS_PER_YEAR, rate).deconstruct() + * ::BLOCKS_PER_YEAR + ) * 10_000_000_000u128, + Perbill::from_perthousand(1) + )); + } + + #[test] + fn single_block_reward_collator() { + let inflation = InflationInfo::new( + ::BLOCKS_PER_YEAR, + Perquintill::from_percent(10), + Perquintill::from_percent(10), + Perquintill::from_percent(40), + Perquintill::from_percent(8), + ); + let reward = inflation + .collator + .compute_reward::(MAX_COLLATOR_STAKE, Perquintill::from_percent(9), 2); + let expected = ::CurrencyBalance::from(15210282150733u64); + assert!( + almost_equal(reward, expected, Perbill::from_perthousand(1)), + "left {:?}, right {:?}", + reward, + expected + ); + } + + #[test] + fn simple_block_reward_check() { + let precision = Perbill::from_perthousand(1); + ExtBuilder::default() + .with_inflation(10, 15, 40, 10, 5) + .with_balances(vec![(1, 10)]) + .with_collators(vec![(1, 10)]) + .build() + .execute_with(|| { + let inflation = InflationInfo::new( + ::BLOCKS_PER_YEAR, + Perquintill::from_percent(10), + Perquintill::from_percent(15), + Perquintill::from_percent(40), + Perquintill::from_percent(10), + ); + let years_u128: BalanceOf = ::BLOCKS_PER_YEAR as u128; + + // Dummy checks for correct instantiation + assert!(inflation.is_valid(::BLOCKS_PER_YEAR)); + assert_eq!(inflation.collator.max_rate, Perquintill::from_percent(10)); + assert_eq!(inflation.collator.reward_rate.annual, Perquintill::from_percent(15)); + assert!( + almost_equal( + inflation.collator.reward_rate.per_block * DECIMALS * 10_000, + Perquintill::from_percent(15) * 10_000 * DECIMALS / years_u128, + precision + ), + "left = {:?}, right = {:?}", + inflation.collator.reward_rate.per_block * 10_000 * DECIMALS, + Perquintill::from_percent(15) * 10_000 * DECIMALS / years_u128, + ); + assert_eq!(inflation.delegator.max_rate, Perquintill::from_percent(40)); + assert_eq!(inflation.delegator.reward_rate.annual, Perquintill::from_percent(10)); + assert!( + almost_equal( + inflation.delegator.reward_rate.per_block * DECIMALS * 10_000, + Perquintill::from_percent(10) * 10_000 * DECIMALS / years_u128, + precision + ), + "left = {:?}, right = {:?}", + inflation.delegator.reward_rate.per_block * DECIMALS * 10_000, + Perquintill::from_percent(10) * 10_000 * DECIMALS / years_u128, + ); + + // Check collator reward computation + let authors_per_round = 1u128; + let mut current_staking_rate: Perquintill = inflation.collator.max_rate; + assert_eq!( + inflation + .collator + .compute_reward::(0, current_staking_rate, authors_per_round), + 0 + ); + current_staking_rate = Perquintill::from_rational(5000u64, 100_000u64); + assert!( + almost_equal( + inflation.collator.compute_reward::( + 5000 * DECIMALS, + current_staking_rate, + authors_per_round + ) * years_u128, + Perquintill::from_percent(15) * 5000 * DECIMALS, + Perbill::from_percent(1) + ), + "left = {:?}, right = {:?}", + inflation + .collator + .compute_reward::(5000 * DECIMALS, current_staking_rate, authors_per_round) + * years_u128, + Perquintill::from_percent(15) * 5000 * DECIMALS, + ); + // Check for max_rate which is 10% + current_staking_rate = Perquintill::from_rational(10_000u64, 100_000u64); + assert!( + almost_equal( + inflation.collator.compute_reward::( + 10_000 * DECIMALS, + current_staking_rate, + authors_per_round + ) * years_u128, + Perquintill::from_percent(15) * 10_000 * DECIMALS, + Perbill::from_percent(1) + ), + "left = {:?}, right = {:?}", + inflation.collator.compute_reward::( + 10_000 * DECIMALS, + current_staking_rate, + authors_per_round + ) * years_u128, + Perquintill::from_percent(15) * 10_000 * DECIMALS, + ); + + // Check for exceeding max_rate: 50% instead of 10% + current_staking_rate = Perquintill::from_rational(50_000u64, 100_000u64); + assert!( + almost_equal( + inflation.collator.compute_reward::( + 50_000 * DECIMALS, + current_staking_rate, + authors_per_round + ) * years_u128, + Perquintill::from_percent(15) * 10_000 * DECIMALS, + Perbill::from_percent(1) + ), + "left = {:?}, right = {:?}", + inflation.collator.compute_reward::( + 50_000 * DECIMALS, + current_staking_rate, + authors_per_round + ) * years_u128, + Perquintill::from_percent(15) * 10_000 * DECIMALS, + ); + + // Check delegator reward computation + current_staking_rate = inflation.delegator.max_rate; + assert_eq!( + inflation + .delegator + .compute_reward::(0, current_staking_rate, authors_per_round), + 0 + ); + current_staking_rate = Perquintill::from_rational(5000u64, 100_000u64); + assert!( + almost_equal( + inflation.delegator.compute_reward::( + 5000 * DECIMALS, + current_staking_rate, + authors_per_round + ) * years_u128, + Perquintill::from_percent(10) * 5000 * DECIMALS, + Perbill::from_percent(1) + ), + "left = {:?}, right = {:?}", + inflation.delegator.compute_reward::( + 5000 * DECIMALS, + current_staking_rate, + authors_per_round + ) * years_u128, + Perquintill::from_percent(10) * 5000 * DECIMALS, + ); + // Check for max_rate which is 40% + current_staking_rate = Perquintill::from_rational(40_000u64, 100_000u64); + assert!( + almost_equal( + inflation.delegator.compute_reward::( + 40_000 * DECIMALS, + current_staking_rate, + authors_per_round + ) * years_u128, + Perquintill::from_percent(10) * 40_000 * DECIMALS, + Perbill::from_percent(1) + ), + "left = {:?}, right = {:?}", + inflation.delegator.compute_reward::( + 40_000 * DECIMALS, + current_staking_rate, + authors_per_round + ) * years_u128, + Perquintill::from_percent(10) * 40_000 * DECIMALS, + ); + + // Check for exceeding max_rate: 50% instead of 40% + current_staking_rate = Perquintill::from_rational(50_000u64, 100_000u64); + assert!( + almost_equal( + inflation.delegator.compute_reward::( + 50_000 * DECIMALS, + current_staking_rate, + authors_per_round + ) * years_u128, + Perquintill::from_percent(8) * 50_000 * DECIMALS, + Perbill::from_percent(1) + ), + "left = {:?}, right = {:?}", + inflation.delegator.compute_reward::( + 50_000 * DECIMALS, + current_staking_rate, + authors_per_round + ) * years_u128, + Perquintill::from_percent(8) * 50_000 * DECIMALS, + ); + }); + } +} diff --git a/pallets/parachain-staking/src/lib.rs b/pallets/parachain-staking/src/lib.rs new file mode 100644 index 000000000..6de3c6988 --- /dev/null +++ b/pallets/parachain-staking/src/lib.rs @@ -0,0 +1,2573 @@ +// KILT Blockchain – https://botlabs.org +// Copyright (C) 2019-2023 BOTLabs GmbH + +// The KILT Blockchain 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. + +// The KILT Blockchain 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 this program. If not, see . + +// If you feel like getting in touch with us, you can do so at info@botlabs.org + +//! # Parachain Staking +//! +//! A simple staking pallet providing means of selecting a set of collators to +//! become block authors based on their total backed stake. The main difference +//! between this pallet and `frame/pallet-staking` is that this pallet uses +//! direct delegation. Delegators choose exactly who they delegate and with what +//! stake. This is different from `frame/pallet-staking` where you approval vote +//! and then run Phragmen. Moreover, this pallet rewards a collator and their +//! delegators immediately when authoring a block. Rewards are calculated +//! separately between collators and delegators. +//! +//! To join the set of candidates, an account must call `join_candidates` with +//! `MinCollatorCandidateStake` <= stake <= `MaxCollatorCandidateStake`. +//! +//! To leave the set of candidates, the collator calls `leave_candidates`. If +//! the call succeeds, the collator is removed from the pool of candidates so +//! they cannot be selected for future collator sets, but they are not unstaking +//! until executing the exit request by calling the extrinsic +//! `execute_leave_candidates` at least `ExitQueueDelay` rounds later. After +//! doing so, the collator candidate as well as their delegators are unstaked. +//! Both parties then have to wait another `StakeDuration` more blocks to be +//! able to unlock their stake. +//! +//! Candidates which requested to leave can still be in the set of authors for +//! the next round due to the design of the session pallet which at the start of +//! session s(i) chooses a set for the next session s(i+1). Thus, candidates +//! have to keep collating at least until the end of the next session (= round). +//! We extend this by delaying their execute by at least `ExitQueueDelay` many +//! sessions. +//! +//! To join the set of delegators, an account must call `join_delegators` with +//! stake >= `MinDelegatorStake`. There are also runtime methods for delegating +//! additional collators and revoking delegations. +//! +//! +//! - [`Config`] +//! - [`Call`] +//! - [`Pallet`] +//! +//! ## Overview +//! +//! The KILT parachain staking pallet provides functions for: +//! - Joining the set of collator candidates of which the best +//! `MaxSelectedCandidates` are chosen to become active collators for the next +//! session. That makes the set of active collators the set of block authors +//! by handing it over to the session and the authority pallet. +//! - Delegating to a collator candidate by staking for them. +//! - Increasing and reducing your stake as a collator or delegator. +//! - Revoking your delegation entirely. +//! - Requesting to leave the set of collator candidates. +//! - Withdrawing your unstaked balance after waiting for a certain number of +//! blocks. +//! +//! ### Terminology +//! +//! - **Candidate:** A user which locks up tokens to be included into the set of +//! authorities which author blocks and receive rewards for doing so. +//! +//! - **Collator:** A candidate that was chosen to collate this round. +//! +//! - **Delegator:** A user which locks up tokens for collators they trust. When +//! their collator authors a block, the corresponding delegators also receive +//! rewards. +//! +//! - **Total Stake:** A collator’s own stake + the sum of delegated stake to +//! this collator. +//! +//! - **Total collator stake:** The sum of tokens locked for staking from all +//! collator candidates. +//! +//! - **Total delegator stake:** The sum of tokens locked for staking from all +//! delegators. +//! +//! - **To Stake:** Lock tokens for staking. +//! +//! - **To Unstake:** Unlock tokens from staking. +//! +//! - **Round (= Session):** A fixed number of blocks in which the set of +//! collators does not change. We set the length of a session to the length of +//! a staking round, thus both words are interchangeable in the context of +//! this pallet. +//! +//! - **Lock:** A freeze on a specified amount of an account's free balance +//! until a specified block number. Multiple locks always operate over the +//! same funds, so they "overlay" rather than "stack" +//! +//! ## Genesis config +//! +//! The ParachainStaking pallet depends on the [`GenesisConfig`]. +//! +//! ## Assumptions +//! +//! - At the start of session s(i), the set of session ids for session s(i+1) +//! are chosen. These equal the set of selected candidates. Thus, we cannot +//! allow collators to leave at least until the start of session s(i+2). + +#![cfg_attr(not(feature = "std"), no_std)] +#![allow(clippy::unused_unit)] + +use frame_support::pallet; + +pub use crate::{default_weights::WeightInfo, pallet::*}; + +#[cfg(feature = "runtime-benchmarks")] +pub mod benchmarking; +pub mod default_weights; + +pub mod migration; +#[cfg(test)] +pub(crate) mod mock; +#[cfg(test)] +pub(crate) mod tests; + +pub mod api; +mod inflation; +mod set; +mod types; + +#[pallet] +pub mod pallet { + use frame_support::{ + assert_ok, + pallet_prelude::*, + storage::bounded_btree_map::BoundedBTreeMap, + traits::{ + Currency, EstimateNextSessionRotation, Get, Imbalance, LockIdentifier, LockableCurrency, OnUnbalanced, + ReservableCurrency, StorageVersion, WithdrawReasons, + }, + BoundedVec, + }; + use frame_system::pallet_prelude::*; + use pallet_balances::{BalanceLock, Locks}; + use pallet_session::ShouldEndSession; + use scale_info::TypeInfo; + use sp_runtime::{ + traits::{Convert, One, SaturatedConversion, Saturating, StaticLookup, Zero}, + Permill, Perquintill, + }; + use sp_staking::SessionIndex; + use sp_std::{convert::TryInto, fmt::Debug, prelude::*}; + + pub use crate::inflation::{InflationInfo, RewardRate, StakingInfo}; + use crate::{ + set::OrderedSet, + types::{ + BalanceOf, Candidate, CandidateOf, CandidateStatus, DelegationCounter, Delegator, NegativeImbalanceOf, + RoundInfo, Stake, StakeOf, TotalStake, + }, + }; + + use super::*; + + /// Kilt-specific lock for staking rewards. + pub(crate) const STAKING_ID: LockIdentifier = *b"kiltpstk"; + + /// The current storage version. + const STORAGE_VERSION: StorageVersion = StorageVersion::new(8); + + /// Pallet for parachain staking. + #[pallet::pallet] + #[pallet::generate_store(pub (super) trait Store)] + #[pallet::storage_version(STORAGE_VERSION)] + pub struct Pallet(PhantomData); + + /// Configuration trait of this pallet. + #[pallet::config] + pub trait Config: frame_system::Config + pallet_balances::Config + pallet_session::Config { + /// Overarching event type + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + // FIXME: Remove Currency and CurrencyBalance types. Problem: Need to restrict + // pallet_balances::Config::Balance with From for usage with Perquintill + // multiplication + /// The currency type + /// Note: Declaration of Balance taken from pallet_gilt + type Currency: Currency + + ReservableCurrency + + LockableCurrency + + Eq; + + /// Just the `Currency::Balance` type; we have this item to allow us to + /// constrain it to `From`. + /// Note: Definition taken from pallet_gilt + type CurrencyBalance: sp_runtime::traits::AtLeast32BitUnsigned + + parity_scale_codec::FullCodec + + Copy + + MaybeSerializeDeserialize + + sp_std::fmt::Debug + + Default + + From + + From + + Into<::Balance> + + From<::Balance> + + From + + TypeInfo + + MaxEncodedLen; + + /// Minimum number of blocks validation rounds can last. + #[pallet::constant] + type MinBlocksPerRound: Get; + + /// Default number of blocks validation rounds last, as set in the + /// genesis configuration. + #[pallet::constant] + type DefaultBlocksPerRound: Get; + /// Number of blocks for which unstaked balance will still be locked + /// before it can be unlocked by actively calling the extrinsic + /// `unlock_unstaked`. + #[pallet::constant] + type StakeDuration: Get; + /// Number of rounds a collator has to stay active after submitting a + /// request to leave the set of collator candidates. + #[pallet::constant] + type ExitQueueDelay: Get; + + /// Minimum number of collators selected from the set of candidates at + /// every validation round. + #[pallet::constant] + type MinCollators: Get; + + /// Minimum number of collators which cannot leave the network if there + /// are no others. + #[pallet::constant] + type MinRequiredCollators: Get; + + /// Maximum number of delegations which can be made within the same + /// round. + /// + /// NOTE: To prevent re-delegation-reward attacks, we should keep this + /// to be one. + #[pallet::constant] + type MaxDelegationsPerRound: Get; + + /// Maximum number of delegators a single collator can have. + #[pallet::constant] + type MaxDelegatorsPerCollator: Get + Debug + PartialEq; + + /// Maximum size of the top candidates set. + #[pallet::constant] + type MaxTopCandidates: Get + Debug + PartialEq; + + /// Minimum stake required for any account to be elected as validator + /// for a round. + #[pallet::constant] + type MinCollatorStake: Get>; + + /// Minimum stake required for any account to be added to the set of + /// candidates. + #[pallet::constant] + type MinCollatorCandidateStake: Get>; + + /// Minimum stake required for any account to become a delegator. + #[pallet::constant] + type MinDelegatorStake: Get>; + + /// Max number of concurrent active unstaking requests before + /// unlocking. + /// + /// NOTE: To protect against irremovability of a candidate or delegator, + /// we only allow for MaxUnstakeRequests - 1 many manual unstake + /// requests. The last one serves as a placeholder for the cases of + /// calling either `kick_delegator`, force_remove_candidate` or + /// `execute_leave_candidates`. Otherwise, a user could max out their + /// unstake requests and prevent themselves from being kicked from the + /// set of candidates/delegators until they unlock their funds. + #[pallet::constant] + type MaxUnstakeRequests: Get; + + /// The starting block number for the network rewards. Once the current + /// block number exceeds this start, the beneficiary will receive the + /// configured reward in each block. + #[pallet::constant] + type NetworkRewardStart: Get<::BlockNumber>; + + /// The rate in percent for the network rewards which are based on the + /// maximum number of collators and the maximum amount a collator can + /// stake. + #[pallet::constant] + type NetworkRewardRate: Get; + + /// The beneficiary to receive the network rewards. + type NetworkRewardBeneficiary: OnUnbalanced>; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; + + const BLOCKS_PER_YEAR: Self::BlockNumber; + } + + #[pallet::error] + pub enum Error { + /// The account is not part of the delegators set. + DelegatorNotFound, + /// The account is not part of the collator candidates set. + CandidateNotFound, + /// The account is already part of the delegators set. + DelegatorExists, + /// The account is already part of the collator candidates set. + CandidateExists, + /// The account tried to stake more or less with amount zero. + ValStakeZero, + /// The account has not staked enough funds to be added to the collator + /// candidates set. + ValStakeBelowMin, + /// The account has already staked the maximum amount of funds possible. + ValStakeAboveMax, + /// The account has not staked enough funds to delegate a collator + /// candidate. + DelegationBelowMin, + /// The collator candidate has already trigger the process to leave the + /// set of collator candidates. + AlreadyLeaving, + /// The collator candidate wanted to execute the exit but has not + /// requested to leave before by calling `init_leave_candidates`. + NotLeaving, + /// The collator tried to leave before waiting at least for + /// `ExitQueueDelay` many rounds. + CannotLeaveYet, + /// The account has a full list of unstaking requests and needs to + /// unlock at least one of these before being able to join (again). + /// NOTE: Can only happen if the account was a candidate or + /// delegator before and either got kicked or exited voluntarily. + CannotJoinBeforeUnlocking, + /// The account is already delegating the collator candidate. + AlreadyDelegating, + /// The account has not delegated any collator candidate yet, hence it + /// is not in the set of delegators. + NotYetDelegating, + /// The delegator has exceeded the number of delegations per round which + /// is equal to MaxDelegatorsPerCollator. + /// + /// This protects against attacks in which a delegator can re-delegate + /// from a collator who has already authored a block, to another one + /// which has not in this round. + DelegationsPerRoundExceeded, + /// The collator candidate has already reached the maximum number of + /// delegators. + /// + /// This error is generated in case a new delegation request does not + /// stake enough funds to replace some other existing delegation. + TooManyDelegators, + /// The set of collator candidates would fall below the required minimum + /// if the collator left. + TooFewCollatorCandidates, + /// The collator candidate is in the process of leaving the set of + /// candidates and cannot perform any other actions in the meantime. + CannotStakeIfLeaving, + /// The collator candidate is in the process of leaving the set of + /// candidates and thus cannot be delegated to. + CannotDelegateIfLeaving, + /// The delegator has already delegated the maximum number of candidates + /// allowed. + MaxCollatorsPerDelegatorExceeded, + /// The delegator has already previously delegated the collator + /// candidate. + AlreadyDelegatedCollator, + /// The given delegation does not exist in the set of delegations. + DelegationNotFound, + /// The collator delegate or the delegator is trying to un-stake more + /// funds that are currently staked. + Underflow, + /// The number of selected candidates per staking round is + /// above the maximum value allowed. + CannotSetAboveMax, + /// The number of selected candidates per staking round is + /// below the minimum value allowed. + CannotSetBelowMin, + /// An invalid inflation configuration is trying to be set. + InvalidSchedule, + /// The staking reward being unlocked does not exist. + /// Max unlocking requests reached. + NoMoreUnstaking, + /// The reward rate cannot be adjusted yet as an entire year has not + /// passed. + TooEarly, + /// Provided staked value is zero. Should never be thrown. + StakeNotFound, + /// Cannot unlock when Unstaked is empty. + UnstakingIsEmpty, + /// Cannot claim rewards if empty. + RewardsNotFound, + } + + #[pallet::event] + #[pallet::generate_deposit(pub(crate) fn deposit_event)] + pub enum Event { + /// A new staking round has started. + /// \[block number, round number\] + NewRound(T::BlockNumber, SessionIndex), + /// A new account has joined the set of top candidates. + /// \[account\] + EnteredTopCandidates(T::AccountId), + /// An account was removed from the set of top candidates. + /// \[account\] + LeftTopCandidates(T::AccountId), + /// A new account has joined the set of collator candidates. + /// \[account, amount staked by the new candidate\] + JoinedCollatorCandidates(T::AccountId, BalanceOf), + /// A collator candidate has increased the amount of funds at stake. + /// \[collator's account, previous stake, new stake\] + CollatorStakedMore(T::AccountId, BalanceOf, BalanceOf), + /// A collator candidate has decreased the amount of funds at stake. + /// \[collator's account, previous stake, new stake\] + CollatorStakedLess(T::AccountId, BalanceOf, BalanceOf), + /// A collator candidate has started the process to leave the set of + /// candidates. \[round number, collator's account, round number when + /// the collator will be effectively removed from the set of + /// candidates\] + CollatorScheduledExit(SessionIndex, T::AccountId, SessionIndex), + /// A collator candidate has canceled the process to leave the set of + /// candidates and was added back to the candidate pool. \[collator's + /// account\] + CollatorCanceledExit(T::AccountId), + /// An account has left the set of collator candidates. + /// \[account, amount of funds un-staked\] + CandidateLeft(T::AccountId, BalanceOf), + /// An account was forcedly removed from the set of collator + /// candidates. \[account, amount of funds un-staked\] + CollatorRemoved(T::AccountId, BalanceOf), + /// The maximum candidate stake has been changed. + /// \[new max amount\] + MaxCandidateStakeChanged(BalanceOf), + /// A delegator has increased the amount of funds at stake for a + /// collator. \[delegator's account, collator's account, previous + /// delegation stake, new delegation stake\] + DelegatorStakedMore(T::AccountId, T::AccountId, BalanceOf, BalanceOf), + /// A delegator has decreased the amount of funds at stake for a + /// collator. \[delegator's account, collator's account, previous + /// delegation stake, new delegation stake\] + DelegatorStakedLess(T::AccountId, T::AccountId, BalanceOf, BalanceOf), + /// An account has left the set of delegators. + /// \[account, amount of funds un-staked\] + DelegatorLeft(T::AccountId, BalanceOf), + /// An account has delegated a new collator candidate. + /// \[account, amount of funds staked, total amount of delegators' funds + /// staked for the collator candidate\] + Delegation(T::AccountId, BalanceOf, T::AccountId, BalanceOf), + /// A new delegation has replaced an existing one in the set of ongoing + /// delegations for a collator candidate. \[new delegator's account, + /// amount of funds staked in the new delegation, replaced delegator's + /// account, amount of funds staked in the replace delegation, collator + /// candidate's account, new total amount of delegators' funds staked + /// for the collator candidate\] + DelegationReplaced( + T::AccountId, + BalanceOf, + T::AccountId, + BalanceOf, + T::AccountId, + BalanceOf, + ), + /// An account has stopped delegating a collator candidate. + /// \[account, collator candidate's account, old amount of delegators' + /// funds staked, new amount of delegators' funds staked\] + DelegatorLeftCollator(T::AccountId, T::AccountId, BalanceOf, BalanceOf), + /// A collator or a delegator has received a reward. + /// \[account, amount of reward\] + Rewarded(T::AccountId, BalanceOf), + /// Inflation configuration for future validation rounds has changed. + /// \[maximum collator's staking rate, maximum collator's reward rate, + /// maximum delegator's staking rate, maximum delegator's reward rate\] + RoundInflationSet(Perquintill, Perquintill, Perquintill, Perquintill), + /// The maximum number of collator candidates selected in future + /// validation rounds has changed. \[old value, new value\] + MaxSelectedCandidatesSet(u32, u32), + /// The length in blocks for future validation rounds has changed. + /// \[round number, first block in the current round, old value, new + /// value\] + BlocksPerRoundSet(SessionIndex, T::BlockNumber, T::BlockNumber, T::BlockNumber), + } + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_initialize(now: T::BlockNumber) -> frame_support::weights::Weight { + let mut post_weight = ::WeightInfo::on_initialize_no_action(); + let mut round = Round::::get(); + + // check for round update + if round.should_update(now) { + // mutate round + round.update(now); + // start next round + Round::::put(round); + + Self::deposit_event(Event::NewRound(round.first, round.current)); + post_weight = ::WeightInfo::on_initialize_round_update(); + } + // check for network reward and mint + // on success, mint each block + if now > T::NetworkRewardStart::get() { + T::NetworkRewardBeneficiary::on_unbalanced(Self::issue_network_reward()); + post_weight = post_weight.saturating_add(::WeightInfo::on_initialize_network_rewards()); + } + post_weight + } + } + + /// The maximum number of collator candidates selected at each round. + #[pallet::storage] + #[pallet::getter(fn max_selected_candidates)] + pub(crate) type MaxSelectedCandidates = StorageValue<_, u32, ValueQuery>; + + /// Current round number and next round scheduled transition. + #[pallet::storage] + #[pallet::getter(fn round)] + pub(crate) type Round = StorageValue<_, RoundInfo, ValueQuery>; + + /// Delegation information for the latest session in which a delegator + /// delegated. + /// + /// It maps from an account to the number of delegations in the last + /// session in which they (re-)delegated. + #[pallet::storage] + #[pallet::getter(fn last_delegation)] + pub(crate) type LastDelegation = + StorageMap<_, Twox64Concat, T::AccountId, DelegationCounter, ValueQuery>; + + /// Delegation staking information. + /// + /// It maps from an account to its delegation details. + #[pallet::storage] + #[pallet::getter(fn delegator_state)] + pub(crate) type DelegatorState = + StorageMap<_, Twox64Concat, T::AccountId, Delegator>, OptionQuery>; + + /// The staking information for a candidate. + /// + /// It maps from an account to its information. + /// Moreover, it counts the number of candidates. + #[pallet::storage] + #[pallet::getter(fn candidate_pool)] + pub(crate) type CandidatePool = CountedStorageMap< + _, + Twox64Concat, + T::AccountId, + Candidate, T::MaxDelegatorsPerCollator>, + OptionQuery, + >; + + /// Total funds locked to back the currently selected collators. + /// The sum of all collator and their delegator stakes. + /// + /// Note: There are more funds locked by this pallet, since the backing for + /// non collating candidates is not included in [TotalCollatorStake]. + #[pallet::storage] + #[pallet::getter(fn total_collator_stake)] + pub(crate) type TotalCollatorStake = StorageValue<_, TotalStake>, ValueQuery>; + + /// The collator candidates with the highest amount of stake. + /// + /// Each time the stake of a collator is increased, it is checked whether + /// this pushes another candidate out of the list. When the stake is + /// reduced however, it is not checked if another candidate has more stake, + /// since this would require iterating over the entire [CandidatePool]. + /// + /// There must always be more candidates than [MaxSelectedCandidates] so + /// that a collator can drop out of the collator set by reducing their + /// stake. + #[pallet::storage] + #[pallet::getter(fn top_candidates)] + pub(crate) type TopCandidates = + StorageValue<_, OrderedSet>, T::MaxTopCandidates>, ValueQuery>; + + /// Inflation configuration. + #[pallet::storage] + #[pallet::getter(fn inflation_config)] + pub(crate) type InflationConfig = StorageValue<_, InflationInfo, ValueQuery>; + + /// The funds waiting to be unstaked. + /// + /// It maps from accounts to all the funds addressed to them in the future + /// blocks. + #[pallet::storage] + #[pallet::getter(fn unstaking)] + pub(crate) type Unstaking = StorageMap< + _, + Twox64Concat, + T::AccountId, + BoundedBTreeMap, T::MaxUnstakeRequests>, + ValueQuery, + >; + + /// The maximum amount a collator candidate can stake. + #[pallet::storage] + #[pallet::getter(fn max_candidate_stake)] + pub(crate) type MaxCollatorCandidateStake = StorageValue<_, BalanceOf, ValueQuery>; + + /// The year in which the last automatic reduction of the reward rates + /// occurred. + /// + /// It starts at zero at genesis and increments by one every BLOCKS_PER_YEAR + /// many blocks. + #[pallet::storage] + #[pallet::getter(fn last_reward_reduction)] + pub(crate) type LastRewardReduction = StorageValue<_, T::BlockNumber, ValueQuery>; + + /// The number of authored blocks for collators. It is updated via the + /// `note_author` hook when authoring a block . + #[pallet::storage] + #[pallet::getter(fn blocks_authored)] + pub(crate) type BlocksAuthored = StorageMap<_, Twox64Concat, T::AccountId, T::BlockNumber, ValueQuery>; + + /// The number of blocks for which rewards have been claimed by an address. + /// + /// For collators, this can be at most BlocksAuthored. It is updated when + /// incrementing collator rewards, either when calling + /// `inc_collator_rewards` or updating the `InflationInfo`. + /// + /// For delegators, this can be at most BlocksAuthored of the collator.It is + /// updated when incrementing delegator rewards, either when calling + /// `inc_delegator_rewards` or updating the `InflationInfo`. + #[pallet::storage] + #[pallet::getter(fn blocks_rewarded)] + pub(crate) type BlocksRewarded = StorageMap<_, Twox64Concat, T::AccountId, T::BlockNumber, ValueQuery>; + + /// The accumulated rewards for collator candidates and delegators. + /// + /// It maps from accounts to their total rewards since the last payout. + #[pallet::storage] + #[pallet::getter(fn rewards)] + pub(crate) type Rewards = StorageMap<_, Twox64Concat, T::AccountId, BalanceOf, ValueQuery>; + + pub type GenesisStaker = Vec<( + ::AccountId, + Option<::AccountId>, + BalanceOf, + )>; + + #[pallet::storage] + #[pallet::getter(fn new_round_forced)] + pub(crate) type ForceNewRound = StorageValue<_, bool, ValueQuery>; + + #[pallet::genesis_config] + pub struct GenesisConfig { + pub stakers: GenesisStaker, + pub inflation_config: InflationInfo, + pub max_candidate_stake: BalanceOf, + } + + #[cfg(feature = "std")] + impl Default for GenesisConfig { + fn default() -> Self { + Self { + stakers: Default::default(), + inflation_config: Default::default(), + max_candidate_stake: Default::default(), + } + } + } + + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + assert!( + self.inflation_config.is_valid(T::BLOCKS_PER_YEAR.saturated_into()), + "Invalid inflation configuration" + ); + + InflationConfig::::put(self.inflation_config.clone()); + MaxCollatorCandidateStake::::put(self.max_candidate_stake); + + // Setup delegate & collators + for &(ref actor, ref opt_val, balance) in &self.stakers { + assert!( + T::Currency::free_balance(actor) >= balance, + "Account does not have enough balance to stake." + ); + if let Some(delegated_val) = opt_val { + assert_ok!(Pallet::::join_delegators( + T::RuntimeOrigin::from(Some(actor.clone()).into()), + T::Lookup::unlookup(delegated_val.clone()), + balance, + )); + } else { + assert_ok!(Pallet::::join_candidates( + T::RuntimeOrigin::from(Some(actor.clone()).into()), + balance + )); + } + } + // Set total selected candidates to minimum config + MaxSelectedCandidates::::put(T::MinCollators::get()); + + Pallet::::update_total_stake(); + + // Start Round 0 at Block 0 + let round: RoundInfo = RoundInfo::new(0u32, 0u32.into(), T::DefaultBlocksPerRound::get()); + Round::::put(round); + } + } + + #[pallet::call] + impl Pallet { + /// Forces the start of the new round in the next block. + /// + /// The new round will be enforced via >::should_end_session. + /// + /// The dispatch origin must be Root. + #[pallet::call_index(0)] + #[pallet::weight(::WeightInfo::force_new_round())] + pub fn force_new_round(origin: OriginFor) -> DispatchResult { + ensure_root(origin)?; + + // set force_new_round handle which, at the start of the next block, will + // trigger `should_end_session` in `Session::on_initialize` and update the + // current round + ForceNewRound::::put(true); + + Ok(()) + } + + /// Set the annual inflation rate to derive per-round inflation. + /// + /// The inflation details are considered valid if the annual reward rate + /// is approximately the per-block reward rate multiplied by the + /// estimated* total number of blocks per year. + /// + /// The estimated average block time is twelve seconds. + /// + /// NOTE: Iterates over CandidatePool and for each candidate over their + /// delegators to update their rewards before the reward rates change. + /// Needs to be improved when scaling up `MaxTopCandidates`. + /// + /// The dispatch origin must be Root. + /// + /// Emits `RoundInflationSet`. + #[pallet::call_index(1)] + #[pallet::weight(::WeightInfo::set_inflation(T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get()))] + pub fn set_inflation( + origin: OriginFor, collator_max_rate_percentage: Perquintill, + collator_annual_reward_rate_percentage: Perquintill, delegator_max_rate_percentage: Perquintill, + delegator_annual_reward_rate_percentage: Perquintill, + ) -> DispatchResultWithPostInfo { + ensure_root(origin)?; + + // Update inflation and increment rewards + let (num_col, num_del) = Self::do_set_inflation( + T::BLOCKS_PER_YEAR, + collator_max_rate_percentage, + collator_annual_reward_rate_percentage, + delegator_max_rate_percentage, + delegator_annual_reward_rate_percentage, + )?; + + Ok(Some(::WeightInfo::set_inflation(num_col, num_del)).into()) + } + + /// Set the maximum number of collator candidates that can be selected + /// at the beginning of each validation round. + /// + /// Changes are not applied until the start of the next round. + /// + /// The new value must be higher than the minimum allowed as set in the + /// pallet's configuration. + /// + /// The dispatch origin must be Root. + /// + /// Emits `MaxSelectedCandidatesSet`. + #[pallet::call_index(2)] + #[pallet::weight(::WeightInfo::set_max_selected_candidates( + *new, + T::MaxDelegatorsPerCollator::get() + ))] + pub fn set_max_selected_candidates(origin: OriginFor, new: u32) -> DispatchResultWithPostInfo { + ensure_root(origin)?; + ensure!(new >= T::MinCollators::get(), Error::::CannotSetBelowMin); + ensure!(new <= T::MaxTopCandidates::get(), Error::::CannotSetAboveMax); + let old = MaxSelectedCandidates::::get(); + + // *** No Fail beyond this point *** + + MaxSelectedCandidates::::put(new); + + // Update total amount at stake for new top collators and their delegators + let start = old.min(new); + let end = old.max(new); + + // The slice [start, end] contains the added or removed collators. We sum up + // their stake to adjust the total stake. + let (diff_collation, diff_delegation, num_delegators) = TopCandidates::::get() + .into_iter() + .skip(start.saturated_into()) + // SAFETY: we ensured that end > start further above. + .take((end - start).saturated_into()) + .filter_map(|candidate| CandidatePool::::get(&candidate.owner)) + .map(|state| { + ( + state.stake, + // SAFETY: the total is always more than the stake + state.total - state.stake, + state.delegators.len().saturated_into::(), + ) + }) + .reduce(|a, b| (a.0.saturating_add(b.0), a.1.saturating_add(b.1), a.2.max(b.2))) + .unwrap_or((BalanceOf::::zero(), BalanceOf::::zero(), 0u32)); + + TotalCollatorStake::::mutate(|total| { + if new > old { + total.collators = total.collators.saturating_add(diff_collation); + total.delegators = total.delegators.saturating_add(diff_delegation); + } else { + total.collators = total.collators.saturating_sub(diff_collation); + total.delegators = total.delegators.saturating_sub(diff_delegation); + } + }); + + Self::deposit_event(Event::MaxSelectedCandidatesSet(old, new)); + + Ok(Some(::WeightInfo::set_max_selected_candidates( + // SAFETY: we ensured that end > start further above. + end - start, + num_delegators, + )) + .into()) + } + + /// Set the number of blocks each validation round lasts. + /// + /// If the new value is less than the length of the current round, the + /// system will immediately move to the next round in the next block. + /// + /// The new value must be higher than the minimum allowed as set in the + /// pallet's configuration. + /// + /// The dispatch origin must be Root. + /// + /// Emits `BlocksPerRoundSet`. + #[pallet::call_index(3)] + #[pallet::weight(::WeightInfo::set_blocks_per_round())] + pub fn set_blocks_per_round(origin: OriginFor, new: T::BlockNumber) -> DispatchResult { + ensure_root(origin)?; + ensure!(new >= T::MinBlocksPerRound::get(), Error::::CannotSetBelowMin); + + let old_round = Round::::get(); + + // *** No Fail beyond this point *** + + Round::::put(RoundInfo { + length: new, + ..old_round + }); + + Self::deposit_event(Event::BlocksPerRoundSet( + old_round.current, + old_round.first, + old_round.length, + new, + )); + Ok(()) + } + + /// Set the maximal amount a collator can stake. Existing stakes are not + /// changed. + /// + /// The dispatch origin must be Root. + /// + /// Emits `MaxCandidateStakeChanged`. + #[pallet::call_index(4)] + #[pallet::weight(::WeightInfo::set_max_candidate_stake())] + pub fn set_max_candidate_stake(origin: OriginFor, new: BalanceOf) -> DispatchResult { + ensure_root(origin)?; + ensure!( + new >= T::MinCollatorCandidateStake::get(), + Error::::CannotSetBelowMin + ); + + // *** No Fail beyond this point *** + + MaxCollatorCandidateStake::::put(new); + + Self::deposit_event(Event::MaxCandidateStakeChanged(new)); + Ok(()) + } + + /// Forcedly removes a collator candidate from the TopCandidates and + /// clears all associated storage for the candidate and their + /// delegators. + /// + /// Prepares unstaking of the candidates and their delegators stake + /// which can be unlocked via `unlock_unstaked` after waiting at + /// least `StakeDuration` many blocks. Also increments rewards for the + /// collator and their delegators. + /// + /// Increments rewards of candidate and their delegators. + /// + /// Emits `CandidateRemoved`. + #[pallet::call_index(5)] + #[pallet::weight(::WeightInfo::force_remove_candidate( + T::MaxTopCandidates::get(), + T::MaxDelegatorsPerCollator::get() + ))] + pub fn force_remove_candidate( + origin: OriginFor, collator: ::Source, + ) -> DispatchResultWithPostInfo { + ensure_root(origin)?; + let collator = T::Lookup::lookup(collator)?; + let state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; + let total_amount = state.total; + + let mut candidates = TopCandidates::::get(); + ensure!( + candidates.len().saturated_into::() > T::MinRequiredCollators::get(), + Error::::TooFewCollatorCandidates + ); + + // *** No Fail except during remove_candidate beyond this point *** + + // remove candidate storage and increment rewards + Self::remove_candidate(&collator, &state)?; + + let (num_collators, num_delegators) = if candidates + .remove(&Stake { + owner: collator.clone(), + amount: state.total, + }) + .is_some() + { + // update top candidates + TopCandidates::::put(candidates); + // update total amount at stake from scratch + Self::update_total_stake() + } else { + (0u32, 0u32) + }; + + Self::deposit_event(Event::CollatorRemoved(collator, total_amount)); + + Ok(Some(::WeightInfo::force_remove_candidate( + num_collators, + num_delegators, + )) + .into()) + } + + /// Join the set of collator candidates. + /// + /// In the next blocks, if the collator candidate has enough funds + /// staked to be included in any of the top `MaxSelectedCandidates` + /// positions, it will be included in the set of potential authors that + /// will be selected by the stake-weighted random selection function. + /// + /// The staked funds of the new collator candidate are added to the + /// total stake of the system. + /// + /// The total amount of funds staked must be within the allowed range as + /// set in the pallet's configuration. + /// + /// The dispatch origin must not be already part of the collator + /// candidates nor of the delegators set. + /// + /// Emits `JoinedCollatorCandidates`. + #[pallet::call_index(6)] + #[pallet::weight(::WeightInfo::join_candidates( + T::MaxTopCandidates::get(), + T::MaxDelegatorsPerCollator::get() + ))] + pub fn join_candidates(origin: OriginFor, stake: BalanceOf) -> DispatchResultWithPostInfo { + let sender = ensure_signed(origin)?; + if let Some(is_active_candidate) = Self::is_active_candidate(&sender) { + ensure!(is_active_candidate, Error::::AlreadyLeaving); + ensure!(!is_active_candidate, Error::::CandidateExists); + } + ensure!(!Self::is_delegator(&sender), Error::::DelegatorExists); + ensure!( + stake >= T::MinCollatorCandidateStake::get(), + Error::::ValStakeBelowMin + ); + ensure!( + stake <= MaxCollatorCandidateStake::::get(), + Error::::ValStakeAboveMax + ); + ensure!( + Unstaking::::get(&sender).len().saturated_into::() < T::MaxUnstakeRequests::get(), + Error::::CannotJoinBeforeUnlocking + ); + + // *** No Fail except during increase_lock beyond this point *** + + Self::increase_lock(&sender, stake, BalanceOf::::zero())?; + + let candidate = Candidate::new(sender.clone(), stake); + let n = Self::update_top_candidates( + sender.clone(), + BalanceOf::::zero(), + BalanceOf::::zero(), + stake, + BalanceOf::::zero(), + ); + CandidatePool::::insert(&sender, candidate); + + Self::deposit_event(Event::JoinedCollatorCandidates(sender, stake)); + Ok(Some(::WeightInfo::join_candidates( + n, + T::MaxDelegatorsPerCollator::get(), + )) + .into()) + } + + /// Request to leave the set of collator candidates. + /// + /// On success, the account is immediately removed from the candidate + /// pool to prevent selection as a collator in future validation rounds, + /// but unstaking of the funds is executed with a delay of + /// `StakeDuration` blocks. + /// + /// The exit request can be reversed by calling + /// `cancel_leave_candidates`. + /// + /// This operation affects the pallet's total stake amount. It is + /// updated even though the funds of the candidate who signaled to leave + /// are still locked for `ExitDelay` + `StakeDuration` more blocks. + /// + /// NOTE 1: Upon starting a new session_i in `new_session`, the current + /// top candidates are selected to be block authors for session_i+1. Any + /// changes to the top candidates afterwards do not effect the set of + /// authors for session_i+1. + /// Thus, we have to make sure none of these collators can + /// leave before session_i+1 ends by delaying their + /// exit for `ExitDelay` many blocks. + /// + /// NOTE 2: We do not increment rewards in this extrinsic as the + /// candidate could still author blocks, and thus be eligible to receive + /// rewards, until the end of the next session. + /// + /// Emits `CollatorScheduledExit`. + #[pallet::call_index(7)] + #[pallet::weight(::WeightInfo::init_leave_candidates( + T::MaxTopCandidates::get(), + T::MaxTopCandidates::get().saturating_mul(T::MaxDelegatorsPerCollator::get()) + ))] + pub fn init_leave_candidates(origin: OriginFor) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + let mut state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; + ensure!(!state.is_leaving(), Error::::AlreadyLeaving); + let mut candidates = TopCandidates::::get(); + ensure!( + candidates.len().saturated_into::() > T::MinRequiredCollators::get(), + Error::::TooFewCollatorCandidates + ); + + let now = Round::::get().current; + let when = now.saturating_add(T::ExitQueueDelay::get()); + state.leave_candidates(when); + + // *** No Fail beyond this point *** + + let (num_collators, num_delegators) = if candidates + .remove(&Stake { + owner: collator.clone(), + amount: state.total, + }) + .is_some() + { + // update top candidates + TopCandidates::::put(candidates); + Self::deposit_event(Event::LeftTopCandidates(collator.clone())); + // update total amount at stake from scratch + Self::update_total_stake() + } else { + (0u32, 0u32) + }; + CandidatePool::::insert(&collator, state); + + Self::deposit_event(Event::CollatorScheduledExit(now, collator, when)); + Ok(Some(::WeightInfo::init_leave_candidates( + num_collators, + num_delegators, + )) + .into()) + } + + /// Execute the network exit of a candidate who requested to leave at + /// least `ExitQueueDelay` rounds ago. Prepares unstaking of the + /// candidates and their delegators stake which can be unlocked via + /// `unlock_unstaked` after waiting at least `StakeDuration` many + /// blocks. + /// + /// Requires the candidate to previously have called + /// `init_leave_candidates`. + /// + /// The exit request can be reversed by calling + /// `cancel_leave_candidates`. + /// + /// NOTE: Iterates over CandidatePool for each candidate over their + /// delegators to set rewards. Needs to be improved when scaling up + /// `MaxTopCandidates`. + /// + /// Emits `CollatorLeft`. + #[pallet::call_index(8)] + #[pallet::weight(::WeightInfo::execute_leave_candidates( + T::MaxTopCandidates::get(), + T::MaxDelegatorsPerCollator::get(), + ))] + pub fn execute_leave_candidates( + origin: OriginFor, collator: ::Source, + ) -> DispatchResultWithPostInfo { + ensure_signed(origin)?; + let collator = T::Lookup::lookup(collator)?; + let state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; + ensure!(state.is_leaving(), Error::::NotLeaving); + ensure!(state.can_exit(Round::::get().current), Error::::CannotLeaveYet); + + let num_delegators = state.delegators.len().saturated_into::(); + let total_amount = state.total; + + // *** No Fail except during remove_candidate beyond this point *** + + // remove candidate storage and increment rewards + Self::remove_candidate(&collator, &state)?; + + Self::deposit_event(Event::CandidateLeft(collator, total_amount)); + + Ok(Some(::WeightInfo::execute_leave_candidates( + T::MaxTopCandidates::get(), + num_delegators, + )) + .into()) + } + + /// Revert the previously requested exit of the network of a collator + /// candidate. On success, adds back the candidate to the TopCandidates + /// and updates the collators. + /// + /// Requires the candidate to previously have called + /// `init_leave_candidates`. + /// + /// Emits `CollatorCanceledExit`. + #[pallet::call_index(9)] + #[pallet::weight(::WeightInfo::cancel_leave_candidates( + T::MaxTopCandidates::get(), + T::MaxDelegatorsPerCollator::get(), + ))] + pub fn cancel_leave_candidates(origin: OriginFor) -> DispatchResultWithPostInfo { + let candidate = ensure_signed(origin)?; + let mut state = CandidatePool::::get(&candidate).ok_or(Error::::CandidateNotFound)?; + ensure!(state.is_leaving(), Error::::NotLeaving); + + // revert leaving state + state.revert_leaving(); + + // *** No Fail beyond this point *** + + let n = Self::update_top_candidates( + candidate.clone(), + state.stake, + // safe because total >= stake + state.total - state.stake, + state.stake, + state.total - state.stake, + ); + + // update candidates for next round + CandidatePool::::insert(&candidate, state); + + Self::deposit_event(Event::CollatorCanceledExit(candidate)); + + Ok(Some(::WeightInfo::cancel_leave_candidates( + n, + T::MaxDelegatorsPerCollator::get(), + )) + .into()) + } + + /// Stake more funds for a collator candidate. + /// + /// If not in the set of candidates, staking enough funds allows the + /// account to be added to it. The larger amount of funds, the higher + /// chances to be selected as the author of the next block. + /// + /// This operation affects the pallet's total stake amount. + /// + /// The resulting total amount of funds staked must be within the + /// allowed range as set in the pallet's configuration. + /// + /// Emits `CollatorStakedMore`. + #[pallet::call_index(10)] + #[pallet::weight(::WeightInfo::candidate_stake_more( + T::MaxTopCandidates::get(), + T::MaxDelegatorsPerCollator::get(), + T::MaxUnstakeRequests::get().saturated_into::() + ))] + pub fn candidate_stake_more(origin: OriginFor, more: BalanceOf) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + + ensure!(!more.is_zero(), Error::::ValStakeZero); + let mut state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; + ensure!(!state.is_leaving(), Error::::CannotStakeIfLeaving); + + let CandidateOf:: { + stake: before_stake, + total: before_total, + .. + } = state; + state.stake_more(more); + let after_stake = state.stake; + ensure!( + state.stake <= MaxCollatorCandidateStake::::get(), + Error::::ValStakeAboveMax + ); + + // *** No Fail except during increase_lock beyond this point *** + + let unstaking_len = Self::increase_lock(&collator, state.stake, more)?; + + let n = if state.is_active() { + Self::update_top_candidates( + collator.clone(), + before_stake, + // safe because total >= stake + before_total - before_stake, + state.stake, + state.total - state.stake, + ) + } else { + 0u32 + }; + CandidatePool::::insert(&collator, state); + + // increment rewards for collator and update number of rewarded blocks + Self::do_inc_collator_reward(&collator, before_stake); + + Self::deposit_event(Event::CollatorStakedMore(collator, before_stake, after_stake)); + Ok(Some(::WeightInfo::candidate_stake_more( + n, + T::MaxDelegatorsPerCollator::get(), + unstaking_len, + )) + .into()) + } + + /// Stake less funds for a collator candidate. + /// + /// If the new amount of staked fund is not large enough, the account + /// could be removed from the set of collator candidates and not be + /// considered for authoring the next blocks. + /// + /// This operation affects the pallet's total stake amount. + /// + /// The unstaked funds are not released immediately to the account, but + /// they will be available after `StakeDuration` blocks. + /// + /// The resulting total amount of funds staked must be within the + /// allowed range as set in the pallet's configuration. + /// + /// Emits `CollatorStakedLess`. + #[pallet::call_index(11)] + #[pallet::weight(::WeightInfo::candidate_stake_less( + T::MaxTopCandidates::get(), + T::MaxDelegatorsPerCollator::get() + ))] + pub fn candidate_stake_less(origin: OriginFor, less: BalanceOf) -> DispatchResultWithPostInfo { + let collator = ensure_signed(origin)?; + ensure!(!less.is_zero(), Error::::ValStakeZero); + + let mut state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; + ensure!(!state.is_leaving(), Error::::CannotStakeIfLeaving); + + let CandidateOf:: { + stake: before_stake, + total: before_total, + .. + } = state; + let after = state.stake_less(less).ok_or(Error::::Underflow)?; + ensure!( + after >= T::MinCollatorCandidateStake::get(), + Error::::ValStakeBelowMin + ); + + // *** No Fail except during prep_unstake beyond this point *** + + // we don't unlock immediately + Self::prep_unstake(&collator, less, false)?; + + let n = if state.is_active() { + Self::update_top_candidates( + collator.clone(), + before_stake, + // safe because total >= stake + before_total - before_stake, + state.stake, + state.total - state.stake, + ) + } else { + 0u32 + }; + CandidatePool::::insert(&collator, state); + + // increment rewards and update number of rewarded blocks + Self::do_inc_collator_reward(&collator, before_stake); + + Self::deposit_event(Event::CollatorStakedLess(collator, before_stake, after)); + Ok(Some(::WeightInfo::candidate_stake_less( + n, + T::MaxDelegatorsPerCollator::get(), + )) + .into()) + } + + /// Join the set of delegators by delegating to a collator candidate. + /// + /// The account that wants to delegate cannot be part of the collator + /// candidates set as well. + /// + /// The caller must _not_ have a delegation. If that is the case, they + /// are required to first remove the delegation. + /// + /// The amount staked must be larger than the minimum required to become + /// a delegator as set in the pallet's configuration. + /// + /// As only `MaxDelegatorsPerCollator` are allowed to delegate a given + /// collator, the amount staked must be larger than the lowest one in + /// the current set of delegator for the operation to be meaningful. + /// + /// The collator's total stake as well as the pallet's total stake are + /// increased accordingly. + /// + /// Emits `Delegation`. + /// Emits `DelegationReplaced` if the candidate has + /// `MaxDelegatorsPerCollator` many delegations but this delegator + /// staked more than one of the other delegators of this candidate. + #[pallet::call_index(12)] + #[pallet::weight(::WeightInfo::join_delegators( + T::MaxTopCandidates::get(), + T::MaxDelegatorsPerCollator::get() + ))] + pub fn join_delegators( + origin: OriginFor, collator: ::Source, amount: BalanceOf, + ) -> DispatchResultWithPostInfo { + let acc = ensure_signed(origin)?; + let collator = T::Lookup::lookup(collator)?; + + // check balance + ensure!( + pallet_balances::Pallet::::free_balance(acc.clone()) >= amount.into(), + pallet_balances::Error::::InsufficientBalance + ); + + // first delegation + ensure!(DelegatorState::::get(&acc).is_none(), Error::::AlreadyDelegating); + ensure!(amount >= T::MinDelegatorStake::get(), Error::::DelegationBelowMin); + + // cannot be a collator candidate and delegator with same AccountId + ensure!(Self::is_active_candidate(&acc).is_none(), Error::::CandidateExists); + ensure!( + Unstaking::::get(&acc).len().saturated_into::() < T::MaxUnstakeRequests::get(), + Error::::CannotJoinBeforeUnlocking + ); + // cannot delegate if number of delegations in this round exceeds + // MaxDelegationsPerRound + let delegation_counter = Self::get_delegation_counter(&acc)?; + + // prepare update of collator state + let mut state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; + let num_delegations_pre_insertion: u32 = state.delegators.len().saturated_into(); + + ensure!(!state.is_leaving(), Error::::CannotDelegateIfLeaving); + let delegation = Stake { + owner: acc.clone(), + amount, + }; + + // attempt to insert delegator and check for uniqueness + // NOTE: excess is handled below because we support replacing a delegator with + // fewer stake + let insert_delegator = state + .delegators + // we handle TooManyDelegators error below in do_update_delegator + .try_insert(delegation.clone()) + .unwrap_or(true); + // should never fail but let's be safe + ensure!(insert_delegator, Error::::DelegatorExists); + + let delegator_state = Delegator { + amount, + owner: collator.clone(), + }; + let CandidateOf:: { + stake: old_stake, + total: old_total, + .. + } = state; + + // update state and potentially prepare kicking a delegator with less staked + // amount (includes setting rewards for kicked delegator) + let state = if num_delegations_pre_insertion == T::MaxDelegatorsPerCollator::get() { + Self::do_update_delegator(delegation, state)? + } else { + state.total = state.total.saturating_add(amount); + state + }; + let new_total = state.total; + + // *** No Fail except during increase_lock beyond this point *** + + // lock stake + Self::increase_lock(&acc, amount, BalanceOf::::zero())?; + + // update top candidates and total amount at stake + let n = if state.is_active() { + Self::update_top_candidates( + collator.clone(), + old_stake, + // safe because total >= stake + old_total - old_stake, + state.stake, + state.total - state.stake, + ) + } else { + 0u32 + }; + + // update states + CandidatePool::::insert(&collator, state); + DelegatorState::::insert(&acc, delegator_state); + LastDelegation::::insert(&acc, delegation_counter); + + // initiate rewarded counter to match the current authored counter of the + // candidate + BlocksRewarded::::insert(&acc, BlocksAuthored::::get(&collator)); + + Self::deposit_event(Event::Delegation(acc, amount, collator, new_total)); + Ok(Some(::WeightInfo::join_delegators( + n, + T::MaxDelegatorsPerCollator::get(), + )) + .into()) + } + + /// Leave the set of delegators and, by implication, revoke the ongoing + /// delegation. + /// + /// All staked funds are not unlocked immediately, but they are added to + /// the queue of pending unstaking, and will effectively be released + /// after `StakeDuration` blocks from the moment the delegator leaves. + /// + /// This operation reduces the total stake of the pallet as well as the + /// stakes of all collators that were delegated, potentially affecting + /// their chances to be included in the set of candidates in the next + /// rounds. + /// + /// Automatically increments the accumulated rewards of the origin of + /// the current delegation. + /// + /// Emits `DelegatorLeft`. + #[pallet::call_index(13)] + #[pallet::weight(::WeightInfo::leave_delegators( + T::MaxTopCandidates::get(), + T::MaxDelegatorsPerCollator::get() + ))] + pub fn leave_delegators(origin: OriginFor) -> DispatchResultWithPostInfo { + let acc = ensure_signed(origin)?; + let delegator = DelegatorState::::get(&acc).ok_or(Error::::DelegatorNotFound)?; + let collator = delegator.owner; + Self::delegator_leaves_collator(acc.clone(), collator)?; + + // *** No Fail beyond this point *** + + DelegatorState::::remove(&acc); + + Self::deposit_event(Event::DelegatorLeft(acc, delegator.amount)); + Ok(Some(::WeightInfo::leave_delegators( + 1, + T::MaxDelegatorsPerCollator::get(), + )) + .into()) + } + + /// Increase the stake for delegating a collator candidate. + /// + /// If not in the set of candidates, staking enough funds allows the + /// collator candidate to be added to it. + /// + /// Emits `DelegatorStakedMore`. + #[pallet::call_index(14)] + #[pallet::weight(::WeightInfo::delegator_stake_more( + T::MaxTopCandidates::get(), + T::MaxDelegatorsPerCollator::get(), + T::MaxUnstakeRequests::get().saturated_into::()) + )] + pub fn delegator_stake_more(origin: OriginFor, more: BalanceOf) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + ensure!(!more.is_zero(), Error::::ValStakeZero); + + let mut delegation = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; + let candidate = delegation.owner.clone(); + let mut collator = CandidatePool::::get(&candidate).ok_or(Error::::CandidateNotFound)?; + ensure!(!collator.is_leaving(), Error::::CannotDelegateIfLeaving); + let stake_after = delegation + .try_increment(candidate.clone(), more) + .map_err(|_| Error::::DelegationNotFound)?; + + // *** No Fail except during increase_lock beyond this point *** + + // update lock + let unstaking_len = Self::increase_lock(&delegator, stake_after, more)?; + + let CandidateOf:: { + stake: before_stake, + total: before_total, + .. + } = collator; + collator.inc_delegator(delegator.clone(), more); + let after = collator.total; + + // update top candidates and total amount at stake + let n = if collator.is_active() { + Self::update_top_candidates( + candidate.clone(), + before_stake, + // safe because total >= stake + before_total - before_stake, + collator.stake, + collator.total - collator.stake, + ) + } else { + 0u32 + }; + + // increment rewards and update number of rewarded blocks + Self::do_inc_delegator_reward(&delegator, stake_after.saturating_sub(more), &candidate); + + CandidatePool::::insert(&candidate, collator); + DelegatorState::::insert(&delegator, delegation); + + Self::deposit_event(Event::DelegatorStakedMore(delegator, candidate, before_total, after)); + Ok(Some(::WeightInfo::delegator_stake_more( + n, + T::MaxDelegatorsPerCollator::get(), + unstaking_len, + )) + .into()) + } + + /// Reduce the stake for delegating a collator candidate. + /// + /// If the new amount of staked fund is not large enough, the collator + /// could be removed from the set of collator candidates and not be + /// considered for authoring the next blocks. + /// + /// The unstaked funds are not release immediately to the account, but + /// they will be available after `StakeDuration` blocks. + /// + /// The remaining staked funds must still be larger than the minimum + /// required by this pallet to maintain the status of delegator. + /// + /// The resulting total amount of funds staked must be within the + /// allowed range as set in the pallet's configuration. + /// + /// Emits `DelegatorStakedLess`. + #[pallet::call_index(15)] + #[pallet::weight(::WeightInfo::delegator_stake_less( + T::MaxTopCandidates::get(), + T::MaxDelegatorsPerCollator::get() + ))] + pub fn delegator_stake_less(origin: OriginFor, less: BalanceOf) -> DispatchResultWithPostInfo { + let delegator = ensure_signed(origin)?; + ensure!(!less.is_zero(), Error::::ValStakeZero); + + let mut delegation = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; + let candidate = delegation.owner.clone(); + let mut collator = CandidatePool::::get(&candidate).ok_or(Error::::CandidateNotFound)?; + ensure!(!collator.is_leaving(), Error::::CannotDelegateIfLeaving); + let stake_after = delegation + .try_decrement(candidate.clone(), less) + .map_err(|_| Error::::DelegationNotFound)? + .ok_or(Error::::Underflow)?; + + ensure!( + stake_after >= T::MinDelegatorStake::get(), + Error::::DelegationBelowMin + ); + + // *** No Fail except during prep_unstake beyond this point *** + + Self::prep_unstake(&delegator, less, false)?; + + let CandidateOf:: { + stake: before_stake, + total: before_total, + .. + } = collator; + collator.dec_delegator(delegator.clone(), less); + let after = collator.total; + + // update top candidates and total amount at stake + let n = if collator.is_active() { + Self::update_top_candidates( + candidate.clone(), + before_stake, + // safe because total >= stake + before_total - before_stake, + collator.stake, + collator.total - collator.stake, + ) + } else { + 0u32 + }; + + // increment rewards and update number of rewarded blocks + Self::do_inc_delegator_reward(&delegator, stake_after.saturating_add(less), &candidate); + + CandidatePool::::insert(&candidate, collator); + DelegatorState::::insert(&delegator, delegation); + + Self::deposit_event(Event::DelegatorStakedLess(delegator, candidate, before_total, after)); + Ok(Some(::WeightInfo::delegator_stake_less( + n, + T::MaxDelegatorsPerCollator::get(), + )) + .into()) + } + + /// Unlock all previously staked funds that are now available for + /// unlocking by the origin account after `StakeDuration` blocks have + /// elapsed. + /// + /// Weight: O(U) where U is the number of locked unstaking requests + /// bounded by `MaxUnstakeRequests`. + /// - Reads: [Origin Account], Unstaking, Locks + /// - Writes: Unstaking, Locks + /// - Kills: Unstaking & Locks if no balance is locked anymore + /// # + #[pallet::call_index(16)] + #[pallet::weight(::WeightInfo::unlock_unstaked( + T::MaxUnstakeRequests::get().saturated_into::() + ))] + pub fn unlock_unstaked( + origin: OriginFor, target: ::Source, + ) -> DispatchResultWithPostInfo { + ensure_signed(origin)?; + let target = T::Lookup::lookup(target)?; + + let unstaking_len = Self::do_unlock(&target)?; + + Ok(Some(::WeightInfo::unlock_unstaked(unstaking_len)).into()) + } + + /// Claim block authoring rewards for the target address. + /// + /// Requires `Rewards` to be set beforehand, which can by triggered by + /// any of the following options + /// * Calling increment_{collator, delegator}_rewards (active) + /// * Altering your stake (active) + /// * Leaving the network as a collator (active) + /// * Revoking a delegation as a delegator (active) + /// * Being a delegator whose collator left the network, altered their + /// stake or incremented rewards (passive) + /// + /// The dispatch origin can be any signed one, e.g., anyone can claim + /// for anyone. + /// + /// Emits `Rewarded`. + #[pallet::call_index(17)] + #[pallet::weight(::WeightInfo::claim_rewards())] + pub fn claim_rewards(origin: OriginFor) -> DispatchResult { + let target = ensure_signed(origin)?; + + // reset rewards + let rewards = Rewards::::take(&target); + ensure!(!rewards.is_zero(), Error::::RewardsNotFound); + + // mint into target + let rewards = T::Currency::deposit_into_existing(&target, rewards)?; + + Self::deposit_event(Event::Rewarded(target, rewards.peek())); + + Ok(()) + } + + /// Actively increment the rewards of a collator. + /// + /// The same effect is triggered by changing the stake or leaving the + /// network. + /// + /// The dispatch origin must be a collator. + #[pallet::call_index(18)] + #[pallet::weight(::WeightInfo::increment_collator_rewards())] + pub fn increment_collator_rewards(origin: OriginFor) -> DispatchResult { + let collator = ensure_signed(origin)?; + let state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; + + // increment rewards and update number of rewarded blocks + Self::do_inc_collator_reward(&collator, state.stake); + + Ok(()) + } + + /// Actively increment the rewards of a delegator. + /// + /// The same effect is triggered by changing the stake or revoking + /// delegations. + /// + /// The dispatch origin must be a delegator. + #[pallet::call_index(19)] + #[pallet::weight(::WeightInfo::increment_delegator_rewards())] + pub fn increment_delegator_rewards(origin: OriginFor) -> DispatchResult { + let delegator = ensure_signed(origin)?; + let delegation = DelegatorState::::get(&delegator).ok_or(Error::::DelegatorNotFound)?; + let collator = delegation.owner; + + // increment rewards and update number of rewarded blocks + Self::do_inc_delegator_reward(&delegator, delegation.amount, &collator); + + Ok(()) + } + + /// Executes the annual reduction of the reward rates for collators and + /// delegators. + /// + /// Moreover, sets rewards for all collators and delegators + /// before adjusting the inflation. + /// + /// The dispatch origin can be any signed one because we bail if called + /// too early. + /// + /// Emits `RoundInflationSet`. + #[pallet::call_index(20)] + #[pallet::weight(::WeightInfo::execute_scheduled_reward_change(T::MaxTopCandidates::get(), T::MaxDelegatorsPerCollator::get()))] + pub fn execute_scheduled_reward_change(origin: OriginFor) -> DispatchResultWithPostInfo { + ensure_signed(origin)?; + + let now = frame_system::Pallet::::block_number(); + let year = now / T::BLOCKS_PER_YEAR; + + // We can already mutate thanks to extrinsics being transactional + let last_update = LastRewardReduction::::mutate(|last_year| { + let old = *last_year; + *last_year = old.saturating_add(T::BlockNumber::one()); + old + }); + // Bail if less than a year (in terms of number of blocks) has passed since the + // last update + ensure!(year > last_update, Error::::TooEarly); + + // Calculate new inflation based on last year + let inflation = InflationConfig::::get(); + + // collator reward rate decreases by 2% p.a. of the previous one + let c_reward_rate = inflation.collator.reward_rate.annual * Perquintill::from_percent(98); + + // delegator reward rate should be 6% in 2nd year and 0% afterwards + let d_reward_rate = if year == T::BlockNumber::one() { + Perquintill::from_percent(6) + } else { + Perquintill::zero() + }; + + // Update inflation and increment rewards + let (num_col, num_del) = Self::do_set_inflation( + T::BLOCKS_PER_YEAR, + inflation.collator.max_rate, + c_reward_rate, + inflation.delegator.max_rate, + d_reward_rate, + )?; + + Ok(Some(::WeightInfo::set_inflation(num_col, num_del)).into()) + } + } + + impl Pallet { + /// Check whether an account is currently delegating. + pub fn is_delegator(acc: &T::AccountId) -> bool { + DelegatorState::::get(acc).is_some() + } + + /// Check whether an account is currently a collator candidate and + /// whether their state is CollatorStatus::Active. + /// + /// Returns Some(is_active) if the account is a candidate, else None. + pub fn is_active_candidate(acc: &T::AccountId) -> Option { + if let Some(state) = CandidatePool::::get(acc) { + Some(state.status == CandidateStatus::Active) + } else { + None + } + } + /// Set the annual inflation rate to derive per-round inflation. + /// + /// The inflation details are considered valid if the annual reward rate + /// is approximately the per-block reward rate multiplied by the + /// estimated* total number of blocks per year. + /// + /// The estimated average block time is twelve seconds. + /// + /// NOTE: Iterates over CandidatePool and for each candidate over their + /// delegators to update their rewards before the reward rates change. + /// Needs to be improved when scaling up `MaxTopCandidates`. + /// + /// Emits `RoundInflationSet`. + fn do_set_inflation( + blocks_per_year: T::BlockNumber, col_max_rate: Perquintill, col_reward_rate: Perquintill, + del_max_rate: Perquintill, del_reward_rate: Perquintill, + ) -> Result<(u32, u32), DispatchError> { + // Check validity of new inflation + let inflation = InflationInfo::new( + blocks_per_year.saturated_into(), + col_max_rate, + col_reward_rate, + del_max_rate, + del_reward_rate, + ); + ensure!( + inflation.is_valid(T::BLOCKS_PER_YEAR.saturated_into()), + Error::::InvalidSchedule + ); + + // Increment rewards for all collators and delegators due to change of reward + // rates + let mut num_delegators = 0u32; + CandidatePool::::iter().for_each(|(id, state)| { + // increment collator rewards + Self::do_inc_collator_reward(&id, state.stake); + // increment delegator rewards + state.delegators.into_iter().for_each(|delegator_state| { + Self::do_inc_delegator_reward(&delegator_state.owner, delegator_state.amount, &id); + num_delegators = num_delegators.saturating_add(1u32); + }); + }); + + // Update inflation + InflationConfig::::put(inflation); + Self::deposit_event(Event::RoundInflationSet( + col_max_rate, + col_reward_rate, + del_max_rate, + del_reward_rate, + )); + + Ok((CandidatePool::::count(), num_delegators)) + } + + /// Update the top candidates and total amount at stake after mutating + /// an active candidate's stake. + /// + /// NOTE: It is assumed that the calling context checks whether the + /// collator candidate is currently active before calling this function. + fn update_top_candidates( + candidate: T::AccountId, old_self: BalanceOf, old_delegators: BalanceOf, new_self: BalanceOf, + new_delegators: BalanceOf, + ) -> u32 { + let mut top_candidates = TopCandidates::::get(); + let num_top_candidates: u32 = top_candidates.len().saturated_into(); + let old_stake = Stake { + owner: candidate.clone(), + amount: old_self.saturating_add(old_delegators), + }; + let new_stake = Stake { + owner: candidate.clone(), + amount: new_self.saturating_add(new_delegators), + }; + + // update TopCandidates set + let maybe_top_candidate_update = if let Ok(i) = top_candidates.linear_search(&old_stake) { + // case 1: candidate is member of TopCandidates with old stake + top_candidates.mutate(|vec| { + if let Some(stake) = vec.get_mut(i) { + stake.amount = new_stake.amount; + } + }); + Some((Some(i), top_candidates)) + } else if top_candidates.try_insert_replace(new_stake.clone()).is_ok() { + // case 2: candidate ascends into TopCandidates with new stake + // and might replace another candidate if TopCandidates is full + Self::deposit_event(Event::EnteredTopCandidates(candidate)); + Some((None, top_candidates)) + } else { + // case 3: candidate neither was nor will be member of TopCandidates + None + }; + + // update storage for TotalCollatorStake and TopCandidates + if let Some((maybe_old_idx, top_candidates)) = maybe_top_candidate_update { + let max_selected_candidates = MaxSelectedCandidates::::get().saturated_into::(); + let was_collating = maybe_old_idx.map(|i| i < max_selected_candidates).unwrap_or(false); + let is_collating = top_candidates + .linear_search(&new_stake) + .map(|i| i < max_selected_candidates) + .unwrap_or(false); + + // update TopCollatorStake storage iff candidate was or will be a collator + match (was_collating, is_collating) { + (true, true) => { + Self::update_total_stake_by(new_self, new_delegators, old_self, old_delegators); + } + (true, false) => { + // candidate left the collator set because they staked less and have been + // replaced by the next candidate in the queue at position + // min(max_selected_candidates, top_candidates) - 1 in TopCandidates + let new_col_idx = max_selected_candidates.min(top_candidates.len()).saturating_sub(1); + + // get displacer + let (add_collators, add_delegators) = Self::get_top_candidate_stake_at(&top_candidates, new_col_idx) + // shouldn't be possible to fail, but we handle it gracefully + .unwrap_or((new_self, new_delegators)); + Self::update_total_stake_by(add_collators, add_delegators, old_self, old_delegators); + } + (false, true) => { + // candidate pushed out the least staked collator which is now at position + // min(max_selected_top_candidates, top_candidates - 1) in TopCandidates + let old_col_idx = max_selected_candidates.min(top_candidates.len().saturating_sub(1)); + + // get amount to subtract from TotalCollatorStake + let (drop_self, drop_delegators) = Self::get_top_candidate_stake_at(&top_candidates, old_col_idx) + // default to zero if candidate DNE, e.g. TopCandidates is not full + .unwrap_or((BalanceOf::::zero(), BalanceOf::::zero())); + Self::update_total_stake_by(new_self, new_delegators, drop_self, drop_delegators); + } + _ => {} + } + + // update TopCandidates storage + TopCandidates::::put(top_candidates); + } + + num_top_candidates + } + + /// Retrieve the staked amounts (self, sum of delegators) of member of + /// [TopCandidates] at the given index, if it exists. + fn get_top_candidate_stake_at( + top_candidates: &OrderedSet, T::MaxTopCandidates>, index: usize, + ) -> Option<(BalanceOf, BalanceOf)> { + top_candidates + .get(index) + .and_then(|stake| CandidatePool::::get(&stake.owner)) + // SAFETY: the total is always more than the stake + .map(|state| (state.stake, state.total - state.stake)) + } + + /// Mutate the [TotalCollatorStake] by both incrementing and decreasing + /// it by the provided values. + fn update_total_stake_by( + add_collators: BalanceOf, add_delegators: BalanceOf, sub_collators: BalanceOf, + sub_delegators: BalanceOf, + ) { + TotalCollatorStake::::mutate(|total| { + total.collators = total + .collators + .saturating_sub(sub_collators) + .saturating_add(add_collators); + total.delegators = total + .delegators + .saturating_sub(sub_delegators) + .saturating_add(add_delegators); + }); + } + + /// Iterate over the top `MaxSelectedCandidates` many collators in terms + /// of cumulated stake (self + from delegators) from the [TopCandidates] + /// and recalculate the [TotalCollatorStake] from scratch. + /// + /// NOTE: Should only be called in rare circumstances in which we cannot + /// guarantee a single candidate's stake has changed, e.g. on genesis or + /// when a collator leaves. Otherwise, please use + /// [update_total_stake_by]. + fn update_total_stake() -> (u32, u32) { + let mut num_of_delegators = 0u32; + let mut collator_stake = BalanceOf::::zero(); + let mut delegator_stake = BalanceOf::::zero(); + + let collators = Self::selected_candidates(); + + // Snapshot exposure for round for weighting reward distribution + for account in collators.iter() { + let state = + CandidatePool::::get(account).expect("all members of TopCandidates must be candidates q.e.d"); + num_of_delegators = num_of_delegators.max(state.delegators.len().saturated_into::()); + + // sum up total stake and amount of collators, delegators + let amount_collator = state.stake; + collator_stake = collator_stake.saturating_add(state.stake); + // safe to subtract because total >= stake + let amount_delegators = state.total - amount_collator; + delegator_stake = delegator_stake.saturating_add(amount_delegators); + } + + TotalCollatorStake::::mutate(|total| { + total.collators = collator_stake; + total.delegators = delegator_stake; + }); + + // return number of selected candidates and the corresponding number of their + // delegators for post-weight correction + (collators.len().saturated_into(), num_of_delegators) + } + + /// Update the collator's state by removing the delegator's stake and + /// starting the process to unlock the delegator's staked funds as well + /// as incrementing their accumulated rewards. + /// + /// This operation affects the pallet's total stake. + fn delegator_leaves_collator(delegator: T::AccountId, collator: T::AccountId) -> DispatchResult { + let mut state = CandidatePool::::get(&collator).ok_or(Error::::CandidateNotFound)?; + + let delegator_stake = state + .delegators + .remove(&Stake { + owner: delegator.clone(), + // amount is irrelevant for removal + amount: BalanceOf::::one(), + }) + .map(|nom| nom.amount) + .ok_or(Error::::DelegatorNotFound)?; + + let CandidateOf:: { + stake: old_stake, + total: old_total, + .. + } = state; + state.total = state.total.saturating_sub(delegator_stake); + let new_total = state.total; + + // increment rewards and kill storage for number of rewarded blocks + Self::do_inc_delegator_reward(&delegator, delegator_stake, &collator); + BlocksRewarded::::remove(&delegator); + + // we don't unlock immediately + Self::prep_unstake(&delegator, delegator_stake, false)?; + + // update top candidates and total amount at stake + if state.is_active() { + Self::update_top_candidates( + collator.clone(), + old_stake, + // safe because total >= stake + old_total - old_stake, + state.stake, + state.total - state.stake, + ); + } + CandidatePool::::insert(&collator, state); + + Self::deposit_event(Event::DelegatorLeftCollator( + delegator, + collator, + delegator_stake, + new_total, + )); + Ok(()) + } + + /// Return the best `MaxSelectedCandidates` many candidates. + /// + /// In case a collator from last round was replaced by a candidate with + /// the same total stake during sorting, we revert this swap to + /// prioritize collators over candidates. + pub fn selected_candidates() -> BoundedVec { + let candidates = TopCandidates::::get(); + + // Should never fail since WASM usize are 32bits and native are either 32 or 64 + let top_n = MaxSelectedCandidates::::get().saturated_into::(); + + log::trace!("{} Candidates for {} Collator seats", candidates.len(), top_n); + + // Choose the top MaxSelectedCandidates qualified candidates + let collators = candidates + .into_iter() + .take(top_n) + .filter(|x| x.amount >= T::MinCollatorStake::get()) + .map(|x| x.owner) + .collect::>(); + + collators.try_into().expect("Did not extend Collators q.e.d.") + } + + /// Attempts to add the stake to the set of delegators of a collator + /// which already reached its maximum size by removing an already + /// existing delegator with less staked value. If the given staked + /// amount is at most the minimum staked value of the original delegator + /// set, an error is returned. + /// + /// Sets rewards for the removed delegator. + /// + /// Returns a tuple which contains the updated candidate state as well + /// as the potentially replaced delegation which will be used later when + /// updating the storage of the replaced delegator. + /// + /// Emits `DelegationReplaced` if the stake exceeds one of the current + /// delegations. + #[allow(clippy::type_complexity)] + fn do_update_delegator( + stake: Stake>, + mut state: Candidate, T::MaxDelegatorsPerCollator>, + ) -> Result, DispatchError> { + // attempt to replace the last element of the set + let stake_to_remove = state + .delegators + .try_insert_replace(stake.clone()) + .map_err(|err_too_many| { + if err_too_many { + Error::::TooManyDelegators + } else { + // should never occur because we previously check this case, but let's be sure + Error::::AlreadyDelegating + } + })?; + + state.total = state.total.saturating_add(stake.amount); + + if let Some(stake_to_remove) = stake_to_remove { + // update total stake + state.total = state.total.saturating_sub(stake_to_remove.amount); + + // update rewards for kicked delegator + Self::do_inc_delegator_reward(&stake_to_remove.owner, stake_to_remove.amount, &state.id); + // prepare unstaking for kicked delegator + Self::prep_unstake(&stake_to_remove.owner, stake_to_remove.amount, true)?; + // remove Delegator state for kicked delegator + DelegatorState::::remove(&stake_to_remove.owner); + + Self::deposit_event(Event::DelegationReplaced( + stake.owner, + stake.amount, + stake_to_remove.owner, + stake_to_remove.amount, + state.id.clone(), + state.total, + )); + } + + Ok(state) + } + + /// Either set or increase the BalanceLock of target account to + /// amount. + /// + /// Consumes unstaked balance which can be unlocked in the future up to + /// amount and updates `Unstaking` storage accordingly. + fn increase_lock(who: &T::AccountId, amount: BalanceOf, more: BalanceOf) -> Result { + ensure!( + pallet_balances::Pallet::::free_balance(who) >= amount.into(), + pallet_balances::Error::::InsufficientBalance + ); + + let mut unstaking_len = 0u32; + + // *** No Fail except during Unstaking mutation beyond this point *** + + // update Unstaking by consuming up to {amount | more} + Unstaking::::try_mutate(who, |unstaking| -> DispatchResult { + // reduce {amount | more} by unstaking until either {amount | more} is zero or + // no unstaking is left + // if more is set, we only want to reduce by more to achieve 100 - 40 + 30 = 90 + // locked + let mut amt_consuming_unstaking = if more.is_zero() { amount } else { more }; + unstaking_len = unstaking.len().saturated_into(); + for (block_number, locked_balance) in unstaking.clone() { + if amt_consuming_unstaking.is_zero() { + break; + } else if locked_balance > amt_consuming_unstaking { + // amount is only reducible by locked_balance - amt_consuming_unstaking + let delta = locked_balance.saturating_sub(amt_consuming_unstaking); + // replace old entry with delta + unstaking + .try_insert(block_number, delta) + .map_err(|_| Error::::NoMoreUnstaking)?; + amt_consuming_unstaking = Zero::zero(); + } else { + // amount is either still reducible or reached + amt_consuming_unstaking = amt_consuming_unstaking.saturating_sub(locked_balance); + unstaking.remove(&block_number); + } + } + Ok(()) + })?; + + // Either set a new lock or potentially extend the existing one if amount + // exceeds the currently locked amount + T::Currency::extend_lock(STAKING_ID, who, amount, WithdrawReasons::all()); + + Ok(unstaking_len) + } + + /// Set the unlocking block for the account and corresponding amount + /// which can be unlocked via `unlock_unstaked` after waiting at + /// least for `StakeDuration` many blocks. + /// + /// Throws if the amount is zero (unlikely) or if active unlocking + /// requests exceed limit. The latter defends against stake reduction + /// spamming. + fn prep_unstake(who: &T::AccountId, amount: BalanceOf, is_removal: bool) -> DispatchResult { + // should never occur but let's be safe + ensure!(!amount.is_zero(), Error::::StakeNotFound); + + let now = frame_system::Pallet::::block_number(); + let unlock_block = now.saturating_add(T::StakeDuration::get()); + let mut unstaking = Unstaking::::get(who); + + let allowed_unstakings = if is_removal { + // the account was forcedly removed and we allow to fill all unstake requests + T::MaxUnstakeRequests::get() + } else { + // we need to reserve a free slot for a forced removal of the account + T::MaxUnstakeRequests::get().saturating_sub(1) + }; + ensure!( + unstaking.len().saturated_into::() < allowed_unstakings, + Error::::NoMoreUnstaking, + ); + + // if existent, we have to add the current amount of same unlock_block, because + // insert overwrites the current value + let amount = amount.saturating_add(*unstaking.get(&unlock_block).unwrap_or(&BalanceOf::::zero())); + unstaking + .try_insert(unlock_block, amount) + .map_err(|_| Error::::NoMoreUnstaking)?; + Unstaking::::insert(who, unstaking); + Ok(()) + } + + /// Clear the CandidatePool of the candidate and remove all delegations + /// to the candidate. Moreover, prepare unstaking for the candidate and + /// their former delegations. + fn remove_candidate( + collator: &T::AccountId, state: &CandidateOf, + ) -> DispatchResult { + // iterate over delegators + for stake in &state.delegators[..] { + // increment rewards + Self::do_inc_delegator_reward(&stake.owner, stake.amount, collator); + // prepare unstaking of delegator + Self::prep_unstake(&stake.owner, stake.amount, true)?; + // remove delegation from delegator state + if let Some(mut delegator) = DelegatorState::::get(&stake.owner) { + delegator + .try_clear(collator.clone()) + .map_err(|_| Error::::DelegationNotFound)?; + DelegatorState::::remove(&stake.owner); + } + } + // prepare unstaking of collator candidate + Self::prep_unstake(&state.id, state.stake, true)?; + + // *** No Fail beyond this point *** + + // increment rewards of collator + Self::do_inc_collator_reward(collator, state.stake); + + // disable validator for next session if they were in the set of validators + pallet_session::Pallet::::validators() + .into_iter() + .enumerate() + .find_map(|(i, id)| { + if ::ValidatorIdOf::convert(collator.clone()) + == Some(id) + { + Some(i) + } else { + None + } + }) + .map(u32::saturated_from::) + // FIXME: Does not prevent the collator from being able to author a block in this (or potentially the next) session. See https://github.com/paritytech/substrate/issues/8004 + .map(pallet_session::Pallet::::disable_index); + + // Kill storage + BlocksAuthored::::remove(collator); + BlocksRewarded::::remove(collator); + CandidatePool::::remove(collator); + Ok(()) + } + + /// Withdraw all staked currency which was unstaked at least + /// `StakeDuration` blocks ago. + fn do_unlock(who: &T::AccountId) -> Result { + let now = frame_system::Pallet::::block_number(); + let mut unstaking = Unstaking::::get(who); + let unstaking_len = unstaking.len().saturated_into::(); + ensure!(!unstaking.is_empty(), Error::::UnstakingIsEmpty); + + let mut total_unlocked: BalanceOf = Zero::zero(); + let mut total_locked: BalanceOf = Zero::zero(); + let mut expired = Vec::new(); + + // check potential unlocks + for (block_number, locked_balance) in unstaking.clone().into_iter() { + if block_number <= now { + expired.push(block_number); + total_unlocked = total_unlocked.saturating_add(locked_balance); + } else { + total_locked = total_locked.saturating_add(locked_balance); + } + } + for block_number in expired { + unstaking.remove(&block_number); + } + + // iterate balance locks to retrieve amount of locked balance + let locks = Locks::::get(who); + total_locked = if let Some(BalanceLock { amount, .. }) = locks.iter().find(|l| l.id == STAKING_ID) { + amount.saturating_sub(total_unlocked.into()).into() + } else { + // should never fail to find the lock since we checked whether unstaking is not + // empty but let's be safe + Zero::zero() + }; + + if total_locked.is_zero() { + T::Currency::remove_lock(STAKING_ID, who); + Unstaking::::remove(who); + } else { + T::Currency::set_lock(STAKING_ID, who, total_locked, WithdrawReasons::all()); + Unstaking::::insert(who, unstaking); + } + + Ok(unstaking_len) + } + + /// Checks whether a delegator can still delegate in this round, e.g., + /// if they have not delegated MaxDelegationsPerRound many times + /// already in this round. + fn get_delegation_counter(delegator: &T::AccountId) -> Result { + let last_delegation = LastDelegation::::get(delegator); + let round = Round::::get(); + + // reset counter if the round advanced since last delegation + let counter = if last_delegation.round < round.current { + 0u32 + } else { + last_delegation.counter + }; + + ensure!( + counter < T::MaxDelegationsPerRound::get(), + Error::::DelegationsPerRoundExceeded + ); + + Ok(DelegationCounter { + round: round.current, + counter: counter.saturating_add(1), + }) + } + + /// Calculates the network rewards per block with the current data and + /// issues these rewards to the network. The imbalance will be handled + /// in `on_initialize` by adding it to the free balance of + /// `NetworkRewardBeneficiary`. + /// + /// Over the course of an entire year, the network rewards equal the + /// maximum annual collator staking rewards multiplied with the + /// NetworkRewardRate. E.g., assuming 10% annual collator reward rate, + /// 10% max staking rate, 200k KILT max collator stake and 30 collators: + /// NetworkRewards = NetworkRewardRate * 10% * 10% * 200_000 KILT * 30 + /// + /// The expected rewards are the product of + /// * the current total maximum collator rewards + /// * and the configured NetworkRewardRate + /// + /// `col_reward_rate_per_block * col_max_stake * max_num_of_collators * + /// NetworkRewardRate` + fn issue_network_reward() -> NegativeImbalanceOf { + // Multiplication with Perquintill cannot overflow + let max_col_rewards = InflationConfig::::get().collator.reward_rate.per_block + * MaxCollatorCandidateStake::::get() + * MaxSelectedCandidates::::get().into(); + let network_reward = T::NetworkRewardRate::get() * max_col_rewards; + + T::Currency::issue(network_reward) + } + + /// Calculates the collator staking rewards for authoring `multiplier` + /// many blocks based on the given stake. + /// + /// Depends on the current total issuance and staking reward + /// configuration for collators. + pub(crate) fn calc_block_rewards_collator(stake: BalanceOf, multiplier: BalanceOf) -> BalanceOf { + let total_issuance = T::Currency::total_issuance(); + let TotalStake { + collators: total_collators, + .. + } = TotalCollatorStake::::get(); + let staking_rate = Perquintill::from_rational(total_collators, total_issuance); + + InflationConfig::::get() + .collator + .compute_reward::(stake, staking_rate, multiplier) + } + + /// Calculates the delegator staking rewards for `multiplier` many + /// blocks based on the given stake. + /// + /// Depends on the current total issuance and staking reward + /// configuration for delegators. + pub(crate) fn calc_block_rewards_delegator(stake: BalanceOf, multiplier: BalanceOf) -> BalanceOf { + let total_issuance = T::Currency::total_issuance(); + let TotalStake { + delegators: total_delegators, + .. + } = TotalCollatorStake::::get(); + let staking_rate = Perquintill::from_rational(total_delegators, total_issuance); + + InflationConfig::::get() + .delegator + .compute_reward::(stake, staking_rate, multiplier) + } + + /// Increment the accumulated rewards of a collator. + /// + /// Updates Rewarded(col) and sets BlocksRewarded(col) to equal + /// BlocksAuthored(col). + fn do_inc_collator_reward(acc: &T::AccountId, stake: BalanceOf) { + let count_authored = BlocksAuthored::::get(acc); + // We can already mutate thanks to extrinsics being transactional + let count_rewarded = BlocksRewarded::::mutate(acc, |rewarded| { + let old = *rewarded; + *rewarded = count_authored; + old + }); + let unclaimed_blocks = count_authored.saturating_sub(count_rewarded); + + Rewards::::mutate(acc, |reward| { + *reward = reward.saturating_add(Self::calc_block_rewards_collator(stake, unclaimed_blocks.into())); + }); + } + + /// Increment the accumulated rewards of a delegator by checking the + /// number of authored blocks by the collator. + /// + /// Updates Rewarded(del) and sets BlocksRewarded(del) to equal + /// BlocksAuthored(col). + fn do_inc_delegator_reward(acc: &T::AccountId, stake: BalanceOf, col: &T::AccountId) { + let count_authored = BlocksAuthored::::get(col); + // We can already mutate thanks to extrinsics being transactional + let count_rewarded = BlocksRewarded::::mutate(acc, |rewarded| { + let old = *rewarded; + *rewarded = count_authored; + old + }); + let unclaimed_blocks = count_authored.saturating_sub(count_rewarded); + + Rewards::::mutate(acc, |reward| { + *reward = reward.saturating_add(Self::calc_block_rewards_delegator(stake, unclaimed_blocks.into())) + }); + } + } + + impl pallet_authorship::EventHandler for Pallet + where + T: Config + pallet_authorship::Config + pallet_session::Config, + { + /// Increments the reward counter of the block author by the current + /// number of collators in the session. + fn note_author(author: T::AccountId) { + // should always include state except if the collator has been forcedly removed + // via `force_remove_candidate` in the current or previous round + if CandidatePool::::get(&author).is_some() { + // necessary to compensate for a potentially fluctuating number of collators + let authors = pallet_session::Pallet::::validators(); + BlocksAuthored::::mutate(&author, |count| { + *count = count.saturating_add(authors.len().saturated_into::()); + }); + } + + frame_system::Pallet::::register_extra_weight_unchecked( + T::DbWeight::get().reads_writes(2, 1), + DispatchClass::Mandatory, + ); + } + } + + impl pallet_session::SessionManager for Pallet { + /// 1. A new session starts. + /// 2. In hook new_session: Read the current top n candidates from the + /// TopCandidates and assign this set to author blocks for the next + /// session. + /// 3. AuRa queries the authorities from the session pallet for + /// this session and picks authors on round-robin-basis from list of + /// authorities. + fn new_session(new_index: SessionIndex) -> Option> { + log::debug!( + "assembling new collators for new session {} at #{:?}", + new_index, + frame_system::Pallet::::block_number(), + ); + + frame_system::Pallet::::register_extra_weight_unchecked( + T::DbWeight::get().reads(2), + DispatchClass::Mandatory, + ); + + let collators = Pallet::::selected_candidates().to_vec(); + if collators.is_empty() { + // we never want to pass an empty set of collators. This would brick the chain. + log::error!("💥 keeping old session because of empty collator set!"); + None + } else { + Some(collators) + } + } + + fn end_session(_end_index: SessionIndex) { + // we too are not caring. + } + + fn start_session(_start_index: SessionIndex) { + // we too are not caring. + } + } + + impl ShouldEndSession for Pallet { + fn should_end_session(now: T::BlockNumber) -> bool { + frame_system::Pallet::::register_extra_weight_unchecked( + T::DbWeight::get().reads(2), + DispatchClass::Mandatory, + ); + + let mut round = Round::::get(); + // always update when a new round should start + if round.should_update(now) { + true + } else if ForceNewRound::::get() { + frame_system::Pallet::::register_extra_weight_unchecked( + T::DbWeight::get().writes(2), + DispatchClass::Mandatory, + ); + // check for forced new round + ForceNewRound::::put(false); + round.update(now); + Round::::put(round); + Self::deposit_event(Event::NewRound(round.first, round.current)); + true + } else { + false + } + } + } + + impl EstimateNextSessionRotation for Pallet { + fn average_session_length() -> T::BlockNumber { + Round::::get().length + } + + fn estimate_current_session_progress(now: T::BlockNumber) -> (Option, Weight) { + let round = Round::::get(); + let passed_blocks = now.saturating_sub(round.first); + + ( + Some(Permill::from_rational(passed_blocks, round.length)), + // One read for the round info, blocknumber is read free + T::DbWeight::get().reads(1), + ) + } + + fn estimate_next_session_rotation(_now: T::BlockNumber) -> (Option, Weight) { + let round = Round::::get(); + + ( + Some(round.first + round.length), + // One read for the round info, blocknumber is read free + T::DbWeight::get().reads(1), + ) + } + } +} diff --git a/pallets/parachain-staking/src/migration.rs b/pallets/parachain-staking/src/migration.rs new file mode 100644 index 000000000..79e74681a --- /dev/null +++ b/pallets/parachain-staking/src/migration.rs @@ -0,0 +1,17 @@ +// KILT Blockchain – https://botlabs.org +// Copyright (C) 2019-2023 BOTLabs GmbH + +// The KILT Blockchain 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. + +// The KILT Blockchain 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 this program. If not, see . + +// If you feel like getting in touch with us, you can do so at info@botlabs.org diff --git a/pallets/parachain-staking/src/mock.rs b/pallets/parachain-staking/src/mock.rs new file mode 100644 index 000000000..838b523ba --- /dev/null +++ b/pallets/parachain-staking/src/mock.rs @@ -0,0 +1,421 @@ +// KILT Blockchain – https://botlabs.org +// Copyright (C) 2019-2023 BOTLabs GmbH + +// The KILT Blockchain 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. + +// The KILT Blockchain 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 this program. If not, see . + +// If you feel like getting in touch with us, you can do so at info@botlabs.org +//! Test utilities + +#![allow(clippy::from_over_into)] + +use frame_support::{ + assert_ok, construct_runtime, parameter_types, + traits::{Currency, GenesisBuild, OnFinalize, OnInitialize, OnUnbalanced}, +}; +use pallet_authorship::EventHandler; +use sp_consensus_aura::sr25519::AuthorityId; +use sp_core::H256; +use sp_runtime::{ + impl_opaque_keys, + testing::{Header, UintAuthorityId}, + traits::{BlakeTwo256, ConvertInto, IdentityLookup, OpaqueKeys}, + Perbill, Perquintill, +}; +use sp_std::fmt::Debug; + +use crate::{self as stake, types::NegativeImbalanceOf}; + +use super::*; + +pub(crate) type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +pub(crate) type Block = frame_system::mocking::MockBlock; +pub(crate) type Balance = u128; +pub(crate) type AccountId = u64; +pub(crate) type BlockNumber = u64; + +pub(crate) const MILLI_KILT: Balance = 10u128.pow(12); +pub(crate) const MAX_COLLATOR_STAKE: Balance = 200_000 * 1000 * MILLI_KILT; +pub(crate) const BLOCKS_PER_ROUND: BlockNumber = 5; +pub(crate) const DECIMALS: Balance = 1000 * MILLI_KILT; +pub(crate) const TREASURY_ACC: AccountId = u64::MAX; + +// Configure a mock runtime to test the pallet. +construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + Aura: pallet_aura::{Pallet, Storage}, + Session: pallet_session::{Pallet, Call, Storage, Event, Config}, + StakePallet: stake::{Pallet, Call, Storage, Config, Event}, + Authorship: pallet_authorship::{Pallet, Storage}, + } +); + +parameter_types! { + pub const BlockHashCount: u64 = 250; + pub const MaximumBlockLength: u32 = 2 * 1024; + pub const AvailableBlockRatio: Perbill = Perbill::one(); + pub const SS58Prefix: u8 = 42; +} + +impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type Index = u64; + type BlockNumber = BlockNumber; + type RuntimeCall = RuntimeCall; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type BlockWeights = (); + type BlockLength = (); + type SS58Prefix = SS58Prefix; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} +parameter_types! { + pub const ExistentialDeposit: Balance = 1; +} + +impl pallet_balances::Config for Test { + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} + +impl pallet_aura::Config for Test { + type AuthorityId = AuthorityId; + type DisabledValidators = (); + type MaxAuthorities = MaxCollatorCandidates; +} + +impl pallet_authorship::Config for Test { + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; + type EventHandler = Pallet; +} + +parameter_types! { + pub const MinBlocksPerRound: BlockNumber = 3; + pub const StakeDuration: u32 = 2; + pub const ExitQueueDelay: u32 = 2; + pub const DefaultBlocksPerRound: BlockNumber = BLOCKS_PER_ROUND; + pub const MinCollators: u32 = 2; + pub const MaxDelegationsPerRound: u32 = 2; + #[derive(Debug, Eq, PartialEq)] + pub const MaxDelegatorsPerCollator: u32 = 4; + pub const MinCollatorStake: Balance = 10; + #[derive(Debug, Eq, PartialEq)] + pub const MaxCollatorCandidates: u32 = 10; + pub const MinDelegatorStake: Balance = 5; + pub const MaxUnstakeRequests: u32 = 6; + pub const NetworkRewardRate: Perquintill = Perquintill::from_percent(10); + pub const NetworkRewardStart: BlockNumber = 5 * 5 * 60 * 24 * 36525 / 100; +} + +pub struct ToBeneficiary(); +impl OnUnbalanced> for ToBeneficiary { + fn on_nonzero_unbalanced(amount: NegativeImbalanceOf) { + // Must resolve into existing but better to be safe. + ::Currency::resolve_creating(&TREASURY_ACC, amount); + } +} + +impl Config for Test { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type CurrencyBalance = ::Balance; + type MinBlocksPerRound = MinBlocksPerRound; + type DefaultBlocksPerRound = DefaultBlocksPerRound; + type StakeDuration = StakeDuration; + type ExitQueueDelay = ExitQueueDelay; + type MinCollators = MinCollators; + type MinRequiredCollators = MinCollators; + type MaxDelegationsPerRound = MaxDelegationsPerRound; + type MaxDelegatorsPerCollator = MaxDelegatorsPerCollator; + type MinCollatorStake = MinCollatorStake; + type MinCollatorCandidateStake = MinCollatorStake; + type MaxTopCandidates = MaxCollatorCandidates; + type MinDelegatorStake = MinDelegatorStake; + type MaxUnstakeRequests = MaxUnstakeRequests; + type NetworkRewardRate = NetworkRewardRate; + type NetworkRewardStart = NetworkRewardStart; + type NetworkRewardBeneficiary = ToBeneficiary; + type WeightInfo = (); + const BLOCKS_PER_YEAR: Self::BlockNumber = 5 * 60 * 24 * 36525 / 100; +} + +impl_opaque_keys! { + pub struct MockSessionKeys { + pub aura: Aura, + } +} + +parameter_types! { + pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17); +} + +impl pallet_session::Config for Test { + type RuntimeEvent = RuntimeEvent; + type ValidatorId = AccountId; + type ValidatorIdOf = ConvertInto; + type ShouldEndSession = StakePallet; + type NextSessionRotation = StakePallet; + type SessionManager = StakePallet; + type SessionHandler = ::KeyTypeIdProviders; + type Keys = MockSessionKeys; + type WeightInfo = (); +} + +parameter_types! { + pub const MinimumPeriod: u64 = 1; +} + +impl pallet_timestamp::Config for Test { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +pub(crate) struct ExtBuilder { + // endowed accounts with balances + balances: Vec<(AccountId, Balance)>, + // [collator, amount] + collators: Vec<(AccountId, Balance)>, + // [delegator, collator, delegation_amount] + delegators: Vec<(AccountId, AccountId, Balance)>, + // inflation config + inflation_config: InflationInfo, + // blocks per round + blocks_per_round: BlockNumber, +} + +impl Default for ExtBuilder { + fn default() -> ExtBuilder { + ExtBuilder { + balances: vec![], + delegators: vec![], + collators: vec![], + blocks_per_round: BLOCKS_PER_ROUND, + inflation_config: InflationInfo::new( + ::BLOCKS_PER_YEAR, + Perquintill::from_percent(10), + Perquintill::from_percent(15), + Perquintill::from_percent(40), + Perquintill::from_percent(10), + ), + } + } +} + +impl ExtBuilder { + #[must_use] + pub(crate) fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self { + self.balances = balances; + self + } + + #[must_use] + pub(crate) fn with_collators(mut self, collators: Vec<(AccountId, Balance)>) -> Self { + self.collators = collators; + self + } + + #[must_use] + pub(crate) fn with_delegators(mut self, delegators: Vec<(AccountId, AccountId, Balance)>) -> Self { + self.delegators = delegators; + self + } + + #[must_use] + pub(crate) fn with_inflation( + mut self, col_max: u64, col_rewards: u64, d_max: u64, d_rewards: u64, blocks_per_round: BlockNumber, + ) -> Self { + self.inflation_config = InflationInfo::new( + ::BLOCKS_PER_YEAR, + Perquintill::from_percent(col_max), + Perquintill::from_percent(col_rewards), + Perquintill::from_percent(d_max), + Perquintill::from_percent(d_rewards), + ); + self.blocks_per_round = blocks_per_round; + + self + } + + #[must_use] + pub(crate) fn set_blocks_per_round(mut self, blocks_per_round: BlockNumber) -> Self { + self.blocks_per_round = blocks_per_round; + self + } + + pub(crate) fn build(self) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default() + .build_storage::() + .expect("Frame system builds valid default genesis config"); + + pallet_balances::GenesisConfig:: { + balances: self.balances.clone(), + } + .assimilate_storage(&mut t) + .expect("Pallet balances storage can be assimilated"); + + let mut stakers: Vec<(AccountId, Option, Balance)> = Vec::new(); + for collator in self.collators.clone() { + stakers.push((collator.0, None, collator.1)); + } + for delegator in self.delegators.clone() { + stakers.push((delegator.0, Some(delegator.1), delegator.2)); + } + stake::GenesisConfig:: { + stakers, + inflation_config: self.inflation_config.clone(), + max_candidate_stake: 160_000_000 * DECIMALS, + } + .assimilate_storage(&mut t) + .expect("Parachain Staking's storage can be assimilated"); + + // stashes are the AccountId + let session_keys: Vec<_> = self + .collators + .iter() + .map(|(k, _)| { + ( + *k, + *k, + MockSessionKeys { + aura: UintAuthorityId(*k).to_public_key(), + }, + ) + }) + .collect(); + + // NOTE: this will initialize the aura authorities + // through OneSessionHandler::on_genesis_session + pallet_session::GenesisConfig:: { keys: session_keys } + .assimilate_storage(&mut t) + .expect("Session Pallet's storage can be assimilated"); + + let mut ext = sp_io::TestExternalities::new(t); + + if self.blocks_per_round != BLOCKS_PER_ROUND { + ext.execute_with(|| { + StakePallet::set_blocks_per_round(RuntimeOrigin::root(), self.blocks_per_round) + .expect("Ran into issues when setting blocks_per_round"); + }); + } + + ext.execute_with(|| System::set_block_number(1)); + ext + } +} + +/// Compare whether the difference of both sides is at most `precision * left`. +pub(crate) fn almost_equal(left: Balance, right: Balance, precision: Perbill) -> bool { + let err = precision * left; + left.max(right) - left.min(right) <= err +} + +/// Incrementelly traverses from the current block to the provided one and +/// potentially sets block authors. +/// +/// If for a block `i` the corresponding index of the authors input is set, this +/// account is regarded to be the block author and thus gets noted. +/// +/// NOTE: At most, this updates the RewardCount of the block author but does not +/// increment rewards or claim them. Please use `roll_to_claim_rewards` in that +/// case. +pub(crate) fn roll_to(n: BlockNumber, authors: Vec>) { + while System::block_number() < n { + if let Some(Some(author)) = authors.get((System::block_number()) as usize) { + StakePallet::note_author(*author); + } + >::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + >::on_initialize(System::block_number()); + } +} + +#[allow(unused_must_use)] +/// Incrementelly traverses from the current block to the provided one and +/// potentially sets block authors. +/// +/// If existent, rewards of the block author and their delegators are +/// incremented and claimed. +/// +/// If for a block `i` the corresponding index of the authors input is set, this +/// account is regarded to be the block author and thus gets noted. +pub(crate) fn roll_to_claim_rewards(n: BlockNumber, authors: Vec>) { + while System::block_number() < n { + if let Some(Some(author)) = authors.get((System::block_number()) as usize) { + StakePallet::note_author(*author); + // author has to increment rewards before claiming + assert_ok!(StakePallet::increment_collator_rewards(RuntimeOrigin::signed(*author))); + // author claims rewards + assert_ok!(StakePallet::claim_rewards(RuntimeOrigin::signed(*author))); + + // claim rewards for delegators + let col_state = StakePallet::candidate_pool(author).expect("Block author must be candidate"); + for delegation in col_state.delegators { + // delegator has to increment rewards before claiming + StakePallet::increment_delegator_rewards(RuntimeOrigin::signed(delegation.owner)); + // NOTE: cannot use assert_ok! as we sometimes expect zero rewards for + // delegators such that the claiming would throw + StakePallet::claim_rewards(RuntimeOrigin::signed(delegation.owner)); + } + } + >::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + >::on_initialize(System::block_number()); + } +} + +pub(crate) fn last_event() -> pallet::Event { + events().pop().expect("Event expected") +} + +pub(crate) fn events() -> Vec> { + System::events() + .into_iter() + .map(|r| r.event) + .filter_map(|e| { + if let RuntimeEvent::StakePallet(inner) = e { + Some(inner) + } else { + None + } + }) + .collect::>() +} diff --git a/pallets/parachain-staking/src/set.rs b/pallets/parachain-staking/src/set.rs new file mode 100644 index 000000000..d8bf16bae --- /dev/null +++ b/pallets/parachain-staking/src/set.rs @@ -0,0 +1,553 @@ +// KILT Blockchain – https://botlabs.org +// Copyright (C) 2019-2023 BOTLabs GmbH + +// The KILT Blockchain 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. + +// The KILT Blockchain 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 this program. If not, see . + +// If you feel like getting in touch with us, you can do so at info@botlabs.org + +use frame_support::{traits::Get, BoundedVec, DefaultNoBound, RuntimeDebug}; +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use sp_runtime::{traits::Zero, SaturatedConversion}; +#[cfg(feature = "std")] +use sp_std::prelude::*; +use sp_std::{ + cmp::Ordering, + convert::TryInto, + ops::{Index, Range, RangeFull}, +}; + +/// An ordered set backed by `BoundedVec`. +#[derive(PartialEq, Eq, Encode, Decode, DefaultNoBound, Clone, TypeInfo, MaxEncodedLen, RuntimeDebug)] +#[scale_info(skip_type_params(S))] +#[codec(mel_bound(T: MaxEncodedLen))] +pub struct OrderedSet>(BoundedVec); + +impl> OrderedSet { + /// Create a new empty set. + pub fn new() -> Self { + Self(BoundedVec::default()) + } + + /// Creates an ordered set from a `BoundedVec`. + /// + /// The vector will be sorted reversily (from greatest to lowest) and + /// deduped first. + pub fn from(bv: BoundedVec) -> Self { + let mut v = bv.into_inner(); + v.sort_by(|a, b| b.cmp(a)); + v.dedup(); + Self::from_sorted_set(v.try_into().map_err(|_| ()).expect("No values were added")) + } + + /// Create a set from a `BoundedVec`. + /// + /// Assumes that `v` is sorted reversely (from greatest to lowest) and only + /// contains unique elements. + pub fn from_sorted_set(bv: BoundedVec) -> Self { + Self(bv) + } + + /// Mutate the set without restrictions. After the set was mutated it will + /// be resorted and deduplicated. + pub fn mutate)>(&mut self, function: F) { + function(&mut self.0); + (self.0[..]).sort_by(|a, b| b.cmp(a)); + + // TODO: add dedup to BoundedVec + let mut i: usize = 0; + let mut next = i.saturating_add(1); + while next < self.len() { + if self[i] == self[next] { + self.0.remove(next); + } else { + i = next; + next = next.saturating_add(1); + } + } + } + + /// Inserts an element, if no equal item exist in the set. + /// + /// Returns an error if insertion would exceed the bounded vec's max size. + /// The error contains the index where the element would be inserted, if + /// enough space would be left. + /// + /// Returns true if the item is unique in the set, otherwise returns false. + pub fn try_insert(&mut self, value: T) -> Result { + match self.linear_search(&value) { + Ok(_) => Ok(false), + Err(loc) => { + self.0.try_insert(loc, value).map_err(|_| loc)?; + Ok(true) + } + } + } + + /// Inserts an element, if no equal item exist in the set. If the set is + /// full, but an element with a lower rank is in the set, the element with + /// the lowest rank will be removed and the new element will be added. + /// + /// Returns + /// * Ok(Some(old_element)) if the new element was added and an old element + /// had to be removed. + /// * Ok(None) if the element was added without removing an element. + /// * Err(true) if the set is full and the new element has a lower rank than + /// the lowest element in the set. + /// * Err(false) if the element is already in the set. + pub fn try_insert_replace(&mut self, value: T) -> Result, bool> { + // the highest allowed index + let highest_index: usize = S::get().saturating_sub(1).saturated_into(); + if S::get().is_zero() { + return Err(true); + } + match self.try_insert(value.clone()) { + Err(loc) if loc <= highest_index => { + // always replace the last element + let last_idx = self.len().saturating_sub(1); + // accessing by index wont panic since we checked the index, inserting the item + // at the end of the list to ensure last-in-least-priority-rule for collators. + // sorting algorithm must be stable! + let old = sp_std::mem::replace(&mut self.0[last_idx], value); + self.sort_greatest_to_lowest(); + Ok(Some(old)) + } + Err(_) => Err(true), + Ok(false) => Err(false), + Ok(_) => Ok(None), + } + } + + /// Inserts a new element or updates the value of an existing one. + /// + /// Returns an error if the maximum size of the bounded vec would be + /// exceeded upon insertion. + /// + /// Returns the old value if existing or None if the value did not exist + /// before. + pub fn try_upsert(&mut self, value: T) -> Result, ()> { + match self.linear_search(&value) { + Ok(i) => { + let old = sp_std::mem::replace(&mut self.0[i], value); + self.sort_greatest_to_lowest(); + Ok(Some(old)) + } + Err(i) => { + // Delegator + self.0.try_insert(i, value).map_err(|_| ())?; + Ok(None) + } + } + } + + /// Removes an element. + /// + /// Returns true if removal happened. + pub fn remove(&mut self, value: &T) -> Option { + match self.linear_search(value) { + Ok(loc) => Some(self.0.remove(loc)), + Err(_) => None, + } + } + + /// Return whether the set contains `value`. + pub fn contains(&self, value: &T) -> bool { + self.linear_search(value).is_ok() + } + + /// Iteratively searches this (from greatest to lowest) ordered set for a + /// given element. + /// + /// 1. If the value is found, then Result::Ok is returned, containing the + /// index of the matching element. + /// 2. If the value is not found, then Result::Err is returned, containing + /// the index where a matching element could be inserted while maintaining + /// sorted order. + pub fn linear_search(&self, value: &T) -> Result { + let size = self.0.len(); + let mut loc: usize = size; + // keep running until we find a smaller item + self.0 + .iter() + .enumerate() + .find_map(|(i, v)| { + match (v.cmp(value), loc == size) { + // prevent to have same items + (Ordering::Equal, _) => Some(Ok(i)), + // eventually, we want to return this index but we need to keep checking for Ordering::Equal in case + // value is still in the set + (Ordering::Less, true) => { + // insert after current element + loc = i; + None + } + _ => None, + } + }) + .unwrap_or(Err(loc)) + } + + /// Clear the set. + pub fn clear(&mut self) { + self.0 = BoundedVec::default(); + } + + /// Return the length of the set. + pub fn len(&self) -> usize { + self.0.len() + } + + /// Return whether the set is empty. + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + /// Convert the set to a bounded vector. + pub fn into_bounded_vec(self) -> BoundedVec { + self.0 + } + + /// Returns a reference to an element or None if out of bounds. + pub fn get(&self, index: usize) -> Option<&T> { + self.0.get(index) + } + + /// Sorts from greatest to lowest. + pub fn sort_greatest_to_lowest(&mut self) { + (self.0[..]).sort_by(|a, b| b.cmp(a)); + } +} + +impl> From> for OrderedSet { + fn from(bv: BoundedVec) -> Self { + Self::from(bv) + } +} + +impl> Index for OrderedSet { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + &self.0[index] + } +} + +impl> Index> for OrderedSet { + type Output = [T]; + + fn index(&self, range: Range) -> &Self::Output { + &self.0[range] + } +} + +impl> Index for OrderedSet { + type Output = [T]; + + fn index(&self, range: RangeFull) -> &Self::Output { + &self.0[range] + } +} + +impl> IntoIterator for OrderedSet { + type Item = T; + type IntoIter = sp_std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +impl> From> for BoundedVec { + fn from(s: OrderedSet) -> Self { + s.0 + } +} + +#[cfg(test)] +mod tests { + use frame_support::parameter_types; + use sp_runtime::RuntimeDebug; + + use crate::{mock::Test, types::StakeOf}; + + use super::*; + + parameter_types! { + #[derive(Eq, PartialEq, RuntimeDebug)] + pub const Zero: u32 = 0; + #[derive(Eq, PartialEq, RuntimeDebug)] + pub const One: u32 = 1; + #[derive(Eq, PartialEq, RuntimeDebug)] + pub const Eight: u32 = 8; + #[derive(Clone, Eq, PartialEq, RuntimeDebug)] + pub const Five: u32 = 5; + } + + #[test] + fn from() { + let v: BoundedVec = vec![4, 2, 3, 4, 3, 1].try_into().unwrap(); + let set: OrderedSet = v.into(); + assert_eq!( + set, + OrderedSet::::from(vec![1, 2, 3, 4].try_into().unwrap()) + ); + } + + #[test] + fn insert() { + let mut set: OrderedSet = OrderedSet::new(); + assert_eq!(set, OrderedSet::::from(vec![].try_into().unwrap())); + + assert_eq!(set.try_insert(1), Ok(true)); + assert_eq!(set, OrderedSet::::from(vec![1].try_into().unwrap())); + + assert_eq!(set.try_insert(5), Ok(true)); + assert_eq!(set, OrderedSet::::from(vec![1, 5].try_into().unwrap())); + + assert_eq!(set.try_insert(3), Ok(true)); + assert_eq!(set, OrderedSet::::from(vec![1, 3, 5].try_into().unwrap())); + + assert_eq!(set.try_insert(3), Ok(false)); + assert_eq!(set, OrderedSet::::from(vec![1, 3, 5].try_into().unwrap())); + } + + #[test] + fn remove() { + let mut set: OrderedSet = OrderedSet::from(vec![1, 2, 3, 4].try_into().unwrap()); + + assert_eq!(set.remove(&5), None); + assert_eq!( + set, + OrderedSet::::from(vec![1, 2, 3, 4].try_into().unwrap()) + ); + + assert_eq!(set.remove(&1), Some(1)); + assert_eq!(set, OrderedSet::::from(vec![2, 3, 4].try_into().unwrap())); + + assert_eq!(set.remove(&3), Some(3)); + assert_eq!(set, OrderedSet::::from(vec![2, 4].try_into().unwrap())); + + assert_eq!(set.remove(&3), None); + assert_eq!(set, OrderedSet::::from(vec![2, 4].try_into().unwrap())); + + assert_eq!(set.remove(&4), Some(4)); + assert_eq!(set, OrderedSet::::from(vec![2].try_into().unwrap())); + + assert_eq!(set.remove(&2), Some(2)); + assert_eq!(set, OrderedSet::::from(vec![].try_into().unwrap())); + + assert_eq!(set.remove(&2), None); + assert_eq!(set, OrderedSet::::from(vec![].try_into().unwrap())); + } + + #[test] + fn contains() { + let set: OrderedSet = OrderedSet::from(vec![1, 2, 3, 4].try_into().unwrap()); + assert!(!set.contains(&5)); + assert!(set.contains(&1)); + assert!(set.contains(&3)); + } + + #[test] + fn clear() { + let mut set: OrderedSet = OrderedSet::from(vec![1, 2, 3, 4].try_into().unwrap()); + set.clear(); + assert_eq!(set, OrderedSet::new()); + } + + #[test] + fn try_insert_replace_integer() { + let mut set: OrderedSet = OrderedSet::from(vec![].try_into().unwrap()); + assert_eq!(set.try_insert_replace(10), Err(true)); + + let mut set: OrderedSet = OrderedSet::from(vec![].try_into().unwrap()); + assert_eq!(set.try_insert_replace(10), Ok(None)); + assert_eq!(set.try_insert_replace(9), Err(true)); + assert_eq!(set.try_insert_replace(11), Ok(Some(10))); + + let mut set: OrderedSet = OrderedSet::from(vec![].try_into().unwrap()); + assert_eq!(set.try_insert_replace(10), Ok(None)); + assert_eq!(set.try_insert_replace(7), Ok(None)); + assert_eq!(set.try_insert_replace(9), Ok(None)); + assert_eq!(set.try_insert_replace(8), Ok(None)); + + assert_eq!(set.clone().into_bounded_vec().into_inner(), vec![10, 9, 8, 7]); + assert_eq!(set.try_insert_replace(5), Ok(None)); + assert!(set.try_insert(11).is_err()); + + assert_eq!(set.try_insert_replace(6), Ok(Some(5))); + assert_eq!(set.clone().into_bounded_vec().into_inner(), vec![10, 9, 8, 7, 6]); + + assert_eq!(set.try_insert_replace(6), Err(false)); + assert_eq!(set.try_insert_replace(5), Err(true)); + + assert_eq!(set.try_insert_replace(10), Err(false)); + assert_eq!(set.try_insert_replace(11), Ok(Some(6))); + assert_eq!(set.into_bounded_vec().into_inner(), vec![11, 10, 9, 8, 7]); + } + + #[test] + fn try_insert_replace_stake() { + let mut set: OrderedSet, Eight> = OrderedSet::from( + vec![ + StakeOf:: { owner: 1, amount: 100 }, + StakeOf:: { owner: 3, amount: 90 }, + StakeOf:: { owner: 5, amount: 80 }, + StakeOf:: { owner: 7, amount: 70 }, + StakeOf:: { owner: 8, amount: 70 }, + StakeOf:: { owner: 9, amount: 60 }, + ] + .try_into() + .unwrap(), + ); + assert_eq!( + set.try_insert_replace(StakeOf:: { owner: 1, amount: 0 }), + Err(false) + ); + assert_eq!( + set.try_insert_replace(StakeOf:: { owner: 7, amount: 100 }), + Err(false) + ); + assert_eq!( + set.try_insert_replace(StakeOf:: { owner: 7, amount: 50 }), + Err(false) + ); + assert_eq!( + set.try_insert_replace(StakeOf:: { owner: 8, amount: 50 }), + Err(false) + ); + assert_eq!( + set.try_insert_replace(StakeOf:: { owner: 2, amount: 100 }), + Ok(None) + ); + assert_eq!( + set.try_insert_replace(StakeOf:: { owner: 2, amount: 90 }), + Err(false) + ); + assert_eq!( + set.try_insert_replace(StakeOf:: { owner: 10, amount: 65 }), + Ok(None) + ); + assert_eq!( + set.try_insert_replace(StakeOf:: { owner: 11, amount: 60 }), + Err(true) + ); + assert_eq!( + set.try_insert_replace(StakeOf:: { owner: 11, amount: 100 }), + Ok(Some(StakeOf:: { owner: 9, amount: 60 })) + ); + } + + #[test] + fn exceeding_max_size_should_fail() { + let mut set: OrderedSet = OrderedSet::from(vec![1, 2, 3, 4, 5].try_into().unwrap()); + let inserted = set.try_insert(6); + + assert!(inserted.is_err()); + } + + #[test] + fn linear_search() { + let set: OrderedSet, Eight> = OrderedSet::from( + vec![ + StakeOf:: { owner: 1, amount: 100 }, + StakeOf:: { owner: 3, amount: 90 }, + StakeOf:: { owner: 5, amount: 80 }, + StakeOf:: { owner: 7, amount: 70 }, + StakeOf:: { owner: 8, amount: 70 }, + StakeOf:: { owner: 9, amount: 60 }, + ] + .try_into() + .unwrap(), + ); + assert_eq!(set.linear_search(&StakeOf:: { owner: 1, amount: 0 }), Ok(0)); + assert_eq!(set.linear_search(&StakeOf:: { owner: 7, amount: 100 }), Ok(3)); + assert_eq!(set.linear_search(&StakeOf:: { owner: 7, amount: 50 }), Ok(3)); + assert_eq!(set.linear_search(&StakeOf:: { owner: 8, amount: 50 }), Ok(4)); + assert_eq!(set.linear_search(&StakeOf:: { owner: 2, amount: 100 }), Err(1)); + assert_eq!(set.linear_search(&StakeOf:: { owner: 2, amount: 90 }), Err(2)); + assert_eq!(set.linear_search(&StakeOf:: { owner: 2, amount: 65 }), Err(5)); + assert_eq!(set.linear_search(&StakeOf:: { owner: 2, amount: 60 }), Err(6)); + assert_eq!(set.linear_search(&StakeOf:: { owner: 2, amount: 59 }), Err(6)); + } + + #[test] + fn upsert_set() { + let mut set: OrderedSet, Eight> = OrderedSet::from( + vec![ + StakeOf:: { owner: 1, amount: 100 }, + StakeOf:: { owner: 3, amount: 90 }, + StakeOf:: { owner: 5, amount: 80 }, + StakeOf:: { owner: 7, amount: 70 }, + StakeOf:: { owner: 9, amount: 60 }, + ] + .try_into() + .unwrap(), + ); + assert_eq!(set.try_insert(StakeOf:: { owner: 2, amount: 75 }), Ok(true)); + assert_eq!( + set, + OrderedSet::from( + vec![ + StakeOf:: { owner: 1, amount: 100 }, + StakeOf:: { owner: 3, amount: 90 }, + StakeOf:: { owner: 5, amount: 80 }, + StakeOf:: { owner: 2, amount: 75 }, + StakeOf:: { owner: 7, amount: 70 }, + StakeOf:: { owner: 9, amount: 60 }, + ] + .try_into() + .unwrap() + ) + ); + assert_eq!( + set.try_upsert(StakeOf:: { owner: 2, amount: 90 }), + Ok(Some(StakeOf:: { owner: 2, amount: 75 })) + ); + assert_eq!( + set, + OrderedSet::from( + vec![ + StakeOf:: { owner: 1, amount: 100 }, + StakeOf:: { owner: 3, amount: 90 }, + StakeOf:: { owner: 2, amount: 90 }, + StakeOf:: { owner: 5, amount: 80 }, + StakeOf:: { owner: 7, amount: 70 }, + StakeOf:: { owner: 9, amount: 60 }, + ] + .try_into() + .unwrap() + ) + ); + assert_eq!( + set.try_upsert(StakeOf:: { owner: 2, amount: 60 }), + Ok(Some(StakeOf:: { owner: 2, amount: 90 })) + ); + assert_eq!( + set, + OrderedSet::from( + vec![ + StakeOf:: { owner: 1, amount: 100 }, + StakeOf:: { owner: 3, amount: 90 }, + StakeOf:: { owner: 5, amount: 80 }, + StakeOf:: { owner: 7, amount: 70 }, + StakeOf:: { owner: 2, amount: 60 }, + StakeOf:: { owner: 9, amount: 60 }, + ] + .try_into() + .unwrap() + ) + ); + } +} diff --git a/pallets/parachain-staking/src/tests.rs b/pallets/parachain-staking/src/tests.rs new file mode 100644 index 000000000..accc93d1a --- /dev/null +++ b/pallets/parachain-staking/src/tests.rs @@ -0,0 +1,4347 @@ +// KILT Blockchain – https://botlabs.org +// Copyright (C) 2019-2023 BOTLabs GmbH + +// The KILT Blockchain 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. + +// The KILT Blockchain 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 this program. If not, see . + +// If you feel like getting in touch with us, you can do so at info@botlabs.org + +//! Unit testing + +use std::{convert::TryInto, iter}; + +use frame_support::{ + assert_noop, assert_ok, storage::bounded_btree_map::BoundedBTreeMap, traits::EstimateNextSessionRotation, + BoundedVec, +}; +use pallet_authorship::EventHandler; +use pallet_balances::{BalanceLock, Error as BalancesError, Reasons}; +use pallet_session::{SessionManager, ShouldEndSession}; +use sp_runtime::{traits::Zero, Perbill, Permill, Perquintill, SaturatedConversion}; + +use kilt_runtime_api_staking::StakingRates; + +use crate::{ + mock::{ + almost_equal, events, last_event, roll_to, roll_to_claim_rewards, AccountId, Balance, Balances, BlockNumber, + ExtBuilder, RuntimeOrigin, Session, StakePallet, System, Test, BLOCKS_PER_ROUND, DECIMALS, TREASURY_ACC, + }, + set::OrderedSet, + types::{ + BalanceOf, Candidate, CandidateStatus, DelegationCounter, Delegator, RoundInfo, Stake, StakeOf, TotalStake, + }, + CandidatePool, Config, Error, Event, Event as StakeEvent, InflationInfo, RewardRate, StakingInfo, STAKING_ID, +}; + +#[test] +fn should_select_collators_genesis_session() { + ExtBuilder::default() + .with_balances(vec![ + (1, 20), + (2, 20), + (3, 20), + (4, 20), + (5, 20), + (6, 20), + (7, 20), + (8, 20), + (9, 20), + (10, 20), + (11, 20), + ]) + .with_collators(vec![(1, 20), (2, 20)]) + .build() + .execute_with(|| { + assert_eq!( + StakePallet::new_session(0) + .expect("first session must return new collators") + .len(), + 2 + ); + assert_eq!( + StakePallet::new_session(1) + .expect("second session must return new collators") + .len(), + 2 + ); + }); +} + +#[test] +fn genesis() { + ExtBuilder::default() + .with_balances(vec![ + (1, 1000), + (2, 300), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 9), + (9, 4), + ]) + .with_collators(vec![(1, 500), (2, 200)]) + .with_delegators(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) + .build() + .execute_with(|| { + assert!(System::events().is_empty()); + + // Collators + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 700, + delegators: 400 + } + ); + assert_eq!( + vec![ + StakeOf:: { owner: 1, amount: 700 }, + StakeOf:: { owner: 2, amount: 400 } + ] + .try_into(), + Ok(StakePallet::top_candidates().into_bounded_vec()) + ); + assert_eq!(CandidatePool::::count(), 2); + + // 1 + assert_eq!(Balances::usable_balance(&1), 500); + assert_eq!(Balances::free_balance(&1), 1000); + assert!(StakePallet::is_active_candidate(&1).is_some()); + assert_eq!( + StakePallet::candidate_pool(&1), + Some( + Candidate::::MaxDelegatorsPerCollator> { + id: 1, + stake: 500, + delegators: OrderedSet::from_sorted_set( + vec![ + StakeOf:: { owner: 3, amount: 100 }, + StakeOf:: { owner: 4, amount: 100 } + ] + .try_into() + .unwrap() + ), + total: 700, + status: CandidateStatus::Active, + } + ) + ); + // 2 + assert_eq!(Balances::usable_balance(&2), 100); + assert_eq!(Balances::free_balance(&2), 300); + assert!(StakePallet::is_active_candidate(&2).is_some()); + assert_eq!( + StakePallet::candidate_pool(&2), + Some( + Candidate::::MaxDelegatorsPerCollator> { + id: 2, + stake: 200, + delegators: OrderedSet::from_sorted_set( + vec![ + StakeOf:: { owner: 5, amount: 100 }, + StakeOf:: { owner: 6, amount: 100 } + ] + .try_into() + .unwrap() + ), + total: 400, + status: CandidateStatus::Active, + } + ) + ); + // Delegators + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 700, + delegators: 400 + } + ); + for x in 3..7 { + assert!(StakePallet::is_delegator(&x)); + assert_eq!(Balances::usable_balance(&x), 0); + assert_eq!(Balances::free_balance(&x), 100); + } + // Uninvolved + for x in 7..10 { + assert!(!StakePallet::is_delegator(&x)); + } + assert_eq!(Balances::free_balance(&7), 100); + assert_eq!(Balances::usable_balance(&7), 100); + assert_eq!(Balances::free_balance(&8), 9); + assert_eq!(Balances::usable_balance(&8), 9); + assert_eq!(Balances::free_balance(&9), 4); + assert_eq!(Balances::usable_balance(&9), 4); + + // Safety first checks + assert_eq!( + StakePallet::max_selected_candidates(), + ::MinCollators::get() + ); + assert_eq!( + StakePallet::round(), + RoundInfo::new(0u32, 0u32.into(), ::DefaultBlocksPerRound::get()) + ); + }); + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + ]) + .with_collators(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) + .with_delegators(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) + .build() + .execute_with(|| { + assert!(System::events().is_empty()); + assert_eq!(CandidatePool::::count(), 5); + + // Collators + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 40, + delegators: 50 + } + ); + assert_eq!( + Ok(StakePallet::top_candidates().into_bounded_vec()), + vec![ + StakeOf:: { owner: 1, amount: 50 }, + StakeOf:: { owner: 2, amount: 40 }, + StakeOf:: { owner: 3, amount: 20 }, + StakeOf:: { owner: 4, amount: 20 }, + StakeOf:: { owner: 5, amount: 10 } + ] + .try_into() + ); + for x in 1..5 { + assert!(StakePallet::is_active_candidate(&x).is_some()); + assert_eq!(Balances::free_balance(&x), 100); + assert_eq!(Balances::usable_balance(&x), 80); + } + assert!(StakePallet::is_active_candidate(&5).is_some()); + assert_eq!(Balances::free_balance(&5), 100); + assert_eq!(Balances::usable_balance(&5), 90); + // Delegators + for x in 6..11 { + assert!(StakePallet::is_delegator(&x)); + assert_eq!(Balances::free_balance(&x), 100); + assert_eq!(Balances::usable_balance(&x), 90); + } + + // Safety first checks + assert_eq!( + StakePallet::max_selected_candidates(), + ::MinCollators::get() + ); + assert_eq!( + StakePallet::round(), + RoundInfo::new(0, 0, ::DefaultBlocksPerRound::get()) + ); + }); +} + +#[test] +fn join_collator_candidates() { + ExtBuilder::default() + .with_balances(vec![ + (1, 1000), + (2, 300), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 9), + (9, 4), + (10, 161_000_000 * DECIMALS), + ]) + .with_collators(vec![(1, 500), (2, 200)]) + .with_delegators(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) + .build() + .execute_with(|| { + assert_eq!(CandidatePool::::count(), 2); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 700, + delegators: 400 + } + ); + assert_noop!( + StakePallet::join_candidates(RuntimeOrigin::signed(1), 11u128,), + Error::::CandidateExists + ); + assert_noop!( + StakePallet::join_delegators(RuntimeOrigin::signed(1), 1, 11u128,), + Error::::CandidateExists + ); + assert_noop!( + StakePallet::join_candidates(RuntimeOrigin::signed(3), 11u128,), + Error::::DelegatorExists + ); + assert_noop!( + StakePallet::join_candidates(RuntimeOrigin::signed(7), 9u128,), + Error::::ValStakeBelowMin + ); + assert_noop!( + StakePallet::join_candidates(RuntimeOrigin::signed(8), 10u128,), + BalancesError::::InsufficientBalance + ); + + assert_eq!(CandidatePool::::count(), 2); + assert!(System::events().is_empty()); + + assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 5)); + assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(7), 10u128,)); + assert_eq!(last_event(), StakeEvent::JoinedCollatorCandidates(7, 10u128)); + + // MaxCollatorCandidateStake + assert_noop!( + StakePallet::join_candidates(RuntimeOrigin::signed(10), 161_000_000 * DECIMALS), + Error::::ValStakeAboveMax + ); + assert_ok!(StakePallet::join_candidates( + RuntimeOrigin::signed(10), + StakePallet::max_candidate_stake() + )); + assert_eq!(CandidatePool::::count(), 4); + + assert_eq!( + last_event(), + StakeEvent::JoinedCollatorCandidates(10, StakePallet::max_candidate_stake(),) + ); + }); +} + +#[test] +fn collator_exit_executes_after_delay() { + ExtBuilder::default() + .with_balances(vec![ + (1, 1000), + (2, 300), + (3, 110), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 9), + (9, 4), + (10, 10), + ]) + .with_collators(vec![(1, 500), (2, 200), (7, 100)]) + .with_delegators(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)]) + .build() + .execute_with(|| { + assert_eq!(CandidatePool::::count(), 3); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 700, + delegators: 400 + } + ); + assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 5)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 800, + delegators: 400 + } + ); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 7]); + roll_to(4, vec![]); + assert_noop!( + StakePallet::init_leave_candidates(RuntimeOrigin::signed(3)), + Error::::CandidateNotFound + ); + + roll_to(11, vec![]); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(2))); + // Still three, candidate didn't leave yet + assert_eq!(CandidatePool::::count(), 3); + assert_noop!( + StakePallet::join_delegators(RuntimeOrigin::signed(10), 2, 10), + Error::::CannotDelegateIfLeaving + ); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 7]); + assert_eq!(last_event(), StakeEvent::CollatorScheduledExit(2, 2, 4)); + let info = StakePallet::candidate_pool(&2).unwrap(); + assert_eq!(info.status, CandidateStatus::Leaving(4)); + + roll_to(21, vec![]); + assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(2), 2)); + assert_eq!(CandidatePool::::count(), 2); + + // we must exclude leaving collators from rewards while + // holding them retroactively accountable for previous faults + // (within the last T::StakeDuration blocks) + roll_to(25, vec![]); + let expected = vec![ + Event::MaxSelectedCandidatesSet(2, 5), + Event::NewRound(5, 1), + Event::NewRound(10, 2), + Event::LeftTopCandidates(2), + Event::CollatorScheduledExit(2, 2, 4), + Event::NewRound(15, 3), + Event::NewRound(20, 4), + Event::CandidateLeft(2, 400), + Event::NewRound(25, 5), + ]; + assert_eq!(events(), expected); + }); +} + +#[test] +fn collator_selection_chooses_top_candidates() { + ExtBuilder::default() + .with_balances(vec![ + (1, 1000), + (2, 1000), + (3, 1000), + (4, 1000), + (5, 1000), + (6, 1000), + (7, 33), + (8, 33), + (9, 33), + ]) + .with_collators(vec![(1, 100), (2, 90), (3, 80), (4, 70), (5, 60), (6, 50)]) + .build() + .execute_with(|| { + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2]); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 190, + delegators: 0 + } + ); + assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 5)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 400, + delegators: 0 + } + ); + roll_to(8, vec![]); + // should choose top MaxSelectedCandidates (5), in order + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3, 4, 5]); + let expected = vec![Event::MaxSelectedCandidatesSet(2, 5), Event::NewRound(5, 1)]; + assert_eq!(events(), expected); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(6))); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3, 4, 5],); + assert_eq!(last_event(), StakeEvent::CollatorScheduledExit(1, 6, 3)); + + roll_to(15, vec![]); + assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(6), 6)); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3, 4, 5]); + + roll_to(21, vec![]); + assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(6), 69u128)); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3, 4, 6]); + assert_eq!(last_event(), StakeEvent::JoinedCollatorCandidates(6, 69u128)); + + roll_to(27, vec![]); + // should choose top MaxSelectedCandidates (5), in order + let expected = vec![ + Event::MaxSelectedCandidatesSet(2, 5), + Event::NewRound(5, 1), + Event::LeftTopCandidates(6), + Event::CollatorScheduledExit(1, 6, 3), + // TotalCollatorStake is updated once candidate 6 left in `execute_delayed_collator_exits` + Event::NewRound(10, 2), + Event::NewRound(15, 3), + Event::CandidateLeft(6, 50), + Event::NewRound(20, 4), + // 5 had staked 60 which was exceeded by 69 of 6 + Event::EnteredTopCandidates(6), + Event::JoinedCollatorCandidates(6, 69), + Event::NewRound(25, 5), + ]; + assert_eq!(events(), expected); + }); +} + +#[test] +fn exit_queue_with_events() { + ExtBuilder::default() + .with_balances(vec![ + (1, 1000), + (2, 1000), + (3, 1000), + (4, 1000), + (5, 1000), + (6, 1000), + (7, 33), + (8, 33), + (9, 33), + ]) + .with_collators(vec![(1, 100), (2, 90), (3, 80), (4, 70), (5, 60), (6, 50)]) + .with_inflation(100, 15, 40, 10, BLOCKS_PER_ROUND) + .build() + .execute_with(|| { + assert_eq!(CandidatePool::::count(), 6); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2]); + assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 5)); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3, 4, 5]); + + roll_to(8, vec![]); + // should choose top MaxSelectedCandidates (5), in order + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3, 4, 5]); + let mut expected = vec![Event::MaxSelectedCandidatesSet(2, 5), Event::NewRound(5, 1)]; + assert_eq!(events(), expected); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(6))); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3, 4, 5]); + assert_eq!(last_event(), StakeEvent::CollatorScheduledExit(1, 6, 3)); + + roll_to(11, vec![]); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(5))); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3, 4]); + assert_eq!(last_event(), StakeEvent::CollatorScheduledExit(2, 5, 4)); + + assert_eq!(CandidatePool::::count(), 6, "No collators have left yet."); + roll_to(16, vec![]); + assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(6), 6)); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(4))); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3]); + assert_eq!(last_event(), StakeEvent::CollatorScheduledExit(3, 4, 5)); + assert_noop!( + StakePallet::init_leave_candidates(RuntimeOrigin::signed(4)), + Error::::AlreadyLeaving + ); + + assert_eq!(CandidatePool::::count(), 5, "Collator #5 left."); + roll_to(20, vec![]); + assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(5), 5)); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3]); + assert_eq!(CandidatePool::::count(), 4, "Two out of six collators left."); + + roll_to(26, vec![]); + assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(4), 4)); + assert_eq!(CandidatePool::::count(), 3, "Three out of six collators left."); + + roll_to(30, vec![]); + let mut new_events = vec![ + Event::LeftTopCandidates(6), + Event::CollatorScheduledExit(1, 6, 3), + Event::NewRound(10, 2), + Event::LeftTopCandidates(5), + Event::CollatorScheduledExit(2, 5, 4), + Event::NewRound(15, 3), + Event::CandidateLeft(6, 50), + Event::LeftTopCandidates(4), + Event::CollatorScheduledExit(3, 4, 5), + Event::NewRound(20, 4), + Event::CandidateLeft(5, 60), + Event::NewRound(25, 5), + Event::CandidateLeft(4, 70), + Event::NewRound(30, 6), + ]; + expected.append(&mut new_events); + assert_eq!(events(), expected); + }); +} + +#[test] +fn execute_leave_candidates_with_delay() { + ExtBuilder::default() + .with_balances(vec![ + (1, 1000), + (2, 1000), + (3, 1000), + (4, 1000), + (5, 1000), + (6, 1000), + (7, 1000), + (8, 1000), + (9, 1000), + (10, 1000), + (11, 1000), + (12, 1000), + (13, 1000), + (14, 1000), + ]) + .with_collators(vec![ + (1, 10), + (2, 20), + (3, 30), + (4, 40), + (5, 50), + (6, 60), + (7, 70), + (8, 80), + (9, 90), + (10, 100), + ]) + .with_delegators(vec![(11, 1, 110), (12, 1, 120), (13, 2, 130), (14, 2, 140)]) + .with_inflation(100, 15, 40, 10, BLOCKS_PER_ROUND) + .build() + .execute_with(|| { + assert_eq!(CandidatePool::::count(), 10); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 30, + delegators: 500 + } + ); + assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 5)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 300, + delegators: 500 + } + ); + + roll_to(5, vec![]); + // should choose top MaxSelectedCandidates (5), in order + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 1, 10, 9, 8]); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(10))); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(9))); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(1))); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(7))); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(6))); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(5))); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(8))); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(2))); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![4, 3]); + for owner in vec![1, 2, 5, 6, 7, 8, 9, 10].iter() { + assert!(StakePallet::candidate_pool(owner) + .unwrap() + .can_exit(1 + ::ExitQueueDelay::get())); + } + let total_stake = TotalStake { + collators: 70, + delegators: 0, + }; + assert_eq!(StakePallet::total_collator_stake(), total_stake); + assert_eq!( + StakePallet::candidate_pool(1), + Some( + Candidate::::MaxDelegatorsPerCollator> { + id: 1, + stake: 10, + delegators: OrderedSet::from( + vec![ + StakeOf:: { owner: 11, amount: 110 }, + StakeOf:: { owner: 12, amount: 120 } + ] + .try_into() + .unwrap() + ), + total: 240, + status: CandidateStatus::Leaving(3) + } + ) + ); + assert_eq!( + StakePallet::candidate_pool(2), + Some( + Candidate::::MaxDelegatorsPerCollator> { + id: 2, + stake: 20, + delegators: OrderedSet::from( + vec![ + StakeOf:: { owner: 13, amount: 130 }, + StakeOf:: { owner: 14, amount: 140 } + ] + .try_into() + .unwrap() + ), + total: 290, + status: CandidateStatus::Leaving(3) + } + ) + ); + for collator in 5u64..=10u64 { + assert_eq!( + StakePallet::candidate_pool(collator), + Some( + Candidate::::MaxDelegatorsPerCollator> { + id: collator, + stake: collator as u128 * 10u128, + delegators: OrderedSet::from(BoundedVec::default()), + total: collator as u128 * 10u128, + status: CandidateStatus::Leaving(3) + } + ) + ); + assert!(StakePallet::is_active_candidate(&collator).is_some()); + assert!(StakePallet::unstaking(collator).is_empty()); + } + assert_eq!( + StakePallet::delegator_state(11), + Some(Delegator:: { owner: 1, amount: 110 }) + ); + assert_eq!( + StakePallet::delegator_state(12), + Some(Delegator:: { owner: 1, amount: 120 }) + ); + assert_eq!( + StakePallet::delegator_state(13), + Some(Delegator:: { owner: 2, amount: 130 }) + ); + assert_eq!( + StakePallet::delegator_state(14), + Some(Delegator:: { owner: 2, amount: 140 }) + ); + for delegator in 11u64..=14u64 { + assert!(StakePallet::is_delegator(&delegator)); + assert!(StakePallet::unstaking(delegator).is_empty()); + } + + // exits cannot be executed yet but in the next round + roll_to(10, vec![]); + assert_eq!(StakePallet::total_collator_stake(), total_stake); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![4, 3]); + for owner in vec![1, 2, 5, 6, 7, 8, 9, 10].iter() { + assert!(StakePallet::candidate_pool(owner) + .unwrap() + .can_exit(1 + ::ExitQueueDelay::get())); + assert_noop!( + StakePallet::execute_leave_candidates(RuntimeOrigin::signed(*owner), *owner), + Error::::CannotLeaveYet + ); + } + assert_eq!(StakePallet::total_collator_stake(), total_stake); + assert_eq!( + StakePallet::candidate_pool(1), + Some( + Candidate::::MaxDelegatorsPerCollator> { + id: 1, + stake: 10, + delegators: OrderedSet::from( + vec![ + StakeOf:: { owner: 11, amount: 110 }, + StakeOf:: { owner: 12, amount: 120 } + ] + .try_into() + .unwrap() + ), + total: 240, + status: CandidateStatus::Leaving(3) + } + ) + ); + assert_eq!( + StakePallet::candidate_pool(2), + Some( + Candidate::::MaxDelegatorsPerCollator> { + id: 2, + stake: 20, + delegators: OrderedSet::from( + vec![ + StakeOf:: { owner: 13, amount: 130 }, + StakeOf:: { owner: 14, amount: 140 } + ] + .try_into() + .unwrap() + ), + total: 290, + status: CandidateStatus::Leaving(3) + } + ) + ); + for collator in 5u64..=10u64 { + assert_eq!( + StakePallet::candidate_pool(collator), + Some( + Candidate::::MaxDelegatorsPerCollator> { + id: collator, + stake: collator as u128 * 10u128, + delegators: OrderedSet::from(BoundedVec::default()), + total: collator as u128 * 10u128, + status: CandidateStatus::Leaving(3) + } + ) + ); + assert!(StakePallet::is_active_candidate(&collator).is_some()); + assert!(StakePallet::unstaking(collator).is_empty()); + } + assert_eq!( + StakePallet::delegator_state(11), + Some(Delegator:: { owner: 1, amount: 110 }) + ); + assert_eq!( + StakePallet::delegator_state(12), + Some(Delegator:: { owner: 1, amount: 120 }) + ); + assert_eq!( + StakePallet::delegator_state(13), + Some(Delegator:: { owner: 2, amount: 130 }) + ); + assert_eq!( + StakePallet::delegator_state(14), + Some(Delegator:: { owner: 2, amount: 140 }) + ); + for delegator in 11u64..=14u64 { + assert!(StakePallet::is_delegator(&delegator)); + assert!(StakePallet::unstaking(delegator).is_empty()); + } + + // first five exits are executed + roll_to(15, vec![]); + assert_eq!(StakePallet::total_collator_stake(), total_stake); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![4, 3]); + for collator in vec![1u64, 2u64, 5u64, 6u64, 7u64].iter() { + assert_ok!(StakePallet::execute_leave_candidates( + RuntimeOrigin::signed(*collator), + *collator + )); + assert!(StakePallet::candidate_pool(&collator).is_none()); + assert!(StakePallet::is_active_candidate(collator).is_none()); + assert_eq!(StakePallet::unstaking(collator).len(), 1); + } + assert_eq!(CandidatePool::::count(), 5, "Five collators left."); + + assert_eq!(StakePallet::total_collator_stake(), total_stake); + for delegator in 11u64..=14u64 { + assert!(!StakePallet::is_delegator(&delegator)); + assert_eq!(StakePallet::unstaking(delegator).len(), 1); + } + + // last 3 exits are executed + roll_to(20, vec![]); + for collator in 8u64..=10u64 { + assert_ok!(StakePallet::execute_leave_candidates( + RuntimeOrigin::signed(collator), + collator + )); + assert!(StakePallet::candidate_pool(&collator).is_none()); + assert!(StakePallet::is_active_candidate(&collator).is_none()); + assert_eq!(StakePallet::unstaking(collator).len(), 1); + } + assert_eq!(CandidatePool::::count(), 2, "3 collators left."); + }); +} + +// FIXME: Re-enable or potentially remove entirely +#[test] +fn multiple_delegations() { + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + (11, 100), + (12, 100), + // new + (13, 100), + (14, 100), + (15, 100), + (16, 100), + (17, 100), + (18, 100), + (99, 1), + ]) + .with_collators(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) + .with_delegators(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) + .set_blocks_per_round(5) + .build() + .execute_with(|| { + assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 5)); + roll_to( + 8, + vec![Some(1), Some(2), Some(3), Some(4), Some(5), Some(1), Some(2), Some(3)], + ); + // chooses top MaxSelectedCandidates (5), in order + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 3, 4, 5]); + let mut expected = vec![Event::MaxSelectedCandidatesSet(2, 5), Event::NewRound(5, 1)]; + assert_eq!(events(), expected); + assert_noop!( + StakePallet::join_delegators(RuntimeOrigin::signed(13), 2, 2), + Error::::DelegationBelowMin, + ); + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(13), 2, 10)); + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(14), 4, 10)); + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(15), 3, 10)); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 4, 3, 5]); + assert_noop!( + StakePallet::join_delegators(RuntimeOrigin::signed(6), 5, 10), + Error::::AlreadyDelegating, + ); + + roll_to( + 16, + vec![Some(1), Some(2), Some(3), Some(4), Some(5), Some(1), Some(2), Some(3)], + ); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2, 4, 3, 5]); + let mut new = vec![ + Event::Delegation(13, 10, 2, 50), + Event::Delegation(14, 10, 4, 30), + Event::Delegation(15, 10, 3, 30), + Event::NewRound(10, 2), + Event::NewRound(15, 3), + ]; + expected.append(&mut new); + assert_eq!(events(), expected); + + roll_to(21, vec![Some(1), Some(2), Some(3), Some(4), Some(5)]); + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(16), 2, 80)); + assert_noop!( + StakePallet::join_delegators(RuntimeOrigin::signed(99), 3, 11), + BalancesError::::InsufficientBalance + ); + assert_noop!( + StakePallet::join_delegators(RuntimeOrigin::signed(17), 2, 10), + Error::::TooManyDelegators + ); + // kick 13 by staking 1 more (11 > 10) + assert!(StakePallet::unstaking(13).is_empty()); + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(17), 2, 11)); + assert!(StakePallet::delegator_state(13).is_none()); + assert_eq!(StakePallet::unstaking(13).get(&23), Some(&10u128)); + // kick 9 by staking 1 more (11 > 10) + assert!(StakePallet::unstaking(9).is_empty()); + assert!(StakePallet::rewards(9).is_zero()); + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(11), 2, 11)); + // 11 should be initiated with the same rewarded counter as the authored counter + // by their collator 2 + assert_eq!(StakePallet::blocks_rewarded(2), StakePallet::blocks_authored(11)); + + assert!(StakePallet::delegator_state(9).is_none()); + assert_eq!(StakePallet::unstaking(9).get(&23), Some(&10u128)); + assert!(!StakePallet::candidate_pool(2) + .unwrap() + .delegators + .contains(&StakeOf:: { owner: 9, amount: 10 })); + + roll_to(26, vec![Some(1), Some(2), Some(3), Some(4), Some(5)]); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 1, 4, 3, 5]); + let mut new2 = vec![ + Event::NewRound(20, 4), + Event::Delegation(16, 80, 2, 130), + Event::DelegationReplaced(17, 11, 13, 10, 2, 131), + Event::Delegation(17, 11, 2, 131), + Event::DelegationReplaced(11, 11, 9, 10, 2, 132), + Event::Delegation(11, 11, 2, 132), + Event::NewRound(25, 5), + ]; + expected.append(&mut new2); + assert_eq!(events(), expected); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(2))); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 4, 3, 5]); + assert_eq!(last_event(), StakeEvent::CollatorScheduledExit(5, 2, 7)); + + roll_to(31, vec![Some(1), Some(2), Some(3), Some(4), Some(5)]); + let mut new3 = vec![ + Event::LeftTopCandidates(2), + Event::CollatorScheduledExit(5, 2, 7), + Event::NewRound(30, 6), + ]; + expected.append(&mut new3); + assert_eq!(events(), expected); + + // test join_delegator errors + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(18), 1, 10)); + assert_noop!( + StakePallet::join_delegators(RuntimeOrigin::signed(12), 1, 10), + Error::::TooManyDelegators + ); + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(12), 1, 11)); + + // verify that delegations are removed after collator leaves, not before + assert!(StakePallet::candidate_pool(2) + .unwrap() + .delegators + .contains(&StakeOf:: { owner: 8, amount: 10 })); + assert!(StakePallet::candidate_pool(2) + .unwrap() + .delegators + .contains(&StakeOf:: { owner: 17, amount: 11 })); + assert_eq!(StakePallet::delegator_state(8).unwrap().amount, 10); + assert_eq!(StakePallet::delegator_state(17).unwrap().amount, 11); + assert_eq!(Balances::usable_balance(&8), 90); + assert_eq!(Balances::usable_balance(&17), 89); + assert_eq!(Balances::free_balance(&8), 100); + assert_eq!(Balances::free_balance(&17), 100); + + roll_to(35, vec![Some(1), Some(2), Some(3), Some(4)]); + assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(2), 2)); + let mut unbonding_8: BoundedBTreeMap, ::MaxUnstakeRequests> = + BoundedBTreeMap::new(); + assert_ok!(unbonding_8.try_insert(35u64 + ::StakeDuration::get() as u64, 10)); + assert_eq!(StakePallet::unstaking(8), unbonding_8); + let mut unbonding_17: BoundedBTreeMap, ::MaxUnstakeRequests> = + BoundedBTreeMap::new(); + assert_ok!(unbonding_17.try_insert(35u64 + ::StakeDuration::get() as u64, 11)); + assert_eq!(StakePallet::unstaking(17), unbonding_17); + + roll_to(37, vec![Some(1), Some(2)]); + assert!(StakePallet::delegator_state(8).is_none()); + assert!(StakePallet::delegator_state(17).is_none()); + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(8), 8)); + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(17), 17)); + assert_noop!( + StakePallet::unlock_unstaked(RuntimeOrigin::signed(12), 12), + Error::::UnstakingIsEmpty + ); + assert_eq!(Balances::usable_balance(&17), 100); + assert_eq!(Balances::usable_balance(&8), 100); + assert_eq!(Balances::free_balance(&17), 100); + assert_eq!(Balances::free_balance(&8), 100); + }); +} + +#[test] +fn should_update_total_stake() { + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + (11, 161_000_000 * DECIMALS), + ]) + .with_collators(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) + .with_delegators(vec![(7, 1, 10), (8, 2, 10), (9, 2, 10)]) + .set_blocks_per_round(5) + .build() + .execute_with(|| { + let mut old_stake = StakePallet::total_collator_stake(); + assert_eq!( + old_stake, + TotalStake { + collators: 40, + delegators: 30 + } + ); + assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 50)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: old_stake.collators + 50, + ..old_stake + } + ); + + old_stake = StakePallet::total_collator_stake(); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 50)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: old_stake.collators - 50, + ..old_stake + } + ); + + old_stake = StakePallet::total_collator_stake(); + assert_ok!(StakePallet::delegator_stake_more(RuntimeOrigin::signed(7), 50)); + assert_noop!( + StakePallet::delegator_stake_more(RuntimeOrigin::signed(7), 0), + Error::::ValStakeZero + ); + assert_noop!( + StakePallet::delegator_stake_less(RuntimeOrigin::signed(7), 0), + Error::::ValStakeZero + ); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + delegators: old_stake.delegators + 50, + ..old_stake + } + ); + + old_stake = StakePallet::total_collator_stake(); + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(7), 50)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + delegators: old_stake.delegators - 50, + ..old_stake + } + ); + + old_stake = StakePallet::total_collator_stake(); + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(11), 1, 200)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + delegators: old_stake.delegators + 200, + ..old_stake + } + ); + + old_stake = StakePallet::total_collator_stake(); + assert_eq!(StakePallet::delegator_state(11).unwrap().amount, 200); + assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(11))); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + delegators: old_stake.delegators - 200, + ..old_stake + } + ); + + let old_stake = StakePallet::total_collator_stake(); + assert_eq!(StakePallet::delegator_state(8).unwrap().amount, 10); + assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(8))); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + delegators: old_stake.delegators - 10, + ..old_stake + } + ); + + // should immediately affect total stake because collator can't be chosen in + // active set from now on, thus delegated stake is reduced + let old_stake = StakePallet::total_collator_stake(); + assert_eq!(StakePallet::candidate_pool(2).unwrap().total, 30); + assert_eq!(StakePallet::candidate_pool(2).unwrap().stake, 20); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 1]); + assert_eq!( + StakePallet::candidate_pool(2).unwrap().stake, + StakePallet::candidate_pool(3).unwrap().stake + ); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(2))); + let old_stake = TotalStake { + delegators: old_stake.delegators - 10, + // total active collator stake is unchanged because number of selected candidates is 2 and 2's + // replacement has the same self stake as 2 + collators: old_stake.collators, + }; + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 3]); + assert_eq!(StakePallet::total_collator_stake(), old_stake); + + // shouldn't change total stake when 2 leaves + roll_to(10, vec![]); + assert_eq!(StakePallet::total_collator_stake(), old_stake); + assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(2), 2)); + assert_eq!(StakePallet::total_collator_stake(), old_stake); + }) +} + +#[test] +fn collators_bond() { + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + (11, 161_000_000 * DECIMALS), + ]) + .with_collators(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) + .with_delegators(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)]) + .set_blocks_per_round(5) + .build() + .execute_with(|| { + roll_to(4, vec![]); + assert_noop!( + StakePallet::candidate_stake_more(RuntimeOrigin::signed(6), 50), + Error::::CandidateNotFound + ); + assert_noop!( + StakePallet::candidate_stake_less(RuntimeOrigin::signed(6), 50), + Error::::CandidateNotFound + ); + assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 50)); + assert_noop!( + StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 40), + BalancesError::::InsufficientBalance + ); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(1))); + assert!(StakePallet::candidate_pool(1) + .unwrap() + .can_exit(::ExitQueueDelay::get())); + + assert_noop!( + StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 30), + Error::::CannotStakeIfLeaving + ); + assert_noop!( + StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10), + Error::::CannotStakeIfLeaving + ); + + roll_to(30, vec![]); + assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert_noop!( + StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 40), + Error::::CandidateNotFound + ); + assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(2), 80)); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(2), 90)); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(3), 10)); + assert_noop!( + StakePallet::candidate_stake_less(RuntimeOrigin::signed(2), 11), + Error::::Underflow + ); + assert_noop!( + StakePallet::candidate_stake_less(RuntimeOrigin::signed(2), 1), + Error::::ValStakeBelowMin + ); + assert_noop!( + StakePallet::candidate_stake_less(RuntimeOrigin::signed(3), 1), + Error::::ValStakeBelowMin + ); + assert_noop!( + StakePallet::candidate_stake_less(RuntimeOrigin::signed(4), 11), + Error::::ValStakeBelowMin + ); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(4), 10)); + + // MaxCollatorCandidateStake + assert_ok!(StakePallet::join_candidates( + RuntimeOrigin::signed(11), + StakePallet::max_candidate_stake() + )); + assert_noop!( + StakePallet::candidate_stake_more(RuntimeOrigin::signed(11), 1u128), + Error::::ValStakeAboveMax, + ); + }); +} + +#[test] +fn delegators_bond() { + ExtBuilder::default() + .with_balances(vec![ + (1, 100), + (2, 100), + (3, 100), + (4, 100), + (5, 100), + (6, 100), + (7, 100), + (8, 100), + (9, 100), + (10, 100), + ]) + .with_collators(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)]) + .with_delegators(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10)]) + .set_blocks_per_round(5) + .build() + .execute_with(|| { + roll_to(4, vec![]); + assert_noop!( + StakePallet::join_delegators(RuntimeOrigin::signed(6), 2, 50), + Error::::AlreadyDelegating + ); + assert_noop!( + StakePallet::delegator_stake_more(RuntimeOrigin::signed(1), 50), + Error::::DelegatorNotFound + ); + assert_noop!( + StakePallet::delegator_stake_less(RuntimeOrigin::signed(1), 50), + Error::::DelegatorNotFound + ); + assert_noop!( + StakePallet::delegator_stake_less(RuntimeOrigin::signed(6), 11), + Error::::Underflow + ); + assert_noop!( + StakePallet::delegator_stake_less(RuntimeOrigin::signed(6), 8), + Error::::DelegationBelowMin + ); + assert_ok!(StakePallet::delegator_stake_more(RuntimeOrigin::signed(6), 10)); + assert_noop!( + StakePallet::delegator_stake_more(RuntimeOrigin::signed(6), 81), + BalancesError::::InsufficientBalance + ); + assert_noop!( + StakePallet::join_delegators(RuntimeOrigin::signed(10), 1, 4), + Error::::DelegationBelowMin + ); + + roll_to(9, vec![]); + assert_eq!(Balances::usable_balance(&6), 80); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(1))); + assert!(StakePallet::candidate_pool(1) + .unwrap() + .can_exit(1 + ::ExitQueueDelay::get())); + + roll_to(31, vec![]); + assert!(StakePallet::is_delegator(&6)); + assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(1), 1)); + assert!(!StakePallet::is_delegator(&6)); + assert_eq!(Balances::usable_balance(&6), 80); + assert_eq!(Balances::free_balance(&6), 100); + }); +} + +#[test] +fn should_leave_delegators() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100)]) + .with_collators(vec![(1, 100)]) + .with_delegators(vec![(2, 1, 100)]) + .build() + .execute_with(|| { + assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); + assert!(StakePallet::delegator_state(2).is_none()); + assert!(!StakePallet::candidate_pool(1) + .unwrap() + .delegators + .contains(&StakeOf:: { owner: 2, amount: 100 })); + assert_noop!( + StakePallet::leave_delegators(RuntimeOrigin::signed(2)), + Error::::DelegatorNotFound + ); + assert_noop!( + StakePallet::leave_delegators(RuntimeOrigin::signed(1)), + Error::::DelegatorNotFound + ); + }); +} + +#[test] +fn round_transitions() { + let col_max = 10; + let col_rewards = 15; + let d_max = 40; + let d_rewards = 10; + let inflation = InflationInfo::new( + ::BLOCKS_PER_YEAR, + Perquintill::from_percent(col_max), + Perquintill::from_percent(col_rewards), + Perquintill::from_percent(d_max), + Perquintill::from_percent(d_rewards), + ); + + // round_immediately_jumps_if_current_duration_exceeds_new_blocks_per_round + // change from 5 bpr to 3 in block 5 -> 8 should be new round + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (6, 100)]) + .with_collators(vec![(1, 20)]) + .with_delegators(vec![(2, 1, 10), (3, 1, 10)]) + .with_inflation(col_max, col_rewards, d_max, d_rewards, 5) + .build() + .execute_with(|| { + assert_eq!(inflation, StakePallet::inflation_config()); + roll_to(5, vec![]); + let init = vec![Event::NewRound(5, 1)]; + assert_eq!(events(), init); + assert_ok!(StakePallet::set_blocks_per_round(RuntimeOrigin::root(), 3)); + assert_noop!( + StakePallet::set_blocks_per_round(RuntimeOrigin::root(), 1), + Error::::CannotSetBelowMin + ); + assert_eq!(last_event(), StakeEvent::BlocksPerRoundSet(1, 5, 5, 3)); + + // inflation config should be untouched after per_block update + assert_eq!(inflation, StakePallet::inflation_config()); + + // last round startet at 5 but we are already at 9, so we expect 9 to be the new + // round + roll_to(8, vec![]); + assert_eq!(last_event(), StakeEvent::NewRound(8, 2)) + }); + + // if duration of current round is less than new bpr, round waits until new bpr + // passes + // change from 5 bpr to 3 in block 6 -> 8 should be new round + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (6, 100)]) + .with_collators(vec![(1, 20)]) + .with_delegators(vec![(2, 1, 10), (3, 1, 10)]) + .with_inflation(col_max, col_rewards, d_max, d_rewards, 5) + .build() + .execute_with(|| { + assert_eq!(inflation, StakePallet::inflation_config()); + // Default round every 5 blocks, but MinBlocksPerRound is 3 and we set it to min + // 3 blocks + roll_to(6, vec![]); + // chooses top MaxSelectedCandidates (5), in order + let init = vec![Event::NewRound(5, 1)]; + assert_eq!(events(), init); + assert_ok!(StakePallet::set_blocks_per_round(RuntimeOrigin::root(), 3)); + assert_eq!(last_event(), StakeEvent::BlocksPerRoundSet(1, 5, 5, 3)); + + // inflation config should be untouched after per_block update + assert_eq!(inflation, StakePallet::inflation_config()); + + // there should not be a new event + roll_to(7, vec![]); + assert_eq!(last_event(), StakeEvent::BlocksPerRoundSet(1, 5, 5, 3)); + + roll_to(8, vec![]); + assert_eq!(last_event(), StakeEvent::NewRound(8, 2)) + }); + + // round_immediately_jumps_if_current_duration_exceeds_new_blocks_per_round + // change from 5 bpr (blocks_per_round) to 3 in block 7 -> 8 should be new round + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (6, 100)]) + .with_collators(vec![(1, 20)]) + .with_delegators(vec![(2, 1, 10), (3, 1, 10)]) + .with_inflation(col_max, col_rewards, d_max, d_rewards, 5) + .build() + .execute_with(|| { + // Default round every 5 blocks, but MinBlocksPerRound is 3 and we set it to min + // 3 blocks + assert_eq!(inflation, StakePallet::inflation_config()); + roll_to(7, vec![]); + // chooses top MaxSelectedCandidates (5), in order + let init = vec![Event::NewRound(5, 1)]; + assert_eq!(events(), init); + assert_ok!(StakePallet::set_blocks_per_round(RuntimeOrigin::root(), 3)); + + // inflation config should be untouched after per_block update + assert_eq!(inflation, StakePallet::inflation_config()); + + assert_eq!( + StakePallet::inflation_config(), + InflationInfo::new( + ::BLOCKS_PER_YEAR, + Perquintill::from_percent(col_max), + Perquintill::from_percent(col_rewards), + Perquintill::from_percent(d_max), + Perquintill::from_percent(d_rewards) + ) + ); + assert_eq!(last_event(), StakeEvent::BlocksPerRoundSet(1, 5, 5, 3)); + roll_to(8, vec![]); + + // last round startet at 5, so we expect 8 to be the new round + assert_eq!(last_event(), StakeEvent::NewRound(8, 2)) + }); +} + +#[test] +fn coinbase_rewards_few_blocks_detailed_check() { + ExtBuilder::default() + .with_balances(vec![ + (1, 40_000_000 * DECIMALS), + (2, 40_000_000 * DECIMALS), + (3, 40_000_000 * DECIMALS), + (4, 20_000_000 * DECIMALS), + (5, 20_000_000 * DECIMALS), + ]) + .with_collators(vec![(1, 8_000_000 * DECIMALS), (2, 8_000_000 * DECIMALS)]) + .with_delegators(vec![ + (3, 1, 32_000_000 * DECIMALS), + (4, 1, 16_000_000 * DECIMALS), + (5, 2, 16_000_000 * DECIMALS), + ]) + .with_inflation(10, 15, 40, 15, 5) + .build() + .execute_with(|| { + let inflation = StakePallet::inflation_config(); + let total_issuance = ::Currency::total_issuance(); + assert_eq!(total_issuance, 160_000_000 * DECIMALS); + + // compute rewards + let c_staking_rate = Perquintill::from_rational(16_000_000 * DECIMALS, total_issuance); + let c_rewards: BalanceOf = + inflation + .collator + .compute_reward::(16_000_000 * DECIMALS, c_staking_rate, 1u128); + let d_staking_rate = Perquintill::from_rational(64_000_000 * DECIMALS, total_issuance); + let d_rewards: BalanceOf = + inflation + .delegator + .compute_reward::(64_000_000 * DECIMALS, d_staking_rate, 2u128); + + // set 1 to be author for blocks 1-3, then 2 for blocks 4-5 + let authors: Vec> = + vec![None, Some(1u64), Some(1u64), Some(1u64), Some(2u64), Some(2u64)]; + // let d_rewards: Balance = 3 * 2469135802453333 / 2; + let user_1 = Balances::usable_balance(&1); + let user_2 = Balances::usable_balance(&2); + let user_3 = Balances::usable_balance(&3); + let user_4 = Balances::usable_balance(&4); + let user_5 = Balances::usable_balance(&5); + + assert_eq!(Balances::usable_balance(&1), user_1); + assert_eq!(Balances::usable_balance(&2), user_2); + assert_eq!(Balances::usable_balance(&3), user_3); + assert_eq!(Balances::usable_balance(&4), user_4); + assert_eq!(Balances::usable_balance(&5), user_5); + + // 1 is block author for 1st block + roll_to_claim_rewards(2, authors.clone()); + assert_eq!(Balances::usable_balance(&1), user_1 + c_rewards); + assert_eq!(Balances::usable_balance(&2), user_2); + assert_eq!(Balances::usable_balance(&3), user_3 + d_rewards / 2); + assert_eq!(Balances::usable_balance(&4), user_4 + d_rewards / 4); + assert_eq!(Balances::usable_balance(&5), user_5); + + // 1 is block author for 2nd block + roll_to_claim_rewards(3, authors.clone()); + assert_eq!(Balances::usable_balance(&1), user_1 + 2 * c_rewards); + assert_eq!(Balances::usable_balance(&2), user_2); + assert_eq!(Balances::usable_balance(&3), user_3 + d_rewards); + assert_eq!(Balances::usable_balance(&4), user_4 + d_rewards / 2); + assert_eq!(Balances::usable_balance(&5), user_5); + + // 1 is block author for 3rd block + roll_to_claim_rewards(4, authors.clone()); + assert_eq!(Balances::usable_balance(&1), user_1 + 3 * c_rewards); + assert_eq!(Balances::usable_balance(&2), user_2); + assert_eq!(Balances::usable_balance(&3), user_3 + d_rewards / 2 * 3); + assert_eq!(Balances::usable_balance(&4), user_4 + d_rewards / 4 * 3); + assert_eq!(Balances::usable_balance(&5), user_5); + + // 2 is block author for 4th block + roll_to_claim_rewards(5, authors.clone()); + assert_eq!(Balances::usable_balance(&1), user_1 + 3 * c_rewards); + assert_eq!(Balances::usable_balance(&2), user_2 + c_rewards); + assert_eq!(Balances::usable_balance(&3), user_3 + d_rewards / 2 * 3); + assert_eq!(Balances::usable_balance(&4), user_4 + d_rewards / 4 * 3); + assert_eq!(Balances::usable_balance(&5), user_5 + d_rewards / 4); + assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(5))); + + // 2 is block author for 5th block + roll_to_claim_rewards(6, authors); + assert_eq!(Balances::usable_balance(&1), user_1 + 3 * c_rewards); + assert_eq!(Balances::usable_balance(&2), user_2 + 2 * c_rewards); + assert_eq!(Balances::usable_balance(&3), user_3 + d_rewards / 2 * 3); + assert_eq!(Balances::usable_balance(&4), user_4 + d_rewards / 4 * 3); + // should not receive rewards due to revoked delegation + assert_eq!(Balances::usable_balance(&5), user_5 + d_rewards / 4); + }); +} + +#[test] +fn delegator_should_not_receive_rewards_after_revoking() { + // test edge case of 1 delegator + ExtBuilder::default() + .with_balances(vec![(1, 10_000_000 * DECIMALS), (2, 10_000_000 * DECIMALS)]) + .with_collators(vec![(1, 10_000_000 * DECIMALS)]) + .with_delegators(vec![(2, 1, 10_000_000 * DECIMALS)]) + .with_inflation(10, 15, 40, 15, 5) + .build() + .execute_with(|| { + assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); + let authors: Vec> = (1u64..100u64).map(|_| Some(1u64)).collect(); + assert_eq!(Balances::usable_balance(&1), Balance::zero()); + assert_eq!(Balances::usable_balance(&2), Balance::zero()); + roll_to_claim_rewards(100, authors); + assert!(Balances::usable_balance(&1) > Balance::zero()); + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); + assert_eq!(Balances::usable_balance(&2), 10_000_000 * DECIMALS); + }); + + ExtBuilder::default() + .with_balances(vec![ + (1, 10_000_000 * DECIMALS), + (2, 10_000_000 * DECIMALS), + (3, 10_000_000 * DECIMALS), + ]) + .with_collators(vec![(1, 10_000_000 * DECIMALS)]) + .with_delegators(vec![(2, 1, 10_000_000 * DECIMALS), (3, 1, 10_000_000 * DECIMALS)]) + .with_inflation(10, 15, 40, 15, 5) + .build() + .execute_with(|| { + assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(3))); + let authors: Vec> = (1u64..100u64).map(|_| Some(1u64)).collect(); + assert_eq!(Balances::usable_balance(&1), Balance::zero()); + assert_eq!(Balances::usable_balance(&2), Balance::zero()); + assert_eq!(Balances::usable_balance(&3), Balance::zero()); + roll_to_claim_rewards(100, authors); + assert!(Balances::usable_balance(&1) > Balance::zero()); + assert!(Balances::usable_balance(&2) > Balance::zero()); + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(3), 3)); + assert_eq!(Balances::usable_balance(&3), 10_000_000 * DECIMALS); + }); +} +#[test] +fn coinbase_rewards_many_blocks_simple_check() { + let num_of_years: Perquintill = Perquintill::from_perthousand(2); + ExtBuilder::default() + .with_balances(vec![ + (1, 40_000_000 * DECIMALS), + (2, 40_000_000 * DECIMALS), + (3, 40_000_000 * DECIMALS), + (4, 20_000_000 * DECIMALS), + (5, 20_000_000 * DECIMALS), + ]) + .with_collators(vec![(1, 8_000_000 * DECIMALS), (2, 8_000_000 * DECIMALS)]) + .with_delegators(vec![ + (3, 1, 32_000_000 * DECIMALS), + (4, 1, 16_000_000 * DECIMALS), + (5, 2, 16_000_000 * DECIMALS), + ]) + .with_inflation(10, 15, 40, 15, 5) + .build() + .execute_with(|| { + let inflation = StakePallet::inflation_config(); + let total_issuance = ::Currency::total_issuance(); + assert_eq!(total_issuance, 160_000_000 * DECIMALS); + let end_block: BlockNumber = num_of_years * Test::BLOCKS_PER_YEAR as BlockNumber; + // set round robin authoring + let authors: Vec> = (0u64..=end_block).map(|i| Some(i % 2 + 1)).collect(); + roll_to_claim_rewards(end_block, authors); + + let rewards_1 = Balances::free_balance(&1).saturating_sub(40_000_000 * DECIMALS); + let rewards_2 = Balances::free_balance(&2).saturating_sub(40_000_000 * DECIMALS); + let rewards_3 = Balances::free_balance(&3).saturating_sub(40_000_000 * DECIMALS); + let rewards_4 = Balances::free_balance(&4).saturating_sub(20_000_000 * DECIMALS); + let rewards_5 = Balances::free_balance(&5).saturating_sub(20_000_000 * DECIMALS); + let expected_collator_rewards = + num_of_years * inflation.collator.reward_rate.annual * 16_000_000 * DECIMALS; + let expected_delegator_rewards = + num_of_years * inflation.delegator.reward_rate.annual * 64_000_000 * DECIMALS; + + // 1200000000000000000000 + // 2399074074058720000 + + // collator rewards should be about the same + assert!(almost_equal(rewards_1, rewards_2, Perbill::from_perthousand(1))); + assert!( + almost_equal( + rewards_1, + num_of_years * inflation.collator.reward_rate.annual * 8_000_000 * DECIMALS, + Perbill::from_perthousand(1) + ), + "left {:?}, right {:?}", + rewards_1, + inflation.collator.reward_rate.annual * 8_000_000 * DECIMALS, + ); + + // delegator rewards should be about the same + assert!( + almost_equal(rewards_3, rewards_4 + rewards_5, Perbill::from_perthousand(1)), + "left {:?}, right {:?}", + rewards_3, + rewards_4 + rewards_5 + ); + assert!(almost_equal( + rewards_3, + num_of_years * inflation.delegator.reward_rate.annual * 32_000_000 * DECIMALS, + Perbill::from_perthousand(1) + )); + + // check rewards in total + assert!( + almost_equal( + rewards_1 + rewards_2, + expected_collator_rewards, + Perbill::from_perthousand(1), + ), + "left {:?}, right {:?}", + rewards_1 + rewards_2, + expected_collator_rewards, + ); + assert!( + almost_equal( + rewards_3 + rewards_4 + rewards_5, + expected_delegator_rewards, + Perbill::from_perthousand(1), + ), + "left {:?}, right {:?}", + rewards_3 + rewards_4 + rewards_5, + expected_delegator_rewards, + ); + + // old issuance + rewards should equal new issuance + assert!( + almost_equal( + total_issuance + expected_collator_rewards + expected_delegator_rewards, + ::Currency::total_issuance(), + Perbill::from_perthousand(1), + ), + "left {:?}, right {:?}", + total_issuance + expected_collator_rewards + expected_delegator_rewards, + ::Currency::total_issuance(), + ); + }); +} + +// Could only occur if we increase MinDelegatorStakeOf::via runtime +// upgrade and don't migrate delegators which fall below minimum +#[test] +fn should_not_reward_delegators_below_min_stake() { + ExtBuilder::default() + .with_balances(vec![(1, 10 * DECIMALS), (2, 10 * DECIMALS), (3, 10 * DECIMALS), (4, 5)]) + .with_collators(vec![(1, 10 * DECIMALS), (2, 10 * DECIMALS)]) + .with_delegators(vec![(3, 2, 10 * DECIMALS)]) + .with_inflation(10, 15, 40, 15, 5) + .build() + .execute_with(|| { + // impossible but lets assume it happened + let mut state = StakePallet::candidate_pool(&1).expect("CollatorState cannot be missing"); + let delegator_stake_below_min = ::MinDelegatorStake::get() - 1; + state.stake += delegator_stake_below_min; + state.total += delegator_stake_below_min; + let impossible_bond = StakeOf:: { + owner: 4u64, + amount: delegator_stake_below_min, + }; + assert_eq!(state.delegators.try_insert(impossible_bond), Ok(true)); + >::insert(1u64, state); + + let authors: Vec> = vec![Some(1u64), Some(1u64), Some(1u64), Some(1u64)]; + assert_eq!(Balances::usable_balance(&1), Balance::zero()); + assert_eq!(Balances::usable_balance(&2), Balance::zero()); + assert_eq!(Balances::usable_balance(&3), Balance::zero()); + assert_eq!(Balances::usable_balance(&4), 5); + + // should only reward 1 + roll_to_claim_rewards(4, authors); + assert!(Balances::usable_balance(&1) > Balance::zero()); + assert_eq!(Balances::usable_balance(&4), 5); + assert_eq!(Balances::usable_balance(&2), Balance::zero()); + assert_eq!(Balances::usable_balance(&3), Balance::zero()); + }); +} + +#[test] +#[should_panic] +fn should_deny_low_delegator_stake() { + ExtBuilder::default() + .with_balances(vec![(1, 10 * DECIMALS), (2, 10 * DECIMALS), (3, 10 * DECIMALS), (4, 1)]) + .with_collators(vec![(1, 10 * DECIMALS), (2, 10 * DECIMALS)]) + .with_delegators(vec![(4, 2, 1)]) + .build() + .execute_with(|| {}); +} + +#[test] +#[should_panic] +fn should_deny_low_collator_stake() { + ExtBuilder::default() + .with_balances(vec![(1, 10 * DECIMALS), (2, 5)]) + .with_collators(vec![(1, 10 * DECIMALS), (2, 5)]) + .build() + .execute_with(|| {}); +} + +#[test] +#[should_panic] +fn should_deny_duplicate_collators() { + ExtBuilder::default() + .with_balances(vec![(1, 10 * DECIMALS)]) + .with_collators(vec![(1, 10 * DECIMALS), (1, 10 * DECIMALS)]) + .build() + .execute_with(|| {}); +} + +#[test] +fn reach_max_top_candidates() { + ExtBuilder::default() + .with_balances(vec![ + (1, 11), + (2, 20), + (3, 11), + (4, 11), + (5, 11), + (6, 11), + (7, 11), + (8, 11), + (9, 11), + (10, 11), + (11, 11), + (12, 12), + (13, 13), + ]) + .with_collators(vec![ + (1, 10), + (2, 20), + (3, 10), + (4, 10), + (5, 10), + (6, 10), + (7, 10), + (8, 10), + (9, 10), + (10, 10), + ]) + .build() + .execute_with(|| { + assert_eq!( + StakePallet::top_candidates().len().saturated_into::(), + ::MaxTopCandidates::get() + ); + // should not be possible to join candidate pool, even with more stake + assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(11), 11)); + assert_eq!( + StakePallet::top_candidates() + .into_iter() + .map(|s| s.owner) + .collect::>(), + vec![2, 11, 1, 3, 4, 5, 6, 7, 8, 9] + ); + // last come, last one in the list + assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(12), 11)); + assert_eq!( + StakePallet::top_candidates() + .into_iter() + .map(|s| s.owner) + .collect::>(), + vec![2, 11, 12, 1, 3, 4, 5, 6, 7, 8] + ); + assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 1)); + assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(3), 1)); + assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(4), 1)); + assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(5), 1)); + assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(6), 1)); + assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(7), 1)); + assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(8), 1)); + assert_eq!( + StakePallet::top_candidates() + .into_iter() + .map(|s| s.owner) + .collect::>(), + vec![2, 11, 12, 1, 3, 4, 5, 6, 7, 8] + ); + }); +} + +#[test] +fn should_estimate_current_session_progress() { + ExtBuilder::default() + .set_blocks_per_round(100) + .with_balances(vec![ + (1, 10), + (2, 20), + (3, 10), + (4, 10), + (5, 10), + (6, 10), + (7, 10), + (8, 10), + (9, 10), + (10, 10), + (11, 10), + ]) + .with_collators(vec![ + (1, 10), + (2, 20), + (3, 10), + (4, 10), + (5, 10), + (6, 10), + (7, 10), + (8, 10), + (9, 10), + (10, 10), + ]) + .build() + .execute_with(|| { + assert_eq!( + StakePallet::estimate_current_session_progress(10).0.unwrap(), + Permill::from_percent(10) + ); + assert_eq!( + StakePallet::estimate_current_session_progress(20).0.unwrap(), + Permill::from_percent(20) + ); + assert_eq!( + StakePallet::estimate_current_session_progress(30).0.unwrap(), + Permill::from_percent(30) + ); + assert_eq!( + StakePallet::estimate_current_session_progress(60).0.unwrap(), + Permill::from_percent(60) + ); + assert_eq!( + StakePallet::estimate_current_session_progress(100).0.unwrap(), + Permill::from_percent(100) + ); + }); +} + +#[test] +fn should_estimate_next_session_rotation() { + ExtBuilder::default() + .set_blocks_per_round(100) + .with_balances(vec![ + (1, 10), + (2, 20), + (3, 10), + (4, 10), + (5, 10), + (6, 10), + (7, 10), + (8, 10), + (9, 10), + (10, 10), + (11, 10), + ]) + .with_collators(vec![ + (1, 10), + (2, 20), + (3, 10), + (4, 10), + (5, 10), + (6, 10), + (7, 10), + (8, 10), + (9, 10), + (10, 10), + ]) + .build() + .execute_with(|| { + assert_eq!(StakePallet::estimate_next_session_rotation(10).0.unwrap(), 100); + assert_eq!(StakePallet::estimate_next_session_rotation(20).0.unwrap(), 100); + assert_eq!(StakePallet::estimate_next_session_rotation(30).0.unwrap(), 100); + assert_eq!(StakePallet::estimate_next_session_rotation(60).0.unwrap(), 100); + assert_eq!(StakePallet::estimate_next_session_rotation(100).0.unwrap(), 100); + }); +} + +#[test] +fn should_end_session_when_appropriate() { + ExtBuilder::default() + .set_blocks_per_round(100) + .with_balances(vec![ + (1, 10), + (2, 20), + (3, 10), + (4, 10), + (5, 10), + (6, 10), + (7, 10), + (8, 10), + (9, 10), + (10, 10), + (11, 10), + ]) + .with_collators(vec![ + (1, 10), + (2, 20), + (3, 10), + (4, 10), + (5, 10), + (6, 10), + (7, 10), + (8, 10), + (9, 10), + (10, 10), + ]) + .build() + .execute_with(|| { + assert!(!StakePallet::should_end_session(10)); + assert!(!StakePallet::should_end_session(20)); + assert!(!StakePallet::should_end_session(30)); + assert!(!StakePallet::should_end_session(60)); + assert!(StakePallet::should_end_session(100)); + }); +} + +#[test] +fn set_max_selected_candidates_safe_guards() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_collators(vec![(1, 10)]) + .build() + .execute_with(|| { + assert_noop!( + StakePallet::set_max_selected_candidates( + RuntimeOrigin::root(), + ::MinCollators::get() - 1 + ), + Error::::CannotSetBelowMin + ); + assert_noop!( + StakePallet::set_max_selected_candidates( + RuntimeOrigin::root(), + ::MaxTopCandidates::get() + 1 + ), + Error::::CannotSetAboveMax + ); + assert_ok!(StakePallet::set_max_selected_candidates( + RuntimeOrigin::root(), + ::MinCollators::get() + 1 + )); + }); +} + +#[test] +fn set_max_selected_candidates_total_stake() { + let balances: Vec<(AccountId, Balance)> = (1..19).map(|x| (x, 100)).collect(); + ExtBuilder::default() + .with_balances(balances) + .with_collators(vec![ + (1, 11), + (2, 12), + (3, 13), + (4, 14), + (5, 15), + (6, 16), + (7, 17), + (8, 18), + ]) + .with_delegators(vec![ + (11, 1, 21), + (12, 2, 22), + (13, 3, 23), + (14, 4, 24), + (15, 5, 25), + (16, 6, 26), + (17, 7, 27), + (18, 8, 28), + ]) + .build() + .execute_with(|| { + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 35, + delegators: 55 + } + ); + + assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 3)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 51, + delegators: 81 + } + ); + + assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 5)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 80, + delegators: 130 + } + ); + + assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 10)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 116, + delegators: 196 + } + ); + + assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 2)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 35, + delegators: 55 + } + ); + }); +} + +#[test] +fn update_inflation() { + ExtBuilder::default() + .with_balances(vec![(1, 10)]) + .with_collators(vec![(1, 10)]) + .build() + .execute_with(|| { + let mut invalid_inflation = InflationInfo { + collator: StakingInfo { + max_rate: Perquintill::one(), + reward_rate: RewardRate { + annual: Perquintill::from_percent(99), + per_block: Perquintill::from_percent(1), + }, + }, + delegator: StakingInfo { + max_rate: Perquintill::one(), + reward_rate: RewardRate { + annual: Perquintill::from_percent(99), + per_block: Perquintill::from_percent(1), + }, + }, + }; + assert!(!invalid_inflation.is_valid(::BLOCKS_PER_YEAR)); + invalid_inflation.collator.reward_rate.per_block = Perquintill::zero(); + assert!(!invalid_inflation.is_valid(::BLOCKS_PER_YEAR)); + + assert_ok!(StakePallet::set_inflation( + RuntimeOrigin::root(), + Perquintill::from_percent(0), + Perquintill::from_percent(100), + Perquintill::from_percent(100), + Perquintill::from_percent(100), + )); + assert_ok!(StakePallet::set_inflation( + RuntimeOrigin::root(), + Perquintill::from_percent(100), + Perquintill::from_percent(0), + Perquintill::from_percent(100), + Perquintill::from_percent(100), + )); + assert_ok!(StakePallet::set_inflation( + RuntimeOrigin::root(), + Perquintill::from_percent(100), + Perquintill::from_percent(100), + Perquintill::from_percent(0), + Perquintill::from_percent(100), + )); + assert_ok!(StakePallet::set_inflation( + RuntimeOrigin::root(), + Perquintill::from_percent(100), + Perquintill::from_percent(100), + Perquintill::from_percent(100), + Perquintill::from_percent(0), + )); + }); +} + +#[test] +fn unlock_unstaked() { + // same_unstaked_as_restaked + // block 1: stake & unstake for 100 + // block 2: stake & unstake for 100 + // should remove first entry in unstaking BoundedBTreeMap when staking in block + // 2 should still have 100 locked until unlocking + ExtBuilder::default() + .with_balances(vec![(1, 10), (2, 100)]) + .with_collators(vec![(1, 10)]) + .with_delegators(vec![(2, 1, 100)]) + .build() + .execute_with(|| { + assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); + let mut unstaking: BoundedBTreeMap, ::MaxUnstakeRequests> = + BoundedBTreeMap::new(); + assert_ok!(unstaking.try_insert(3, 100)); + let lock = BalanceLock { + id: STAKING_ID, + amount: 100, + reasons: Reasons::All, + }; + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + // shouldn't be able to unlock anything + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + + // join delegators and revoke again --> consume unstaking at block 3 + roll_to(2, vec![]); + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 100)); + assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); + unstaking.remove(&3); + assert_ok!(unstaking.try_insert(4, 100)); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + // shouldn't be able to unlock anything + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + + // should reduce unlocking but not unlock anything + roll_to(3, vec![]); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + // shouldn't be able to unlock anything + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + + roll_to(4, vec![]); + unstaking.remove(&4); + assert_eq!(Balances::locks(2), vec![lock]); + // shouldn't be able to unlock anything + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![]); + }); + + // less_unstaked_than_restaked + // block 1: stake & unstake for 10 + // block 2: stake & unstake for 100 + // should remove first entry in unstaking BoundedBTreeMap when staking in block + // 2 should still have 90 locked until unlocking in block 4 + ExtBuilder::default() + .with_balances(vec![(1, 10), (2, 100)]) + .with_collators(vec![(1, 10)]) + .with_delegators(vec![(2, 1, 10)]) + .build() + .execute_with(|| { + assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); + let mut unstaking: BoundedBTreeMap, ::MaxUnstakeRequests> = + BoundedBTreeMap::new(); + assert_ok!(unstaking.try_insert(3, 10)); + let mut lock = BalanceLock { + id: STAKING_ID, + amount: 10, + reasons: Reasons::All, + }; + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + // shouldn't be able to unlock anything + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + + // join delegators and revoke again + roll_to(2, vec![]); + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 100)); + assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); + unstaking.remove(&3); + assert_ok!(unstaking.try_insert(4, 100)); + lock.amount = 100; + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + // shouldn't be able to unlock anything + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + + roll_to(3, vec![]); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + // shouldn't be able to unlock anything + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + + // unlock unstaked, remove lock, empty unlocking + roll_to(4, vec![]); + unstaking.remove(&4); + assert_eq!(Balances::locks(2), vec![lock]); + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![]); + }); + + // more_unstaked_than_restaked + // block 1: stake & unstake for 100 + // block 2: stake & unstake for 10 + // should reduce first entry from amount 100 to 90 in unstaking BoundedBTreeMap + // when staking in block 2 + // should have 100 locked until unlocking in block 3, then 10 + // should have 10 locked until further unlocking in block 4 + ExtBuilder::default() + .with_balances(vec![(1, 10), (2, 100)]) + .with_collators(vec![(1, 10)]) + .with_delegators(vec![(2, 1, 100)]) + .build() + .execute_with(|| { + assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); + let mut unstaking: BoundedBTreeMap, ::MaxUnstakeRequests> = + BoundedBTreeMap::new(); + assert_ok!(unstaking.try_insert(3, 100)); + let mut lock = BalanceLock { + id: STAKING_ID, + amount: 100, + reasons: Reasons::All, + }; + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + // shouldn't be able to unlock anything + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + + // join delegators and revoke again + roll_to(2, vec![]); + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 10)); + assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); + assert_ok!(unstaking.try_insert(3, 90)); + assert_ok!(unstaking.try_insert(4, 10)); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + // shouldn't be able to unlock anything + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + + // should reduce unlocking but not unlock anything + roll_to(3, vec![]); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + // should be able to unlock 90 of 100 from unstaking + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); + unstaking.remove(&3); + lock.amount = 10; + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + + roll_to(4, vec![]); + assert_eq!(Balances::locks(2), vec![lock]); + // should be able to unlock 10 of remaining 10 + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); + unstaking.remove(&4); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(2), vec![]); + }); + + // test_stake_less + // block 1: stake & unstake for 100 + // block 2: stake & unstake for 10 + // should reduce first entry from amount 100 to 90 in unstaking BoundedBTreeMap + // when staking in block 2 + // should have 100 locked until unlocking in block 3, then 10 + // should have 10 locked until further unlocking in block 4 + ExtBuilder::default() + .with_balances(vec![(1, 200), (2, 200)]) + .with_collators(vec![(1, 200)]) + .with_delegators(vec![(2, 1, 200)]) + .build() + .execute_with(|| { + // should be able to decrease more often than MaxUnstakeRequests because it's + // the same block and thus unstaking is increased at block 3 instead of having + // multiple entries for the same block + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10)); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10)); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10)); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10)); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10)); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10),); + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10)); + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10)); + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10)); + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10)); + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10)); + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10),); + let mut unstaking: BoundedBTreeMap, ::MaxUnstakeRequests> = + BoundedBTreeMap::new(); + assert_ok!(unstaking.try_insert(3, 60)); + let mut lock = BalanceLock { + id: STAKING_ID, + amount: 200, + reasons: Reasons::All, + }; + assert_eq!(Balances::locks(1), vec![lock.clone()]); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + assert_eq!(StakePallet::unstaking(1), unstaking); + assert_eq!(StakePallet::unstaking(2), unstaking); + // shouldn't be able to unlock anything + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(1), 1)); + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); + assert_eq!(StakePallet::unstaking(1), unstaking); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(1), vec![lock.clone()]); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + + roll_to(2, vec![]); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10),); + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10),); + assert_ok!(unstaking.try_insert(4, 10)); + assert_eq!(Balances::locks(1), vec![lock.clone()]); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + assert_eq!(StakePallet::unstaking(1), unstaking); + assert_eq!(StakePallet::unstaking(2), unstaking); + // shouldn't be able to unlock anything + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(1), 1)); + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); + assert_eq!(StakePallet::unstaking(1), unstaking); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(1), vec![lock.clone()]); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + + roll_to(3, vec![]); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10),); + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10),); + assert_ok!(unstaking.try_insert(5, 10)); + assert_ok!(unstaking.try_insert(5, 10)); + assert_eq!(Balances::locks(1), vec![lock.clone()]); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + assert_eq!(StakePallet::unstaking(1), unstaking); + assert_eq!(StakePallet::unstaking(2), unstaking); + // should unlock 60 + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(1), 1)); + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); + lock.amount = 140; + unstaking.remove(&3); + assert_eq!(StakePallet::unstaking(1), unstaking); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(1), vec![lock.clone()]); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + + // reach MaxUnstakeRequests + roll_to(4, vec![]); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10)); + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10)); + roll_to(5, vec![]); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10)); + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10)); + roll_to(6, vec![]); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10)); + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10)); + assert_ok!(unstaking.try_insert(6, 10)); + assert_ok!(unstaking.try_insert(7, 10)); + assert_ok!(unstaking.try_insert(8, 10)); + assert_eq!(StakePallet::unstaking(1), unstaking); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(1), vec![lock.clone()]); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + + roll_to(7, vec![]); + assert_noop!( + StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 10), + Error::::NoMoreUnstaking + ); + assert_noop!( + StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 10), + Error::::NoMoreUnstaking + ); + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(1), 1)); + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(2), 2)); + unstaking.remove(&4); + unstaking.remove(&5); + unstaking.remove(&6); + unstaking.remove(&7); + lock.amount = 100; + assert_eq!(StakePallet::unstaking(1), unstaking); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(1), vec![lock.clone()]); + assert_eq!(Balances::locks(2), vec![lock.clone()]); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 40)); + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(2), 40)); + assert_ok!(unstaking.try_insert(9, 40)); + assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 30)); + assert_ok!(StakePallet::delegator_stake_more(RuntimeOrigin::signed(2), 30)); + unstaking.remove(&8); + assert_ok!(unstaking.try_insert(9, 20)); + assert_eq!(StakePallet::unstaking(1), unstaking); + assert_eq!(StakePallet::unstaking(2), unstaking); + assert_eq!(Balances::locks(1), vec![lock.clone()]); + assert_eq!(Balances::locks(2), vec![lock]); + }); +} + +#[test] +fn kick_candidate_with_full_unstaking() { + ExtBuilder::default() + .with_balances(vec![(1, 200), (2, 200), (3, 300)]) + .with_collators(vec![(1, 200), (2, 200), (3, 200)]) + .build() + .execute_with(|| { + let max_unstake_reqs: usize = ::MaxUnstakeRequests::get() + .saturating_sub(1) + .saturated_into(); + // Fill unstake requests + for block in 1u64..1u64.saturating_add(max_unstake_reqs as u64) { + System::set_block_number(block); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(3), 1)); + } + assert_eq!(StakePallet::unstaking(3).into_inner().len(), max_unstake_reqs); + + // Additional unstake should fail + System::set_block_number(100); + assert_noop!( + StakePallet::candidate_stake_less(RuntimeOrigin::signed(3), 1), + Error::::NoMoreUnstaking + ); + + // Fill last unstake request by removing candidate and unstaking all stake + assert_ok!(StakePallet::force_remove_candidate(RuntimeOrigin::root(), 3)); + + // Cannot join with full unstaking + assert_eq!(StakePallet::unstaking(3).into_inner().len(), max_unstake_reqs + 1); + assert_noop!( + StakePallet::join_candidates(RuntimeOrigin::signed(3), 100), + Error::::CannotJoinBeforeUnlocking + ); + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(3), 3)); + assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(3), 100)); + }); +} +#[test] +fn kick_delegator_with_full_unstaking() { + ExtBuilder::default() + .with_balances(vec![(1, 200), (2, 200), (3, 200), (4, 200), (5, 420), (6, 200)]) + .with_collators(vec![(1, 200)]) + .with_delegators(vec![(2, 1, 200), (3, 1, 200), (4, 1, 200), (5, 1, 200)]) + .build() + .execute_with(|| { + let max_unstake_reqs: usize = ::MaxUnstakeRequests::get() + .saturating_sub(1) + .saturated_into(); + // Fill unstake requests + for block in 1u64..1u64.saturating_add(max_unstake_reqs as u64) { + System::set_block_number(block); + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(5), 1)); + } + assert_eq!(StakePallet::unstaking(5).into_inner().len(), max_unstake_reqs); + + // Additional unstake should fail + System::set_block_number(100); + assert_noop!( + StakePallet::delegator_stake_less(RuntimeOrigin::signed(5), 1), + Error::::NoMoreUnstaking + ); + + // Fill last unstake request by replacing delegator + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(6), 1, 200)); + assert_eq!(StakePallet::unstaking(5).into_inner().len(), max_unstake_reqs + 1); + assert!(!StakePallet::is_delegator(&5)); + + // Cannot join with full unstaking + assert_noop!( + StakePallet::join_delegators(RuntimeOrigin::signed(5), 1, 100), + Error::::CannotJoinBeforeUnlocking + ); + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(5), 5)); + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(5), 1, 220)); + }); +} + +#[test] +fn candidate_leaves() { + let balances: Vec<(AccountId, Balance)> = (1u64..=15u64).map(|id| (id, 100)).collect(); + ExtBuilder::default() + .with_balances(balances) + .with_collators(vec![(1, 100), (2, 100)]) + .with_delegators(vec![(12, 1, 100), (13, 1, 10)]) + .build() + .execute_with(|| { + assert_eq!( + StakePallet::top_candidates() + .into_iter() + .map(|s| s.owner) + .collect::>(), + vec![1, 2] + ); + assert_noop!( + StakePallet::init_leave_candidates(RuntimeOrigin::signed(11)), + Error::::CandidateNotFound + ); + assert_noop!( + StakePallet::init_leave_candidates(RuntimeOrigin::signed(1)), + Error::::TooFewCollatorCandidates + ); + // add five more collator to max fill TopCandidates + for candidate in 3u64..11u64 { + assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(candidate), 100)); + } + assert_eq!( + StakePallet::top_candidates() + .into_iter() + .map(|s| s.owner) + .collect::>(), + (1u64..11u64).collect::>() + ); + assert_eq!(CandidatePool::::count(), 10); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(1))); + assert_eq!( + StakePallet::top_candidates() + .into_iter() + .map(|s| s.owner) + .collect::>(), + (2u64..11u64).collect::>() + ); + assert_noop!( + StakePallet::join_delegators(RuntimeOrigin::signed(15), 1, 10), + Error::::CannotDelegateIfLeaving + ); + assert_noop!( + StakePallet::delegator_stake_more(RuntimeOrigin::signed(12), 1), + Error::::CannotDelegateIfLeaving + ); + assert_noop!( + StakePallet::delegator_stake_less(RuntimeOrigin::signed(12), 1), + Error::::CannotDelegateIfLeaving + ); + assert_noop!( + StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 1), + Error::::CannotStakeIfLeaving + ); + assert_noop!( + StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 1), + Error::::CannotStakeIfLeaving + ); + assert_noop!( + StakePallet::init_leave_candidates(RuntimeOrigin::signed(1)), + Error::::AlreadyLeaving + ); + assert_eq!( + StakePallet::candidate_pool(1).unwrap().status, + CandidateStatus::Leaving(2) + ); + assert!(StakePallet::candidate_pool(1).unwrap().can_exit(2)); + assert!(!StakePallet::candidate_pool(1).unwrap().can_exit(1)); + assert!(StakePallet::candidate_pool(1).unwrap().can_exit(3)); + + // next rounds starts, cannot leave yet + roll_to(5, vec![]); + assert_noop!( + StakePallet::execute_leave_candidates(RuntimeOrigin::signed(2), 2), + Error::::NotLeaving + ); + assert_noop!( + StakePallet::execute_leave_candidates(RuntimeOrigin::signed(2), 1), + Error::::CannotLeaveYet + ); + // add 11 as candidate to reach max size for TopCandidates and then try leave + // again as 1 which should not be possible + assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(11), 100)); + assert_eq!( + StakePallet::top_candidates() + .into_iter() + .map(|s| s.owner) + .collect::>(), + (2u64..12u64).collect::>() + ); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(11))); + // join back + assert_ok!(StakePallet::cancel_leave_candidates(RuntimeOrigin::signed(1))); + assert_eq!( + StakePallet::top_candidates() + .into_iter() + .map(|s| s.owner) + .collect::>(), + (1u64..11u64).collect::>() + ); + + let stake: Vec> = (1u64..11u64) + .zip(iter::once(210).chain(iter::repeat(100))) + .map(|(id, amount)| StakeOf:: { owner: id, amount }) + .collect(); + assert_eq!( + StakePallet::top_candidates(), + OrderedSet::from(stake.try_into().unwrap()) + ); + let state = StakePallet::candidate_pool(1).unwrap(); + assert_eq!(state.status, CandidateStatus::Active); + assert_eq!(state.delegators.len(), 2); + assert_eq!(state.total, 210); + assert_eq!( + state.total, + StakePallet::top_candidates() + .into_bounded_vec() + .iter() + .find(|other| other.owner == 1) + .unwrap() + .amount + ); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2]); + + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(1))); + + roll_to(15, vec![]); + assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(13), 1)); + let mut unstaking: BoundedBTreeMap, ::MaxUnstakeRequests> = + BoundedBTreeMap::new(); + assert_ok!(unstaking.try_insert(17, 100)); + assert_eq!(StakePallet::unstaking(1), unstaking); + assert_eq!(StakePallet::unstaking(12), unstaking); + + // cannot unlock yet + roll_to(16, vec![]); + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(4), 1)); + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(4), 12)); + assert_eq!(StakePallet::unstaking(1), unstaking); + assert_eq!(StakePallet::unstaking(12), unstaking); + + // can unlock now + roll_to(17, vec![]); + unstaking.remove(&17); + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(4), 1)); + assert_ok!(StakePallet::unlock_unstaked(RuntimeOrigin::signed(4), 12)); + assert_eq!(StakePallet::unstaking(1), unstaking); + assert_eq!(StakePallet::unstaking(12), unstaking); + }); +} + +#[test] +fn adjust_reward_rates() { + ExtBuilder::default() + .with_balances(vec![(1, 10_000_000 * DECIMALS), (2, 90_000_000 * DECIMALS)]) + .with_collators(vec![(1, 10_000_000 * DECIMALS)]) + .with_delegators(vec![(2, 1, 40_000_000 * DECIMALS)]) + .with_inflation(10, 10, 40, 8, 5) + .build() + .execute_with(|| { + let inflation_0 = StakePallet::inflation_config(); + let num_of_years = 3 * ::BLOCKS_PER_YEAR; + // 1 authors every block + let authors: Vec> = (0u64..=num_of_years).map(|_| Some(1u64)).collect(); + + // reward once in first year + roll_to_claim_rewards(2, authors.clone()); + let c_rewards_0 = Balances::free_balance(&1).saturating_sub(10_000_000 * DECIMALS); + let d_rewards_0 = Balances::free_balance(&2).saturating_sub(90_000_000 * DECIMALS); + assert!(!c_rewards_0.is_zero()); + assert!(!d_rewards_0.is_zero()); + + // finish first year + System::set_block_number(::BLOCKS_PER_YEAR); + roll_to_claim_rewards(::BLOCKS_PER_YEAR + 1, vec![]); + // reward reduction should not happen automatically anymore + assert_eq!(StakePallet::last_reward_reduction(), 0u64); + assert_ok!(StakePallet::execute_scheduled_reward_change(RuntimeOrigin::signed(1))); + assert_eq!(StakePallet::last_reward_reduction(), 1u64); + let inflation_1 = InflationInfo::new( + ::BLOCKS_PER_YEAR, + inflation_0.collator.max_rate, + Perquintill::from_parts(98000000000000000), + inflation_0.delegator.max_rate, + Perquintill::from_percent(6), + ); + assert_eq!(StakePallet::inflation_config(), inflation_1); + // reward once in 2nd year + roll_to_claim_rewards(::BLOCKS_PER_YEAR + 2, authors.clone()); + let c_rewards_1 = Balances::free_balance(&1) + .saturating_sub(10_000_000 * DECIMALS) + .saturating_sub(c_rewards_0); + let d_rewards_1 = Balances::free_balance(&2) + .saturating_sub(90_000_000 * DECIMALS) + .saturating_sub(d_rewards_0); + assert!( + c_rewards_0 > c_rewards_1, + "left {:?}, right {:?}", + c_rewards_0, + c_rewards_1 + ); + assert!(d_rewards_0 > d_rewards_1); + + // finish 2nd year + System::set_block_number(2 * ::BLOCKS_PER_YEAR); + roll_to_claim_rewards(2 * ::BLOCKS_PER_YEAR + 1, vec![]); + // reward reduction should not happen automatically anymore + assert_eq!(StakePallet::last_reward_reduction(), 1u64); + assert_ok!(StakePallet::execute_scheduled_reward_change(RuntimeOrigin::signed(1))); + assert_eq!(StakePallet::last_reward_reduction(), 2u64); + let inflation_2 = InflationInfo::new( + ::BLOCKS_PER_YEAR, + inflation_0.collator.max_rate, + Perquintill::from_parts(96040000000000000), + inflation_0.delegator.max_rate, + Perquintill::zero(), + ); + assert_eq!(StakePallet::inflation_config(), inflation_2); + // reward once in 3rd year + roll_to_claim_rewards(2 * ::BLOCKS_PER_YEAR + 2, authors); + let c_rewards_2 = Balances::free_balance(&1) + .saturating_sub(10_000_000 * DECIMALS) + .saturating_sub(c_rewards_0) + .saturating_sub(c_rewards_1); + assert!(c_rewards_1 > c_rewards_2); + // should be zero because we set reward rate to zero + let d_rewards_2 = Balances::free_balance(&2) + .saturating_sub(90_000_000 * DECIMALS) + .saturating_sub(d_rewards_0) + .saturating_sub(d_rewards_1); + assert!(d_rewards_2.is_zero()); + }); +} + +#[test] +fn increase_max_candidate_stake() { + let max_stake = 160_000_000 * DECIMALS; + ExtBuilder::default() + .with_balances(vec![(1, 200_000_000 * DECIMALS)]) + .with_collators(vec![(1, max_stake)]) + .build() + .execute_with(|| { + assert_eq!(StakePallet::max_candidate_stake(), max_stake); + assert_noop!( + StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 1), + Error::::ValStakeAboveMax + ); + + assert_ok!(StakePallet::set_max_candidate_stake( + RuntimeOrigin::root(), + max_stake + 1 + )); + assert_eq!(last_event(), StakeEvent::MaxCandidateStakeChanged(max_stake + 1)); + assert_eq!(StakePallet::max_candidate_stake(), max_stake + 1); + assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 1)); + assert_noop!( + StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 1), + Error::::ValStakeAboveMax + ); + }); +} + +#[test] +fn decrease_max_candidate_stake() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100)]) + .with_collators(vec![(1, 100), (2, 90), (3, 40)]) + .with_delegators(vec![(4, 2, 10), (5, 3, 20)]) + .build() + .execute_with(|| { + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2]); + assert_eq!( + StakePallet::top_candidates(), + OrderedSet::from_sorted_set( + vec![ + StakeOf:: { owner: 1, amount: 100 }, + StakeOf:: { owner: 2, amount: 100 }, + StakeOf:: { owner: 3, amount: 60 } + ] + .try_into() + .unwrap() + ) + ); + + assert_ok!(StakePallet::set_max_candidate_stake(RuntimeOrigin::root(), 50)); + assert_eq!(StakePallet::max_candidate_stake(), 50); + assert_eq!(last_event(), StakeEvent::MaxCandidateStakeChanged(50)); + + // check collator states, nothing changed + assert_eq!( + StakePallet::top_candidates(), + OrderedSet::from_sorted_set( + vec![ + StakeOf:: { owner: 1, amount: 100 }, + StakeOf:: { owner: 2, amount: 100 }, + StakeOf:: { owner: 3, amount: 60 } + ] + .try_into() + .unwrap() + ) + ); + + assert_noop!( + StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 0), + Error::::ValStakeZero + ); + assert_noop!( + StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 0), + Error::::ValStakeZero + ); + assert_noop!( + StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 1), + Error::::ValStakeAboveMax + ); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 50)); + assert_noop!( + StakePallet::set_max_candidate_stake(RuntimeOrigin::root(), 9), + Error::::CannotSetBelowMin + ); + }); +} + +#[test] +fn exceed_delegations_per_round() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100)]) + .with_collators(vec![(1, 100)]) + .with_delegators(vec![(2, 1, 100)]) + .build() + .execute_with(|| { + // leave and re-join to set counter to 2 (= MaxDelegationsPerRound) + assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 100)); + assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); + // reached max delegations in this round + assert_noop!( + StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 100), + Error::::DelegationsPerRoundExceeded + ); + + // roll to next round to clear DelegationCounter + roll_to(5, vec![]); + assert_eq!( + StakePallet::last_delegation(2), + DelegationCounter { round: 0, counter: 2 } + ); + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 100)); + // counter should be reset because the round changed + assert_eq!( + StakePallet::last_delegation(2), + DelegationCounter { round: 1, counter: 1 } + ); + // leave and re-join to set counter to 2 (= MaxDelegationsPerRound)) + assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 100)); + assert_noop!( + StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 100), + Error::::AlreadyDelegating + ); + assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(2))); + assert_noop!( + StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 100), + Error::::DelegationsPerRoundExceeded + ); + assert_eq!( + StakePallet::last_delegation(2), + DelegationCounter { round: 1, counter: 2 } + ); + }); +} + +#[test] +fn force_remove_candidate() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (6, 100)]) + .with_collators(vec![(1, 100), (2, 100), (3, 100)]) + .with_delegators(vec![(4, 1, 50), (5, 1, 50)]) + .build() + .execute_with(|| { + assert_eq!(CandidatePool::::count(), 3); + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(6), 2, 50)); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2]); + assert!(StakePallet::unstaking(1).get(&3).is_none()); + assert!(StakePallet::unstaking(2).get(&3).is_none()); + assert!(StakePallet::unstaking(3).get(&3).is_none()); + + // force remove 1 + assert!(Session::disabled_validators().is_empty()); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 200, + delegators: 150 + } + ); + assert_ok!(StakePallet::force_remove_candidate(RuntimeOrigin::root(), 1)); + // collator stake does not change since 3, who took 1's place, has staked the + // same amount + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 200, + delegators: 50 + } + ); + assert_eq!(Session::disabled_validators(), vec![0]); + assert_eq!(last_event(), StakeEvent::CollatorRemoved(1, 200)); + assert!(!StakePallet::top_candidates().contains(&StakeOf:: { owner: 1, amount: 100 })); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 3]); + assert_eq!(CandidatePool::::count(), 2); + assert!(StakePallet::candidate_pool(1).is_none()); + assert!(StakePallet::delegator_state(4).is_none()); + assert!(StakePallet::delegator_state(5).is_none()); + assert_eq!(StakePallet::unstaking(1).get(&3), Some(&100)); + assert_eq!(StakePallet::unstaking(4).get(&3), Some(&50)); + assert_eq!(StakePallet::unstaking(5).get(&3), Some(&50)); + + assert_noop!( + StakePallet::force_remove_candidate(RuntimeOrigin::root(), 2), + Error::::TooFewCollatorCandidates + ); + assert_noop!( + StakePallet::force_remove_candidate(RuntimeOrigin::root(), 4), + Error::::CandidateNotFound + ); + + // session 1: expect 1 to still be in validator set but as disabled + roll_to(5, vec![]); + assert_eq!(Session::current_index(), 1); + assert_eq!(Session::validators(), vec![1, 2]); + assert_eq!(Session::disabled_validators(), vec![0]); + + // session 2: expect validator set to have changed + roll_to(10, vec![]); + assert_eq!(Session::validators(), vec![2, 3]); + assert!(Session::disabled_validators().is_empty()); + }); +} + +#[test] +fn prioritize_collators() { + ExtBuilder::default() + .with_balances(vec![ + (1, 200), + (2, 200), + (3, 200), + (4, 200), + (5, 200), + (6, 200), + (7, 200), + ]) + .with_collators(vec![(2, 100), (3, 100)]) + .build() + .execute_with(|| { + assert_eq!( + StakePallet::top_candidates(), + OrderedSet::from_sorted_set( + vec![2, 3] + .into_iter() + .map(|id| StakeOf:: { owner: id, amount: 100 }) + .collect::>>() + .try_into() + .unwrap() + ) + ); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 3]); + assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(1), 100)); + assert_eq!( + StakePallet::top_candidates(), + OrderedSet::from_sorted_set( + vec![2, 3, 1] + .into_iter() + .map(|id| StakeOf:: { owner: id, amount: 100 }) + .collect::>>() + .try_into() + .unwrap() + ) + ); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 3]); + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(2))); + assert_eq!(StakePallet::top_candidates().len(), 2); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![3, 1]); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(3), 10)); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 3]); + + // add 6 + assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(6), 100)); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 6]); + assert_eq!( + StakePallet::top_candidates(), + OrderedSet::from_sorted_set( + vec![1, 6] + .into_iter() + .map(|id| StakeOf:: { owner: id, amount: 100 }) + .chain(vec![StakeOf:: { owner: 3, amount: 90 }]) + .collect::>>() + .try_into() + .unwrap() + ) + ); + + // add 4 + assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(4), 100)); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 6]); + assert_eq!( + StakePallet::top_candidates(), + OrderedSet::from_sorted_set( + vec![1, 6, 4] + .into_iter() + .map(|id| StakeOf:: { owner: id, amount: 100 }) + .chain(vec![StakeOf:: { owner: 3, amount: 90 }]) + .collect::>>() + .try_into() + .unwrap() + ) + ); + + // add 5 + assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(5), 100)); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 6]); + assert_eq!( + StakePallet::top_candidates(), + OrderedSet::from_sorted_set( + vec![1, 6, 4, 5] + .into_iter() + .map(|id| StakeOf:: { owner: id, amount: 100 }) + .chain(vec![StakeOf:: { owner: 3, amount: 90 }]) + .collect::>>() + .try_into() + .unwrap() + ) + ); + + // 3 stake_more + assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(3), 20)); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![3, 1]); + assert_eq!( + StakePallet::top_candidates(), + OrderedSet::from_sorted_set( + vec![ + StakeOf:: { owner: 3, amount: 110 }, + StakeOf:: { owner: 1, amount: 100 }, + StakeOf:: { owner: 6, amount: 100 }, + StakeOf:: { owner: 4, amount: 100 }, + StakeOf:: { owner: 5, amount: 100 }, + ] + .try_into() + .unwrap() + ) + ); + + // 1 stake_less + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), 1)); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![3, 6]); + assert_eq!( + StakePallet::top_candidates(), + OrderedSet::from_sorted_set( + vec![ + StakeOf:: { owner: 3, amount: 110 }, + StakeOf:: { owner: 6, amount: 100 }, + StakeOf:: { owner: 4, amount: 100 }, + StakeOf:: { owner: 5, amount: 100 }, + StakeOf:: { owner: 1, amount: 99 }, + ] + .try_into() + .unwrap() + ) + ); + + // 7 delegates to 4 + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(7), 5, 20)); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![5, 3]); + assert_eq!( + StakePallet::top_candidates(), + OrderedSet::from_sorted_set( + vec![ + StakeOf:: { owner: 5, amount: 120 }, + StakeOf:: { owner: 3, amount: 110 }, + StakeOf:: { owner: 6, amount: 100 }, + StakeOf:: { owner: 4, amount: 100 }, + StakeOf:: { owner: 1, amount: 99 }, + ] + .try_into() + .unwrap() + ) + ); + + // 7 decreases delegation + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(7), 10)); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![5, 3]); + assert_eq!( + StakePallet::top_candidates(), + OrderedSet::from_sorted_set( + vec![ + StakeOf:: { owner: 5, amount: 110 }, + StakeOf:: { owner: 3, amount: 110 }, + StakeOf:: { owner: 6, amount: 100 }, + StakeOf:: { owner: 4, amount: 100 }, + StakeOf:: { owner: 1, amount: 99 }, + ] + .try_into() + .unwrap() + ) + ); + assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(7))); + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![3, 5]); + assert_eq!( + StakePallet::top_candidates(), + OrderedSet::from_sorted_set( + vec![ + StakeOf:: { owner: 3, amount: 110 }, + StakeOf:: { owner: 5, amount: 100 }, + StakeOf:: { owner: 6, amount: 100 }, + StakeOf:: { owner: 4, amount: 100 }, + StakeOf:: { owner: 1, amount: 99 }, + ] + .try_into() + .unwrap() + ) + ); + }); +} + +#[test] +fn prioritize_delegators() { + ExtBuilder::default() + .with_balances(vec![ + (1, 1000), + (2, 1000), + (3, 1000), + (4, 1000), + (5, 1000), + (6, 1000), + (7, 1000), + (8, 1000), + (9, 1000), + ]) + .with_collators(vec![(1, 100), (2, 100), (3, 100)]) + .with_delegators(vec![(4, 2, 100), (7, 2, 100), (6, 2, 100)]) + .build() + .execute_with(|| { + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![2, 1]); + assert_eq!( + StakePallet::candidate_pool(2).unwrap().delegators, + OrderedSet::from_sorted_set( + vec![ + StakeOf:: { owner: 4, amount: 100 }, + StakeOf:: { owner: 7, amount: 100 }, + StakeOf:: { owner: 6, amount: 100 }, + ] + .try_into() + .unwrap() + ) + ); + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(5), 2, 110)); + assert_eq!( + StakePallet::candidate_pool(2).unwrap().delegators, + OrderedSet::from_sorted_set( + vec![ + StakeOf:: { owner: 5, amount: 110 }, + StakeOf:: { owner: 4, amount: 100 }, + StakeOf:: { owner: 7, amount: 100 }, + StakeOf:: { owner: 6, amount: 100 }, + ] + .try_into() + .unwrap() + ) + ); + + // delegate_less + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(5), 10)); + assert_eq!( + StakePallet::candidate_pool(2).unwrap().delegators, + OrderedSet::from_sorted_set( + vec![ + StakeOf:: { owner: 5, amount: 100 }, + StakeOf:: { owner: 4, amount: 100 }, + StakeOf:: { owner: 7, amount: 100 }, + StakeOf:: { owner: 6, amount: 100 }, + ] + .try_into() + .unwrap() + ) + ); + + // delegate_more + assert_ok!(StakePallet::delegator_stake_more(RuntimeOrigin::signed(6), 10)); + assert_eq!( + StakePallet::candidate_pool(2).unwrap().delegators, + OrderedSet::from_sorted_set( + vec![ + StakeOf:: { owner: 6, amount: 110 }, + StakeOf:: { owner: 5, amount: 100 }, + StakeOf:: { owner: 4, amount: 100 }, + StakeOf:: { owner: 7, amount: 100 }, + ] + .try_into() + .unwrap() + ) + ); + assert_ok!(StakePallet::delegator_stake_more(RuntimeOrigin::signed(7), 10)); + assert_eq!( + StakePallet::candidate_pool(2).unwrap().delegators, + OrderedSet::from_sorted_set( + vec![ + StakeOf:: { owner: 6, amount: 110 }, + StakeOf:: { owner: 7, amount: 110 }, + StakeOf:: { owner: 5, amount: 100 }, + StakeOf:: { owner: 4, amount: 100 }, + ] + .try_into() + .unwrap() + ) + ); + }); +} + +#[test] +fn authorities_per_round() { + let stake = 100 * DECIMALS; + ExtBuilder::default() + .with_balances(vec![ + (1, stake), + (2, stake), + (3, stake), + (4, stake), + (5, stake), + (6, stake), + (7, stake), + (8, stake), + (9, stake), + (10, stake), + (11, 100 * stake), + ]) + .with_collators(vec![(1, stake), (2, stake), (3, stake), (4, stake)]) + .build() + .execute_with(|| { + assert_eq!(StakePallet::selected_candidates().into_inner(), vec![1, 2]); + // reward 1 once per round + let authors: Vec> = (0u64..=100) + .map(|i| if i % 5 == 2 { Some(1u64) } else { None }) + .collect(); + let inflation = StakePallet::inflation_config(); + + // roll to last block of round 0 + roll_to_claim_rewards(4, authors.clone()); + let reward_0 = inflation.collator.reward_rate.per_block * stake * 2; + assert_eq!(Balances::free_balance(1), stake + reward_0); + // increase max selected candidates which will become effective in round 2 + assert_ok!(StakePallet::set_max_selected_candidates(RuntimeOrigin::root(), 10)); + + // roll to last block of round 1 + // should still multiply with 2 because the Authority set was chosen at start of + // round 1 + roll_to_claim_rewards(9, authors.clone()); + let reward_1 = inflation.collator.reward_rate.per_block * stake * 2; + assert_eq!(Balances::free_balance(1), stake + reward_0 + reward_1); + + // roll to last block of round 2 + // should multiply with 4 because there are only 4 candidates + roll_to_claim_rewards(14, authors.clone()); + let reward_2 = inflation.collator.reward_rate.per_block * stake * 4; + assert_eq!(Balances::free_balance(1), stake + reward_0 + reward_1 + reward_2); + + // roll to last block of round 3 + // should multiply with 4 because there are only 4 candidates + roll_to_claim_rewards(19, authors); + let reward_3 = inflation.collator.reward_rate.per_block * stake * 4; + assert_eq!( + Balances::free_balance(1), + stake + reward_0 + reward_1 + reward_2 + reward_3 + ); + }); +} + +#[test] +fn force_new_round() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (6, 100)]) + .with_collators(vec![(1, 100), (2, 100), (3, 100), (4, 100)]) + .build() + .execute_with(|| { + let mut round = RoundInfo { + current: 0, + first: 0, + length: 5, + }; + assert_eq!(StakePallet::round(), round); + assert_eq!(Session::validators(), vec![1, 2]); + assert_eq!(Session::current_index(), 0); + // 3 should be validator in round 2 + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(5), 3, 100)); + + // init force new round from 0 to 1, updating the authorities + assert_ok!(StakePallet::force_new_round(RuntimeOrigin::root())); + assert_eq!(StakePallet::round(), round); + assert_eq!(Session::current_index(), 0); + assert!(StakePallet::new_round_forced()); + + // force new round should become active by starting next block + roll_to(2, vec![]); + round = RoundInfo { + current: 1, + first: 2, + length: 5, + }; + assert_eq!(Session::current_index(), 1); + assert_eq!(Session::validators(), vec![1, 2]); + assert!(!StakePallet::new_round_forced()); + + // roll to next block in same round 1 + roll_to(3, vec![]); + assert_eq!(Session::current_index(), 1); + assert_eq!(StakePallet::round(), round); + // assert_eq!(Session::validators(), vec![3, 1]); + assert!(!StakePallet::new_round_forced()); + // 4 should become validator in session 3 if we do not force a new round + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(6), 4, 100)); + + // end session 2 naturally + roll_to(7, vec![]); + round = RoundInfo { + current: 2, + first: 7, + length: 5, + }; + assert_eq!(StakePallet::round(), round); + assert_eq!(Session::current_index(), 2); + assert!(!StakePallet::new_round_forced()); + assert_eq!(Session::validators(), vec![3, 1]); + + // force new round 3 + assert_ok!(StakePallet::force_new_round(RuntimeOrigin::root())); + assert_eq!(StakePallet::round(), round); + assert_eq!(Session::current_index(), 2); + // validator set should not change until next round + assert_eq!(Session::validators(), vec![3, 1]); + assert!(StakePallet::new_round_forced()); + + // force new round should become active by starting next block + roll_to(8, vec![]); + round = RoundInfo { + current: 3, + first: 8, + length: 5, + }; + assert_eq!(Session::current_index(), 3); + assert_eq!(StakePallet::round(), round); + assert_eq!(Session::validators(), vec![3, 4]); + assert!(!StakePallet::new_round_forced()); + }); +} + +#[test] +fn replace_lowest_delegator() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100), (5, 100), (6, 100)]) + .with_collators(vec![(1, 100)]) + .with_delegators(vec![(2, 1, 51), (3, 1, 51), (4, 1, 51), (5, 1, 50)]) + .build() + .execute_with(|| { + assert_eq!( + StakePallet::candidate_pool(1).unwrap().delegators.len() as u32, + ::MaxDelegatorsPerCollator::get() + ); + + // 6 replaces 5 + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(6), 1, 51)); + assert!(StakePallet::delegator_state(5).is_none()); + assert_eq!( + StakePallet::candidate_pool(1) + .unwrap() + .delegators + .into_bounded_vec() + .into_inner(), + vec![ + Stake { owner: 2, amount: 51 }, + Stake { owner: 3, amount: 51 }, + Stake { owner: 4, amount: 51 }, + Stake { owner: 6, amount: 51 } + ] + ); + + // 5 attempts to replace 6 with more balance than available + frame_support::assert_noop!( + StakePallet::join_delegators(RuntimeOrigin::signed(5), 1, 101), + BalancesError::::InsufficientBalance + ); + assert!(StakePallet::delegator_state(6).is_some()); + }) +} + +#[test] +fn network_reward_multiple_blocks() { + let max_stake: Balance = 160_000_000 * DECIMALS; + let collators: Vec<(AccountId, Balance)> = (1u64..=::MinCollators::get().saturating_add(1).into()) + .map(|acc_id| (acc_id, max_stake)) + .collect(); + + ExtBuilder::default() + .with_balances(collators.clone()) + .with_collators(collators) + .build() + .execute_with(|| { + assert_eq!(max_stake, StakePallet::max_candidate_stake()); + let total_collator_stake = max_stake.saturating_mul(::MinCollators::get().into()); + assert_eq!(total_collator_stake, StakePallet::total_collator_stake().collators); + assert!(Balances::free_balance(&TREASURY_ACC).is_zero()); + let total_issuance = ::Currency::total_issuance(); + + // total issuance should not increase when not noting authors because we haven't + // reached NetworkRewardStart yet + roll_to(10, vec![None]); + assert!(Balances::free_balance(&TREASURY_ACC).is_zero()); + assert_eq!(total_issuance, ::Currency::total_issuance()); + + // set current block to one block before NetworkRewardStart + let network_reward_start = ::NetworkRewardStart::get(); + System::set_block_number(network_reward_start.saturating_sub(1)); + + // network rewards should only appear 1 block after start + roll_to(network_reward_start, vec![None]); + assert!(Balances::free_balance(&TREASURY_ACC).is_zero()); + assert_eq!(total_issuance, ::Currency::total_issuance()); + + // should mint to treasury now + roll_to(network_reward_start + 1, vec![None]); + let network_reward = Balances::free_balance(&TREASURY_ACC); + assert!(!network_reward.is_zero()); + assert_eq!( + total_issuance + network_reward, + ::Currency::total_issuance() + ); + let inflation_config = StakePallet::inflation_config(); + let col_rewards = inflation_config.collator.reward_rate.per_block * total_collator_stake; + assert_eq!(network_reward, ::NetworkRewardRate::get() * col_rewards); + + // should mint exactly the same amount + roll_to(network_reward_start + 2, vec![None]); + assert_eq!(2 * network_reward, Balances::free_balance(&TREASURY_ACC)); + assert_eq!( + total_issuance + 2 * network_reward, + ::Currency::total_issuance() + ); + + // should mint exactly the same amount in each block + roll_to(network_reward_start + 100, vec![None]); + assert_eq!(100 * network_reward, Balances::free_balance(&TREASURY_ACC)); + assert_eq!( + total_issuance + 100 * network_reward, + ::Currency::total_issuance() + ); + + // should mint the same amount even if a collator exits because reward is only + // based on MaxCollatorCandidateStake and MaxSelectedCandidates + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(1))); + roll_to(network_reward_start + 101, vec![None]); + assert_eq!(101 * network_reward, Balances::free_balance(&TREASURY_ACC)); + assert_eq!( + total_issuance + 101 * network_reward, + ::Currency::total_issuance() + ); + }); +} + +#[test] +fn network_reward_increase_max_candidate_stake() { + let max_stake: Balance = 160_000_000 * DECIMALS; + let collators: Vec<(AccountId, Balance)> = (1u64..=::MinCollators::get().into()) + .map(|acc_id| (acc_id, max_stake)) + .collect(); + + ExtBuilder::default() + .with_balances(collators.clone()) + .with_collators(collators) + .build() + .execute_with(|| { + let network_reward_start = ::NetworkRewardStart::get(); + let total_issuance = ::Currency::total_issuance(); + System::set_block_number(network_reward_start); + + // should mint to treasury now + roll_to(network_reward_start + 1, vec![None]); + let reward_before = Balances::free_balance(&TREASURY_ACC); + assert!(!reward_before.is_zero()); + assert_eq!( + total_issuance + reward_before, + ::Currency::total_issuance() + ); + + // double max stake + let max_stake_doubled = 320_000_000 * DECIMALS; + let reward_after = 2 * reward_before; + assert_ok!(StakePallet::set_max_candidate_stake( + RuntimeOrigin::root(), + max_stake_doubled + )); + roll_to(network_reward_start + 2, vec![None]); + assert_eq!(reward_before + reward_after, Balances::free_balance(&TREASURY_ACC)); + assert_eq!( + reward_before + reward_after + total_issuance, + ::Currency::total_issuance() + ); + }); +} + +#[test] +fn network_reward_increase_max_collator_count() { + let max_stake: Balance = 160_000_000 * DECIMALS; + let collators: Vec<(AccountId, Balance)> = (1u64..=::MinCollators::get().into()) + .map(|acc_id| (acc_id, max_stake)) + .collect(); + + ExtBuilder::default() + .with_balances(collators.clone()) + .with_collators(collators) + .build() + .execute_with(|| { + let network_reward_start = ::NetworkRewardStart::get(); + let total_issuance = ::Currency::total_issuance(); + System::set_block_number(network_reward_start); + + // should mint to treasury now + roll_to(network_reward_start + 1, vec![None]); + let reward_before = Balances::free_balance(&TREASURY_ACC); + assert!(!reward_before.is_zero()); + assert_eq!( + total_issuance + reward_before, + ::Currency::total_issuance() + ); + + // tripple number of max collators + let reward_after = 3 * reward_before; + assert_ok!(StakePallet::set_max_selected_candidates( + RuntimeOrigin::root(), + ::MinCollators::get() * 3 + )); + roll_to(network_reward_start + 2, vec![None]); + assert_eq!(reward_before + reward_after, Balances::free_balance(&TREASURY_ACC)); + assert_eq!( + reward_before + reward_after + total_issuance, + ::Currency::total_issuance() + ); + }); +} + +#[test] +fn update_total_stake_collators_stay() { + ExtBuilder::default() + .with_balances(vec![(1, 200), (2, 200), (3, 200), (4, 200)]) + .with_collators(vec![(1, 100), (2, 50)]) + .with_delegators(vec![(3, 1, 100), (4, 2, 50)]) + .build() + .execute_with(|| { + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 150, + delegators: 150 + } + ); + assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 10)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 160, + delegators: 150 + } + ); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(2), 5)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 155, + delegators: 150 + } + ); + assert_ok!(StakePallet::delegator_stake_more(RuntimeOrigin::signed(3), 10)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 155, + delegators: 160 + } + ); + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(4), 5)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 155, + delegators: 155 + } + ); + }); +} + +#[test] +fn update_total_stake_displace_collators() { + ExtBuilder::default() + .with_balances(vec![ + (1, 200), + (2, 200), + (3, 200), + (4, 200), + (5, 200), + (6, 200), + (7, 200), + (8, 200), + (1337, 200), + ]) + .with_collators(vec![(1, 10), (2, 20), (3, 30), (4, 40)]) + .with_delegators(vec![(5, 1, 50), (6, 2, 50), (7, 3, 55), (8, 4, 55)]) + .build() + .execute_with(|| { + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 70, + delegators: 110 + } + ); + + // 4 is pushed out by staking less + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(4), 30)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 50, + delegators: 105 + } + ); + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(8), 45)); + + // 3 is pushed out by delegator staking less + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(7), 45)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 30, + delegators: 100 + } + ); + + // 1 is pushed out by new candidate + assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(1337), 100)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 120, + delegators: 50 + } + ); + }); +} + +#[test] +fn update_total_stake_new_collators() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100), (3, 100), (4, 100)]) + .with_collators(vec![(1, 100)]) + .with_delegators(vec![(4, 1, 100)]) + .build() + .execute_with(|| { + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 100, + delegators: 100 + } + ); + assert_ok!(StakePallet::join_candidates(RuntimeOrigin::signed(2), 100)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 200, + delegators: 100 + } + ); + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(3), 2, 50)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 200, + delegators: 150 + } + ); + assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(4))); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 200, + delegators: 50 + } + ); + }); +} + +#[test] +fn update_total_stake_no_collator_changes() { + ExtBuilder::default() + .with_balances(vec![ + (1, 200), + (2, 200), + (3, 200), + (4, 200), + (5, 200), + (6, 200), + (7, 200), + (8, 200), + (1337, 200), + ]) + .with_collators(vec![(1, 10), (2, 20), (3, 30), (4, 40)]) + .with_delegators(vec![(5, 1, 50), (6, 2, 50), (7, 3, 55), (8, 4, 55)]) + .build() + .execute_with(|| { + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 70, + delegators: 110 + } + ); + assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), 10)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 70, + delegators: 110 + } + ); + assert_ok!(StakePallet::delegator_stake_more(RuntimeOrigin::signed(5), 10)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 70, + delegators: 110 + } + ); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(2), 10)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 70, + delegators: 110 + } + ); + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(6), 10)); + assert_eq!( + StakePallet::total_collator_stake(), + TotalStake { + collators: 70, + delegators: 110 + } + ); + }); +} + +#[test] +fn rewards_candidate_stake_more() { + ExtBuilder::default() + .with_balances(vec![(1, 2 * DECIMALS), (2, DECIMALS), (3, DECIMALS)]) + .with_collators(vec![(1, DECIMALS)]) + .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) + .build() + .execute_with(|| { + // note once to set counter to 1 + StakePallet::note_author(1); + assert_eq!(StakePallet::blocks_authored(1), 1); + assert!(StakePallet::blocks_authored(2).is_zero()); + assert!(StakePallet::blocks_authored(3).is_zero()); + (1..=3).for_each(|id| { + assert!(StakePallet::blocks_rewarded(id).is_zero()); + assert!(StakePallet::rewards(id).is_zero()); + }); + + // stake less to trigger reward incrementing for collator + assert_ok!(StakePallet::candidate_stake_more(RuntimeOrigin::signed(1), DECIMALS)); + assert!(!StakePallet::rewards(1).is_zero()); + assert!(!StakePallet::blocks_rewarded(1).is_zero()); + // delegator reward storage should be untouched + (2..=3).for_each(|id| { + assert!( + StakePallet::rewards(id).is_zero(), + "Rewards not zero for acc_id {:?}", + id + ); + assert!( + StakePallet::blocks_rewarded(id).is_zero(), + "BlocksRewaeded not zero for acc_id {:?}", + id + ); + }); + }); +} + +#[test] +fn rewards_candidate_stake_less() { + ExtBuilder::default() + .with_balances(vec![(1, 2 * DECIMALS), (2, DECIMALS), (3, DECIMALS)]) + .with_collators(vec![(1, 2 * DECIMALS)]) + .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) + .build() + .execute_with(|| { + // note once to set counter to 1 + StakePallet::note_author(1); + assert_eq!(StakePallet::blocks_authored(1), 1); + assert!(StakePallet::blocks_authored(2).is_zero()); + assert!(StakePallet::blocks_authored(3).is_zero()); + (1..=3).for_each(|id| { + assert!(StakePallet::blocks_rewarded(id).is_zero()); + assert!(StakePallet::rewards(id).is_zero()); + }); + + // stake less to trigger reward incrementing for collator + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), DECIMALS)); + assert!(!StakePallet::rewards(1).is_zero()); + assert!(!StakePallet::blocks_rewarded(1).is_zero()); + // delegator reward storage should be untouched + (2..=3).for_each(|id| { + assert!( + StakePallet::rewards(id).is_zero(), + "Rewards not zero for acc_id {:?}", + id + ); + assert!( + StakePallet::blocks_rewarded(id).is_zero(), + "BlocksRewaeded not zero for acc_id {:?}", + id + ); + }); + }); +} + +#[test] +fn rewards_candidate_leave_network() { + ExtBuilder::default() + .with_balances(vec![ + (1, 2 * DECIMALS), + (2, DECIMALS), + (3, DECIMALS), + (4, DECIMALS), + (5, DECIMALS), + ]) + .with_collators(vec![(1, 2 * DECIMALS), (4, DECIMALS), (5, DECIMALS)]) + .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) + .build() + .execute_with(|| { + // init does not increment rewards + assert_ok!(StakePallet::init_leave_candidates(RuntimeOrigin::signed(1))); + + // advance two rounds to enable leaving + roll_to( + 10, + vec![ + // we're already in block 1, so cant note_author for block 1 + None, + Some(1), + Some(2), + Some(1), + Some(2), + Some(1), + Some(2), + Some(1), + Some(2), + ], + ); + // Only authored should be bumped for collator, not rewarded + assert_eq!(StakePallet::blocks_authored(1), 4 * 2); + assert!(StakePallet::blocks_rewarded(1).is_zero()); + + // count for delegators should not be incremented + assert!(StakePallet::blocks_rewarded(2).is_zero()); + assert!(StakePallet::blocks_rewarded(3).is_zero()); + + // rewards should not be incremented + (1..=3).for_each(|id| { + assert!(StakePallet::rewards(id).is_zero()); + }); + + // execute leave intent to trigger reward incrementing for collator and + // delegators + assert_ok!(StakePallet::execute_leave_candidates(RuntimeOrigin::signed(1), 1)); + + // reward counting storages should be killed for collator + assert!(StakePallet::blocks_authored(1).is_zero()); + assert!(StakePallet::blocks_rewarded(1).is_zero()); + assert!(!StakePallet::rewards(1).is_zero()); + + // reward counting storages should NOT be killed for delegators + (2..=3).for_each(|id| { + assert!(!StakePallet::rewards(id).is_zero(), "Zero rewards acc_id {:?}", id); + assert_eq!( + StakePallet::blocks_rewarded(id), + 4 * 2, + "Rewarded blocks Delegator {:?} do not match up with exited collator", + id + ); + }); + }); +} + +#[test] +fn rewards_force_remove_candidate() { + ExtBuilder::default() + .with_balances(vec![ + (1, DECIMALS), + (2, DECIMALS), + (3, DECIMALS), + (4, DECIMALS), + (5, DECIMALS), + ]) + .with_collators(vec![(1, DECIMALS), (4, DECIMALS), (5, DECIMALS)]) + .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) + .build() + .execute_with(|| { + // init does not increment rewards + StakePallet::note_author(1); + StakePallet::note_author(2); + + // removing triggers reward increment for collator 1 and delegators 4, 5 + assert_ok!(StakePallet::force_remove_candidate(RuntimeOrigin::root(), 1)); + // rewarded counter storage should be killed for collator + assert!(StakePallet::blocks_authored(1).is_zero()); + assert!(StakePallet::blocks_rewarded(1).is_zero()); + // rewards should be set + assert!(!StakePallet::rewards(1).is_zero()); + + (1..=3).for_each(|id| { + // rewards should be non zero + assert!(!StakePallet::rewards(id).is_zero(), "Zero rewards for acc_id {:?}", id); + // rewards should equal API call + assert_eq!( + StakePallet::get_unclaimed_staking_rewards(&id), + StakePallet::rewards(id) + ); + if id > 1 { + assert_eq!( + StakePallet::blocks_rewarded(id), + 2, + "Rewarded counter does not match for delegator {:?}", + id + ); + } + }); + assert_eq!(StakePallet::get_unclaimed_staking_rewards(&1), StakePallet::rewards(1)); + + (4..=5).for_each(|id| { + assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + assert!(StakePallet::blocks_rewarded(id).is_zero(), "acc_id {:?}", id); + }); + }); +} + +#[test] +fn blocks_rewarded_join_delegators() { + ExtBuilder::default() + .with_balances(vec![(1, 100), (2, 100)]) + .with_collators(vec![(1, 100)]) + .build() + .execute_with(|| { + // note once to set counter to 1 + StakePallet::note_author(1); + assert_eq!(StakePallet::blocks_authored(1), 1); + assert!(StakePallet::blocks_rewarded(1).is_zero()); + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(2), 1, 100)); + // delegator's rewarded counter should equal of collator's authored counter upon + // joining + assert_eq!(StakePallet::blocks_rewarded(2), StakePallet::blocks_authored(1)); + }); +} + +#[test] +fn rewards_delegator_stake_more() { + ExtBuilder::default() + .with_balances(vec![(1, DECIMALS), (2, DECIMALS), (3, 2 * DECIMALS)]) + .with_collators(vec![(1, DECIMALS)]) + .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) + .build() + .execute_with(|| { + // note once to set counter to 1 + StakePallet::note_author(1); + assert_eq!(StakePallet::blocks_authored(1), 1); + assert!(StakePallet::blocks_rewarded(2).is_zero()); + assert!(StakePallet::blocks_rewarded(3).is_zero()); + (1..=3).for_each(|id| { + assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + }); + + // stake less to trigger reward incrementing just for 3 + assert_ok!(StakePallet::delegator_stake_more(RuntimeOrigin::signed(3), DECIMALS)); + // 1 should still have counter 1 but no rewards + assert_eq!(StakePallet::blocks_authored(1), 1); + assert!(StakePallet::blocks_rewarded(1).is_zero()); + assert!(StakePallet::rewards(1).is_zero()); + // 2 should still have neither rewards nor counter + assert!(StakePallet::blocks_rewarded(2).is_zero()); + assert!(StakePallet::rewards(2).is_zero()); + // 3 should have rewards and the same counter as 1 + assert_eq!(StakePallet::blocks_rewarded(3), 1); + assert!(!StakePallet::rewards(3).is_zero()); + }); +} + +#[test] +fn rewards_delegator_stake_less() { + ExtBuilder::default() + .with_balances(vec![(1, DECIMALS), (2, DECIMALS), (3, 2 * DECIMALS)]) + .with_collators(vec![(1, DECIMALS)]) + .with_delegators(vec![(2, 1, DECIMALS), (3, 1, 2 * DECIMALS)]) + .build() + .execute_with(|| { + // note once to set counter to 1 + StakePallet::note_author(1); + assert_eq!(StakePallet::blocks_authored(1), 1); + assert!(StakePallet::blocks_rewarded(2).is_zero()); + assert!(StakePallet::blocks_rewarded(3).is_zero()); + (1..=3).for_each(|id| { + assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + }); + + // stake less to trigger reward incrementing just for 3 + assert_ok!(StakePallet::delegator_stake_less(RuntimeOrigin::signed(3), DECIMALS)); + // 1 should still have counter 1 but no rewards + assert_eq!(StakePallet::blocks_authored(1), 1); + assert!(StakePallet::blocks_rewarded(1).is_zero()); + assert!(StakePallet::rewards(1).is_zero()); + // 2 should still have neither rewards nor counter + assert!(StakePallet::blocks_rewarded(2).is_zero()); + assert!(StakePallet::rewards(2).is_zero()); + // 3 should have rewards and the same counter as 1 + assert_eq!(StakePallet::blocks_rewarded(3), 1); + assert!(!StakePallet::rewards(3).is_zero()); + }); +} + +#[test] +fn rewards_delegator_replaced() { + ExtBuilder::default() + .with_balances(vec![ + (1, 2 * DECIMALS), + (2, 2 * DECIMALS), + (3, 2 * DECIMALS), + (4, 2 * DECIMALS), + (5, 2 * DECIMALS), + (6, 2 * DECIMALS), + ]) + .with_collators(vec![(1, 2 * DECIMALS)]) + .with_delegators(vec![ + (2, 1, 2 * DECIMALS), + (3, 1, 2 * DECIMALS), + (4, 1, 2 * DECIMALS), + (5, 1, DECIMALS), + ]) + .build() + .execute_with(|| { + // note once to set counter to 1 + StakePallet::note_author(1); + assert_eq!(StakePallet::blocks_authored(1), 1); + + // 6 kicks 5 + assert_ok!(StakePallet::join_delegators(RuntimeOrigin::signed(6), 1, 2 * DECIMALS)); + // 5 should have rewards and counter updated + assert!(!StakePallet::rewards(5).is_zero()); + assert_eq!(StakePallet::blocks_rewarded(5), 1); + // 6 should not have rewards but same counter as former collator + assert!(StakePallet::rewards(6).is_zero()); + assert_eq!(StakePallet::blocks_rewarded(6), 1); + }); +} + +#[test] +fn rewards_delegator_leaves() { + ExtBuilder::default() + .with_balances(vec![(1, DECIMALS), (2, DECIMALS), (3, DECIMALS)]) + .with_collators(vec![(1, DECIMALS)]) + .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) + .build() + .execute_with(|| { + // note collator once to set their counter to 1 + StakePallet::note_author(1); + assert_eq!(StakePallet::blocks_authored(1), 1); + assert!(StakePallet::blocks_rewarded(2).is_zero()); + assert!(StakePallet::blocks_rewarded(3).is_zero()); + (1..=3).for_each(|id| { + assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + }); + + // only 3 should have non-zero rewards + assert_ok!(StakePallet::leave_delegators(RuntimeOrigin::signed(3))); + assert!(StakePallet::blocks_rewarded(1).is_zero()); + assert!(StakePallet::rewards(1).is_zero()); + assert!(StakePallet::blocks_rewarded(2).is_zero()); + assert!(StakePallet::rewards(2).is_zero()); + assert!(!StakePallet::rewards(3).is_zero()); + assert_eq!(StakePallet::get_unclaimed_staking_rewards(&3), StakePallet::rewards(3)); + // counter should be reset due to leaving + assert!(StakePallet::blocks_rewarded(3).is_zero()); + }); +} + +#[test] +fn rewards_set_inflation() { + let hundred = Perquintill::from_percent(100); + ExtBuilder::default() + .with_balances(vec![ + (1, DECIMALS), + (2, DECIMALS), + (3, DECIMALS), + (4, DECIMALS), + (5, DECIMALS), + ]) + .with_collators(vec![(1, DECIMALS), (2, DECIMALS)]) + .with_delegators(vec![(3, 1, DECIMALS), (4, 1, DECIMALS), (5, 2, DECIMALS)]) + .build() + .execute_with(|| { + // note collators + StakePallet::note_author(1); + StakePallet::note_author(1); + StakePallet::note_author(2); + + // set inflation to trigger reward setting + assert_ok!(StakePallet::set_inflation( + RuntimeOrigin::root(), + hundred, + hundred, + hundred, + hundred + )); + // rewards and counters should be set + (1..=5).for_each(|id| { + assert!(!StakePallet::blocks_rewarded(id).is_zero(), "acc_id {:?}", id); + assert!(!StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + }); + }); +} + +#[test] +fn rewards_yearly_inflation_adjustment() { + ExtBuilder::default() + .with_balances(vec![ + (1, DECIMALS), + (2, DECIMALS), + (3, DECIMALS), + (4, DECIMALS), + (5, DECIMALS), + ]) + .with_collators(vec![(1, DECIMALS), (2, DECIMALS)]) + .with_delegators(vec![(3, 1, DECIMALS), (4, 1, DECIMALS), (5, 2, DECIMALS)]) + .build() + .execute_with(|| { + // init counter and go to next year + StakePallet::note_author(1); + StakePallet::note_author(2); + System::set_block_number(::BLOCKS_PER_YEAR - 1); + roll_to_claim_rewards(::BLOCKS_PER_YEAR + 1, vec![]); + assert!(!StakePallet::blocks_authored(1).is_zero()); + assert!(!StakePallet::blocks_authored(2).is_zero()); + + // rewards should not be triggered before executing pending adjustment + (1..=5).for_each(|id| { + assert!(StakePallet::rewards(id).is_zero(), "acc_id {:?}", id); + }); + + // execute to trigger reward increment + assert_ok!(StakePallet::execute_scheduled_reward_change(RuntimeOrigin::signed(1))); + (1..=5).for_each(|id| { + assert!( + !StakePallet::blocks_rewarded(id).is_zero(), + "Zero rewarded blocks for acc_id {:?}", + id + ); + assert!(!StakePallet::rewards(id).is_zero(), "Zero rewards for acc_id {:?}", id); + }); + }); +} + +#[test] +fn rewards_incrementing_and_claiming() { + ExtBuilder::default() + .with_balances(vec![(1, DECIMALS), (2, DECIMALS), (3, DECIMALS)]) + .with_collators(vec![(1, DECIMALS)]) + .with_delegators(vec![(2, 1, DECIMALS), (3, 1, DECIMALS)]) + .build() + .execute_with(|| { + // claiming should not be possible with zero counters + (1..=3).for_each(|id| { + assert_noop!( + StakePallet::claim_rewards(RuntimeOrigin::signed(id)), + Error::::RewardsNotFound, + ); + }); + + // note once to set counter to 1 + StakePallet::note_author(1); + assert_eq!(StakePallet::blocks_authored(1), 1); + assert!(StakePallet::blocks_rewarded(2).is_zero()); + + // claiming should not be possible before incrementing rewards + (1..=3).for_each(|id| { + assert_noop!( + StakePallet::claim_rewards(RuntimeOrigin::signed(id)), + Error::::RewardsNotFound + ); + }); + + // increment rewards for 2 and match counter to collator + assert_ok!(StakePallet::increment_delegator_rewards(RuntimeOrigin::signed(2))); + assert_eq!(StakePallet::blocks_rewarded(2), 1); + let rewards_2 = StakePallet::rewards(2); + assert!(!rewards_2.is_zero()); + assert!(StakePallet::blocks_rewarded(3).is_zero()); + assert!(StakePallet::rewards(3).is_zero()); + + // should only update rewards for collator as well + assert_ok!(StakePallet::increment_collator_rewards(RuntimeOrigin::signed(1))); + assert_eq!(StakePallet::blocks_rewarded(1), StakePallet::blocks_authored(1)); + assert!(!StakePallet::rewards(1).is_zero()); + // rewards of 2 should not be changed + assert_eq!(StakePallet::rewards(2), rewards_2); + // 3 should still not have blocks rewarded bumped + assert!(StakePallet::blocks_rewarded(3).is_zero()); + + // claim for 1 to move rewards into balance + assert_ok!(StakePallet::claim_rewards(RuntimeOrigin::signed(1))); + assert!(StakePallet::rewards(1).is_zero()); + // delegator situation should be unchanged + assert!(Balances::free_balance(&1) > DECIMALS); + assert_eq!(Balances::free_balance(&2), DECIMALS); + assert_eq!(Balances::free_balance(&3), DECIMALS); + + // incrementing again should not change anything because collator has not + // authored blocks since last inc + assert_ok!(StakePallet::increment_delegator_rewards(RuntimeOrigin::signed(2))); + assert_eq!(StakePallet::blocks_rewarded(2), 1); + // claim for 2 to move rewards into balance + assert_ok!(StakePallet::claim_rewards(RuntimeOrigin::signed(2))); + assert!(Balances::free_balance(&2) > DECIMALS); + assert!(StakePallet::rewards(2).is_zero()); + assert_eq!(Balances::free_balance(&3), DECIMALS); + + // should not be able to claim for incorrect role + assert_noop!( + StakePallet::increment_collator_rewards(RuntimeOrigin::signed(2)), + Error::::CandidateNotFound + ); + assert_noop!( + StakePallet::increment_delegator_rewards(RuntimeOrigin::signed(1)), + Error::::DelegatorNotFound + ); + }); +} + +#[test] +fn api_get_unclaimed_staking_rewards() { + let stake = 100_000 * DECIMALS; + ExtBuilder::default() + .with_balances(vec![(1, stake), (2, stake), (3, 100 * stake)]) + .with_collators(vec![(1, stake), (3, 2 * stake)]) + .with_delegators(vec![(2, 1, stake)]) + .build() + .execute_with(|| { + let inflation_config = StakePallet::inflation_config(); + + // Increment rewards of 1 and 2 + roll_to(2, vec![None, Some(1)]); + assert_eq!( + StakePallet::get_unclaimed_staking_rewards(&1), + // Multiplying with 2 because there are two authors + inflation_config.collator.reward_rate.per_block * stake * 2 + ); + assert_eq!( + StakePallet::get_unclaimed_staking_rewards(&2), + inflation_config.delegator.reward_rate.per_block * stake * 2 + ); + assert!(StakePallet::get_unclaimed_staking_rewards(&3).is_zero()); + + // Should only increment rewards of 3 + roll_to(3, vec![None, None, Some(3)]); + let rewards_1 = StakePallet::get_unclaimed_staking_rewards(&1); + let rewards_2 = StakePallet::get_unclaimed_staking_rewards(&2); + let rewards_3 = StakePallet::get_unclaimed_staking_rewards(&3); + assert_eq!(2 * rewards_1, rewards_3,); + assert_eq!(rewards_2, inflation_config.delegator.reward_rate.per_block * stake * 2); + + // API and actual claiming should match + assert_ok!(StakePallet::increment_collator_rewards(RuntimeOrigin::signed(1))); + assert_ok!(StakePallet::claim_rewards(RuntimeOrigin::signed(1))); + assert_eq!(rewards_1, Balances::usable_balance(&1)); + assert!(StakePallet::get_unclaimed_staking_rewards(&1).is_zero()); + + assert_ok!(StakePallet::increment_delegator_rewards(RuntimeOrigin::signed(2))); + assert_ok!(StakePallet::claim_rewards(RuntimeOrigin::signed(2))); + assert_eq!(rewards_2, Balances::usable_balance(&2)); + assert!(StakePallet::get_unclaimed_staking_rewards(&2).is_zero()); + + assert_ok!(StakePallet::increment_collator_rewards(RuntimeOrigin::signed(3))); + assert_ok!(StakePallet::claim_rewards(RuntimeOrigin::signed(3))); + assert_eq!(rewards_3 + 98 * stake, Balances::usable_balance(&3)); + assert!(StakePallet::get_unclaimed_staking_rewards(&3).is_zero()); + }); +} + +#[test] +fn api_get_staking_rates() { + let stake = 100_000 * DECIMALS; + ExtBuilder::default() + .with_balances(vec![(1, stake), (2, stake), (3, 2 * stake)]) + .with_collators(vec![(1, stake), (2, stake)]) + .with_delegators(vec![(3, 1, stake)]) + .with_inflation(25, 10, 25, 8, ::BLOCKS_PER_YEAR) + .build() + .execute_with(|| { + let mut rates = StakingRates { + collator_staking_rate: Perquintill::from_percent(50), + collator_reward_rate: Perquintill::from_percent(5), + delegator_staking_rate: Perquintill::from_percent(25), + delegator_reward_rate: Perquintill::from_percent(8), + }; + // collators exceed max staking rate + assert_eq!(rates, StakePallet::get_staking_rates()); + + // candidates stake less to not exceed max staking rate + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(1), stake / 2)); + assert_ok!(StakePallet::candidate_stake_less(RuntimeOrigin::signed(2), stake / 2)); + // delegator stakes more to exceed + assert_ok!(StakePallet::delegator_stake_more(RuntimeOrigin::signed(3), stake)); + rates.collator_staking_rate = Perquintill::from_percent(25); + rates.collator_reward_rate = Perquintill::from_percent(10); + rates.delegator_staking_rate = Perquintill::from_percent(50); + rates.delegator_reward_rate = Perquintill::from_percent(4); + assert_eq!(rates, StakePallet::get_staking_rates()); + }); +} diff --git a/pallets/parachain-staking/src/types.rs b/pallets/parachain-staking/src/types.rs new file mode 100644 index 000000000..0bc0d59ad --- /dev/null +++ b/pallets/parachain-staking/src/types.rs @@ -0,0 +1,321 @@ +// KILT Blockchain – https://botlabs.org +// Copyright (C) 2019-2023 BOTLabs GmbH + +// The KILT Blockchain 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. + +// The KILT Blockchain 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 this program. If not, see . + +// If you feel like getting in touch with us, you can do so at info@botlabs.org + +use frame_support::traits::{Currency, Get}; +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use sp_runtime::{ + traits::{AtLeast32BitUnsigned, CheckedSub, Saturating, Zero}, + RuntimeDebug, +}; +use sp_staking::SessionIndex; +use sp_std::{ + cmp::Ordering, + fmt::Debug, + ops::{Add, Sub}, +}; + +use crate::{set::OrderedSet, Config}; + +/// A struct represented an amount of staked funds. +/// +/// The stake has a destination account (to which the stake is directed) and an +/// amount of funds staked. +#[derive(Default, Clone, Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +#[codec(mel_bound(AccountId: MaxEncodedLen, Balance: MaxEncodedLen))] +pub struct Stake +where + AccountId: Eq + Ord, + Balance: Eq + Ord, +{ + /// The account that is backed by the stake. + pub owner: AccountId, + + /// The amount of backing the `owner` received. + pub amount: Balance, +} + +impl From for Stake +where + A: Eq + Ord, + B: Default + Eq + Ord, +{ + fn from(owner: A) -> Self { + Stake { + owner, + amount: B::default(), + } + } +} + +impl PartialOrd for Stake { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +// We order by stake and only return an equal order, if both account ids match. +// This prevents the same account ids to be in the same OrderedSet. Otherwise, +// it is ordered from greatest to lowest stake (primary) and from first joined +// to last joined (primary). +impl Ord for Stake { + fn cmp(&self, other: &Self) -> Ordering { + match (self.owner.cmp(&other.owner), self.amount.cmp(&other.amount)) { + // enforce unique account ids + (Ordering::Equal, _) => Ordering::Equal, + // prioritize existing members if stakes match + (_, Ordering::Equal) => Ordering::Greater, + // order by stake + (_, ord) => ord, + } + } +} + +/// The activity status of the collator. +#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub enum CandidateStatus { + /// Committed to be online and producing valid blocks (not equivocating) + Active, + /// Staked until the inner round + Leaving(SessionIndex), +} + +impl Default for CandidateStatus { + fn default() -> CandidateStatus { + CandidateStatus::Active + } +} + +#[derive(Encode, Decode, Clone, RuntimeDebug, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +#[scale_info(skip_type_params(MaxDelegatorsPerCandidate))] +#[codec(mel_bound(AccountId: MaxEncodedLen, Balance: MaxEncodedLen))] +/// Global collator state with commission fee, staked funds, and delegations +pub struct Candidate +where + AccountId: Eq + Ord + Debug, + Balance: Eq + Ord + Debug, + MaxDelegatorsPerCandidate: Get + Debug + PartialEq, +{ + /// Account id of the candidate. + pub id: AccountId, + + /// The stake that the candidate put down. + pub stake: Balance, + + /// The delegators that back the candidate. + pub delegators: OrderedSet, MaxDelegatorsPerCandidate>, + + /// The total backing a collator has. + /// + /// Should equal the sum of all delegators stake adding collators stake + pub total: Balance, + + /// The current status of the candidate. Indicates whether a candidate is + /// active or leaving the candidate pool + pub status: CandidateStatus, +} + +impl Candidate +where + A: Ord + Clone + Debug, + B: AtLeast32BitUnsigned + Ord + Copy + Saturating + Debug + Zero, + S: Get + Debug + PartialEq, +{ + pub fn new(id: A, stake: B) -> Self { + let total = stake; + Candidate { + id, + stake, + delegators: OrderedSet::new(), + total, + status: CandidateStatus::default(), // default active + } + } + + pub fn is_active(&self) -> bool { + self.status == CandidateStatus::Active + } + + pub fn is_leaving(&self) -> bool { + matches!(self.status, CandidateStatus::Leaving(_)) + } + + pub fn can_exit(&self, when: u32) -> bool { + matches!(self.status, CandidateStatus::Leaving(at) if at <= when ) + } + + pub fn revert_leaving(&mut self) { + self.status = CandidateStatus::Active; + } + + pub fn stake_more(&mut self, more: B) { + self.stake = self.stake.saturating_add(more); + self.total = self.total.saturating_add(more); + } + + // Returns None if underflow or less == self.stake (in which case collator + // should leave). + pub fn stake_less(&mut self, less: B) -> Option { + if self.stake > less { + self.stake = self.stake.saturating_sub(less); + self.total = self.total.saturating_sub(less); + Some(self.stake) + } else { + None + } + } + + pub fn inc_delegator(&mut self, delegator: A, more: B) { + if let Ok(i) = self.delegators.linear_search(&Stake:: { + owner: delegator, + amount: B::zero(), + }) { + self.delegators + .mutate(|vec| vec[i].amount = vec[i].amount.saturating_add(more)); + self.total = self.total.saturating_add(more); + self.delegators.sort_greatest_to_lowest() + } + } + + pub fn dec_delegator(&mut self, delegator: A, less: B) { + if let Ok(i) = self.delegators.linear_search(&Stake:: { + owner: delegator, + amount: B::zero(), + }) { + self.delegators + .mutate(|vec| vec[i].amount = vec[i].amount.saturating_sub(less)); + self.total = self.total.saturating_sub(less); + self.delegators.sort_greatest_to_lowest() + } + } + + pub fn leave_candidates(&mut self, round: SessionIndex) { + self.status = CandidateStatus::Leaving(round); + } +} + +pub type Delegator = Stake; +impl Delegator +where + AccountId: Eq + Ord + Clone + Debug, + Balance: Copy + Add + Saturating + PartialOrd + Eq + Ord + Debug + Zero + Default + CheckedSub, +{ + /// Returns Ok if the delegation for the + /// collator exists and `Err` otherwise. + pub fn try_clear(&mut self, collator: AccountId) -> Result<(), ()> { + if self.owner == collator { + self.amount = Balance::zero(); + Ok(()) + } else { + Err(()) + } + } + + /// Returns Ok(delegated_amount) if successful, `Err` if delegation was + /// not found. + pub fn try_increment(&mut self, collator: AccountId, more: Balance) -> Result { + if self.owner == collator { + self.amount = self.amount.saturating_add(more); + Ok(self.amount) + } else { + Err(()) + } + } + + /// Returns Ok(Some(delegated_amount)) if successful, `Err` if delegation + /// was not found and Ok(None) if delegated stake would underflow. + pub fn try_decrement(&mut self, collator: AccountId, less: Balance) -> Result, ()> { + if self.owner == collator { + Ok(self.amount.checked_sub(&less).map(|new| { + self.amount = new; + self.amount + })) + } else { + Err(()) + } + } +} + +/// The current round index and transition information. +#[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct RoundInfo { + /// Current round index. + pub current: SessionIndex, + /// The first block of the current round. + pub first: BlockNumber, + /// The length of the current round in blocks. + pub length: BlockNumber, +} + +impl RoundInfo +where + B: Copy + Saturating + From + PartialOrd, +{ + pub fn new(current: SessionIndex, first: B, length: B) -> RoundInfo { + RoundInfo { current, first, length } + } + + /// Checks if the round should be updated. + /// + /// The round should update if `self.length` or more blocks where produced + /// after `self.first`. + pub fn should_update(&self, now: B) -> bool { + let l = now.saturating_sub(self.first); + l >= self.length + } + + /// Starts a new round. + pub fn update(&mut self, now: B) { + self.current = self.current.saturating_add(1u32); + self.first = now; + } +} + +impl Default for RoundInfo +where + B: Copy + Saturating + Add + Sub + From + PartialOrd, +{ + fn default() -> RoundInfo { + RoundInfo::new(0u32, 0u32.into(), 20.into()) + } +} + +/// The total stake of the pallet. +/// +/// The stake includes both collators' and delegators' staked funds. +#[derive(Default, Clone, Encode, Decode, RuntimeDebug, PartialEq, Eq, TypeInfo, MaxEncodedLen)] +pub struct TotalStake { + pub collators: Balance, + pub delegators: Balance, +} + +/// The number of delegations a delegator has done within the last session in +/// which they delegated. +#[derive(Default, Clone, Encode, Decode, Eq, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)] +pub struct DelegationCounter { + /// The index of the last delegation. + pub round: SessionIndex, + /// The number of delegations made within round. + pub counter: u32, +} + +pub type AccountIdOf = ::AccountId; +pub type BalanceOf = <::Currency as Currency>>::Balance; +pub type CandidateOf = Candidate, BalanceOf, S>; +pub type StakeOf = Stake, BalanceOf>; +pub type NegativeImbalanceOf = <::Currency as Currency>>::NegativeImbalance; diff --git a/pallets/sandbox/Cargo.toml b/pallets/sandbox/Cargo.toml index 2fbc67cbf..7fd58da17 100644 --- a/pallets/sandbox/Cargo.toml +++ b/pallets/sandbox/Cargo.toml @@ -40,6 +40,7 @@ sp-runtime.workspace = true pallet-balances.workspace = true pallet-insecure-randomness-collective-flip.workspace = true pallet-assets.workspace = true +pallet-credentials.workspace = true [features] @@ -57,6 +58,7 @@ std = [ "sp-runtime/std", "pallet-assets/std", "pallet-balances/std", + "pallet-credentials/std", "polimec-traits/std", "frame-benchmarking?/std", "parachains-common/std", diff --git a/pallets/sandbox/src/mock.rs b/pallets/sandbox/src/mock.rs index f23912681..b1dacf3bf 100644 --- a/pallets/sandbox/src/mock.rs +++ b/pallets/sandbox/src/mock.rs @@ -50,6 +50,7 @@ frame_support::construct_runtime!( Assets: pallet_assets, Balances: pallet_balances, FundingModule: pallet_funding, + Credentials: pallet_credentials, Sandbox: crate, } ); @@ -105,6 +106,17 @@ impl pallet_balances::Config for TestRuntime { impl pallet_insecure_randomness_collective_flip::Config for TestRuntime {} +impl pallet_credentials::Config for TestRuntime { + type RuntimeEvent = RuntimeEvent; + type AddOrigin = EnsureSigned; + type RemoveOrigin = EnsureSigned; + type SwapOrigin = EnsureSigned; + type ResetOrigin = EnsureSigned; + type PrimeOrigin = EnsureSigned; + type MembershipInitialized = (); + type MembershipChanged = (); +} + impl pallet_assets::Config for TestRuntime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; @@ -155,6 +167,7 @@ impl pallet_funding::Config for TestRuntime { type MaxProjectsToUpdatePerBlock = ConstU32<100>; type CommunityFundingDuration = CommunityRoundDuration; type Randomness = RandomnessCollectiveFlip; + type HandleMembers = Credentials; type PreImageLimit = ConstU32<1024>; // Low value to simplify the tests type MaximumBidsPerUser = ConstU32<4>; @@ -179,6 +192,12 @@ pub fn new_test_ext() -> sp_io::TestExternalities { GenesisConfig { balances: BalancesConfig { balances: vec![] }, + credentials: CredentialsConfig { + issuers: vec![1, 16558220937623665250], + retails: vec![2], + professionals: vec![2, 3], + institutionals: vec![4], + }, ..Default::default() } .assimilate_storage(&mut t) diff --git a/pallets/sandbox/src/tests.rs b/pallets/sandbox/src/tests.rs index c6ef58158..71fdc3562 100644 --- a/pallets/sandbox/src/tests.rs +++ b/pallets/sandbox/src/tests.rs @@ -133,6 +133,12 @@ pub fn new_test_ext() -> sp_io::TestExternalities { (4, 10_000_000 * PLMC), ], }, + credentials: CredentialsConfig { + issuers: vec![1, 16558220937623665250], + retails: vec![2], + professionals: vec![2, 3], + institutionals: vec![4], + }, ..Default::default() } .assimilate_storage(&mut t) diff --git a/runtime-api/credentials/Cargo.toml b/runtime-api/credentials/Cargo.toml new file mode 100644 index 000000000..6874844cf --- /dev/null +++ b/runtime-api/credentials/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = 'polimec-runtime-api-credentials' +description = "Runtime APIs for dealing with credentials and membership." +authors.workspace = true +documentation.workspace = true +edition.workspace = true +homepage.workspace = true +license-file.workspace = true +readme.workspace = true +repository.workspace = true +version.workspace = true + + +[dependencies] +parity-scale-codec = { workspace = true, features = [ + "derive", +] } +scale-info = { workspace = true, features = ["derive"] } + +sp-runtime.workspace = true +sp-api.workspace = true +sp-std.workspace = true +polimec-traits.workspace = true + + +[features] +default = ["std"] +std = [ + "sp-api/std", + "parity-scale-codec/std", + "scale-info/std", + "sp-std/std", + "sp-runtime/std", + "polimec-traits/std", +] diff --git a/runtime-api/staking/Cargo.toml b/runtime-api/staking/Cargo.toml new file mode 100644 index 000000000..ff0109a09 --- /dev/null +++ b/runtime-api/staking/Cargo.toml @@ -0,0 +1,23 @@ +[package] +version = "0.1.0" +authors = ["KILT "] +edition = "2021" +repository = 'https://github.com/polimec/polimec-node' +name = "kilt-runtime-api-staking" +description = "Runtime APIs for dealing with parachain staking." + +[dependencies] +# External dependencies +parity-scale-codec = { workspace = true, features = [ + "derive", +] } +scale-info = { workspace = true, features = ["derive"] } + +# Substrate dependencies +sp-api.workspace = true +sp-runtime.workspace = true + + +[features] +default = ["std"] +std = ["parity-scale-codec/std", "sp-api/std", "sp-runtime/std", "scale-info/std"] diff --git a/runtime-api/staking/src/lib.rs b/runtime-api/staking/src/lib.rs new file mode 100644 index 000000000..197ee3502 --- /dev/null +++ b/runtime-api/staking/src/lib.rs @@ -0,0 +1,46 @@ +// KILT Blockchain – https://botlabs.org +// Copyright (C) 2019-2023 BOTLabs GmbH + +// The KILT Blockchain 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. + +// The KILT Blockchain 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 this program. If not, see . + +// If you feel like getting in touch with us, you can do so at info@botlabs.org + +#![cfg_attr(not(feature = "std"), no_std)] + +use parity_scale_codec::{Codec, Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use sp_runtime::Perquintill; + +#[derive(Decode, Encode, TypeInfo, MaxEncodedLen, PartialEq, Eq, Debug)] +pub struct StakingRates { + pub collator_staking_rate: Perquintill, + pub collator_reward_rate: Perquintill, + pub delegator_staking_rate: Perquintill, + pub delegator_reward_rate: Perquintill, +} + +sp_api::decl_runtime_apis! { + /// The API to query staking and reward rates. + pub trait Staking + where + AccountId: Codec, + Balance: Codec + { + /// Returns the current staking rewards for a given account address. + fn get_unclaimed_staking_rewards(account: &AccountId) -> Balance; + /// Returns the current staking and reward rates for collators and + /// delegators. + fn get_staking_rates() -> StakingRates; + } +} diff --git a/runtimes/base/Cargo.toml b/runtimes/base/Cargo.toml index 73809d8af..8f9a0d5d2 100644 --- a/runtimes/base/Cargo.toml +++ b/runtimes/base/Cargo.toml @@ -25,6 +25,8 @@ scale-info = { version = "2.3.1", default-features = false, features = [ smallvec = "1.10.0" # Local +runtime-common.workspace = true +parachain-staking.workspace = true # Substrate frame-benchmarking = { workspace = true, optional = true } @@ -80,7 +82,7 @@ polkadot-primitives.workspace = true [features] default = ["std"] -fast-gov = [] +fast-gov = ["runtime-common/fast-gov"] std = [ "polkadot-primitives/std", "frame-benchmarking?/std", @@ -108,6 +110,7 @@ std = [ "pallet-transaction-payment-rpc-runtime-api/std", "pallet-transaction-payment/std", "pallet-treasury/std", + "parachain-staking/std", "pallet-xcm/std", "parachain-info/std", "polkadot-parachain/std", @@ -126,6 +129,7 @@ std = [ "xcm-builder/std", "xcm-executor/std", "xcm/std", + "runtime-common/std", ] runtime-benchmarks = [ @@ -141,6 +145,7 @@ runtime-benchmarks = [ "xcm-builder/runtime-benchmarks", "cumulus-pallet-session-benchmarking/runtime-benchmarks", "cumulus-pallet-xcmp-queue/runtime-benchmarks", + "runtime-common/runtime-benchmarks", ] try-runtime = [ @@ -161,4 +166,5 @@ try-runtime = [ "pallet-transaction-payment/try-runtime", "pallet-xcm/try-runtime", "parachain-info/try-runtime", + "runtime-common/try-runtime", ] diff --git a/runtimes/base/src/currency.rs b/runtimes/base/src/currency.rs deleted file mode 100644 index 3d89c4f25..000000000 --- a/runtimes/base/src/currency.rs +++ /dev/null @@ -1,14 +0,0 @@ -use crate::Balance; - -/// One PLMC -pub const PLMC: Balance = 10u128.pow(10); -/// 0.001 PLMC -pub const MILLI_PLMC: Balance = 10u128.pow(7); -/// 0.000_001 PLMC -pub const MICRO_PLMC: Balance = 10u128.pow(4); - -pub const EXISTENTIAL_DEPOSIT: Balance = MILLI_PLMC; - -pub const fn deposit(items: u32, bytes: u32) -> Balance { - (items as Balance * 20 * PLMC + (bytes as Balance) * 100 * MICRO_PLMC) / 100 -} \ No newline at end of file diff --git a/runtimes/base/src/lib.rs b/runtimes/base/src/lib.rs index 230849198..6f2b46cf7 100644 --- a/runtimes/base/src/lib.rs +++ b/runtimes/base/src/lib.rs @@ -53,16 +53,17 @@ use sp_std::prelude::*; use sp_version::NativeVersion; use sp_version::RuntimeVersion; // XCM Imports -use parachains_common::AVERAGE_ON_INITIALIZE_RATIO; -use parachains_common::HOURS; -use parachains_common::MAXIMUM_BLOCK_WEIGHT; -use parachains_common::NORMAL_DISPATCH_RATIO; -use parachains_common::SLOT_DURATION; -use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; use xcm::latest::prelude::BodyId; -use xcm_config::{XcmConfig, XcmOriginToTransactDispatchOrigin}; use xcm_executor::XcmExecutor; +pub use runtime_common::constants::*; +use runtime_common::{ + fees::{ToAuthor, WeightToFee}, + FeeSplit, +}; +use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; +use xcm_config::{XcmConfig, XcmOriginToTransactDispatchOrigin}; + // Make the WASM binary available. #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); @@ -126,123 +127,16 @@ pub type CheckedExtrinsic = generic::CheckedExtrinsic, Runtime, AllPalletsWithSystem>; -pub mod fee { - use super::{currency::MICRO_PLMC, Balance, ExtrinsicBaseWeight}; - use frame_support::weights::{Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}; - use smallvec::smallvec; - use sp_arithmetic::traits::{BaseArithmetic, Unsigned}; - use sp_runtime::{Perbill, SaturatedConversion}; - - /// Handles converting a weight scalar to a fee value, based on the scale and granularity of the - /// node's balance type. - /// - /// This should typically create a mapping between the following ranges: - /// - `[0, MAXIMUM_BLOCK_WEIGHT]` - /// - `[Balance::min, Balance::max]` - /// - /// Yet, it can be used for any other sort of change to weight-fee. Some examples being: - /// - Setting it to `0` will essentially disable the weight fee. - /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. - pub struct WeightToFee; - impl frame_support::weights::WeightToFee for WeightToFee { - type Balance = Balance; - - fn weight_to_fee(weight: &Weight) -> Self::Balance { - let ref_time = Balance::saturated_from(weight.ref_time()); - let proof_size = Balance::saturated_from(weight.proof_size()); - - let ref_polynomial = RefTimeToFee::polynomial(); - let proof_polynomial = ProofSizeToFee::polynomial(); - - // Get fee amount from ref_time based on the RefTime polynomial - let ref_fee: Balance = ref_polynomial - .iter() - .fold(0, |acc, term| term.saturating_eval(acc, ref_time)); - - // Get fee amount from proof_size based on the ProofSize polynomial - let proof_fee: Balance = proof_polynomial - .iter() - .fold(0, |acc, term| term.saturating_eval(acc, proof_size)); - - // Take the maximum instead of the sum to charge by the more scarce resource. - ref_fee.max(proof_fee) - } - } - - /// Maps the Ref time component of `Weight` to a fee. - pub struct RefTimeToFee; - impl WeightToFeePolynomial for RefTimeToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 MILLIUNIT: - // in our template, we map to 1/10 of that, or 1/10 MILLIUNIT - let p = MILLIUNIT / 10; - let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); - smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } - } - - /// Maps the proof size component of `Weight` to a fee. - pub struct ProofSizeToFee; - impl WeightToFeePolynomial for ProofSizeToFee { - type Balance = Balance; - fn polynomial() -> WeightToFeeCoefficients { - // Map 10kb proof to 1 CENT. - let p = MILLIUNIT / 10; - let q = 10_000; - - smallvec![WeightToFeeCoefficient { - degree: 1, - negative: false, - coeff_frac: Perbill::from_rational(p % q, q), - coeff_integer: p / q, - }] - } - } - - // TODO: Refactor out this code to use `FeePolynomial` on versions using polkadot-v0.9.42 and above: - pub trait WeightCoefficientCalc { - fn saturating_eval(&self, result: Balance, x: Balance) -> Balance; - } - - impl WeightCoefficientCalc for WeightToFeeCoefficient - where - Balance: BaseArithmetic + From + Copy + Unsigned + SaturatedConversion, - { - fn saturating_eval(&self, mut result: Balance, x: Balance) -> Balance { - let power = x.saturating_pow(self.degree.into()); - - let frac = self.coeff_frac * power; // Overflow safe since coeff_frac is strictly less than 1. - let integer = self.coeff_integer.saturating_mul(power); - // Do not add them together here to avoid an underflow. - - if self.negative { - result = result.saturating_sub(frac); - result = result.saturating_sub(integer); - } else { - result = result.saturating_add(frac); - result = result.saturating_add(integer); - } - - result - } - } -} - /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know /// the specifics of the runtime. They can then be made to be agnostic over specific formats /// of data like extrinsics, allowing for them to continue syncing the network through upgrades /// to even the core data structures. pub mod opaque { - use super::*; + pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; use sp_runtime::{generic, traits::BlakeTwo256}; - pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; + use super::*; + /// Opaque block header type. pub type Header = generic::Header; /// Opaque block type. @@ -373,7 +267,7 @@ impl pallet_timestamp::Config for Runtime { impl pallet_authorship::Config for Runtime { type FindAuthor = pallet_session::FindAccountFromAuthorIndex; - type EventHandler = (); + type EventHandler = ParachainStaking; } parameter_types! { @@ -401,11 +295,12 @@ parameter_types! { impl pallet_transaction_payment::Config for Runtime { type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter>; - type WeightToFee = WeightToFee; - type LengthToFee = ConstantMultiplier; + type OnChargeTransaction = + pallet_transaction_payment::CurrencyAdapter>>; + type OperationalFeeMultiplier = runtime_common::constants::fee::OperationalFeeMultiplier; + type WeightToFee = WeightToFee; + type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; - type OperationalFeeMultiplier = ConstU8<5>; } parameter_types! { @@ -456,9 +351,9 @@ impl pallet_session::Config for Runtime { type RuntimeEvent = RuntimeEvent; type ValidatorId = AccountId; type ValidatorIdOf = ConvertInto; - type ShouldEndSession = (); - type NextSessionRotation = (); - type SessionManager = (); + type ShouldEndSession = ParachainStaking; + type NextSessionRotation = ParachainStaking; + type SessionManager = ParachainStaking; type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; // type WeightInfo = weights::pallet_session::WeightInfo; @@ -509,6 +404,33 @@ impl pallet_treasury::Config for Runtime { type MaxApprovals = MaxApprovals; } +impl parachain_staking::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type CurrencyBalance = Balance; + + type MinBlocksPerRound = runtime_common::constants::staking::MinBlocksPerRound; + type DefaultBlocksPerRound = runtime_common::constants::staking::DefaultBlocksPerRound; + type StakeDuration = runtime_common::constants::staking::StakeDuration; + type ExitQueueDelay = runtime_common::constants::staking::ExitQueueDelay; + type MinCollators = runtime_common::constants::staking::MinCollators; + type MinRequiredCollators = runtime_common::constants::staking::MinRequiredCollators; + type MaxDelegationsPerRound = runtime_common::constants::staking::MaxDelegationsPerRound; + type MaxDelegatorsPerCollator = runtime_common::constants::staking::MaxDelegatorsPerCollator; + type MinCollatorStake = runtime_common::constants::staking::MinCollatorStake; + type MinCollatorCandidateStake = runtime_common::constants::staking::MinCollatorStake; + type MaxTopCandidates = runtime_common::constants::staking::MaxCollatorCandidates; + type MinDelegatorStake = runtime_common::constants::staking::MinDelegatorStake; + type MaxUnstakeRequests = runtime_common::constants::staking::MaxUnstakeRequests; + type NetworkRewardRate = runtime_common::constants::staking::NetworkRewardRate; + type NetworkRewardStart = runtime_common::constants::staking::NetworkRewardStart; + type NetworkRewardBeneficiary = Treasury; + // type WeightInfo = weights::parachain_staking::WeightInfo; + type WeightInfo = (); + + const BLOCKS_PER_YEAR: Self::BlockNumber = runtime_common::constants::BLOCKS_PER_YEAR; +} + impl pallet_sudo::Config for Runtime { type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; @@ -538,6 +460,7 @@ construct_runtime!( // Dependencies: AuraExt on Aura, Authorship and Session on ParachainStaking Aura: pallet_aura = 23, Session: pallet_session = 22, + ParachainStaking: parachain_staking = 21, Authorship: pallet_authorship = 20, AuraExt: cumulus_pallet_aura_ext = 24, @@ -763,8 +686,7 @@ struct CheckInherents; impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { fn check_inherents( - block: &Block, - relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, + block: &Block, relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, ) -> sp_inherents::CheckInherentsResult { let relay_chain_slot = relay_state_proof .read_slot() diff --git a/runtimes/common/Cargo.toml b/runtimes/common/Cargo.toml new file mode 100644 index 000000000..f4ae2a40e --- /dev/null +++ b/runtimes/common/Cargo.toml @@ -0,0 +1,90 @@ +[package] +authors.workspace = true +documentation.workspace = true +edition.workspace = true +homepage.workspace = true +license-file.workspace = true +readme.workspace = true +repository.workspace = true +version.workspace = true +name = "runtime-common" +description = "Common interfaces, types, constants and functionality for all Polimec runtimes." + +[dev-dependencies] +sp-io = { workspace = true, features = ["std"] } + +[dependencies] +# External dependencies +parity-scale-codec = { workspace = true, features = [ + "derive", +] } +log.workspace = true +scale-info = { workspace = true, features = ["derive"] } +smallvec.workspace = true + +# Internal dependencies +parachain-staking.workspace = true +did.workspace = true +dip-support.workspace = true +pallet-did-lookup = { workspace = true, optional = true } +pallet-dip-consumer.workspace = true +pallet-dip-provider.workspace = true + +# Substrate dependencies +frame-support.workspace = true +frame-system.workspace = true +pallet-authorship.workspace = true +pallet-balances.workspace = true +pallet-transaction-payment.workspace = true +sp-consensus-aura.workspace = true +sp-core.workspace = true +sp-io.workspace = true +sp-trie.workspace = true +sp-runtime.workspace = true +sp-std.workspace = true +pallet-membership.workspace = true + +# Cumulus dependencies +cumulus-primitives-core.workspace = true + +# Polkadot dependencies +polkadot-parachain.workspace = true +xcm.workspace = true +xcm-builder.workspace = true +xcm-executor.workspace = true +parachains-common.workspace = true + +[features] +default = ["std"] +fast-gov = [] +runtime-benchmarks = [ + "frame-support/runtime-benchmarks", + "parachain-staking/runtime-benchmarks", + "polkadot-parachain/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", +] +std = [ + "parity-scale-codec/std", + "frame-support/std", + "frame-system/std", + "cumulus-primitives-core/std", + "pallet-authorship/std", + "pallet-balances/std", + "pallet-transaction-payment/std", + "pallet-membership/std", + "parachain-staking/std", + "polkadot-parachain/std", + "scale-info/std", + "sp-consensus-aura/std", + "sp-core/std", + "sp-io/std", + "sp-runtime/std", + "sp-std/std", + "xcm-builder/std", + "xcm-executor/std", + "xcm/std", + "parachains-common/std", + "dip-support/std", +] +try-runtime = ["frame-support/try-runtime"] diff --git a/runtimes/common/src/constants.rs b/runtimes/common/src/constants.rs new file mode 100644 index 000000000..72e961558 --- /dev/null +++ b/runtimes/common/src/constants.rs @@ -0,0 +1,358 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +use frame_support::{ + parameter_types, + traits::WithdrawReasons, + weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}, +}; +use sp_runtime::{Perbill, Percent, Perquintill}; + +pub use parachain_staking::InflationInfo; + +use crate::{Balance, BlockNumber}; + +/// This determines the average expected block time that we are targetting. +/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`. +/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked +/// up by `pallet_aura` to implement `fn slot_duration()`. +/// +/// Change this to adjust the block time. +pub const MILLISECS_PER_BLOCK: u64 = 12_000; + +pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; + +// Time is measured by number of blocks. +pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); +pub const HOURS: BlockNumber = MINUTES * 60; +pub const DAYS: BlockNumber = HOURS * 24; +// Julian year as Substrate handles it +pub const BLOCKS_PER_YEAR: BlockNumber = DAYS * 36525 / 100; + +pub const MAX_COLLATOR_STAKE: Balance = 200_000 * PLMC; + +/// One PLMC +pub const PLMC: Balance = 10u128.pow(10); + +/// 0.001 PLMC +pub const MILLI_PLMC: Balance = 10u128.pow(7); + +/// 0.000_001 PLMC +pub const MICRO_PLMC: Balance = 10u128.pow(4); + +pub const EXISTENTIAL_DEPOSIT: Balance = 10 * MILLI_PLMC; + +// 1 in 4 blocks (on average, not counting collisions) will be primary babe +// blocks. +pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4); + +/// We assume that ~10% of the block weight is consumed by `on_initalize` +/// handlers. This is used to limit the maximal weight of a single extrinsic. +pub const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(10); +/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be +/// used by Operational extrinsics. +pub const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); +/// We allow for 0.5 of a second of compute with a 12 second average block time. +pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_ref_time(WEIGHT_REF_TIME_PER_SECOND) + .saturating_div(2) + .set_proof_size(cumulus_primitives_core::relay_chain::MAX_POV_SIZE as u64); + +pub const INFLATION_CONFIG: (Perquintill, Perquintill, Perquintill, Perquintill) = ( + // max collator staking rate + Perquintill::from_percent(40), + // collator reward rate + Perquintill::from_percent(10), + // max delegator staking rate + Perquintill::from_percent(10), + // delegator reward rate + Perquintill::from_percent(8), +); + +/// Inflation configuration which is used at genesis +pub fn polimec_inflation_config() -> InflationInfo { + InflationInfo::new( + BLOCKS_PER_YEAR.into(), + // max collator staking rate + Perquintill::from_percent(40), + // collator reward rate + Perquintill::from_percent(10), + // max delegator staking rate + Perquintill::from_percent(10), + // delegator reward rate + Perquintill::from_percent(8), + ) +} + +/// Calculate the storage deposit based on the number of storage items and the +/// combined byte size of those items. +pub const fn deposit(items: u32, bytes: u32) -> Balance { + items as Balance * 56 * MILLI_PLMC + (bytes as Balance) * 50 * MICRO_PLMC +} + +/// The size of an index in the index pallet. +/// The size is checked in the runtime by a test. +pub const MAX_INDICES_BYTE_LENGTH: u32 = 49; + +/// Copied from Kusama & Polkadot runtime +pub const MAX_VESTING_SCHEDULES: u32 = 28; + +parameter_types! { + /// Vesting Pallet. Copied from Kusama & Polkadot runtime + pub const MinVestedTransfer: Balance = 100 * MILLI_PLMC; + /// Deposits per byte + pub const ByteDeposit: Balance = deposit(0, 1); + /// Index Pallet. Deposit taken for an account index + pub const IndicesDeposit: Balance = deposit(1, MAX_INDICES_BYTE_LENGTH); + /// CType Pallet. Per byte fee for a ctype. + pub const CtypeFee: Balance = MILLI_PLMC; + pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons = + WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); +} + +pub mod delegation { + use super::*; + + pub const DELEGATION_DEPOSIT: Balance = PLMC; + pub const MAX_SIGNATURE_BYTE_LENGTH: u16 = 64; + pub const MAX_PARENT_CHECKS: u32 = 5; + pub const MAX_REVOCATIONS: u32 = 5; + pub const MAX_REMOVALS: u32 = MAX_REVOCATIONS; + pub const MAX_CHILDREN: u32 = 1000; + + parameter_types! { + pub const MaxSignatureByteLength: u16 = MAX_SIGNATURE_BYTE_LENGTH; + pub const MaxParentChecks: u32 = MAX_PARENT_CHECKS; + pub const MaxRevocations: u32 = MAX_REVOCATIONS; + pub const MaxRemovals: u32 = MAX_REMOVALS; + #[derive(Clone)] + pub const MaxChildren: u32 = MAX_CHILDREN; + pub const DelegationDeposit: Balance = DELEGATION_DEPOSIT; + } +} + +pub mod staking { + use super::*; + + /// Minimum round length is 1 hour (300 * 12 second block times) + #[cfg(feature = "fast-gov")] + pub const MIN_BLOCKS_PER_ROUND: BlockNumber = 10; + #[cfg(not(feature = "fast-gov"))] + pub const MIN_BLOCKS_PER_ROUND: BlockNumber = HOURS; + + #[cfg(feature = "fast-gov")] + pub const DEFAULT_BLOCKS_PER_ROUND: BlockNumber = 20; + #[cfg(not(feature = "fast-gov"))] + pub const DEFAULT_BLOCKS_PER_ROUND: BlockNumber = 2 * HOURS; + + #[cfg(feature = "fast-gov")] + pub const STAKE_DURATION: BlockNumber = 30; + #[cfg(not(feature = "fast-gov"))] + pub const STAKE_DURATION: BlockNumber = 7 * DAYS; + + #[cfg(feature = "fast-gov")] + pub const MIN_COLLATORS: u32 = 4; + #[cfg(not(feature = "fast-gov"))] + pub const MIN_COLLATORS: u32 = 16; + + #[cfg(feature = "fast-gov")] + pub const MAX_CANDIDATES: u32 = 16; + #[cfg(not(feature = "fast-gov"))] + pub const MAX_CANDIDATES: u32 = 75; + + pub const MAX_DELEGATORS_PER_COLLATOR: u32 = 35; + pub const MIN_DELEGATOR_STAKE: Balance = 20 * PLMC; + + pub const NETWORK_REWARD_RATE: Perquintill = Perquintill::from_percent(10); + + parameter_types! { + /// Minimum round length is 1 hour + pub const MinBlocksPerRound: BlockNumber = MIN_BLOCKS_PER_ROUND; + /// Default length of a round/session is 2 hours + pub const DefaultBlocksPerRound: BlockNumber = DEFAULT_BLOCKS_PER_ROUND; + /// Unstaked balance can be unlocked after 7 days + pub const StakeDuration: BlockNumber = STAKE_DURATION; + /// Collator exit requests are delayed by 4 hours (2 rounds/sessions) + pub const ExitQueueDelay: u32 = 2; + /// Minimum 16 collators selected per round, default at genesis and minimum forever after + pub const MinCollators: u32 = MIN_COLLATORS; + /// At least 4 candidates which cannot leave the network if there are no other candidates. + pub const MinRequiredCollators: u32 = 4; + /// We only allow one delegation per round. + pub const MaxDelegationsPerRound: u32 = 1; + /// Maximum 25 delegators per collator at launch, might be increased later + #[derive(Debug, Eq, PartialEq)] + pub const MaxDelegatorsPerCollator: u32 = MAX_DELEGATORS_PER_COLLATOR; + /// Minimum stake required to be reserved to be a collator is 10_000 + pub const MinCollatorStake: Balance = 10_000 * PLMC; + /// Minimum stake required to be reserved to be a delegator is 1000 + pub const MinDelegatorStake: Balance = MIN_DELEGATOR_STAKE; + /// Maximum number of collator candidates + #[derive(Debug, Eq, PartialEq)] + pub const MaxCollatorCandidates: u32 = MAX_CANDIDATES; + /// Maximum number of concurrent requests to unlock unstaked balance + pub const MaxUnstakeRequests: u32 = 10; + /// The starting block number for the network rewards + pub const NetworkRewardStart: BlockNumber = super::treasury::INITIAL_PERIOD_LENGTH; + /// The rate in percent for the network rewards + pub const NetworkRewardRate: Perquintill = NETWORK_REWARD_RATE; + } +} + +pub mod governance { + use super::*; + + pub const MIN_DEPOSIT: Balance = PLMC; + + #[cfg(feature = "fast-gov")] + pub const LAUNCH_PERIOD: BlockNumber = 7 * MINUTES; + #[cfg(not(feature = "fast-gov"))] + pub const LAUNCH_PERIOD: BlockNumber = 7 * DAYS; + + #[cfg(feature = "fast-gov")] + pub const VOTING_PERIOD: BlockNumber = 7 * MINUTES; + #[cfg(not(feature = "fast-gov"))] + pub const VOTING_PERIOD: BlockNumber = 7 * DAYS; + + #[cfg(feature = "fast-gov")] + pub const FAST_TRACK_VOTING_PERIOD: BlockNumber = 3 * MINUTES; + #[cfg(not(feature = "fast-gov"))] + pub const FAST_TRACK_VOTING_PERIOD: BlockNumber = 3 * HOURS; + + #[cfg(feature = "fast-gov")] + pub const ENACTMENT_PERIOD: BlockNumber = 8 * MINUTES; + #[cfg(not(feature = "fast-gov"))] + pub const ENACTMENT_PERIOD: BlockNumber = DAYS; + + #[cfg(feature = "fast-gov")] + pub const COOLOFF_PERIOD: BlockNumber = 7 * MINUTES; + #[cfg(not(feature = "fast-gov"))] + pub const COOLOFF_PERIOD: BlockNumber = 7 * DAYS; + + #[cfg(feature = "fast-gov")] + pub const SPEND_PERIOD: BlockNumber = 6 * MINUTES; + #[cfg(not(feature = "fast-gov"))] + pub const SPEND_PERIOD: BlockNumber = 6 * DAYS; + + #[cfg(feature = "fast-gov")] + pub const ROTATION_PERIOD: BlockNumber = 80 * MINUTES; + #[cfg(not(feature = "fast-gov"))] + pub const ROTATION_PERIOD: BlockNumber = 80 * HOURS; + + #[cfg(feature = "fast-gov")] + pub const TERM_DURATION: BlockNumber = 15 * MINUTES; + #[cfg(not(feature = "fast-gov"))] + pub const TERM_DURATION: BlockNumber = DAYS; + + #[cfg(feature = "fast-gov")] + pub const COUNCIL_MOTION_DURATION: BlockNumber = 4 * MINUTES; + #[cfg(not(feature = "fast-gov"))] + pub const COUNCIL_MOTION_DURATION: BlockNumber = 3 * DAYS; + + #[cfg(feature = "fast-gov")] + pub const TECHNICAL_MOTION_DURATION: BlockNumber = 4 * MINUTES; + #[cfg(not(feature = "fast-gov"))] + pub const TECHNICAL_MOTION_DURATION: BlockNumber = 3 * DAYS; + + parameter_types! { + // Democracy Pallet + pub const LaunchPeriod: BlockNumber = LAUNCH_PERIOD; + pub const VotingPeriod: BlockNumber = VOTING_PERIOD; + pub const FastTrackVotingPeriod: BlockNumber = FAST_TRACK_VOTING_PERIOD; + pub const MinimumDeposit: Balance = MIN_DEPOSIT; + pub const EnactmentPeriod: BlockNumber = ENACTMENT_PERIOD; + pub const CooloffPeriod: BlockNumber = COOLOFF_PERIOD; + pub const MaxProposals: u32 = 100; + // Council Pallet + pub const CouncilMotionDuration: BlockNumber = COUNCIL_MOTION_DURATION; + pub const CouncilMaxProposals: u32 = 100; + pub const CouncilMaxMembers: u32 = 100; + // Technical Committee + pub const TechnicalMotionDuration: BlockNumber = TECHNICAL_MOTION_DURATION; + pub const TechnicalMaxProposals: u32 = 100; + pub const TechnicalMaxMembers: u32 = 100; + } +} + +pub mod treasury { + use super::*; + + pub const INITIAL_PERIOD_LENGTH: BlockNumber = BLOCKS_PER_YEAR.saturating_mul(5); + const YEARLY_REWARD: Balance = 2_000_000u128 * PLMC; + pub const INITIAL_PERIOD_REWARD_PER_BLOCK: Balance = YEARLY_REWARD / (BLOCKS_PER_YEAR as Balance); + + parameter_types! { + pub const InitialPeriodLength: BlockNumber = INITIAL_PERIOD_LENGTH; + pub const InitialPeriodReward: Balance = INITIAL_PERIOD_REWARD_PER_BLOCK; + } +} + +pub mod proxy { + use super::*; + + parameter_types! { + // One storage item; key size 32, value size 8; . + pub const ProxyDepositBase: Balance = deposit(1, 8); + // Additional storage item size of 33 bytes. + pub const ProxyDepositFactor: Balance = deposit(0, 33); + pub const MaxProxies: u16 = 10; + pub const AnnouncementDepositBase: Balance = deposit(1, 8); + pub const AnnouncementDepositFactor: Balance = deposit(0, 66); + pub const MaxPending: u16 = 10; + } +} + +pub mod preimage { + use super::*; + + parameter_types! { + pub const PreimageMaxSize: u32 = 4096 * 1024; + pub const PreimageBaseDeposit: Balance = deposit(2, 64); + } +} + +pub mod tips { + use super::*; + + parameter_types! { + pub const MaximumReasonLength: u32 = 16384; + pub const TipCountdown: BlockNumber = DAYS; + pub const TipFindersFee: Percent = Percent::from_percent(20); + pub const TipReportDepositBase: Balance = deposit(1, 1); + } +} + +pub mod fee { + use super::*; + + parameter_types! { + /// This value increases the priority of `Operational` transactions by adding + /// a "virtual tip" that's equal to the `OperationalFeeMultiplier * final_fee`. + pub const OperationalFeeMultiplier: u8 = 5; + pub const TransactionByteFee: Balance = MICRO_PLMC; + } +} + +#[cfg(test)] +mod tests { + use super::*; + + // TODO: static assert + #[allow(clippy::assertions_on_constants)] + #[test] + fn blocks_per_year_saturation() { + assert!(BLOCKS_PER_YEAR < u32::MAX); + } +} diff --git a/runtimes/common/src/fees.rs b/runtimes/common/src/fees.rs new file mode 100644 index 000000000..88f5ebefb --- /dev/null +++ b/runtimes/common/src/fees.rs @@ -0,0 +1,279 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +use frame_support::{ + dispatch::DispatchClass, + traits::{Currency, Get, Imbalance, OnUnbalanced}, + weights::{ + Weight, WeightToFee as WeightToFeeT, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, + }, +}; +use pallet_balances::WeightInfo; +use pallet_transaction_payment::OnChargeTransaction; +use smallvec::smallvec; +use sp_runtime::Perbill; + +use crate::{constants::MILLI_PLMC, AccountId, Balance, NegativeImbalanceOf}; + +/// Split two Imbalances between two unbalanced handlers. +/// The first Imbalance will be split according to the given ratio. The second +/// Imbalance will be handled by the second beneficiary. +/// +/// In case of transaction payment, the first Imbalance is the fee and the +/// second imbalance the tip. +pub struct SplitFeesByRatio( + sp_std::marker::PhantomData<(R, Ratio, Beneficiary1, Beneficiary2)>, +); +impl OnUnbalanced> + for SplitFeesByRatio +where + R: pallet_balances::Config, + Beneficiary1: OnUnbalanced>, + Beneficiary2: OnUnbalanced>, + Ratio: Get<(u32, u32)>, +{ + fn on_unbalanceds(mut fees_then_tips: impl Iterator>) { + let ratio = Ratio::get(); + if let Some(fees) = fees_then_tips.next() { + let mut split = fees.ration(ratio.0, ratio.1); + if let Some(tips) = fees_then_tips.next() { + // for tips, if any, 100% to author + tips.merge_into(&mut split.1); + } + Beneficiary1::on_unbalanced(split.0); + Beneficiary2::on_unbalanced(split.1); + } + } +} + +/// Logic for the author to get a portion of fees. +pub struct ToAuthor(sp_std::marker::PhantomData); + +impl OnUnbalanced> for ToAuthor +where + R: pallet_balances::Config + pallet_authorship::Config, + ::AccountId: From, + ::AccountId: Into, + ::Balance: Into, +{ + fn on_nonzero_unbalanced(amount: NegativeImbalanceOf) { + if let Some(author) = >::author() { + >::resolve_creating(&author, amount); + } + } +} + +/// Handles converting a weight scalar to a fee value, based on the scale and +/// granularity of the node's balance type. +/// +/// This should typically create a mapping between the following ranges: +/// - [0, MAXIMUM_BLOCK_WEIGHT] +/// - [Balance::min, Balance::max] +/// +/// Yet, it can be used for any other sort of change to weight-fee. Some +/// examples being: +/// - Setting it to `0` will essentially disable the weight fee. +/// - Setting it to `1` will cause the literal `#[weight = x]` values to be +/// charged. +pub struct WeightToFee(sp_std::marker::PhantomData); +impl WeightToFeePolynomial for WeightToFee +where + R: pallet_transaction_payment::Config, + R: frame_system::Config, + R: pallet_balances::Config, + u128: From<<::OnChargeTransaction as OnChargeTransaction>::Balance>, +{ + type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { + // The should be fee + let wanted_fee: Balance = 10 * MILLI_PLMC; + + // TODO: transfer_keep_alive is 288 byte long? + let tx_len: u64 = 288; + let byte_fee: Balance = + ::LengthToFee::weight_to_fee(&Weight::from_ref_time(tx_len)) + .into(); + let base_weight: Weight = ::BlockWeights::get() + .get(DispatchClass::Normal) + .base_extrinsic; + let base_weight_fee: Balance = + ::LengthToFee::weight_to_fee(&base_weight).into(); + let tx_weight_fee: Balance = ::LengthToFee::weight_to_fee( + &::WeightInfo::transfer_keep_alive(), + ) + .into(); + let unbalanced_fee: Balance = base_weight_fee.saturating_add(tx_weight_fee); + + let wanted_weight_fee: Balance = wanted_fee.saturating_sub(byte_fee); + + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(wanted_weight_fee % unbalanced_fee, unbalanced_fee), + coeff_integer: wanted_weight_fee / unbalanced_fee, + }] + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{ + AccountId, BlockExecutionWeight, ExtrinsicBaseWeight, AVERAGE_ON_INITIALIZE_RATIO, MAXIMUM_BLOCK_WEIGHT, + NORMAL_DISPATCH_RATIO, + }; + use frame_support::{dispatch::DispatchClass, parameter_types, traits::FindAuthor}; + use frame_system::limits; + use sp_core::H256; + use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, + Perbill, + }; + + type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; + type Block = frame_system::mocking::MockBlock; + + frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Authorship: pallet_authorship::{Pallet, Storage}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + } + ); + + parameter_types! { + pub const BlockHashCount: u64 = 250; + // One to one clone of our runtimes' blockweight + pub BlockWeights: limits::BlockWeights = limits::BlockWeights::builder() + .base_block(BlockExecutionWeight::get()) + .for_class(DispatchClass::all(), |weights| { + weights.base_extrinsic = ExtrinsicBaseWeight::get(); + }) + .for_class(DispatchClass::Normal, |weights| { + weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + }) + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); + // Operational transactions have some extra reserved space, so that they + // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. + weights.reserved = Some( + MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT + ); + }) + .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) + .build_or_panic(); + pub BlockLength: limits::BlockLength = limits::BlockLength::max(2 * 1024); + pub const AvailableBlockRatio: Perbill = Perbill::one(); + } + + impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type RuntimeOrigin = RuntimeOrigin; + type Index = u64; + type BlockNumber = u64; + type RuntimeCall = RuntimeCall; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type BlockLength = BlockLength; + type BlockWeights = BlockWeights; + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; + } + + impl pallet_balances::Config for Test { + type Balance = u64; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = (); + type AccountStore = System; + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type WeightInfo = (); + } + + pub const TREASURY_ACC: AccountId = crate::AccountId::new([1u8; 32]); + const AUTHOR_ACC: AccountId = AccountId::new([2; 32]); + + pub struct ToBeneficiary(); + impl OnUnbalanced> for ToBeneficiary { + fn on_nonzero_unbalanced(amount: NegativeImbalanceOf) { + // Must resolve into existing but better to be safe. + >::resolve_creating(&TREASURY_ACC, amount); + } + } + + pub struct OneAuthor; + impl FindAuthor for OneAuthor { + fn find_author<'a, I>(_: I) -> Option + where + I: 'a, + { + Some(AUTHOR_ACC) + } + } + impl pallet_authorship::Config for Test { + type FindAuthor = OneAuthor; + type EventHandler = (); + } + + pub fn new_test_ext() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + // We use default for brevity, but you can configure as desired if needed. + pallet_balances::GenesisConfig::::default() + .assimilate_storage(&mut t) + .unwrap(); + t.into() + } + + parameter_types! { + pub const Ratio: (u32, u32) = (50, 50); + } + + #[test] + fn test_fees_and_tip_split() { + new_test_ext().execute_with(|| { + let fee = Balances::issue(10); + let tip = Balances::issue(20); + + assert_eq!(Balances::free_balance(TREASURY_ACC), 0); + assert_eq!(Balances::free_balance(AUTHOR_ACC), 0); + + SplitFeesByRatio::>::on_unbalanceds(vec![fee, tip].into_iter()); + + assert_eq!(Balances::free_balance(TREASURY_ACC), 5); + assert_eq!(Balances::free_balance(AUTHOR_ACC), 25); + }); + } +} diff --git a/runtimes/common/src/lib.rs b/runtimes/common/src/lib.rs new file mode 100644 index 000000000..7a2d83e10 --- /dev/null +++ b/runtimes/common/src/lib.rs @@ -0,0 +1,184 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use constants::{AVERAGE_ON_INITIALIZE_RATIO, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO}; +use fees::SplitFeesByRatio; + +pub use sp_consensus_aura::sr25519::AuthorityId; + +pub use opaque::*; + +pub use frame_support::weights::constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; +use frame_support::{ + dispatch::DispatchClass, + parameter_types, + traits::{Contains, ContainsLengthBound, Currency, Get, SortedMembers}, +}; +use frame_system::limits; +use pallet_transaction_payment::{Multiplier, TargetedFeeAdjustment}; +use parachains_common::{Balance, BlockNumber}; +use sp_runtime::{ + generic, + traits::{Bounded, IdentifyAccount, Verify}, + FixedPointNumber, MultiSignature, Perquintill, SaturatedConversion, +}; +use sp_std::marker::PhantomData; + +pub mod constants; +pub mod fees; +pub mod xcm_config; + +/// Opaque types. These are used by the CLI to instantiate machinery that don't +/// need to know the specifics of the runtime. They can then be made to be +/// agnostic over specific formats of data like extrinsics, allowing for them to +/// continue syncing the network through upgrades to even the core data +/// structures. +pub mod opaque { + use super::*; + use sp_runtime::{generic, traits::BlakeTwo256}; + + pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; + /// Opaque block header type. + pub type Header = generic::Header; + /// Opaque block type. + pub type Block = generic::Block; + /// Opaque block identifier type. + pub type BlockId = generic::BlockId; +} + +/// Alias to 512-bit hash when used in the context of a transaction signature on +/// the chain. +pub type Signature = MultiSignature; + +/// Alias to the public key used for this chain, actually a `MultiSigner`. Like +/// the signature, this also isn't a fixed size when encoded, as different +/// cryptos have different size public keys. +pub type AccountPublic = ::Signer; + +/// Alias to the opaque account ID type for this chain, actually a +/// `AccountId32`. This is always 32 bytes. +pub type AccountId = ::AccountId; + +/// The type for looking up accounts. We don't expect more than 4 billion of +/// them, but you never know... +pub type AccountIndex = u32; + +/// Identifier for a chain. 32-bit should be plenty. +pub type ChainId = u32; + +pub type Amount = i128; + +/// Index of a transaction in the chain. +pub type Index = u64; + +/// A hash of some data used by the chain. +pub type Hash = sp_core::H256; + +/// Digest item type. +pub type DigestItem = generic::DigestItem; + +/// A Kilt DID subject identifier. +pub type DidIdentifier = AccountId; + +pub type NegativeImbalanceOf = + as Currency<::AccountId>>::NegativeImbalance; + +// Common constants used in all runtimes. +parameter_types! { + pub const BlockHashCount: BlockNumber = 2400; + /// The portion of the `NORMAL_DISPATCH_RATIO` that we adjust the fees with. Blocks filled less + /// than this will decrease the weight and more will increase. + pub const TargetBlockFullness: Perquintill = Perquintill::from_percent(25); + /// The adjustment variable of the runtime. Higher values will cause `TargetBlockFullness` to + /// change the fees more rapidly. + pub AdjustmentVariable: Multiplier = Multiplier::saturating_from_rational(3, 100_000); + /// Minimum amount of the multiplier. This value cannot be too low. A test case should ensure + /// that combined with `AdjustmentVariable`, we can recover from the minimum. + /// See `multiplier_can_grow_from_zero`. + pub MinimumMultiplier: Multiplier = Multiplier::saturating_from_rational(1, 1_000_000u128); + /// The maximum amount of the multiplier. + pub MaximumMultiplier: Multiplier = Bounded::max_value(); + /// Maximum length of block. Up to 5MB. + pub RuntimeBlockLength: limits::BlockLength = + limits::BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); + /// Block weights base values and limits. + pub RuntimeBlockWeights: limits::BlockWeights = limits::BlockWeights::builder() + .base_block(BlockExecutionWeight::get()) + .for_class(DispatchClass::all(), |weights| { + weights.base_extrinsic = ExtrinsicBaseWeight::get(); + }) + .for_class(DispatchClass::Normal, |weights| { + weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + }) + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); + // Operational transactions have some extra reserved space, so that they + // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. + weights.reserved = Some( + MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT, + ); + }) + .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) + .build_or_panic(); + + /// Fee split ratio between treasury and block author (order is important). + pub const FeeSplitRatio: (u32, u32) = (50, 50); +} + +/// Split the fees using a preconfigured Ratio +/// (`runtime_common::FeeSplitRatio`). +pub type FeeSplit = SplitFeesByRatio; + +/// Parameterized slow adjusting fee updated based on +/// https://w3f-research.readthedocs.io/en/latest/polkadot/Token%20Economics.html#-2.-slow-adjusting-mechanism +pub type SlowAdjustingFeeUpdate = + TargetedFeeAdjustment; + +pub struct Tippers(PhantomData, PhantomData); +impl ContainsLengthBound for Tippers +where + R: pallet_membership::Config, +{ + fn max_len() -> usize { + >::MaxMembers::get().saturated_into() + } + + fn min_len() -> usize { + 0 + } +} + +impl SortedMembers for Tippers +where + R: pallet_membership::Config, + pallet_membership::Pallet: SortedMembers + Contains, +{ + fn sorted_members() -> sp_std::vec::Vec { + pallet_membership::Pallet::::sorted_members() + } + + #[cfg(feature = "runtime-benchmarks")] + fn add(who: &R::AccountId) { + pallet_membership::Members::::mutate(|members| match members.binary_search_by(|m| m.cmp(who)) { + Ok(_) => (), + Err(pos) => members + .try_insert(pos, who.clone()) + .expect("Should not fail to add members"), + }) + } +} diff --git a/runtimes/common/src/xcm_config.rs b/runtimes/common/src/xcm_config.rs new file mode 100644 index 000000000..f685ddc7d --- /dev/null +++ b/runtimes/common/src/xcm_config.rs @@ -0,0 +1,160 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + +use core::marker::PhantomData; + +use frame_support::{log, match_types, parameter_types}; +use polkadot_parachain::primitives::Sibling; +use xcm::{latest::prelude::*, v3::Weight}; +use xcm_builder::{ + AccountId32Aliases, AllowUnpaidExecutionFrom, CurrencyAdapter, IsConcrete, ParentIsPreset, + SiblingParachainConvertsVia, +}; +use xcm_executor::traits::ShouldExecute; + +use crate::AccountId; + +parameter_types! { + // One XCM operation is 1_000_000_000 weight, almost certainly a conservative estimate. + pub UnitWeightCost: u64 = 1_000_000_000; + pub const MaxInstructions: u32 = 100; +} + +match_types! { + // The legislative of our parent (i.e. Polkadot majority vote for Spiritnet). + pub type ParentLegislative: impl Contains = { + MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Legislative, .. }) } + }; +} + +// Note: This might move to polkadot's xcm module. +/// Deny executing the xcm message if it matches any of the Deny filter +/// regardless of anything else. If it passes the Deny and matches one of the +/// Allow cases, then it is let through. +pub struct DenyThenTry(PhantomData<(Deny, Allow)>); + +impl ShouldExecute for DenyThenTry +where + Deny: ShouldExecute, + Allow: ShouldExecute, +{ + fn should_execute( + origin: &MultiLocation, message: &mut [Instruction], max_weight: Weight, weight_credit: &mut Weight, + ) -> Result<(), ()> { + Deny::should_execute(origin, message, max_weight, weight_credit)?; + Allow::should_execute(origin, message, max_weight, weight_credit) + } +} + +/// Explicitly deny ReserveTransfer to the relay chain. Allow calls from the +/// relay chain governance. +pub type XcmBarrier = DenyThenTry< + DenyReserveTransferToRelayChain, + ( + // We don't allow anything from any sibling chain, therefore the following is not included here: + // * TakeWeightCredit + // * AllowTopLevelPaidExecutionFrom + + // We allow everything from the relay chain if it was sent by the relay chain legislative (i.e., democracy + // vote). Since the relaychain doesn't own KILTs and missing fees shouldn't prevent calls from the relaychain + // legislative, we allow unpaid execution. + AllowUnpaidExecutionFrom, + ), +>; + +/// Reserved funds to the relay chain can't return. See https://github.com/paritytech/polkadot/issues/5233 +pub struct DenyReserveTransferToRelayChain; +impl ShouldExecute for DenyReserveTransferToRelayChain { + fn should_execute( + origin: &MultiLocation, message: &mut [Instruction], _max_weight: Weight, _weight_credit: &mut Weight, + ) -> Result<(), ()> { + if message.iter().any(|inst| { + matches!( + inst, + InitiateReserveWithdraw { + reserve: MultiLocation { + parents: 1, + interior: Here + }, + .. + } | DepositReserveAsset { + dest: MultiLocation { + parents: 1, + interior: Here + }, + .. + } | TransferReserveAsset { + dest: MultiLocation { + parents: 1, + interior: Here + }, + .. + } + ) + }) { + return Err(()); // Deny + } + + // Allow reserve transfers to arrive from relay chain + if matches!( + origin, + MultiLocation { + parents: 1, + interior: Here + } + ) && message.iter().any(|inst| matches!(inst, ReserveAssetDeposited { .. })) + { + log::warn!( + target: "xcm::barriers", + "Unexpected ReserveAssetDeposited from the relay chain", + ); + } + // Permit everything else + Ok(()) + } +} + +parameter_types! { + pub const RelayLocation: MultiLocation = MultiLocation::parent(); + pub const HereLocation: MultiLocation = MultiLocation::here(); +} + +/// Type for specifying how a `MultiLocation` can be converted into an +/// `AccountId`. This is used when determining ownership of accounts for asset +/// transacting and when attempting to use XCM `Transact` in order to determine +/// the dispatch Origin. +pub type LocationToAccountId = ( + // The parent (Relay-chain) origin converts to the b"parent" `AccountId`. + ParentIsPreset, + // Sibling parachain origins convert to AccountId via the `ParaId::into`. + SiblingParachainConvertsVia, + // Straight up local `AccountId32` origins just alias directly to `AccountId`. + AccountId32Aliases, +); + +/// Means for transacting assets on this chain. +pub type LocalAssetTransactor = CurrencyAdapter< + // Use this currency: + Currency, + // Use this currency when it is a fungible asset matching the given location or name: + IsConcrete, + // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We don't track any teleports. + (), +>; diff --git a/runtimes/standalone/Cargo.toml b/runtimes/standalone/Cargo.toml index d2b067ff1..fc036bdc1 100644 --- a/runtimes/standalone/Cargo.toml +++ b/runtimes/standalone/Cargo.toml @@ -66,14 +66,16 @@ hex-literal = { workspace = true, optional = true } # Local Dependencies pallet-funding.workspace = true +pallet-credentials.workspace = true polimec-traits.workspace = true +runtime-common.workspace = true [build-dependencies] substrate-wasm-builder.workspace = true [features] default = ["std"] -fast-gov = [] +fast-gov = ["runtime-common/fast-gov"] std = [ "frame-benchmarking?/std", "parity-scale-codec/std", @@ -105,6 +107,7 @@ std = [ "sp-std/std", "sp-transaction-pool/std", "sp-version/std", + "pallet-credentials/std", "pallet-funding/std", "pallet-democracy/std", "pallet-collective/std", @@ -114,6 +117,7 @@ std = [ "pallet-insecure-randomness-collective-flip/std", "polimec-traits/std", "pallet-vesting/std", + "runtime-common/std" ] runtime-benchmarks = [ @@ -128,11 +132,13 @@ runtime-benchmarks = [ "sp-runtime/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-collective/runtime-benchmarks", + "pallet-credentials/runtime-benchmarks", "pallet-democracy/runtime-benchmarks", "pallet-funding/runtime-benchmarks", "pallet-scheduler/runtime-benchmarks", "polimec-traits/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", + "runtime-common/runtime-benchmarks" ] try-runtime = [ "frame-executive/try-runtime", @@ -148,6 +154,7 @@ try-runtime = [ "pallet-transaction-payment/try-runtime", "pallet-authorship/try-runtime", "pallet-collective/try-runtime", + "pallet-credentials/try-runtime", "pallet-democracy/try-runtime", "pallet-funding/try-runtime", "pallet-insecure-randomness-collective-flip/try-runtime", @@ -155,4 +162,5 @@ try-runtime = [ "pallet-session/try-runtime", "polimec-traits/try-runtime", "pallet-vesting/try-runtime", + "runtime-common/try-runtime" ] diff --git a/runtimes/testnet/Cargo.toml b/runtimes/testnet/Cargo.toml index 7cb6f4dbc..e526e248d 100644 --- a/runtimes/testnet/Cargo.toml +++ b/runtimes/testnet/Cargo.toml @@ -25,7 +25,11 @@ smallvec.workspace = true # Polimec specific pallet-funding.workspace = true +parachain-staking.workspace = true +pallet-credentials.workspace = true +pallet-asset-registry.workspace = true polimec-traits.workspace = true +runtime-common.workspace = true # KILT specific pallet-dip-consumer.workspace = true @@ -103,7 +107,7 @@ polkadot-primitives.workspace = true [features] default = ["std"] -fast-gov = [] +fast-gov = ["runtime-common/fast-gov"] std = [ "pallet-asset-tx-payment/std", "pallet-assets/std", @@ -127,10 +131,12 @@ std = [ "frame-system/std", "pallet-assets/std", "pallet-asset-tx-payment/std", + "pallet-asset-registry/std", "pallet-aura/std", "pallet-authorship/std", "pallet-balances/std", "pallet-collective/std", + "pallet-credentials/std", "pallet-democracy/std", "pallet-scheduler/std", "pallet-session/std", @@ -147,10 +153,12 @@ std = [ "pallet-preimage/std", "pallet-insecure-randomness-collective-flip/std", "parachains-common/std", + "parachain-staking/std", "parachain-info/std", "polkadot-parachain/std", "polkadot-runtime-common/std", "polimec-traits/std", + "runtime-common/std", "sp-api/std", "sp-block-builder/std", "sp-consensus-aura/std", @@ -187,6 +195,7 @@ runtime-benchmarks = [ "cumulus-pallet-xcmp-queue/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-vesting/runtime-benchmarks", + "runtime-common/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-collective/runtime-benchmarks", ] @@ -210,6 +219,7 @@ try-runtime = [ "pallet-xcm/try-runtime", "parachain-info/try-runtime", "pallet-vesting/try-runtime", + "runtime-common/try-runtime", "pallet-assets/try-runtime", "pallet-asset-tx-payment/try-runtime", ] diff --git a/rust-toolchain.toml b/rust-toolchain.toml index f805bace5..6f5d27ec8 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2022-11-15" +channel = "stable" components = [ "rustfmt", "clippy" ] targets = [ "wasm32-unknown-unknown" ] \ No newline at end of file From 0f1d2e63ff9d3fa3f1b4410276993b87a0693940 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 13:51:00 +0200 Subject: [PATCH 61/80] Revert "chore: remove unused file" This reverts commit 927fd91b7fff682033597416929a569d3633bd16. --- shell.nix | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 shell.nix diff --git a/shell.nix b/shell.nix new file mode 100644 index 000000000..c08005c16 --- /dev/null +++ b/shell.nix @@ -0,0 +1,35 @@ +let + mozillaOverlay = + import (builtins.fetchGit { + url = "https://github.com/mozilla/nixpkgs-mozilla.git"; + rev = "57c8084c7ef41366993909c20491e359bbb90f54"; + }); + pinned = builtins.fetchGit { + # Descriptive name to make the store path easier to identify + url = "https://github.com/nixos/nixpkgs/"; + # Commit hash for nixos-unstable as of 2020-04-26 + # `git ls-remote https://github.com/nixos/nixpkgs nixos-unstable` + ref = "refs/heads/nixos-unstable"; + rev = "1fe6ed37fd9beb92afe90671c0c2a662a03463dd"; + }; + nixpkgs = import pinned { overlays = [ mozillaOverlay ]; }; + toolchain = with nixpkgs; (rustChannelOf { date = "2021-09-14"; channel = "nightly"; }); + rust-wasm = toolchain.rust.override { + targets = [ "wasm32-unknown-unknown" ]; + }; +in +with nixpkgs; pkgs.mkShell { + buildInputs = [ + clang + pkg-config + rust-wasm + ] ++ stdenv.lib.optionals stdenv.isDarwin [ + darwin.apple_sdk.frameworks.Security + ]; + + LIBCLANG_PATH = "${llvmPackages.libclang}/lib"; + PROTOC = "${protobuf}/bin/protoc"; + RUST_SRC_PATH = "${toolchain.rust-src}/lib/rustlib/src/rust/library/"; + ROCKSDB_LIB_DIR = "${rocksdb}/lib"; + +} From 499e2b3158e49fb3d976b8059d809bf207841af5 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 14:01:35 +0200 Subject: [PATCH 62/80] feat: add vesting to funding --- polimec-skeleton/pallets/funding/src/mock.rs | 1 + polimec-skeleton/pallets/funding/src/tests.rs | 11 ----------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/polimec-skeleton/pallets/funding/src/mock.rs b/polimec-skeleton/pallets/funding/src/mock.rs index ee627df7c..904a64d01 100644 --- a/polimec-skeleton/pallets/funding/src/mock.rs +++ b/polimec-skeleton/pallets/funding/src/mock.rs @@ -277,6 +277,7 @@ impl pallet_funding::Config for TestRuntime { type WeightInfo = (); type FeeBrackets = FeeBrackets; type EvaluationSuccessThreshold = EarlyEvaluationThreshold; + type Vesting = Vesting; } // Build genesis storage according to the mock runtime. diff --git a/polimec-skeleton/pallets/funding/src/tests.rs b/polimec-skeleton/pallets/funding/src/tests.rs index 26411a800..af7158243 100644 --- a/polimec-skeleton/pallets/funding/src/tests.rs +++ b/polimec-skeleton/pallets/funding/src/tests.rs @@ -360,17 +360,6 @@ impl TestEnvironment { balances }) } - fn get_all_reserved_plmc_balances(&self, reserve_type: LockType>) -> UserToPLMCBalance { - self.ext_env.borrow_mut().execute_with(|| { - let mut fundings = UserToPLMCBalance::new(); - let user_keys: Vec = frame_system::Account::::iter_keys().collect(); - for user in user_keys { - let funding = Balances::balance_on_hold(&reserve_type, &user); - fundings.push((user, funding)); - } - fundings - }) - } #[allow(dead_code)] fn get_all_reserved_plmc_balances(&self, reserve_type: LockType>) -> UserToPLMCBalance { self.ext_env.borrow_mut().execute_with(|| { From 326977a81daeb60219e4232dce0d0a00d56f63c5 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 14:04:51 +0200 Subject: [PATCH 63/80] chore: add missing headers --- .../pallets/linear-release/src/impls.rs | 16 ++++++++ .../pallets/linear-release/src/lib.rs | 41 +++++++------------ .../pallets/linear-release/src/mock.rs | 16 ++++++++ .../pallets/linear-release/src/tests.rs | 16 ++++++++ .../pallets/linear-release/src/traits.rs | 16 +++++++- .../pallets/linear-release/src/types.rs | 16 ++++++++ 6 files changed, 94 insertions(+), 27 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/impls.rs b/polimec-skeleton/pallets/linear-release/src/impls.rs index b21431814..b7d648179 100644 --- a/polimec-skeleton/pallets/linear-release/src/impls.rs +++ b/polimec-skeleton/pallets/linear-release/src/impls.rs @@ -1,3 +1,19 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + use super::*; impl Pallet { diff --git a/polimec-skeleton/pallets/linear-release/src/lib.rs b/polimec-skeleton/pallets/linear-release/src/lib.rs index ceb9645b3..47f71addd 100644 --- a/polimec-skeleton/pallets/linear-release/src/lib.rs +++ b/polimec-skeleton/pallets/linear-release/src/lib.rs @@ -1,29 +1,18 @@ -// This file is part of Substrate. - -// Copyright (C) Parity Technologies (UK) Ltd. -// SPDX-License-Identifier: Apache-2.0 - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! -//! # Dev Mode Example Pallet -//! -//! A simple example of a FRAME pallet demonstrating -//! the ease of requirements for a pallet in dev mode. -//! -//! Run `cargo doc --package pallet-dev-mode --open` to view this pallet's documentation. -//! -//! **Dev mode is not meant to be used in production.** +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] diff --git a/polimec-skeleton/pallets/linear-release/src/mock.rs b/polimec-skeleton/pallets/linear-release/src/mock.rs index 30124247c..bd751c9bb 100644 --- a/polimec-skeleton/pallets/linear-release/src/mock.rs +++ b/polimec-skeleton/pallets/linear-release/src/mock.rs @@ -1,3 +1,19 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + use frame_support::{ parameter_types, traits::{ConstU32, ConstU64, WithdrawReasons}, diff --git a/polimec-skeleton/pallets/linear-release/src/tests.rs b/polimec-skeleton/pallets/linear-release/src/tests.rs index 3703b0a01..7d75140ea 100644 --- a/polimec-skeleton/pallets/linear-release/src/tests.rs +++ b/polimec-skeleton/pallets/linear-release/src/tests.rs @@ -1,3 +1,19 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + use frame_support::{assert_noop, assert_ok, assert_storage_noop, dispatch::EncodeLike}; use frame_system::RawOrigin; use sp_runtime::{ diff --git a/polimec-skeleton/pallets/linear-release/src/traits.rs b/polimec-skeleton/pallets/linear-release/src/traits.rs index 2cc5e5e53..205e92e19 100644 --- a/polimec-skeleton/pallets/linear-release/src/traits.rs +++ b/polimec-skeleton/pallets/linear-release/src/traits.rs @@ -1,4 +1,18 @@ -// TODO: Add Header +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . use frame_support::{pallet_prelude::DispatchResult, traits::tokens::fungible}; diff --git a/polimec-skeleton/pallets/linear-release/src/types.rs b/polimec-skeleton/pallets/linear-release/src/types.rs index b13bf4469..fafcd3179 100644 --- a/polimec-skeleton/pallets/linear-release/src/types.rs +++ b/polimec-skeleton/pallets/linear-release/src/types.rs @@ -1,3 +1,19 @@ +// Polimec Blockchain – https://www.polimec.org/ +// Copyright (C) Polimec 2022. All rights reserved. + +// The Polimec Blockchain 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. + +// The Polimec Blockchain 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 this program. If not, see . + use super::*; /// Enum used to identify PLMC holds From 78506e6a3d3736ba230a0550affd14bdba24940d Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Fri, 21 Jul 2023 14:16:44 +0200 Subject: [PATCH 64/80] chore: cargo fmt --- .../pallets/linear-release/src/impls.rs | 12 ++++++------ polimec-skeleton/pallets/linear-release/src/lib.rs | 2 +- polimec-skeleton/pallets/linear-release/src/mock.rs | 13 ++++++------- .../pallets/linear-release/src/tests.rs | 8 +++++--- .../pallets/linear-release/src/traits.rs | 10 ++++++---- 5 files changed, 24 insertions(+), 21 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/impls.rs b/polimec-skeleton/pallets/linear-release/src/impls.rs index b7d648179..3c4f3fb72 100644 --- a/polimec-skeleton/pallets/linear-release/src/impls.rs +++ b/polimec-skeleton/pallets/linear-release/src/impls.rs @@ -72,7 +72,7 @@ impl Pallet { // Validate user inputs. ensure!(schedule.locked() >= T::MinVestedTransfer::get(), Error::::AmountLow); if !schedule.is_valid() { - return Err(Error::::InvalidScheduleParams.into()); + return Err(Error::::InvalidScheduleParams.into()) }; // Check we can add to this account prior to any storage writes. @@ -274,13 +274,13 @@ impl ReleaseSchedule, ReasonOf> for Pallet { reason: ReasonOf, ) -> DispatchResult { if locked.is_zero() { - return Ok(()); + return Ok(()) } let vesting_schedule = VestingInfo::new(locked, per_block, starting_block); // Check for `per_block` or `locked` of 0. if !vesting_schedule.is_valid() { - return Err(Error::::InvalidScheduleParams.into()); + return Err(Error::::InvalidScheduleParams.into()) }; let mut schedules = Self::vesting(who, reason).unwrap_or_default(); @@ -307,7 +307,7 @@ impl ReleaseSchedule, ReasonOf> for Pallet { ) -> DispatchResult { // Check for `per_block` or `locked` of 0. if !VestingInfo::new(locked, per_block, starting_block).is_valid() { - return Err(Error::::InvalidScheduleParams.into()); + return Err(Error::::InvalidScheduleParams.into()) } ensure!( @@ -326,13 +326,13 @@ impl ReleaseSchedule, ReasonOf> for Pallet { reason: ReasonOf, ) -> DispatchResult { if locked.is_zero() { - return Ok(()); + return Ok(()) } let vesting_schedule = VestingInfo::new(locked, per_block, starting_block); // Check for `per_block` or `locked` of 0. if !vesting_schedule.is_valid() { - return Err(Error::::InvalidScheduleParams.into()); + return Err(Error::::InvalidScheduleParams.into()) }; let mut schedules = Self::vesting(who, reason).unwrap_or_default(); diff --git a/polimec-skeleton/pallets/linear-release/src/lib.rs b/polimec-skeleton/pallets/linear-release/src/lib.rs index 47f71addd..470d8a9a2 100644 --- a/polimec-skeleton/pallets/linear-release/src/lib.rs +++ b/polimec-skeleton/pallets/linear-release/src/lib.rs @@ -363,7 +363,7 @@ pub mod pallet { ) -> DispatchResult { let who = ensure_signed(origin)?; if schedule1_index == schedule2_index { - return Ok(()); + return Ok(()) }; let schedule1_index = schedule1_index as usize; let schedule2_index = schedule2_index as usize; diff --git a/polimec-skeleton/pallets/linear-release/src/mock.rs b/polimec-skeleton/pallets/linear-release/src/mock.rs index bd751c9bb..284d64733 100644 --- a/polimec-skeleton/pallets/linear-release/src/mock.rs +++ b/polimec-skeleton/pallets/linear-release/src/mock.rs @@ -96,11 +96,13 @@ impl Config for Test { type Balance = u64; type BlockNumberToBalance = Identity; type Currency = Balances; - type Reason = LockType; // TODO: Use the type from Balances. + // TODO: Use the type from Balances. type MinVestedTransfer = MinVestedTransfer; + type Reason = LockType; type RuntimeEvent = RuntimeEvent; type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; type WeightInfo = (); + const MAX_VESTING_SCHEDULES: u32 = 3; } @@ -116,7 +118,6 @@ impl ExtBuilder { self } - pub fn build(self) -> sp_io::TestExternalities { EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit); let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); @@ -140,15 +141,13 @@ impl ExtBuilder { vec![ (1, 0, 10, 5 * self.existential_deposit, LockType::Participation(0)), (2, 10, 20, self.existential_deposit, LockType::Participation(0)), - (12, 10, 20, 5 * self.existential_deposit, LockType::Participation(0)), + (12, 10, 20, 5 * self.existential_deposit, LockType::Participation(0)), ] }; - pallet_vesting::GenesisConfig:: { vesting } - .assimilate_storage(&mut t) - .unwrap(); + pallet_vesting::GenesisConfig:: { vesting }.assimilate_storage(&mut t).unwrap(); let mut ext = sp_io::TestExternalities::new(t); ext.execute_with(|| System::set_block_number(1)); ext } -} \ No newline at end of file +} diff --git a/polimec-skeleton/pallets/linear-release/src/tests.rs b/polimec-skeleton/pallets/linear-release/src/tests.rs index 7d75140ea..e527231dd 100644 --- a/polimec-skeleton/pallets/linear-release/src/tests.rs +++ b/polimec-skeleton/pallets/linear-release/src/tests.rs @@ -1298,13 +1298,15 @@ fn merge_schedules_different_reason() { assert_eq!(Balances::balance(&2), ED); assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0]); - // Add a schedule that is identical to the one that already exists. assert_ok!(Vesting::vested_transfer(Some(14).into(), 2, sched0, LockType::Participation(1))); assert_ok!(Vesting::vested_transfer(Some(14).into(), 2, sched0, LockType::Participation(1))); assert_eq!(Vesting::vesting(&2, LockType::Participation(1)).unwrap(), vec![sched0, sched0]); assert_eq!(Balances::balance(&2), ED); - assert_noop!(Vesting::merge_schedules(Some(2).into(), 0, 1, LockType::Participation(0)), Error::::ScheduleIndexOutOfBounds); + assert_noop!( + Vesting::merge_schedules(Some(2).into(), 0, 1, LockType::Participation(0)), + Error::::ScheduleIndexOutOfBounds + ); assert_ok!(Vesting::merge_schedules(Some(2).into(), 0, 1, LockType::Participation(1))); // Since we merged identical schedules, the new schedule finishes at the same @@ -1318,4 +1320,4 @@ fn merge_schedules_different_reason() { assert_eq!(Balances::balance(&2), ED); }); -} \ No newline at end of file +} diff --git a/polimec-skeleton/pallets/linear-release/src/traits.rs b/polimec-skeleton/pallets/linear-release/src/traits.rs index 205e92e19..0e834c6f3 100644 --- a/polimec-skeleton/pallets/linear-release/src/traits.rs +++ b/polimec-skeleton/pallets/linear-release/src/traits.rs @@ -26,11 +26,13 @@ pub trait ReleaseSchedule { type Currency: fungible::InspectHold + fungible::MutateHold + fungible::BalancedHold; - /// Get the amount that is currently being vested and cannot be transferred out of this account. /// Returns `None` if the account has no vesting schedule. - fn vesting_balance(who: &AccountId, reason: Reason) -> Option<>::Balance>; + fn vesting_balance( + who: &AccountId, + reason: Reason, + ) -> Option<>::Balance>; /// Adds a release schedule to a given account. /// @@ -61,7 +63,7 @@ pub trait ReleaseSchedule { locked: >::Balance, per_block: >::Balance, starting_block: Self::Moment, - reason: Reason + reason: Reason, ) -> DispatchResult; /// Checks if `add_release_schedule` would work against `who`. @@ -70,7 +72,7 @@ pub trait ReleaseSchedule { locked: >::Balance, per_block: >::Balance, starting_block: Self::Moment, - reason: Reason + reason: Reason, ) -> DispatchResult; /// Remove a release schedule for a given account. From 07064398fa7eceab8ec6c5cc80d1bdd34367a7c2 Mon Sep 17 00:00:00 2001 From: Robert Hambrock Date: Sat, 22 Jul 2023 10:47:08 +0200 Subject: [PATCH 65/80] rename total_{locked->held}_now & typos --- polimec-skeleton/pallets/linear-release/src/impls.rs | 10 +++++----- polimec-skeleton/pallets/linear-release/src/traits.rs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/impls.rs b/polimec-skeleton/pallets/linear-release/src/impls.rs index 3c4f3fb72..b532980a3 100644 --- a/polimec-skeleton/pallets/linear-release/src/impls.rs +++ b/polimec-skeleton/pallets/linear-release/src/impls.rs @@ -144,10 +144,10 @@ impl Pallet { /// Write an accounts updated vesting lock to storage. pub fn write_lock( who: &T::AccountId, - total_locked_now: BalanceOf, + total_held_now: BalanceOf, reason: ReasonOf, ) -> Result<(), DispatchError> { - if total_locked_now.is_zero() { + if total_held_now.is_zero() { T::Currency::release( &reason, who, @@ -156,10 +156,10 @@ impl Pallet { )?; Self::deposit_event(Event::::VestingCompleted { account: who.clone() }); } else { - let alredy_holded = T::Currency::balance_on_hold(&reason, who); - let to_release = alredy_holded.saturating_sub(total_locked_now); + let already_held = T::Currency::balance_on_hold(&reason, who); + let to_release = already_held.saturating_sub(total_held_now); T::Currency::release(&reason, who, to_release, Precision::BestEffort)?; - Self::deposit_event(Event::::VestingUpdated { account: who.clone(), unvested: total_locked_now }); + Self::deposit_event(Event::::VestingUpdated { account: who.clone(), unvested: to_release }); }; Ok(()) diff --git a/polimec-skeleton/pallets/linear-release/src/traits.rs b/polimec-skeleton/pallets/linear-release/src/traits.rs index 0e834c6f3..9a55a861d 100644 --- a/polimec-skeleton/pallets/linear-release/src/traits.rs +++ b/polimec-skeleton/pallets/linear-release/src/traits.rs @@ -50,7 +50,7 @@ pub trait ReleaseSchedule { reason: Reason, ) -> DispatchResult; - /// Ser a release schedule to a given account, without locking any funds. + /// Set a release schedule to a given account, without locking any funds. /// /// If the account has `MaxVestingSchedules`, an Error is returned and nothing /// is updated. From e8916c997b15a4070cce68a5d65582cdb8eb15c7 Mon Sep 17 00:00:00 2001 From: lrazovic <4128940+lrazovic@users.noreply.github.com> Date: Sun, 23 Jul 2023 19:23:42 +0200 Subject: [PATCH 66/80] feat: use Exact preceision --- polimec-skeleton/pallets/linear-release/src/impls.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polimec-skeleton/pallets/linear-release/src/impls.rs b/polimec-skeleton/pallets/linear-release/src/impls.rs index b532980a3..2bf715fcf 100644 --- a/polimec-skeleton/pallets/linear-release/src/impls.rs +++ b/polimec-skeleton/pallets/linear-release/src/impls.rs @@ -89,7 +89,7 @@ impl Pallet { &source, &target, schedule.locked(), - Precision::BestEffort, + Precision::Exact, frame_support::traits::tokens::Preservation::Expendable, frame_support::traits::tokens::Fortitude::Polite, )?; From 61663e3288b37bc96809fab60f1c4f83235100fd Mon Sep 17 00:00:00 2001 From: lrazovic <4128940+lrazovic@users.noreply.github.com> Date: Sun, 23 Jul 2023 19:25:59 +0200 Subject: [PATCH 67/80] chore: rename for clarity --- .../pallets/linear-release/src/impls.rs | 23 +++++++++---------- .../pallets/linear-release/src/lib.rs | 4 ++-- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/impls.rs b/polimec-skeleton/pallets/linear-release/src/impls.rs index 2bf715fcf..d5d14e084 100644 --- a/polimec-skeleton/pallets/linear-release/src/impls.rs +++ b/polimec-skeleton/pallets/linear-release/src/impls.rs @@ -125,7 +125,7 @@ impl Pallet { ) -> (Vec, BlockNumberFor>>, BalanceOf) { let now = >::block_number(); - let mut total_locked_now: BalanceOf = Zero::zero(); + let mut total_releasable: BalanceOf = Zero::zero(); let filtered_schedules = action .pick_schedules::(schedules) .filter(|schedule| { @@ -138,11 +138,11 @@ impl Pallet { }) .collect::>(); - (filtered_schedules, total_locked_now) + (filtered_schedules, total_releasable) } /// Write an accounts updated vesting lock to storage. - pub fn write_lock( + pub fn write_release( who: &T::AccountId, total_held_now: BalanceOf, reason: ReasonOf, @@ -166,7 +166,7 @@ impl Pallet { } /// Write an accounts updated vesting schedules to storage. - pub fn write_vesting( + pub fn write_vesting_schedule( who: &T::AccountId, schedules: Vec, BlockNumberFor>>, reason: ReasonOf, @@ -188,9 +188,8 @@ impl Pallet { let schedules = Self::vesting(&who, reason).ok_or(Error::::NotVesting)?; let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), VestingAction::Passive)?; - - Self::write_vesting(&who, schedules, reason)?; - Self::write_lock(&who, locked_now, reason)?; + Self::write_vesting_schedule(&who, schedules, reason)?; + Self::write_release(&who, locked_now, reason)?; Ok(()) } @@ -291,8 +290,8 @@ impl ReleaseSchedule, ReasonOf> for Pallet { let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), VestingAction::Passive)?; - Self::write_vesting(who, schedules, reason)?; - Self::write_lock(who, locked_now, reason)?; + Self::write_vesting_schedule(who, schedules, reason)?; + Self::write_release(who, locked_now, reason)?; Ok(()) } @@ -343,7 +342,7 @@ impl ReleaseSchedule, ReasonOf> for Pallet { let (schedules, _) = Self::exec_action(schedules.to_vec(), VestingAction::Passive)?; - Self::write_vesting(who, schedules, reason)?; + Self::write_vesting_schedule(who, schedules, reason)?; Ok(()) } @@ -354,8 +353,8 @@ impl ReleaseSchedule, ReasonOf> for Pallet { let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), remove_action)?; - Self::write_vesting(who, schedules, reason)?; - Self::write_lock(who, locked_now, reason)?; + Self::write_vesting_schedule(who, schedules, reason)?; + Self::write_release(who, locked_now, reason)?; Ok(()) } } diff --git a/polimec-skeleton/pallets/linear-release/src/lib.rs b/polimec-skeleton/pallets/linear-release/src/lib.rs index 470d8a9a2..ac1a0e960 100644 --- a/polimec-skeleton/pallets/linear-release/src/lib.rs +++ b/polimec-skeleton/pallets/linear-release/src/lib.rs @@ -374,8 +374,8 @@ pub mod pallet { let (schedules, locked_now) = Self::exec_action(schedules.to_vec(), merge_action)?; - Self::write_vesting(&who, schedules, reason)?; - Self::write_lock(&who, locked_now, reason)?; + Self::write_vesting_schedule(&who, schedules, reason)?; + Self::write_release(&who, locked_now, reason)?; Ok(()) } From 9274cbde6bce827d3af0a5333654746fe132bcb7 Mon Sep 17 00:00:00 2001 From: lrazovic <4128940+lrazovic@users.noreply.github.com> Date: Sun, 23 Jul 2023 19:26:21 +0200 Subject: [PATCH 68/80] feat: accrue, not add --- polimec-skeleton/pallets/linear-release/src/impls.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polimec-skeleton/pallets/linear-release/src/impls.rs b/polimec-skeleton/pallets/linear-release/src/impls.rs index d5d14e084..6d876e4ef 100644 --- a/polimec-skeleton/pallets/linear-release/src/impls.rs +++ b/polimec-skeleton/pallets/linear-release/src/impls.rs @@ -132,7 +132,7 @@ impl Pallet { let locked_now = schedule.locked_at::(now); let keep = !locked_now.is_zero(); if keep { - total_locked_now = total_locked_now.saturating_add(locked_now); + total_releasable.saturating_accrue(locked_now); } keep }) From 434e29e46703319827b29eccd85c5d00295c5c20 Mon Sep 17 00:00:00 2001 From: lrazovic <4128940+lrazovic@users.noreply.github.com> Date: Sun, 23 Jul 2023 19:27:58 +0200 Subject: [PATCH 69/80] feat: new extrinsics to "release" all the reasons --- .../pallets/linear-release/src/lib.rs | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/lib.rs b/polimec-skeleton/pallets/linear-release/src/lib.rs index ac1a0e960..81bf33780 100644 --- a/polimec-skeleton/pallets/linear-release/src/lib.rs +++ b/polimec-skeleton/pallets/linear-release/src/lib.rs @@ -251,7 +251,7 @@ pub mod pallet { #[pallet::call] impl Pallet { - /// Unlock any vested funds of the sender account. + /// Unlock any vested funds of the sender account, for the given `reason`. /// /// The dispatch origin for this call must be _Signed_ and the sender must have funds still /// locked under this pallet. @@ -266,7 +266,7 @@ pub mod pallet { Self::do_vest(who, reason) } - /// Unlock any vested funds of a `target` account. + /// Unlock any vested funds of a `target` account, for the given `reason`. /// /// The dispatch origin for this call must be _Signed_. /// @@ -379,5 +379,45 @@ pub mod pallet { Ok(()) } + + /// Unlock any vested funds of the sender account. + /// + /// The dispatch origin for this call must be _Signed_ and the sender must have funds still + /// locked under this pallet. + /// + /// Emits either `VestingCompleted` or `VestingUpdated`. + /// + /// ## Complexity + /// - `O(1)`. + #[pallet::call_index(5)] + pub fn vest_all(origin: OriginFor) -> DispatchResult { + let who = ensure_signed(origin)?; + let reasons = >::iter_key_prefix(&who); + for reason in reasons { + Self::do_vest(who.clone(), reason)?; + } + Ok(()) + } + + /// Unlock any vested funds of a `target` account. + /// + /// The dispatch origin for this call must be _Signed_. + /// + /// - `target`: The account whose vested funds should be unlocked. Must have funds still + /// locked under this pallet. + /// + /// Emits either `VestingCompleted` or `VestingUpdated`. + /// + /// ## Complexity + /// - `O(1)`. + #[pallet::call_index(6)] + pub fn vest_all_other(origin: OriginFor, target: AccountIdOf) -> DispatchResult { + ensure_signed(origin)?; + let reasons = >::iter_key_prefix(&target); + for reason in reasons { + Self::do_vest(target.clone(), reason)?; + } + Ok(()) + } } } From e7f9b1fa8819534d866ed5d48cfbcbf8a2e243fa Mon Sep 17 00:00:00 2001 From: lrazovic <4128940+lrazovic@users.noreply.github.com> Date: Sun, 23 Jul 2023 19:30:52 +0200 Subject: [PATCH 70/80] feat: modify what the "vesting_balance" is --- .../pallets/linear-release/src/impls.rs | 8 +- .../pallets/linear-release/src/tests.rs | 113 ++++++++++-------- .../pallets/linear-release/src/types.rs | 18 ++- 3 files changed, 79 insertions(+), 60 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/impls.rs b/polimec-skeleton/pallets/linear-release/src/impls.rs index 6d876e4ef..82971fc5c 100644 --- a/polimec-skeleton/pallets/linear-release/src/impls.rs +++ b/polimec-skeleton/pallets/linear-release/src/impls.rs @@ -240,14 +240,14 @@ impl ReleaseSchedule, ReasonOf> for Pallet { type Currency = T::Currency; type Moment = BlockNumberFor; - /// Get the amount that is currently being vested and cannot be transferred out of this account. + /// Get the amount that is currently being held and cannot be transferred out of this account. fn vesting_balance(who: &T::AccountId, reason: ReasonOf) -> Option> { if let Some(v) = Self::vesting(who, reason) { let now = >::block_number(); - let total_locked_now = v.iter().fold(Zero::zero(), |total, schedule| { - schedule.locked_at::(now).saturating_add(total) + let total_releasable = v.iter().fold(Zero::zero(), |total, schedule| { + schedule.releaseble_at::(now).saturating_add(total) }); - Some(T::Currency::balance_on_hold(&reason, who).min(total_locked_now)) + Some(total_releasable) } else { None } diff --git a/polimec-skeleton/pallets/linear-release/src/tests.rs b/polimec-skeleton/pallets/linear-release/src/tests.rs index e527231dd..c0083b22f 100644 --- a/polimec-skeleton/pallets/linear-release/src/tests.rs +++ b/polimec-skeleton/pallets/linear-release/src/tests.rs @@ -72,28 +72,28 @@ fn check_vesting_status() { assert_eq!(Vesting::vesting(&12, LockType::Participation(0)).unwrap(), vec![user12_vesting_schedule]); // Account 12 has a vesting schedule // Account 1 has only 128 units vested from their illiquid ED * 5 units at block 1 - assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(128 * 9)); + assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(128)); // Account 2 has their full balance locked - assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(ED * 20)); + assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(0)); // Account 12 has only their illiquid funds locked - assert_eq!(Vesting::vesting_balance(&12, LockType::Participation(0)), Some(ED * 5)); + assert_eq!(Vesting::vesting_balance(&12, LockType::Participation(0)), Some(0)); System::set_block_number(10); assert_eq!(System::block_number(), 10); // Account 1 has fully vested by block 10 - assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(0)); + assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(ED * 5)); // Account 2 has started vesting by block 10 - assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(ED * 20)); + assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(0)); // Account 12 has started vesting by block 10 - assert_eq!(Vesting::vesting_balance(&12, LockType::Participation(0)), Some(ED * 5)); + assert_eq!(Vesting::vesting_balance(&12, LockType::Participation(0)), Some(0)); System::set_block_number(30); assert_eq!(System::block_number(), 30); - assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(0)); // Account 1 is still fully vested, and not negative - assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(0)); // Account 2 has fully vested by block 30 - assert_eq!(Vesting::vesting_balance(&12, LockType::Participation(0)), Some(0)); // Account 2 has fully vested by block 30 + assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(ED * 5)); // Account 1 is still fully vested, and not negative + assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(ED * 20)); // Account 2 has fully vested by block 30 + assert_eq!(Vesting::vesting_balance(&12, LockType::Participation(0)), Some(ED * 5)); // Account 2 has fully vested by block 30 // Once we unlock the funds, they are removed from storage. vest_and_assert_no_vesting::(1, LockType::Participation(0)); @@ -117,7 +117,7 @@ fn check_vesting_status_for_multi_schedule_account() { // Account 2's free balance is the one set in Genesis inside the Balances pallet. let balance = Balances::balance(&2); assert_eq!(balance, ED * (1)); - assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(ED * (20))); + assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(0)); // Add a 2nd schedule that is already unlocking by block #1. let sched1 = VestingInfo::new( @@ -125,7 +125,9 @@ fn check_vesting_status_for_multi_schedule_account() { ED, // Vesting over 10 blocks 0, ); + assert_eq!(Balances::balance_on_hold(&LockType::Participation(0), &2), 20 * ED); assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1, LockType::Participation(0))); + assert_eq!(Balances::balance_on_hold(&LockType::Participation(0), &2), 29 * ED); // Why 29 and not 30? Because sched1 is already unlocking. // Free balance is the one set in Genesis inside the Balances pallet // + the one from the vested transfer. // BUT NOT the one in sched0, since the vesting will start at block #10. @@ -141,6 +143,7 @@ fn check_vesting_status_for_multi_schedule_account() { 5, ); assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched2, LockType::Participation(0))); + assert_eq!(Balances::balance_on_hold(&LockType::Participation(0), &2), 15104); // 59 * ED System::set_block_number(9); assert_eq!(System::block_number(), 9); @@ -152,27 +155,34 @@ fn check_vesting_status_for_multi_schedule_account() { assert_ok!(Vesting::vest(Some(2).into(), LockType::Participation(0))); let balance = Balances::balance(&2); assert_eq!(balance, ED * (1 + 9 + 4)); // 1 from Genesis + 9 from sched1 + 4 from sched2 + assert_eq!(Balances::balance_on_hold(&LockType::Participation(0), &2), 12032); // 47 * ED // sched1 and sched2 are freeing funds at block #9, but sched0 is not. assert_eq!( Vesting::vesting_balance(&2, LockType::Participation(0)), - Some(sched0.per_block() * 20 + sched1.per_block() * 1 + sched2.per_block() * 26) + Some(sched1.per_block() * System::block_number() + sched2.per_block() * 4) ); System::set_block_number(20); // At block #20 sched1 is fully unlocked while sched2 and sched0 are partially unlocked. assert_eq!( Vesting::vesting_balance(&2, LockType::Participation(0)), - Some(sched0.per_block() * 10 + sched2.per_block() * 15) + Some(sched1.locked() + sched0.per_block() * 10 + sched2.per_block() * 15) ); System::set_block_number(30); // At block #30 sched0 and sched1 are fully unlocked while sched2 is partially unlocked. - assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(sched2.per_block() * 5)); + assert_eq!( + Vesting::vesting_balance(&2, LockType::Participation(0)), + Some(sched0.locked() + sched1.locked() + sched2.per_block() * 25) + ); // At block #35 sched2 fully unlocks and thus all schedules funds are unlocked. System::set_block_number(35); - assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(0)); + assert_eq!( + Vesting::vesting_balance(&2, LockType::Participation(0)), + Some(sched0.locked() + sched1.locked() + sched2.locked()) + ); // Since we have not called any extrinsics that would unlock funds the schedules // are still in storage, assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0, sched1, sched2]); @@ -187,7 +197,7 @@ fn unvested_balance_should_not_transfer() { let user1_free_balance = Balances::free_balance(&1); assert_eq!(user1_free_balance, 50); // Account 1 has free balance // Account 1 has only 5 units vested at block 1 (plus 50 unvested) - assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(45)); // Account 1 cannot send more than vested amount... + assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(5)); // Account 1 cannot send more than vested amount... assert_noop!(Balances::transfer_allow_death(Some(1).into(), 2, 56), TokenError::FundsUnavailable); }); } @@ -199,7 +209,7 @@ fn vested_balance_should_transfer() { let user1_free_balance = Balances::free_balance(&1); assert_eq!(user1_free_balance, 50); // Account 1 has free balance // Account 1 has only 5 units vested at block 1 (plus 50 unvested) - assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(45)); + assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(5)); assert_noop!(Balances::transfer_allow_death(Some(1).into(), 2, 45), TokenError::Frozen); // Account 1 free balance - ED is < 45 assert_ok!(Vesting::vest(Some(1).into(), LockType::Participation(0))); let user1_free_balance = Balances::free_balance(&1); @@ -231,8 +241,8 @@ fn vested_balance_should_transfer_with_multi_sched() { let user1_free_balance = Balances::free_balance(&1); assert_eq!(user1_free_balance, user1_initial_free_balance + (2 * sched0.per_block())); - // - assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(9 * ED)); + // Account "1" has only 256 units (1 ED) unlocking at block 1 (plus 1280 already free). + assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(1 * ED)); assert_ok!(Vesting::vest(Some(1).into(), LockType::Participation(0))); let user1_free_balance = Balances::balance(&1); assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, user1_free_balance - ED)); @@ -253,7 +263,7 @@ fn vested_balance_should_transfer_using_vest_other() { let user1_free_balance = Balances::free_balance(&1); assert_eq!(user1_free_balance, 50); // Account 1 has free balance // Account 1 has only 5 units vested at block 1 (plus 50 unvested) - assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(45)); + assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(5)); assert_ok!(Vesting::vest_other(Some(2).into(), 1, LockType::Participation(0))); assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 55 - 10)); }); @@ -270,8 +280,8 @@ fn vested_balance_should_transfer_using_vest_other_with_multi_sched() { let user1_free_balance = Balances::free_balance(&1); assert_eq!(user1_free_balance, 1536); // Account 1 has free balance - // Account 1 has only 256 units unlocking at block 1 (plus 1280 already free). - assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(9 * ED)); + // Account 1 has only 256 units (1 ED) unlocking at block 1 (plus 1280 already free). + assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(ED)); assert_ok!(Vesting::vest_other(Some(2).into(), 1, LockType::Participation(0))); assert_ok!(Balances::transfer_allow_death(Some(1).into(), 2, 1536 - ED)); }); @@ -302,15 +312,13 @@ fn extra_balance_should_transfer() { assert_eq!(user2_free_balance, 110); // Account 2 has 100 more free balance than normal // Account 1 has only 5 units vested at block 1 (plus 150 unvested) - assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(45)); + assert_eq!(Vesting::vesting_balance(&1, LockType::Participation(0)), Some(5)); assert_ok!(Vesting::vest(Some(1).into(), LockType::Participation(0))); let user1_free_balance2 = Balances::free_balance(&1); assert_eq!(user1_free_balance2, 155); // Account 1 has 100 more free balance than normal assert_ok!(Balances::transfer_allow_death(Some(1).into(), 3, 155 - 10)); // Account 1 can send extra units gained // Account 2 has no units vested at block 1, but gained 100 - assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(200)); - assert_ok!(Vesting::vest(Some(2).into(), LockType::Participation(0))); assert_ok!(Balances::transfer_allow_death(Some(2).into(), 3, 100 - 10)); // Account 2 can send extra // units gained }); @@ -323,7 +331,7 @@ fn liquid_funds_should_transfer_with_delayed_vesting() { assert_eq!(user12_free_balance, 1280); // Account 12 has free balance // Account 12 has liquid funds - assert_eq!(Vesting::vesting_balance(&12, LockType::Participation(0)), Some(256 * 5)); + assert_eq!(Vesting::vesting_balance(&12, LockType::Participation(0)), Some(0)); // Account 12 has delayed vesting let user12_vesting_schedule = VestingInfo::new( @@ -362,7 +370,7 @@ fn vested_transfer_works() { let user4_free_balance_updated = Balances::free_balance(&4); assert_eq!(user4_free_balance_updated, 256 * 40); // Account 4 has 5 * 256 locked. - assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(256 * 5)); + assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(0)); System::set_block_number(20); assert_eq!(System::block_number(), 20); @@ -374,7 +382,7 @@ fn vested_transfer_works() { assert_eq!(System::block_number(), 30); // Account 4 has fully vested, - assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(0)); + assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(new_vesting_schedule.locked())); // and after unlocking its schedules are removed from storage. vest_and_assert_no_vesting::(4, LockType::Participation(0)); }); @@ -442,8 +450,7 @@ fn vested_transfer_allows_max_schedules() { } // The schedules count towards vesting balance - let transferred_amount = ::MinVestedTransfer::get() * max_schedules as u64; - assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(transferred_amount)); + assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(0)); // BUT NOT the free balance. assert_eq!(Balances::free_balance(&4), user_4_free_balance); @@ -457,7 +464,10 @@ fn vested_transfer_allows_max_schedules() { // Account 4 has fully vested when all the schedules end, System::set_block_number(::MinVestedTransfer::get() + sched.starting_block()); - assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(0)); + assert_eq!( + Vesting::vesting_balance(&4, LockType::Participation(0)), + Some(sched.locked() * max_schedules as u64) + ); // and after unlocking its schedules are removed from storage. vest_and_assert_no_vesting::(4, LockType::Participation(0)); }); @@ -499,7 +509,7 @@ fn force_vested_transfer_works() { let user4_free_balance_updated = Balances::free_balance(&4); assert_eq!(user4_free_balance_updated, ED * 40); // Account 4 has 5 * ED locked. - assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(ED * 5)); + assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(0)); System::set_block_number(20); assert_eq!(System::block_number(), 20); @@ -511,7 +521,7 @@ fn force_vested_transfer_works() { assert_eq!(System::block_number(), 30); // Account 4 has fully vested, - assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(0)); + assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(new_vesting_schedule.locked())); // and after unlocking its schedules are removed from storage. vest_and_assert_no_vesting::(4, LockType::Participation(0)); }); @@ -596,8 +606,7 @@ fn force_vested_transfer_allows_max_schedules() { } // The schedules count towards vesting balance. - let transferred_amount = ::MinVestedTransfer::get() * max_schedules as u64; - assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(transferred_amount)); + assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(0)); // but NOT free balance. assert_eq!(Balances::free_balance(&4), user_4_free_balance); @@ -611,7 +620,7 @@ fn force_vested_transfer_allows_max_schedules() { // Account 4 has fully vested when all the schedules end, System::set_block_number(::MinVestedTransfer::get() + 10); - assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(0)); + assert_eq!(Vesting::vesting_balance(&4, LockType::Participation(0)), Some(sched.locked * max_schedules as u64)); // and after unlocking its schedules are removed from storage. vest_and_assert_no_vesting::(4, LockType::Participation(0)); }); @@ -955,20 +964,13 @@ fn merge_finished_and_yet_to_be_started_schedules() { assert_ok!(Vesting::vested_transfer(Some(13).into(), 2, sched2, LockType::Participation(0))); assert_eq!(Vesting::vesting(&2, LockType::Participation(0)).unwrap(), vec![sched0, sched1, sched2]); - assert_eq!( - Vesting::vesting_balance(&2, LockType::Participation(0)).unwrap(), - Balances::balance_on_hold(&LockType::Participation(0), &2) - ); - assert_eq!( - Vesting::vesting_balance(&2, LockType::Participation(0)), - Some(sched0.locked() + sched1.locked() + sched2.locked()) - ); + assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(0)); System::set_block_number(30); // At block 30, sched0 has finished unlocking while sched1 and sched2 are still fully // locked, - assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(sched1.locked() + sched2.locked())); + assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(sched0.locked())); // but since we have not vested usable balance is still 0. assert_eq!(Balances::balance(&2), ED); @@ -981,6 +983,10 @@ fn merge_finished_and_yet_to_be_started_schedules() { // The usable balance is updated because merging fully unlocked sched0. assert_eq!(Balances::balance(&2), ED + sched0.locked()); + assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(0)); + System::set_block_number(75); + assert_eq!(Vesting::vesting_balance(&2, LockType::Participation(0)), Some(sched2.locked() + sched1.locked())); + vest_and_assert_no_vesting::(2, LockType::Participation(0)); }); } @@ -1146,18 +1152,18 @@ fn set_release_schedule() { user3_vesting_schedule.starting_block, LockType::Participation(0) )); - assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(15 * ED)); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(0)); // 1 ED can be "released", we need to call vest to release it. System::set_block_number(2); - assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(14 * ED)); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(1 * ED)); assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(0))); let user_3_free_balance = Balances::free_balance(&3); assert_eq!(user_3_free_balance, 16 * ED); // 2 ED can be "released" System::set_block_number(3); - assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(13 * ED)); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(2 * ED)); assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(0))); let user_3_free_balance = Balances::free_balance(&3); assert_eq!(user_3_free_balance, 17 * ED); @@ -1165,10 +1171,11 @@ fn set_release_schedule() { // Go to the end of the schedule System::set_block_number(16); assert_eq!(System::block_number(), 16); - assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(0)); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(user3_vesting_schedule.locked)); vest_and_assert_no_vesting::(3, LockType::Participation(0)); let user_3_free_balance = Balances::free_balance(&3); assert_eq!(user_3_free_balance, 30 * ED); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), None); }); } @@ -1205,11 +1212,11 @@ fn cannot_release_different_reason() { user3_vesting_schedule.starting_block, LockType::Participation(0) )); - assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(15 * ED)); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(0)); // 1 ED can be "released", we need to call vest to release it. System::set_block_number(2); - assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(14 * ED)); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(1 * ED)); assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(0))); let user_3_free_balance = Balances::free_balance(&3); assert_eq!(user_3_free_balance, 16 * ED); @@ -1249,7 +1256,7 @@ fn multile_holds_release_schedule() { user3_vesting_schedule.starting_block, LockType::Participation(0) )); - assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(15 * ED)); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(0)); // Hold 7 ED more assert_ok!(Balances::hold(&LockType::Participation(1), &3, 7 * ED)); @@ -1269,8 +1276,8 @@ fn multile_holds_release_schedule() { user3_vesting_schedule.starting_block, LockType::Participation(1) )); - assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(15 * ED)); - assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(1)), Some(7 * ED)); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(0)); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(1)), Some(0)); System::set_block_number(16); assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(0))); diff --git a/polimec-skeleton/pallets/linear-release/src/types.rs b/polimec-skeleton/pallets/linear-release/src/types.rs index fafcd3179..2dca76d99 100644 --- a/polimec-skeleton/pallets/linear-release/src/types.rs +++ b/polimec-skeleton/pallets/linear-release/src/types.rs @@ -75,11 +75,11 @@ where } /// Amount locked at block `n`. - pub fn locked_at>(&self, n: BlockNumber) -> Balance { + pub fn locked_at>(&self, now: BlockNumber) -> Balance { // Number of blocks that count toward vesting; // saturating to 0 when n < starting_block. - let vested_block_count = n.saturating_sub(self.starting_block); - let vested_block_count = BlockNumberToBalance::convert(vested_block_count); + let time_range = now.saturating_sub(self.starting_block); + let vested_block_count = BlockNumberToBalance::convert(time_range); // Return amount that is still locked in vesting. vested_block_count .checked_mul(&self.per_block()) // `per_block` accessor guarantees at least 1. @@ -87,6 +87,18 @@ where .unwrap_or(Zero::zero()) } + /// Amount to be released at block `n`. + pub fn releaseble_at>(&self, now: BlockNumber) -> Balance { + // Number of blocks that count toward vesting; + // saturating to 0 when n < starting_block. + let time_range = now.saturating_sub(self.starting_block); + let vested_block_count = BlockNumberToBalance::convert(time_range); + // TODO: Find a way to improve this. + // Return amount that is releasable in vesting. + let res = vested_block_count.checked_mul(&self.per_block()).unwrap_or(Zero::zero()); + res.min(self.locked) + } + /// Block number at which the schedule ends (as type `Balance`). pub fn ending_block_as_balance>(&self) -> Balance { let starting_block = BlockNumberToBalance::convert(self.starting_block); From 87b89b8a5f2c638e82590e76ac2ad40af20e7642 Mon Sep 17 00:00:00 2001 From: lrazovic <4128940+lrazovic@users.noreply.github.com> Date: Sun, 23 Jul 2023 19:31:23 +0200 Subject: [PATCH 71/80] test: add tests for the new vest_all extrinsics --- .../pallets/linear-release/src/tests.rs | 156 +++++++++++++++++- 1 file changed, 153 insertions(+), 3 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/tests.rs b/polimec-skeleton/pallets/linear-release/src/tests.rs index c0083b22f..11e5f2d62 100644 --- a/polimec-skeleton/pallets/linear-release/src/tests.rs +++ b/polimec-skeleton/pallets/linear-release/src/tests.rs @@ -128,9 +128,9 @@ fn check_vesting_status_for_multi_schedule_account() { assert_eq!(Balances::balance_on_hold(&LockType::Participation(0), &2), 20 * ED); assert_ok!(Vesting::vested_transfer(Some(4).into(), 2, sched1, LockType::Participation(0))); assert_eq!(Balances::balance_on_hold(&LockType::Participation(0), &2), 29 * ED); // Why 29 and not 30? Because sched1 is already unlocking. - // Free balance is the one set in Genesis inside the Balances pallet - // + the one from the vested transfer. - // BUT NOT the one in sched0, since the vesting will start at block #10. + // Free balance is the one set in Genesis inside the Balances pallet + // + the one from the vested transfer. + // BUT NOT the one in sched0, since the vesting will start at block #10. let balance = Balances::balance(&2); assert_eq!(balance, ED * (2)); // The most recently added schedule exists. @@ -1328,3 +1328,153 @@ fn merge_schedules_different_reason() { assert_eq!(Balances::balance(&2), ED); }); } + +#[test] +fn vest_all_different_reason() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + assert_eq!(System::block_number(), 1); + // Initial Status + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 30 * ED); // 7680 ED + let user_3_reserved_balance = Balances::reserved_balance(&3); + assert_eq!(user_3_reserved_balance, 0); + let user_3_on_hold_balance = Balances::balance_on_hold(&LockType::Participation(0), &3); + assert_eq!(user_3_on_hold_balance, 0); + // assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), None); + + // Hold 15 ED + assert_ok!(Balances::hold(&LockType::Participation(0), &3, 15 * ED)); + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 15 * ED); + let user_3_on_hold_balance = Balances::balance_on_hold(&LockType::Participation(0), &3); + assert_eq!(user_3_on_hold_balance, 15 * ED); + let user_3_reserved_balance = Balances::reserved_balance(&3); + assert_eq!(user_3_reserved_balance, 15 * ED); + // assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), None); + + // Set release schedule to release the locked amount, starting from now, one ED per block. + let user3_vesting_schedule = VestingInfo::new(user_3_on_hold_balance, ED, 0); + assert_ok!(Vesting::set_release_schedule( + &3, + user3_vesting_schedule.locked, + user3_vesting_schedule.per_block, + user3_vesting_schedule.starting_block, + LockType::Participation(0) + )); + + assert_eq!(Vesting::vesting(&3, LockType::Participation(0)).unwrap(), vec![user3_vesting_schedule]); + let user_3_on_hold_balance = Balances::balance_on_hold(&LockType::Participation(0), &3); + assert_eq!(user_3_on_hold_balance, 15 * ED); + // assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(1 * ED)); + + // Hold 7 ED more + assert_ok!(Balances::hold(&LockType::Participation(1), &3, 7 * ED)); + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 8 * ED); + let user_3_on_hold_balance = Balances::balance_on_hold(&LockType::Participation(1), &3); + assert_eq!(user_3_on_hold_balance, 7 * ED); + let user_3_reserved_balance = Balances::reserved_balance(&3); + assert_eq!(user_3_reserved_balance, 22 * ED); + + // Set release schedule to release the locked amount, starting from now, one ED per block. + let user3_vesting_schedule = VestingInfo::new(user_3_on_hold_balance, ED, System::block_number() + 21); + assert_ok!(Vesting::set_release_schedule( + &3, + user3_vesting_schedule.locked, + user3_vesting_schedule.per_block, + user3_vesting_schedule.starting_block, + LockType::Participation(1) + )); + assert_eq!(Vesting::vesting(&3, LockType::Participation(1)).unwrap(), vec![user3_vesting_schedule]); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(1)), Some(0)); + + System::set_block_number(101); + assert_eq!(System::block_number(), 101); + assert_eq!(Vesting::vesting(&3, LockType::Participation(1)).unwrap(), vec![user3_vesting_schedule]); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(15 * ED)); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(1)), Some(7 * ED)); + assert_ok!(Vesting::vest_all(Some(3).into())); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(1)), None); + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 30 * ED); + }); +} + +#[test] +fn manual_vest_all_different_reason() { + ExtBuilder::default().existential_deposit(ED).build().execute_with(|| { + assert_eq!(System::block_number(), 1); + // Initial Status + let user_3_initial_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_initial_free_balance, 30 * ED); // 7680 ED + let user_3_reserved_balance = Balances::reserved_balance(&3); + assert_eq!(user_3_reserved_balance, 0); + let user_3_on_hold_balance = Balances::balance_on_hold(&LockType::Participation(0), &3); + assert_eq!(user_3_on_hold_balance, 0); + // assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), None); + + // Hold 15 ED + assert_ok!(Balances::hold(&LockType::Participation(0), &3, 15 * ED)); + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 15 * ED); + let user_3_on_hold_balance = Balances::balance_on_hold(&LockType::Participation(0), &3); + assert_eq!(user_3_on_hold_balance, 15 * ED); + let user_3_reserved_balance = Balances::reserved_balance(&3); + assert_eq!(user_3_reserved_balance, 15 * ED); + // assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), None); + + // Set release schedule to release the locked amount, starting from now, one ED per block. + let user3_vesting_schedule = VestingInfo::new(user_3_on_hold_balance, ED, 0); + assert_ok!(Vesting::set_release_schedule( + &3, + user3_vesting_schedule.locked, + user3_vesting_schedule.per_block, + user3_vesting_schedule.starting_block, + LockType::Participation(0) + )); + + assert_eq!(Vesting::vesting(&3, LockType::Participation(0)).unwrap(), vec![user3_vesting_schedule]); + let user_3_on_hold_balance = Balances::balance_on_hold(&LockType::Participation(0), &3); + assert_eq!(user_3_on_hold_balance, 15 * ED); + // assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(1 * ED)); + + // Hold 7 ED more + assert_ok!(Balances::hold(&LockType::Participation(1), &3, 7 * ED)); + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 8 * ED); + let user_3_on_hold_balance = Balances::balance_on_hold(&LockType::Participation(1), &3); + assert_eq!(user_3_on_hold_balance, 7 * ED); + let user_3_reserved_balance = Balances::reserved_balance(&3); + assert_eq!(user_3_reserved_balance, 22 * ED); + + // Set release schedule to release the locked amount, starting from now, one ED per block. + let user3_vesting_schedule = VestingInfo::new(user_3_on_hold_balance, ED, System::block_number() + 21); + assert_ok!(Vesting::set_release_schedule( + &3, + user3_vesting_schedule.locked, + user3_vesting_schedule.per_block, + user3_vesting_schedule.starting_block, + LockType::Participation(1) + )); + assert_eq!(Vesting::vesting(&3, LockType::Participation(1)).unwrap(), vec![user3_vesting_schedule]); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(1)), Some(0)); + + System::set_block_number(101); + assert_eq!(System::block_number(), 101); + assert_eq!(Vesting::vesting(&3, LockType::Participation(1)).unwrap(), vec![user3_vesting_schedule]); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), Some(15 * ED)); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(1)), Some(7 * ED)); + assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(0))); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(0)), None); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(1)), Some(7 * ED)); + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!( + user_3_free_balance, + user_3_initial_free_balance - Vesting::vesting_balance(&3, LockType::Participation(1)).unwrap() + ); + assert_ok!(Vesting::vest(Some(3).into(), LockType::Participation(1))); + assert_eq!(Vesting::vesting_balance(&3, LockType::Participation(1)), None); + let user_3_free_balance = Balances::free_balance(&3); + assert_eq!(user_3_free_balance, 30 * ED); + }); +} From 5db9099ef5cef1627cffc73521b78c89d2749809 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Mon, 24 Jul 2023 09:24:16 +0200 Subject: [PATCH 72/80] chore: clippy warnings --- polimec-skeleton/pallets/linear-release/src/impls.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/impls.rs b/polimec-skeleton/pallets/linear-release/src/impls.rs index 82971fc5c..4d1894986 100644 --- a/polimec-skeleton/pallets/linear-release/src/impls.rs +++ b/polimec-skeleton/pallets/linear-release/src/impls.rs @@ -114,8 +114,8 @@ impl Pallet { /// /// Returns a tuple that consists of: /// - Vec of vesting schedules, where completed schedules and those specified - /// by filter are removed. (Note the vec is not checked for respecting - /// bounded length.) + /// by filter are removed. (Note the vec is not checked for respecting + /// bounded length.) /// - The amount locked at the current block number based on the given schedules. /// /// NOTE: the amount locked does not include any schedules that are filtered out via `action`. @@ -175,7 +175,7 @@ impl Pallet { schedules.try_into().map_err(|_| Error::::AtMaxVestingSchedules)?; if schedules.len() == 0 { - Vesting::::remove(&who, reason); + Vesting::::remove(who, reason); } else { Vesting::::insert(who, reason, schedules) } @@ -229,7 +229,7 @@ impl Pallet { }; debug_assert!( - locked_now > Zero::zero() && schedules.len() > 0 || locked_now == Zero::zero() && schedules.len() == 0 + locked_now > Zero::zero() && !schedules.is_empty() || locked_now == Zero::zero() && schedules.is_empty() ); Ok((schedules, locked_now)) From c68e994f04373a525339bfdf31a3b217930e20eb Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Mon, 24 Jul 2023 09:38:51 +0200 Subject: [PATCH 73/80] feat: add pallet-linear-release to the runtime --- polimec-skeleton/runtime/Cargo.toml | 2 ++ polimec-skeleton/runtime/src/lib.rs | 26 +++++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/polimec-skeleton/runtime/Cargo.toml b/polimec-skeleton/runtime/Cargo.toml index bbd969ff5..69969b7b6 100644 --- a/polimec-skeleton/runtime/Cargo.toml +++ b/polimec-skeleton/runtime/Cargo.toml @@ -79,6 +79,7 @@ parachain-info = { git = "https://github.com/paritytech/cumulus.git", branch = " # Not from the Template pallet-funding = { path = "../pallets/funding", default-features = false } +pallet-linear-release = { path = "../pallets/linear-release", default-features = false } pallet-credentials = { path = "../pallets/credentials", default-features = false } pallet-assets = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } @@ -139,6 +140,7 @@ std = [ "parachains-common/std", "polkadot-primitives/std", "pallet-asset-tx-payment/std", + "pallet-linear-release/std" ] runtime-benchmarks = [ diff --git a/polimec-skeleton/runtime/src/lib.rs b/polimec-skeleton/runtime/src/lib.rs index 0dc93dd96..a8b19f9c6 100644 --- a/polimec-skeleton/runtime/src/lib.rs +++ b/polimec-skeleton/runtime/src/lib.rs @@ -14,7 +14,7 @@ use frame_support::{ construct_runtime, dispatch::DispatchClass, parameter_types, - traits::{AsEnsureOriginWithArg, ConstU32, ConstU64, ConstU8, EitherOfDiverse, Everything}, + traits::{AsEnsureOriginWithArg, ConstU32, ConstU64, ConstU8, EitherOfDiverse, Everything, WithdrawReasons}, weights::{ConstantMultiplier, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial}, PalletId, }; @@ -29,7 +29,7 @@ pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, BlakeTwo256, Block as BlockT}, + traits::{AccountIdLookup, ConvertInto, BlakeTwo256, Block as BlockT}, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, FixedU128, Percent, }; @@ -595,7 +595,6 @@ impl pallet_funding::Config for Runtime { type MaxProjectsToUpdatePerBlock = ConstU32<100>; type MaxEvaluationsPerUser = (); type MaxBidsPerUser = ConstU32<256>; - type MaxContributionsPerUser = ConstU32<256>; type ContributionVesting = ContributionVestingDuration; #[cfg(feature = "runtime-benchmarks")] @@ -603,6 +602,26 @@ impl pallet_funding::Config for Runtime { type WeightInfo = (); type FeeBrackets = FeeBrackets; type EvaluationSuccessThreshold = EarlyEvaluationThreshold; + type Vesting = Vesting; +} + +parameter_types! { + pub const MinVestedTransfer: Balance = 1 * PLMC; + pub UnvestedFundsAllowedWithdrawReasons: WithdrawReasons = + WithdrawReasons::except(WithdrawReasons::TRANSFER | WithdrawReasons::RESERVE); +} + +impl pallet_linear_release::Config for Runtime { + type Balance = Balance; + type BlockNumberToBalance = ConvertInto; + type Currency = Balances; + type MinVestedTransfer = MinVestedTransfer; + type Reason = BondTypeOf; + type RuntimeEvent = RuntimeEvent; + type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; + type WeightInfo = (); + + const MAX_VESTING_SCHEDULES: u32 = 12; } impl pallet_credentials::Config for Runtime { @@ -652,6 +671,7 @@ construct_runtime!( Random: pallet_insecure_randomness_collective_flip = 40, Funding: pallet_funding = 41, Credentials: pallet_credentials = 42, + Vesting: pallet_linear_release = 43, } ); From 0817995b01b0b3df818a7657e5e41efb635f5191 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Mon, 24 Jul 2023 09:43:10 +0200 Subject: [PATCH 74/80] feat: add default genesis config to the node --- polimec-skeleton/node/src/chain_spec.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/polimec-skeleton/node/src/chain_spec.rs b/polimec-skeleton/node/src/chain_spec.rs index 6229daf4a..3416ed5f4 100644 --- a/polimec-skeleton/node/src/chain_spec.rs +++ b/polimec-skeleton/node/src/chain_spec.rs @@ -216,5 +216,6 @@ fn testnet_genesis( }, transaction_payment: Default::default(), credentials: Default::default(), + vesting: Default::default() } } From 3d14489c716283ce81d04ed938e3d62c44deb674 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Mon, 24 Jul 2023 13:04:46 +0200 Subject: [PATCH 75/80] chore: fmt --- polimec-skeleton/Cargo.lock | 1678 +++++++++-------- polimec-skeleton/node/src/chain_spec.rs | 34 +- polimec-skeleton/node/src/cli.rs | 15 +- polimec-skeleton/node/src/command.rs | 69 +- polimec-skeleton/node/src/rpc.rs | 6 +- polimec-skeleton/node/src/service.rs | 58 +- .../pallets/credentials/src/lib.rs | 22 +- .../pallets/credentials/src/mock.rs | 60 +- .../pallets/credentials/src/tests.rs | 25 +- polimec-skeleton/pallets/funding/Cargo.toml | 2 +- .../pallets/funding/src/benchmarking.rs | 10 +- .../pallets/funding/src/functions.rs | 517 ++--- polimec-skeleton/pallets/funding/src/impls.rs | 148 +- polimec-skeleton/pallets/funding/src/lib.rs | 132 +- polimec-skeleton/pallets/funding/src/mock.rs | 165 +- polimec-skeleton/pallets/funding/src/tests.rs | 1173 ++++-------- .../pallets/funding/src/traits.rs | 2 - polimec-skeleton/pallets/funding/src/types.rs | 39 +- .../pallets/linear-release/Cargo.toml | 7 +- .../pallets/linear-release/src/lib.rs | 4 +- .../pallets/linear-release/src/mock.rs | 3 +- .../pallets/linear-release/src/tests.rs | 6 +- polimec-skeleton/runtime/build.rs | 6 +- polimec-skeleton/runtime/src/lib.rs | 266 ++- .../runtime/src/weights/block_weights.rs | 5 +- .../runtime/src/weights/extrinsic_weights.rs | 10 +- polimec-skeleton/runtime/src/xcm_config.rs | 107 +- 27 files changed, 1972 insertions(+), 2597 deletions(-) diff --git a/polimec-skeleton/Cargo.lock b/polimec-skeleton/Cargo.lock index c94f071d5..cec5fc1a0 100644 --- a/polimec-skeleton/Cargo.lock +++ b/polimec-skeleton/Cargo.lock @@ -23,11 +23,11 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" dependencies = [ - "gimli 0.27.2", + "gimli 0.27.3", ] [[package]] @@ -90,9 +90,9 @@ dependencies = [ [[package]] name = "aes" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433cfd6710c9986c576a25ca913c39d66a6474107b406f34f91d4a8923395241" +checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" dependencies = [ "cfg-if", "cipher 0.4.4", @@ -115,12 +115,12 @@ dependencies = [ [[package]] name = "aes-gcm" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e1366e0c69c9f927b1fa5ce2c7bf9eafc8f9268c0b9800729e8b267612447c" +checksum = "209b47e8954a928e1d72e86eca7000ebb6655fe1436d33eefc2201cad027e237" dependencies = [ "aead 0.5.2", - "aes 0.8.2", + "aes 0.8.3", "cipher 0.4.4", "ctr 0.9.2", "ghash 0.5.0", @@ -153,7 +153,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.9", + "getrandom 0.2.10", "once_cell", "version_check", ] @@ -165,25 +165,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ "cfg-if", - "getrandom 0.2.9", + "getrandom 0.2.10", "once_cell", "version_check", ] [[package]] name = "aho-corasick" -version = "0.7.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" -dependencies = [ - "memchr", -] - -[[package]] -name = "aho-corasick" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" dependencies = [ "memchr", ] @@ -194,6 +185,12 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4436e0292ab1bb631b42973c61205e704475fe8126af845c8d923c0996328127" +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -229,15 +226,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" +checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" [[package]] name = "anstyle-parse" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" dependencies = [ "utf8parse", ] @@ -263,9 +260,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" [[package]] name = "approx" @@ -308,9 +305,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "arrayvec" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "asn1-rs" @@ -325,7 +322,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.21", + "time 0.3.23", ] [[package]] @@ -341,7 +338,7 @@ dependencies = [ "num-traits", "rusticata-macros", "thiserror", - "time 0.3.21", + "time 0.3.23", ] [[package]] @@ -393,9 +390,9 @@ checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "async-channel" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", "event-listener", @@ -416,9 +413,9 @@ dependencies = [ "log", "parking", "polling", - "rustix 0.37.19", + "rustix 0.37.23", "slab", - "socket2", + "socket2 0.4.9", "waker-fn", ] @@ -439,31 +436,31 @@ checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "asynchronous-codec" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06a0daa378f5fd10634e44b0a29b2a87b890657658e072a30d6f26e57ddee182" +checksum = "4057f2c32adbb2fc158e22fb38433c8e9bbf76b75a4732c7c0cbaf695fb65568" dependencies = [ "bytes", "futures-sink", "futures-util", "memchr", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", ] [[package]] @@ -491,16 +488,16 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" dependencies = [ - "addr2line 0.19.0", + "addr2line 0.20.0", "cc", "cfg-if", "libc", - "miniz_oxide 0.6.2", - "object 0.30.3", + "miniz_oxide", + "object 0.31.1", "rustc-demangle", ] @@ -530,9 +527,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.0" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" [[package]] name = "base64ct" @@ -552,7 +549,7 @@ dependencies = [ [[package]] name = "binary-merkle-tree" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "hash-db", "log", @@ -573,7 +570,7 @@ version = "0.64.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cexpr", "clang-sys", "lazy_static", @@ -593,6 +590,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" + [[package]] name = "bitvec" version = "1.0.1" @@ -611,7 +614,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -621,8 +624,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc" dependencies = [ "arrayref", - "arrayvec 0.7.2", - "constant_time_eq", + "arrayvec 0.7.4", + "constant_time_eq 0.2.6", ] [[package]] @@ -632,22 +635,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6637f448b9e61dfadbdcbae9a885fadee1f3eaffb1f8d3c1965d3ade8bdfd44f" dependencies = [ "arrayref", - "arrayvec 0.7.2", - "constant_time_eq", + "arrayvec 0.7.4", + "constant_time_eq 0.2.6", ] [[package]] name = "blake3" -version = "1.3.3" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef" +checksum = "199c42ab6972d92c9f8995f086273d25c42fc0f7b2a1fcefba465c1352d25ba5" dependencies = [ "arrayref", - "arrayvec 0.7.2", + "arrayvec 0.7.4", "cc", "cfg-if", - "constant_time_eq", - "digest 0.10.6", + "constant_time_eq 0.3.0", + "digest 0.10.7", ] [[package]] @@ -707,9 +710,9 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "bounded-collections" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07fbd1d11282a1eb134d3c3b7cf8ce213b5161c6e5f73fb1b98618482c606b64" +checksum = "eb5b05133427c07c4776906f673ccf36c21b102c9829c641a5b56bd151d44fd6" dependencies = [ "log", "parity-scale-codec", @@ -734,9 +737,9 @@ checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] name = "bstr" -version = "1.4.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09" +checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" dependencies = [ "memchr", "serde", @@ -753,9 +756,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.12.2" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c6ed94e98ecff0c12dd1b04c15ec0d7d9458ca8fe806cea6f12954efe74c63b" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "byte-slice-cast" @@ -800,18 +803,18 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.4" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" dependencies = [ "serde", ] [[package]] name = "cargo-platform" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27" +checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479" dependencies = [ "serde", ] @@ -824,7 +827,7 @@ checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" dependencies = [ "camino", "cargo-platform", - "semver 1.0.17", + "semver 1.0.18", "serde", "serde_json", "thiserror", @@ -907,13 +910,13 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.24" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" dependencies = [ + "android-tzdata", "iana-time-zone", "js-sys", - "num-integer", "num-traits", "time 0.1.45", "wasm-bindgen", @@ -983,9 +986,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.2.7" +version = "4.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34d21f9bf1b425d2968943631ec91202fe5e837264063503708b83013f8fc938" +checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" dependencies = [ "clap_builder", "clap_derive", @@ -994,34 +997,33 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.2.7" +version = "4.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914c8c79fb560f238ef6429439a30023c862f7a28e688c58f7203f12b29970bd" +checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1" dependencies = [ "anstream", "anstyle", - "bitflags", "clap_lex", "strsim", ] [[package]] name = "clap_derive" -version = "4.2.0" +version = "4.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" +checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "clap_lex" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" [[package]] name = "coarsetime" @@ -1074,9 +1076,9 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "comfy-table" -version = "6.1.4" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e7b787b0dc42e8111badfdbe4c3059158ccb2db8780352fa1b01e8ccf45cc4d" +checksum = "7e959d788268e3bf9d35ace83e81b124190378e4c91c9067524675e33394b8ba" dependencies = [ "strum", "strum_macros", @@ -1092,17 +1094,36 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "console" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.45.0", +] + [[package]] name = "const-oid" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" +checksum = "795bc6e66a8e340f075fcf6227e417a2dc976b92b91f3cdc778bb858778b6747" [[package]] name = "constant_time_eq" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13418e745008f7349ec7e449155f419a61b92b58a99cc3616942b926825ec76b" +checksum = "21a53c0a4d288377e7415b53dcfc3c04da5cdc2cc95c8d5ac178b58f0b861ad6" + +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" [[package]] name = "convert_case" @@ -1156,9 +1177,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] @@ -1178,7 +1199,7 @@ version = "0.93.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "253531aca9b6f56103c9420369db3263e784df39aa1c90685a1f69cfbba0623e" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "bumpalo", "cranelift-bforest", "cranelift-codegen-meta", @@ -1309,14 +1330,14 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.14" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", - "memoffset 0.8.0", + "memoffset 0.9.0", "scopeguard", ] @@ -1332,9 +1353,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", ] @@ -1661,7 +1682,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] @@ -1952,9 +1973,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.94" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" +checksum = "f68e12e817cb19eaab81aaec582b4052d07debd3c3c6b083b9d361db47c7dc9d" dependencies = [ "cc", "cxxbridge-flags", @@ -1964,9 +1985,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.94" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" +checksum = "e789217e4ab7cf8cc9ce82253180a9fe331f35f5d339f0ccfe0270b39433f397" dependencies = [ "cc", "codespan-reporting", @@ -1974,24 +1995,24 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "cxxbridge-flags" -version = "1.0.94" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" +checksum = "78a19f4c80fd9ab6c882286fa865e92e07688f4387370a209508014ead8751d0" [[package]] name = "cxxbridge-macro" -version = "1.0.94" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" +checksum = "b8fcfa71f66c8563c4fa9dd2bb68368d50267856f831ac5d85367e0805f9606c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] @@ -2031,15 +2052,15 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb" +checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "data-encoding-macro" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86927b7cd2fe88fa698b87404b287ab98d1a0063a34071d92e575b72d3029aca" +checksum = "c904b33cc60130e1aeea4956ab803d08a3f4a0ca82d64ed757afac3891f2bb99" dependencies = [ "data-encoding", "data-encoding-macro-internal", @@ -2047,9 +2068,9 @@ dependencies = [ [[package]] name = "data-encoding-macro-internal" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5bbed42daaa95e780b60a50546aa345b8413a1e46f9a40a12907d3598f038db" +checksum = "8fdf3fce3ce863539ec1d7fd1b6dcc3c645663376b43ed376bbf887733e4f772" dependencies = [ "data-encoding", "syn 1.0.109", @@ -2068,9 +2089,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.5" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e58dffcdcc8ee7b22f0c1f71a69243d7c2d9ad87b5a14361f2424a1565c219" +checksum = "0c7ed52955ce76b1554f509074bb357d3fb8ac9b51288a65a3fd480d1dfba946" dependencies = [ "const-oid", "zeroize", @@ -2196,9 +2217,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "const-oid", @@ -2255,7 +2276,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] @@ -2272,9 +2293,9 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" [[package]] name = "dtoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65d09067bfacaa79114679b279d7f5885b53295b1e2cfb4e79c8e4bd3d633169" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" [[package]] name = "dyn-clonable" @@ -2299,9 +2320,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b0cf012f1230e43cd00ebb729c6bb58707ecfa8ad08b52ef3a4ccd2697fc30" +checksum = "304e6508efa593091e97a9abbc10f90aa7ca635b6d2784feff3c89d41dd12272" [[package]] name = "ecdsa" @@ -2317,13 +2338,13 @@ dependencies = [ [[package]] name = "ecdsa" -version = "0.16.7" +version = "0.16.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428" +checksum = "a4b1e0c257a9e9f25f90ff76d7a68360ed497ee519c8e428d1825ef0000799d4" dependencies = [ - "der 0.7.5", - "digest 0.10.6", - "elliptic-curve 0.13.4", + "der 0.7.7", + "digest 0.10.7", + "elliptic-curve 0.13.5", "rfc6979 0.4.0", "signature 2.1.0", "spki 0.7.2", @@ -2368,9 +2389,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "elliptic-curve" @@ -2381,7 +2402,7 @@ dependencies = [ "base16ct 0.1.1", "crypto-bigint 0.4.9", "der 0.6.1", - "digest 0.10.6", + "digest 0.10.7", "ff 0.12.1", "generic-array 0.14.7", "group 0.12.1", @@ -2396,23 +2417,29 @@ dependencies = [ [[package]] name = "elliptic-curve" -version = "0.13.4" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75c71eaa367f2e5d556414a8eea812bc62985c879748d6403edabd9cb03f16e7" +checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" dependencies = [ "base16ct 0.2.0", "crypto-bigint 0.5.2", - "digest 0.10.6", + "digest 0.10.7", "ff 0.13.0", "generic-array 0.14.7", "group 0.13.0", "pkcs8 0.10.2", "rand_core 0.6.4", - "sec1 0.7.2", + "sec1 0.7.3", "subtle", "zeroize", ] +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + [[package]] name = "enum-as-inner" version = "0.5.1" @@ -2442,18 +2469,18 @@ checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "enumn" -version = "0.1.8" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48016319042fb7c87b78d2993084a831793a897a5cd1a2a67cab9d1eeb4b7d76" +checksum = "b893c4eb2dc092c811165f84dc7447fae16fb66521717968c34c509b39b1a5c5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] @@ -2488,6 +2515,12 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48c92028aaa870e83d51c64e5d4e0b6981b360c522198c23959f219a4e1b15b" +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "errno" version = "0.3.1" @@ -2571,7 +2604,7 @@ dependencies = [ "fs-err", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] @@ -2595,6 +2628,12 @@ dependencies = [ "instant", ] +[[package]] +name = "fastrand" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" + [[package]] name = "fatality" version = "0.0.6" @@ -2612,7 +2651,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5aa1e3ae159e592ad222dc90c5acbad632b527779ba88486abe92782ab268bd" dependencies = [ "expander 0.0.4", - "indexmap", + "indexmap 1.9.3", "proc-macro-crate", "proc-macro2", "quote", @@ -2719,7 +2758,7 @@ checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743" dependencies = [ "crc32fast", "libz-sys", - "miniz_oxide 0.7.1", + "miniz_oxide", ] [[package]] @@ -2740,16 +2779,16 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "fork-tree" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", ] [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] @@ -2763,7 +2802,7 @@ checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" [[package]] name = "frame-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-support-procedural", @@ -2788,7 +2827,7 @@ dependencies = [ [[package]] name = "frame-benchmarking-cli" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "Inflector", "array-bytes 4.2.0", @@ -2835,18 +2874,18 @@ dependencies = [ [[package]] name = "frame-election-provider-solution-type" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "frame-election-provider-support" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-election-provider-solution-type", "frame-support", @@ -2863,7 +2902,7 @@ dependencies = [ [[package]] name = "frame-executive" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -2892,10 +2931,11 @@ dependencies = [ [[package]] name = "frame-remote-externalities" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-recursion", "futures", + "indicatif", "jsonrpsee", "log", "parity-scale-codec", @@ -2903,6 +2943,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", + "spinners", "substrate-rpc-client", "tokio", ] @@ -2910,9 +2951,9 @@ dependencies = [ [[package]] name = "frame-support" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ - "bitflags", + "bitflags 1.3.2", "environmental", "frame-metadata", "frame-support-procedural", @@ -2943,7 +2984,7 @@ dependencies = [ [[package]] name = "frame-support-procedural" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "Inflector", "cfg-expr", @@ -2953,35 +2994,35 @@ dependencies = [ "proc-macro-warning", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "frame-support-procedural-tools" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support-procedural-tools-derive", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "frame-support-procedural-tools-derive" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "frame-system" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "log", @@ -2999,7 +3040,7 @@ dependencies = [ [[package]] name = "frame-system-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -3014,7 +3055,7 @@ dependencies = [ [[package]] name = "frame-system-rpc-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "sp-api", @@ -3023,7 +3064,7 @@ dependencies = [ [[package]] name = "frame-try-runtime" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "parity-scale-codec", @@ -3050,11 +3091,11 @@ dependencies = [ [[package]] name = "fs4" -version = "0.6.4" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f5b6908aecca5812a4569056285e58c666588c9573ee59765bf1d3692699e2" +checksum = "2eeb4ed9e12f43b7fa0baae3f9cdda28352770132ef2e09a23760c29cae8bd47" dependencies = [ - "rustix 0.37.19", + "rustix 0.38.4", "windows-sys 0.48.0", ] @@ -3119,12 +3160,12 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" dependencies = [ - "fastrand", + "fastrand 1.9.0", "futures-core", "futures-io", "memchr", "parking", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "waker-fn", ] @@ -3136,7 +3177,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] @@ -3181,7 +3222,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "pin-utils", "slab", ] @@ -3238,9 +3279,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", @@ -3264,7 +3305,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" dependencies = [ "opaque-debug 0.3.0", - "polyval 0.6.0", + "polyval 0.6.1", ] [[package]] @@ -3274,15 +3315,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" dependencies = [ "fallible-iterator", - "indexmap", + "indexmap 1.9.3", "stable_deref_trait", ] [[package]] name = "gimli" -version = "0.27.2" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" [[package]] name = "glob" @@ -3292,11 +3333,11 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +checksum = "1391ab1f92ffcc08911957149833e682aa3fe252b9f45f966d2ef972274c97df" dependencies = [ - "aho-corasick 0.7.20", + "aho-corasick", "bstr", "fnv", "log", @@ -3327,9 +3368,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.19" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" +checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" dependencies = [ "bytes", "fnv", @@ -3337,7 +3378,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 1.9.3", "slab", "tokio", "tokio-util", @@ -3391,6 +3432,12 @@ dependencies = [ "ahash 0.8.3", ] +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + [[package]] name = "heck" version = "0.4.1" @@ -3408,18 +3455,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "hex" @@ -3468,7 +3506,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -3512,14 +3550,14 @@ checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes", "http", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", ] [[package]] name = "http-range-header" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" +checksum = "add0ab9360ddbd88cfeb3bd9574a1d85cfdfa14db10b3e21d3700dbc4328758f" [[package]] name = "httparse" @@ -3541,9 +3579,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.26" +version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ "bytes", "futures-channel", @@ -3555,8 +3593,8 @@ dependencies = [ "httparse", "httpdate", "itoa", - "pin-project-lite 0.2.9", - "socket2", + "pin-project-lite 0.2.10", + "socket2 0.4.9", "tokio", "tower-service", "tracing", @@ -3581,9 +3619,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.56" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3621,9 +3659,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -3698,6 +3736,29 @@ dependencies = [ "serde", ] +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown 0.14.0", +] + +[[package]] +name = "indicatif" +version = "0.17.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ff8cc23a7393a397ed1d7f56e6365cba772aba9f9912ab968b03043c395d057" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "unicode-width", +] + [[package]] name = "inout" version = "0.1.3" @@ -3752,11 +3813,11 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi 0.3.2", "libc", "windows-sys 0.48.0", ] @@ -3769,31 +3830,30 @@ checksum = "aa2f047c0a98b2f299aa5d6d7088443570faae494e9ae1305e48be000c9e0eb1" [[package]] name = "ipconfig" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd302af1b90f2463a98fa5ad469fc212c8e3175a41c3068601bfa2727591c5be" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" dependencies = [ - "socket2", + "socket2 0.5.3", "widestring", - "winapi", + "windows-sys 0.48.0", "winreg", ] [[package]] name = "ipnet" -version = "2.7.2" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" +checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" [[package]] name = "is-terminal" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ - "hermit-abi 0.3.1", - "io-lifetimes", - "rustix 0.37.19", + "hermit-abi 0.3.2", + "rustix 0.38.4", "windows-sys 0.48.0", ] @@ -3817,9 +3877,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jobserver" @@ -3832,9 +3892,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.63" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] @@ -3882,7 +3942,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4e70b4439a751a5de7dd5ed55eacff78ebf4ffe0fc009cb1ebb11417f5b536b" dependencies = [ "anyhow", - "arrayvec 0.7.2", + "arrayvec 0.7.4", "async-lock", "async-trait", "beef", @@ -3990,10 +4050,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cadb76004ed8e97623117f3df85b17aaa6626ab0b0831e6573f104df16cd1bcc" dependencies = [ "cfg-if", - "ecdsa 0.16.7", - "elliptic-curve 0.13.4", + "ecdsa 0.16.8", + "elliptic-curve 0.13.5", "once_cell", - "sha2 0.10.6", + "sha2 0.10.7", ] [[package]] @@ -4008,7 +4068,7 @@ dependencies = [ [[package]] name = "kusama-runtime" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitvec", "frame-benchmarking", @@ -4106,7 +4166,7 @@ dependencies = [ [[package]] name = "kusama-runtime-constants" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "frame-support", "polkadot-primitives", @@ -4164,9 +4224,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.144" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libloading" @@ -4199,7 +4259,7 @@ dependencies = [ "bytes", "futures", "futures-timer", - "getrandom 0.2.9", + "getrandom 0.2.10", "instant", "libp2p-core 0.38.0", "libp2p-dns", @@ -4250,7 +4310,7 @@ dependencies = [ "rand 0.8.5", "rw-stream-sink", "sec1 0.3.0", - "sha2 0.10.6", + "sha2 0.10.7", "smallvec", "thiserror", "unsigned-varint", @@ -4334,7 +4394,7 @@ dependencies = [ "multihash 0.17.0", "quick-protobuf", "rand 0.8.5", - "sha2 0.10.6", + "sha2 0.10.7", "thiserror", "zeroize", ] @@ -4345,7 +4405,7 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2766dcd2be8c87d5e1f35487deb22d765f49c6ae1251b3633efe3b25698bd3d2" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "asynchronous-codec", "bytes", "either", @@ -4359,7 +4419,7 @@ dependencies = [ "prost", "prost-build", "rand 0.8.5", - "sha2 0.10.6", + "sha2 0.10.7", "smallvec", "thiserror", "uint", @@ -4381,7 +4441,7 @@ dependencies = [ "log", "rand 0.8.5", "smallvec", - "socket2", + "socket2 0.4.9", "tokio", "trust-dns-proto", "void", @@ -4434,7 +4494,7 @@ dependencies = [ "prost", "prost-build", "rand 0.8.5", - "sha2 0.10.6", + "sha2 0.10.7", "snow", "static_assertions", "thiserror", @@ -4542,7 +4602,7 @@ dependencies = [ "libc", "libp2p-core 0.38.0", "log", - "socket2", + "socket2 0.4.9", "tokio", ] @@ -4708,9 +4768,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.9" +version = "1.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ee889ecc9568871456d42f603d6a0ce59ff328d291063a45cbdf0036baf6db" +checksum = "24e6ab01971eb092ffe6a7d42f49f9ff42662f17604681e2843ad65077ba47dc" dependencies = [ "cc", "pkg-config", @@ -4719,9 +4779,9 @@ dependencies = [ [[package]] name = "link-cplusplus" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" dependencies = [ "cc", ] @@ -4743,9 +4803,9 @@ dependencies = [ [[package]] name = "linregress" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "475015a7f8f017edb28d2e69813be23500ad4b32cfe3421c4148efc97324ee52" +checksum = "4de0b5f52a9f84544d268f5fabb71b38962d6aa3c6600b8bcd27d44ccf9c9c45" dependencies = [ "nalgebra", ] @@ -4758,15 +4818,21 @@ checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" [[package]] name = "linux-raw-sys" -version = "0.3.7" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "linux-raw-sys" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f" +checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", @@ -4774,12 +4840,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "lru" @@ -4837,6 +4900,12 @@ dependencies = [ "libc", ] +[[package]] +name = "maplit" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" + [[package]] name = "match_cfg" version = "0.1.0" @@ -4849,7 +4918,7 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] @@ -4874,7 +4943,7 @@ version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -4889,7 +4958,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffc89ccdc6e10d6907450f753537ebc5c5d3460d2e4e62ea74bd571db62c0f9e" dependencies = [ - "rustix 0.37.19", + "rustix 0.37.23", ] [[package]] @@ -4912,9 +4981,9 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] @@ -4963,15 +5032,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "miniz_oxide" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.7.1" @@ -4983,20 +5043,19 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] name = "mmr-gadget" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "futures", "log", @@ -5015,7 +5074,7 @@ dependencies = [ [[package]] name = "mmr-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "anyhow", "jsonrpsee", @@ -5113,9 +5172,9 @@ dependencies = [ "blake2s_simd", "blake3", "core2", - "digest 0.10.6", + "digest 0.10.7", "multihash-derive", - "sha2 0.10.6", + "sha2 0.10.7", "sha3", "unsigned-varint", ] @@ -5167,9 +5226,9 @@ dependencies = [ [[package]] name = "nalgebra" -version = "0.32.2" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d68d47bba83f9e2006d117a9a33af1524e655516b8919caac694427a6fb1e511" +checksum = "307ed9b18cc2423f29e83f84fd23a8e73628727990181f18641a8b5dc2ab1caa" dependencies = [ "approx", "matrixmultiply", @@ -5183,9 +5242,9 @@ dependencies = [ [[package]] name = "nalgebra-macros" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d232c68884c0c99810a5a4d333ef7e47689cfd0edc85efc9e54e1e6bf5212766" +checksum = "91761aed67d03ad966ef783ae962ef9bbaca728d2dd7ceb7939ec110fffad998" dependencies = [ "proc-macro2", "quote", @@ -5226,7 +5285,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9ea4302b9759a7a88242299225ea3688e63c85ea136371bb6cf94fd674efaab" dependencies = [ "anyhow", - "bitflags", + "bitflags 1.3.2", "byteorder", "libc", "netlink-packet-core", @@ -5279,7 +5338,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "libc", "memoffset 0.6.5", @@ -5333,7 +5392,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "itoa", ] @@ -5361,23 +5420,29 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi 0.3.2", "libc", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "object" version = "0.29.0" @@ -5386,15 +5451,15 @@ checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ "crc32fast", "hashbrown 0.12.3", - "indexmap", + "indexmap 1.9.3", "memchr", ] [[package]] name = "object" -version = "0.30.3" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" dependencies = [ "memchr", ] @@ -5419,9 +5484,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "opaque-debug" @@ -5490,7 +5555,7 @@ checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" dependencies = [ "ecdsa 0.14.8", "elliptic-curve 0.12.3", - "sha2 0.10.6", + "sha2 0.10.7", ] [[package]] @@ -5501,7 +5566,7 @@ checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa" dependencies = [ "ecdsa 0.14.8", "elliptic-curve 0.12.3", - "sha2 0.10.6", + "sha2 0.10.7", ] [[package]] @@ -5517,7 +5582,7 @@ dependencies = [ [[package]] name = "pallet-asset-tx-payment" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5535,7 +5600,7 @@ dependencies = [ [[package]] name = "pallet-assets" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5550,7 +5615,7 @@ dependencies = [ [[package]] name = "pallet-aura" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -5566,7 +5631,7 @@ dependencies = [ [[package]] name = "pallet-authority-discovery" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -5582,7 +5647,7 @@ dependencies = [ [[package]] name = "pallet-authorship" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -5596,7 +5661,7 @@ dependencies = [ [[package]] name = "pallet-babe" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5620,7 +5685,7 @@ dependencies = [ [[package]] name = "pallet-bags-list" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -5640,7 +5705,7 @@ dependencies = [ [[package]] name = "pallet-balances" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5655,7 +5720,7 @@ dependencies = [ [[package]] name = "pallet-beefy" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -5674,7 +5739,7 @@ dependencies = [ [[package]] name = "pallet-beefy-mmr" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", "binary-merkle-tree", @@ -5698,7 +5763,7 @@ dependencies = [ [[package]] name = "pallet-bounties" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5716,7 +5781,7 @@ dependencies = [ [[package]] name = "pallet-child-bounties" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5754,7 +5819,7 @@ dependencies = [ [[package]] name = "pallet-collective" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5771,7 +5836,7 @@ dependencies = [ [[package]] name = "pallet-conviction-voting" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "assert_matches", "frame-benchmarking", @@ -5805,7 +5870,7 @@ dependencies = [ [[package]] name = "pallet-democracy" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5823,7 +5888,7 @@ dependencies = [ [[package]] name = "pallet-election-provider-multi-phase" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -5846,7 +5911,7 @@ dependencies = [ [[package]] name = "pallet-election-provider-support-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -5859,7 +5924,7 @@ dependencies = [ [[package]] name = "pallet-elections-phragmen" version = "5.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5877,7 +5942,7 @@ dependencies = [ [[package]] name = "pallet-fast-unstake" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -5919,7 +5984,7 @@ dependencies = [ [[package]] name = "pallet-grandpa" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5942,7 +6007,7 @@ dependencies = [ [[package]] name = "pallet-identity" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "enumflags2", "frame-benchmarking", @@ -5958,7 +6023,7 @@ dependencies = [ [[package]] name = "pallet-im-online" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5978,7 +6043,7 @@ dependencies = [ [[package]] name = "pallet-indices" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -5995,7 +6060,7 @@ dependencies = [ [[package]] name = "pallet-insecure-randomness-collective-flip" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -6014,9 +6079,10 @@ dependencies = [ "frame-system", "log", "pallet-balances", + "pallet-funding", "parity-scale-codec", + "polimec-traits", "scale-info", - "serde", "sp-core", "sp-io", "sp-runtime", @@ -6026,7 +6092,7 @@ dependencies = [ [[package]] name = "pallet-membership" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6043,7 +6109,7 @@ dependencies = [ [[package]] name = "pallet-mmr" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6060,7 +6126,7 @@ dependencies = [ [[package]] name = "pallet-multisig" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6076,7 +6142,7 @@ dependencies = [ [[package]] name = "pallet-nis" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6092,7 +6158,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools" version = "1.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -6109,7 +6175,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-benchmarking" version = "1.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -6129,7 +6195,7 @@ dependencies = [ [[package]] name = "pallet-nomination-pools-runtime-api" version = "1.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "pallet-nomination-pools", "parity-scale-codec", @@ -6140,7 +6206,7 @@ dependencies = [ [[package]] name = "pallet-offences" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -6157,7 +6223,7 @@ dependencies = [ [[package]] name = "pallet-offences-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -6181,7 +6247,7 @@ dependencies = [ [[package]] name = "pallet-preimage" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6198,7 +6264,7 @@ dependencies = [ [[package]] name = "pallet-proxy" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6213,7 +6279,7 @@ dependencies = [ [[package]] name = "pallet-ranked-collective" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6231,7 +6297,7 @@ dependencies = [ [[package]] name = "pallet-recovery" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6246,7 +6312,7 @@ dependencies = [ [[package]] name = "pallet-referenda" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "assert_matches", "frame-benchmarking", @@ -6265,7 +6331,7 @@ dependencies = [ [[package]] name = "pallet-scheduler" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6282,7 +6348,7 @@ dependencies = [ [[package]] name = "pallet-session" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -6303,7 +6369,7 @@ dependencies = [ [[package]] name = "pallet-session-benchmarking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6319,7 +6385,7 @@ dependencies = [ [[package]] name = "pallet-society" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -6333,7 +6399,7 @@ dependencies = [ [[package]] name = "pallet-staking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-election-provider-support", @@ -6356,18 +6422,18 @@ dependencies = [ [[package]] name = "pallet-staking-reward-curve" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "pallet-staking-reward-fn" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "log", "sp-arithmetic", @@ -6376,7 +6442,7 @@ dependencies = [ [[package]] name = "pallet-staking-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "sp-api", @@ -6385,7 +6451,7 @@ dependencies = [ [[package]] name = "pallet-state-trie-migration" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6402,7 +6468,7 @@ dependencies = [ [[package]] name = "pallet-sudo" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -6416,7 +6482,7 @@ dependencies = [ [[package]] name = "pallet-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6434,7 +6500,7 @@ dependencies = [ [[package]] name = "pallet-tips" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6453,7 +6519,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-support", "frame-system", @@ -6469,7 +6535,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "jsonrpsee", "pallet-transaction-payment-rpc-runtime-api", @@ -6485,7 +6551,7 @@ dependencies = [ [[package]] name = "pallet-transaction-payment-rpc-runtime-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "pallet-transaction-payment", "parity-scale-codec", @@ -6497,7 +6563,7 @@ dependencies = [ [[package]] name = "pallet-treasury" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6514,7 +6580,7 @@ dependencies = [ [[package]] name = "pallet-utility" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6530,7 +6596,7 @@ dependencies = [ [[package]] name = "pallet-vesting" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6545,7 +6611,7 @@ dependencies = [ [[package]] name = "pallet-whitelist" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-benchmarking", "frame-support", @@ -6560,7 +6626,7 @@ dependencies = [ [[package]] name = "pallet-xcm" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bounded-collections", "frame-benchmarking", @@ -6581,7 +6647,7 @@ dependencies = [ [[package]] name = "pallet-xcm-benchmarks" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "frame-benchmarking", "frame-support", @@ -6694,6 +6760,7 @@ dependencies = [ "pallet-credentials", "pallet-funding", "pallet-insecure-randomness-collective-flip", + "pallet-linear-release", "pallet-session", "pallet-sudo", "pallet-timestamp", @@ -6754,9 +6821,9 @@ dependencies = [ [[package]] name = "parity-db" -version = "0.4.8" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4890dcb9556136a4ec2b0c51fa4a08c8b733b829506af8fff2e853f3a065985b" +checksum = "78f19d20a0d2cc52327a88d131fa1c4ea81ea4a04714aedcfeca2dd410049cf8" dependencies = [ "blake2", "crc32fast", @@ -6774,11 +6841,11 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.5.0" +version = "3.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ddb756ca205bd108aee3c62c6d3c994e1df84a59b9d6d4a5ea42ee1fd5a9a28" +checksum = "dd8e946cc0cc711189c0b0249fb8b599cbeeab9784d83c415719368bb8d4ac64" dependencies = [ - "arrayvec 0.7.2", + "arrayvec 0.7.4", "bitvec", "byte-slice-cast", "bytes", @@ -6789,9 +6856,9 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.1.4" +version = "3.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b26a931f824dd4eca30b3e43bb4f31cd5f0d3a403c5f5ff27106b805bfde7b" +checksum = "2a296c3079b5fefbc499e1de58dc26c09b1b9a5952d26694ee89f04a43ebbb3e" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -6835,7 +6902,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.9.7", + "parking_lot_core 0.9.8", ] [[package]] @@ -6854,22 +6921,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.7" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.2.16", + "redox_syscall 0.3.5", "smallvec", - "windows-sys 0.45.0", + "windows-targets 0.48.1", ] [[package]] name = "paste" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "pbkdf2" @@ -6886,7 +6953,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -6915,15 +6982,15 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e68e84bfb01f0507134eac1e9b410a12ba379d064eab48c50ba4ce329a527b70" +checksum = "0d2d1d55045829d65aad9d389139882ad623b33b904e7c9f1b10c5b8927298e5" dependencies = [ "thiserror", "ucd-trie", @@ -6931,9 +6998,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b79d4c71c865a25a4322296122e3924d30bc8ee0834c8bfc8b95f7f054afbfb" +checksum = "5f94bca7e7a599d89dea5dfa309e217e7906c3c007fb9c3299c40b10d6a315d3" dependencies = [ "pest", "pest_generator", @@ -6941,26 +7008,26 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c435bf1076437b851ebc8edc3a18442796b30f1728ffea6262d59bbe28b077e" +checksum = "99d490fe7e8556575ff6911e45567ab95e71617f43781e5c05490dc8d75c965c" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "pest_meta" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "745a452f8eb71e39ffd8ee32b3c5f51d03845f99786fa9b68db6ff509c505411" +checksum = "2674c66ebb4b4d9036012091b537aae5878970d6999f81a265034d85b136b341" dependencies = [ "once_cell", "pest", - "sha2 0.10.6", + "sha2 0.10.7", ] [[package]] @@ -6970,27 +7037,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ "fixedbitset", - "indexmap", + "indexmap 1.9.3", ] [[package]] name = "pin-project" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] @@ -7001,9 +7068,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" [[package]] name = "pin-utils" @@ -7027,7 +7094,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.5", + "der 0.7.7", "spki 0.7.2", ] @@ -7068,7 +7135,7 @@ dependencies = [ [[package]] name = "polkadot-approval-distribution" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "futures", "polkadot-node-jaeger", @@ -7084,7 +7151,7 @@ dependencies = [ [[package]] name = "polkadot-availability-bitfield-distribution" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "futures", "polkadot-node-network-protocol", @@ -7098,7 +7165,7 @@ dependencies = [ [[package]] name = "polkadot-availability-distribution" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "derive_more", "fatality", @@ -7121,7 +7188,7 @@ dependencies = [ [[package]] name = "polkadot-availability-recovery" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "fatality", "futures", @@ -7142,7 +7209,7 @@ dependencies = [ [[package]] name = "polkadot-cli" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "clap", "frame-benchmarking-cli", @@ -7171,7 +7238,7 @@ dependencies = [ [[package]] name = "polkadot-client" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "async-trait", "frame-benchmarking", @@ -7214,7 +7281,7 @@ dependencies = [ [[package]] name = "polkadot-collator-protocol" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "always-assert", "bitvec", @@ -7236,7 +7303,7 @@ dependencies = [ [[package]] name = "polkadot-core-primitives" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "parity-scale-codec", "scale-info", @@ -7248,13 +7315,13 @@ dependencies = [ [[package]] name = "polkadot-dispute-distribution" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "derive_more", "fatality", "futures", "futures-timer", - "indexmap", + "indexmap 1.9.3", "lru 0.9.0", "parity-scale-codec", "polkadot-erasure-coding", @@ -7273,7 +7340,7 @@ dependencies = [ [[package]] name = "polkadot-erasure-coding" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "parity-scale-codec", "polkadot-node-primitives", @@ -7287,7 +7354,7 @@ dependencies = [ [[package]] name = "polkadot-gossip-support" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "futures", "futures-timer", @@ -7307,7 +7374,7 @@ dependencies = [ [[package]] name = "polkadot-network-bridge" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "always-assert", "async-trait", @@ -7330,7 +7397,7 @@ dependencies = [ [[package]] name = "polkadot-node-collation-generation" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "futures", "parity-scale-codec", @@ -7348,7 +7415,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-approval-voting" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitvec", "derive_more", @@ -7377,7 +7444,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-av-store" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitvec", "futures", @@ -7398,7 +7465,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-backing" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitvec", "fatality", @@ -7417,7 +7484,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-bitfield-signing" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "futures", "polkadot-node-subsystem", @@ -7432,7 +7499,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-candidate-validation" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "async-trait", "futures", @@ -7452,7 +7519,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-api" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "futures", "polkadot-node-metrics", @@ -7467,7 +7534,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-chain-selection" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "futures", "futures-timer", @@ -7484,7 +7551,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-dispute-coordinator" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "fatality", "futures", @@ -7503,7 +7570,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-parachains-inherent" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "async-trait", "futures", @@ -7520,7 +7587,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-provisioner" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitvec", "fatality", @@ -7538,7 +7605,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-pvf" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "always-assert", "futures", @@ -7565,7 +7632,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-pvf-checker" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "futures", "polkadot-node-primitives", @@ -7581,7 +7648,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-pvf-worker" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "assert_matches", "cpu-time", @@ -7610,7 +7677,7 @@ dependencies = [ [[package]] name = "polkadot-node-core-runtime-api" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "futures", "lru 0.9.0", @@ -7625,7 +7692,7 @@ dependencies = [ [[package]] name = "polkadot-node-jaeger" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "lazy_static", "log", @@ -7643,7 +7710,7 @@ dependencies = [ [[package]] name = "polkadot-node-metrics" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bs58", "futures", @@ -7662,7 +7729,7 @@ dependencies = [ [[package]] name = "polkadot-node-network-protocol" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "async-trait", "derive_more", @@ -7684,7 +7751,7 @@ dependencies = [ [[package]] name = "polkadot-node-primitives" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bounded-vec", "futures", @@ -7706,7 +7773,7 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "polkadot-node-jaeger", "polkadot-node-subsystem-types", @@ -7716,7 +7783,7 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-types" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "async-trait", "derive_more", @@ -7739,7 +7806,7 @@ dependencies = [ [[package]] name = "polkadot-node-subsystem-util" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "async-trait", "derive_more", @@ -7772,7 +7839,7 @@ dependencies = [ [[package]] name = "polkadot-overseer" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "async-trait", "futures", @@ -7795,7 +7862,7 @@ dependencies = [ [[package]] name = "polkadot-parachain" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bounded-collections", "derive_more", @@ -7812,7 +7879,7 @@ dependencies = [ [[package]] name = "polkadot-performance-test" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "env_logger 0.9.3", "kusama-runtime", @@ -7830,7 +7897,7 @@ dependencies = [ [[package]] name = "polkadot-primitives" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitvec", "hex-literal", @@ -7856,7 +7923,7 @@ dependencies = [ [[package]] name = "polkadot-rpc" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "jsonrpsee", "mmr-rpc", @@ -7888,7 +7955,7 @@ dependencies = [ [[package]] name = "polkadot-runtime" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitvec", "frame-benchmarking", @@ -7982,7 +8049,7 @@ dependencies = [ [[package]] name = "polkadot-runtime-common" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitvec", "frame-benchmarking", @@ -8028,7 +8095,7 @@ dependencies = [ [[package]] name = "polkadot-runtime-constants" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "frame-support", "polkadot-primitives", @@ -8042,7 +8109,7 @@ dependencies = [ [[package]] name = "polkadot-runtime-metrics" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bs58", "parity-scale-codec", @@ -8054,9 +8121,9 @@ dependencies = [ [[package]] name = "polkadot-runtime-parachains" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ - "bitflags", + "bitflags 1.3.2", "bitvec", "derive_more", "frame-benchmarking", @@ -8098,7 +8165,7 @@ dependencies = [ [[package]] name = "polkadot-service" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "async-trait", "frame-benchmarking-cli", @@ -8208,12 +8275,12 @@ dependencies = [ [[package]] name = "polkadot-statement-distribution" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "arrayvec 0.5.2", "fatality", "futures", - "indexmap", + "indexmap 1.9.3", "parity-scale-codec", "polkadot-node-network-protocol", "polkadot-node-primitives", @@ -8229,7 +8296,7 @@ dependencies = [ [[package]] name = "polkadot-statement-table" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "parity-scale-codec", "polkadot-primitives", @@ -8243,12 +8310,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" dependencies = [ "autocfg", - "bitflags", + "bitflags 1.3.2", "cfg-if", "concurrent-queue", "libc", "log", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "windows-sys 0.48.0", ] @@ -8277,16 +8344,22 @@ dependencies = [ [[package]] name = "polyval" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef234e08c11dfcb2e56f79fd70f6f2eb7f025c0ce2333e82f4f0518ecad30c6" +checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" dependencies = [ "cfg-if", "cpufeatures", "opaque-debug 0.3.0", - "universal-hash 0.5.0", + "universal-hash 0.5.1", ] +[[package]] +name = "portable-atomic" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edc55135a600d700580e406b4de0d59cb9ad25e344a3a091a97ded2622ec4ec6" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -8404,14 +8477,14 @@ checksum = "0e99670bafb56b9a106419397343bdbc8b8742c3cc449fec6345f86173f47cd4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "proc-macro2" -version = "1.0.57" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4ec6d5fe0b140acb27c9a0444118cf55bfbb4e0b259739429abb4521dd67c16" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] @@ -8557,9 +8630,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c10f662eee9c94ddd7135043e544f3c82fa839a1e7b865911331961b53186c" +checksum = "f31999cfc7927c4e212e60fd50934ab40e8e8bfd2d493d6095d2d306bc0764d9" dependencies = [ "bytes", "rand 0.8.5", @@ -8575,9 +8648,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.27" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] @@ -8647,7 +8720,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.9", + "getrandom 0.2.10", ] [[package]] @@ -8704,7 +8777,7 @@ checksum = "6413f3de1edee53342e6138e75b56d32e7bc6e332b3bd62d497b1929d4cfbcdd" dependencies = [ "pem", "ring", - "time 0.3.21", + "time 0.3.23", "x509-parser 0.13.2", "yasna", ] @@ -8717,7 +8790,7 @@ checksum = "ffbe84efe2f38dea12e9bfc1f65377fdf03e53a18cb3b995faedf7934c7e785b" dependencies = [ "pem", "ring", - "time 0.3.21", + "time 0.3.23", "yasna", ] @@ -8727,7 +8800,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -8736,7 +8809,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -8745,7 +8818,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.9", + "getrandom 0.2.10", "redox_syscall 0.2.16", "thiserror", ] @@ -8765,22 +8838,22 @@ dependencies = [ [[package]] name = "ref-cast" -version = "1.0.16" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43faa91b1c8b36841ee70e97188a869d37ae21759da6846d4be66de5bf7b12c" +checksum = "61ef7e18e8841942ddb1cf845054f8008410030a3997875d9e49b7a363063df1" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.16" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d2275aab483050ab2a7364c1a46604865ee7d6906684e08db0f090acf74f9e7" +checksum = "2dfaf0c85b766276c797f3791f5bc6d5bd116b41d53049af2789666b0c0bc9fa" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] @@ -8797,13 +8870,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.1" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" +checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" dependencies = [ - "aho-corasick 1.0.1", + "aho-corasick", "memchr", - "regex-syntax 0.7.1", + "regex-automata 0.3.3", + "regex-syntax 0.7.4", ] [[package]] @@ -8815,6 +8889,17 @@ dependencies = [ "regex-syntax 0.6.29", ] +[[package]] +name = "regex-automata" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.7.4", +] + [[package]] name = "regex-syntax" version = "0.6.29" @@ -8823,9 +8908,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.1" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "region" @@ -8833,7 +8918,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e" dependencies = [ - "bitflags", + "bitflags 1.3.2", "libc", "mach", "winapi", @@ -8898,7 +8983,7 @@ dependencies = [ [[package]] name = "rococo-runtime" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "binary-merkle-tree", "frame-benchmarking", @@ -8984,7 +9069,7 @@ dependencies = [ [[package]] name = "rococo-runtime-constants" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "frame-support", "polkadot-primitives", @@ -9089,7 +9174,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.17", + "semver 1.0.18", ] [[package]] @@ -9103,11 +9188,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.36.13" +version = "0.36.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a38f9520be93aba504e8ca974197f46158de5dcaa9fa04b57c57cd6a679d658" +checksum = "c37f1bd5ef1b5422177b7646cba67430579cfe2ace80f284fee876bca52ad941" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", @@ -9117,15 +9202,28 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.19" +version = "0.37.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" +checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", - "linux-raw-sys 0.3.7", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" +dependencies = [ + "bitflags 2.3.3", + "errno", + "libc", + "linux-raw-sys 0.4.3", "windows-sys 0.48.0", ] @@ -9156,9 +9254,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ "openssl-probe", "rustls-pemfile", @@ -9168,18 +9266,18 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ - "base64 0.21.0", + "base64 0.21.2", ] [[package]] name = "rustversion" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "rw-stream-sink" @@ -9194,9 +9292,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "safe-mix" @@ -9209,9 +9307,9 @@ dependencies = [ [[package]] name = "safe_arch" -version = "0.6.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "794821e4ccb0d9f979512f9c1973480123f9bd62a90d74ab0f9426fcf8f4a529" +checksum = "f398075ce1e6a179b46f51bd88d0598b92b00d3551f1a2d4ac49e771b56ac354" dependencies = [ "bytemuck", ] @@ -9228,7 +9326,7 @@ dependencies = [ [[package]] name = "sc-allocator" version = "4.1.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "log", "sp-core", @@ -9239,7 +9337,7 @@ dependencies = [ [[package]] name = "sc-authority-discovery" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "futures", @@ -9267,7 +9365,7 @@ dependencies = [ [[package]] name = "sc-basic-authorship" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "futures", "futures-timer", @@ -9290,7 +9388,7 @@ dependencies = [ [[package]] name = "sc-block-builder" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "sc-client-api", @@ -9305,7 +9403,7 @@ dependencies = [ [[package]] name = "sc-chain-spec" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "memmap2", "sc-chain-spec-derive", @@ -9324,18 +9422,18 @@ dependencies = [ [[package]] name = "sc-chain-spec-derive" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "sc-cli" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", "chrono", @@ -9375,7 +9473,7 @@ dependencies = [ [[package]] name = "sc-client-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "fnv", "futures", @@ -9401,7 +9499,7 @@ dependencies = [ [[package]] name = "sc-client-db" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "hash-db", "kvdb", @@ -9427,7 +9525,7 @@ dependencies = [ [[package]] name = "sc-consensus" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "futures", @@ -9452,7 +9550,7 @@ dependencies = [ [[package]] name = "sc-consensus-aura" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "futures", @@ -9481,7 +9579,7 @@ dependencies = [ [[package]] name = "sc-consensus-babe" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "fork-tree", @@ -9517,7 +9615,7 @@ dependencies = [ [[package]] name = "sc-consensus-babe-rpc" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "futures", "jsonrpsee", @@ -9539,7 +9637,7 @@ dependencies = [ [[package]] name = "sc-consensus-beefy" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", "async-trait", @@ -9574,7 +9672,7 @@ dependencies = [ [[package]] name = "sc-consensus-beefy-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "futures", "jsonrpsee", @@ -9593,7 +9691,7 @@ dependencies = [ [[package]] name = "sc-consensus-epochs" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "fork-tree", "parity-scale-codec", @@ -9606,7 +9704,7 @@ dependencies = [ [[package]] name = "sc-consensus-grandpa" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "ahash 0.8.3", "array-bytes 4.2.0", @@ -9646,7 +9744,7 @@ dependencies = [ [[package]] name = "sc-consensus-grandpa-rpc" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "finality-grandpa", "futures", @@ -9666,7 +9764,7 @@ dependencies = [ [[package]] name = "sc-consensus-slots" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "futures", @@ -9689,7 +9787,7 @@ dependencies = [ [[package]] name = "sc-executor" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "lru 0.8.1", "parity-scale-codec", @@ -9713,7 +9811,7 @@ dependencies = [ [[package]] name = "sc-executor-common" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "sc-allocator", "sp-maybe-compressed-blob", @@ -9726,7 +9824,7 @@ dependencies = [ [[package]] name = "sc-executor-wasmi" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "log", "sc-allocator", @@ -9739,14 +9837,14 @@ dependencies = [ [[package]] name = "sc-executor-wasmtime" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "anyhow", "cfg-if", "libc", "log", "once_cell", - "rustix 0.36.13", + "rustix 0.36.15", "sc-allocator", "sc-executor-common", "sp-runtime-interface", @@ -9757,7 +9855,7 @@ dependencies = [ [[package]] name = "sc-informant" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "ansi_term", "futures", @@ -9773,7 +9871,7 @@ dependencies = [ [[package]] name = "sc-keystore" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", "async-trait", @@ -9788,7 +9886,7 @@ dependencies = [ [[package]] name = "sc-network" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", "async-channel", @@ -9833,7 +9931,7 @@ dependencies = [ [[package]] name = "sc-network-bitswap" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "cid", "futures", @@ -9853,11 +9951,11 @@ dependencies = [ [[package]] name = "sc-network-common" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", "async-trait", - "bitflags", + "bitflags 1.3.2", "bytes", "futures", "futures-timer", @@ -9881,7 +9979,7 @@ dependencies = [ [[package]] name = "sc-network-gossip" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "ahash 0.8.3", "futures", @@ -9900,7 +9998,7 @@ dependencies = [ [[package]] name = "sc-network-light" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", "futures", @@ -9922,7 +10020,7 @@ dependencies = [ [[package]] name = "sc-network-sync" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", "async-trait", @@ -9956,7 +10054,7 @@ dependencies = [ [[package]] name = "sc-network-transactions" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", "futures", @@ -9976,7 +10074,7 @@ dependencies = [ [[package]] name = "sc-offchain" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", "bytes", @@ -10007,7 +10105,7 @@ dependencies = [ [[package]] name = "sc-peerset" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "futures", "libp2p", @@ -10020,7 +10118,7 @@ dependencies = [ [[package]] name = "sc-proposer-metrics" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "log", "substrate-prometheus-endpoint", @@ -10029,7 +10127,7 @@ dependencies = [ [[package]] name = "sc-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "futures", "jsonrpsee", @@ -10059,7 +10157,7 @@ dependencies = [ [[package]] name = "sc-rpc-api" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -10078,7 +10176,7 @@ dependencies = [ [[package]] name = "sc-rpc-server" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "http", "jsonrpsee", @@ -10093,7 +10191,7 @@ dependencies = [ [[package]] name = "sc-rpc-spec-v2" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", "futures", @@ -10119,7 +10217,7 @@ dependencies = [ [[package]] name = "sc-service" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "directories", @@ -10185,7 +10283,7 @@ dependencies = [ [[package]] name = "sc-state-db" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "log", "parity-scale-codec", @@ -10196,7 +10294,7 @@ dependencies = [ [[package]] name = "sc-storage-monitor" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "clap", "fs4", @@ -10212,7 +10310,7 @@ dependencies = [ [[package]] name = "sc-sync-state-rpc" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "jsonrpsee", "parity-scale-codec", @@ -10231,7 +10329,7 @@ dependencies = [ [[package]] name = "sc-sysinfo" version = "6.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "futures", "libc", @@ -10250,7 +10348,7 @@ dependencies = [ [[package]] name = "sc-telemetry" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "chrono", "futures", @@ -10269,7 +10367,7 @@ dependencies = [ [[package]] name = "sc-tracing" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "ansi_term", "atty", @@ -10300,18 +10398,18 @@ dependencies = [ [[package]] name = "sc-tracing-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "sc-transaction-pool" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "futures", @@ -10338,7 +10436,7 @@ dependencies = [ [[package]] name = "sc-transaction-pool-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "futures", @@ -10352,7 +10450,7 @@ dependencies = [ [[package]] name = "sc-utils" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-channel", "futures", @@ -10366,9 +10464,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.7.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b569c32c806ec3abdf3b5869fb8bf1e0d275a7c1c9b0b05603d9464632649edf" +checksum = "35c0a159d0c45c12b20c5a844feb1fe4bea86e28f17b92a5f0c42193634d3782" dependencies = [ "bitvec", "cfg-if", @@ -10380,9 +10478,9 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.6.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53012eae69e5aa5c14671942a5dd47de59d4cdcff8532a6dd0e081faf1119482" +checksum = "912e55f6d20e0e80d63733872b40e1227c0bce1e1ab81ba67d696339bfd7fd29" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -10392,11 +10490,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" dependencies = [ - "windows-sys 0.42.0", + "windows-sys 0.48.0", ] [[package]] @@ -10430,15 +10528,15 @@ dependencies = [ [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "scratch" -version = "1.0.5" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" +checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152" [[package]] name = "sct" @@ -10488,12 +10586,12 @@ dependencies = [ [[package]] name = "sec1" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0aec48e813d6b90b15f0b8948af3c63483992dee44c03e9930b3eebdabe046e" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct 0.2.0", - "der 0.7.5", + "der 0.7.7", "generic-array 0.14.7", "pkcs8 0.10.2", "subtle", @@ -10529,11 +10627,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2855b3715770894e67cbfa3df957790aa0c9edc3bf06efa1a84d77fa0839d1" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -10542,9 +10640,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -10570,9 +10668,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" dependencies = [ "serde", ] @@ -10585,29 +10683,29 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.163" +version = "1.0.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +checksum = "5d25439cd7397d044e2748a6fe2432b5e85db703d6d097bd014b3c0ad1ebff0b" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.163" +version = "1.0.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +checksum = "b23f7ade6f110613c0d63858ddb8b94c1041f550eab58a16b371bdf2c9c80ab4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b" dependencies = [ "itoa", "ryu", @@ -10616,9 +10714,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" dependencies = [ "serde", ] @@ -10644,7 +10742,7 @@ checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -10674,13 +10772,13 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -10689,7 +10787,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "keccak", ] @@ -10723,7 +10821,7 @@ version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "rand_core 0.6.4", ] @@ -10733,7 +10831,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "rand_core 0.6.4", ] @@ -10774,7 +10872,7 @@ checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" [[package]] name = "slot-range-helper" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "enumn", "parity-scale-codec", @@ -10794,9 +10892,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "snap" @@ -10817,7 +10915,7 @@ dependencies = [ "rand_core 0.6.4", "ring", "rustc_version 0.4.0", - "sha2 0.10.6", + "sha2 0.10.7", "subtle", ] @@ -10831,6 +10929,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "socket2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "soketto" version = "0.7.1" @@ -10851,7 +10959,7 @@ dependencies = [ [[package]] name = "sp-api" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "hash-db", "log", @@ -10871,7 +10979,7 @@ dependencies = [ [[package]] name = "sp-api-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "Inflector", "blake2", @@ -10879,13 +10987,13 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "sp-application-crypto" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", @@ -10898,7 +11006,7 @@ dependencies = [ [[package]] name = "sp-arithmetic" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "integer-sqrt", "num-traits", @@ -10912,7 +11020,7 @@ dependencies = [ [[package]] name = "sp-authority-discovery" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", @@ -10925,7 +11033,7 @@ dependencies = [ [[package]] name = "sp-block-builder" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "sp-api", @@ -10937,7 +11045,7 @@ dependencies = [ [[package]] name = "sp-blockchain" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "futures", "log", @@ -10955,7 +11063,7 @@ dependencies = [ [[package]] name = "sp-consensus" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "futures", @@ -10970,7 +11078,7 @@ dependencies = [ [[package]] name = "sp-consensus-aura" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "parity-scale-codec", @@ -10988,7 +11096,7 @@ dependencies = [ [[package]] name = "sp-consensus-babe" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "parity-scale-codec", @@ -11009,7 +11117,7 @@ dependencies = [ [[package]] name = "sp-consensus-beefy" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "lazy_static", "parity-scale-codec", @@ -11028,7 +11136,7 @@ dependencies = [ [[package]] name = "sp-consensus-grandpa" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "finality-grandpa", "log", @@ -11046,7 +11154,7 @@ dependencies = [ [[package]] name = "sp-consensus-slots" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", @@ -11058,10 +11166,10 @@ dependencies = [ [[package]] name = "sp-core" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "array-bytes 4.2.0", - "bitflags", + "bitflags 1.3.2", "blake2", "bounded-collections", "bs58", @@ -11102,12 +11210,12 @@ dependencies = [ [[package]] name = "sp-core-hashing" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "blake2b_simd", "byteorder", - "digest 0.10.6", - "sha2 0.10.6", + "digest 0.10.7", + "sha2 0.10.7", "sha3", "sp-std", "twox-hash", @@ -11116,18 +11224,18 @@ dependencies = [ [[package]] name = "sp-core-hashing-proc-macro" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "proc-macro2", "quote", "sp-core-hashing", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "sp-database" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "kvdb", "parking_lot 0.12.1", @@ -11136,17 +11244,17 @@ dependencies = [ [[package]] name = "sp-debug-derive" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "sp-externalities" version = "0.13.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "environmental", "parity-scale-codec", @@ -11157,7 +11265,7 @@ dependencies = [ [[package]] name = "sp-inherents" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "impl-trait-for-tuples", @@ -11172,7 +11280,7 @@ dependencies = [ [[package]] name = "sp-io" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "bytes", "ed25519", @@ -11198,7 +11306,7 @@ dependencies = [ [[package]] name = "sp-keyring" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "lazy_static", "sp-core", @@ -11209,7 +11317,7 @@ dependencies = [ [[package]] name = "sp-keystore" version = "0.13.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "futures", "parity-scale-codec", @@ -11223,16 +11331,16 @@ dependencies = [ [[package]] name = "sp-maybe-compressed-blob" version = "4.1.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "thiserror", - "zstd 0.12.3+zstd.1.5.2", + "zstd 0.12.4", ] [[package]] name = "sp-metadata-ir" version = "0.1.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-metadata", "parity-scale-codec", @@ -11243,7 +11351,7 @@ dependencies = [ [[package]] name = "sp-mmr-primitives" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "ckb-merkle-mountain-range", "log", @@ -11261,7 +11369,7 @@ dependencies = [ [[package]] name = "sp-npos-elections" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", @@ -11275,7 +11383,7 @@ dependencies = [ [[package]] name = "sp-offchain" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "sp-api", "sp-core", @@ -11285,7 +11393,7 @@ dependencies = [ [[package]] name = "sp-panic-handler" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "backtrace", "lazy_static", @@ -11295,7 +11403,7 @@ dependencies = [ [[package]] name = "sp-rpc" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "rustc-hash", "serde", @@ -11305,7 +11413,7 @@ dependencies = [ [[package]] name = "sp-runtime" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "either", "hash256-std-hasher", @@ -11327,7 +11435,7 @@ dependencies = [ [[package]] name = "sp-runtime-interface" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "bytes", "impl-trait-for-tuples", @@ -11345,19 +11453,19 @@ dependencies = [ [[package]] name = "sp-runtime-interface-proc-macro" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "Inflector", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "sp-session" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", @@ -11371,7 +11479,7 @@ dependencies = [ [[package]] name = "sp-staking" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", @@ -11384,7 +11492,7 @@ dependencies = [ [[package]] name = "sp-state-machine" version = "0.13.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "hash-db", "log", @@ -11404,12 +11512,12 @@ dependencies = [ [[package]] name = "sp-std" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" [[package]] name = "sp-storage" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "impl-serde", "parity-scale-codec", @@ -11422,7 +11530,7 @@ dependencies = [ [[package]] name = "sp-timestamp" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "futures-timer", @@ -11437,7 +11545,7 @@ dependencies = [ [[package]] name = "sp-tracing" version = "6.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "sp-std", @@ -11449,7 +11557,7 @@ dependencies = [ [[package]] name = "sp-transaction-pool" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "sp-api", "sp-runtime", @@ -11458,7 +11566,7 @@ dependencies = [ [[package]] name = "sp-transaction-storage-proof" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "log", @@ -11474,7 +11582,7 @@ dependencies = [ [[package]] name = "sp-trie" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "ahash 0.8.3", "hash-db", @@ -11497,7 +11605,7 @@ dependencies = [ [[package]] name = "sp-version" version = "5.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "impl-serde", "parity-scale-codec", @@ -11514,18 +11622,18 @@ dependencies = [ [[package]] name = "sp-version-proc-macro" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] name = "sp-wasm-interface" version = "7.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "anyhow", "impl-trait-for-tuples", @@ -11539,7 +11647,7 @@ dependencies = [ [[package]] name = "sp-weights" version = "4.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "parity-scale-codec", "scale-info", @@ -11557,6 +11665,17 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +[[package]] +name = "spinners" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08615eea740067d9899969bc2891c68a19c315cb1f66640af9a9ecb91b13bcab" +dependencies = [ + "lazy_static", + "maplit", + "strum", +] + [[package]] name = "spki" version = "0.6.0" @@ -11574,14 +11693,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" dependencies = [ "base64ct", - "der 0.7.5", + "der 0.7.7", ] [[package]] name = "ss58-registry" -version = "1.40.0" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47a8ad42e5fc72d5b1eb104a5546937eaf39843499948bb666d6e93c62423b" +checksum = "bfc443bad666016e012538782d9e3006213a7db43e9fb1dda91657dc06a6fa08" dependencies = [ "Inflector", "num-format", @@ -11622,7 +11741,7 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a2a1c578e98c1c16fc3b8ec1328f7659a500737d7a0c6d625e73e830ff9c1f6" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg_aliases", "libc", "parking_lot 0.11.2", @@ -11720,7 +11839,7 @@ dependencies = [ [[package]] name = "substrate-build-script-utils" version = "3.0.0" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "platforms 2.0.0", ] @@ -11728,7 +11847,7 @@ dependencies = [ [[package]] name = "substrate-frame-rpc-system" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "frame-system-rpc-runtime-api", "futures", @@ -11747,7 +11866,7 @@ dependencies = [ [[package]] name = "substrate-prometheus-endpoint" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "hyper", "log", @@ -11759,7 +11878,7 @@ dependencies = [ [[package]] name = "substrate-rpc-client" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "jsonrpsee", @@ -11772,7 +11891,7 @@ dependencies = [ [[package]] name = "substrate-state-trie-migration-rpc" version = "4.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "jsonrpsee", "log", @@ -11791,7 +11910,7 @@ dependencies = [ [[package]] name = "substrate-wasm-builder" version = "5.0.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "ansi_term", "build-helper", @@ -11800,7 +11919,7 @@ dependencies = [ "sp-maybe-compressed-blob", "strum", "tempfile", - "toml 0.7.3", + "toml 0.7.6", "walkdir", "wasm-opt", ] @@ -11833,9 +11952,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.16" +version = "2.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" +checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0" dependencies = [ "proc-macro2", "quote", @@ -11860,7 +11979,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "system-configuration-sys", ] @@ -11883,21 +12002,21 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" -version = "0.12.7" +version = "0.12.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd1ba337640d60c3e96bc6f0638a939b9c9a7f2c316a1598c279828b3d1dc8c5" +checksum = "1d2faeef5759ab89935255b1a4cd98e0baf99d1085e37d36599c625dac49ae8e" [[package]] name = "tempfile" -version = "3.5.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998" dependencies = [ "cfg-if", - "fastrand", + "fastrand 2.0.0", "redox_syscall 0.3.5", - "rustix 0.37.19", - "windows-sys 0.45.0", + "rustix 0.38.4", + "windows-sys 0.48.0", ] [[package]] @@ -11917,22 +12036,22 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] @@ -12007,9 +12126,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.21" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc" +checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" dependencies = [ "itoa", "serde", @@ -12025,9 +12144,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" +checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4" dependencies = [ "time-core", ] @@ -12044,7 +12163,7 @@ dependencies = [ "pbkdf2 0.11.0", "rand 0.8.5", "rustc-hash", - "sha2 0.10.6", + "sha2 0.10.7", "thiserror", "unicode-normalization", "wasm-bindgen", @@ -12078,19 +12197,20 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.28.1" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg", + "backtrace", "bytes", "libc", "mio", "num_cpus", "parking_lot 0.12.1", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "signal-hook-registry", - "socket2", + "socket2 0.4.9", "tokio-macros", "windows-sys 0.48.0", ] @@ -12103,7 +12223,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] @@ -12124,7 +12244,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" dependencies = [ "futures-core", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "tokio", "tokio-util", ] @@ -12139,7 +12259,7 @@ dependencies = [ "futures-core", "futures-io", "futures-sink", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "tokio", "tracing", ] @@ -12155,9 +12275,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.3" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21" +checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" dependencies = [ "serde", "serde_spanned", @@ -12167,20 +12287,20 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.8" +version = "0.19.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" dependencies = [ - "indexmap", + "indexmap 2.0.0", "serde", "serde_spanned", "toml_datetime", @@ -12204,14 +12324,14 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" dependencies = [ - "bitflags", + "bitflags 1.3.2", "bytes", "futures-core", "futures-util", "http", "http-body", "http-range-header", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "tower-layer", "tower-service", ] @@ -12236,20 +12356,20 @@ checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if", "log", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.10", "tracing-attributes", "tracing-core", ] [[package]] name = "tracing-attributes" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] @@ -12275,7 +12395,7 @@ dependencies = [ [[package]] name = "tracing-gum" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "polkadot-node-jaeger", "polkadot-primitives", @@ -12286,13 +12406,13 @@ dependencies = [ [[package]] name = "tracing-gum-proc-macro" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "expander 2.0.0", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] @@ -12379,7 +12499,7 @@ dependencies = [ "lazy_static", "rand 0.8.5", "smallvec", - "socket2", + "socket2 0.4.9", "thiserror", "tinyvec", "tokio", @@ -12416,7 +12536,7 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "try-runtime-cli" version = "0.10.0-dev" -source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#3bb3882ce094ac211dea93fabfdcd4f902f5a7fd" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" dependencies = [ "async-trait", "clap", @@ -12447,7 +12567,7 @@ dependencies = [ "sp-version", "sp-weights", "substrate-rpc-client", - "zstd 0.12.3+zstd.1.5.2", + "zstd 0.12.4", ] [[package]] @@ -12482,7 +12602,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", - "digest 0.10.6", + "digest 0.10.7", "rand 0.8.5", "static_assertions", ] @@ -12495,9 +12615,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "ucd-trie" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "uint" @@ -12519,9 +12639,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-normalization" @@ -12556,9 +12676,9 @@ dependencies = [ [[package]] name = "universal-hash" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d3160b73c9a19f7e2939a2fdad446c57c1bbbbf4d919d3213ff1267a580d8b5" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" dependencies = [ "crypto-common", "subtle", @@ -12584,12 +12704,12 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" dependencies = [ "form_urlencoded", - "idna 0.3.0", + "idna 0.4.0", "percent-encoding", ] @@ -12601,11 +12721,11 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.3.3" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" dependencies = [ - "getrandom 0.2.9", + "getrandom 0.2.10", ] [[package]] @@ -12659,11 +12779,10 @@ dependencies = [ [[package]] name = "want" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "log", "try-lock", ] @@ -12687,9 +12806,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -12697,24 +12816,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.36" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" dependencies = [ "cfg-if", "js-sys", @@ -12724,9 +12843,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -12734,22 +12853,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wasm-instrument" @@ -12856,7 +12975,7 @@ version = "0.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64b20236ab624147dfbb62cf12a19aaf66af0e41b8398838b66e997d07d269d4" dependencies = [ - "indexmap", + "indexmap 1.9.3", "url", ] @@ -12869,7 +12988,7 @@ dependencies = [ "anyhow", "bincode", "cfg-if", - "indexmap", + "indexmap 1.9.3", "libc", "log", "object 0.29.0", @@ -12909,9 +13028,9 @@ dependencies = [ "directories-next", "file-per-thread-logger", "log", - "rustix 0.36.13", + "rustix 0.36.15", "serde", - "sha2 0.10.6", + "sha2 0.10.7", "toml 0.5.11", "windows-sys 0.42.0", "zstd 0.11.2+zstd.1.5.2", @@ -12947,7 +13066,7 @@ dependencies = [ "anyhow", "cranelift-entity", "gimli 0.26.2", - "indexmap", + "indexmap 1.9.3", "log", "object 0.29.0", "serde", @@ -12989,7 +13108,7 @@ checksum = "eed41cbcbf74ce3ff6f1d07d1b707888166dc408d1a880f651268f4f7c9194b2" dependencies = [ "object 0.29.0", "once_cell", - "rustix 0.36.13", + "rustix 0.36.15", ] [[package]] @@ -13012,7 +13131,7 @@ dependencies = [ "anyhow", "cc", "cfg-if", - "indexmap", + "indexmap 1.9.3", "libc", "log", "mach", @@ -13020,7 +13139,7 @@ dependencies = [ "memoffset 0.6.5", "paste", "rand 0.8.5", - "rustix 0.36.13", + "rustix 0.36.15", "wasmtime-asm-macros", "wasmtime-environ", "wasmtime-jit-debug", @@ -13041,9 +13160,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.63" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" dependencies = [ "js-sys", "wasm-bindgen", @@ -13101,10 +13220,10 @@ dependencies = [ "sdp", "serde", "serde_json", - "sha2 0.10.6", + "sha2 0.10.7", "stun", "thiserror", - "time 0.3.21", + "time 0.3.23", "tokio", "turn", "url", @@ -13141,7 +13260,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "942be5bd85f072c3128396f6e5a9bfb93ca8c1939ded735d177b7bcba9a13d05" dependencies = [ "aes 0.6.0", - "aes-gcm 0.10.1", + "aes-gcm 0.10.2", "async-trait", "bincode", "block-modes", @@ -13164,7 +13283,7 @@ dependencies = [ "sec1 0.3.0", "serde", "sha1", - "sha2 0.10.6", + "sha2 0.10.7", "signature 1.6.4", "subtle", "thiserror", @@ -13206,7 +13325,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f08dfd7a6e3987e255c4dbe710dde5d94d0f0574f8a21afa95d171376c143106" dependencies = [ "log", - "socket2", + "socket2 0.4.9", "thiserror", "tokio", "webrtc-util", @@ -13273,7 +13392,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93f1db1727772c05cf7a2cfece52c3aca8045ca1e176cd517d323489aa3c6d87" dependencies = [ "async-trait", - "bitflags", + "bitflags 1.3.2", "bytes", "cc", "ipnet", @@ -13290,7 +13409,7 @@ dependencies = [ [[package]] name = "westend-runtime" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bitvec", "frame-benchmarking", @@ -13382,7 +13501,7 @@ dependencies = [ [[package]] name = "westend-runtime-constants" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "frame-support", "polkadot-primitives", @@ -13406,9 +13525,9 @@ dependencies = [ [[package]] name = "wide" -version = "0.7.8" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b689b6c49d6549434bf944e6b0f39238cf63693cb7a147e9d887507fffa3b223" +checksum = "aa469ffa65ef7e0ba0f164183697b89b854253fd31aeb92358b7b6155177d62f" dependencies = [ "bytemuck", "safe_arch", @@ -13416,9 +13535,9 @@ dependencies = [ [[package]] name = "widestring" -version = "0.5.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" [[package]] name = "winapi" @@ -13470,7 +13589,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.48.1", ] [[package]] @@ -13503,7 +13622,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.48.1", ] [[package]] @@ -13523,9 +13642,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ "windows_aarch64_gnullvm 0.48.0", "windows_aarch64_msvc 0.48.0", @@ -13652,20 +13771,21 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.4.6" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699" +checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7" dependencies = [ "memchr", ] [[package]] name = "winreg" -version = "0.10.1" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "winapi", + "cfg-if", + "windows-sys 0.48.0", ] [[package]] @@ -13715,7 +13835,7 @@ dependencies = [ "ring", "rusticata-macros", "thiserror", - "time 0.3.21", + "time 0.3.23", ] [[package]] @@ -13733,13 +13853,13 @@ dependencies = [ "oid-registry 0.6.1", "rusticata-macros", "thiserror", - "time 0.3.21", + "time 0.3.23", ] [[package]] name = "xcm" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "bounded-collections", "derivative", @@ -13755,7 +13875,7 @@ dependencies = [ [[package]] name = "xcm-builder" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "frame-support", "frame-system", @@ -13776,7 +13896,7 @@ dependencies = [ [[package]] name = "xcm-executor" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "environmental", "frame-benchmarking", @@ -13796,12 +13916,12 @@ dependencies = [ [[package]] name = "xcm-procedural" version = "0.9.42" -source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#9b1fc27cec47f01a2c229532ee7ab79cc5bb28ef" +source = "git+https://github.com/paritytech/polkadot?branch=release-v0.9.42#6f991987c0b4cbbd7d4badc9ef08d83da5fefbfd" dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] @@ -13824,7 +13944,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" dependencies = [ - "time 0.3.21", + "time 0.3.23", ] [[package]] @@ -13844,7 +13964,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.16", + "syn 2.0.27", ] [[package]] @@ -13858,11 +13978,11 @@ dependencies = [ [[package]] name = "zstd" -version = "0.12.3+zstd.1.5.2" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76eea132fb024e0e13fd9c2f5d5d595d8a967aa72382ac2f9d39fcc95afd0806" +checksum = "1a27595e173641171fc74a1232b7b1c7a7cb6e18222c11e9dfb9888fa424c53c" dependencies = [ - "zstd-safe 6.0.5+zstd.1.5.4", + "zstd-safe 6.0.6", ] [[package]] @@ -13877,9 +13997,9 @@ dependencies = [ [[package]] name = "zstd-safe" -version = "6.0.5+zstd.1.5.4" +version = "6.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56d9e60b4b1758206c238a10165fbcae3ca37b01744e394c463463f6529d23b" +checksum = "ee98ffd0b48ee95e6c5168188e44a54550b1564d9d530ee21d5f0eaed1069581" dependencies = [ "libc", "zstd-sys", diff --git a/polimec-skeleton/node/src/chain_spec.rs b/polimec-skeleton/node/src/chain_spec.rs index 3416ed5f4..e7002bc48 100644 --- a/polimec-skeleton/node/src/chain_spec.rs +++ b/polimec-skeleton/node/src/chain_spec.rs @@ -14,9 +14,7 @@ const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION; /// Helper function to generate a crypto pair from seed pub fn get_from_seed(seed: &str) -> ::Public { - TPublic::Pair::from_string(&format!("//{}", seed), None) - .expect("static values are valid; qed") - .public() + TPublic::Pair::from_string(&format!("//{}", seed), None).expect("static values are valid; qed").public() } /// The extensions for the [`ChainSpec`]. @@ -77,14 +75,8 @@ pub fn development_config() -> ChainSpec { testnet_genesis( // initial collators. vec![ - ( - get_account_id_from_seed::("Alice"), - get_collator_keys_from_seed("Alice"), - ), - ( - get_account_id_from_seed::("Bob"), - get_collator_keys_from_seed("Bob"), - ), + (get_account_id_from_seed::("Alice"), get_collator_keys_from_seed("Alice")), + (get_account_id_from_seed::("Bob"), get_collator_keys_from_seed("Bob")), ], vec![ get_account_id_from_seed::("Alice"), @@ -132,14 +124,8 @@ pub fn local_testnet_config() -> ChainSpec { testnet_genesis( // initial collators. vec![ - ( - get_account_id_from_seed::("Alice"), - get_collator_keys_from_seed("Alice"), - ), - ( - get_account_id_from_seed::("Bob"), - get_collator_keys_from_seed("Bob"), - ), + (get_account_id_from_seed::("Alice"), get_collator_keys_from_seed("Alice")), + (get_account_id_from_seed::("Bob"), get_collator_keys_from_seed("Bob")), ], vec![ get_account_id_from_seed::("Alice"), @@ -177,7 +163,9 @@ pub fn local_testnet_config() -> ChainSpec { } fn testnet_genesis( - invulnerables: Vec<(AccountId, AuraId)>, endowed_accounts: Vec, id: ParaId, + invulnerables: Vec<(AccountId, AuraId)>, + endowed_accounts: Vec, + id: ParaId, ) -> parachain_template_runtime::GenesisConfig { parachain_template_runtime::GenesisConfig { system: parachain_template_runtime::SystemConfig { @@ -211,11 +199,9 @@ fn testnet_genesis( aura: Default::default(), aura_ext: Default::default(), parachain_system: Default::default(), - polkadot_xcm: parachain_template_runtime::PolkadotXcmConfig { - safe_xcm_version: Some(SAFE_XCM_VERSION), - }, + polkadot_xcm: parachain_template_runtime::PolkadotXcmConfig { safe_xcm_version: Some(SAFE_XCM_VERSION) }, transaction_payment: Default::default(), credentials: Default::default(), - vesting: Default::default() + vesting: Default::default(), } } diff --git a/polimec-skeleton/node/src/cli.rs b/polimec-skeleton/node/src/cli.rs index 1308bc5d1..0453bf534 100644 --- a/polimec-skeleton/node/src/cli.rs +++ b/polimec-skeleton/node/src/cli.rs @@ -57,11 +57,7 @@ const AFTER_HELP_EXAMPLE: &str = color_print::cstr!( "# ); #[derive(Debug, clap::Parser)] -#[command( - propagate_version = true, - args_conflicts_with_subcommands = true, - subcommand_negates_reqs = true -)] +#[command(propagate_version = true, args_conflicts_with_subcommands = true, subcommand_negates_reqs = true)] #[clap(after_help = AFTER_HELP_EXAMPLE)] pub struct Cli { #[command(subcommand)] @@ -100,15 +96,12 @@ pub struct RelayChainCli { impl RelayChainCli { /// Parse the relay chain CLI parameters using the para chain `Configuration`. pub fn new<'a>( - para_config: &sc_service::Configuration, relay_chain_args: impl Iterator, + para_config: &sc_service::Configuration, + relay_chain_args: impl Iterator, ) -> Self { let extension = crate::chain_spec::Extensions::try_get(&*para_config.chain_spec); let chain_id = extension.map(|e| e.relay_chain.clone()); let base_path = para_config.base_path.as_ref().map(|x| x.path().join("polkadot")); - Self { - base_path, - chain_id, - base: clap::Parser::parse_from(relay_chain_args), - } + Self { base_path, chain_id, base: clap::Parser::parse_from(relay_chain_args) } } } diff --git a/polimec-skeleton/node/src/command.rs b/polimec-skeleton/node/src/command.rs index 288d67388..d5e364522 100644 --- a/polimec-skeleton/node/src/command.rs +++ b/polimec-skeleton/node/src/command.rs @@ -128,37 +128,35 @@ pub fn run() -> Result<()> { Some(Subcommand::BuildSpec(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) - } + }, Some(Subcommand::CheckBlock(cmd)) => { construct_async_run!(|components, cli, cmd, config| { Ok(cmd.run(components.client, components.import_queue)) }) - } + }, Some(Subcommand::ExportBlocks(cmd)) => { construct_async_run!(|components, cli, cmd, config| Ok(cmd.run(components.client, config.database))) - } + }, Some(Subcommand::ExportState(cmd)) => { construct_async_run!(|components, cli, cmd, config| Ok(cmd.run(components.client, config.chain_spec))) - } + }, Some(Subcommand::ImportBlocks(cmd)) => { construct_async_run!(|components, cli, cmd, config| { Ok(cmd.run(components.client, components.import_queue)) }) - } + }, Some(Subcommand::Revert(cmd)) => { construct_async_run!(|components, cli, cmd, config| { Ok(cmd.run(components.client, components.backend, None)) }) - } + }, Some(Subcommand::PurgeChain(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|config| { let polkadot_cli = RelayChainCli::new( &config, - [RelayChainCli::executable_name()] - .iter() - .chain(cli.relay_chain_args.iter()), + [RelayChainCli::executable_name()].iter().chain(cli.relay_chain_args.iter()), ); let polkadot_config = @@ -167,7 +165,7 @@ pub fn run() -> Result<()> { cmd.run(config, polkadot_config) }) - } + }, Some(Subcommand::ExportGenesisState(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|_config| { @@ -175,40 +173,38 @@ pub fn run() -> Result<()> { let state_version = Cli::native_runtime_version(&spec).state_version(); cmd.run::(&*spec, state_version) }) - } + }, Some(Subcommand::ExportGenesisWasm(cmd)) => { let runner = cli.create_runner(cmd)?; runner.sync_run(|_config| { let spec = cli.load_spec(&cmd.shared_params.chain.clone().unwrap_or_default())?; cmd.run(&*spec) }) - } + }, Some(Subcommand::Benchmark(cmd)) => { let runner = cli.create_runner(cmd)?; // Switch on the concrete benchmark sub-command- match cmd { - BenchmarkCmd::Pallet(cmd) => { + BenchmarkCmd::Pallet(cmd) => if cfg!(feature = "runtime-benchmarks") { runner.sync_run(|config| cmd.run::(config)) } else { Err("Benchmarking wasn't enabled when building the node. \ You can enable it with `--features runtime-benchmarks`." .into()) - } - } + }, BenchmarkCmd::Block(cmd) => runner.sync_run(|config| { let partials = new_partial(&config)?; cmd.run(partials.client) }), #[cfg(not(feature = "runtime-benchmarks"))] - BenchmarkCmd::Storage(_) => { + BenchmarkCmd::Storage(_) => return Err(sc_cli::Error::Input( "Compile with --features=runtime-benchmarks \ to enable storage benchmarks." .into(), ) - .into()) - } + .into()), #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { let partials = new_partial(&config)?; @@ -216,15 +212,14 @@ pub fn run() -> Result<()> { let storage = partials.backend.expose_storage(); cmd.run(config, partials.client.clone(), db, storage) }), - BenchmarkCmd::Machine(cmd) => { - runner.sync_run(|config| cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone())) - } + BenchmarkCmd::Machine(cmd) => + runner.sync_run(|config| cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone())), // NOTE: this allows the Client to leniently implement // new benchmark commands without requiring a companion MR. #[allow(unreachable_patterns)] _ => Err("Benchmarking sub-command unsupported".into()), } - } + }, #[cfg(feature = "try-runtime")] Some(Subcommand::TryRuntime(cmd)) => { use parachain_template_runtime::MILLISECS_PER_BLOCK; @@ -246,12 +241,9 @@ pub fn run() -> Result<()> { let info_provider = timestamp_with_aura_info(MILLISECS_PER_BLOCK); runner.async_run(|_| { - Ok(( - cmd.run::, _>(Some(info_provider)), - task_manager, - )) + Ok((cmd.run::, _>(Some(info_provider)), task_manager)) }) - } + }, #[cfg(not(feature = "try-runtime"))] Some(Subcommand::TryRuntime) => Err("Try-runtime was not enabled when building the node. \ You can enable it with `--features try-runtime`." @@ -311,7 +303,7 @@ pub fn run() -> Result<()> { .map(|r| r.0) .map_err(Into::into) }) - } + }, } } @@ -351,10 +343,7 @@ impl CliConfiguration for RelayChainCli { } fn base_path(&self) -> Result> { - Ok(self - .shared_params() - .base_path()? - .or_else(|| self.base_path.clone().map(Into::into))) + Ok(self.shared_params().base_path()?.or_else(|| self.base_path.clone().map(Into::into))) } fn rpc_http(&self, default_listen_port: u16) -> Result> { @@ -370,13 +359,19 @@ impl CliConfiguration for RelayChainCli { } fn prometheus_config( - &self, default_listen_port: u16, chain_spec: &Box, + &self, + default_listen_port: u16, + chain_spec: &Box, ) -> Result> { self.base.base.prometheus_config(default_listen_port, chain_spec) } fn init( - &self, _support_url: &String, _impl_version: &String, _logger_hook: F, _config: &sc_service::Configuration, + &self, + _support_url: &String, + _impl_version: &String, + _logger_hook: F, + _config: &sc_service::Configuration, ) -> Result<()> where F: FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration), @@ -387,11 +382,7 @@ impl CliConfiguration for RelayChainCli { fn chain_id(&self, is_dev: bool) -> Result { let chain_id = self.base.base.chain_id(is_dev)?; - Ok(if chain_id.is_empty() { - self.chain_id.clone().unwrap_or_default() - } else { - chain_id - }) + Ok(if chain_id.is_empty() { self.chain_id.clone().unwrap_or_default() } else { chain_id }) } fn role(&self, is_dev: bool) -> Result { diff --git a/polimec-skeleton/node/src/rpc.rs b/polimec-skeleton/node/src/rpc.rs index 24bad1e9e..77fc3af78 100644 --- a/polimec-skeleton/node/src/rpc.rs +++ b/polimec-skeleton/node/src/rpc.rs @@ -48,11 +48,7 @@ where use substrate_frame_rpc_system::{System, SystemApiServer}; let mut module = RpcExtension::new(()); - let FullDeps { - client, - pool, - deny_unsafe, - } = deps; + let FullDeps { client, pool, deny_unsafe } = deps; module.merge(System::new(client.clone(), pool, deny_unsafe).into_rpc())?; module.merge(TransactionPayment::new(client).into_rpc())?; diff --git a/polimec-skeleton/node/src/service.rs b/polimec-skeleton/node/src/service.rs index be0366bc3..afca3993a 100644 --- a/polimec-skeleton/node/src/service.rs +++ b/polimec-skeleton/node/src/service.rs @@ -81,9 +81,7 @@ pub fn new_partial( let heap_pages = config .default_heap_pages - .map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| HeapAllocStrategy::Static { - extra_pages: h as _, - }); + .map_or(DEFAULT_HEAP_ALLOC_STRATEGY, |h| HeapAllocStrategy::Static { extra_pages: h as _ }); let wasm = WasmExecutor::builder() .with_execution_method(config.wasm_method) @@ -144,8 +142,11 @@ pub fn new_partial( /// This is the actual implementation that is abstract over the executor and the runtime api. #[sc_tracing::logging::prefix_logs_with("Parachain")] async fn start_node_impl( - parachain_config: Configuration, polkadot_config: Configuration, collator_options: CollatorOptions, - para_id: ParaId, hwbench: Option, + parachain_config: Configuration, + polkadot_config: Configuration, + collator_options: CollatorOptions, + para_id: ParaId, + hwbench: Option, ) -> sc_service::error::Result<(TaskManager, Arc)> { let parachain_config = prepare_node_config(parachain_config); @@ -199,11 +200,7 @@ async fn start_node_impl( let transaction_pool = transaction_pool.clone(); Box::new(move |deny_unsafe, _| { - let deps = crate::rpc::FullDeps { - client: client.clone(), - pool: transaction_pool.clone(), - deny_unsafe, - }; + let deps = crate::rpc::FullDeps { client: client.clone(), pool: transaction_pool.clone(), deny_unsafe }; crate::rpc::create_full(deps).map_err(Into::into) }) @@ -250,9 +247,8 @@ async fn start_node_impl( let relay_chain_slot_duration = Duration::from_secs(6); - let overseer_handle = relay_chain_interface - .overseer_handle() - .map_err(|e| sc_service::Error::Application(Box::new(e)))?; + let overseer_handle = + relay_chain_interface.overseer_handle().map_err(|e| sc_service::Error::Application(Box::new(e)))?; if validator { let parachain_consensus = build_consensus( @@ -310,8 +306,11 @@ async fn start_node_impl( /// Build the import queue for the parachain runtime. fn build_import_queue( - client: Arc, block_import: ParachainBlockImport, config: &Configuration, - telemetry: Option, task_manager: &TaskManager, + client: Arc, + block_import: ParachainBlockImport, + config: &Configuration, + telemetry: Option, + task_manager: &TaskManager, ) -> Result, sc_service::Error> { let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; @@ -338,11 +337,17 @@ fn build_import_queue( } fn build_consensus( - client: Arc, block_import: ParachainBlockImport, prometheus_registry: Option<&Registry>, - telemetry: Option, task_manager: &TaskManager, + client: Arc, + block_import: ParachainBlockImport, + prometheus_registry: Option<&Registry>, + telemetry: Option, + task_manager: &TaskManager, relay_chain_interface: Arc, transaction_pool: Arc>, - sync_oracle: Arc>, keystore: KeystorePtr, force_authoring: bool, para_id: ParaId, + sync_oracle: Arc>, + keystore: KeystorePtr, + force_authoring: bool, + para_id: ParaId, ) -> Result>, sc_service::Error> { let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; @@ -393,21 +398,16 @@ fn build_consensus( telemetry, }; - Ok(AuraConsensus::build::< - sp_consensus_aura::sr25519::AuthorityPair, - _, - _, - _, - _, - _, - _, - >(params)) + Ok(AuraConsensus::build::(params)) } /// Start a parachain node. pub async fn start_parachain_node( - parachain_config: Configuration, polkadot_config: Configuration, collator_options: CollatorOptions, - para_id: ParaId, hwbench: Option, + parachain_config: Configuration, + polkadot_config: Configuration, + collator_options: CollatorOptions, + para_id: ParaId, + hwbench: Option, ) -> sc_service::error::Result<(TaskManager, Arc)> { start_node_impl(parachain_config, polkadot_config, collator_options, para_id, hwbench).await } diff --git a/polimec-skeleton/pallets/credentials/src/lib.rs b/polimec-skeleton/pallets/credentials/src/lib.rs index 287497eeb..a06c219e9 100644 --- a/polimec-skeleton/pallets/credentials/src/lib.rs +++ b/polimec-skeleton/pallets/credentials/src/lib.rs @@ -139,25 +139,13 @@ pub mod pallet { use sp_std::collections::btree_set::BTreeSet; let issuers_set: BTreeSet<_> = self.issuers.iter().collect(); - assert_eq!( - issuers_set.len(), - self.issuers.len(), - "Issuers cannot contain duplicate accounts." - ); + assert_eq!(issuers_set.len(), self.issuers.len(), "Issuers cannot contain duplicate accounts."); let retails_set: BTreeSet<_> = self.retails.iter().collect(); - assert_eq!( - retails_set.len(), - self.retails.len(), - "Issuers cannot contain duplicate accounts." - ); + assert_eq!(retails_set.len(), self.retails.len(), "Issuers cannot contain duplicate accounts."); let professionals_set: BTreeSet<_> = self.professionals.iter().collect(); - assert_eq!( - professionals_set.len(), - self.professionals.len(), - "Issuers cannot contain duplicate accounts." - ); + assert_eq!(professionals_set.len(), self.professionals.len(), "Issuers cannot contain duplicate accounts."); let institutionals_set: BTreeSet<_> = self.institutionals.iter().collect(); assert_eq!( @@ -194,7 +182,9 @@ pub mod pallet { // TODO: Set a proper weight #[pallet::weight(1)] pub fn remove_member( - origin: OriginFor, credential: Credential, who: AccountIdLookupOf, + origin: OriginFor, + credential: Credential, + who: AccountIdLookupOf, ) -> DispatchResult { T::RemoveOrigin::ensure_origin(origin)?; let who = T::Lookup::lookup(who)?; diff --git a/polimec-skeleton/pallets/credentials/src/mock.rs b/polimec-skeleton/pallets/credentials/src/mock.rs index 22f2f23a4..e4089b5e8 100644 --- a/polimec-skeleton/pallets/credentials/src/mock.rs +++ b/polimec-skeleton/pallets/credentials/src/mock.rs @@ -49,30 +49,30 @@ parameter_types! { } impl frame_system::Config for Test { + type AccountData = pallet_balances::AccountData; + type AccountId = AccountId; type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); + type BlockHashCount = BlockHashCount; type BlockLength = (); - type DbWeight = (); - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Index = u64; type BlockNumber = BlockNumber; + type BlockWeights = (); + type DbWeight = (); type Hash = H256; type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; type Header = Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); + type Index = u64; + type Lookup = IdentityLookup; + type MaxConsumers = frame_support::traits::ConstU32<16>; type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = ConstU16<42>; + type OnNewAccount = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type PalletInfo = PalletInfo; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type SS58Prefix = ConstU16<42>; + type SystemWeightInfo = (); + type Version = (); } parameter_types! { @@ -80,30 +80,30 @@ parameter_types! { } impl pallet_balances::Config for Test { - type MaxLocks = frame_support::traits::ConstU32<1024>; - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; + type AccountStore = System; type Balance = Balance; - type RuntimeEvent = RuntimeEvent; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = (); - type HoldIdentifier = [u8; 8]; type FreezeIdentifier = [u8; 8]; + type HoldIdentifier = [u8; 8]; type MaxFreezes = frame_support::traits::ConstU32<1024>; type MaxHolds = frame_support::traits::ConstU32<1024>; + type MaxLocks = frame_support::traits::ConstU32<1024>; + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); } impl pallet_credentials::Config for Test { - type RuntimeEvent = RuntimeEvent; type AddOrigin = EnsureRoot; + type MembershipChanged = (); + type MembershipInitialized = (); + type PrimeOrigin = EnsureRoot; type RemoveOrigin = EnsureRoot; - type SwapOrigin = EnsureRoot; type ResetOrigin = EnsureRoot; - type PrimeOrigin = EnsureRoot; - type MembershipInitialized = (); - type MembershipChanged = (); + type RuntimeEvent = RuntimeEvent; + type SwapOrigin = EnsureRoot; } // Build genesis storage according to the mock runtime. @@ -112,9 +112,7 @@ pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); GenesisConfig { - balances: BalancesConfig { - balances: vec![(1, 512), (2, 512), (3, 512), (4, 512), (5, 512)], - }, + balances: BalancesConfig { balances: vec![(1, 512), (2, 512), (3, 512), (4, 512), (5, 512)] }, credentials: CredentialsConfig { issuers: vec![1], retails: vec![2], diff --git a/polimec-skeleton/pallets/credentials/src/tests.rs b/polimec-skeleton/pallets/credentials/src/tests.rs index ad6470204..423377849 100644 --- a/polimec-skeleton/pallets/credentials/src/tests.rs +++ b/polimec-skeleton/pallets/credentials/src/tests.rs @@ -19,10 +19,7 @@ use frame_support::{assert_noop, assert_ok, error::BadOrigin, BoundedVec}; use polimec_traits::{Country, Credential, Issuers, MemberRole, PolimecMembers}; pub fn last_event() -> RuntimeEvent { - frame_system::Pallet::::events() - .pop() - .expect("Event expected") - .event + frame_system::Pallet::::events().pop().expect("Event expected").event } const ALICE: AccountId = 1; @@ -71,10 +68,7 @@ fn add_member_works() { fn only_root_can_add_member() { new_test_ext().execute_with(|| { let cred = new_test_credential(MemberRole::Issuer); - assert_noop!( - Credentials::add_member(RuntimeOrigin::signed(ALICE), cred, BOB), - BadOrigin - ); + assert_noop!(Credentials::add_member(RuntimeOrigin::signed(ALICE), cred, BOB), BadOrigin); }) } @@ -82,10 +76,7 @@ fn only_root_can_add_member() { fn cant_add_already_member() { new_test_ext().execute_with(|| { let cred = new_test_credential(MemberRole::Issuer); - assert_noop!( - Credentials::add_member(RuntimeOrigin::root(), cred, ALICE), - Error::::AlreadyMember - ); + assert_noop!(Credentials::add_member(RuntimeOrigin::root(), cred, ALICE), Error::::AlreadyMember); }) } @@ -102,10 +93,7 @@ fn remove_member_works() { fn only_root_can_remove_member() { new_test_ext().execute_with(|| { let cred = new_test_credential(MemberRole::Issuer); - assert_noop!( - Credentials::remove_member(RuntimeOrigin::signed(ALICE), cred, ALICE), - BadOrigin - ); + assert_noop!(Credentials::remove_member(RuntimeOrigin::signed(ALICE), cred, ALICE), BadOrigin); }) } @@ -113,10 +101,7 @@ fn only_root_can_remove_member() { fn cant_remove_not_a_member() { new_test_ext().execute_with(|| { let cred = new_test_credential(MemberRole::Issuer); - assert_noop!( - Credentials::remove_member(RuntimeOrigin::root(), cred, EVE), - Error::::NotMember - ); + assert_noop!(Credentials::remove_member(RuntimeOrigin::root(), cred, EVE), Error::::NotMember); }) } diff --git a/polimec-skeleton/pallets/funding/Cargo.toml b/polimec-skeleton/pallets/funding/Cargo.toml index 6f72aa543..738fce461 100644 --- a/polimec-skeleton/pallets/funding/Cargo.toml +++ b/polimec-skeleton/pallets/funding/Cargo.toml @@ -29,7 +29,6 @@ sp-std = { git = "https://github.com/paritytech/substrate", default-features = f sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } sp-arithmetic = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } polimec-traits = { path = "../../traits", default-features = false } -pallet-linear-release = { path = "../linear-release", default-features = false } [dev-dependencies] sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } @@ -38,6 +37,7 @@ pallet-balances = { git = "https://github.com/paritytech/substrate", default-fea pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } pallet-assets = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } pallet-credentials = { path = "../credentials", default-features = false } +pallet-linear-release = { path = "../linear-release", default-features = false } [features] default = ["std"] diff --git a/polimec-skeleton/pallets/funding/src/benchmarking.rs b/polimec-skeleton/pallets/funding/src/benchmarking.rs index 7757afd77..18e6f1e77 100644 --- a/polimec-skeleton/pallets/funding/src/benchmarking.rs +++ b/polimec-skeleton/pallets/funding/src/benchmarking.rs @@ -27,14 +27,13 @@ type PolimecSystem = frame_system::Pallet; use super::*; use frame_benchmarking::{account, benchmarks}; -use frame_support::dispatch::RawOrigin; -use frame_support::traits::OriginTrait; use frame_support::{ assert_ok, + dispatch::RawOrigin, traits::{ fungible::Mutate, fungibles::{Inspect, Mutate as FungiblesMutate}, - Hooks, + Hooks, OriginTrait, }, }; use frame_system::{Pallet as System, RawOrigin as SystemOrigin}; @@ -67,10 +66,7 @@ fn assert_last_event(generic_event: ::RuntimeEvent) { #[allow(unused)] fn get_events() -> frame_benchmarking::Vec<::RuntimeEvent> { - frame_system::Pallet::::events() - .into_iter() - .map(|r| r.event) - .collect::>() + frame_system::Pallet::::events().into_iter().map(|r| r.event).collect::>() } fn create_default_project(id: Option) -> (T::ProjectIdentifier, AccountIdOf, ProjectMetadataOf) { diff --git a/polimec-skeleton/pallets/funding/src/functions.rs b/polimec-skeleton/pallets/funding/src/functions.rs index fd4139e86..4912b8c22 100644 --- a/polimec-skeleton/pallets/funding/src/functions.rs +++ b/polimec-skeleton/pallets/funding/src/functions.rs @@ -21,14 +21,13 @@ use super::*; use crate::traits::{BondingRequirementCalculation, ProvideStatemintPrice}; -use frame_support::traits::fungible::InspectHold; -use frame_support::traits::tokens::{Precision, Preservation}; use frame_support::{ ensure, pallet_prelude::DispatchError, traits::{ - fungible::MutateHold as FungibleMutateHold, + fungible::{InspectHold, MutateHold as FungibleMutateHold}, fungibles::{metadata::Mutate as MetadataMutate, Create, Mutate as FungiblesMutate}, + tokens::{Precision, Preservation}, Get, }, }; @@ -76,7 +75,7 @@ impl Pallet { ValidityError::PriceTooLow => Err(Error::::PriceTooLow.into()), ValidityError::ParticipantsSizeError => Err(Error::::ParticipantsSizeError.into()), ValidityError::TicketSizeError => Err(Error::::TicketSizeError.into()), - }; + } } // * Calculate new variables * @@ -151,26 +150,14 @@ impl Pallet { // * Validity checks * ensure!(project_details.issuer == caller, Error::::NotAllowed); - ensure!( - project_details.status == ProjectStatus::Application, - Error::::ProjectNotInApplicationRound - ); + ensure!(project_details.status == ProjectStatus::Application, Error::::ProjectNotInApplicationRound); ensure!(!project_details.is_frozen, Error::::ProjectAlreadyFrozen); - ensure!( - project_metadata.offchain_information_hash.is_some(), - Error::::MetadataNotProvided - ); + ensure!(project_metadata.offchain_information_hash.is_some(), Error::::MetadataNotProvided); // * Calculate new variables * let evaluation_end_block = now + T::EvaluationDuration::get(); - project_details - .phase_transition_points - .application - .update(None, Some(now)); - project_details - .phase_transition_points - .evaluation - .update(Some(now + 1u32.into()), Some(evaluation_end_block)); + project_details.phase_transition_points.application.update(None, Some(now)); + project_details.phase_transition_points.evaluation.update(Some(now + 1u32.into()), Some(evaluation_end_block)); project_details.is_frozen = true; project_details.status = ProjectStatus::EvaluationRound; @@ -178,10 +165,7 @@ impl Pallet { // TODO: Should we make it possible to end an application, and schedule for a later point the evaluation? // Or should we just make it so that the evaluation starts immediately after the application ends? ProjectsDetails::::insert(project_id, project_details); - Self::add_to_update_store( - evaluation_end_block + 1u32.into(), - (&project_id, UpdateType::EvaluationEnd), - ); + Self::add_to_update_store(evaluation_end_block + 1u32.into(), (&project_id, UpdateType::EvaluationEnd)); // * Emit events * Self::deposit_event(Event::::EvaluationStarted { project_id }); @@ -221,29 +205,22 @@ impl Pallet { // * Get variables * let mut project_details = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); - let evaluation_end_block = project_details - .phase_transition_points - .evaluation - .end() - .ok_or(Error::::FieldIsNone)?; + let evaluation_end_block = + project_details.phase_transition_points.evaluation.end().ok_or(Error::::FieldIsNone)?; let fundraising_target_usd = project_details.fundraising_target; let current_plmc_price = T::PriceProvider::get_price(PLMC_STATEMINT_ID).ok_or(Error::::PLMCPriceNotAvailable)?; // * Validity checks * - ensure!( - project_details.status == ProjectStatus::EvaluationRound, - Error::::ProjectNotInEvaluationRound - ); + ensure!(project_details.status == ProjectStatus::EvaluationRound, Error::::ProjectNotInEvaluationRound); ensure!(now > evaluation_end_block, Error::::EvaluationPeriodNotEnded); // * Calculate new variables * let initial_balance: BalanceOf = 0u32.into(); let total_amount_bonded = Evaluations::::iter_prefix(project_id).fold(initial_balance, |total, (_evaluator, bonds)| { - let user_total_plmc_bond = bonds - .iter() - .fold(total, |acc, bond| acc.saturating_add(bond.original_plmc_bond)); + let user_total_plmc_bond = + bonds.iter().fold(total, |acc, bond| acc.saturating_add(bond.original_plmc_bond)); total.saturating_add(user_total_plmc_bond) }); @@ -268,10 +245,7 @@ impl Pallet { project_details .phase_transition_points .auction_initialize_period - .update( - Some(auction_initialize_period_start_block.clone()), - Some(auction_initialize_period_end_block), - ); + .update(Some(auction_initialize_period_start_block.clone()), Some(auction_initialize_period_end_block)); project_details.status = ProjectStatus::AuctionInitializePeriod; ProjectsDetails::::insert(project_id, project_details); Self::add_to_update_store( @@ -344,10 +318,7 @@ impl Pallet { caller == project_details.issuer || caller == T::PalletId::get().into_account_truncating(), Error::::NotAllowed ); - ensure!( - now >= auction_initialize_period_start_block, - Error::::TooEarlyForEnglishAuctionStart - ); + ensure!(now >= auction_initialize_period_start_block, Error::::TooEarlyForEnglishAuctionStart); ensure!( project_details.status == ProjectStatus::AuctionInitializePeriod, Error::::ProjectNotInAuctionInitializePeriodRound @@ -371,10 +342,7 @@ impl Pallet { Self::remove_from_update_store(&project_id)?; } // Schedule for automatic transition to candle auction round - Self::add_to_update_store( - english_end_block + 1u32.into(), - (&project_id, UpdateType::CandleAuctionStart), - ); + Self::add_to_update_store(english_end_block + 1u32.into(), (&project_id, UpdateType::CandleAuctionStart)); // * Emit events * Self::deposit_event(Event::::EnglishAuctionStarted { project_id, when: now }); @@ -409,11 +377,8 @@ impl Pallet { // * Get variables * let mut project_details = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); - let english_end_block = project_details - .phase_transition_points - .english_auction - .end() - .ok_or(Error::::FieldIsNone)?; + let english_end_block = + project_details.phase_transition_points.english_auction.end().ok_or(Error::::FieldIsNone)?; // * Validity checks * ensure!(now > english_end_block, Error::::TooEarlyForCandleAuctionStart); @@ -434,10 +399,7 @@ impl Pallet { project_details.status = ProjectStatus::AuctionRound(AuctionPhase::Candle); ProjectsDetails::::insert(project_id, project_details); // Schedule for automatic check by on_initialize. Success depending on enough funding reached - Self::add_to_update_store( - candle_end_block + 1u32.into(), - (&project_id, UpdateType::CommunityFundingStart), - ); + Self::add_to_update_store(candle_end_block + 1u32.into(), (&project_id, UpdateType::CommunityFundingStart)); // * Emit events * Self::deposit_event(Event::::CandleAuctionStarted { project_id, when: now }); @@ -471,22 +433,13 @@ impl Pallet { // * Get variables * let project_details = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); - let auction_candle_start_block = project_details - .phase_transition_points - .candle_auction - .start() - .ok_or(Error::::FieldIsNone)?; - let auction_candle_end_block = project_details - .phase_transition_points - .candle_auction - .end() - .ok_or(Error::::FieldIsNone)?; + let auction_candle_start_block = + project_details.phase_transition_points.candle_auction.start().ok_or(Error::::FieldIsNone)?; + let auction_candle_end_block = + project_details.phase_transition_points.candle_auction.end().ok_or(Error::::FieldIsNone)?; // * Validity checks * - ensure!( - now > auction_candle_end_block, - Error::::TooEarlyForCommunityRoundStart - ); + ensure!(now > auction_candle_end_block, Error::::TooEarlyForCommunityRoundStart); ensure!( project_details.status == ProjectStatus::AuctionRound(AuctionPhase::Candle), Error::::ProjectNotInCandleAuctionRound @@ -514,7 +467,7 @@ impl Pallet { Self::deposit_event(Event::::AuctionFailed { project_id }); Ok(()) - } + }, e @ Err(_) => e, Ok(()) => { // Get info again after updating it with new price. @@ -534,7 +487,7 @@ impl Pallet { Self::deposit_event(Event::::CommunityFundingStarted { project_id }); Ok(()) - } + }, } } @@ -563,18 +516,12 @@ impl Pallet { // * Get variables * let mut project_details = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; let now = >::block_number(); - let community_end_block = project_details - .phase_transition_points - .community - .end() - .ok_or(Error::::FieldIsNone)?; + let community_end_block = + project_details.phase_transition_points.community.end().ok_or(Error::::FieldIsNone)?; // * Validity checks * ensure!(now > community_end_block, Error::::TooEarlyForRemainderRoundStart); - ensure!( - project_details.status == ProjectStatus::CommunityRound, - Error::::ProjectNotInCommunityRound - ); + ensure!(project_details.status == ProjectStatus::CommunityRound, Error::::ProjectNotInCommunityRound); // * Calculate new variables * let remainder_start_block = now + 1u32.into(); @@ -638,9 +585,9 @@ impl Pallet { // * Validity checks * ensure!( - remaining_cts == 0u32.into() - || project_details.status == ProjectStatus::FundingFailed - || matches!(remainder_end_block, Some(end_block) if now > end_block), + remaining_cts == 0u32.into() || + project_details.status == ProjectStatus::FundingFailed || + matches!(remainder_end_block, Some(end_block) if now > end_block), Error::::TooEarlyForFundingEnd ); @@ -720,10 +667,7 @@ impl Pallet { let mut project_details = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; // * Validity checks * - ensure!( - project_details.status == ProjectStatus::FundingSuccessful, - Error::::ProjectNotInFundingEndedRound - ); + ensure!(project_details.status == ProjectStatus::FundingSuccessful, Error::::ProjectNotInFundingEndedRound); // Update project Info project_details.status = ProjectStatus::ReadyToLaunch; @@ -748,7 +692,9 @@ impl Pallet { /// * [`ProjectsDetails`] - Check that the project is not frozen /// * [`ProjectsMetadata`] - Update the metadata hash pub fn do_edit_metadata( - issuer: AccountIdOf, project_id: T::ProjectIdentifier, project_metadata_hash: T::Hash, + issuer: AccountIdOf, + project_id: T::ProjectIdentifier, + project_metadata_hash: T::Hash, ) -> Result<(), DispatchError> { // * Get variables * let mut project_metadata = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; @@ -757,10 +703,7 @@ impl Pallet { // * Validity checks * ensure!(project_details.issuer == issuer, Error::::NotAllowed); ensure!(!project_details.is_frozen, Error::::Frozen); - ensure!( - !Images::::contains_key(project_metadata_hash), - Error::::MetadataAlreadyExists - ); + ensure!(!Images::::contains_key(project_metadata_hash), Error::::MetadataAlreadyExists); // TODO: PLMC-133. Replace this when this PR is merged: https://github.com/KILTprotocol/kilt-node/pull/448 // ensure!( @@ -779,9 +722,12 @@ impl Pallet { Ok(()) } + // Note: usd_amount needs to have the same amount of decimals as PLMC,, so when multiplied by the plmc-usd price, it gives us the PLMC amount with the decimals we wanted. pub fn do_evaluate( - evaluator: AccountIdOf, project_id: T::ProjectIdentifier, usd_amount: BalanceOf, + evaluator: AccountIdOf, + project_id: T::ProjectIdentifier, + usd_amount: BalanceOf, ) -> Result<(), DispatchError> { // * Get variables * let mut project_details = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; @@ -790,18 +736,12 @@ impl Pallet { let mut caller_existing_evaluations = Evaluations::::get(project_id, evaluator.clone()); let plmc_usd_price = T::PriceProvider::get_price(PLMC_STATEMINT_ID).ok_or(Error::::PLMCPriceNotAvailable)?; let early_evaluation_reward_threshold_usd = - T::EvaluationSuccessThreshold::get() * project_details.fundraising_target; + T::EvaluationSuccessThreshold::get() * project_details.fundraising_target; let evaluation_round_info = &mut project_details.evaluation_round_info; // * Validity Checks * - ensure!( - evaluator.clone() != project_details.issuer, - Error::::ContributionToThemselves - ); - ensure!( - project_details.status == ProjectStatus::EvaluationRound, - Error::::EvaluationNotStarted - ); + ensure!(evaluator.clone() != project_details.issuer, Error::::ContributionToThemselves); + ensure!(project_details.status == ProjectStatus::EvaluationRound, Error::::EvaluationNotStarted); // * Calculate new variables * let plmc_bond = plmc_usd_price @@ -842,15 +782,12 @@ impl Pallet { Ok(_) => { T::NativeCurrency::hold(&LockType::Evaluation(project_id), &evaluator, plmc_bond) .map_err(|_| Error::::InsufficientBalance)?; - } + }, Err(_) => { // Evaluations are stored in descending order. If the evaluation vector for the user is full, we drop the lowest/last bond let lowest_evaluation = caller_existing_evaluations.swap_remove(caller_existing_evaluations.len() - 1); - ensure!( - lowest_evaluation.original_plmc_bond < plmc_bond, - Error::::EvaluationBondTooLow - ); + ensure!(lowest_evaluation.original_plmc_bond < plmc_bond, Error::::EvaluationBondTooLow); T::NativeCurrency::release( &LockType::Evaluation(project_id), @@ -864,10 +801,8 @@ impl Pallet { .map_err(|_| Error::::InsufficientBalance)?; // This should never fail since we just removed an element from the vector - caller_existing_evaluations - .try_push(new_evaluation) - .map_err(|_| Error::::ImpossibleState)?; - } + caller_existing_evaluations.try_push(new_evaluation).map_err(|_| Error::::ImpossibleState)?; + }, }; caller_existing_evaluations.sort_by_key(|bond| Reverse(bond.original_plmc_bond)); @@ -879,11 +814,7 @@ impl Pallet { ProjectsDetails::::insert(project_id, project_details); // * Emit events * - Self::deposit_event(Event::::FundsBonded { - project_id, - amount: plmc_bond, - bonder: evaluator, - }); + Self::deposit_event(Event::::FundsBonded { project_id, amount: plmc_bond, bonder: evaluator }); Ok(()) } @@ -903,8 +834,12 @@ impl Pallet { /// * [`BiddingBonds`] - Update the storage with the bidder's PLMC bond for that bid /// * [`Bids`] - Check previous bids by that user, and update the storage with the new bid pub fn do_bid( - bidder: AccountIdOf, project_id: T::ProjectIdentifier, ct_amount: BalanceOf, ct_usd_price: T::Price, - multiplier: Option>, funding_asset: AcceptedFundingAsset, + bidder: AccountIdOf, + project_id: T::ProjectIdentifier, + ct_amount: BalanceOf, + ct_usd_price: T::Price, + multiplier: Option>, + funding_asset: AcceptedFundingAsset, ) -> Result<(), DispatchError> { // * Get variables * let project_metadata = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; @@ -919,14 +854,8 @@ impl Pallet { let multiplier = multiplier.unwrap_or_default(); // * Validity checks * - ensure!( - bidder.clone() != project_details.issuer, - Error::::ContributionToThemselves - ); - ensure!( - matches!(project_details.status, ProjectStatus::AuctionRound(_)), - Error::::AuctionNotStarted - ); + ensure!(bidder.clone() != project_details.issuer, Error::::ContributionToThemselves); + ensure!(matches!(project_details.status, ProjectStatus::AuctionRound(_)), Error::::AuctionNotStarted); ensure!(ct_usd_price >= project_metadata.minimum_price, Error::::BidTooLow); if let Some(minimum_ticket_size) = project_metadata.ticket_size.minimum { // Make sure the bid amount is greater than the minimum specified by the issuer @@ -936,20 +865,15 @@ impl Pallet { // Make sure the bid amount is less than the maximum specified by the issuer ensure!(ticket_size <= maximum_ticket_size, Error::::BidTooLow); }; - ensure!( - funding_asset == project_metadata.participation_currencies, - Error::::FundingAssetNotAccepted - ); + ensure!(funding_asset == project_metadata.participation_currencies, Error::::FundingAssetNotAccepted); // * Calculate new variables * let (plmc_vesting_period, ct_vesting_period) = Self::calculate_vesting_periods(bidder.clone(), multiplier, ct_amount, ct_usd_price) .map_err(|_| Error::::BadMath)?; let required_plmc_bond = plmc_vesting_period.amount; - let required_funding_asset_transfer = funding_asset_usd_price - .reciprocal() - .ok_or(Error::::BadMath)? - .saturating_mul_int(ticket_size); + let required_funding_asset_transfer = + funding_asset_usd_price.reciprocal().ok_or(Error::::BadMath)?.saturating_mul_int(ticket_size); let asset_id = funding_asset.to_statemint_id(); let new_bid = BidInfoOf:: { @@ -980,14 +904,10 @@ impl Pallet { // TODO: PLMC-159. Send an XCM message to Statemint/e to transfer a `bid.market_cap` amount of USDC (or the Currency specified by the issuer) to the PalletId Account // Alternative TODO: PLMC-159. The user should have the specified currency (e.g: USDC) already on Polimec - } + }, Err(_) => { // Since the bids are sorted by price, and in this branch the Vec is full, the last element is the lowest bid - let lowest_plmc_bond = existing_bids - .iter() - .last() - .ok_or(Error::::ImpossibleState)? - .plmc_bond; + let lowest_plmc_bond = existing_bids.iter().last().ok_or(Error::::ImpossibleState)?.plmc_bond; ensure!(new_bid.plmc_bond > lowest_plmc_bond, Error::::BidTooLow); @@ -1005,10 +925,8 @@ impl Pallet { Self::try_funding_asset_hold(&bidder, project_id, required_funding_asset_transfer, asset_id)?; // This should never fail, since we just removed an element from the Vec - existing_bids - .try_push(new_bid) - .map_err(|_| Error::::ImpossibleState)?; - } + existing_bids.try_push(new_bid).map_err(|_| Error::::ImpossibleState)?; + }, }; existing_bids.sort_by(|a, b| b.cmp(a)); @@ -1016,12 +934,7 @@ impl Pallet { Bids::::set(project_id, bidder, existing_bids); NextBidId::::set(bid_id.saturating_add(One::one())); - Self::deposit_event(Event::::Bid { - project_id, - amount: ct_amount, - price: ct_usd_price, - multiplier, - }); + Self::deposit_event(Event::::Bid { project_id, amount: ct_amount, price: ct_usd_price, multiplier }); Ok(()) } @@ -1041,8 +954,11 @@ impl Pallet { /// * [`Contributions`] - Update storage with the new contribution /// * [`T::NativeCurrency`] - Update the balance of the contributor and the project pot pub fn do_contribute( - contributor: AccountIdOf, project_id: T::ProjectIdentifier, token_amount: BalanceOf, - multiplier: Option>, asset: AcceptedFundingAsset, + contributor: AccountIdOf, + project_id: T::ProjectIdentifier, + token_amount: BalanceOf, + multiplier: Option>, + asset: AcceptedFundingAsset, ) -> Result<(), DispatchError> { // * Get variables * let project_metadata = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectNotFound)?; @@ -1051,9 +967,7 @@ impl Pallet { let contribution_id = Self::next_contribution_id(); let mut existing_contributions = Contributions::::get(project_id, contributor.clone()); - let ct_usd_price = project_details - .weighted_average_price - .ok_or(Error::::AuctionNotStarted)?; + let ct_usd_price = project_details.weighted_average_price.ok_or(Error::::AuctionNotStarted)?; let mut ticket_size = ct_usd_price.checked_mul_int(token_amount).ok_or(Error::::BadMath)?; let funding_asset_usd_price = T::PriceProvider::get_price(asset.to_statemint_id()).ok_or(Error::::PriceNotFound)?; @@ -1061,13 +975,10 @@ impl Pallet { let multiplier = multiplier.unwrap_or_default(); // * Validity checks * + ensure!(contributor.clone() != project_details.issuer, Error::::ContributionToThemselves); ensure!( - contributor.clone() != project_details.issuer, - Error::::ContributionToThemselves - ); - ensure!( - project_details.status == ProjectStatus::CommunityRound - || project_details.status == ProjectStatus::RemainderRound, + project_details.status == ProjectStatus::CommunityRound || + project_details.status == ProjectStatus::RemainderRound, Error::::AuctionNotStarted ); @@ -1079,10 +990,7 @@ impl Pallet { // Make sure the bid amount is less than the maximum specified by the issuer ensure!(ticket_size <= maximum_ticket_size, Error::::ContributionTooHigh); }; - ensure!( - project_metadata.participation_currencies == asset, - Error::::FundingAssetNotAccepted - ); + ensure!(project_metadata.participation_currencies == asset, Error::::FundingAssetNotAccepted); // TODO: PLMC-133. Replace this when this PR is merged: https://github.com/KILTprotocol/kilt-node/pull/448 // ensure!( @@ -1095,23 +1003,17 @@ impl Pallet { token_amount } else { let remaining_amount = project_details.remaining_contribution_tokens; - ticket_size = ct_usd_price - .checked_mul_int(remaining_amount) - .ok_or(Error::::BadMath)?; + ticket_size = ct_usd_price.checked_mul_int(remaining_amount).ok_or(Error::::BadMath)?; remaining_amount }; let (plmc_vesting_period, ct_vesting_period) = Self::calculate_vesting_periods(contributor.clone(), multiplier.clone(), buyable_tokens, ct_usd_price) .map_err(|_| Error::::BadMath)?; let required_plmc_bond = plmc_vesting_period.amount; - let required_funding_asset_transfer = funding_asset_usd_price - .reciprocal() - .ok_or(Error::::BadMath)? - .saturating_mul_int(ticket_size); + let required_funding_asset_transfer = + funding_asset_usd_price.reciprocal().ok_or(Error::::BadMath)?.saturating_mul_int(ticket_size); let asset_id = asset.to_statemint_id(); - let remaining_cts_after_purchase = project_details - .remaining_contribution_tokens - .saturating_sub(buyable_tokens); + let remaining_cts_after_purchase = project_details.remaining_contribution_tokens.saturating_sub(buyable_tokens); let new_contribution = ContributionInfoOf:: { id: contribution_id, @@ -1133,19 +1035,13 @@ impl Pallet { Ok(_) => { Self::try_plmc_participation_lock(&contributor, project_id, required_plmc_bond)?; Self::try_funding_asset_hold(&contributor, project_id, required_funding_asset_transfer, asset_id)?; - } + }, Err(_) => { // The contributions are sorted by highest PLMC bond. If the contribution vector for the user is full, we drop the lowest/last item - let lowest_plmc_bond = existing_contributions - .iter() - .last() - .ok_or(Error::::ImpossibleState)? - .plmc_bond; - - ensure!( - new_contribution.plmc_bond > lowest_plmc_bond, - Error::::ContributionTooLow - ); + let lowest_plmc_bond = + existing_contributions.iter().last().ok_or(Error::::ImpossibleState)?.plmc_bond; + + ensure!(new_contribution.plmc_bond > lowest_plmc_bond, Error::::ContributionTooLow); Self::release_last_funding_item_in_vec( &contributor, @@ -1161,10 +1057,8 @@ impl Pallet { Self::try_funding_asset_hold(&contributor, project_id, required_funding_asset_transfer, asset_id)?; // This should never fail, since we just removed an item from the vector - existing_contributions - .try_push(new_contribution) - .map_err(|_| Error::::ImpossibleState)?; - } + existing_contributions.try_push(new_contribution).map_err(|_| Error::::ImpossibleState)?; + }, } existing_contributions.sort_by_key(|contribution| Reverse(contribution.plmc_bond)); @@ -1185,12 +1079,7 @@ impl Pallet { } // * Emit events * - Self::deposit_event(Event::::Contribution { - project_id, - contributor, - amount: token_amount, - multiplier, - }); + Self::deposit_event(Event::::Contribution { project_id, contributor, amount: token_amount, multiplier }); Ok(()) } @@ -1205,7 +1094,9 @@ impl Pallet { /// * [`BiddingBonds`] - Update the bid with the new vesting period struct, reflecting this withdrawal /// * [`T::NativeCurrency`] - Unreserve the unbonded amount pub fn do_vested_plmc_bid_unbond_for( - releaser: AccountIdOf, project_id: T::ProjectIdentifier, bidder: AccountIdOf, + releaser: AccountIdOf, + project_id: T::ProjectIdentifier, + bidder: AccountIdOf, ) -> Result<(), DispatchError> { // * Get variables * let bids = Bids::::get(project_id, &bidder); @@ -1218,7 +1109,7 @@ impl Pallet { // * Validity checks * // check that it is not too early to withdraw the next amount if plmc_vesting.next_withdrawal > now { - continue; + continue } // * Calculate variables * @@ -1228,7 +1119,7 @@ impl Pallet { while let Ok(amount) = plmc_vesting.calculate_next_withdrawal() { unbond_amount = unbond_amount.saturating_add(amount); if plmc_vesting.next_withdrawal > now { - break; + break } } bid.plmc_vesting_period = plmc_vesting; @@ -1273,7 +1164,9 @@ impl Pallet { /// * `AuctionsInfo` - Check if its time to mint some tokens based on the bid vesting period, and update the bid after minting. /// * `T::ContributionTokenCurrency` - Mint the tokens to the bidder pub fn do_vested_contribution_token_bid_mint_for( - releaser: AccountIdOf, project_id: T::ProjectIdentifier, bidder: AccountIdOf, + releaser: AccountIdOf, + project_id: T::ProjectIdentifier, + bidder: AccountIdOf, ) -> Result<(), DispatchError> { // * Get variables * let bids = Bids::::get(project_id, &bidder); @@ -1286,7 +1179,7 @@ impl Pallet { // * Validity checks * // check that it is not too early to withdraw the next amount if ct_vesting.next_withdrawal > now { - continue; + continue } // * Calculate variables * @@ -1294,7 +1187,7 @@ impl Pallet { while let Ok(amount) = ct_vesting.calculate_next_withdrawal() { mint_amount = mint_amount.saturating_add(amount); if ct_vesting.next_withdrawal > now { - break; + break } } bid.ct_vesting_period = ct_vesting; @@ -1331,7 +1224,9 @@ impl Pallet { /// * [`BiddingBonds`] - Update the bid with the new vesting period struct, reflecting this withdrawal /// * [`T::NativeCurrency`] - Unreserve the unbonded amount pub fn do_vested_plmc_purchase_unbond_for( - releaser: AccountIdOf, project_id: T::ProjectIdentifier, claimer: AccountIdOf, + releaser: AccountIdOf, + project_id: T::ProjectIdentifier, + claimer: AccountIdOf, ) -> Result<(), DispatchError> { // * Get variables * let project_details = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; @@ -1345,10 +1240,7 @@ impl Pallet { // T::HandleMembers::is_in(&MemberRole::Issuer, &issuer), // Error::::NotAuthorized // ); - ensure!( - project_details.status == ProjectStatus::FundingSuccessful, - Error::::CannotClaimYet - ); + ensure!(project_details.status == ProjectStatus::FundingSuccessful, Error::::CannotClaimYet); // TODO: PLMC-160. Check the flow of the final_price if the final price discovery during the Auction Round fails for mut contribution in contributions { @@ -1358,7 +1250,7 @@ impl Pallet { // * Validity checks * // check that it is not too early to withdraw the next amount if plmc_vesting.next_withdrawal > now { - continue; + continue } // * Calculate variables * @@ -1366,7 +1258,7 @@ impl Pallet { while let Ok(amount) = plmc_vesting.calculate_next_withdrawal() { unbond_amount = unbond_amount.saturating_add(amount); if plmc_vesting.next_withdrawal > now { - break; + break } } contribution.plmc_vesting_period = plmc_vesting; @@ -1396,9 +1288,7 @@ impl Pallet { // Obviously also the participants of the Auction Round should be able to claim their tokens // In theory this should never fail, since we insert the same number of contributions as before let updated_contributions: BoundedVec, T::MaxContributionsPerUser> = - updated_contributions - .try_into() - .map_err(|_| Error::::TooManyContributions)?; + updated_contributions.try_into().map_err(|_| Error::::TooManyContributions)?; Contributions::::insert(project_id, &claimer, updated_contributions); Ok(()) @@ -1415,7 +1305,9 @@ impl Pallet { /// * [`Contributions`] - Check if its time to mint some tokens based on the contributions vesting periods, and update the contribution after minting. /// * [`T::ContributionTokenCurrency`] - Mint the tokens to the claimer pub fn do_vested_contribution_token_purchase_mint_for( - releaser: AccountIdOf, project_id: T::ProjectIdentifier, claimer: AccountIdOf, + releaser: AccountIdOf, + project_id: T::ProjectIdentifier, + claimer: AccountIdOf, ) -> Result<(), DispatchError> { // * Get variables * let project_details = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; @@ -1429,10 +1321,7 @@ impl Pallet { // T::HandleMembers::is_in(&MemberRole::Issuer, &issuer), // Error::::NotAuthorized // ); - ensure!( - project_details.status == ProjectStatus::FundingSuccessful, - Error::::CannotClaimYet - ); + ensure!(project_details.status == ProjectStatus::FundingSuccessful, Error::::CannotClaimYet); // TODO: PLMC-160. Check the flow of the final_price if the final price discovery during the Auction Round fails for mut contribution in contributions { @@ -1442,7 +1331,7 @@ impl Pallet { // * Validity checks * // check that it is not too early to withdraw the next amount if ct_vesting.next_withdrawal > now { - continue; + continue } // * Calculate variables * @@ -1450,7 +1339,7 @@ impl Pallet { while let Ok(amount) = ct_vesting.calculate_next_withdrawal() { mint_amount = mint_amount.saturating_add(amount); if ct_vesting.next_withdrawal > now { - break; + break } } contribution.ct_vesting_period = ct_vesting; @@ -1475,16 +1364,16 @@ impl Pallet { // Obviously also the participants of the Auction Round should be able to claim their tokens // In theory this should never fail, since we insert the same number of contributions as before let updated_contributions: BoundedVec, T::MaxContributionsPerUser> = - updated_contributions - .try_into() - .map_err(|_| Error::::TooManyContributions)?; + updated_contributions.try_into().map_err(|_| Error::::TooManyContributions)?; Contributions::::insert(project_id, &claimer, updated_contributions); Ok(()) } pub fn do_evaluation_unbond_for( - releaser: AccountIdOf, project_id: T::ProjectIdentifier, evaluator: AccountIdOf, + releaser: AccountIdOf, + project_id: T::ProjectIdentifier, + evaluator: AccountIdOf, evaluation_id: T::StorageItemId, ) -> Result<(), DispatchError> { // * Get variables * @@ -1498,8 +1387,8 @@ impl Pallet { // * Validity checks * ensure!( - released_evaluation.rewarded_or_slashed == true - && matches!( + released_evaluation.rewarded_or_slashed == true && + matches!( project_details.status, ProjectStatus::EvaluationFailed | ProjectStatus::FundingFailed | ProjectStatus::FundingSuccessful ), @@ -1527,19 +1416,19 @@ impl Pallet { } pub fn do_evaluation_reward( - caller: AccountIdOf, project_id: T::ProjectIdentifier, evaluator: AccountIdOf, + caller: AccountIdOf, + project_id: T::ProjectIdentifier, + evaluator: AccountIdOf, evaluation_id: StorageItemIdOf, ) -> Result<(), DispatchError> { // * Get variables * let project_details = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectInfoNotFound)?; - let ct_price = project_details - .weighted_average_price - .ok_or(Error::::ImpossibleState)?; + let ct_price = project_details.weighted_average_price.ok_or(Error::::ImpossibleState)?; let reward_info = if let EvaluatorsOutcome::Rewarded(info) = project_details.evaluation_round_info.evaluators_outcome { info } else { - return Err(Error::::NotAllowed.into()); + return Err(Error::::NotAllowed.into()) }; let mut user_evaluations = Evaluations::::get(project_id, evaluator.clone()); let evaluation = user_evaluations @@ -1549,16 +1438,14 @@ impl Pallet { // * Validity checks * ensure!( - evaluation.rewarded_or_slashed == false - && matches!(project_details.status, ProjectStatus::FundingSuccessful), + evaluation.rewarded_or_slashed == false && + matches!(project_details.status, ProjectStatus::FundingSuccessful), Error::::NotAllowed ); // * Calculate variables * - let early_reward_weight = Perquintill::from_rational( - evaluation.early_usd_amount, - reward_info.early_evaluator_total_bonded_usd, - ); + let early_reward_weight = + Perquintill::from_rational(evaluation.early_usd_amount, reward_info.early_evaluator_total_bonded_usd); let normal_reward_weight = Perquintill::from_rational( evaluation.late_usd_amount.saturating_add(evaluation.early_usd_amount), reward_info.normal_evaluator_total_bonded_usd, @@ -1589,42 +1476,54 @@ impl Pallet { } pub fn do_release_bid_funds_for( - _caller: AccountIdOf, _project_id: T::ProjectIdentifier, _bidder: AccountIdOf, + _caller: AccountIdOf, + _project_id: T::ProjectIdentifier, + _bidder: AccountIdOf, _bid_id: StorageItemIdOf, ) -> Result<(), DispatchError> { Ok(()) } pub fn do_bid_unbond_for( - _caller: AccountIdOf, _project_id: T::ProjectIdentifier, _bidder: AccountIdOf, + _caller: AccountIdOf, + _project_id: T::ProjectIdentifier, + _bidder: AccountIdOf, _bid_id: StorageItemIdOf, ) -> Result<(), DispatchError> { Ok(()) } pub fn do_release_contribution_funds_for( - _caller: AccountIdOf, _project_id: T::ProjectIdentifier, _contributor: AccountIdOf, + _caller: AccountIdOf, + _project_id: T::ProjectIdentifier, + _contributor: AccountIdOf, _contribution_id: StorageItemIdOf, ) -> Result<(), DispatchError> { Ok(()) } pub fn do_contribution_unbond_for( - _caller: AccountIdOf, _project_id: T::ProjectIdentifier, _contributor: AccountIdOf, + _caller: AccountIdOf, + _project_id: T::ProjectIdentifier, + _contributor: AccountIdOf, _contribution_id: StorageItemIdOf, ) -> Result<(), DispatchError> { Ok(()) } pub fn do_payout_contribution_funds_for( - _caller: AccountIdOf, _project_id: T::ProjectIdentifier, _contributor: AccountIdOf, + _caller: AccountIdOf, + _project_id: T::ProjectIdentifier, + _contributor: AccountIdOf, _contribution_id: StorageItemIdOf, ) -> Result<(), DispatchError> { Ok(()) } pub fn do_payout_bid_funds_for( - _caller: AccountIdOf, _project_id: T::ProjectIdentifier, _bidder: AccountIdOf, + _caller: AccountIdOf, + _project_id: T::ProjectIdentifier, + _bidder: AccountIdOf, _bid_id: StorageItemIdOf, ) -> Result<(), DispatchError> { Ok(()) @@ -1671,22 +1570,18 @@ impl Pallet { /// Based on the amount of tokens and price to buy, a desired multiplier, and the type of investor the caller is, /// calculate the amount and vesting periods of bonded PLMC and reward CT tokens. pub fn calculate_vesting_periods( - _caller: AccountIdOf, multiplier: MultiplierOf, token_amount: BalanceOf, token_price: T::Price, - ) -> Result< - ( - Vesting>, - Vesting>, - ), - DispatchError, - > { + _caller: AccountIdOf, + multiplier: MultiplierOf, + token_amount: BalanceOf, + token_price: T::Price, + ) -> Result<(Vesting>, Vesting>), DispatchError> { let plmc_start: T::BlockNumber = 0u32.into(); let ct_start: T::BlockNumber = (T::MaxProjectsToUpdatePerBlock::get() * 7).into(); // TODO: Calculate real vesting periods based on multiplier and caller type // FIXME: if divide fails, we probably dont want to assume the multiplier is one let ticket_size = token_price.checked_mul_int(token_amount).ok_or(Error::::BadMath)?; - let usd_bonding_amount = multiplier - .calculate_bonding_requirement(ticket_size) - .map_err(|_| Error::::BadMath)?; + let usd_bonding_amount = + multiplier.calculate_bonding_requirement(ticket_size).map_err(|_| Error::::BadMath)?; let plmc_price = T::PriceProvider::get_price(PLMC_STATEMINT_ID).ok_or(Error::::PLMCPriceNotAvailable)?; let plmc_bonding_amount = plmc_price .reciprocal() @@ -1713,12 +1608,12 @@ impl Pallet { /// Calculates the price (in USD) of contribution tokens for the Community and Remainder Rounds pub fn calculate_weighted_average_price( - project_id: T::ProjectIdentifier, end_block: T::BlockNumber, total_allocation_size: BalanceOf, + project_id: T::ProjectIdentifier, + end_block: T::BlockNumber, + total_allocation_size: BalanceOf, ) -> Result<(), DispatchError> { // Get all the bids that were made before the end of the candle - let mut bids = Bids::::iter_prefix(project_id) - .flat_map(|(_bidder, bids)| bids) - .collect::>(); + let mut bids = Bids::::iter_prefix(project_id).flat_map(|(_bidder, bids)| bids).collect::>(); // temp variable to store the sum of the bids let mut bid_token_amount_sum = BalanceOf::::zero(); // temp variable to store the total value of the bids (i.e price * amount) @@ -1753,7 +1648,7 @@ impl Pallet { bid.funding_asset_amount_locked = BalanceOf::::zero(); bid.plmc_bond = BalanceOf::::zero(); - return Ok(bid); + return Ok(bid) } let buyable_amount = total_allocation_size.saturating_sub(bid_token_amount_sum); if buyable_amount == 0_u32.into() { @@ -1776,7 +1671,7 @@ impl Pallet { )?; bid.funding_asset_amount_locked = BalanceOf::::zero(); bid.plmc_bond = BalanceOf::::zero(); - return Ok(bid); + return Ok(bid) } else if bid.original_ct_amount <= buyable_amount { let maybe_ticket_size = bid.original_ct_usd_price.checked_mul_int(bid.original_ct_amount); if let Some(ticket_size) = maybe_ticket_size { @@ -1804,7 +1699,7 @@ impl Pallet { )?; bid.funding_asset_amount_locked = BalanceOf::::zero(); bid.plmc_bond = BalanceOf::::zero(); - return Ok(bid); + return Ok(bid) } } else { let maybe_ticket_size = bid.original_ct_usd_price.checked_mul_int(buyable_amount); @@ -1825,8 +1720,7 @@ impl Pallet { bid.funding_asset.to_statemint_id(), &project_account, &bid.bidder, - bid.funding_asset_amount_locked - .saturating_sub(funding_asset_amount_needed), + bid.funding_asset_amount_locked.saturating_sub(funding_asset_amount_needed), Preservation::Preserve, )?; @@ -1869,7 +1763,7 @@ impl Pallet { bid.funding_asset_amount_locked = BalanceOf::::zero(); bid.plmc_bond = BalanceOf::::zero(); - return Ok(bid); + return Ok(bid) } } @@ -1902,7 +1796,8 @@ impl Pallet { .filter_map(|bid| match bid.status { BidStatus::Accepted => { let bid_weight = ::saturating_from_rational( - bid.original_ct_usd_price.saturating_mul_int(bid.original_ct_amount), bid_usd_value_sum + bid.original_ct_usd_price.saturating_mul_int(bid.original_ct_amount), + bid_usd_value_sum, ); let weighted_price = bid.original_ct_usd_price * bid_weight; Some(weighted_price) @@ -1910,7 +1805,8 @@ impl Pallet { BidStatus::PartiallyAccepted(amount, _) => { let bid_weight = ::saturating_from_rational( - bid.original_ct_usd_price.saturating_mul_int(amount), bid_usd_value_sum + bid.original_ct_usd_price.saturating_mul_int(amount), + bid_usd_value_sum, ); Some(bid.original_ct_usd_price.saturating_mul(bid_weight)) }, @@ -1924,18 +1820,14 @@ impl Pallet { // Update the bid in the storage for bid in bids.into_iter() { Bids::::mutate(project_id, bid.bidder.clone(), |bids| -> Result<(), DispatchError> { - let bid_index = bids - .clone() - .into_iter() - .position(|b| b.id == bid.id) - .ok_or(Error::::ImpossibleState)?; + let bid_index = + bids.clone().into_iter().position(|b| b.id == bid.id).ok_or(Error::::ImpossibleState)?; let mut final_bid = bid; if final_bid.final_ct_usd_price > weighted_token_price { final_bid.final_ct_usd_price = weighted_token_price; - let new_ticket_size = weighted_token_price - .checked_mul_int(final_bid.final_ct_amount) - .ok_or(Error::::BadMath)?; + let new_ticket_size = + weighted_token_price.checked_mul_int(final_bid.final_ct_amount).ok_or(Error::::BadMath)?; let funding_asset_price = T::PriceProvider::get_price(final_bid.funding_asset.to_statemint_id()) .ok_or(Error::::PriceNotFound)?; @@ -1949,9 +1841,7 @@ impl Pallet { final_bid.funding_asset.to_statemint_id(), &project_account, &final_bid.bidder, - final_bid - .funding_asset_amount_locked - .saturating_sub(funding_asset_amount_needed), + final_bid.funding_asset_amount_locked.saturating_sub(funding_asset_amount_needed), Preservation::Preserve, ); if let Err(e) = try_transfer { @@ -1998,9 +1888,8 @@ impl Pallet { info.weighted_average_price = Some(weighted_token_price); info.remaining_contribution_tokens = info.remaining_contribution_tokens.saturating_sub(bid_token_amount_sum); - info.funding_amount_reached = info - .funding_amount_reached - .saturating_add(final_total_funding_reached_by_bids); + info.funding_amount_reached = + info.funding_amount_reached.saturating_add(final_total_funding_reached_by_bids); Ok(()) } else { Err(Error::::ProjectNotFound.into()) @@ -2011,7 +1900,8 @@ impl Pallet { } pub fn select_random_block( - candle_starting_block: T::BlockNumber, candle_ending_block: T::BlockNumber, + candle_starting_block: T::BlockNumber, + candle_ending_block: T::BlockNumber, ) -> T::BlockNumber { let nonce = Self::get_and_increment_nonce(); let (random_value, _known_since) = T::Randomness::random(&nonce); @@ -2032,7 +1922,8 @@ impl Pallet { // This function is kept separate from the `do_claim_contribution_tokens` for easier testing the logic #[inline(always)] pub fn calculate_claimable_tokens( - contribution_amount: BalanceOf, weighted_average_price: BalanceOf, + contribution_amount: BalanceOf, + weighted_average_price: BalanceOf, ) -> FixedU128 { FixedU128::saturating_from_rational(contribution_amount, weighted_average_price) } @@ -2043,7 +1934,9 @@ impl Pallet { } pub fn try_plmc_participation_lock( - who: &T::AccountId, project_id: T::ProjectIdentifier, amount: BalanceOf, + who: &T::AccountId, + project_id: T::ProjectIdentifier, + amount: BalanceOf, ) -> Result<(), DispatchError> { // Check if the user has already locked tokens in the evaluation period let evaluation_bonded = ::NativeCurrency::balance_on_hold(&LockType::Evaluation(project_id), who); @@ -2067,7 +1960,10 @@ impl Pallet { // TODO(216): use the hold interface of the fungibles::MutateHold once its implemented on pallet_assets. pub fn try_funding_asset_hold( - who: &T::AccountId, project_id: T::ProjectIdentifier, amount: BalanceOf, asset_id: AssetIdOf, + who: &T::AccountId, + project_id: T::ProjectIdentifier, + amount: BalanceOf, + asset_id: AssetIdOf, ) -> Result<(), DispatchError> { let fund_account = Self::fund_account_id(project_id); @@ -2078,36 +1974,28 @@ impl Pallet { // TODO(216): use the hold interface of the fungibles::MutateHold once its implemented on pallet_assets. pub fn release_last_funding_item_in_vec( - who: &T::AccountId, project_id: T::ProjectIdentifier, asset_id: AssetIdOf, vec: &mut BoundedVec, - plmc_getter: impl Fn(&I) -> BalanceOf, funding_asset_getter: impl Fn(&I) -> BalanceOf, + who: &T::AccountId, + project_id: T::ProjectIdentifier, + asset_id: AssetIdOf, + vec: &mut BoundedVec, + plmc_getter: impl Fn(&I) -> BalanceOf, + funding_asset_getter: impl Fn(&I) -> BalanceOf, ) -> Result<(), DispatchError> { let fund_account = Self::fund_account_id(project_id); let last_item = vec.swap_remove(vec.len() - 1); let plmc_amount = plmc_getter(&last_item); let funding_asset_amount = funding_asset_getter(&last_item); - T::NativeCurrency::release( - &LockType::Participation(project_id), - &who, - plmc_amount, - Precision::Exact, - )?; + T::NativeCurrency::release(&LockType::Participation(project_id), &who, plmc_amount, Precision::Exact)?; - T::FundingCurrency::transfer( - asset_id, - &fund_account, - &who, - funding_asset_amount, - Preservation::Expendable, - )?; + T::FundingCurrency::transfer(asset_id, &fund_account, &who, funding_asset_amount, Preservation::Expendable)?; Ok(()) } pub fn calculate_fees(project_id: T::ProjectIdentifier) -> Result, DispatchError> { - let funding_reached = ProjectsDetails::::get(project_id) - .ok_or(Error::::ProjectNotFound)? - .funding_amount_reached; + let funding_reached = + ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?.funding_amount_reached; let mut remaining_for_fee = funding_reached; Ok(T::FeeBrackets::get() @@ -2180,12 +2068,7 @@ impl Pallet { pub fn get_evaluator_rewards_info( project_id: ::ProjectIdentifier, ) -> Result< - ( - ::Balance, - ::Balance, - ::Balance, - ::Balance, - ), + (::Balance, ::Balance, ::Balance, ::Balance), DispatchError, > { let project_details = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; @@ -2219,19 +2102,11 @@ impl Pallet { let early_evaluator_total_locked = evaluation_usd_amounts .iter() - .fold(BalanceOf::::zero(), |acc, (_, (early, _))| { - acc.saturating_add(*early) - }); - let late_evaluator_total_locked = evaluation_usd_amounts - .iter() - .fold(BalanceOf::::zero(), |acc, (_, (_, late))| acc.saturating_add(*late)); + .fold(BalanceOf::::zero(), |acc, (_, (early, _))| acc.saturating_add(*early)); + let late_evaluator_total_locked = + evaluation_usd_amounts.iter().fold(BalanceOf::::zero(), |acc, (_, (_, late))| acc.saturating_add(*late)); let all_evaluator_total_locked = early_evaluator_total_locked.saturating_add(late_evaluator_total_locked); - Ok(( - early_evaluator_rewards, - all_evaluator_rewards, - early_evaluator_total_locked, - all_evaluator_total_locked, - )) + Ok((early_evaluator_rewards, all_evaluator_rewards, early_evaluator_total_locked, all_evaluator_total_locked)) } pub fn generate_evaluators_outcome( diff --git a/polimec-skeleton/pallets/funding/src/impls.rs b/polimec-skeleton/pallets/funding/src/impls.rs index 4c67c102a..201b33d33 100644 --- a/polimec-skeleton/pallets/funding/src/impls.rs +++ b/polimec-skeleton/pallets/funding/src/impls.rs @@ -1,17 +1,16 @@ -use crate::traits::DoRemainingOperation; -use crate::*; -use frame_support::traits::Get; -use frame_support::weights::Weight; -use sp_runtime::traits::AccountIdConversion; -use sp_runtime::DispatchError; +use crate::{traits::DoRemainingOperation, *}; +use frame_support::{traits::Get, weights::Weight}; +use sp_runtime::{traits::AccountIdConversion, DispatchError}; use sp_std::prelude::*; impl DoRemainingOperation for ProjectFinalizer { fn is_done(&self) -> bool { matches!(self, ProjectFinalizer::None) } + fn do_one_operation( - &mut self, project_id: T::ProjectIdentifier, + &mut self, + project_id: T::ProjectIdentifier, ) -> Result { match self { ProjectFinalizer::None => Err(Error::::NoFinalizerSet.into()), @@ -21,14 +20,14 @@ impl DoRemainingOperation for ProjectFinalizer { *self = ProjectFinalizer::None; } Ok(weight) - } + }, ProjectFinalizer::Failure(ops) => { let weight = ops.do_one_operation::(project_id)?; if ops.is_done() { *self = ProjectFinalizer::None; } Ok(weight) - } + }, } } } @@ -44,8 +43,8 @@ impl DoRemainingOperation for SuccessFinalizer { *self = SuccessFinalizer::EvaluationRewardOrSlash(remaining_evaluators_to_reward_or_slash::(project_id)); Ok(Weight::zero()) - } - SuccessFinalizer::EvaluationRewardOrSlash(remaining) => { + }, + SuccessFinalizer::EvaluationRewardOrSlash(remaining) => if *remaining == 0 { *self = SuccessFinalizer::EvaluationUnbonding(remaining_evaluations::(project_id)); Ok(Weight::zero()) @@ -53,9 +52,8 @@ impl DoRemainingOperation for SuccessFinalizer { let (consumed_weight, remaining_evaluations) = reward_or_slash_one_evaluation::(project_id)?; *self = SuccessFinalizer::EvaluationRewardOrSlash(remaining_evaluations); Ok(consumed_weight) - } - } - SuccessFinalizer::EvaluationUnbonding(remaining) => { + }, + SuccessFinalizer::EvaluationUnbonding(remaining) => if *remaining == 0 { *self = SuccessFinalizer::BidPLMCVesting(remaining_bids_without_plmc_vesting::(project_id)); Ok(Weight::zero()) @@ -63,9 +61,8 @@ impl DoRemainingOperation for SuccessFinalizer { let (consumed_weight, remaining_evaluations) = unbond_one_evaluation::(project_id); *self = SuccessFinalizer::EvaluationUnbonding(remaining_evaluations); Ok(consumed_weight) - } - } - SuccessFinalizer::BidPLMCVesting(remaining) => { + }, + SuccessFinalizer::BidPLMCVesting(remaining) => if *remaining == 0 { *self = SuccessFinalizer::BidCTMint(remaining_bids_without_ct_minted::(project_id)); Ok(Weight::zero()) @@ -73,9 +70,8 @@ impl DoRemainingOperation for SuccessFinalizer { let (consumed_weight, remaining_bids) = start_bid_plmc_vesting_schedule::(project_id); *self = SuccessFinalizer::BidPLMCVesting(remaining_bids); Ok(consumed_weight) - } - } - SuccessFinalizer::BidCTMint(remaining) => { + }, + SuccessFinalizer::BidCTMint(remaining) => if *remaining == 0 { *self = SuccessFinalizer::ContributionPLMCVesting( remaining_contributions_without_plmc_vesting::(project_id), @@ -85,9 +81,8 @@ impl DoRemainingOperation for SuccessFinalizer { let (consumed_weight, remaining_bids) = mint_ct_for_one_bid::(project_id); *self = SuccessFinalizer::BidCTMint(remaining_bids); Ok(consumed_weight) - } - } - SuccessFinalizer::ContributionPLMCVesting(remaining) => { + }, + SuccessFinalizer::ContributionPLMCVesting(remaining) => if *remaining == 0 { *self = SuccessFinalizer::ContributionCTMint(remaining_contributions_without_ct_minted::( project_id, @@ -98,9 +93,8 @@ impl DoRemainingOperation for SuccessFinalizer { start_contribution_plmc_vesting_schedule::(project_id); *self = SuccessFinalizer::ContributionPLMCVesting(remaining_contributions); Ok(consumed_weight) - } - } - SuccessFinalizer::ContributionCTMint(remaining) => { + }, + SuccessFinalizer::ContributionCTMint(remaining) => if *remaining == 0 { *self = SuccessFinalizer::BidFundingPayout(remaining_bids_without_issuer_payout::(project_id)); Ok(Weight::zero()) @@ -108,9 +102,8 @@ impl DoRemainingOperation for SuccessFinalizer { let (consumed_weight, remaining_contributions) = mint_ct_for_one_contribution::(project_id); *self = SuccessFinalizer::ContributionCTMint(remaining_contributions); Ok(consumed_weight) - } - } - SuccessFinalizer::BidFundingPayout(remaining) => { + }, + SuccessFinalizer::BidFundingPayout(remaining) => if *remaining == 0 { *self = SuccessFinalizer::ContributionFundingPayout( remaining_contributions_without_issuer_payout::(project_id), @@ -120,9 +113,8 @@ impl DoRemainingOperation for SuccessFinalizer { let (consumed_weight, remaining_contributions) = issuer_funding_payout_one_bid::(project_id); *self = SuccessFinalizer::BidFundingPayout(remaining_contributions); Ok(consumed_weight) - } - } - SuccessFinalizer::ContributionFundingPayout(remaining) => { + }, + SuccessFinalizer::ContributionFundingPayout(remaining) => if *remaining == 0 { *self = SuccessFinalizer::Finished; Ok(Weight::zero()) @@ -131,8 +123,7 @@ impl DoRemainingOperation for SuccessFinalizer { issuer_funding_payout_one_contribution::(project_id); *self = SuccessFinalizer::ContributionFundingPayout(remaining_contributions); Ok(consumed_weight) - } - } + }, SuccessFinalizer::Finished => Err(Error::::FinalizerFinished.into()), } } @@ -142,15 +133,16 @@ impl DoRemainingOperation for FailureFinalizer { fn is_done(&self) -> bool { matches!(self, FailureFinalizer::Finished) } + fn do_one_operation(&mut self, project_id: T::ProjectIdentifier) -> Result { match self { FailureFinalizer::Initialized => { *self = FailureFinalizer::EvaluationRewardOrSlash(remaining_evaluators_to_reward_or_slash::(project_id)); Ok(Weight::zero()) - } + }, - FailureFinalizer::EvaluationRewardOrSlash(remaining) => { + FailureFinalizer::EvaluationRewardOrSlash(remaining) => if *remaining == 0 { *self = FailureFinalizer::EvaluationUnbonding(remaining_evaluations::(project_id)); Ok(Weight::zero()) @@ -158,10 +150,9 @@ impl DoRemainingOperation for FailureFinalizer { let (consumed_weight, remaining_evaluators) = reward_or_slash_one_evaluation::(project_id)?; *self = FailureFinalizer::EvaluationRewardOrSlash(remaining_evaluators); Ok(consumed_weight) - } - } + }, - FailureFinalizer::EvaluationUnbonding(remaining) => { + FailureFinalizer::EvaluationUnbonding(remaining) => if *remaining == 0 { *self = FailureFinalizer::BidFundingRelease(remaining_bids_to_release_funds::(project_id)); Ok(Weight::zero()) @@ -169,10 +160,9 @@ impl DoRemainingOperation for FailureFinalizer { let (consumed_weight, remaining_evaluators) = unbond_one_evaluation::(project_id); *self = FailureFinalizer::EvaluationUnbonding(remaining_evaluators); Ok(consumed_weight) - } - } + }, - FailureFinalizer::BidFundingRelease(remaining) => { + FailureFinalizer::BidFundingRelease(remaining) => if *remaining == 0 { *self = FailureFinalizer::BidUnbonding(remaining_bids::(project_id)); Ok(Weight::zero()) @@ -180,10 +170,9 @@ impl DoRemainingOperation for FailureFinalizer { let (consumed_weight, remaining_bids) = release_funds_one_bid::(project_id); *self = FailureFinalizer::BidFundingRelease(remaining_bids); Ok(consumed_weight) - } - } + }, - FailureFinalizer::BidUnbonding(remaining) => { + FailureFinalizer::BidUnbonding(remaining) => if *remaining == 0 { *self = FailureFinalizer::ContributionFundingRelease( remaining_contributions_to_release_funds::(project_id), @@ -193,10 +182,9 @@ impl DoRemainingOperation for FailureFinalizer { let (consumed_weight, remaining_bids) = unbond_one_bid::(project_id); *self = FailureFinalizer::BidUnbonding(remaining_bids); Ok(consumed_weight) - } - } + }, - FailureFinalizer::ContributionFundingRelease(remaining) => { + FailureFinalizer::ContributionFundingRelease(remaining) => if *remaining == 0 { *self = FailureFinalizer::ContributionUnbonding(remaining_contributions::(project_id)); Ok(Weight::zero()) @@ -204,10 +192,9 @@ impl DoRemainingOperation for FailureFinalizer { let (consumed_weight, remaining_contributions) = release_funds_one_contribution::(project_id); *self = FailureFinalizer::ContributionFundingRelease(remaining_contributions); Ok(consumed_weight) - } - } + }, - FailureFinalizer::ContributionUnbonding(remaining) => { + FailureFinalizer::ContributionUnbonding(remaining) => if *remaining == 0 { *self = FailureFinalizer::Finished; Ok(Weight::zero()) @@ -215,8 +202,7 @@ impl DoRemainingOperation for FailureFinalizer { let (consumed_weight, remaining_contributions) = unbond_one_contribution::(project_id); *self = FailureFinalizer::ContributionUnbonding(remaining_contributions); Ok(consumed_weight) - } - } + }, FailureFinalizer::Finished => Err(Error::::FinalizerFinished.into()), } @@ -240,10 +226,7 @@ fn remaining_evaluations(project_id: T::ProjectIdentifier) -> u64 { } fn remaining_bids_to_release_funds(project_id: T::ProjectIdentifier) -> u64 { - Bids::::iter_prefix_values(project_id) - .flatten() - .filter(|bid| !bid.funds_released) - .count() as u64 + Bids::::iter_prefix_values(project_id).flatten().filter(|bid| !bid.funds_released).count() as u64 } fn remaining_bids(project_id: T::ProjectIdentifier) -> u64 { @@ -284,27 +267,18 @@ fn remaining_contributions_without_ct_minted(_project_id: T::ProjectI } fn remaining_bids_without_issuer_payout(project_id: T::ProjectIdentifier) -> u64 { - Bids::::iter_prefix_values(project_id) - .flatten() - .filter(|bid| !bid.funds_released) - .count() as u64 + Bids::::iter_prefix_values(project_id).flatten().filter(|bid| !bid.funds_released).count() as u64 } fn remaining_contributions_without_issuer_payout(project_id: T::ProjectIdentifier) -> u64 { - Contributions::::iter_prefix_values(project_id) - .flatten() - .filter(|bid| !bid.funds_released) - .count() as u64 + Contributions::::iter_prefix_values(project_id).flatten().filter(|bid| !bid.funds_released).count() as u64 } fn reward_or_slash_one_evaluation(project_id: T::ProjectIdentifier) -> Result<(Weight, u64), DispatchError> { let project_details = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectNotFound)?; let project_evaluations: Vec<_> = Evaluations::::iter_prefix_values(project_id).collect(); - let remaining_evaluations = project_evaluations - .iter() - .flatten() - .filter(|evaluation| !evaluation.rewarded_or_slashed) - .count() as u64; + let remaining_evaluations = + project_evaluations.iter().flatten().filter(|evaluation| !evaluation.rewarded_or_slashed).count() as u64; let maybe_user_evaluations = project_evaluations .into_iter() @@ -332,7 +306,7 @@ fn reward_or_slash_one_evaluation(project_id: T::ProjectIdentifier) - error: e, }), }; - } + }, _ => (), } @@ -351,9 +325,8 @@ fn unbond_one_evaluation(project_id: T::ProjectIdentifier) -> let project_evaluations: Vec<_> = Evaluations::::iter_prefix_values(project_id).collect(); let evaluation_count = project_evaluations.iter().flatten().count() as u64; - let maybe_user_evaluations = project_evaluations - .into_iter() - .find(|evaluations| evaluations.iter().any(|e| e.rewarded_or_slashed)); + let maybe_user_evaluations = + project_evaluations.into_iter().find(|evaluations| evaluations.iter().any(|e| e.rewarded_or_slashed)); if let Some(mut user_evaluations) = maybe_user_evaluations { let evaluation = user_evaluations @@ -384,9 +357,7 @@ fn unbond_one_evaluation(project_id: T::ProjectIdentifier) -> fn release_funds_one_bid(project_id: T::ProjectIdentifier) -> (Weight, u64) { let project_bids: Vec<_> = Bids::::iter_prefix_values(project_id).collect(); let remaining_bids = project_bids.iter().flatten().filter(|bid| !bid.funds_released).count() as u64; - let maybe_user_bids = project_bids - .into_iter() - .find(|bids| bids.iter().any(|bid| !bid.funds_released)); + let maybe_user_bids = project_bids.into_iter().find(|bids| bids.iter().any(|bid| !bid.funds_released)); if let Some(mut user_bids) = maybe_user_bids { let mut bid = user_bids @@ -425,9 +396,7 @@ fn unbond_one_bid(project_id: T::ProjectIdentifier) -> (Weight, u64) // remove when do_bid_unbond_for is correctly implemented let bids_count = 0u64; - let maybe_user_bids = project_bids - .into_iter() - .find(|bids| bids.iter().any(|e| e.funds_released)); + let maybe_user_bids = project_bids.into_iter().find(|bids| bids.iter().any(|e| e.funds_released)); if let Some(mut user_bids) = maybe_user_bids { let bid = user_bids @@ -505,9 +474,8 @@ fn unbond_one_contribution(project_id: T::ProjectIdentifier) -> (Weig // let contributions_count = project_contributions.iter().flatten().count() as u64; let contributions_count = 0u64; - let maybe_user_contributions = project_contributions - .into_iter() - .find(|contributions| contributions.iter().any(|e| e.funds_released)); + let maybe_user_contributions = + project_contributions.into_iter().find(|contributions| contributions.iter().any(|e| e.funds_released)); if let Some(mut user_contributions) = maybe_user_contributions { let contribution = user_contributions @@ -565,9 +533,7 @@ fn issuer_funding_payout_one_bid(project_id: T::ProjectIdentifier) -> // .count() as u64; let remaining_bids = 0u64; - let maybe_user_bids = project_bids - .into_iter() - .find(|bids| bids.iter().any(|bid| !bid.funds_released)); + let maybe_user_bids = project_bids.into_iter().find(|bids| bids.iter().any(|bid| !bid.funds_released)); if let Some(mut user_bids) = maybe_user_bids { let mut bid = user_bids @@ -648,9 +614,7 @@ fn issuer_funding_payout_one_contribution(project_id: T::ProjectIdent // might come in handy later #[allow(unused)] fn unbond_evaluators(project_id: T::ProjectIdentifier, max_weight: Weight) -> (Weight, OperationsLeft) { - let evaluations = Evaluations::::iter_prefix_values(project_id) - .flatten() - .collect::>>(); + let evaluations = Evaluations::::iter_prefix_values(project_id).flatten().collect::>>(); let mut used_weight = Weight::zero(); @@ -675,10 +639,8 @@ fn unbond_evaluators(project_id: T::ProjectIdentifier, max_weight: We }) .collect::>(); - let successful_results = unbond_results - .into_iter() - .filter(|result| if let Err(e) = result { false } else { true }) - .collect::>(); + let successful_results = + unbond_results.into_iter().filter(|result| if let Err(e) = result { false } else { true }).collect::>(); let operations_left = if successful_results.len() == evaluations.len() { OperationsLeft::None diff --git a/polimec-skeleton/pallets/funding/src/lib.rs b/polimec-skeleton/pallets/funding/src/lib.rs index 8a9bafd41..f255d1fd3 100644 --- a/polimec-skeleton/pallets/funding/src/lib.rs +++ b/polimec-skeleton/pallets/funding/src/lib.rs @@ -177,9 +177,9 @@ // we add more without this limit. #![cfg_attr(feature = "runtime-benchmarks", recursion_limit = "512")] +pub mod functions; pub mod types; pub mod weights; -pub mod functions; #[cfg(test)] pub mod mock; @@ -210,7 +210,6 @@ use frame_support::{ use parity_scale_codec::{Decode, Encode}; use sp_arithmetic::traits::{One, Saturating}; - use sp_runtime::{traits::AccountIdConversion, FixedPointNumber, FixedPointOperand, FixedU128}; use sp_std::prelude::*; @@ -314,7 +313,7 @@ pub mod pallet { /// Something that provides the members of Polimec type HandleMembers: PolimecMembers>; - type Vesting: traits::ReleaseSchedule, BondTypeOf>; + type Vesting: polimec_traits::ReleaseSchedule, BondTypeOf>; /// The maximum length of data stored on-chain. #[pallet::constant] @@ -493,23 +492,13 @@ pub mod pallet { end_block: T::BlockNumber, }, /// The auction round of a project started. - EnglishAuctionStarted { - project_id: T::ProjectIdentifier, - when: T::BlockNumber, - }, + EnglishAuctionStarted { project_id: T::ProjectIdentifier, when: T::BlockNumber }, /// The candle auction part of the auction started for a project - CandleAuctionStarted { - project_id: T::ProjectIdentifier, - when: T::BlockNumber, - }, + CandleAuctionStarted { project_id: T::ProjectIdentifier, when: T::BlockNumber }, /// The auction round of a project ended. AuctionFailed { project_id: T::ProjectIdentifier }, /// A `bonder` bonded an `amount` of PLMC for `project_id`. - FundsBonded { - project_id: T::ProjectIdentifier, - amount: BalanceOf, - bonder: AccountIdOf, - }, + FundsBonded { project_id: T::ProjectIdentifier, amount: BalanceOf, bonder: AccountIdOf }, /// Someone paid for the release of a user's PLMC bond for a project. BondReleased { project_id: T::ProjectIdentifier, @@ -518,12 +507,7 @@ pub mod pallet { releaser: AccountIdOf, }, /// A bid was made for a project - Bid { - project_id: T::ProjectIdentifier, - amount: BalanceOf, - price: T::Price, - multiplier: MultiplierOf, - }, + Bid { project_id: T::ProjectIdentifier, amount: BalanceOf, price: T::Price, multiplier: MultiplierOf }, /// A contribution was made for a project. i.e token purchase Contribution { project_id: T::ProjectIdentifier, @@ -536,15 +520,9 @@ pub mod pallet { /// A project is now in the remainder funding round RemainderFundingStarted { project_id: T::ProjectIdentifier }, /// A project has now finished funding - FundingEnded { - project_id: T::ProjectIdentifier, - outcome: FundingOutcome, - }, + FundingEnded { project_id: T::ProjectIdentifier, outcome: FundingOutcome }, /// Something was not properly initialized. Most likely due to dev error manually calling do_* functions or updating storage - TransitionError { - project_id: T::ProjectIdentifier, - error: DispatchError, - }, + TransitionError { project_id: T::ProjectIdentifier, error: DispatchError }, /// Something terribly wrong happened where the bond could not be unbonded. Most likely a programming error EvaluationUnbondFailed { project_id: ProjectIdOf, @@ -751,7 +729,9 @@ pub mod pallet { /// Change the metadata hash of a project #[pallet::weight(T::WeightInfo::edit_metadata())] pub fn edit_metadata( - origin: OriginFor, project_id: T::ProjectIdentifier, project_metadata_hash: T::Hash, + origin: OriginFor, + project_id: T::ProjectIdentifier, + project_metadata_hash: T::Hash, ) -> DispatchResult { let issuer = ensure_signed(origin)?; @@ -790,7 +770,9 @@ pub mod pallet { /// Bond PLMC for a project in the evaluation stage #[pallet::weight(T::WeightInfo::bond())] pub fn bond_evaluation( - origin: OriginFor, project_id: T::ProjectIdentifier, #[pallet::compact] usd_amount: BalanceOf, + origin: OriginFor, + project_id: T::ProjectIdentifier, + #[pallet::compact] usd_amount: BalanceOf, ) -> DispatchResult { let evaluator = ensure_signed(origin)?; Self::do_evaluate(evaluator, project_id, usd_amount) @@ -799,7 +781,9 @@ pub mod pallet { /// Release evaluation-bonded PLMC when a project finishes its funding round. #[pallet::weight(T::WeightInfo::evaluation_unbond_for())] pub fn evaluation_unbond_for( - origin: OriginFor, bond_id: T::StorageItemId, project_id: T::ProjectIdentifier, + origin: OriginFor, + bond_id: T::StorageItemId, + project_id: T::ProjectIdentifier, evaluator: AccountIdOf, ) -> DispatchResult { let releaser = ensure_signed(origin)?; @@ -809,8 +793,12 @@ pub mod pallet { /// Bid for a project in the Auction round #[pallet::weight(T::WeightInfo::bid())] pub fn bid( - origin: OriginFor, project_id: T::ProjectIdentifier, #[pallet::compact] amount: BalanceOf, - price: PriceOf, multiplier: Option, asset: AcceptedFundingAsset, + origin: OriginFor, + project_id: T::ProjectIdentifier, + #[pallet::compact] amount: BalanceOf, + price: PriceOf, + multiplier: Option, + asset: AcceptedFundingAsset, ) -> DispatchResult { let bidder = ensure_signed(origin)?; @@ -825,8 +813,11 @@ pub mod pallet { /// Buy tokens in the Community or Remainder round at the price set in the Auction Round #[pallet::weight(T::WeightInfo::contribute())] pub fn contribute( - origin: OriginFor, project_id: T::ProjectIdentifier, #[pallet::compact] amount: BalanceOf, - multiplier: Option>, asset: AcceptedFundingAsset, + origin: OriginFor, + project_id: T::ProjectIdentifier, + #[pallet::compact] amount: BalanceOf, + multiplier: Option>, + asset: AcceptedFundingAsset, ) -> DispatchResult { let contributor = ensure_signed(origin)?; @@ -835,7 +826,9 @@ pub mod pallet { /// Unbond some plmc from a contribution, after a step in the vesting period has passed. pub fn vested_plmc_bid_unbond_for( - origin: OriginFor, project_id: T::ProjectIdentifier, bidder: AccountIdOf, + origin: OriginFor, + project_id: T::ProjectIdentifier, + bidder: AccountIdOf, ) -> DispatchResult { // TODO: PLMC-157. Manage the fact that the CTs may not be claimed by those entitled let releaser = ensure_signed(origin)?; @@ -846,7 +839,9 @@ pub mod pallet { // TODO: PLMC-157. Manage the fact that the CTs may not be claimed by those entitled /// Mint contribution tokens after a step in the vesting period for a successful bid. pub fn vested_contribution_token_bid_mint_for( - origin: OriginFor, project_id: T::ProjectIdentifier, bidder: AccountIdOf, + origin: OriginFor, + project_id: T::ProjectIdentifier, + bidder: AccountIdOf, ) -> DispatchResult { let releaser = ensure_signed(origin)?; @@ -856,7 +851,9 @@ pub mod pallet { // TODO: PLMC-157. Manage the fact that the CTs may not be claimed by those entitled /// Unbond some plmc from a contribution, after a step in the vesting period has passed. pub fn vested_plmc_purchase_unbond_for( - origin: OriginFor, project_id: T::ProjectIdentifier, purchaser: AccountIdOf, + origin: OriginFor, + project_id: T::ProjectIdentifier, + purchaser: AccountIdOf, ) -> DispatchResult { let releaser = ensure_signed(origin)?; @@ -866,7 +863,9 @@ pub mod pallet { // TODO: PLMC-157. Manage the fact that the CTs may not be claimed by those entitled /// Mint contribution tokens after a step in the vesting period for a contribution. pub fn vested_contribution_token_purchase_mint_for( - origin: OriginFor, project_id: T::ProjectIdentifier, purchaser: AccountIdOf, + origin: OriginFor, + project_id: T::ProjectIdentifier, + purchaser: AccountIdOf, ) -> DispatchResult { let releaser = ensure_signed(origin)?; @@ -883,7 +882,7 @@ pub mod pallet { // EvaluationRound -> AuctionInitializePeriod | EvaluationFailed UpdateType::EvaluationEnd => { unwrap_result_or_skip!(Self::do_evaluation_end(project_id), project_id); - } + }, // AuctionInitializePeriod -> AuctionRound(AuctionPhase::English) // Only if it wasn't first handled by user extrinsic @@ -892,27 +891,27 @@ pub mod pallet { Self::do_english_auction(T::PalletId::get().into_account_truncating(), project_id), project_id ); - } + }, // AuctionRound(AuctionPhase::English) -> AuctionRound(AuctionPhase::Candle) UpdateType::CandleAuctionStart => { unwrap_result_or_skip!(Self::do_candle_auction(project_id), project_id); - } + }, // AuctionRound(AuctionPhase::Candle) -> CommunityRound UpdateType::CommunityFundingStart => { unwrap_result_or_skip!(Self::do_community_funding(project_id), project_id); - } + }, // CommunityRound -> RemainderRound UpdateType::RemainderFundingStart => { unwrap_result_or_skip!(Self::do_remainder_funding(project_id), project_id) - } + }, // CommunityRound || RemainderRound -> FundingEnded UpdateType::FundingEnd => { unwrap_result_or_skip!(Self::do_end_funding(project_id), project_id) - } + }, } } // TODO: PLMC-127. Set a proper weight @@ -924,16 +923,15 @@ pub mod pallet { let projects_needing_cleanup = ProjectsDetails::::iter() .filter_map(|(project_id, info)| match info.cleanup { - ProjectCleanup::Ready(project_finalizer) if project_finalizer != ProjectFinalizer::None => { - Some((project_id, project_finalizer)) - } + ProjectCleanup::Ready(project_finalizer) if project_finalizer != ProjectFinalizer::None => + Some((project_id, project_finalizer)), _ => None, }) .collect::>(); let projects_amount = projects_needing_cleanup.len() as u64; if projects_amount == 0 { - return max_weight; + return max_weight } let mut max_weight_per_project = remaining_weight.saturating_div(projects_amount); @@ -946,14 +944,10 @@ pub mod pallet { if let Ok(weight) = project_finalizer.do_one_operation::(project_id) { consumed_weight.saturating_accrue(weight); } else { - break; + break } } - let mut details = if let Some(d) = ProjectsDetails::::get(project_id) { - d - } else { - continue; - }; + let mut details = if let Some(d) = ProjectsDetails::::get(project_id) { d } else { continue }; if let ProjectFinalizer::None = project_finalizer { details.cleanup = ProjectCleanup::Finished; } else { @@ -982,18 +976,13 @@ pub mod pallet { fn create_project_id_parameter(id: u32) -> T::ProjectIdentifier { id.into() } + fn create_dummy_project(metadata_hash: T::Hash) -> ProjectMetadataOf { let project: ProjectMetadataOf = ProjectMetadata { total_allocation_size: 1_000_000_0_000_000_000u64.into(), minimum_price: PriceOf::::saturating_from_integer(1), - ticket_size: TicketSize { - minimum: Some(1u8.into()), - maximum: None, - }, - participants_size: ParticipantsSize { - minimum: Some(2), - maximum: None, - }, + ticket_size: TicketSize { minimum: Some(1u8.into()), maximum: None }, + participants_size: ParticipantsSize { minimum: Some(2), maximum: None }, offchain_information_hash: Some(metadata_hash), ..Default::default() }; @@ -1015,8 +1004,8 @@ pub mod local_macros { project_id: $project_id, error: Error::::FieldIsNone.into(), }); - continue; - } + continue + }, } }; } @@ -1028,12 +1017,9 @@ pub mod local_macros { match $option { Ok(val) => val, Err(err) => { - Self::deposit_event(Event::::TransitionError { - project_id: $project_id, - error: err, - }); - continue; - } + Self::deposit_event(Event::::TransitionError { project_id: $project_id, error: err }); + continue + }, } }; } diff --git a/polimec-skeleton/pallets/funding/src/mock.rs b/polimec-skeleton/pallets/funding/src/mock.rs index 904a64d01..542bf5e28 100644 --- a/polimec-skeleton/pallets/funding/src/mock.rs +++ b/polimec-skeleton/pallets/funding/src/mock.rs @@ -33,7 +33,7 @@ use sp_arithmetic::Percent; use sp_core::H256; use sp_runtime::{ testing::Header, - traits::{BlakeTwo256, IdentityLookup, ConvertInto}, + traits::{BlakeTwo256, ConvertInto, IdentityLookup}, BuildStorage, }; use system::EnsureSigned; @@ -94,111 +94,111 @@ parameter_types! { } impl pallet_assets::Config for TestRuntime { - type RuntimeEvent = RuntimeEvent; - type Balance = Balance; - type RemoveItemsLimit = ConstU32<1000>; + type ApprovalDeposit = ApprovalDeposit; + type AssetAccountDeposit = AssetAccountDeposit; + type AssetDeposit = AssetDeposit; type AssetId = AssetId; type AssetIdParameter = parity_scale_codec::Compact; - type Currency = Balances; + type Balance = Balance; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); + type CallbackHandle = (); type CreateOrigin = AsEnsureOriginWithArg>; + type Currency = Balances; + type Extra = (); type ForceOrigin = EnsureRoot; - type AssetDeposit = AssetDeposit; - type AssetAccountDeposit = AssetAccountDeposit; + type Freezer = (); type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type ApprovalDeposit = ApprovalDeposit; + type RemoveItemsLimit = ConstU32<1000>; + type RuntimeEvent = RuntimeEvent; type StringLimit = AssetsStringLimit; - type Freezer = (); - type Extra = (); - type CallbackHandle = (); type WeightInfo = (); - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); } impl pallet_assets::Config for TestRuntime { - type RuntimeEvent = RuntimeEvent; - type Balance = Balance; - type RemoveItemsLimit = ConstU32<1000>; + type ApprovalDeposit = ApprovalDeposit; + type AssetAccountDeposit = AssetAccountDeposit; + type AssetDeposit = AssetDeposit; type AssetId = AssetId; type AssetIdParameter = parity_scale_codec::Compact; - type Currency = Balances; + type Balance = Balance; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); + type CallbackHandle = (); type CreateOrigin = AsEnsureOriginWithArg>; + type Currency = Balances; + type Extra = (); type ForceOrigin = EnsureRoot; - type AssetDeposit = AssetDeposit; - type AssetAccountDeposit = AssetAccountDeposit; + type Freezer = (); type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type ApprovalDeposit = ApprovalDeposit; + type RemoveItemsLimit = ConstU32<1000>; + type RuntimeEvent = RuntimeEvent; type StringLimit = AssetsStringLimit; - type Freezer = (); - type Extra = (); - type CallbackHandle = (); type WeightInfo = (); - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); } parameter_types! { pub const BlockHashCount: u32 = 250; } impl system::Config for TestRuntime { + type AccountData = pallet_balances::AccountData; + type AccountId = AccountId; type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); + type BlockHashCount = BlockHashCount; type BlockLength = (); - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Index = u64; type BlockNumber = BlockNumber; + type BlockWeights = (); + type DbWeight = (); type Hash = H256; type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; type Header = Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = BlockHashCount; - type DbWeight = (); - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); + type Index = u64; + type Lookup = IdentityLookup; + type MaxConsumers = frame_support::traits::ConstU32<16>; type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = ConstU16<42>; + type OnNewAccount = (); type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; + type PalletInfo = PalletInfo; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type SS58Prefix = ConstU16<42>; + type SystemWeightInfo = (); + type Version = (); } parameter_types! { pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT; } impl pallet_balances::Config for TestRuntime { - type RuntimeEvent = RuntimeEvent; - type WeightInfo = (); + type AccountStore = System; type Balance = Balance; type DustRemoval = (); type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type ReserveIdentifier = LockType; - type HoldIdentifier = LockType; type FreezeIdentifier = (); + type HoldIdentifier = LockType; + type MaxFreezes = (); + type MaxHolds = ConstU32<1024>; type MaxLocks = frame_support::traits::ConstU32<1024>; type MaxReserves = frame_support::traits::ConstU32<1024>; - type MaxHolds = ConstU32<1024>; - type MaxFreezes = (); + type ReserveIdentifier = LockType; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); } impl pallet_insecure_randomness_collective_flip::Config for TestRuntime {} impl pallet_credentials::Config for TestRuntime { - type RuntimeEvent = RuntimeEvent; type AddOrigin = EnsureSigned; + type MembershipChanged = (); + type MembershipInitialized = (); + type PrimeOrigin = EnsureSigned; type RemoveOrigin = EnsureSigned; - type SwapOrigin = EnsureSigned; type ResetOrigin = EnsureSigned; - type PrimeOrigin = EnsureSigned; - type MembershipInitialized = (); - type MembershipChanged = (); + type RuntimeEvent = RuntimeEvent; + type SwapOrigin = EnsureSigned; } pub const HOURS: BlockNumber = 300u64; @@ -237,55 +237,54 @@ impl pallet_linear_release::Config for TestRuntime { type BlockNumberToBalance = ConvertInto; type Currency = Balances; type MinVestedTransfer = MinVestedTransfer; + type Reason = LockType; type RuntimeEvent = RuntimeEvent; type UnvestedFundsAllowedWithdrawReasons = UnvestedFundsAllowedWithdrawReasons; type WeightInfo = (); - type Reason = LockType; + const MAX_VESTING_SCHEDULES: u32 = 3; } impl pallet_funding::Config for TestRuntime { - type RuntimeEvent = RuntimeEvent; - type ProjectIdentifier = Identifier; - type Multiplier = Multiplier; - type Balance = Balance; - type Price = FixedU128; - type NativeCurrency = Balances; - type FundingCurrency = StatemintAssets; - type ContributionTokenCurrency = LocalAssets; - type PriceProvider = ConstPriceProvider; - type StorageItemId = u128; - type Randomness = RandomnessCollectiveFlip; - type HandleMembers = Credentials; - type StringLimit = ConstU32<64>; - type PreImageLimit = ConstU32<1024>; - type EvaluationDuration = EvaluationDuration; type AuctionInitializePeriodDuration = AuctionInitializePeriodDuration; - type EnglishAuctionDuration = EnglishAuctionDuration; + type Balance = Balance; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); type CandleAuctionDuration = CandleAuctionDuration; type CommunityFundingDuration = CommunityRoundDuration; - type RemainderFundingDuration = RemainderFundingDuration; - type PalletId = FundingPalletId; - type MaxProjectsToUpdatePerBlock = ConstU32<100>; - type MaxEvaluationsPerUser = ConstU32<4>; + type ContributionTokenCurrency = LocalAssets; + type ContributionVesting = ConstU32<4>; + type EnglishAuctionDuration = EnglishAuctionDuration; + type EvaluationDuration = EvaluationDuration; + type EvaluationSuccessThreshold = EarlyEvaluationThreshold; + type FeeBrackets = FeeBrackets; + type FundingCurrency = StatemintAssets; + type HandleMembers = Credentials; // Low value to simplify the tests type MaxBidsPerUser = ConstU32<4>; type MaxContributionsPerUser = ConstU32<4>; - type ContributionVesting = ConstU32<4>; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); - type WeightInfo = (); - type FeeBrackets = FeeBrackets; - type EvaluationSuccessThreshold = EarlyEvaluationThreshold; + type MaxEvaluationsPerUser = ConstU32<4>; + type MaxProjectsToUpdatePerBlock = ConstU32<100>; + type Multiplier = Multiplier; + type NativeCurrency = Balances; + type PalletId = FundingPalletId; + type PreImageLimit = ConstU32<1024>; + type Price = FixedU128; + type PriceProvider = ConstPriceProvider; + type ProjectIdentifier = Identifier; + type Randomness = RandomnessCollectiveFlip; + type RemainderFundingDuration = RemainderFundingDuration; + type RuntimeEvent = RuntimeEvent; + type StorageItemId = u128; + type StringLimit = ConstU32<64>; type Vesting = Vesting; + type WeightInfo = (); } // Build genesis storage according to the mock runtime. // TODO: PLMC-161. Add some mocks projects at Genesis to simplify the tests pub fn new_test_ext() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); GenesisConfig { balances: BalancesConfig { diff --git a/polimec-skeleton/pallets/funding/src/tests.rs b/polimec-skeleton/pallets/funding/src/tests.rs index af7158243..de2e8a752 100644 --- a/polimec-skeleton/pallets/funding/src/tests.rs +++ b/polimec-skeleton/pallets/funding/src/tests.rs @@ -41,17 +41,13 @@ use helper_functions::*; use crate::traits::BondingRequirementCalculation; use sp_arithmetic::traits::Zero; use sp_runtime::DispatchError; -use std::cell::RefCell; -use std::iter::zip; +use std::{cell::RefCell, iter::zip}; type ProjectIdOf = ::ProjectIdentifier; type UserToPLMCBalance = Vec<(AccountId, BalanceOf)>; type UserToUSDBalance = Vec<(AccountId, BalanceOf)>; -type UserToStatemintAsset = Vec<( - AccountId, - BalanceOf, - >::AssetId, -)>; +type UserToStatemintAsset = + Vec<(AccountId, BalanceOf, >::AssetId)>; #[derive(Clone, Copy)] pub struct TestBid { @@ -63,16 +59,13 @@ pub struct TestBid { } impl TestBid { fn new( - bidder: AccountId, amount: BalanceOf, price: PriceOf, - multiplier: Option>, asset: AcceptedFundingAsset, + bidder: AccountId, + amount: BalanceOf, + price: PriceOf, + multiplier: Option>, + asset: AcceptedFundingAsset, ) -> Self { - Self { - bidder, - amount, - price, - multiplier, - asset, - } + Self { bidder, amount, price, multiplier, asset } } } pub type TestBids = Vec; @@ -86,15 +79,12 @@ pub struct TestContribution { } impl TestContribution { fn new( - contributor: AccountId, amount: BalanceOf, multiplier: Option>, + contributor: AccountId, + amount: BalanceOf, + multiplier: Option>, asset: AcceptedFundingAsset, ) -> Self { - Self { - contributor, - amount, - multiplier, - asset, - } + Self { contributor, amount, multiplier, asset } } } pub type TestContributions = Vec; @@ -166,60 +156,60 @@ impl Default for BidInfoFilterOf { impl BidInfoFilterOf { fn matches_bid(&self, bid: &BidInfoOf) -> bool { if self.id.is_some() && self.id.unwrap() != bid.id { - return false; + return false } if self.project_id.is_some() && self.project_id.unwrap() != bid.project_id { - return false; + return false } if self.bidder.is_some() && self.bidder.unwrap() != bid.bidder { - return false; + return false } if self.status.is_some() && self.status.as_ref().unwrap() != &bid.status { - return false; + return false } if self.original_ct_amount.is_some() && self.original_ct_amount.unwrap() != bid.original_ct_amount { - return false; + return false } if self.original_ct_usd_price.is_some() && self.original_ct_usd_price.unwrap() != bid.original_ct_usd_price { - return false; + return false } if self.final_ct_amount.is_some() && self.final_ct_amount.unwrap() != bid.final_ct_amount { - return false; + return false } if self.final_ct_usd_price.is_some() && self.final_ct_usd_price.unwrap() != bid.final_ct_usd_price { - return false; + return false } if self.funding_asset.is_some() && self.funding_asset.unwrap() != bid.funding_asset { - return false; + return false } - if self.funding_asset_amount_locked.is_some() - && self.funding_asset_amount_locked.unwrap() != bid.funding_asset_amount_locked + if self.funding_asset_amount_locked.is_some() && + self.funding_asset_amount_locked.unwrap() != bid.funding_asset_amount_locked { - return false; + return false } if self.multiplier.is_some() && self.multiplier.unwrap() != bid.multiplier { - return false; + return false } if self.plmc_bond.is_some() && self.plmc_bond.unwrap() != bid.plmc_bond { - return false; + return false } if self.funded.is_some() && self.funded.unwrap() != bid.funded { - return false; + return false } if self.plmc_vesting_period.is_some() && self.plmc_vesting_period.unwrap() != bid.plmc_vesting_period { - return false; + return false } if self.ct_vesting_period.is_some() && self.ct_vesting_period.unwrap() != bid.ct_vesting_period { - return false; + return false } if self.when.is_some() && self.when.unwrap() != bid.when { - return false; + return false } if self.funds_released.is_some() && self.funds_released.unwrap() != bid.funds_released { - return false; + return false } - return true; + return true } } @@ -306,23 +296,22 @@ pub struct TestEnvironment { } impl TestEnvironment { pub fn new() -> Self { - Self { - ext_env: RefCell::new(new_test_ext()), - nonce: RefCell::new(0u64), - } + Self { ext_env: RefCell::new(new_test_ext()), nonce: RefCell::new(0u64) } } + fn get_new_nonce(&self) -> u64 { let nonce = self.nonce.borrow_mut().clone(); self.nonce.replace(nonce + 1); nonce } + fn create_project( - &self, issuer: AccountId, project: ProjectMetadataOf, + &self, + issuer: AccountId, + project: ProjectMetadataOf, ) -> Result { // Create project in the externalities environment of this struct instance - self.ext_env - .borrow_mut() - .execute_with(|| FundingModule::create(RuntimeOrigin::signed(issuer), project))?; + self.ext_env.borrow_mut().execute_with(|| FundingModule::create(RuntimeOrigin::signed(issuer), project))?; // Retrieve the project_id from the events let project_id = self.ext_env.borrow_mut().execute_with(|| { @@ -337,12 +326,9 @@ impl TestEnvironment { .clone() }); - Ok(CreatedProject { - test_env: self, - issuer, - project_id, - }) + Ok(CreatedProject { test_env: self, issuer, project_id }) } + fn in_ext(&self, execute: impl FnOnce() -> R) -> R { self.ext_env.borrow_mut().execute_with(execute) } @@ -360,6 +346,7 @@ impl TestEnvironment { balances }) } + #[allow(dead_code)] fn get_all_reserved_plmc_balances(&self, reserve_type: LockType>) -> UserToPLMCBalance { self.ext_env.borrow_mut().execute_with(|| { @@ -372,6 +359,7 @@ impl TestEnvironment { fundings }) } + #[allow(dead_code)] fn get_all_free_statemint_asset_balances(&self, asset_id: AssetId) -> UserToStatemintAsset { self.ext_env.borrow_mut().execute_with(|| { @@ -397,8 +385,11 @@ impl TestEnvironment { balances }) } + fn get_reserved_plmc_balances_for( - &self, user_keys: Vec, lock_type: LockType>, + &self, + user_keys: Vec, + lock_type: LockType>, ) -> UserToPLMCBalance { self.ext_env.borrow_mut().execute_with(|| { let mut balances = UserToPLMCBalance::new(); @@ -410,8 +401,11 @@ impl TestEnvironment { balances }) } + fn get_free_statemint_asset_balances_for( - &self, asset_id: AssetId, user_keys: Vec, + &self, + asset_id: AssetId, + user_keys: Vec, ) -> UserToStatemintAsset { self.ext_env.borrow_mut().execute_with(|| { let mut balances = UserToStatemintAsset::new(); @@ -423,13 +417,17 @@ impl TestEnvironment { balances }) } + fn get_plmc_total_supply(&self) -> BalanceOf { self.ext_env .borrow_mut() .execute_with(|| ::NativeCurrency::total_issuance()) } + fn do_reserved_plmc_assertions( - &self, correct_funds: UserToPLMCBalance, reserve_type: LockType>, + &self, + correct_funds: UserToPLMCBalance, + reserve_type: LockType>, ) { for (user, balance) in correct_funds { self.ext_env.borrow_mut().execute_with(|| { @@ -446,6 +444,7 @@ impl TestEnvironment { } }); } + fn mint_statemint_asset_to(&self, mapping: UserToStatemintAsset) { self.ext_env.borrow_mut().execute_with(|| { for (account, amount, id) in mapping { @@ -453,9 +452,11 @@ impl TestEnvironment { } }); } + fn current_block(&self) -> BlockNumber { self.ext_env.borrow_mut().execute_with(|| System::block_number()) } + fn advance_time(&self, amount: BlockNumber) -> Result<(), DispatchError> { self.ext_env.borrow_mut().execute_with(|| { for _block in 0..amount { @@ -472,6 +473,7 @@ impl TestEnvironment { Ok(()) }) } + fn do_free_plmc_assertions(&self, correct_funds: UserToPLMCBalance) { for (user, balance) in correct_funds { self.ext_env.borrow_mut().execute_with(|| { @@ -490,16 +492,15 @@ impl TestEnvironment { for (user, expected_amount, token_id) in correct_funds { self.ext_env.borrow_mut().execute_with(|| { let real_amount = ::FundingCurrency::balance(token_id, &user); - assert_eq!( - expected_amount, real_amount, - "Wrong statemint asset balance expected for user {}", - user - ); + assert_eq!(expected_amount, real_amount, "Wrong statemint asset balance expected for user {}", user); }); } } + fn do_bid_transferred_statemint_asset_assertions( - &self, correct_funds: UserToStatemintAsset, project_id: ProjectIdOf, + &self, + correct_funds: UserToStatemintAsset, + project_id: ProjectIdOf, ) { for (user, expected_amount, _token_id) in correct_funds { self.ext_env.borrow_mut().execute_with(|| { @@ -520,7 +521,9 @@ impl TestEnvironment { // Check if a Contribution storage item exists for the given funding asset transfer fn do_contribution_transferred_statemint_asset_assertions( - &self, correct_funds: UserToStatemintAsset, project_id: ProjectIdOf, + &self, + correct_funds: UserToStatemintAsset, + project_id: ProjectIdOf, ) { for (user, expected_amount, _token_id) in correct_funds { self.ext_env.borrow_mut().execute_with(|| { @@ -543,16 +546,19 @@ impl<'a> ProjectInstance for CreatedProject<'a> { fn get_test_environment(&self) -> &TestEnvironment { self.test_env } + fn get_issuer(&self) -> AccountId { self.issuer.clone() } + fn get_project_id(&self) -> ProjectIdOf { self.project_id.clone() } } impl<'a> CreatedProject<'a> { fn new_with( - test_env: &'a TestEnvironment, project_metadata: ProjectMetadataOf, + test_env: &'a TestEnvironment, + project_metadata: ProjectMetadataOf, issuer: ::AccountId, ) -> Self { let now = test_env.current_block(); @@ -563,7 +569,9 @@ impl<'a> CreatedProject<'a> { } fn creation_assertions( - &self, expected_metadata: ProjectMetadataOf, creation_start_block: BlockNumberOf, + &self, + expected_metadata: ProjectMetadataOf, + creation_start_block: BlockNumberOf, ) { let metadata = self.get_project_metadata(); let details = self.get_project_details(); @@ -573,10 +581,7 @@ impl<'a> CreatedProject<'a> { weighted_average_price: None, status: ProjectStatus::Application, phase_transition_points: PhaseTransitionPoints { - application: BlockNumberPair { - start: Some(creation_start_block), - end: None, - }, + application: BlockNumberPair { start: Some(creation_start_block), end: None }, ..Default::default() }, fundraising_target: expected_metadata @@ -602,11 +607,7 @@ impl<'a> CreatedProject<'a> { self.in_ext(|| FundingModule::start_evaluation(RuntimeOrigin::signed(caller), self.project_id))?; assert_eq!(self.get_project_details().status, ProjectStatus::EvaluationRound); - Ok(EvaluatingProject { - test_env: self.test_env, - issuer: self.issuer, - project_id: self.project_id, - }) + Ok(EvaluatingProject { test_env: self.test_env, issuer: self.issuer, project_id: self.project_id }) } } @@ -620,16 +621,19 @@ impl<'a> ProjectInstance for EvaluatingProject<'a> { fn get_test_environment(&self) -> &TestEnvironment { self.test_env } + fn get_issuer(&self) -> AccountId { self.issuer.clone() } + fn get_project_id(&self) -> ProjectIdOf { self.project_id.clone() } } impl<'a> EvaluatingProject<'a> { fn new_with( - test_env: &'a TestEnvironment, project_metadata: ProjectMetadataOf, + test_env: &'a TestEnvironment, + project_metadata: ProjectMetadataOf, issuer: ::AccountId, ) -> Self { let created_project = CreatedProject::new_with(test_env, project_metadata.clone(), issuer); @@ -641,17 +645,17 @@ impl<'a> EvaluatingProject<'a> { } pub fn evaluation_assertions( - &self, expected_free_plmc_balances: UserToPLMCBalance, expected_reserved_plmc_balances: UserToPLMCBalance, + &self, + expected_free_plmc_balances: UserToPLMCBalance, + expected_reserved_plmc_balances: UserToPLMCBalance, total_plmc_supply: BalanceOf, ) { let project_details = self.get_project_details(); let test_env = self.test_env; assert_eq!(project_details.status, ProjectStatus::EvaluationRound); test_env.do_free_plmc_assertions(expected_free_plmc_balances); - test_env.do_reserved_plmc_assertions( - expected_reserved_plmc_balances, - LockType::Evaluation(self.get_project_id()), - ); + test_env + .do_reserved_plmc_assertions(expected_reserved_plmc_balances, LockType::Evaluation(self.get_project_id())); test_env.do_total_plmc_assertions(total_plmc_supply); } @@ -676,23 +680,13 @@ impl<'a> EvaluatingProject<'a> { self.test_env.advance_time(blocks_to_start).unwrap(); }; - assert_eq!( - self.get_project_details().status, - ProjectStatus::AuctionInitializePeriod - ); + assert_eq!(self.get_project_details().status, ProjectStatus::AuctionInitializePeriod); self.in_ext(|| FundingModule::start_auction(RuntimeOrigin::signed(caller), self.get_project_id()))?; - assert_eq!( - self.get_project_details().status, - ProjectStatus::AuctionRound(AuctionPhase::English) - ); + assert_eq!(self.get_project_details().status, ProjectStatus::AuctionRound(AuctionPhase::English)); - Ok(AuctioningProject { - test_env: self.test_env, - issuer: self.issuer, - project_id: self.project_id, - }) + Ok(AuctioningProject { test_env: self.test_env, issuer: self.issuer, project_id: self.project_id }) } } @@ -706,32 +700,31 @@ impl<'a> ProjectInstance for AuctioningProject<'a> { fn get_test_environment(&self) -> &TestEnvironment { self.test_env } + fn get_issuer(&self) -> AccountId { self.issuer.clone() } + fn get_project_id(&self) -> ProjectIdOf { self.project_id.clone() } } impl<'a> AuctioningProject<'a> { fn new_with( - test_env: &'a TestEnvironment, project_metadata: ProjectMetadataOf, - issuer: ::AccountId, evaluations: UserToUSDBalance, + test_env: &'a TestEnvironment, + project_metadata: ProjectMetadataOf, + issuer: ::AccountId, + evaluations: UserToUSDBalance, ) -> Self { let evaluating_project = EvaluatingProject::new_with(test_env, project_metadata, issuer); - let evaluators = evaluations - .iter() - .map(|(acc, _val)| acc.clone()) - .collect::>>(); + let evaluators = evaluations.iter().map(|(acc, _val)| acc.clone()).collect::>>(); let prev_supply = test_env.get_plmc_total_supply(); let prev_plmc_balances = test_env.get_free_plmc_balances_for(evaluators); let plmc_eval_deposits: UserToPLMCBalance = calculate_evaluation_plmc_spent(evaluations.clone()); - let plmc_existential_deposits: UserToPLMCBalance = evaluations - .iter() - .map(|(account, _amount)| (account.clone(), get_ed())) - .collect::<_>(); + let plmc_existential_deposits: UserToPLMCBalance = + evaluations.iter().map(|(account, _amount)| (account.clone(), get_ed())).collect::<_>(); let expected_remaining_plmc: UserToPLMCBalance = merge_add_mappings_by_user(vec![prev_plmc_balances.clone(), plmc_existential_deposits.clone()]); @@ -778,9 +771,7 @@ impl<'a> AuctioningProject<'a> { let candle_start = english_end + 2; - self.test_env - .advance_time(candle_start.saturating_sub(self.test_env.current_block())) - .unwrap(); + self.test_env.advance_time(candle_start.saturating_sub(self.test_env.current_block())).unwrap(); let candle_end = self .get_project_details() .phase_transition_points @@ -790,17 +781,11 @@ impl<'a> AuctioningProject<'a> { let community_start = candle_end + 2; - self.test_env - .advance_time(community_start.saturating_sub(self.test_env.current_block())) - .unwrap(); + self.test_env.advance_time(community_start.saturating_sub(self.test_env.current_block())).unwrap(); assert_eq!(self.get_project_details().status, ProjectStatus::CommunityRound); - CommunityFundingProject { - test_env: self.test_env, - issuer: self.issuer, - project_id: self.project_id, - } + CommunityFundingProject { test_env: self.test_env, issuer: self.issuer, project_id: self.project_id } } } @@ -814,17 +799,22 @@ impl<'a> ProjectInstance for CommunityFundingProject<'a> { fn get_test_environment(&self) -> &TestEnvironment { self.test_env } + fn get_issuer(&self) -> AccountId { self.issuer.clone() } + fn get_project_id(&self) -> ProjectIdOf { self.project_id.clone() } } impl<'a> CommunityFundingProject<'a> { fn new_with( - test_env: &'a TestEnvironment, project_metadata: ProjectMetadataOf, - issuer: ::AccountId, evaluations: UserToUSDBalance, bids: TestBids, + test_env: &'a TestEnvironment, + project_metadata: ProjectMetadataOf, + issuer: ::AccountId, + evaluations: UserToUSDBalance, + bids: TestBids, ) -> Self { let auctioning_project = AuctioningProject::new_with(test_env, project_metadata, issuer, evaluations.clone()); @@ -834,10 +824,7 @@ impl<'a> CommunityFundingProject<'a> { panic!("Cannot start community funding without bids") } - let bidders = bids - .iter() - .map(|b| b.bidder.clone()) - .collect::>>(); + let bidders = bids.iter().map(|b| b.bidder.clone()).collect::>>(); let asset_id = bids[0].asset.to_statemint_id(); let prev_plmc_balances = test_env.get_free_plmc_balances_for(bidders.clone()); let prev_funding_asset_balances = test_env.get_free_statemint_asset_balances_for(asset_id, bidders); @@ -904,17 +891,16 @@ impl<'a> CommunityFundingProject<'a> { } fn finalized_bids_assertions( - &self, bid_expectations: Vec>, expected_ct_sold: BalanceOf, + &self, + bid_expectations: Vec>, + expected_ct_sold: BalanceOf, ) { let project_metadata = self.get_project_metadata(); let project_details = self.get_project_details(); let project_id = self.get_project_id(); let project_bids = self.in_ext(|| Bids::::iter_prefix(project_id).collect::>()); let flattened_bids = project_bids.into_iter().map(|bid| bid.1).flatten().collect::>(); - assert!( - matches!(project_details.weighted_average_price, Some(_)), - "Weighted average price should exist" - ); + assert!(matches!(project_details.weighted_average_price, Some(_)), "Weighted average price should exist"); for filter in bid_expectations { let _found_bid = flattened_bids.iter().find(|bid| filter.matches_bid(&bid)).unwrap(); @@ -937,40 +923,26 @@ impl<'a> CommunityFundingProject<'a> { .end() .expect("Community funding end point should exist"); let remainder_start = community_funding_end + 1; - self.test_env - .advance_time(remainder_start.saturating_sub(self.test_env.current_block())) - .unwrap(); + self.test_env.advance_time(remainder_start.saturating_sub(self.test_env.current_block())).unwrap(); assert_eq!(self.get_project_details().status, ProjectStatus::RemainderRound); - RemainderFundingProject { - test_env: self.test_env, - issuer: self.issuer, - project_id: self.project_id, - } + RemainderFundingProject { test_env: self.test_env, issuer: self.issuer, project_id: self.project_id } } fn finish_funding(self) -> FinishedProject<'a> { let test_env = self.get_test_environment(); let (update_block, _) = self.get_update_pair(); - test_env - .advance_time(update_block.saturating_sub(test_env.current_block())) - .unwrap(); + test_env.advance_time(update_block.saturating_sub(test_env.current_block())).unwrap(); if self.get_project_details().status == ProjectStatus::RemainderRound { let (end_block, _) = self.get_update_pair(); - self.test_env - .advance_time(end_block.saturating_sub(self.test_env.current_block())) - .unwrap(); + self.test_env.advance_time(end_block.saturating_sub(self.test_env.current_block())).unwrap(); } let project_details = self.get_project_details(); assert!( - matches!(project_details.status, ProjectStatus::FundingSuccessful) - || matches!(project_details.status, ProjectStatus::FundingFailed), + matches!(project_details.status, ProjectStatus::FundingSuccessful) || + matches!(project_details.status, ProjectStatus::FundingFailed), "Project should be in Finished status" ); - FinishedProject { - test_env: self.test_env, - issuer: self.issuer, - project_id: self.project_id, - } + FinishedProject { test_env: self.test_env, issuer: self.issuer, project_id: self.project_id } } } @@ -984,9 +956,11 @@ impl<'a> ProjectInstance for RemainderFundingProject<'a> { fn get_test_environment(&self) -> &TestEnvironment { self.test_env } + fn get_issuer(&self) -> AccountId { self.issuer.clone() } + fn get_project_id(&self) -> ProjectIdOf { self.project_id.clone() } @@ -1009,17 +983,18 @@ impl<'a> RemainderFundingProject<'a> { } fn new_with( - test_env: &'a TestEnvironment, project_metadata: ProjectMetadataOf, issuer: AccountId, - evaluations: UserToUSDBalance, bids: TestBids, contributions: TestContributions, + test_env: &'a TestEnvironment, + project_metadata: ProjectMetadataOf, + issuer: AccountId, + evaluations: UserToUSDBalance, + bids: TestBids, + contributions: TestContributions, ) -> Self { let community_funding_project = CommunityFundingProject::new_with(test_env, project_metadata, issuer, evaluations.clone(), bids.clone()); let project_id = community_funding_project.get_project_id(); - let ct_price = community_funding_project - .get_project_details() - .weighted_average_price - .unwrap(); + let ct_price = community_funding_project.get_project_details().weighted_average_price.unwrap(); let contributors = contributions.iter().map(|cont| cont.contributor).collect::>(); let asset_id = contributions[0].asset.to_statemint_id(); let prev_plmc_balances = test_env.get_free_plmc_balances_for(contributors.clone()); @@ -1034,10 +1009,8 @@ impl<'a> RemainderFundingProject<'a> { merge_subtract_mappings_by_user(plmc_contribution_deposits.clone(), vec![plmc_evaluation_deposits]); let total_plmc_participation_locked = merge_add_mappings_by_user(vec![plmc_bid_deposits, plmc_contribution_deposits.clone()]); - let plmc_existential_deposits: UserToPLMCBalance = contributors - .iter() - .map(|acc| (acc.clone(), get_ed())) - .collect::>(); + let plmc_existential_deposits: UserToPLMCBalance = + contributors.iter().map(|acc| (acc.clone(), get_ed())).collect::>(); let funding_asset_deposits = calculate_contributed_funding_asset_spent(contributions.clone(), ct_price); let contributor_balances = @@ -1053,9 +1026,7 @@ impl<'a> RemainderFundingProject<'a> { test_env.mint_plmc_to(plmc_existential_deposits.clone()); test_env.mint_statemint_asset_to(funding_asset_deposits.clone()); - community_funding_project - .buy_for_retail_users(contributions.clone()) - .expect("Contributing should work"); + community_funding_project.buy_for_retail_users(contributions.clone()).expect("Contributing should work"); test_env.do_reserved_plmc_assertions(total_plmc_participation_locked, LockType::Participation(project_id)); test_env.do_contribution_transferred_statemint_asset_assertions(funding_asset_deposits, project_id); @@ -1071,23 +1042,13 @@ impl<'a> RemainderFundingProject<'a> { fn end_funding(&self) -> FinishedProject<'a> { assert_eq!(self.get_project_details().status, ProjectStatus::RemainderRound); - let remainder_funding_end = self - .get_project_details() - .phase_transition_points - .remainder - .end() - .expect("Should have remainder end"); + let remainder_funding_end = + self.get_project_details().phase_transition_points.remainder.end().expect("Should have remainder end"); let finish_block = remainder_funding_end + 1; - self.test_env - .advance_time(finish_block.saturating_sub(self.test_env.current_block())) - .unwrap(); + self.test_env.advance_time(finish_block.saturating_sub(self.test_env.current_block())).unwrap(); assert_eq!(self.get_project_details().status, ProjectStatus::FundingSuccessful); - FinishedProject { - test_env: self.test_env, - issuer: self.issuer.clone(), - project_id: self.project_id.clone(), - } + FinishedProject { test_env: self.test_env, issuer: self.issuer.clone(), project_id: self.project_id.clone() } } } @@ -1101,17 +1062,23 @@ impl<'a> ProjectInstance for FinishedProject<'a> { fn get_test_environment(&self) -> &TestEnvironment { self.test_env } + fn get_issuer(&self) -> AccountId { self.issuer.clone() } + fn get_project_id(&self) -> ProjectIdOf { self.project_id.clone() } } impl<'a> FinishedProject<'a> { fn new_with( - test_env: &'a TestEnvironment, project_metadata: ProjectMetadataOf, issuer: AccountId, - evaluations: UserToUSDBalance, bids: TestBids, community_contributions: TestContributions, + test_env: &'a TestEnvironment, + project_metadata: ProjectMetadataOf, + issuer: AccountId, + evaluations: UserToUSDBalance, + bids: TestBids, + community_contributions: TestContributions, remainder_contributions: TestContributions, ) -> Self { let remainder_funding_project = RemainderFundingProject::new_with( @@ -1124,18 +1091,12 @@ impl<'a> FinishedProject<'a> { ); if remainder_contributions.is_empty() { - return remainder_funding_project.end_funding(); + return remainder_funding_project.end_funding() } let project_id = remainder_funding_project.get_project_id(); - let ct_price = remainder_funding_project - .get_project_details() - .weighted_average_price - .unwrap(); - let contributors = remainder_contributions - .iter() - .map(|cont| cont.contributor) - .collect::>(); + let ct_price = remainder_funding_project.get_project_details().weighted_average_price.unwrap(); + let contributors = remainder_contributions.iter().map(|cont| cont.contributor).collect::>(); let asset_id = remainder_contributions[0].asset.to_statemint_id(); let prev_plmc_balances = test_env.get_free_plmc_balances_for(contributors.clone()); let prev_funding_asset_balances = @@ -1157,10 +1118,8 @@ impl<'a> FinishedProject<'a> { plmc_community_contribution_deposits, plmc_remainder_contribution_deposits.clone(), ]); - let plmc_existential_deposits: UserToPLMCBalance = contributors - .iter() - .map(|acc| (acc.clone(), get_ed())) - .collect::>(); + let plmc_existential_deposits: UserToPLMCBalance = + contributors.iter().map(|acc| (acc.clone(), get_ed())).collect::>(); let funding_asset_deposits = calculate_contributed_funding_asset_spent(remainder_contributions.clone(), ct_price); @@ -1197,10 +1156,10 @@ impl<'a> FinishedProject<'a> { assert_eq!( project_details.remaining_contribution_tokens, - project_metadata.total_allocation_size - - auction_bought_tokens - - community_bought_tokens - - remainder_bought_tokens, + project_metadata.total_allocation_size - + auction_bought_tokens - + community_bought_tokens - + remainder_bought_tokens, "Remaining CTs are incorrect" ); @@ -1224,14 +1183,8 @@ mod defaults { mainnet_token_max_supply: 8_000_000_0_000_000_000, total_allocation_size: 1_000_000_0_000_000_000, minimum_price: PriceOf::::from_float(1.0), - ticket_size: TicketSize { - minimum: Some(1), - maximum: None, - }, - participants_size: ParticipantsSize { - minimum: Some(2), - maximum: None, - }, + ticket_size: TicketSize { minimum: Some(1), maximum: None }, + participants_size: ParticipantsSize { minimum: Some(2), maximum: None }, funding_thresholds: Default::default(), conversion_rate: 0, participation_currencies: AcceptedFundingAsset::USDT, @@ -1254,11 +1207,7 @@ mod defaults { } pub fn default_evaluations() -> UserToUSDBalance { - vec![ - (EVALUATOR_1, 50_000 * PLMC), - (EVALUATOR_2, 25_000 * PLMC), - (EVALUATOR_3, 32_000 * PLMC), - ] + vec![(EVALUATOR_1, 50_000 * PLMC), (EVALUATOR_2, 25_000 * PLMC), (EVALUATOR_3, 32_000 * PLMC)] } pub fn default_failing_evaluations() -> UserToPLMCBalance { @@ -1268,20 +1217,8 @@ mod defaults { pub fn default_bids() -> TestBids { // This should reflect the bidding currency, which currently is USDT vec![ - TestBid::new( - BIDDER_1, - 50000 * ASSET_UNIT, - 18_u128.into(), - None, - AcceptedFundingAsset::USDT, - ), - TestBid::new( - BIDDER_2, - 40000 * ASSET_UNIT, - 15_u128.into(), - None, - AcceptedFundingAsset::USDT, - ), + TestBid::new(BIDDER_1, 50000 * ASSET_UNIT, 18_u128.into(), None, AcceptedFundingAsset::USDT), + TestBid::new(BIDDER_2, 40000 * ASSET_UNIT, 15_u128.into(), None, AcceptedFundingAsset::USDT), ] } @@ -1328,11 +1265,7 @@ pub mod helper_functions { let mut output = UserToPLMCBalance::new(); for bid in bids { let usd_ticket_size = bid.price.saturating_mul_int(bid.amount); - let usd_bond = bid - .multiplier - .unwrap_or_default() - .calculate_bonding_requirement(usd_ticket_size) - .unwrap(); + let usd_bond = bid.multiplier.unwrap_or_default().calculate_bonding_requirement(usd_ticket_size).unwrap(); let plmc_bond = plmc_price.reciprocal().unwrap().saturating_mul_int(usd_bond); output.push((bid.bidder, plmc_bond)); } @@ -1341,7 +1274,8 @@ pub mod helper_functions { // This differs from `calculate_auction_plmc_spent` in that it recalculates bids over the average price as using that price. pub fn calculate_auction_plmc_spent_after_price_calculation( - bids: TestBids, price: PriceOf, + bids: TestBids, + price: PriceOf, ) -> UserToPLMCBalance { let plmc_price = PriceMap::get().get(&PLMC_STATEMINT_ID).unwrap().clone(); let mut output = UserToPLMCBalance::new(); @@ -1349,11 +1283,7 @@ pub mod helper_functions { let final_price = if bid.price < price { bid.price } else { price }; let usd_ticket_size = final_price.saturating_mul_int(bid.amount); - let usd_bond = bid - .multiplier - .unwrap_or_default() - .calculate_bonding_requirement(usd_ticket_size) - .unwrap(); + let usd_bond = bid.multiplier.unwrap_or_default().calculate_bonding_requirement(usd_ticket_size).unwrap(); let plmc_bond = plmc_price.reciprocal().unwrap().saturating_mul_int(usd_bond); output.push((bid.bidder, plmc_bond)); } @@ -1372,17 +1302,14 @@ pub mod helper_functions { } pub fn calculate_contributed_plmc_spent( - contributions: TestContributions, token_usd_price: PriceOf, + contributions: TestContributions, + token_usd_price: PriceOf, ) -> UserToPLMCBalance { let plmc_price = PriceMap::get().get(&PLMC_STATEMINT_ID).unwrap().clone(); let mut output = UserToPLMCBalance::new(); for cont in contributions { let usd_ticket_size = token_usd_price.saturating_mul_int(cont.amount); - let usd_bond = cont - .multiplier - .unwrap_or_default() - .calculate_bonding_requirement(usd_ticket_size) - .unwrap(); + let usd_bond = cont.multiplier.unwrap_or_default().calculate_bonding_requirement(usd_ticket_size).unwrap(); let plmc_bond = plmc_price.reciprocal().unwrap().saturating_mul_int(usd_bond); output.push((cont.contributor, plmc_bond)); } @@ -1390,7 +1317,8 @@ pub mod helper_functions { } pub fn calculate_contributed_funding_asset_spent( - contributions: TestContributions, token_usd_price: PriceOf, + contributions: TestContributions, + token_usd_price: PriceOf, ) -> UserToStatemintAsset { let mut output = UserToStatemintAsset::new(); for cont in contributions { @@ -1423,13 +1351,13 @@ pub mod helper_functions { (None, None) => break, (Some(_), None) => { output.extend_from_slice(&old_output[i..]); - break; - } + break + }, (None, Some(_)) => { output.extend_from_slice(&map[j..]); - break; - } - (Some((acc_i, val_i)), Some((acc_j, val_j))) => { + break + }, + (Some((acc_i, val_i)), Some((acc_j, val_j))) => if acc_i == acc_j { output.push((acc_i.clone(), val_i.clone() + val_j.clone())); i += 1; @@ -1440,8 +1368,7 @@ pub mod helper_functions { } else { output.push(map[j]); j += 1; - } - } + }, } } } @@ -1449,7 +1376,10 @@ pub mod helper_functions { } pub fn generic_map_merge_reduce( - mappings: Vec>, key_extractor: impl Fn(&M) -> K, initial_state: S, merge_reduce: impl Fn(&M, S) -> S, + mappings: Vec>, + key_extractor: impl Fn(&M) -> K, + initial_state: S, + merge_reduce: impl Fn(&M, S) -> S, ) -> Vec<(K, S)> { let mut output = BTreeMap::new(); for mut map in mappings { @@ -1463,7 +1393,9 @@ pub mod helper_functions { } pub fn generic_map_merge( - mut mappings: Vec>, key_extractor: impl Fn(&M) -> K, merger: impl Fn(&M, &M) -> M, + mut mappings: Vec>, + key_extractor: impl Fn(&M) -> K, + merger: impl Fn(&M, &M) -> M, ) -> Vec { let mut output = mappings.swap_remove(0); output.sort_by_key(|k| key_extractor(k)); @@ -1481,12 +1413,12 @@ pub mod helper_functions { (None, None) => break, (Some(_), None) => { output.extend_from_slice(&old_output[i..]); - break; - } + break + }, (None, Some(_)) => { output.extend_from_slice(&new_map[j..]); - break; - } + break + }, (Some(m_i), Some(m_j)) => { let k_i = key_extractor(m_i); let k_j = key_extractor(m_j); @@ -1501,7 +1433,7 @@ pub mod helper_functions { output.push(new_map[j].clone()); j += 1; } - } + }, } } } @@ -1510,7 +1442,8 @@ pub mod helper_functions { // Mappings should be sorted based on their account id, ascending. pub fn merge_subtract_mappings_by_user( - base_mapping: Vec<(AccountIdOf, I)>, subtract_mappings: Vec, I)>>, + base_mapping: Vec<(AccountIdOf, I)>, + subtract_mappings: Vec, I)>>, ) -> Vec<(AccountIdOf, I)> { let mut output = base_mapping; output.sort_by_key(|k| k.0); @@ -1528,13 +1461,13 @@ pub mod helper_functions { (None, None) => break, (Some(_), None) => { output.extend_from_slice(&old_output[i..]); - break; - } + break + }, (None, Some(_)) => { output.extend_from_slice(&map[j..]); - break; - } - (Some((acc_i, val_i)), Some((acc_j, val_j))) => { + break + }, + (Some((acc_i, val_i)), Some((acc_j, val_j))) => if acc_i == acc_j { output.push((acc_i.clone(), val_i.clone().saturating_sub(val_j.clone()))); i += 1; @@ -1545,8 +1478,7 @@ pub mod helper_functions { } else { output.push(map[j]); j += 1; - } - } + }, } } } @@ -1602,8 +1534,8 @@ pub mod helper_functions { .. } => { panic!("Project {} transition failed in on_initialize: {:?}", project_id, error); - } - _ => {} + }, + _ => {}, } } @@ -1619,7 +1551,7 @@ pub mod helper_functions { DispatchError::Module(module_error) => { let pallet_error: Error = Decode::decode(&mut &module_error.error[..]).unwrap(); Err(pallet_error) - } + }, _ => panic!("wrong conversion"), }, _ => Ok(()), @@ -1638,11 +1570,7 @@ mod creation_round_success { test_env.mint_plmc_to(default_plmc_balances()); test_env.ext_env.borrow_mut().execute_with(|| { - assert_ok!(Balances::transfer( - RuntimeOrigin::signed(EVALUATOR_1), - EVALUATOR_2, - 1 * PLMC - )); + assert_ok!(Balances::transfer(RuntimeOrigin::signed(EVALUATOR_1), EVALUATOR_2, 1 * PLMC)); }); } @@ -1707,14 +1635,8 @@ mod creation_round_failure { fn price_too_low() { let wrong_project: ProjectMetadataOf = ProjectMetadata { minimum_price: 0_u128.into(), - ticket_size: TicketSize { - minimum: Some(1), - maximum: None, - }, - participants_size: ParticipantsSize { - minimum: Some(2), - maximum: None, - }, + ticket_size: TicketSize { minimum: Some(1), maximum: None }, + participants_size: ParticipantsSize { minimum: Some(2), maximum: None }, offchain_information_hash: Some(hashed(METADATA)), ..Default::default() }; @@ -1729,14 +1651,8 @@ mod creation_round_failure { fn participants_size_error() { let wrong_project: ProjectMetadataOf = ProjectMetadata { minimum_price: 1_u128.into(), - ticket_size: TicketSize { - minimum: Some(1), - maximum: None, - }, - participants_size: ParticipantsSize { - minimum: None, - maximum: None, - }, + ticket_size: TicketSize { minimum: Some(1), maximum: None }, + participants_size: ParticipantsSize { minimum: None, maximum: None }, offchain_information_hash: Some(hashed(METADATA)), ..Default::default() }; @@ -1752,14 +1668,8 @@ mod creation_round_failure { fn ticket_size_error() { let wrong_project: ProjectMetadataOf = ProjectMetadata { minimum_price: 1_u128.into(), - ticket_size: TicketSize { - minimum: None, - maximum: None, - }, - participants_size: ParticipantsSize { - minimum: Some(1), - maximum: None, - }, + ticket_size: TicketSize { minimum: None, maximum: None }, + participants_size: ParticipantsSize { minimum: Some(1), maximum: None }, offchain_information_hash: Some(hashed(METADATA)), ..Default::default() }; @@ -1776,14 +1686,8 @@ mod creation_round_failure { fn multiple_field_error() { let wrong_project: ProjectMetadataOf = ProjectMetadata { minimum_price: 0_u128.into(), - ticket_size: TicketSize { - minimum: None, - maximum: None, - }, - participants_size: ParticipantsSize { - minimum: None, - maximum: None, - }, + ticket_size: TicketSize { minimum: None, maximum: None }, + participants_size: ParticipantsSize { minimum: None, maximum: None }, ..Default::default() }; let test_env = TestEnvironment::new(); @@ -1841,14 +1745,8 @@ mod evaluation_round_success { mainnet_token_max_supply: 8_000_000_0_000_000_000, total_allocation_size: 100_000_0_000_000_000, minimum_price: PriceOf::::from_float(10.0), - ticket_size: TicketSize { - minimum: Some(1), - maximum: None, - }, - participants_size: ParticipantsSize { - minimum: Some(2), - maximum: None, - }, + ticket_size: TicketSize { minimum: Some(1), maximum: None }, + participants_size: ParticipantsSize { minimum: Some(2), maximum: None }, funding_thresholds: Default::default(), conversion_rate: 0, participation_currencies: AcceptedFundingAsset::USDT, @@ -1864,27 +1762,9 @@ mod evaluation_round_success { ]; let bids: TestBids = vec![ - TestBid::new( - BIDDER_1, - 10_000 * ASSET_UNIT, - 15.into(), - None, - AcceptedFundingAsset::USDT, - ), - TestBid::new( - BIDDER_2, - 20_000 * ASSET_UNIT, - 20.into(), - None, - AcceptedFundingAsset::USDT, - ), - TestBid::new( - BIDDER_4, - 20_000 * ASSET_UNIT, - 16.into(), - None, - AcceptedFundingAsset::USDT, - ), + TestBid::new(BIDDER_1, 10_000 * ASSET_UNIT, 15.into(), None, AcceptedFundingAsset::USDT), + TestBid::new(BIDDER_2, 20_000 * ASSET_UNIT, 20.into(), None, AcceptedFundingAsset::USDT), + TestBid::new(BIDDER_4, 20_000 * ASSET_UNIT, 16.into(), None, AcceptedFundingAsset::USDT), ]; let contributions: TestContributions = vec![ @@ -1902,10 +1782,7 @@ mod evaluation_round_success { let details = community_funding_project.get_project_details(); let ct_price = details.weighted_average_price.unwrap(); let mut plmc_deposits = calculate_contributed_plmc_spent(contributions.clone(), ct_price); - plmc_deposits = plmc_deposits - .into_iter() - .map(|(account, balance)| (account, balance + get_ed())) - .collect(); + plmc_deposits = plmc_deposits.into_iter().map(|(account, balance)| (account, balance + get_ed())).collect(); let funding_deposits = calculate_contributed_funding_asset_spent(contributions.clone(), ct_price); test_env.mint_plmc_to(plmc_deposits); @@ -1917,18 +1794,9 @@ mod evaluation_round_success { let project_id = finished_project.project_id; let actual_reward_balances = test_env.in_ext(|| { vec![ - ( - EVALUATOR_1, - ::ContributionTokenCurrency::balance(project_id, EVALUATOR_1), - ), - ( - EVALUATOR_2, - ::ContributionTokenCurrency::balance(project_id, EVALUATOR_2), - ), - ( - EVALUATOR_3, - ::ContributionTokenCurrency::balance(project_id, EVALUATOR_3), - ), + (EVALUATOR_1, ::ContributionTokenCurrency::balance(project_id, EVALUATOR_1)), + (EVALUATOR_2, ::ContributionTokenCurrency::balance(project_id, EVALUATOR_2)), + (EVALUATOR_3, ::ContributionTokenCurrency::balance(project_id, EVALUATOR_3)), ] }); let expected_ct_rewards = vec![ @@ -1966,10 +1834,8 @@ mod evaluation_round_success { remainder_funding_project.end_funding(); test_env.advance_time(10).unwrap(); - let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc - .iter() - .map(|(evaluator, _amount)| (*evaluator, Zero::zero())) - .collect(); + let post_unbond_amounts: UserToPLMCBalance = + prev_reserved_plmc.iter().map(|(evaluator, _amount)| (*evaluator, Zero::zero())).collect(); test_env.do_reserved_plmc_assertions(post_unbond_amounts.clone(), LockType::Evaluation(project_id)); test_env.do_reserved_plmc_assertions(post_unbond_amounts, LockType::Participation(project_id)); @@ -1992,19 +1858,8 @@ mod evaluation_round_success { default_project(test_env.get_new_nonce()), ISSUER, evaluations.clone(), - vec![TestBid::new( - BUYER_1, - 1000 * ASSET_UNIT, - 10u128.into(), - None, - AcceptedFundingAsset::USDT, - )], - vec![TestContribution::new( - BUYER_1, - 1000 * US_DOLLAR, - None, - AcceptedFundingAsset::USDT, - )], + vec![TestBid::new(BUYER_1, 1000 * ASSET_UNIT, 10u128.into(), None, AcceptedFundingAsset::USDT)], + vec![TestContribution::new(BUYER_1, 1000 * US_DOLLAR, None, AcceptedFundingAsset::USDT)], ); let project_id = remainder_funding_project.get_project_id(); @@ -2013,16 +1868,11 @@ mod evaluation_round_success { let prev_free_plmc = test_env.get_free_plmc_balances_for(evaluators.clone()); let finished_project = remainder_funding_project.end_funding(); - assert_eq!( - finished_project.get_project_details().status, - ProjectStatus::FundingFailed - ); + assert_eq!(finished_project.get_project_details().status, ProjectStatus::FundingFailed); test_env.advance_time(10).unwrap(); - let post_unbond_amounts: UserToPLMCBalance = prev_reserved_plmc - .iter() - .map(|(evaluator, _amount)| (*evaluator, Zero::zero())) - .collect(); + let post_unbond_amounts: UserToPLMCBalance = + prev_reserved_plmc.iter().map(|(evaluator, _amount)| (*evaluator, Zero::zero())).collect(); test_env.do_reserved_plmc_assertions(post_unbond_amounts.clone(), LockType::Evaluation(project_id)); test_env.do_reserved_plmc_assertions(post_unbond_amounts, LockType::Participation(project_id)); @@ -2047,10 +1897,8 @@ mod evaluation_round_failure { let project = default_project(test_env.get_new_nonce()); let evaluations = default_failing_evaluations(); let plmc_eval_deposits: UserToPLMCBalance = calculate_evaluation_plmc_spent(evaluations.clone()); - let plmc_existential_deposits: UserToPLMCBalance = evaluations - .iter() - .map(|(account, _amount)| (account.clone(), get_ed())) - .collect::<_>(); + let plmc_existential_deposits: UserToPLMCBalance = + evaluations.iter().map(|(account, _amount)| (account.clone(), get_ed())).collect::<_>(); let expected_evaluator_balances = merge_add_mappings_by_user(vec![plmc_eval_deposits.clone(), plmc_existential_deposits.clone()]); @@ -2067,19 +1915,14 @@ mod evaluation_round_failure { .expect("Evaluation round end block should be set"); let project_id = evaluating_project.get_project_id(); - evaluating_project - .bond_for_users(default_failing_evaluations()) - .expect("Bonding should work"); + evaluating_project.bond_for_users(default_failing_evaluations()).expect("Bonding should work"); test_env.do_free_plmc_assertions(plmc_existential_deposits); test_env.do_reserved_plmc_assertions(plmc_eval_deposits, LockType::Evaluation(project_id)); test_env.advance_time(evaluation_end - now + 1).unwrap(); - assert_eq!( - evaluating_project.get_project_details().status, - ProjectStatus::EvaluationFailed - ); + assert_eq!(evaluating_project.get_project_details().status, ProjectStatus::EvaluationFailed); // Check that on_idle has unlocked the failed bonds test_env.advance_time(10).unwrap(); @@ -2098,10 +1941,8 @@ mod evaluation_round_failure { .map(|(account, amount)| (account.clone(), amount / 2)) .collect::(); - let plmc_existential_deposits: UserToPLMCBalance = evaluations - .iter() - .map(|(account, _amount)| (account.clone(), get_ed())) - .collect::<_>(); + let plmc_existential_deposits: UserToPLMCBalance = + evaluations.iter().map(|(account, _amount)| (account.clone(), get_ed())).collect::<_>(); test_env.mint_plmc_to(insufficient_eval_deposits.clone()); test_env.mint_plmc_to(plmc_existential_deposits); @@ -2153,13 +1994,8 @@ mod auction_round_success { let mut evaluations = default_evaluations(); let evaluator_bidder = 69; let evaluation_amount = 420 * US_DOLLAR; - let evaluator_bid = TestBid::new( - evaluator_bidder, - 600 * ASSET_UNIT, - 15.into(), - None, - AcceptedFundingAsset::USDT, - ); + let evaluator_bid = + TestBid::new(evaluator_bidder, 600 * ASSET_UNIT, 15.into(), None, AcceptedFundingAsset::USDT); evaluations.push((evaluator_bidder, evaluation_amount)); let bidding_project = AuctioningProject::new_with(&test_env, project, issuer, evaluations); @@ -2181,23 +2017,12 @@ mod auction_round_success { let project = default_project(test_env.get_new_nonce()); let mut evaluations = default_evaluations(); let evaluator_bidder = 69; - let evaluator_bid = TestBid::new( - evaluator_bidder, - 600 * ASSET_UNIT, - 15.into(), - None, - AcceptedFundingAsset::USDT, - ); + let evaluator_bid = + TestBid::new(evaluator_bidder, 600 * ASSET_UNIT, 15.into(), None, AcceptedFundingAsset::USDT); let mut bids = Vec::new(); for _ in 0..::MaxBidsPerUser::get() { - bids.push(TestBid::new( - evaluator_bidder, - 10 * ASSET_UNIT, - 15.into(), - None, - AcceptedFundingAsset::USDT, - )); + bids.push(TestBid::new(evaluator_bidder, 10 * ASSET_UNIT, 15.into(), None, AcceptedFundingAsset::USDT)); } let fill_necessary_plmc_for_bids = calculate_auction_plmc_spent(bids.clone()); @@ -2232,8 +2057,8 @@ mod auction_round_success { }); let post_fill_evaluation_bond = bid_necessary_plmc[0].1 - FUNDED_DELTA_PLMC; assert!( - evaluation_bond < post_fill_evaluation_bond + 10_u128 - || evaluation_bond > post_fill_evaluation_bond - 10_u128 + evaluation_bond < post_fill_evaluation_bond + 10_u128 || + evaluation_bond > post_fill_evaluation_bond - 10_u128 ); bidding_project.bid_for_users(vec![evaluator_bid]).unwrap(); @@ -2290,10 +2115,7 @@ mod auction_round_success { auctioning_project.bid_for_users(bids).unwrap(); let community_funding_project = auctioning_project.start_community_funding(); - let token_price = community_funding_project - .get_project_details() - .weighted_average_price - .unwrap(); + let token_price = community_funding_project.get_project_details().weighted_average_price.unwrap(); let price_in_10_decimals = token_price.checked_mul_int(1_0_000_000_000_u128).unwrap(); let price_in_12_decimals = token_price.checked_mul_int(1_000_000_000_000_u128).unwrap(); @@ -2309,27 +2131,9 @@ mod auction_round_success { let auctioning_project = AuctioningProject::new_with(&test_env, project_metadata, ISSUER, default_evaluations()); let bids = vec![ - TestBid::new( - BIDDER_1, - 10_000 * ASSET_UNIT, - 15.into(), - None, - AcceptedFundingAsset::USDT, - ), - TestBid::new( - BIDDER_2, - 20_000 * ASSET_UNIT, - 20.into(), - None, - AcceptedFundingAsset::USDT, - ), - TestBid::new( - BIDDER_3, - 20_000 * ASSET_UNIT, - 16.into(), - None, - AcceptedFundingAsset::USDT, - ), + TestBid::new(BIDDER_1, 10_000 * ASSET_UNIT, 15.into(), None, AcceptedFundingAsset::USDT), + TestBid::new(BIDDER_2, 20_000 * ASSET_UNIT, 20.into(), None, AcceptedFundingAsset::USDT), + TestBid::new(BIDDER_3, 20_000 * ASSET_UNIT, 16.into(), None, AcceptedFundingAsset::USDT), ]; let statemint_funding = calculate_auction_funding_asset_spent(bids.clone()); @@ -2347,10 +2151,7 @@ mod auction_round_success { auctioning_project.bid_for_users(bids).unwrap(); let community_funding_project = auctioning_project.start_community_funding(); - let token_price = community_funding_project - .get_project_details() - .weighted_average_price - .unwrap(); + let token_price = community_funding_project.get_project_details().weighted_average_price.unwrap(); let price_in_10_decimals = token_price.checked_mul_int(1_0_000_000_000_u128).unwrap(); assert_eq!(price_in_10_decimals, 17_6_666_666_666); @@ -2371,13 +2172,8 @@ mod auction_round_success { .expect("Auction start point should exist"); // The block following the end of the english auction, is used to transition the project into candle auction. // We move past that transition, into the start of the candle auction. - test_env - .advance_time(english_end_block - test_env.current_block() + 1) - .unwrap(); - assert_eq!( - auctioning_project.get_project_details().status, - ProjectStatus::AuctionRound(AuctionPhase::Candle) - ); + test_env.advance_time(english_end_block - test_env.current_block() + 1).unwrap(); + assert_eq!(auctioning_project.get_project_details().status, ProjectStatus::AuctionRound(AuctionPhase::Candle)); let candle_end_block = auctioning_project .get_project_details() @@ -2387,13 +2183,8 @@ mod auction_round_success { .expect("Candle auction end point should exist"); let mut bidding_account = 1000; - let bid_info = TestBid::new( - 0, - 50u128, - PriceOf::::from_float(15f64), - None, - AcceptedFundingAsset::USDT, - ); + let bid_info = + TestBid::new(0, 50u128, PriceOf::::from_float(15f64), None, AcceptedFundingAsset::USDT); let plmc_necessary_funding = calculate_auction_plmc_spent(vec![bid_info.clone()])[0].1; let statemint_asset_necessary_funding = calculate_auction_funding_asset_spent(vec![bid_info.clone()])[0].1; @@ -2421,18 +2212,14 @@ mod auction_round_success { bid_info.multiplier, bid_info.asset, )]; - auctioning_project - .bid_for_users(bids.clone()) - .expect("Candle Bidding should not fail"); + auctioning_project.bid_for_users(bids.clone()).expect("Candle Bidding should not fail"); bids_made.push(bids[0]); bidding_account += 1; test_env.advance_time(1).unwrap(); } - test_env - .advance_time(candle_end_block - test_env.current_block() + 1) - .unwrap(); + test_env.advance_time(candle_end_block - test_env.current_block() + 1).unwrap(); let random_end = auctioning_project .get_project_details() @@ -2443,10 +2230,8 @@ mod auction_round_success { let split = (random_end - starting_bid_block + 1) as usize; let excluded_bids = bids_made.split_off(split); let included_bids = bids_made; - let _weighted_price = auctioning_project - .get_project_details() - .weighted_average_price - .expect("Weighted price should exist"); + let _weighted_price = + auctioning_project.get_project_details().weighted_average_price.expect("Weighted price should exist"); for bid in included_bids { let pid = auctioning_project.get_project_id(); @@ -2490,28 +2275,15 @@ mod auction_round_success { let project = EvaluatingProject::new_with(&test_env, default_project(0), ISSUER); let evaluations = default_evaluations(); let required_plmc = calculate_evaluation_plmc_spent(evaluations.clone()); - let ed_plmc: UserToPLMCBalance = evaluations - .clone() - .into_iter() - .map(|(account, _amount)| (account, get_ed())) - .collect(); + let ed_plmc: UserToPLMCBalance = + evaluations.clone().into_iter().map(|(account, _amount)| (account, get_ed())).collect(); test_env.mint_plmc_to(required_plmc); test_env.mint_plmc_to(ed_plmc); project.bond_for_users(evaluations).unwrap(); - test_env - .advance_time(::EvaluationDuration::get() + 1) - .unwrap(); - assert_eq!( - project.get_project_details().status, - ProjectStatus::AuctionInitializePeriod - ); - test_env - .advance_time(::AuctionInitializePeriodDuration::get() + 2) - .unwrap(); - assert_eq!( - project.get_project_details().status, - ProjectStatus::AuctionRound(AuctionPhase::English) - ); + test_env.advance_time(::EvaluationDuration::get() + 1).unwrap(); + assert_eq!(project.get_project_details().status, ProjectStatus::AuctionInitializePeriod); + test_env.advance_time(::AuctionInitializePeriodDuration::get() + 2).unwrap(); + assert_eq!(project.get_project_details().status, ProjectStatus::AuctionRound(AuctionPhase::English)); } #[test] @@ -2520,30 +2292,19 @@ mod auction_round_success { let project = EvaluatingProject::new_with(&test_env, default_project(0), ISSUER); let evaluations = default_evaluations(); let required_plmc = calculate_evaluation_plmc_spent(evaluations.clone()); - let ed_plmc: UserToPLMCBalance = evaluations - .clone() - .into_iter() - .map(|(account, _amount)| (account, get_ed())) - .collect(); + let ed_plmc: UserToPLMCBalance = + evaluations.clone().into_iter().map(|(account, _amount)| (account, get_ed())).collect(); test_env.mint_plmc_to(required_plmc); test_env.mint_plmc_to(ed_plmc); project.bond_for_users(evaluations).unwrap(); - test_env - .advance_time(::EvaluationDuration::get() + 1) - .unwrap(); - assert_eq!( - project.get_project_details().status, - ProjectStatus::AuctionInitializePeriod - ); + test_env.advance_time(::EvaluationDuration::get() + 1).unwrap(); + assert_eq!(project.get_project_details().status, ProjectStatus::AuctionInitializePeriod); test_env.advance_time(1).unwrap(); test_env .in_ext(|| FundingModule::start_auction(RuntimeOrigin::signed(ISSUER), project.get_project_id())) .unwrap(); - assert_eq!( - project.get_project_details().status, - ProjectStatus::AuctionRound(AuctionPhase::English) - ); + assert_eq!(project.get_project_details().status, ProjectStatus::AuctionRound(AuctionPhase::English)); } #[test] @@ -2552,21 +2313,13 @@ mod auction_round_success { let project = EvaluatingProject::new_with(&test_env, default_project(0), ISSUER); let evaluations = default_evaluations(); let required_plmc = calculate_evaluation_plmc_spent(evaluations.clone()); - let ed_plmc: UserToPLMCBalance = evaluations - .clone() - .into_iter() - .map(|(account, _amount)| (account, get_ed())) - .collect(); + let ed_plmc: UserToPLMCBalance = + evaluations.clone().into_iter().map(|(account, _amount)| (account, get_ed())).collect(); test_env.mint_plmc_to(required_plmc); test_env.mint_plmc_to(ed_plmc); project.bond_for_users(evaluations).unwrap(); - test_env - .advance_time(::EvaluationDuration::get() + 1) - .unwrap(); - assert_eq!( - project.get_project_details().status, - ProjectStatus::AuctionInitializePeriod - ); + test_env.advance_time(::EvaluationDuration::get() + 1).unwrap(); + assert_eq!(project.get_project_details().status, ProjectStatus::AuctionInitializePeriod); test_env.advance_time(1).unwrap(); for account in 6000..6010 { @@ -2585,13 +2338,7 @@ mod auction_round_success { let evaluations = default_evaluations(); let mut bids = default_bids(); let evaluator = evaluations[0].0; - bids.push(TestBid::new( - evaluator, - 150 * ASSET_UNIT, - 21_u128.into(), - None, - AcceptedFundingAsset::USDT, - )); + bids.push(TestBid::new(evaluator, 150 * ASSET_UNIT, 21_u128.into(), None, AcceptedFundingAsset::USDT)); let _community_funding_project = CommunityFundingProject::new_with(&test_env, project, issuer, evaluations, bids); } @@ -2603,37 +2350,16 @@ mod auction_round_success { let project = default_project(test_env.get_new_nonce()); let evaluations = default_evaluations(); let bids: TestBids = vec![ - TestBid::new( - BIDDER_1, - 10_000 * ASSET_UNIT, - 15.into(), - None, - AcceptedFundingAsset::USDT, - ), - TestBid::new( - BIDDER_2, - 20_000 * ASSET_UNIT, - 20.into(), - None, - AcceptedFundingAsset::USDT, - ), - TestBid::new( - BIDDER_4, - 20_000 * ASSET_UNIT, - 16.into(), - None, - AcceptedFundingAsset::USDT, - ), + TestBid::new(BIDDER_1, 10_000 * ASSET_UNIT, 15.into(), None, AcceptedFundingAsset::USDT), + TestBid::new(BIDDER_2, 20_000 * ASSET_UNIT, 20.into(), None, AcceptedFundingAsset::USDT), + TestBid::new(BIDDER_4, 20_000 * ASSET_UNIT, 16.into(), None, AcceptedFundingAsset::USDT), ]; let community_funding_project = CommunityFundingProject::new_with(&test_env, project, issuer, evaluations, bids); let project_id = community_funding_project.project_id; let bidder_2_bid = test_env.in_ext(|| Bids::::get(project_id, BIDDER_2))[0]; - assert_eq!( - bidder_2_bid.final_ct_usd_price.checked_mul_int(US_DOLLAR).unwrap(), - 17_6_666_666_666 - ); + assert_eq!(bidder_2_bid.final_ct_usd_price.checked_mul_int(US_DOLLAR).unwrap(), 17_6_666_666_666); } } @@ -2701,35 +2427,11 @@ mod auction_round_failure { let project_id = auctioning_project.project_id; const DAVE: AccountId = 42; let bids: TestBids = vec![ - TestBid::new( - DAVE, - 10_000 * USDT_UNIT, - 2_u128.into(), - None, - AcceptedFundingAsset::USDT, - ), // 20k - TestBid::new( - DAVE, - 12_000 * USDT_UNIT, - 8_u128.into(), - None, - AcceptedFundingAsset::USDT, - ), // 96k - TestBid::new( - DAVE, - 15_000 * USDT_UNIT, - 5_u128.into(), - None, - AcceptedFundingAsset::USDT, - ), // 75k - TestBid::new(DAVE, 1_000 * USDT_UNIT, 7_u128.into(), None, AcceptedFundingAsset::USDT), // 7k - TestBid::new( - DAVE, - 20_000 * USDT_UNIT, - 5_u128.into(), - None, - AcceptedFundingAsset::USDT, - ), // 100k + TestBid::new(DAVE, 10_000 * USDT_UNIT, 2_u128.into(), None, AcceptedFundingAsset::USDT), // 20k + TestBid::new(DAVE, 12_000 * USDT_UNIT, 8_u128.into(), None, AcceptedFundingAsset::USDT), // 96k + TestBid::new(DAVE, 15_000 * USDT_UNIT, 5_u128.into(), None, AcceptedFundingAsset::USDT), // 75k + TestBid::new(DAVE, 1_000 * USDT_UNIT, 7_u128.into(), None, AcceptedFundingAsset::USDT), // 7k + TestBid::new(DAVE, 20_000 * USDT_UNIT, 5_u128.into(), None, AcceptedFundingAsset::USDT), // 100k ]; let mut plmc_fundings: UserToPLMCBalance = calculate_auction_plmc_spent(bids.clone()); @@ -2802,20 +2504,8 @@ mod auction_round_failure { let max_cts_for_bids = metadata.total_allocation_size.clone(); let project_id = auctioning_project.get_project_id(); - let glutton_bid = TestBid::new( - BIDDER_1, - max_cts_for_bids, - 10_u128.into(), - None, - AcceptedFundingAsset::USDT, - ); - let rejected_bid = TestBid::new( - BIDDER_2, - 10_000 * ASSET_UNIT, - 5_u128.into(), - None, - AcceptedFundingAsset::USDT, - ); + let glutton_bid = TestBid::new(BIDDER_1, max_cts_for_bids, 10_u128.into(), None, AcceptedFundingAsset::USDT); + let rejected_bid = TestBid::new(BIDDER_2, 10_000 * ASSET_UNIT, 5_u128.into(), None, AcceptedFundingAsset::USDT); let mut plmc_fundings: UserToPLMCBalance = calculate_auction_plmc_spent(vec![glutton_bid.clone(), rejected_bid.clone()]); @@ -2827,9 +2517,7 @@ mod auction_round_failure { test_env.mint_plmc_to(plmc_fundings.clone()); test_env.mint_statemint_asset_to(usdt_fundings.clone()); - auctioning_project - .bid_for_users(vec![glutton_bid, rejected_bid]) - .expect("Bids should pass"); + auctioning_project.bid_for_users(vec![glutton_bid, rejected_bid]).expect("Bids should pass"); test_env.do_free_plmc_assertions(vec![(BIDDER_1, get_ed()), (BIDDER_2, get_ed())]); test_env.do_reserved_plmc_assertions( @@ -2838,16 +2526,8 @@ mod auction_round_failure { ); test_env.do_bid_transferred_statemint_asset_assertions( vec![ - ( - BIDDER_1, - usdt_fundings[0].1, - AcceptedFundingAsset::USDT.to_statemint_id(), - ), - ( - BIDDER_2, - usdt_fundings[1].1, - AcceptedFundingAsset::USDT.to_statemint_id(), - ), + (BIDDER_1, usdt_fundings[0].1, AcceptedFundingAsset::USDT.to_statemint_id()), + (BIDDER_2, usdt_fundings[1].1, AcceptedFundingAsset::USDT.to_statemint_id()), ], project_id, ); @@ -2863,11 +2543,7 @@ mod auction_round_failure { test_env.do_bid_transferred_statemint_asset_assertions( vec![ - ( - BIDDER_1, - usdt_fundings[0].1, - AcceptedFundingAsset::USDT.to_statemint_id(), - ), + (BIDDER_1, usdt_fundings[0].1, AcceptedFundingAsset::USDT.to_statemint_id()), (BIDDER_2, 0, AcceptedFundingAsset::USDT.to_statemint_id()), ], project_id, @@ -2892,20 +2568,16 @@ mod auction_round_failure { test_env.mint_plmc_to(plmc_fundings.clone()); test_env.mint_statemint_asset_to(usdt_fundings.clone()); - auctioning_project - .bid_for_users(vec![bid_in]) - .expect("Bids should pass"); + auctioning_project.bid_for_users(vec![bid_in]).expect("Bids should pass"); test_env .advance_time( - ::EnglishAuctionDuration::get() - + ::CandleAuctionDuration::get() - - 1, + ::EnglishAuctionDuration::get() + + ::CandleAuctionDuration::get() - + 1, ) .unwrap(); - auctioning_project - .bid_for_users(vec![bid_out]) - .expect("Bids should pass"); + auctioning_project.bid_for_users(vec![bid_out]).expect("Bids should pass"); test_env.do_free_plmc_assertions(vec![(BIDDER_1, get_ed()), (BIDDER_2, get_ed())]); test_env.do_reserved_plmc_assertions( @@ -2914,16 +2586,8 @@ mod auction_round_failure { ); test_env.do_bid_transferred_statemint_asset_assertions( vec![ - ( - BIDDER_1, - usdt_fundings[0].1, - AcceptedFundingAsset::USDT.to_statemint_id(), - ), - ( - BIDDER_2, - usdt_fundings[1].1, - AcceptedFundingAsset::USDT.to_statemint_id(), - ), + (BIDDER_1, usdt_fundings[0].1, AcceptedFundingAsset::USDT.to_statemint_id()), + (BIDDER_2, usdt_fundings[1].1, AcceptedFundingAsset::USDT.to_statemint_id()), ], project_id, ); @@ -2937,11 +2601,7 @@ mod auction_round_failure { test_env.do_bid_transferred_statemint_asset_assertions( vec![ - ( - BIDDER_1, - usdt_fundings[0].1, - AcceptedFundingAsset::USDT.to_statemint_id(), - ), + (BIDDER_1, usdt_fundings[0].1, AcceptedFundingAsset::USDT.to_statemint_id()), (BIDDER_2, 0, AcceptedFundingAsset::USDT.to_statemint_id()), ], project_id, @@ -3019,10 +2679,7 @@ mod community_round_success { CommunityFundingProject::new_with(&test_env, metadata, issuer, evaluations, bids); const BOB: AccountId = 42; - let token_price = community_funding_project - .get_project_details() - .weighted_average_price - .unwrap(); + let token_price = community_funding_project.get_project_details().weighted_average_price.unwrap(); let contributions: TestContributions = vec![ TestContribution::new(BOB, 3 * ASSET_UNIT, None, AcceptedFundingAsset::USDT), TestContribution::new(BOB, 4 * ASSET_UNIT, None, AcceptedFundingAsset::USDT), @@ -3047,12 +2704,8 @@ mod community_round_success { .expect("The Buyer should be able to buy multiple times"); let project_id = community_funding_project.get_project_id(); - let bob_total_contributions: BalanceOf = community_funding_project.in_ext(|| { - Contributions::::get(project_id, BOB) - .iter() - .map(|c| c.funding_asset_amount) - .sum() - }); + let bob_total_contributions: BalanceOf = community_funding_project + .in_ext(|| Contributions::::get(project_id, BOB).iter().map(|c| c.funding_asset_amount).sum()); let total_contributed = calculate_contributed_funding_asset_spent(contributions.clone(), token_price) .iter() @@ -3074,21 +2727,13 @@ mod community_round_success { ); const BOB: AccountId = 808; - let remaining_ct = community_funding_project - .get_project_details() - .remaining_contribution_tokens; - let ct_price = community_funding_project - .get_project_details() - .weighted_average_price - .expect("CT Price should exist"); + let remaining_ct = community_funding_project.get_project_details().remaining_contribution_tokens; + let ct_price = + community_funding_project.get_project_details().weighted_average_price.expect("CT Price should exist"); let project_id = community_funding_project.get_project_id(); - let contributions: TestContributions = vec![TestContribution::new( - BOB, - remaining_ct, - None, - AcceptedFundingAsset::USDT, - )]; + let contributions: TestContributions = + vec![TestContribution::new(BOB, remaining_ct, None, AcceptedFundingAsset::USDT)]; let mut plmc_fundings: UserToPLMCBalance = calculate_contributed_plmc_spent(contributions.clone(), ct_price); plmc_fundings.push((BOB, get_ed())); let statemint_asset_fundings: UserToStatemintAsset = @@ -3104,18 +2749,13 @@ mod community_round_success { test_env.advance_time(2u64).unwrap(); // Check remaining CTs is 0 assert_eq!( - community_funding_project - .get_project_details() - .remaining_contribution_tokens, + community_funding_project.get_project_details().remaining_contribution_tokens, 0, "There are still remaining CTs" ); // Check project is in FundingEnded state - assert_eq!( - community_funding_project.get_project_details().status, - ProjectStatus::FundingSuccessful - ); + assert_eq!(community_funding_project.get_project_details().status, ProjectStatus::FundingSuccessful); test_env.do_free_plmc_assertions(vec![plmc_fundings[1].clone()]); test_env.do_free_statemint_asset_assertions(vec![(BOB, 0_u128, AcceptedFundingAsset::USDT.to_statemint_id())]); @@ -3139,14 +2779,10 @@ mod community_round_success { const BOB: AccountId = 808; const OVERBUY_CT: BalanceOf = 40 * ASSET_UNIT; - let remaining_ct = community_funding_project - .get_project_details() - .remaining_contribution_tokens; + let remaining_ct = community_funding_project.get_project_details().remaining_contribution_tokens; - let ct_price = community_funding_project - .get_project_details() - .weighted_average_price - .expect("CT Price should exist"); + let ct_price = + community_funding_project.get_project_details().weighted_average_price.expect("CT Price should exist"); let project_id = community_funding_project.get_project_id(); @@ -3170,26 +2806,20 @@ mod community_round_success { // Check remaining CTs is 0 assert_eq!( - community_funding_project - .get_project_details() - .remaining_contribution_tokens, + community_funding_project.get_project_details().remaining_contribution_tokens, 0, "There are still remaining CTs" ); // Check project is in FundingEnded state - assert_eq!( - community_funding_project.get_project_details().status, - ProjectStatus::FundingSuccessful - ); + assert_eq!(community_funding_project.get_project_details().status, ProjectStatus::FundingSuccessful); let reserved_plmc = plmc_fundings.swap_remove(0).1; let remaining_plmc: Balance = plmc_fundings.iter().fold(0_u128, |acc, (_, amount)| acc + amount); let actual_funding_transferred = statemint_asset_fundings.swap_remove(0).1; - let remaining_statemint_assets: Balance = statemint_asset_fundings - .iter() - .fold(0_u128, |acc, (_, amount, _)| acc + amount); + let remaining_statemint_assets: Balance = + statemint_asset_fundings.iter().fold(0_u128, |acc, (_, amount, _)| acc + amount); test_env.do_free_plmc_assertions(vec![(BOB, remaining_plmc)]); test_env.do_free_statemint_asset_assertions(vec![( @@ -3199,11 +2829,7 @@ mod community_round_success { )]); test_env.do_reserved_plmc_assertions(vec![(BOB, reserved_plmc)], LockType::Participation(project_id)); test_env.do_contribution_transferred_statemint_asset_assertions( - vec![( - BOB, - actual_funding_transferred, - AcceptedFundingAsset::USDT.to_statemint_id(), - )], + vec![(BOB, actual_funding_transferred, AcceptedFundingAsset::USDT.to_statemint_id())], community_funding_project.get_project_id(), ); } @@ -3263,19 +2889,12 @@ mod community_round_success { }); assert_eq!(plmc_bond_stored, sum_balance_mappings(vec![plmc_funding.clone()])); - assert_eq!( - statemint_asset_contributions_stored, - sum_statemint_mappings(vec![statemint_funding.clone()]) - ); + assert_eq!(statemint_asset_contributions_stored, sum_statemint_mappings(vec![statemint_funding.clone()])); let new_multiplier: Option> = None; let new_token_amount: BalanceOf = 2 * ASSET_UNIT; - let new_contribution: TestContributions = vec![TestContribution::new( - CONTRIBUTOR, - new_token_amount, - new_multiplier, - AcceptedFundingAsset::USDT, - )]; + let new_contribution: TestContributions = + vec![TestContribution::new(CONTRIBUTOR, new_token_amount, new_multiplier, AcceptedFundingAsset::USDT)]; let new_plmc_funding = calculate_contributed_plmc_spent(new_contribution.clone(), token_price); let new_statemint_funding = calculate_contributed_funding_asset_spent(new_contribution.clone(), token_price); @@ -3290,10 +2909,7 @@ mod community_round_success { let contributor_post_return_statemint_asset_balance = project.in_ext(|| ::FundingCurrency::balance(USDT_STATEMINT_ID, &CONTRIBUTOR)); - assert_eq!( - contributor_post_return_plmc_balance, - contributor_post_buy_plmc_balance + plmc_funding[0].1 - ); + assert_eq!(contributor_post_return_plmc_balance, contributor_post_buy_plmc_balance + plmc_funding[0].1); assert_eq!( contributor_post_return_statemint_asset_balance, contributor_post_buy_statemint_asset_balance + statemint_funding.clone()[0].1 @@ -3316,8 +2932,8 @@ mod community_round_success { assert_eq!( new_statemint_asset_contributions_stored, - statemint_asset_contributions_stored + sum_statemint_mappings(vec![new_statemint_funding.clone()]) - - statemint_funding[0].1 + statemint_asset_contributions_stored + sum_statemint_mappings(vec![new_statemint_funding.clone()]) - + statemint_funding[0].1 ); } @@ -3376,19 +2992,12 @@ mod community_round_success { }); assert_eq!(plmc_bond_stored, sum_balance_mappings(vec![plmc_funding.clone()])); - assert_eq!( - statemint_asset_contributions_stored, - sum_statemint_mappings(vec![statemint_funding.clone()]) - ); + assert_eq!(statemint_asset_contributions_stored, sum_statemint_mappings(vec![statemint_funding.clone()])); let new_multiplier: Option> = None; let new_token_amount: BalanceOf = 10 * ASSET_UNIT; - let new_contribution: TestContributions = vec![TestContribution::new( - CONTRIBUTOR, - new_token_amount, - new_multiplier, - AcceptedFundingAsset::USDT, - )]; + let new_contribution: TestContributions = + vec![TestContribution::new(CONTRIBUTOR, new_token_amount, new_multiplier, AcceptedFundingAsset::USDT)]; let new_plmc_funding = calculate_contributed_plmc_spent(new_contribution.clone(), token_price); let new_statemint_funding = calculate_contributed_funding_asset_spent(new_contribution.clone(), token_price); @@ -3403,10 +3012,7 @@ mod community_round_success { let contributor_post_return_statemint_asset_balance = project.in_ext(|| ::FundingCurrency::balance(USDT_STATEMINT_ID, &CONTRIBUTOR)); - assert_eq!( - contributor_post_return_plmc_balance, - contributor_post_buy_plmc_balance + plmc_funding[0].1 - ); + assert_eq!(contributor_post_return_plmc_balance, contributor_post_buy_plmc_balance + plmc_funding[0].1); assert_eq!( contributor_post_return_statemint_asset_balance, contributor_post_buy_statemint_asset_balance + statemint_funding.clone()[0].1 @@ -3429,8 +3035,8 @@ mod community_round_success { assert_eq!( new_statemint_asset_contributions_stored, - statemint_asset_contributions_stored + sum_statemint_mappings(vec![new_statemint_funding.clone()]) - - statemint_funding[0].1 + statemint_asset_contributions_stored + sum_statemint_mappings(vec![new_statemint_funding.clone()]) - + statemint_funding[0].1 ); } @@ -3442,29 +3048,19 @@ mod community_round_success { let mut evaluations = default_evaluations(); let evaluator_contributor = 69; let evaluation_amount = 420 * US_DOLLAR; - let contribution = TestContribution::new( - evaluator_contributor, - 600 * ASSET_UNIT, - None, - AcceptedFundingAsset::USDT, - ); + let contribution = + TestContribution::new(evaluator_contributor, 600 * ASSET_UNIT, None, AcceptedFundingAsset::USDT); evaluations.push((evaluator_contributor, evaluation_amount)); let bids = default_bids(); let contributing_project = CommunityFundingProject::new_with(&test_env, project, issuer, evaluations, bids); - let ct_price = contributing_project - .get_project_details() - .weighted_average_price - .unwrap(); + let ct_price = contributing_project.get_project_details().weighted_average_price.unwrap(); let already_bonded_plmc = calculate_evaluation_plmc_spent(vec![(evaluator_contributor, evaluation_amount)])[0].1; let necessary_plmc_for_bid = calculate_contributed_plmc_spent(vec![contribution], ct_price)[0].1; let necessary_usdt_for_bid = calculate_contributed_funding_asset_spent(vec![contribution], ct_price); - test_env.mint_plmc_to(vec![( - evaluator_contributor, - necessary_plmc_for_bid - already_bonded_plmc, - )]); + test_env.mint_plmc_to(vec![(evaluator_contributor, necessary_plmc_for_bid - already_bonded_plmc)]); test_env.mint_statemint_asset_to(necessary_usdt_for_bid); contributing_project.buy_for_retail_users(vec![contribution]).unwrap(); @@ -3478,12 +3074,8 @@ mod community_round_success { let mut evaluations = default_evaluations(); let bids = default_bids(); let evaluator_contributor = 69; - let overflow_contribution = TestContribution::new( - evaluator_contributor, - 600 * ASSET_UNIT, - None, - AcceptedFundingAsset::USDT, - ); + let overflow_contribution = + TestContribution::new(evaluator_contributor, 600 * ASSET_UNIT, None, AcceptedFundingAsset::USDT); let mut fill_contributions = Vec::new(); for _i in 0..::MaxContributionsPerUser::get() { @@ -3520,9 +3112,7 @@ mod community_round_success { test_env.mint_statemint_asset_to(fill_necessary_usdt); test_env.mint_statemint_asset_to(overflow_necessary_usdt); - community_funding_project - .buy_for_retail_users(fill_contributions) - .unwrap(); + community_funding_project.buy_for_retail_users(fill_contributions).unwrap(); let evaluation_bond = test_env.in_ext(|| { ::NativeCurrency::balance_on_hold( @@ -3532,13 +3122,11 @@ mod community_round_success { }); let post_fill_evaluation_bond = overflow_necessary_plmc[0].1 - FUNDED_DELTA_PLMC; assert!( - evaluation_bond < post_fill_evaluation_bond + 10_u128 - || evaluation_bond > post_fill_evaluation_bond - 10_u128 + evaluation_bond < post_fill_evaluation_bond + 10_u128 || + evaluation_bond > post_fill_evaluation_bond - 10_u128 ); - community_funding_project - .buy_for_retail_users(vec![overflow_contribution]) - .unwrap(); + community_funding_project.buy_for_retail_users(vec![overflow_contribution]).unwrap(); let evaluation_bond = test_env.in_ext(|| { ::NativeCurrency::balance_on_hold( &LockType::Evaluation(project_id), @@ -3581,35 +3169,23 @@ mod remainder_round_success { let community_contributions = default_community_buys(); let evaluator_contributor = 69; let evaluation_amount = 420 * US_DOLLAR; - let remainder_contribution = TestContribution::new( - evaluator_contributor, - 600 * ASSET_UNIT, - None, - AcceptedFundingAsset::USDT, - ); + let remainder_contribution = + TestContribution::new(evaluator_contributor, 600 * ASSET_UNIT, None, AcceptedFundingAsset::USDT); evaluations.push((evaluator_contributor, evaluation_amount)); let bids = default_bids(); let contributing_project = RemainderFundingProject::new_with(&test_env, project, issuer, evaluations, bids, community_contributions); - let ct_price = contributing_project - .get_project_details() - .weighted_average_price - .unwrap(); + let ct_price = contributing_project.get_project_details().weighted_average_price.unwrap(); let already_bonded_plmc = calculate_evaluation_plmc_spent(vec![(evaluator_contributor, evaluation_amount)])[0].1; let necessary_plmc_for_buy = calculate_contributed_plmc_spent(vec![remainder_contribution], ct_price)[0].1; let necessary_usdt_for_buy = calculate_contributed_funding_asset_spent(vec![remainder_contribution], ct_price); - test_env.mint_plmc_to(vec![( - evaluator_contributor, - necessary_plmc_for_buy - already_bonded_plmc, - )]); + test_env.mint_plmc_to(vec![(evaluator_contributor, necessary_plmc_for_buy - already_bonded_plmc)]); test_env.mint_statemint_asset_to(necessary_usdt_for_buy); - contributing_project - .buy_for_any_user(vec![remainder_contribution]) - .unwrap(); + contributing_project.buy_for_any_user(vec![remainder_contribution]).unwrap(); } #[test] @@ -3620,12 +3196,8 @@ mod remainder_round_success { let mut evaluations = default_evaluations(); let bids = default_bids(); let evaluator_contributor = 69; - let overflow_contribution = TestContribution::new( - evaluator_contributor, - 600 * ASSET_UNIT, - None, - AcceptedFundingAsset::USDT, - ); + let overflow_contribution = + TestContribution::new(evaluator_contributor, 600 * ASSET_UNIT, None, AcceptedFundingAsset::USDT); let mut fill_contributions = Vec::new(); for _i in 0..::MaxContributionsPerUser::get() { @@ -3673,13 +3245,11 @@ mod remainder_round_success { }); let post_fill_evaluation_bond = overflow_necessary_plmc[0].1 - FUNDED_DELTA_PLMC; assert!( - evaluation_bond < post_fill_evaluation_bond + 10_u128 - || evaluation_bond > post_fill_evaluation_bond - 10_u128 + evaluation_bond < post_fill_evaluation_bond + 10_u128 || + evaluation_bond > post_fill_evaluation_bond - 10_u128 ); - remainder_funding_project - .buy_for_any_user(vec![overflow_contribution]) - .unwrap(); + remainder_funding_project.buy_for_any_user(vec![overflow_contribution]).unwrap(); let evaluation_bond = test_env.in_ext(|| { ::NativeCurrency::balance_on_hold( &LockType::Evaluation(project_id), @@ -3702,21 +3272,13 @@ mod remainder_round_success { ); const BOB: AccountId = 808; - let remaining_ct = remainder_funding_project - .get_project_details() - .remaining_contribution_tokens; - let ct_price = remainder_funding_project - .get_project_details() - .weighted_average_price - .expect("CT Price should exist"); + let remaining_ct = remainder_funding_project.get_project_details().remaining_contribution_tokens; + let ct_price = + remainder_funding_project.get_project_details().weighted_average_price.expect("CT Price should exist"); let project_id = remainder_funding_project.get_project_id(); - let contributions: TestContributions = vec![TestContribution::new( - BOB, - remaining_ct, - None, - AcceptedFundingAsset::USDT, - )]; + let contributions: TestContributions = + vec![TestContribution::new(BOB, remaining_ct, None, AcceptedFundingAsset::USDT)]; let mut plmc_fundings: UserToPLMCBalance = calculate_contributed_plmc_spent(contributions.clone(), ct_price); plmc_fundings.push((BOB, get_ed())); let statemint_asset_fundings: UserToStatemintAsset = @@ -3733,18 +3295,13 @@ mod remainder_round_success { // Check remaining CTs is 0 assert_eq!( - remainder_funding_project - .get_project_details() - .remaining_contribution_tokens, + remainder_funding_project.get_project_details().remaining_contribution_tokens, 0, "There are still remaining CTs" ); // Check project is in FundingEnded state - assert_eq!( - remainder_funding_project.get_project_details().status, - ProjectStatus::FundingSuccessful - ); + assert_eq!(remainder_funding_project.get_project_details().status, ProjectStatus::FundingSuccessful); test_env.do_free_plmc_assertions(vec![plmc_fundings[1].clone()]); test_env.do_free_statemint_asset_assertions(vec![(BOB, 0_u128, AcceptedFundingAsset::USDT.to_statemint_id())]); @@ -3769,14 +3326,10 @@ mod remainder_round_success { const BOB: AccountId = 808; const OVERBUY_CT: BalanceOf = 40 * ASSET_UNIT; - let remaining_ct = remainder_funding_project - .get_project_details() - .remaining_contribution_tokens; + let remaining_ct = remainder_funding_project.get_project_details().remaining_contribution_tokens; - let ct_price = remainder_funding_project - .get_project_details() - .weighted_average_price - .expect("CT Price should exist"); + let ct_price = + remainder_funding_project.get_project_details().weighted_average_price.expect("CT Price should exist"); let project_id = remainder_funding_project.get_project_id(); @@ -3800,26 +3353,20 @@ mod remainder_round_success { // Check remaining CTs is 0 assert_eq!( - remainder_funding_project - .get_project_details() - .remaining_contribution_tokens, + remainder_funding_project.get_project_details().remaining_contribution_tokens, 0, "There are still remaining CTs" ); // Check project is in FundingEnded state - assert_eq!( - remainder_funding_project.get_project_details().status, - ProjectStatus::FundingSuccessful - ); + assert_eq!(remainder_funding_project.get_project_details().status, ProjectStatus::FundingSuccessful); let reserved_plmc = plmc_fundings.swap_remove(0).1; let remaining_plmc: Balance = plmc_fundings.iter().fold(0_u128, |acc, (_, amount)| acc + amount); let actual_funding_transferred = statemint_asset_fundings.swap_remove(0).1; - let remaining_statemint_assets: Balance = statemint_asset_fundings - .iter() - .fold(0_u128, |acc, (_, amount, _)| acc + amount); + let remaining_statemint_assets: Balance = + statemint_asset_fundings.iter().fold(0_u128, |acc, (_, amount, _)| acc + amount); test_env.do_free_plmc_assertions(vec![(BOB, remaining_plmc)]); test_env.do_free_statemint_asset_assertions(vec![( @@ -3829,11 +3376,7 @@ mod remainder_round_success { )]); test_env.do_reserved_plmc_assertions(vec![(BOB, reserved_plmc)], LockType::Participation(project_id)); test_env.do_contribution_transferred_statemint_asset_assertions( - vec![( - BOB, - actual_funding_transferred, - AcceptedFundingAsset::USDT.to_statemint_id(), - )], + vec![(BOB, actual_funding_transferred, AcceptedFundingAsset::USDT.to_statemint_id())], remainder_funding_project.get_project_id(), ); } @@ -4008,10 +3551,8 @@ mod bids_vesting { plmc_remainder_contribution_deposits.clone(), ]); - test_env.do_reserved_plmc_assertions( - total_plmc_participation_locked.clone(), - LockType::Participation(project_id), - ); + test_env + .do_reserved_plmc_assertions(total_plmc_participation_locked.clone(), LockType::Participation(project_id)); for (bidder, deposit) in plmc_bid_deposits { let bidder_participation_locked = total_plmc_participation_locked @@ -4306,11 +3847,7 @@ mod misc_features { FundingModule::remove_from_update_store(&69u32).unwrap(); let stored = ProjectsToUpdate::::iter_values().collect::>(); - assert_eq!( - stored[2], - vec![], - "Vector should be empty for that block after deletion" - ); + assert_eq!(stored[2], vec![], "Vector should be empty for that block after deletion"); }); } diff --git a/polimec-skeleton/pallets/funding/src/traits.rs b/polimec-skeleton/pallets/funding/src/traits.rs index c7c98f806..51a845b3b 100644 --- a/polimec-skeleton/pallets/funding/src/traits.rs +++ b/polimec-skeleton/pallets/funding/src/traits.rs @@ -19,5 +19,3 @@ pub trait DoRemainingOperation { fn do_one_operation(&mut self, project_id: T::ProjectIdentifier) -> Result; } - -pub use pallet_linear_release::traits::ReleaseSchedule; diff --git a/polimec-skeleton/pallets/funding/src/types.rs b/polimec-skeleton/pallets/funding/src/types.rs index 75e92f121..189e2a8ef 100644 --- a/polimec-skeleton/pallets/funding/src/types.rs +++ b/polimec-skeleton/pallets/funding/src/types.rs @@ -18,15 +18,14 @@ //! Types for Funding pallet. -use crate::traits::{BondingRequirementCalculation, ProvideStatemintPrice}; -use crate::BalanceOf; +use crate::{ + traits::{BondingRequirementCalculation, ProvideStatemintPrice}, + BalanceOf, +}; use frame_support::{pallet_prelude::*, traits::tokens::Balance as BalanceT}; -use sp_arithmetic::traits::Saturating; -use sp_arithmetic::{FixedPointNumber, FixedPointOperand}; +use sp_arithmetic::{traits::Saturating, FixedPointNumber, FixedPointOperand}; use sp_runtime::traits::CheckedDiv; -use sp_std::cmp::Eq; -use sp_std::collections::btree_map::*; -use sp_std::prelude::*; +use sp_std::{cmp::Eq, collections::btree_map::*, prelude::*}; pub use config_types::*; pub use inner_types::*; @@ -53,8 +52,9 @@ pub mod config_types { } } - /// Enum used to identify PLMC holds - #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen, Copy, Ord, PartialOrd)] + /// Enum used to identify PLMC holds. + /// It implements Serialize and Deserialize (only in the "std" feature set) to hold a fungible in the Genesis Configuration. + #[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo, Ord, PartialOrd)] #[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] pub enum LockType { Evaluation(ProjectId), @@ -109,7 +109,7 @@ pub mod storage_types { // TODO: PLMC-162. Perform a REAL validity check pub fn validity_check(&self) -> Result<(), ValidityError> { if self.minimum_price == Price::zero() { - return Err(ValidityError::PriceTooLow); + return Err(ValidityError::PriceTooLow) } self.ticket_size.is_valid()?; self.participants_size.is_valid()?; @@ -272,14 +272,10 @@ pub mod inner_types { impl TicketSize { pub(crate) fn is_valid(&self) -> Result<(), ValidityError> { if self.minimum.is_some() && self.maximum.is_some() { - return if self.minimum < self.maximum { - Ok(()) - } else { - Err(ValidityError::TicketSizeError) - }; + return if self.minimum < self.maximum { Ok(()) } else { Err(ValidityError::TicketSizeError) } } if self.minimum.is_some() || self.maximum.is_some() { - return Ok(()); + return Ok(()) } Err(ValidityError::TicketSizeError) @@ -294,20 +290,18 @@ pub mod inner_types { impl ParticipantsSize { pub(crate) fn is_valid(&self) -> Result<(), ValidityError> { match (self.minimum, self.maximum) { - (Some(min), Some(max)) => { + (Some(min), Some(max)) => if min < max && min > 0 && max > 0 { Ok(()) } else { Err(ValidityError::ParticipantsSizeError) - } - } - (Some(elem), None) | (None, Some(elem)) => { + }, + (Some(elem), None) | (None, Some(elem)) => if elem > 0 { Ok(()) } else { Err(ValidityError::ParticipantsSizeError) - } - } + }, (None, None) => Err(ValidityError::ParticipantsSizeError), } } @@ -385,6 +379,7 @@ pub mod inner_types { pub fn new(start: Option, end: Option) -> Self { Self { start, end } } + pub fn start(&self) -> Option { self.start } diff --git a/polimec-skeleton/pallets/linear-release/Cargo.toml b/polimec-skeleton/pallets/linear-release/Cargo.toml index f1b056962..7ec323169 100644 --- a/polimec-skeleton/pallets/linear-release/Cargo.toml +++ b/polimec-skeleton/pallets/linear-release/Cargo.toml @@ -13,7 +13,6 @@ readme = "README.md" targets = ["x86_64-unknown-linux-gnu"] [dependencies] -serde = { version = "1.0.136", optional = true } codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false } log = { version = "0.4.17", default-features = false } scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } @@ -21,11 +20,14 @@ frame-support = { git = "https://github.com/paritytech/substrate", default-featu frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +polimec-traits = { path = "../../traits", default-features = false } [dev-dependencies] sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42" } +pallet-funding = { path = "../funding", default-features = false } + [features] default = ["std"] @@ -38,6 +40,7 @@ std = [ "sp-runtime/std", "sp-std/std", "pallet-balances/std", - "serde" + "polimec-traits/std", + "pallet-funding/std" ] try-runtime = ["frame-support/try-runtime"] diff --git a/polimec-skeleton/pallets/linear-release/src/lib.rs b/polimec-skeleton/pallets/linear-release/src/lib.rs index 81bf33780..0ab4e401c 100644 --- a/polimec-skeleton/pallets/linear-release/src/lib.rs +++ b/polimec-skeleton/pallets/linear-release/src/lib.rs @@ -30,7 +30,7 @@ use frame_support::{ }; use frame_system::{pallet_prelude::*, WeightInfo}; -// use crate::types::LockType; +use polimec_traits::ReleaseSchedule; use scale_info::TypeInfo; use sp_runtime::{ traits::{AtLeast32BitUnsigned, Bounded, Convert, One, Saturating, Zero}, @@ -40,7 +40,6 @@ use sp_std::{marker::PhantomData, prelude::*}; // Re-export pallet items so that they can be accessed from the crate namespace. pub use pallet::*; -use traits::ReleaseSchedule; use types::VestingInfo; #[cfg(test)] @@ -49,7 +48,6 @@ mod mock; mod tests; mod impls; -pub mod traits; mod types; pub type BalanceOf = ::Balance; diff --git a/polimec-skeleton/pallets/linear-release/src/mock.rs b/polimec-skeleton/pallets/linear-release/src/mock.rs index 284d64733..bbaed490d 100644 --- a/polimec-skeleton/pallets/linear-release/src/mock.rs +++ b/polimec-skeleton/pallets/linear-release/src/mock.rs @@ -25,7 +25,8 @@ use sp_runtime::{ }; use super::*; -use crate::{self as pallet_vesting, types::LockType}; +use crate::{self as pallet_vesting}; +use pallet_funding::LockType; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; diff --git a/polimec-skeleton/pallets/linear-release/src/tests.rs b/polimec-skeleton/pallets/linear-release/src/tests.rs index 11e5f2d62..409de08f3 100644 --- a/polimec-skeleton/pallets/linear-release/src/tests.rs +++ b/polimec-skeleton/pallets/linear-release/src/tests.rs @@ -22,10 +22,8 @@ use sp_runtime::{ }; use super::{Vesting as VestingStorage, *}; -use crate::{ - mock::{Balances, ExtBuilder, System, Test, Vesting}, - types::LockType, -}; +use crate::mock::{Balances, ExtBuilder, System, Test, Vesting}; +use pallet_funding::LockType; /// A default existential deposit. const ED: u64 = 256; diff --git a/polimec-skeleton/runtime/build.rs b/polimec-skeleton/runtime/build.rs index 02d6973f2..2313c9d0d 100644 --- a/polimec-skeleton/runtime/build.rs +++ b/polimec-skeleton/runtime/build.rs @@ -1,10 +1,6 @@ #[cfg(feature = "std")] fn main() { - substrate_wasm_builder::WasmBuilder::new() - .with_current_project() - .export_heap_base() - .import_memory() - .build() + substrate_wasm_builder::WasmBuilder::new().with_current_project().export_heap_base().import_memory().build() } /// The wasm builder is deactivated when compiling diff --git a/polimec-skeleton/runtime/src/lib.rs b/polimec-skeleton/runtime/src/lib.rs index a8b19f9c6..e0f844981 100644 --- a/polimec-skeleton/runtime/src/lib.rs +++ b/polimec-skeleton/runtime/src/lib.rs @@ -29,7 +29,7 @@ pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, ConvertInto, BlakeTwo256, Block as BlockT}, + traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto}, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, FixedU128, Percent, }; @@ -123,6 +123,7 @@ pub type Executive = pub struct WeightToFee; impl WeightToFeePolynomial for WeightToFee { type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 MILLIUNIT: // in our template, we map to 1/10 of that, or 1/10 MILLIUNIT @@ -176,9 +177,7 @@ pub use parachains_common::MILLISECS_PER_BLOCK; pub use parachains_common::SLOT_DURATION; // Time is measured by number of blocks. -pub use parachains_common::DAYS; -pub use parachains_common::HOURS; -pub use parachains_common::MINUTES; +pub use parachains_common::{DAYS, HOURS, MINUTES}; /// We assume that ~5% of the block weight is consumed by `on_initialize` handlers. This is /// used to limit the maximal weight of a single extrinsic. @@ -194,10 +193,7 @@ pub use parachains_common::MAXIMUM_BLOCK_WEIGHT; /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { - NativeVersion { - runtime_version: VERSION, - can_author_with: Default::default(), - } + NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } } parameter_types! { @@ -233,66 +229,66 @@ parameter_types! { // Configure FRAME pallets to include in runtime. impl frame_system::Config for Runtime { + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; /// The identifier used to distinguish between accounts. type AccountId = PolimecAccountId; - /// The aggregated dispatch type that is available for extrinsics. - type RuntimeCall = RuntimeCall; - /// The lookup mechanism to get account ID from whatever is passed in dispatchers. - type Lookup = AccountIdLookup; - /// The index type for storing how many extrinsics an account has signed. - type Index = Index; + /// The basic call filter to use in dispatchable. + type BaseCallFilter = Everything; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + /// The maximum length of a block (in bytes). + type BlockLength = RuntimeBlockLength; /// The index type for blocks. type BlockNumber = BlockNumber; + /// Block & extrinsics weights: base values and limits. + type BlockWeights = RuntimeBlockWeights; + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; /// The type for hashing blocks and tries. type Hash = Hash; /// The hashing algorithm used. type Hashing = BlakeTwo256; /// The header type. type Header = generic::Header; + /// The index type for storing how many extrinsics an account has signed. + type Index = Index; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = AccountIdLookup; + type MaxConsumers = frame_support::traits::ConstU32<16>; + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); + /// What to do if a new account is created. + type OnNewAccount = (); + /// The action to take on a Runtime Upgrade + type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; + /// Converts a module to an index of this module in the runtime. + type PalletInfo = PalletInfo; + /// The aggregated dispatch type that is available for extrinsics. + type RuntimeCall = RuntimeCall; /// The ubiquitous event type. type RuntimeEvent = RuntimeEvent; /// The ubiquitous origin type. type RuntimeOrigin = RuntimeOrigin; - /// Maximum number of block number to block hash mappings to keep (oldest pruned first). - type BlockHashCount = BlockHashCount; - /// Runtime version. - type Version = Version; - /// Converts a module to an index of this module in the runtime. - type PalletInfo = PalletInfo; - /// The data to be stored in an account. - type AccountData = pallet_balances::AccountData; - /// What to do if a new account is created. - type OnNewAccount = (); - /// What to do if an account is fully reaped from the system. - type OnKilledAccount = (); - /// The weight of database operations that the runtime can invoke. - type DbWeight = RocksDbWeight; - /// The basic call filter to use in dispatchable. - type BaseCallFilter = Everything; - /// Weight information for the extrinsics of this pallet. - type SystemWeightInfo = (); - /// Block & extrinsics weights: base values and limits. - type BlockWeights = RuntimeBlockWeights; - /// The maximum length of a block (in bytes). - type BlockLength = RuntimeBlockLength; /// This is used as an identifier of the chain. 42 is the generic substrate prefix. type SS58Prefix = SS58Prefix; - /// The action to take on a Runtime Upgrade - type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; - type MaxConsumers = frame_support::traits::ConstU32<16>; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = (); + /// Runtime version. + type Version = Version; } impl pallet_timestamp::Config for Runtime { + type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; /// A timestamp: milliseconds since the unix epoch. type Moment = u64; type OnTimestampSet = Aura; - type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; type WeightInfo = (); } impl pallet_authorship::Config for Runtime { - type FindAuthor = pallet_session::FindAccountFromAuthorIndex; type EventHandler = (CollatorSelection,); + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; } parameter_types! { @@ -302,21 +298,21 @@ parameter_types! { } impl pallet_balances::Config for Runtime { + type AccountStore = System; /// The type for recording an account's balance. type Balance = Balance; type DustRemoval = (); - /// The ubiquitous event type. - type RuntimeEvent = RuntimeEvent; type ExistentialDeposit = ExistentialDeposit; - type AccountStore = System; - type WeightInfo = pallet_balances::weights::SubstrateWeight; + type FreezeIdentifier = (); + type HoldIdentifier = BondTypeOf; + type MaxFreezes = MaxReserves; + type MaxHolds = MaxLocks; type MaxLocks = MaxLocks; type MaxReserves = MaxReserves; type ReserveIdentifier = (); - type HoldIdentifier = BondTypeOf; - type FreezeIdentifier = (); - type MaxHolds = MaxLocks; - type MaxFreezes = MaxReserves; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_balances::weights::SubstrateWeight; } parameter_types! { @@ -325,12 +321,12 @@ parameter_types! { } impl pallet_transaction_payment::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; - type WeightToFee = WeightToFee; - type LengthToFee = ConstantMultiplier; type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type LengthToFee = ConstantMultiplier; + type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; type OperationalFeeMultiplier = ConstU8<5>; + type RuntimeEvent = RuntimeEvent; + type WeightToFee = WeightToFee; } parameter_types! { @@ -339,15 +335,15 @@ parameter_types! { } impl cumulus_pallet_parachain_system::Config for Runtime { - type RuntimeEvent = RuntimeEvent; + type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; + type DmpMessageHandler = DmpQueue; type OnSystemEvent = (); - type SelfParaId = parachain_info::Pallet; type OutboundXcmpMessageSource = XcmpQueue; - type DmpMessageHandler = DmpQueue; type ReservedDmpWeight = ReservedDmpWeight; - type XcmpMessageHandler = XcmpQueue; type ReservedXcmpWeight = ReservedXcmpWeight; - type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; + type RuntimeEvent = RuntimeEvent; + type SelfParaId = parachain_info::Pallet; + type XcmpMessageHandler = XcmpQueue; } impl parachain_info::Config for Runtime {} @@ -355,21 +351,21 @@ impl parachain_info::Config for Runtime {} impl cumulus_pallet_aura_ext::Config for Runtime {} impl cumulus_pallet_xcmp_queue::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type XcmExecutor = XcmExecutor; type ChannelInfo = ParachainSystem; - type VersionWrapper = (); - type ExecuteOverweightOrigin = EnsureRoot; type ControllerOrigin = EnsureRoot; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; - type WeightInfo = (); + type ExecuteOverweightOrigin = EnsureRoot; type PriceForSiblingDelivery = (); + type RuntimeEvent = RuntimeEvent; + type VersionWrapper = (); + type WeightInfo = (); + type XcmExecutor = XcmExecutor; } impl cumulus_pallet_dmp_queue::Config for Runtime { + type ExecuteOverweightOrigin = EnsureRoot; type RuntimeEvent = RuntimeEvent; type XcmExecutor = XcmExecutor; - type ExecuteOverweightOrigin = EnsureRoot; } parameter_types! { @@ -378,16 +374,16 @@ parameter_types! { } impl pallet_session::Config for Runtime { + type Keys = SessionKeys; + type NextSessionRotation = pallet_session::PeriodicSessions; type RuntimeEvent = RuntimeEvent; + // Essentially just Aura, but let's be pedantic. + type SessionHandler = ::KeyTypeIdProviders; + type SessionManager = CollatorSelection; + type ShouldEndSession = pallet_session::PeriodicSessions; type ValidatorId = ::AccountId; // we don't have stash and controller, thus we don't need the convert as well. type ValidatorIdOf = pallet_collator_selection::IdentityCollator; - type ShouldEndSession = pallet_session::PeriodicSessions; - type NextSessionRotation = pallet_session::PeriodicSessions; - type SessionManager = CollatorSelection; - // Essentially just Aura, but let's be pedantic. - type SessionHandler = ::KeyTypeIdProviders; - type Keys = SessionKeys; type WeightInfo = (); } @@ -412,15 +408,15 @@ pub type CollatorSelectionUpdateOrigin = EitherOfDiverse, EnsureXcm>>; impl pallet_collator_selection::Config for Runtime { - type RuntimeEvent = RuntimeEvent; type Currency = Balances; - type UpdateOrigin = CollatorSelectionUpdateOrigin; - type PotId = PotId; - type MaxCandidates = MaxCandidates; - type MinCandidates = MinCandidates; - type MaxInvulnerables = MaxInvulnerables; // should be a multiple of session or things will get inconsistent type KickThreshold = Period; + type MaxCandidates = MaxCandidates; + type MaxInvulnerables = MaxInvulnerables; + type MinCandidates = MinCandidates; + type PotId = PotId; + type RuntimeEvent = RuntimeEvent; + type UpdateOrigin = CollatorSelectionUpdateOrigin; type ValidatorId = ::AccountId; type ValidatorIdOf = pallet_collator_selection::IdentityCollator; type ValidatorRegistration = Session; @@ -465,49 +461,49 @@ use pallet_funding::BondTypeOf; pub use parachains_common::AssetIdForTrustBackedAssets as AssetId; impl pallet_assets::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Balance = Balance; - type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; + type ApprovalDeposit = ApprovalDeposit; + type AssetAccountDeposit = AssetAccountDeposit; + type AssetDeposit = AssetDeposit; type AssetId = AssetId; type AssetIdParameter = parity_scale_codec::Compact; - type Currency = Balances; + type Balance = Balance; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); + type CallbackHandle = (); type CreateOrigin = AsEnsureOriginWithArg>; + type Currency = Balances; + type Extra = (); type ForceOrigin = EnsureRoot; - type AssetDeposit = AssetDeposit; - type AssetAccountDeposit = AssetAccountDeposit; + type Freezer = (); type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type ApprovalDeposit = ApprovalDeposit; + type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; + type RuntimeEvent = RuntimeEvent; type StringLimit = AssetsStringLimit; - type Freezer = (); - type Extra = (); - type CallbackHandle = (); type WeightInfo = (); - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); } impl pallet_assets::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type Balance = Balance; - type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; + type ApprovalDeposit = ApprovalDeposit; + type AssetAccountDeposit = AssetAccountDeposit; + type AssetDeposit = AssetDeposit; type AssetId = AssetId; type AssetIdParameter = parity_scale_codec::Compact; - type Currency = Balances; + type Balance = Balance; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); + type CallbackHandle = (); type CreateOrigin = AsEnsureOriginWithArg>; + type Currency = Balances; + type Extra = (); type ForceOrigin = EnsureRoot; - type AssetDeposit = AssetDeposit; - type AssetAccountDeposit = AssetAccountDeposit; + type Freezer = (); type MetadataDepositBase = MetadataDepositBase; type MetadataDepositPerByte = MetadataDepositPerByte; - type ApprovalDeposit = ApprovalDeposit; + type RemoveItemsLimit = frame_support::traits::ConstU32<1000>; + type RuntimeEvent = RuntimeEvent; type StringLimit = AssetsStringLimit; - type Freezer = (); - type Extra = (); - type CallbackHandle = (); type WeightInfo = (); - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); } impl pallet_insecure_randomness_collective_flip::Config for Runtime {} @@ -571,38 +567,38 @@ parameter_types! { } impl pallet_funding::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type ProjectIdentifier = u32; - type Multiplier = pallet_funding::types::Multiplier; - type Balance = Balance; - type Price = FixedU128; - type NativeCurrency = Balances; - type FundingCurrency = StatemintAssets; - type ContributionTokenCurrency = LocalAssets; - type PriceProvider = pallet_funding::types::ConstPriceProvider; - type StorageItemId = u128; - type Randomness = Random; - type HandleMembers = Credentials; - type StringLimit = ConstU32<64>; - type PreImageLimit = ConstU32<1024>; - type EvaluationDuration = EvaluationDuration; type AuctionInitializePeriodDuration = AuctionInitializePeriodDuration; - type EnglishAuctionDuration = EnglishAuctionDuration; + type Balance = Balance; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); type CandleAuctionDuration = CandleAuctionDuration; type CommunityFundingDuration = CommunityFundingDuration; - type RemainderFundingDuration = RemainderFundingDuration; - type PalletId = FundingPalletId; - type MaxProjectsToUpdatePerBlock = ConstU32<100>; - type MaxEvaluationsPerUser = (); - type MaxBidsPerUser = ConstU32<256>; - type MaxContributionsPerUser = ConstU32<256>; + type ContributionTokenCurrency = LocalAssets; type ContributionVesting = ContributionVestingDuration; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); - type WeightInfo = (); - type FeeBrackets = FeeBrackets; + type EnglishAuctionDuration = EnglishAuctionDuration; + type EvaluationDuration = EvaluationDuration; type EvaluationSuccessThreshold = EarlyEvaluationThreshold; + type FeeBrackets = FeeBrackets; + type FundingCurrency = StatemintAssets; + type HandleMembers = Credentials; + type MaxBidsPerUser = ConstU32<256>; + type MaxContributionsPerUser = ConstU32<256>; + type MaxEvaluationsPerUser = (); + type MaxProjectsToUpdatePerBlock = ConstU32<100>; + type Multiplier = pallet_funding::types::Multiplier; + type NativeCurrency = Balances; + type PalletId = FundingPalletId; + type PreImageLimit = ConstU32<1024>; + type Price = FixedU128; + type PriceProvider = pallet_funding::types::ConstPriceProvider; + type ProjectIdentifier = u32; + type Randomness = Random; + type RemainderFundingDuration = RemainderFundingDuration; + type RuntimeEvent = RuntimeEvent; + type StorageItemId = u128; + type StringLimit = ConstU32<64>; type Vesting = Vesting; + type WeightInfo = (); } parameter_types! { @@ -625,14 +621,14 @@ impl pallet_linear_release::Config for Runtime { } impl pallet_credentials::Config for Runtime { - type RuntimeEvent = RuntimeEvent; type AddOrigin = EnsureRoot; + type MembershipChanged = (); + type MembershipInitialized = (); + type PrimeOrigin = EnsureRoot; type RemoveOrigin = EnsureRoot; - type SwapOrigin = EnsureRoot; type ResetOrigin = EnsureRoot; - type PrimeOrigin = EnsureRoot; - type MembershipInitialized = (); - type MembershipChanged = (); + type RuntimeEvent = RuntimeEvent; + type SwapOrigin = EnsureRoot; } // Create the runtime by composing the FRAME pallets that were previously configured. @@ -896,11 +892,11 @@ struct CheckInherents; impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { fn check_inherents( - block: &Block, relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, + block: &Block, + relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, ) -> sp_inherents::CheckInherentsResult { - let relay_chain_slot = relay_state_proof - .read_slot() - .expect("Could not read the relay chain slot from the proof"); + let relay_chain_slot = + relay_state_proof.read_slot().expect("Could not read the relay chain slot from the proof"); let inherent_data = cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( relay_chain_slot, diff --git a/polimec-skeleton/runtime/src/weights/block_weights.rs b/polimec-skeleton/runtime/src/weights/block_weights.rs index b2092d875..d87144b01 100644 --- a/polimec-skeleton/runtime/src/weights/block_weights.rs +++ b/polimec-skeleton/runtime/src/weights/block_weights.rs @@ -44,10 +44,7 @@ pub mod constants { "Weight should be at least 100 µs." ); // At most 50 ms. - assert!( - w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, - "Weight should be at most 50 ms." - ); + assert!(w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 50 ms."); } } } diff --git a/polimec-skeleton/runtime/src/weights/extrinsic_weights.rs b/polimec-skeleton/runtime/src/weights/extrinsic_weights.rs index 332c3b324..55b3706db 100644 --- a/polimec-skeleton/runtime/src/weights/extrinsic_weights.rs +++ b/polimec-skeleton/runtime/src/weights/extrinsic_weights.rs @@ -39,15 +39,9 @@ pub mod constants { let w = super::constants::ExtrinsicBaseWeight::get(); // At least 10 µs. - assert!( - w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, - "Weight should be at least 10 µs." - ); + assert!(w.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, "Weight should be at least 10 µs."); // At most 1 ms. - assert!( - w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, - "Weight should be at most 1 ms." - ); + assert!(w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, "Weight should be at most 1 ms."); } } } diff --git a/polimec-skeleton/runtime/src/xcm_config.rs b/polimec-skeleton/runtime/src/xcm_config.rs index 2b38bfda0..05cd6b869 100644 --- a/polimec-skeleton/runtime/src/xcm_config.rs +++ b/polimec-skeleton/runtime/src/xcm_config.rs @@ -122,19 +122,14 @@ pub struct NativeToFungible; impl Convert for NativeToFungible { fn convert(asset: MultiLocation) -> Result { match asset { - MultiLocation { - parents: 1, - interior: Here, - } => Ok(AssetIdPalletAssets::from(0u32)), + MultiLocation { parents: 1, interior: Here } => Ok(AssetIdPalletAssets::from(0u32)), _ => Err(asset), } } + fn reverse(value: AssetIdPalletAssets) -> Result { if value == AssetIdPalletAssets::from(0u32) { - Ok(MultiLocation { - parents: 1, - interior: Here, - }) + Ok(MultiLocation { parents: 1, interior: Here }) } else { Err(value) } @@ -251,23 +246,13 @@ impl ContainsPair for StatemintAssetsFilter { // location must be the statemint parachain let loc = MultiLocation::new(1, X1(Parachain(1000))); // asset must be either a fungible asset from `pallet_assets` or the native token of the relay chain - &loc == origin - && match asset { + &loc == origin && + match asset { MultiAsset { - id: - Concrete(MultiLocation { - parents: 0, - interior: X2(PalletInstance(50), GeneralIndex(_)), - }), - .. - } => true, - MultiAsset { - id: Concrete(MultiLocation { - parents: 1, - interior: Here, - }), + id: Concrete(MultiLocation { parents: 0, interior: X2(PalletInstance(50), GeneralIndex(_)) }), .. } => true, + MultiAsset { id: Concrete(MultiLocation { parents: 1, interior: Here }), .. } => true, _ => false, } @@ -277,8 +262,8 @@ impl ContainsPair for StatemintAssetsFilter { impl> ContainsPair for AssetsFrom { fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool { let loc = T::get(); - &loc == origin - && matches!(asset, MultiAsset { id: AssetId::Concrete(asset_loc), fun: Fungible(_a) } + &loc == origin && + matches!(asset, MultiAsset { id: AssetId::Concrete(asset_loc), fun: Fungible(_a) } if asset_loc.match_and_split(&loc).is_some()) } } @@ -344,7 +329,7 @@ impl ContainsPair for MultiNativeAsset { fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool { if let Some(ref reserve) = asset.reserve() { if reserve == origin { - return true; + return true } } false @@ -365,35 +350,35 @@ pub type Reserves = (NativeAsset, StatemintAssetsFilter); pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { - type RuntimeCall = RuntimeCall; - type XcmSender = XcmRouter; + type AssetClaims = PolkadotXcm; + type AssetExchanger = (); + type AssetLocker = (); // How to withdraw and deposit an asset. type AssetTransactor = AssetTransactors; - type OriginConverter = XcmOriginToTransactDispatchOrigin; + type AssetTrap = PolkadotXcm; + type Barrier = Barrier; + type CallDispatcher = RuntimeCall; + type FeeManager = (); type IsReserve = Reserves; type IsTeleporter = NativeAsset; - type UniversalLocation = UniversalLocation; - type Barrier = Barrier; - type Weigher = FixedWeightBounds; + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type MessageExporter = (); + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type PalletInstancesInfo = AllPalletsWithSystem; + type ResponseHandler = PolkadotXcm; + type RuntimeCall = RuntimeCall; + // TODO: Restrict this to a subset of allowed `RuntimeCall`. + type SafeCallFilter = Everything; + type SubscriptionService = PolkadotXcm; type Trader = ( // TODO: weight to fee has to be carefully considered. For now use default UsingComponents>, FixedRateOfFungible, ); - type ResponseHandler = PolkadotXcm; - type AssetTrap = PolkadotXcm; - type AssetClaims = PolkadotXcm; - type SubscriptionService = PolkadotXcm; - type PalletInstancesInfo = AllPalletsWithSystem; - type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type AssetLocker = (); - type AssetExchanger = (); - type FeeManager = (); - type MessageExporter = (); type UniversalAliases = Nothing; - type CallDispatcher = RuntimeCall; - // TODO: Restrict this to a subset of allowed `RuntimeCall`. - type SafeCallFilter = Everything; + type UniversalLocation = UniversalLocation; + type Weigher = FixedWeightBounds; + type XcmSender = XcmRouter; } /// No local origins on this chain are allowed to dispatch XCM sends/executions. @@ -414,34 +399,34 @@ parameter_types! { } impl pallet_xcm::Config for Runtime { - type RuntimeEvent = RuntimeEvent; + type AdminOrigin = EnsureRoot; + // ^ Override for AdvertisedXcmVersion default + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; type Currency = Balances; type CurrencyMatcher = (); - type SendXcmOrigin = EnsureXcmOrigin; - type XcmRouter = XcmRouter; type ExecuteXcmOrigin = EnsureXcmOrigin; + type MaxLockers = ConstU32<8>; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type SendXcmOrigin = EnsureXcmOrigin; + type SovereignAccountOf = LocationToAccountId; + type TrustedLockers = (); + type UniversalLocation = UniversalLocation; + type Weigher = FixedWeightBounds; + type WeightInfo = pallet_xcm::TestWeightInfo; // TODO: change back to `Nothing` once we add the xcm functionalities into a pallet type XcmExecuteFilter = Everything; // ^ Disable dispatchable execute on the XCM pallet. // Needs to be `Everything` for local testing. type XcmExecutor = XcmExecutor; - type XcmTeleportFilter = Everything; type XcmReserveTransferFilter = Everything; - type Weigher = FixedWeightBounds; - type UniversalLocation = UniversalLocation; + type XcmRouter = XcmRouter; + type XcmTeleportFilter = Everything; - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; - // ^ Override for AdvertisedXcmVersion default - type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; - type TrustedLockers = (); - type SovereignAccountOf = LocationToAccountId; - type MaxLockers = ConstU32<8>; - type WeightInfo = pallet_xcm::TestWeightInfo; - type AdminOrigin = EnsureRoot; - #[cfg(feature = "runtime-benchmarks")] - type ReachableDest = ReachableDest; } impl cumulus_pallet_xcm::Config for Runtime { From c9f89c921da63a95352bed0f7cfb3ebc01420468 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Mon, 24 Jul 2023 13:05:13 +0200 Subject: [PATCH 76/80] feat: move the ReleaseSchedule trait outside of the pallet --- .../pallets/linear-release/src/traits.rs | 82 ------------------ .../pallets/linear-release/src/types.rs | 8 -- polimec-skeleton/traits/src/lib.rs | 83 ++++++++++++++++--- 3 files changed, 73 insertions(+), 100 deletions(-) delete mode 100644 polimec-skeleton/pallets/linear-release/src/traits.rs diff --git a/polimec-skeleton/pallets/linear-release/src/traits.rs b/polimec-skeleton/pallets/linear-release/src/traits.rs deleted file mode 100644 index 9a55a861d..000000000 --- a/polimec-skeleton/pallets/linear-release/src/traits.rs +++ /dev/null @@ -1,82 +0,0 @@ -// Polimec Blockchain – https://www.polimec.org/ -// Copyright (C) Polimec 2022. All rights reserved. - -// The Polimec Blockchain 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. - -// The Polimec Blockchain 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 this program. If not, see . - -use frame_support::{pallet_prelude::DispatchResult, traits::tokens::fungible}; - -/// A release schedule over a fungible. This allows a particular fungible to have release limits -/// applied to it. -pub trait ReleaseSchedule { - /// The quantity used to denote time; usually just a `BlockNumber`. - type Moment; - - /// The currency that this schedule applies to. - type Currency: fungible::InspectHold - + fungible::MutateHold - + fungible::BalancedHold; - - /// Get the amount that is currently being vested and cannot be transferred out of this account. - /// Returns `None` if the account has no vesting schedule. - fn vesting_balance( - who: &AccountId, - reason: Reason, - ) -> Option<>::Balance>; - - /// Adds a release schedule to a given account. - /// - /// If the account has `MaxVestingSchedules`, an Error is returned and nothing - /// is updated. - /// - /// Is a no-op if the amount to be vested is zero. - /// - /// NOTE: This doesn't alter the free balance of the account. - fn add_release_schedule( - who: &AccountId, - locked: >::Balance, - per_block: >::Balance, - starting_block: Self::Moment, - reason: Reason, - ) -> DispatchResult; - - /// Set a release schedule to a given account, without locking any funds. - /// - /// If the account has `MaxVestingSchedules`, an Error is returned and nothing - /// is updated. - /// - /// Is a no-op if the amount to be vested is zero. - /// - /// NOTE: This doesn't alter the free balance of the account. - fn set_release_schedule( - who: &AccountId, - locked: >::Balance, - per_block: >::Balance, - starting_block: Self::Moment, - reason: Reason, - ) -> DispatchResult; - - /// Checks if `add_release_schedule` would work against `who`. - fn can_add_release_schedule( - who: &AccountId, - locked: >::Balance, - per_block: >::Balance, - starting_block: Self::Moment, - reason: Reason, - ) -> DispatchResult; - - /// Remove a release schedule for a given account. - /// - /// NOTE: This doesn't alter the free balance of the account. - fn remove_vesting_schedule(who: &AccountId, schedule_index: u32, reason: Reason) -> DispatchResult; -} diff --git a/polimec-skeleton/pallets/linear-release/src/types.rs b/polimec-skeleton/pallets/linear-release/src/types.rs index 2dca76d99..eb2016040 100644 --- a/polimec-skeleton/pallets/linear-release/src/types.rs +++ b/polimec-skeleton/pallets/linear-release/src/types.rs @@ -16,14 +16,6 @@ use super::*; -/// Enum used to identify PLMC holds -#[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo, Ord, PartialOrd)] -#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] -pub enum LockType { - Evaluation(ProjectId), - Participation(ProjectId), -} - /// Struct to encode the vesting schedule of an individual account. #[derive(Encode, Decode, Copy, Clone, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)] pub struct VestingInfo { diff --git a/polimec-skeleton/traits/src/lib.rs b/polimec-skeleton/traits/src/lib.rs index ab2269e92..1944005fd 100644 --- a/polimec-skeleton/traits/src/lib.rs +++ b/polimec-skeleton/traits/src/lib.rs @@ -16,11 +16,11 @@ #![cfg_attr(not(feature = "std"), no_std)] +// TODO: To be removed after "The Merge" + +// --> use core::slice::Iter; -use frame_support::{ - pallet_prelude::{Decode, DispatchError, Encode, MaxEncodedLen, TypeInfo}, - BoundedVec, RuntimeDebug, -}; +use frame_support::{pallet_prelude::*, traits::tokens::fungible, BoundedVec, RuntimeDebug}; use serde::{Deserialize, Serialize}; use sp_std::vec::Vec; @@ -35,12 +35,8 @@ pub enum MemberRole { impl MemberRole { pub fn iterator() -> Iter<'static, MemberRole> { - static ROLES: [MemberRole; 4] = [ - MemberRole::Issuer, - MemberRole::Retail, - MemberRole::Professional, - MemberRole::Institutional, - ]; + static ROLES: [MemberRole; 4] = + [MemberRole::Issuer, MemberRole::Retail, MemberRole::Professional, MemberRole::Institutional]; ROLES.iter() } } @@ -81,3 +77,70 @@ pub trait PolimecMembers { fn get_members_of(role: &MemberRole) -> Vec; fn get_roles_of(who: &AccountId) -> Vec; } + +// <-- + +/// A release schedule over a fungible. This allows a particular fungible to have release limits +/// applied to it. +pub trait ReleaseSchedule { + /// The quantity used to denote time; usually just a `BlockNumber`. + type Moment; + + /// The currency that this schedule applies to. + type Currency: fungible::InspectHold + + fungible::MutateHold + + fungible::BalancedHold; + + /// Get the amount that is currently being vested and cannot be transferred out of this account. + /// Returns `None` if the account has no vesting schedule. + fn vesting_balance( + who: &AccountId, + reason: Reason, + ) -> Option<>::Balance>; + + /// Adds a release schedule to a given account. + /// + /// If the account has `MaxVestingSchedules`, an Error is returned and nothing + /// is updated. + /// + /// Is a no-op if the amount to be vested is zero. + /// + /// NOTE: This doesn't alter the free balance of the account. + fn add_release_schedule( + who: &AccountId, + locked: >::Balance, + per_block: >::Balance, + starting_block: Self::Moment, + reason: Reason, + ) -> DispatchResult; + + /// Set a release schedule to a given account, without locking any funds. + /// + /// If the account has `MaxVestingSchedules`, an Error is returned and nothing + /// is updated. + /// + /// Is a no-op if the amount to be vested is zero. + /// + /// NOTE: This doesn't alter the free balance of the account. + fn set_release_schedule( + who: &AccountId, + locked: >::Balance, + per_block: >::Balance, + starting_block: Self::Moment, + reason: Reason, + ) -> DispatchResult; + + /// Checks if `add_release_schedule` would work against `who`. + fn can_add_release_schedule( + who: &AccountId, + locked: >::Balance, + per_block: >::Balance, + starting_block: Self::Moment, + reason: Reason, + ) -> DispatchResult; + + /// Remove a release schedule for a given account. + /// + /// NOTE: This doesn't alter the free balance of the account. + fn remove_vesting_schedule(who: &AccountId, schedule_index: u32, reason: Reason) -> DispatchResult; +} From ff1432f353ac4e1f9c94ffcd33087e7cf0e07f0c Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Mon, 24 Jul 2023 13:06:18 +0200 Subject: [PATCH 77/80] doc: remove "\" --- polimec-skeleton/pallets/linear-release/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/src/lib.rs b/polimec-skeleton/pallets/linear-release/src/lib.rs index 0ab4e401c..d517aebec 100644 --- a/polimec-skeleton/pallets/linear-release/src/lib.rs +++ b/polimec-skeleton/pallets/linear-release/src/lib.rs @@ -208,11 +208,11 @@ pub mod pallet { account: T::AccountId, unvested: BalanceOf, }, - /// An \[account\] has become fully vested. + /// An `account` has become fully vested. VestingCompleted { account: T::AccountId, }, - // An \[account\] has reveived a vested transfer of \[amount\]. + // An `account` has reveived a vested transfer of `amount`. VestingTransferred { to: T::AccountId, amount: BalanceOf, From a53332aa5a4b12ea22014c349e35ae7b0c42e07f Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Mon, 24 Jul 2023 13:50:52 +0200 Subject: [PATCH 78/80] doc: add a TODO to a possible future improvement --- polimec-skeleton/pallets/linear-release/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/polimec-skeleton/pallets/linear-release/src/lib.rs b/polimec-skeleton/pallets/linear-release/src/lib.rs index d517aebec..f20c34149 100644 --- a/polimec-skeleton/pallets/linear-release/src/lib.rs +++ b/polimec-skeleton/pallets/linear-release/src/lib.rs @@ -50,6 +50,11 @@ mod tests; mod impls; mod types; + +// TODO: Find a way to use +// 1. type BalanceOf = <::Currency as fungible::Inspect<::AccountId>>::Balance; +// 2. type ReasonOf = <::Currency as InspectHold<::AccountId>>::Reason; +// So we can remove the `Balance` and the `Reason` type from the pallet's config. pub type BalanceOf = ::Balance; pub type ReasonOf = ::Reason; pub type AccountIdOf = ::AccountId; From 729f6e269a8e1198dde17473ec71c5c2d81bb8c9 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Mon, 24 Jul 2023 14:00:38 +0200 Subject: [PATCH 79/80] doc: README revamp --- .../pallets/linear-release/README.md | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/README.md b/polimec-skeleton/pallets/linear-release/README.md index 4c9ee8862..7ee3f02d3 100644 --- a/polimec-skeleton/pallets/linear-release/README.md +++ b/polimec-skeleton/pallets/linear-release/README.md @@ -1,11 +1,21 @@ -# Dev Mode Example Pallet +# Pallet Linear Release -A simple example of a FRAME pallet demonstrating -the ease of requirements for a pallet in dev mode. +A modified version of [pallet-vesting](https://github.com/paritytech/substrate/tree/polkadot-v0.9.42/frame/vesting/src). It allows to set a Release Schedule using the new `fungible::Hold` API instead of the old and deprecated `LockableCurrency`. -Run `cargo doc --package pallet-dev-mode --open` to view this pallet's documentation. +It implements the new `ReleaseSchedule` trait. The trait serves to apply release limits to a particular fungible and provides several key methods to interact with the release schedule for an account. -**Dev mode is not meant to be used in production.** +Key features of the `ReleaseSchedule` trait include: -License: MIT-0 +- `vesting_balance`: This method returns the amount that is currently being vested and cannot be transferred out of an account. It returns None if the account has no vesting schedule. +- `add_release_schedule`: This method allows a release schedule to be added to a given account. If the account has reached the MaxVestingSchedules, an error is returned and nothing is updated. It's a no-op if the amount to be vested is zero. Importantly, this doesn't alter the free balance of the account. +- `set_release_schedule`: This method sets a release schedule for a given account, without locking any funds. Similar to the add_release_schedule, it returns an error if the account has MaxVestingSchedules and doesn't alter the free balance of the account. +- `can_add_release_schedule`: This method checks if a release schedule can be added to a given account. +- `remove_vesting_schedule`: This method allows for a vesting schedule to be removed from a given account. Note, this does not alter the free balance of the account. + +The main differences with pallet_vesting are: + +- Use of `fungible::Hold` instead of `LockableCurrency`, this change enable a more granular control. +- Add `set_release_schedule` to set a `ReleaseSchedule` without locking the fungible in the same transaction. + +Here you can find a diff with the original pallet-vesting: https://gist.github.com/lrazovic/04efb94ecc19f08e80ac6eff48a8adb0 \ No newline at end of file From 435210a45225771f916ed25ce77794dd507b8342 Mon Sep 17 00:00:00 2001 From: Leonardo Razovic <4128940+lrazovic@users.noreply.github.com> Date: Mon, 24 Jul 2023 14:06:00 +0200 Subject: [PATCH 80/80] docs: fix markdown --- polimec-skeleton/pallets/linear-release/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/polimec-skeleton/pallets/linear-release/README.md b/polimec-skeleton/pallets/linear-release/README.md index 7ee3f02d3..8e3b366ec 100644 --- a/polimec-skeleton/pallets/linear-release/README.md +++ b/polimec-skeleton/pallets/linear-release/README.md @@ -8,8 +8,8 @@ It implements the new `ReleaseSchedule` trait. The trait serves to apply release Key features of the `ReleaseSchedule` trait include: - `vesting_balance`: This method returns the amount that is currently being vested and cannot be transferred out of an account. It returns None if the account has no vesting schedule. -- `add_release_schedule`: This method allows a release schedule to be added to a given account. If the account has reached the MaxVestingSchedules, an error is returned and nothing is updated. It's a no-op if the amount to be vested is zero. Importantly, this doesn't alter the free balance of the account. -- `set_release_schedule`: This method sets a release schedule for a given account, without locking any funds. Similar to the add_release_schedule, it returns an error if the account has MaxVestingSchedules and doesn't alter the free balance of the account. +- `add_release_schedule`: This method allows a release schedule to be added to a given account. If the account has reached the MaxVestingSchedules, an error is returned and nothing is updated. It's a no-op if the amount to be vested is zero. +- `set_release_schedule`: This method sets a release schedule for a given account, without locking any funds. Similar to the `add_release_schedule`, it returns an error if the account has `MaxVestingSchedules` and doesn't alter the free balance of the account. - `can_add_release_schedule`: This method checks if a release schedule can be added to a given account. - `remove_vesting_schedule`: This method allows for a vesting schedule to be removed from a given account. Note, this does not alter the free balance of the account.