diff --git a/Cargo.lock b/Cargo.lock index 5df5f8698..67e43278d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3066,7 +3066,6 @@ dependencies = [ "frame-support", "frame-system", "log", - "pallet-assets", "pallet-authorship", "pallet-balances", "pallet-session", diff --git a/pallet/account-migration/src/benchmarking.rs b/pallet/account-migration/src/benchmarking.rs index f0af9f29c..f92f845aa 100644 --- a/pallet/account-migration/src/benchmarking.rs +++ b/pallet/account-migration/src/benchmarking.rs @@ -114,9 +114,8 @@ mod benchmarks { ); >::insert( from, - Ledger { + OldLedger { staked_ring: 1, - staked_kton: 1, staked_deposits: BoundedVec::truncate_from(vec![ Default::default(); ::MaxDeposits::get() @@ -130,15 +129,7 @@ mod benchmarks { ::MaxUnstakings::get() as usize ]), - unstaking_kton: BoundedVec::truncate_from(vec![ - ( - Default::default(), - Default::default() - ); - ::MaxUnstakings::get() - as usize - ]), - unstaking_deposits: Default::default(), + ..Default::default() }, ); } diff --git a/pallet/account-migration/src/lib.rs b/pallet/account-migration/src/lib.rs index a207efc46..db70bcfda 100644 --- a/pallet/account-migration/src/lib.rs +++ b/pallet/account-migration/src/lib.rs @@ -57,7 +57,7 @@ pub use weights::WeightInfo; // darwinia use darwinia_deposit::Deposit; -use darwinia_staking::Ledger; +use darwinia_staking::{migration::v2::OldLedger, Ledger}; use dc_primitives::{AccountId as AccountId20, AssetId, Balance, Nonce}; // substrate use frame_support::{ @@ -66,7 +66,7 @@ use frame_support::{ traits::{Currency, ExistenceRequirement::AllowDeath}, StorageHasher, }; -use frame_system::{pallet_prelude::*, AccountInfo, RawOrigin}; +use frame_system::{pallet_prelude::*, AccountInfo}; use pallet_balances::AccountData; use pallet_identity::{Judgement, Registration}; use sp_core::{ @@ -175,10 +175,10 @@ pub mod pallet { Registration, ConstU32<100>>, >; - /// [`darwinia_staking::Ledgers`] data. + /// [`darwinia_staking::migration::v2::OldLedger`] data. #[pallet::storage] #[pallet::getter(fn ledger_of)] - pub type Ledgers = StorageMap<_, Blake2_128Concat, AccountId32, Ledger>; + pub type Ledgers = StorageMap<_, Blake2_128Concat, AccountId32, OldLedger>; /// Multisig migration caches. #[pallet::storage] @@ -480,7 +480,6 @@ pub mod pallet { let now = >::block_number(); l.unstaking_ring.retain(|(_, t)| t > &now); - l.unstaking_kton.retain(|(_, t)| t > &now); let staking_pot = darwinia_staking::account_id(); let r = l.staked_ring + l.unstaking_ring.iter().map(|(r, _)| r).sum::(); @@ -497,21 +496,15 @@ pub mod pallet { )?; } - let k = l.staked_kton + l.unstaking_kton.iter().map(|(k, _)| k).sum::(); - - // To calculated the worst case in benchmark. - debug_assert!(k > 0); - - if k != 0 { - >::transfer( - RawOrigin::Signed(*to).into(), - KTON_ID.into(), - staking_pot, - k, - )?; - } - - >::insert(to, l); + >::insert( + to, + Ledger { + staked_ring: l.staked_ring, + staked_deposits: l.staked_deposits, + unstaking_ring: l.unstaking_ring, + unstaking_deposits: l.unstaking_deposits, + }, + ); } Ok(()) diff --git a/pallet/account-migration/src/mock.rs b/pallet/account-migration/src/mock.rs index bd9115f0b..b2b6df46e 100644 --- a/pallet/account-migration/src/mock.rs +++ b/pallet/account-migration/src/mock.rs @@ -168,7 +168,6 @@ impl darwinia_staking::Config for Runtime { type KtonStakerNotifier = (); type MaxDeposits = (); type MaxUnstakings = (); - type MigrationCurve = (); type MinStakingDuration = (); type Ring = Dummy; type RuntimeEvent = RuntimeEvent; diff --git a/pallet/staking/Cargo.toml b/pallet/staking/Cargo.toml index 377ae2bdd..54b649825 100644 --- a/pallet/staking/Cargo.toml +++ b/pallet/staking/Cargo.toml @@ -41,7 +41,6 @@ darwinia-deposit = { workspace = true, features = ["std"] } # substrate dc-inflation = { workspace = true, features = ["std"] } -pallet-assets = { workspace = true, features = ["std"] } pallet-balances = { workspace = true, features = ["std"] } pallet-session = { workspace = true, features = ["std"] } pallet-timestamp = { workspace = true, features = ["std"] } @@ -88,7 +87,6 @@ runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", - "pallet-assets/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] diff --git a/pallet/staking/src/benchmarking.rs b/pallet/staking/src/benchmarking.rs index 05dd0c184..4e604c122 100644 --- a/pallet/staking/src/benchmarking.rs +++ b/pallet/staking/src/benchmarking.rs @@ -64,7 +64,7 @@ mod benchmarks { // // The total number of deposit items has reached `Config::MaxUnstakings`. #[extrinsic_call] - _(RawOrigin::Signed(a), UNIT, UNIT, deposits); + _(RawOrigin::Signed(a), UNIT, deposits); } #[benchmark] @@ -77,14 +77,13 @@ mod benchmarks { let deposits = deposit_for::(&a, x); - >::stake(RawOrigin::Signed(a.clone()).into(), UNIT, UNIT, deposits.clone()) - .unwrap(); + >::stake(RawOrigin::Signed(a.clone()).into(), UNIT, deposits.clone()).unwrap(); // Worst-case scenario: // // The total number of deposit items has reached `Config::MaxUnstakings`. #[extrinsic_call] - _(RawOrigin::Signed(a), UNIT, UNIT, deposits); + _(RawOrigin::Signed(a), UNIT, deposits); } #[benchmark] @@ -97,10 +96,8 @@ mod benchmarks { let deposits = deposit_for::(&a, x); - >::stake(RawOrigin::Signed(a.clone()).into(), UNIT, UNIT, deposits.clone()) - .unwrap(); - >::unstake(RawOrigin::Signed(a.clone()).into(), UNIT, UNIT, deposits.clone()) - .unwrap(); + >::stake(RawOrigin::Signed(a.clone()).into(), UNIT, deposits.clone()).unwrap(); + >::unstake(RawOrigin::Signed(a.clone()).into(), UNIT, deposits.clone()).unwrap(); // Worst-case scenario: // @@ -119,9 +116,8 @@ mod benchmarks { let deposits = deposit_for::(&a, ::MaxUnstakings::get()); - >::stake(RawOrigin::Signed(a.clone()).into(), UNIT, UNIT, deposits.clone()) - .unwrap(); - >::unstake(RawOrigin::Signed(a.clone()).into(), UNIT, UNIT, deposits).unwrap(); + >::stake(RawOrigin::Signed(a.clone()).into(), UNIT, deposits.clone()).unwrap(); + >::unstake(RawOrigin::Signed(a.clone()).into(), UNIT, deposits).unwrap(); >::set_block_number( >::block_number() + T::MinStakingDuration::get(), @@ -158,13 +154,7 @@ mod benchmarks { // Remove `+ 1` after https://github.com/paritytech/substrate/pull/13655. ::Ring::make_free_balance_be(&a, UNIT + 1); - >::stake( - RawOrigin::Signed(a.clone()).into(), - UNIT, - Default::default(), - Default::default(), - ) - .unwrap(); + >::stake(RawOrigin::Signed(a.clone()).into(), UNIT, Default::default()).unwrap(); >::collect(RawOrigin::Signed(a.clone()).into(), Default::default()).unwrap(); // Worst-case scenario: @@ -181,13 +171,7 @@ mod benchmarks { // Remove `+ 1` after https://github.com/paritytech/substrate/pull/13655. ::Ring::make_free_balance_be(&a, UNIT + 1); - >::stake( - RawOrigin::Signed(a.clone()).into(), - UNIT, - Default::default(), - Default::default(), - ) - .unwrap(); + >::stake(RawOrigin::Signed(a.clone()).into(), UNIT, Default::default()).unwrap(); >::collect(RawOrigin::Signed(a.clone()).into(), Default::default()).unwrap(); >::nominate(RawOrigin::Signed(a.clone()).into(), a.clone()).unwrap(); diff --git a/pallet/staking/src/lib.rs b/pallet/staking/src/lib.rs index e93b4c817..89de74106 100644 --- a/pallet/staking/src/lib.rs +++ b/pallet/staking/src/lib.rs @@ -25,7 +25,6 @@ //! //! ### Acceptable stakes: //! - RING: Darwinia's native token -//! - KTON: Darwinia's commitment token //! - Deposit: Locking RINGs' ticket #![cfg_attr(not(feature = "std"), no_std)] @@ -47,8 +46,6 @@ pub use weights::WeightInfo; pub use darwinia_staking_traits::*; -// core -use core::mem; // crates.io use codec::FullCodec; use ethabi::{Function, Param, ParamType, StateMutability, Token}; @@ -64,7 +61,7 @@ use frame_system::{pallet_prelude::*, RawOrigin}; use sp_core::{H160, U256}; use sp_runtime::{ traits::{AccountIdConversion, Convert, One, Zero}, - Perbill, Perquintill, + Perbill, }; use sp_std::{collections::btree_map::BTreeMap, prelude::*}; @@ -102,7 +99,7 @@ pub mod pallet { #[cfg(feature = "runtime-benchmarks")] use darwinia_deposit::Config as DepositConfig; - const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); + const STORAGE_VERSION: StorageVersion = StorageVersion::new(2); /// Empty trait acts as a place holder to satisfy the `#[pallet::config]` macro. #[cfg(not(feature = "runtime-benchmarks"))] @@ -119,6 +116,7 @@ pub mod pallet { /// RING [`Stake`] interface. type Ring: Stake; + // TODO: Remove after the migration. /// KTON [`Stake`] interface. type Kton: Stake; @@ -149,10 +147,6 @@ pub mod pallet { #[pallet::constant] type MaxUnstakings: Get; - #[pallet::constant] - /// The curve of migration. - type MigrationCurve: Get; - /// The address of KTON reward distribution contract. #[pallet::constant] type KtonRewardDistributionContract: Get; @@ -162,38 +156,18 @@ pub mod pallet { #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - /// An account has staked. - Staked { - staker: T::AccountId, - ring_amount: Balance, - kton_amount: Balance, - deposits: Vec>, - }, - /// An account has unstaked. - Unstaked { - staker: T::AccountId, - ring_amount: Balance, - kton_amount: Balance, - deposits: Vec>, - }, - CommissionUpdated { - who: T::AccountId, - commission: Perbill, - }, + /// An account has staked some assets. + Staked { who: T::AccountId, ring_amount: Balance, deposits: Vec> }, + /// An account has unstaked assets. + Unstaked { who: T::AccountId, ring_amount: Balance, deposits: Vec> }, + /// A collator has updated their commission. + CommissionUpdated { who: T::AccountId, commission: Perbill }, /// A payout has been made for the staker. - Payout { - staker: T::AccountId, - amount: Balance, - }, + Payout { who: T::AccountId, amount: Balance }, /// Unable to pay the staker's reward. - Unpaid { - staker: T::AccountId, - amount: Balance, - }, + Unpaid { who: T::AccountId, amount: Balance }, /// A new collator set has been elected. - Elected { - collators: Vec, - }, + Elected { collators: Vec }, } #[pallet::error] @@ -219,18 +193,6 @@ pub mod pallet { #[pallet::getter(fn ledger_of)] pub type Ledgers = StorageMap<_, Blake2_128Concat, T::AccountId, Ledger>; - /// Total staked RING. - /// - /// This will count RING + deposit(locking RING). - #[pallet::storage] - #[pallet::getter(fn ring_pool)] - pub type RingPool = StorageValue<_, Balance, ValueQuery>; - - /// Total staked KTON. - #[pallet::storage] - #[pallet::getter(fn kton_pool)] - pub type KtonPool = StorageValue<_, Balance, ValueQuery>; - /// The map from (wannabe) collator to the preferences of that collator. #[pallet::storage] #[pallet::getter(fn collator_of)] @@ -328,11 +290,6 @@ pub mod pallet { #[pallet::getter(fn elapsed_time)] pub type ElapsedTime = StorageValue<_, Moment, ValueQuery>; - /// Migration starting block. - #[pallet::storage] - #[pallet::getter(fn migration_start_block)] - pub type MigrationStartBlock = StorageValue<_, BlockNumberFor, ValueQuery>; - #[derive(DefaultNoBound)] #[pallet::genesis_config] pub struct GenesisConfig { @@ -357,9 +314,13 @@ pub mod pallet { >::put(self.elapsed_time); >::put(self.collator_count); - self.collators.iter().for_each(|(who, stake)| { - >::stake(RawOrigin::Signed(who.to_owned()).into(), *stake, 0, Vec::new()) - .expect("[pallet::staking] 0, genesis must be built; qed"); + self.collators.iter().for_each(|(who, ring_amount)| { + >::stake( + RawOrigin::Signed(who.to_owned()).into(), + *ring_amount, + Vec::new(), + ) + .expect("[pallet::staking] 0, genesis must be built; qed"); >::collect(RawOrigin::Signed(who.to_owned()).into(), Default::default()) .expect("[pallet::staking] 1, genesis must be built; qed"); >::nominate(RawOrigin::Signed(who.to_owned()).into(), who.to_owned()) @@ -398,12 +359,11 @@ pub mod pallet { pub fn stake( origin: OriginFor, ring_amount: Balance, - kton_amount: Balance, deposits: Vec>, ) -> DispatchResult { let who = ensure_signed(origin)?; - if ring_amount == 0 && kton_amount == 0 && deposits.is_empty() { + if ring_amount == 0 && deposits.is_empty() { return Ok(()); } @@ -415,10 +375,8 @@ pub mod pallet { *l = Some(Ledger { staked_ring: Default::default(), - staked_kton: Default::default(), staked_deposits: Default::default(), unstaking_ring: Default::default(), - unstaking_kton: Default::default(), unstaking_deposits: Default::default(), }); @@ -426,18 +384,7 @@ pub mod pallet { }; if ring_amount != 0 { - Self::stake_token::<::Ring, RingPool>( - &who, - &mut l.staked_ring, - ring_amount, - )?; - } - if kton_amount != 0 { - Self::stake_token::<::Kton, KtonPool>( - &who, - &mut l.staked_kton, - kton_amount, - )?; + Self::stake_ring(&who, &mut l.staked_ring, ring_amount)?; } for d in deposits.clone() { @@ -447,7 +394,7 @@ pub mod pallet { DispatchResult::Ok(()) })?; - Self::deposit_event(Event::Staked { staker: who, ring_amount, kton_amount, deposits }); + Self::deposit_event(Event::Staked { who, ring_amount, deposits }); Ok(()) } @@ -458,12 +405,11 @@ pub mod pallet { pub fn unstake( origin: OriginFor, ring_amount: Balance, - kton_amount: Balance, deposits: Vec>, ) -> DispatchResult { let who = ensure_signed(origin)?; - if ring_amount == 0 && kton_amount == 0 && deposits.is_empty() { + if ring_amount == 0 && deposits.is_empty() { return Ok(()); } @@ -471,19 +417,11 @@ pub mod pallet { let l = l.as_mut().ok_or(>::NotStaker)?; if ring_amount != 0 { - Self::unstake_token::>( - &mut l.staked_ring, - Some(&mut l.unstaking_ring), - ring_amount, - )?; - } - if kton_amount != 0 { - Self::unstake_token::>(&mut l.staked_kton, None, kton_amount)?; - ::Kton::unstake(&who, kton_amount)?; + Self::unstake_ring(&mut l.staked_ring, &mut l.unstaking_ring, ring_amount)?; } for d in deposits { - Self::unstake_deposit(&who, l, d)?; + Self::unstake_deposit(l, d)?; } DispatchResult::Ok(()) @@ -512,15 +450,11 @@ pub mod pallet { let l = l.as_mut().ok_or(>::NotStaker)?; if ring_amount != 0 { - Self::restake_token::>( - &mut l.staked_ring, - &mut l.unstaking_ring, - ring_amount, - )?; + Self::restake_ring(&mut l.staked_ring, &mut l.unstaking_ring, ring_amount)?; } for d in deposits { - Self::restake_deposit(&who, l, d)?; + Self::restake_deposit(l, d)?; } DispatchResult::Ok(()) @@ -627,40 +561,13 @@ pub mod pallet { where T: Config, { - fn update_pool

(increase: bool, amount: Balance) -> DispatchResult - where - P: frame_support::StorageValue, - { - P::try_mutate(|p| { - *p = if increase { - p.checked_add(amount) - .ok_or("[pallet::staking] `u128` must not be overflowed; qed")? - } else { - p.checked_sub(amount) - .ok_or("[pallet::staking] `u128` must not be overflowed; qed")? - }; - - Ok(()) - }) - } + fn stake_ring(who: &T::AccountId, staked: &mut Balance, amount: Balance) -> DispatchResult { + ::Ring::stake(who, amount)?; - fn stake_token( - who: &T::AccountId, - record: &mut Balance, - amount: Balance, - ) -> DispatchResult - where - S: Stake, - P: frame_support::StorageValue, - { - S::stake(who, amount)?; - - *record = record + *staked = staked .checked_add(amount) .ok_or("[pallet::staking] `u128` must not be overflowed; qed")?; - Self::update_pool::

(true, amount)?; - Ok(()) } @@ -673,41 +580,29 @@ pub mod pallet { ledger.staked_deposits.try_push(deposit).map_err(|_| >::ExceedMaxDeposits)?; - Self::update_pool::>(true, T::Deposit::amount(who, deposit)?)?; - Ok(()) } - fn unstake_token

( + fn unstake_ring( staked: &mut Balance, - unstaking: Option<&mut BoundedVec<(Balance, BlockNumberFor), T::MaxUnstakings>>, + unstaking: &mut BoundedVec<(Balance, BlockNumberFor), T::MaxUnstakings>, amount: Balance, - ) -> DispatchResult - where - P: frame_support::StorageValue, - { + ) -> DispatchResult { *staked = staked .checked_sub(amount) .ok_or("[pallet::staking] `u128` must not be overflowed; qed")?; - if let Some(u) = unstaking { - u.try_push(( + unstaking + .try_push(( amount, >::block_number() + T::MinStakingDuration::get(), )) .map_err(|_| >::ExceedMaxUnstakings)?; - } - - Self::update_pool::

(false, amount)?; Ok(()) } - fn unstake_deposit( - who: &T::AccountId, - ledger: &mut Ledger, - deposit: DepositId, - ) -> DispatchResult { + fn unstake_deposit(ledger: &mut Ledger, deposit: DepositId) -> DispatchResult { ledger .unstaking_deposits .try_push(( @@ -722,19 +617,14 @@ pub mod pallet { )) .map_err(|_| >::ExceedMaxUnstakings)?; - Self::update_pool::>(false, T::Deposit::amount(who, deposit)?)?; - Ok(()) } - fn restake_token

( + fn restake_ring( staked: &mut Balance, unstaking: &mut BoundedVec<(Balance, BlockNumberFor), T::MaxUnstakings>, mut amount: Balance, - ) -> DispatchResult - where - P: frame_support::StorageValue, - { + ) -> DispatchResult { let mut actual_restake = 0; // Cancel the latest `unstake` first. @@ -762,16 +652,10 @@ pub mod pallet { *staked += actual_restake; - Self::update_pool::

(true, actual_restake)?; - Ok(()) } - fn restake_deposit( - who: &T::AccountId, - ledger: &mut Ledger, - deposit: DepositId, - ) -> DispatchResult { + fn restake_deposit(ledger: &mut Ledger, deposit: DepositId) -> DispatchResult { ledger .staked_deposits .try_push( @@ -788,8 +672,6 @@ pub mod pallet { ) .map_err(|_| >::ExceedMaxDeposits)?; - Self::update_pool::>(true, T::Deposit::amount(who, deposit)?)?; - Ok(()) } @@ -809,10 +691,6 @@ pub mod pallet { } }); ::Ring::unstake(who, r_claimed)?; - ::Kton::unstake( - who, - mem::take(&mut l.unstaking_kton).into_iter().fold(0, |s, (a, _)| s + a), - )?; let mut d_claimed = Vec::new(); @@ -861,70 +739,27 @@ pub mod pallet { }); } - /// Calculate the power of the given account. - #[cfg(any(feature = "runtime-benchmarks", test))] - pub fn quick_power_of(who: &T::AccountId) -> Power { - Self::power_of( - who, - >::get(), - >::get(), - T::MigrationCurve::get(), - ) - } - - /// Calculate the power of the given account. - /// - /// This is an optimized version of [`Self::quick_power_of`]. - /// Avoiding read the pools' storage multiple times. - pub fn power_of( - who: &T::AccountId, - ring_pool: Balance, - kton_pool: Balance, - migration_ratio: Perquintill, - ) -> Power { - // Power is a mixture of RING and KTON. - // - `total_ring_power = (amount / total_staked_ring) * HALF_POWER` - // - `total_kton_power = (amount / total_staked_kton) * HALF_POWER` - - const HALF_POWER: u128 = 500_000_000; - + /// Calculate the stakes of the given account. + pub fn stake_of(who: &T::AccountId) -> Balance { >::get(who) .map(|l| { - (Perquintill::from_rational( - l.staked_ring - + l.staked_deposits - .into_iter() - // We don't care if the deposit exists here. - // It was guaranteed by the `stake`/`unstake`/`restake` functions. - .fold(0, |r, d| r + T::Deposit::amount(who, d).unwrap_or_default()), - ring_pool.max(1), - ) * HALF_POWER) - .saturating_add( - Perquintill::from_rational(l.staked_kton, kton_pool.max(1)) - * (migration_ratio * HALF_POWER), - ) as _ + l.staked_ring + + l.staked_deposits + .into_iter() + // We don't care if the deposit exists here. + // It was guaranteed by the `stake`/`unstake`/`restake` functions. + .fold(0, |r, d| r + T::Deposit::amount(who, d).unwrap_or_default()) }) .unwrap_or_default() } /// Distribute the session reward to staking pot and update the stakers' reward record. pub fn distribute_session_reward(amount: Balance) { - let (reward_to_v1, reward_to_v2) = { - let reward_to_ring = amount / 2; - let reward_to_kton = amount - reward_to_ring; - #[cfg(not(any(test, feature = "runtime-benchmarks")))] - let ratio = T::MigrationCurve::get(); - #[cfg(any(test, feature = "runtime-benchmarks"))] - let ratio = Perquintill::one(); - let reward_to_kton_v1 = ratio * reward_to_kton; - let reward_to_kton_v2 = reward_to_kton - reward_to_kton_v1; - - (reward_to_ring + reward_to_kton_v1, reward_to_kton_v2) - }; + let reward_to_ring = amount.saturating_div(2); + let reward_to_kton = amount.saturating_sub(reward_to_ring); let (sum, map) = >::take(); - let staking_pot = account_id(); - let actual_reward_v1 = map.into_iter().fold(0, |s, (c, p)| { - let r = Perbill::from_rational(p, sum) * reward_to_v1; + let actual_reward_to_ring = map.into_iter().fold(0, |s, (c, p)| { + let r = Perbill::from_rational(p, sum) * reward_to_ring; >::mutate(c, |u| *u = u.map(|u| u + r).or(Some(r))); @@ -932,16 +767,16 @@ pub mod pallet { }); let reward = |who, amount| { if T::IssuingManager::reward(&who, amount).is_ok() { - Self::deposit_event(Event::Payout { staker: who, amount }); + Self::deposit_event(Event::Payout { who, amount }); } else { - Self::deposit_event(Event::Unpaid { staker: who, amount }); + Self::deposit_event(Event::Unpaid { who, amount }); } }; - reward(staking_pot, actual_reward_v1); - reward(T::KtonRewardDistributionContract::get(), reward_to_v2); + reward(account_id(), actual_reward_to_ring); + reward(T::KtonRewardDistributionContract::get(), reward_to_kton); - T::KtonStakerNotifier::notify(reward_to_v2); + T::KtonStakerNotifier::notify(reward_to_kton); } /// Pay the reward to the collator and its nominators. @@ -960,16 +795,16 @@ pub mod pallet { c_payout += n_payout; } else if T::IssuingManager::reward(&n_exposure.who, n_payout).is_ok() { - Self::deposit_event(Event::Payout { staker: n_exposure.who, amount: n_payout }); + Self::deposit_event(Event::Payout { who: n_exposure.who, amount: n_payout }); } else { - Self::deposit_event(Event::Unpaid { staker: n_exposure.who, amount: n_payout }); + Self::deposit_event(Event::Unpaid { who: n_exposure.who, amount: n_payout }); } } if T::IssuingManager::reward(&collator, c_payout).is_ok() { - Self::deposit_event(Event::Payout { staker: collator, amount: c_payout }); + Self::deposit_event(Event::Payout { who: collator, amount: c_payout }); } else { - Self::deposit_event(Event::Unpaid { staker: collator, amount: c_payout }); + Self::deposit_event(Event::Unpaid { who: collator, amount: c_payout }); } Ok(::WeightInfo::payout()) @@ -990,15 +825,16 @@ pub mod pallet { "[pallet::staking] assembling new collators for new session {index} at #{bn:?}", ); - if let Ok(collators) = Self::elect() { - if !collators.is_empty() { + if let Ok(cs) = Self::elect() { + if !cs.is_empty() { // TODO?: if we really need this event - Self::deposit_event(Event::Elected { collators: collators.clone() }); + Self::deposit_event(Event::Elected { collators: cs.clone() }); - return Some(collators); + return Some(cs); } } + // This error log is acceptable when testing with `genesis_collator = false`. log::error!( "[pallet::staking] fail to elect collators for new session {index} at #{bn:?}" ); @@ -1030,9 +866,6 @@ pub mod pallet { /// This should only be called by the [`pallet_session::SessionManager::new_session`]. pub fn elect() -> Result, DispatchError> { let nominators = >::iter().collect::>(); - let ring_pool = >::get(); - let kton_pool = >::get(); - let migration_ratio = T::MigrationCurve::get(); let mut collators = >::iter() .map(|(c, cm)| { let scaler = Perbill::one() - cm; @@ -1041,8 +874,7 @@ pub mod pallet { .iter() .filter_map(|(n, c_)| { if c_ == &c { - let nominator_v = scaler - * Self::power_of(n, ring_pool, kton_pool, migration_ratio); + let nominator_v = scaler * Self::stake_of(n); collator_v += nominator_v; @@ -1075,9 +907,6 @@ pub mod pallet { } pub use pallet::*; -type Power = u32; -type Vote = u32; - type DepositId = <::Deposit as Stake>::Item; /// Issuing and reward manager. @@ -1145,14 +974,10 @@ where { /// Staked RING. pub staked_ring: Balance, - /// Staked KTON. - pub staked_kton: Balance, /// Staked deposits. pub staked_deposits: BoundedVec, ::MaxDeposits>, /// The RING in unstaking process. pub unstaking_ring: BoundedVec<(Balance, BlockNumberFor), T::MaxUnstakings>, - /// The KTON in unstaking process. - pub unstaking_kton: BoundedVec<(Balance, BlockNumberFor), T::MaxUnstakings>, /// The deposit in unstaking process. pub unstaking_deposits: BoundedVec<(DepositId, BlockNumberFor), T::MaxUnstakings>, } @@ -1162,10 +987,8 @@ where { fn is_empty(&self) -> bool { self.staked_ring == 0 - && self.staked_kton == 0 && self.staked_deposits.is_empty() && self.unstaking_ring.is_empty() - && self.unstaking_kton.is_empty() && self.unstaking_deposits.is_empty() } } @@ -1177,7 +1000,7 @@ pub struct Exposure { /// The commission of this collator. pub commission: Perbill, /// The total vote backing this collator. - pub vote: Vote, + pub vote: Balance, /// Nominator staking map. pub nominators: Vec>, } @@ -1188,7 +1011,7 @@ pub struct IndividualExposure { /// Nominator. pub who: AccountId, /// Nominator's staking vote. - pub vote: Vote, + pub vote: Balance, } // Add reward points to block authors: @@ -1241,25 +1064,6 @@ where } } -/// A curve helps to migrate to staking v2 smoothly. -pub struct MigrationCurve(PhantomData); -impl Get for MigrationCurve -where - T: Config, -{ - fn get() -> Perquintill { - // substrate - use sp_runtime::traits::SaturatedConversion; - - let x = (>::block_number() - >::get()) - .saturated_into::() - .max(1); - let month_in_blocks = 30 * 24 * 60 * 60 / 12; - - Perquintill::one() - Perquintill::from_rational(x, month_in_blocks) - } -} - /// KTON staker contact notification interface. pub trait KtonStakerNotification { /// Notify the KTON staker contract. diff --git a/pallet/staking/src/migration.rs b/pallet/staking/src/migration.rs index ba097a6b3..33af6418d 100644 --- a/pallet/staking/src/migration.rs +++ b/pallet/staking/src/migration.rs @@ -1,135 +1,6 @@ //! Pallet migrations. -// core -use core::marker::PhantomData; -// darwinia -use crate::*; -// substrate -use frame_support::traits::OnRuntimeUpgrade; -#[cfg(feature = "try-runtime")] -use sp_runtime::TryRuntimeError; - /// Migration version 1. -pub mod v1 { - // darwinia - use super::*; - - type AccountId = ::AccountId; - - #[frame_support::storage_alias] - type NextExposures = - StorageMap, Twox64Concat, AccountId, ExposureV0>>; - - #[frame_support::storage_alias] - type Exposures = - StorageMap, Twox64Concat, AccountId, ExposureV0>>; - - #[frame_support::storage_alias] - type RewardPoints = - StorageValue, (u32, BTreeMap, u32>), ValueQuery>; - - #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, RuntimeDebug)] - struct ExposureV0 { - vote: Vote, - nominators: Vec>, - } - - /// Migrate darwinia-staking from v0 to v1. - pub struct MigrateToV1(PhantomData); - impl OnRuntimeUpgrade for MigrateToV1 - where - T: Config, - { - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result, TryRuntimeError> { - Ok(Vec::new()) - } - - fn on_runtime_upgrade() -> Weight { - let version = StorageVersion::get::>(); - - if version != 0 { - log::warn!( - "[pallet::staking] skipping v0 to v1 migration: executed on wrong storage version. Expected version 0, found {version:?}", - ); - - return T::DbWeight::get().reads(1); - } - - let mut count = 4; - - let (sum, map) = >::take(); - >::put(( - >::from(sum / 20), - map.into_iter() - .map(|(k, v)| (k, >::from(v / 20))) - .collect::>(), - )); - - >::iter().drain().for_each(|(k, v)| { - count += 1; - - >::insert( - &k, - Exposure { - commission: >::get(&k).unwrap_or_default(), - vote: v.vote, - nominators: v.nominators, - }, - ); - }); - >::iter().drain().for_each(|(k, v)| { - count += 1; - - >::insert( - &k, - Exposure { - commission: >::get(&k).unwrap_or_default(), - vote: v.vote, - nominators: v.nominators, - }, - ); - }); - - StorageVersion::new(1).put::>(); - - T::DbWeight::get().reads_writes(count, count) - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade(_: Vec) -> Result<(), TryRuntimeError> { - assert_eq!(StorageVersion::get::>(), 1, "Version must be upgraded."); - - // Old storages should be killed. - assert_eq!(>::iter_keys().count(), 0); - assert_eq!(>::iter_keys().count(), 0); - assert!(!>::exists()); - - // Check the starting state is correct. - assert_eq!( - >::get(), - ( - ExposureCacheState::Previous, - ExposureCacheState::Current, - ExposureCacheState::Next - ) - ); - - assert_eq!( - >::iter_keys().count(), - 0, - "Previous exposure should be empty at start." - ); - - // Check that everything decoded fine. - >::iter_keys().for_each(|k| { - assert!(>::try_get(k).is_ok(), "Can not decode V1 `Exposure`."); - }); - >::iter_keys().for_each(|k| { - assert!(>::try_get(k).is_ok(), "Can not decode V1 `Exposure`."); - }); - - Ok(()) - } - } -} +pub mod v1; +/// Migration version 2. +pub mod v2; diff --git a/pallet/staking/src/migration/v1.rs b/pallet/staking/src/migration/v1.rs new file mode 100644 index 000000000..ca89dd12c --- /dev/null +++ b/pallet/staking/src/migration/v1.rs @@ -0,0 +1,123 @@ +// core +use core::marker::PhantomData; +// darwinia +use crate::*; +// substrate +use frame_support::traits::OnRuntimeUpgrade; +#[cfg(feature = "try-runtime")] +use sp_runtime::TryRuntimeError; + +type AccountId = ::AccountId; + +#[frame_support::storage_alias] +type NextExposures = + StorageMap, Twox64Concat, AccountId, ExposureV0>>; + +#[frame_support::storage_alias] +type Exposures = + StorageMap, Twox64Concat, AccountId, ExposureV0>>; + +#[frame_support::storage_alias] +type RewardPoints = + StorageValue, (u32, BTreeMap, u32>), ValueQuery>; + +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, RuntimeDebug)] +struct ExposureV0 { + vote: Balance, + nominators: Vec>, +} + +/// Migrate darwinia-staking from v0 to v1. +pub struct MigrateToV1(PhantomData); +impl OnRuntimeUpgrade for MigrateToV1 +where + T: Config, +{ + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, TryRuntimeError> { + Ok(Vec::new()) + } + + fn on_runtime_upgrade() -> Weight { + let version = StorageVersion::get::>(); + + if version != 0 { + log::warn!( + "[pallet::staking] skipping v0 to v1 migration: executed on wrong storage version. Expected version 0, found {version:?}", + ); + + return T::DbWeight::get().reads(1); + } + + let mut count = 4; + + let (sum, map) = >::take(); + >::put(( + >::from(sum / 20), + map.into_iter() + .map(|(k, v)| (k, >::from(v / 20))) + .collect::>(), + )); + + >::iter().drain().for_each(|(k, v)| { + count += 1; + + >::insert( + &k, + Exposure { + commission: >::get(&k).unwrap_or_default(), + vote: v.vote, + nominators: v.nominators, + }, + ); + }); + >::iter().drain().for_each(|(k, v)| { + count += 1; + + >::insert( + &k, + Exposure { + commission: >::get(&k).unwrap_or_default(), + vote: v.vote, + nominators: v.nominators, + }, + ); + }); + + StorageVersion::new(1).put::>(); + + T::DbWeight::get().reads_writes(count, count) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(_: Vec) -> Result<(), TryRuntimeError> { + assert_eq!(StorageVersion::get::>(), 1, "Version must be upgraded."); + + // Old storages should be killed. + assert_eq!(>::iter_keys().count(), 0); + assert_eq!(>::iter_keys().count(), 0); + assert!(!>::exists()); + + // Check the starting state is correct. + assert_eq!( + >::get(), + (ExposureCacheState::Previous, ExposureCacheState::Current, ExposureCacheState::Next) + ); + + assert_eq!( + >::iter_keys().count(), + 0, + "Previous exposure should be empty at start." + ); + + // Check that everything decoded fine. + >::iter_keys().for_each(|k| { + assert!(>::try_get(k).is_ok(), "Can not decode V1 `Exposure`."); + }); + >::iter_keys().for_each(|k| { + assert!(>::try_get(k).is_ok(), "Can not decode V1 `Exposure`."); + }); + + Ok(()) + } +} diff --git a/pallet/staking/src/migration/v2.rs b/pallet/staking/src/migration/v2.rs new file mode 100644 index 000000000..00fe97b7a --- /dev/null +++ b/pallet/staking/src/migration/v2.rs @@ -0,0 +1,151 @@ +// core +use core::marker::PhantomData; +// darwinia +use crate::*; +// substrate +use frame_support::traits::OnRuntimeUpgrade; +#[cfg(feature = "try-runtime")] +use sp_runtime::TryRuntimeError; + +#[frame_support::storage_alias] +type RingPool = StorageValue, ()>; +#[frame_support::storage_alias] +type KtonPool = StorageValue, ()>; +#[frame_support::storage_alias] +type MigrationStartBlock = StorageValue, ()>; + +#[allow(missing_docs)] +#[derive( + DebugNoBound, + DefaultNoBound, + PartialEqNoBound, + EqNoBound, + Encode, + Decode, + MaxEncodedLen, + TypeInfo, +)] +#[scale_info(skip_type_params(T))] +pub struct OldLedger +where + T: Config, +{ + pub staked_ring: Balance, + pub staked_kton: Balance, + pub staked_deposits: BoundedVec, ::MaxDeposits>, + pub unstaking_ring: BoundedVec<(Balance, BlockNumberFor), T::MaxUnstakings>, + pub unstaking_kton: BoundedVec<(Balance, BlockNumberFor), T::MaxUnstakings>, + pub unstaking_deposits: BoundedVec<(DepositId, BlockNumberFor), T::MaxUnstakings>, +} + +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, RuntimeDebug)] +struct OldExposure { + commission: Perbill, + vote: u32, + nominators: Vec>, +} +#[cfg_attr(test, derive(Clone))] +#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, RuntimeDebug)] +struct OldIndividualExposure { + who: AccountId, + vote: u32, +} + +/// Migrate darwinia-staking from v1 to v2. +pub struct MigrateToV2(PhantomData); +impl OnRuntimeUpgrade for MigrateToV2 +where + T: Config, +{ + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, TryRuntimeError> { + Ok(Vec::new()) + } + + fn on_runtime_upgrade() -> Weight { + let version = StorageVersion::get::>(); + let r = 1; + + if version != 1 { + log::warn!( + "\ + [pallet::staking] skipping v1 to v2 migration: executed on wrong storage version.\ + Expected version 1, found {version:?}\ + ", + ); + + return T::DbWeight::get().reads(r); + } + + let mut w = 4; + + >::kill(); + >::kill(); + >::kill(); + >::translate::, _>(|a, o| { + w += 2; + + let _ = ::Kton::unstake( + &a, + o.staked_kton + o.unstaking_kton.into_iter().fold(0, |s, (v, _)| s + v), + ); + + Some(Ledger { + staked_ring: o.staked_ring, + staked_deposits: o.staked_deposits, + unstaking_ring: o.unstaking_ring, + unstaking_deposits: o.unstaking_deposits, + }) + }); + >::translate_values::, _>(|o| { + w += 1; + + Some(Exposure { + commission: o.commission, + vote: o.vote as _, + nominators: o + .nominators + .into_iter() + .map(|o| IndividualExposure { who: o.who, vote: o.vote as _ }) + .collect(), + }) + }); + >::translate_values::, _>(|o| { + w += 1; + + Some(Exposure { + commission: o.commission, + vote: o.vote as _, + nominators: o + .nominators + .into_iter() + .map(|o| IndividualExposure { who: o.who, vote: o.vote as _ }) + .collect(), + }) + }); + >::translate_values::, _>(|o| { + w += 1; + + Some(Exposure { + commission: o.commission, + vote: o.vote as _, + nominators: o + .nominators + .into_iter() + .map(|o| IndividualExposure { who: o.who, vote: o.vote as _ }) + .collect(), + }) + }); + + StorageVersion::new(2).put::>(); + + T::DbWeight::get().reads_writes(r, w) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(_: Vec) -> Result<(), TryRuntimeError> { + assert_eq!(StorageVersion::get::>(), 2, "Version must be upgraded."); + + Ok(()) + } +} diff --git a/pallet/staking/src/mock.rs b/pallet/staking/src/mock.rs index c8bf584a1..db2cbab44 100644 --- a/pallet/staking/src/mock.rs +++ b/pallet/staking/src/mock.rs @@ -19,7 +19,7 @@ pub use crate as darwinia_staking; // darwinia -use dc_types::{AssetId, Balance, Moment, UNIT}; +use dc_types::{Balance, Moment, UNIT}; // substrate use frame_support::traits::{Currency, OnInitialize}; use sp_io::TestExternalities; @@ -77,53 +77,16 @@ impl pallet_balances::Config for Runtime { type WeightInfo = (); } -#[cfg(feature = "runtime-benchmarks")] -pub enum BenchmarkHelper {} -#[cfg(feature = "runtime-benchmarks")] -impl pallet_assets::BenchmarkHelper> for BenchmarkHelper { - fn create_asset_id_parameter(id: u32) -> codec::Compact { - (id as u64).into() - } -} -impl pallet_assets::Config for Runtime { - type ApprovalDeposit = (); - type AssetAccountDeposit = (); - type AssetDeposit = (); - type AssetId = AssetId; - type AssetIdParameter = codec::Compact; - type Balance = Balance; - #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = BenchmarkHelper; - type CallbackHandle = (); - type CreateOrigin = frame_support::traits::AsEnsureOriginWithArg< - frame_system::EnsureSignedBy, AccountId>, - >; - type Currency = Balances; - type Extra = (); - type ForceOrigin = frame_system::EnsureRoot; - type Freezer = (); - type MetadataDepositBase = (); - type MetadataDepositPerByte = (); - type RemoveItemsLimit = (); - type RuntimeEvent = RuntimeEvent; - type StringLimit = frame_support::traits::ConstU32<4>; - type WeightInfo = (); -} - pub enum KtonMinting {} impl darwinia_deposit::SimpleAsset for KtonMinting { type AccountId = AccountId; - fn mint(beneficiary: &Self::AccountId, amount: Balance) -> sp_runtime::DispatchResult { - Assets::mint(RuntimeOrigin::signed(0), 0.into(), *beneficiary, amount) + fn mint(_: &Self::AccountId, _: Balance) -> sp_runtime::DispatchResult { + Ok(()) } - fn burn(who: &Self::AccountId, amount: Balance) -> sp_runtime::DispatchResult { - if Assets::balance(0, who) < amount { - Err(>::BalanceLow)?; - } - - Assets::burn(RuntimeOrigin::signed(0), 0.into(), *who, amount) + fn burn(_: &Self::AccountId, _: Balance) -> sp_runtime::DispatchResult { + Ok(()) } } impl darwinia_deposit::Config for Runtime { @@ -135,30 +98,6 @@ impl darwinia_deposit::Config for Runtime { type WeightInfo = (); } -pub enum RingStaking {} -impl darwinia_staking::Stake for RingStaking { - type AccountId = AccountId; - type Item = Balance; - - fn stake(who: &Self::AccountId, item: Self::Item) -> sp_runtime::DispatchResult { - >::transfer( - who, - &darwinia_staking::account_id(), - item, - frame_support::traits::ExistenceRequirement::AllowDeath, - ) - } - - fn unstake(who: &Self::AccountId, item: Self::Item) -> sp_runtime::DispatchResult { - >::transfer( - &darwinia_staking::account_id(), - who, - item, - frame_support::traits::ExistenceRequirement::AllowDeath, - ) - } -} - frame_support::parameter_types! { pub static SessionHandlerCollators: Vec = Vec::new(); pub static SessionChangeBlock: BlockNumber = 0; @@ -232,32 +171,8 @@ impl pallet_treasury::Config for Runtime { frame_support::parameter_types! { pub PayoutFraction: sp_runtime::Perbill = sp_runtime::Perbill::from_percent(40); - pub MigrationCurve: sp_runtime::Perquintill = sp_runtime::Perquintill::one(); pub static InflationType: u8 = 0; } -pub enum KtonStaking {} -impl darwinia_staking::Stake for KtonStaking { - type AccountId = AccountId; - type Item = Balance; - - fn stake(who: &Self::AccountId, item: Self::Item) -> sp_runtime::DispatchResult { - Assets::transfer( - RuntimeOrigin::signed(*who), - 0.into(), - darwinia_staking::account_id(), - item, - ) - } - - fn unstake(who: &Self::AccountId, item: Self::Item) -> sp_runtime::DispatchResult { - Assets::transfer( - RuntimeOrigin::signed(darwinia_staking::account_id()), - 0.into(), - *who, - item, - ) - } -} pub enum StatedOnSessionEnd {} impl darwinia_staking::IssuingManager for StatedOnSessionEnd { fn inflate() -> Balance { @@ -336,6 +251,42 @@ impl frame_support::traits::Get for ShouldEndSession { ) } } +pub enum RingStaking {} +impl darwinia_staking::Stake for RingStaking { + type AccountId = AccountId; + type Item = Balance; + + fn stake(who: &Self::AccountId, item: Self::Item) -> sp_runtime::DispatchResult { + >::transfer( + who, + &darwinia_staking::account_id(), + item, + frame_support::traits::ExistenceRequirement::AllowDeath, + ) + } + + fn unstake(who: &Self::AccountId, item: Self::Item) -> sp_runtime::DispatchResult { + >::transfer( + &darwinia_staking::account_id(), + who, + item, + frame_support::traits::ExistenceRequirement::AllowDeath, + ) + } +} +pub enum KtonStaking {} +impl darwinia_staking::Stake for KtonStaking { + type AccountId = AccountId; + type Item = Balance; + + fn stake(_: &Self::AccountId, _: Self::Item) -> sp_runtime::DispatchResult { + Ok(()) + } + + fn unstake(_: &Self::AccountId, _: Self::Item) -> sp_runtime::DispatchResult { + Ok(()) + } +} impl darwinia_staking::Config for Runtime { type Currency = Balances; type Deposit = Deposit; @@ -345,7 +296,6 @@ impl darwinia_staking::Config for Runtime { type KtonStakerNotifier = (); type MaxDeposits = ::MaxDeposits; type MaxUnstakings = frame_support::traits::ConstU32<16>; - type MigrationCurve = MigrationCurve; type MinStakingDuration = frame_support::traits::ConstU64<3>; type Ring = RingStaking; type RuntimeEvent = RuntimeEvent; @@ -360,7 +310,6 @@ frame_support::construct_runtime! { System: frame_system, Timestamp: pallet_timestamp, Balances: pallet_balances, - Assets: pallet_assets, Deposit: darwinia_deposit, Session: pallet_session, Treasury: pallet_treasury, @@ -375,10 +324,8 @@ impl ZeroDefault for darwinia_staking::Ledger { fn default() -> Self { Self { staked_ring: Default::default(), - staked_kton: Default::default(), staked_deposits: Default::default(), unstaking_ring: Default::default(), - unstaking_kton: Default::default(), unstaking_deposits: Default::default(), } } @@ -436,13 +383,6 @@ impl ExtBuilder { } .assimilate_storage(&mut storage) .unwrap(); - pallet_assets::GenesisConfig:: { - assets: vec![(0, 0, true, 1)], - metadata: vec![(0, b"KTON".to_vec(), b"KTON".to_vec(), 18)], - accounts: (1..=10).map(|i| (0, i, 1_000 * UNIT)).collect(), - } - .assimilate_storage(&mut storage) - .unwrap(); darwinia_staking::GenesisConfig:: { collator_count: self.collator_count, collators: if self.genesis_collator { diff --git a/pallet/staking/src/tests.rs b/pallet/staking/src/tests.rs index eaf893d64..1da057a96 100644 --- a/pallet/staking/src/tests.rs +++ b/pallet/staking/src/tests.rs @@ -19,7 +19,7 @@ // core use core::time::Duration; // darwinia -use crate::{mock::*, MigrationCurve, *}; +use crate::{mock::*, *}; use darwinia_deposit::Error as DepositError; use dc_types::UNIT; // substrate @@ -118,10 +118,9 @@ fn stake_should_work() { assert_eq!(System::account(1).consumers, 0); assert!(Staking::ledger_of(1).is_none()); assert_eq!(Balances::free_balance(1), 1_000 * UNIT); - assert_eq!(Assets::balance(0, 1), 1_000 * UNIT); // Stake 1 RING. - assert_ok!(Staking::stake(RuntimeOrigin::signed(1), UNIT, 0, Vec::new())); + assert_ok!(Staking::stake(RuntimeOrigin::signed(1), UNIT, Vec::new())); assert_eq!(System::account(1).consumers, 1); assert_eq!( Staking::ledger_of(1).unwrap(), @@ -129,47 +128,35 @@ fn stake_should_work() { ); assert_eq!(Balances::free_balance(1), 999 * UNIT); - // Stake 1 KTON. - assert_eq!(System::account(1).consumers, 1); - assert_ok!(Staking::stake(RuntimeOrigin::signed(1), 0, UNIT, Vec::new())); - assert_eq!(Assets::balance(0, 1), 999 * UNIT); - assert_eq!( - Staking::ledger_of(1).unwrap(), - Ledger { staked_ring: UNIT, staked_kton: UNIT, ..ZeroDefault::default() } - ); - // Stake invalid deposit. assert_noop!( - Staking::stake(RuntimeOrigin::signed(1), 0, 0, vec![0]), + Staking::stake(RuntimeOrigin::signed(1), 0, vec![0]), >::DepositNotFound ); // Stake 1 deposit. assert_eq!(System::account(1).consumers, 1); assert_ok!(Deposit::lock(RuntimeOrigin::signed(1), UNIT, 1)); - assert_ok!(Staking::stake(RuntimeOrigin::signed(1), 0, 0, vec![0])); + assert_ok!(Staking::stake(RuntimeOrigin::signed(1), 0, vec![0])); assert_eq!( Staking::ledger_of(1).unwrap(), Ledger { staked_ring: UNIT, - staked_kton: UNIT, staked_deposits: BoundedVec::truncate_from(vec![0]), ..ZeroDefault::default() } ); - // Stake 500 RING, 500 KTON and 2 deposits. + // Stake 500 RING and 2 deposits. assert_eq!(System::account(1).consumers, 2); assert_ok!(Deposit::lock(RuntimeOrigin::signed(1), 200 * UNIT, 1)); assert_ok!(Deposit::lock(RuntimeOrigin::signed(1), 200 * UNIT, 1)); - assert_ok!(Staking::stake(RuntimeOrigin::signed(1), 500 * UNIT, 500 * UNIT, vec![1, 2])); + assert_ok!(Staking::stake(RuntimeOrigin::signed(1), 500 * UNIT, vec![1, 2])); assert_eq!(Balances::free_balance(1), 98 * UNIT); - assert_eq!(Assets::balance(0, 1), 499 * UNIT + 3_053_299_492_385_785); assert_eq!( Staking::ledger_of(1).unwrap(), Ledger { staked_ring: 501 * UNIT, - staked_kton: 501 * UNIT, staked_deposits: BoundedVec::truncate_from(vec![0, 1, 2]), ..ZeroDefault::default() } @@ -183,40 +170,23 @@ fn unstake_should_work() { assert_ok!(Deposit::lock(RuntimeOrigin::signed(1), UNIT, 1)); assert_ok!(Deposit::lock(RuntimeOrigin::signed(1), UNIT, 1)); assert_ok!(Deposit::lock(RuntimeOrigin::signed(1), UNIT, 1)); - assert_ok!(Staking::stake(RuntimeOrigin::signed(1), 3 * UNIT, 3 * UNIT, vec![0, 1, 2])); + assert_ok!(Staking::stake(RuntimeOrigin::signed(1), 3 * UNIT, vec![0, 1, 2])); assert_eq!(Balances::free_balance(1), 994 * UNIT); - assert_eq!(Assets::balance(0, 1), 997 * UNIT + 22_842_639_593_907); assert_eq!( Staking::ledger_of(1).unwrap(), Ledger { staked_ring: 3 * UNIT, - staked_kton: 3 * UNIT, staked_deposits: BoundedVec::truncate_from(vec![0, 1, 2]), ..ZeroDefault::default() } ); // Unstake 1 RING. - assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), UNIT, 0, Vec::new())); + assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), UNIT, Vec::new())); assert_eq!( Staking::ledger_of(1).unwrap(), Ledger { staked_ring: 2 * UNIT, - staked_kton: 3 * UNIT, - staked_deposits: BoundedVec::truncate_from(vec![0, 1, 2]), - unstaking_ring: BoundedVec::truncate_from(vec![(UNIT, 6)]), - ..ZeroDefault::default() - } - ); - - // Unstake 1 KTON. - Efflux::block(1); - assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), 0, UNIT, Vec::new())); - assert_eq!( - Staking::ledger_of(1).unwrap(), - Ledger { - staked_ring: 2 * UNIT, - staked_kton: 2 * UNIT, staked_deposits: BoundedVec::truncate_from(vec![0, 1, 2]), unstaking_ring: BoundedVec::truncate_from(vec![(UNIT, 6)]), ..ZeroDefault::default() @@ -225,40 +195,37 @@ fn unstake_should_work() { // Unstake invalid deposit. assert_noop!( - Staking::unstake(RuntimeOrigin::signed(1), 0, 0, vec![3]), + Staking::unstake(RuntimeOrigin::signed(1), 0, vec![3]), >::DepositNotFound ); // Unstake 1 deposit. Efflux::block(1); - assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), 0, 0, vec![1])); + assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), 0, vec![1])); assert_eq!( Staking::ledger_of(1).unwrap(), Ledger { staked_ring: 2 * UNIT, - staked_kton: 2 * UNIT, staked_deposits: BoundedVec::truncate_from(vec![0, 2]), unstaking_ring: BoundedVec::truncate_from(vec![(UNIT, 6)]), - unstaking_deposits: BoundedVec::truncate_from(vec![(1, 8)]), - ..ZeroDefault::default() + unstaking_deposits: BoundedVec::truncate_from(vec![(1, 7)]) } ); - // Unstake 2 RING, 2 KTON and 2 deposits. + // Unstake 2 RING and 2 deposits. Efflux::block(1); - assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), 2 * UNIT, 2 * UNIT, vec![0, 2])); + assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), 2 * UNIT, vec![0, 2])); assert_eq!( Staking::ledger_of(1).unwrap(), Ledger { - unstaking_ring: BoundedVec::truncate_from(vec![(UNIT, 6), (2 * UNIT, 9)]), - unstaking_deposits: BoundedVec::truncate_from(vec![(1, 8), (0, 9), (2, 9)]), + unstaking_ring: BoundedVec::truncate_from(vec![(UNIT, 6), (2 * UNIT, 8)]), + unstaking_deposits: BoundedVec::truncate_from(vec![(1, 7), (0, 8), (2, 8)]), ..ZeroDefault::default() } ); // Keep the stakes for at least `MinStakingDuration`. assert_eq!(Balances::free_balance(1), 994 * UNIT); - assert_eq!(Assets::balance(0, 1), 1_000 * UNIT + 22_842_639_593_907); }); } @@ -268,14 +235,13 @@ fn restake_should_work() { assert_ok!(Deposit::lock(RuntimeOrigin::signed(1), UNIT, 1)); assert_ok!(Deposit::lock(RuntimeOrigin::signed(1), UNIT, 1)); assert_ok!(Deposit::lock(RuntimeOrigin::signed(1), UNIT, 1)); - assert_ok!(Staking::stake(RuntimeOrigin::signed(1), 3 * UNIT, 3 * UNIT, vec![0, 1, 2])); - assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), UNIT, UNIT, vec![0, 1, 2])); + assert_ok!(Staking::stake(RuntimeOrigin::signed(1), 3 * UNIT, vec![0, 1, 2])); + assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), UNIT, vec![0, 1, 2])); Efflux::block(1); - assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), UNIT, UNIT, Vec::new())); + assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), UNIT, Vec::new())); Efflux::block(1); - assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), UNIT, UNIT, Vec::new())); + assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), UNIT, Vec::new())); assert_eq!(Balances::free_balance(1), 994 * UNIT); - assert_eq!(Assets::balance(0, 1), 1_000 * UNIT + 22_842_639_593_907); assert_eq!( Staking::ledger_of(1).unwrap(), Ledger { @@ -299,7 +265,7 @@ fn restake_should_work() { // Restake invalid deposit. assert_noop!( - Staking::unstake(RuntimeOrigin::signed(1), 0, 0, vec![3]), + Staking::unstake(RuntimeOrigin::signed(1), 0, vec![3]), >::DepositNotFound ); @@ -336,66 +302,48 @@ fn claim_should_work() { assert_ok!(Deposit::lock(RuntimeOrigin::signed(1), UNIT, 1)); assert_ok!(Deposit::lock(RuntimeOrigin::signed(1), UNIT, 1)); assert_ok!(Deposit::lock(RuntimeOrigin::signed(1), UNIT, 1)); - assert_ok!(Staking::stake(RuntimeOrigin::signed(1), 2 * UNIT, 2 * UNIT, vec![0, 1, 2])); + assert_ok!(Staking::stake(RuntimeOrigin::signed(1), 2 * UNIT, vec![0, 1, 2])); assert_eq!(System::account(1).consumers, 2); - assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), UNIT, 0, Vec::new())); + assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), UNIT, Vec::new())); Efflux::block(1); - assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), 0, UNIT, Vec::new())); + assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), 0, vec![0])); Efflux::block(1); - assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), 0, 0, vec![0])); - Efflux::block(1); - assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), UNIT, UNIT, vec![1, 2])); + assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), UNIT, vec![1, 2])); assert_eq!(Balances::free_balance(1), 995 * UNIT); - assert_eq!(Assets::balance(0, 1), 1_000 * UNIT + 22_842_639_593_907); - assert_eq!( - Staking::ledger_of(1).unwrap(), - Ledger { - unstaking_ring: BoundedVec::truncate_from(vec![(UNIT, 6), (UNIT, 9)]), - unstaking_deposits: BoundedVec::truncate_from(vec![(0, 8), (1, 9), (2, 9)]), - ..ZeroDefault::default() - } - ); - - // 4 expired. - assert_ok!(Staking::claim(RuntimeOrigin::signed(1))); - assert_eq!(System::account(1).consumers, 2); - assert_eq!(Balances::free_balance(1), 996 * UNIT); assert_eq!( Staking::ledger_of(1).unwrap(), Ledger { - unstaking_ring: BoundedVec::truncate_from(vec![(UNIT, 9)]), - unstaking_deposits: BoundedVec::truncate_from(vec![(0, 8), (1, 9), (2, 9)]), + unstaking_ring: BoundedVec::truncate_from(vec![(UNIT, 6), (UNIT, 8)]), + unstaking_deposits: BoundedVec::truncate_from(vec![(0, 7), (1, 8), (2, 8)]), ..ZeroDefault::default() } ); - // 5 expired. Efflux::block(1); assert_ok!(Staking::claim(RuntimeOrigin::signed(1))); assert_eq!(System::account(1).consumers, 2); + assert_eq!(Balances::free_balance(1), 996 * UNIT); assert_eq!( Staking::ledger_of(1).unwrap(), Ledger { - unstaking_ring: BoundedVec::truncate_from(vec![(UNIT, 9)]), - unstaking_deposits: BoundedVec::truncate_from(vec![(0, 8), (1, 9), (2, 9)]), + unstaking_ring: BoundedVec::truncate_from(vec![(UNIT, 8)]), + unstaking_deposits: BoundedVec::truncate_from(vec![(0, 7), (1, 8), (2, 8)]), ..ZeroDefault::default() } ); - // 6 expired. Efflux::block(1); assert_ok!(Staking::claim(RuntimeOrigin::signed(1))); assert_eq!(System::account(1).consumers, 2); assert_eq!( Staking::ledger_of(1).unwrap(), Ledger { - unstaking_ring: BoundedVec::truncate_from(vec![(UNIT, 9)]), - unstaking_deposits: BoundedVec::truncate_from(vec![(1, 9), (2, 9)]), + unstaking_ring: BoundedVec::truncate_from(vec![(UNIT, 8)]), + unstaking_deposits: BoundedVec::truncate_from(vec![(1, 8), (2, 8)]), ..ZeroDefault::default() } ); - // 7 expired. Efflux::block(2); assert_ok!(Staking::claim(RuntimeOrigin::signed(1))); assert_eq!(System::account(1).consumers, 1); @@ -408,7 +356,7 @@ fn claim_should_work() { fn collect_should_work() { ExtBuilder::default().build().execute_with(|| { assert!(Staking::collator_of(1).is_none()); - assert_ok!(Staking::stake(RuntimeOrigin::signed(1), UNIT, 0, Vec::new())); + assert_ok!(Staking::stake(RuntimeOrigin::signed(1), UNIT, Vec::new())); (0..=99).for_each(|c| { let c = Perbill::from_percent(c); @@ -422,12 +370,12 @@ fn collect_should_work() { #[test] fn nominate_should_work() { ExtBuilder::default().build().execute_with(|| { - assert_ok!(Staking::stake(RuntimeOrigin::signed(1), UNIT, 0, Vec::new())); + assert_ok!(Staking::stake(RuntimeOrigin::signed(1), UNIT, Vec::new())); assert_ok!(Staking::collect(RuntimeOrigin::signed(1), Perbill::zero())); (2..=10).for_each(|n| { assert!(Staking::nominator_of(n).is_none()); - assert_ok!(Staking::stake(RuntimeOrigin::signed(n), UNIT, 0, Vec::new())); + assert_ok!(Staking::stake(RuntimeOrigin::signed(n), UNIT, Vec::new())); assert_ok!(Staking::nominate(RuntimeOrigin::signed(n), 1)); assert_eq!(Staking::nominator_of(n).unwrap(), 1); }); @@ -437,10 +385,10 @@ fn nominate_should_work() { #[test] fn chill_should_work() { ExtBuilder::default().build().execute_with(|| { - assert_ok!(Staking::stake(RuntimeOrigin::signed(1), UNIT, 0, Vec::new())); + assert_ok!(Staking::stake(RuntimeOrigin::signed(1), UNIT, Vec::new())); assert_ok!(Staking::collect(RuntimeOrigin::signed(1), Perbill::zero())); (2..=10).for_each(|n| { - assert_ok!(Staking::stake(RuntimeOrigin::signed(n), UNIT, 0, Vec::new())); + assert_ok!(Staking::stake(RuntimeOrigin::signed(n), UNIT, Vec::new())); assert_ok!(Staking::nominate(RuntimeOrigin::signed(n), 1)); }); assert!(Staking::collator_of(1).is_some()); @@ -469,142 +417,46 @@ fn set_collator_count_should_work() { }); } -#[test] -fn power_should_work() { - ExtBuilder::default().build().execute_with(|| { - assert_eq!(Staking::quick_power_of(&1), 0); - assert_eq!(Staking::quick_power_of(&2), 0); - assert_eq!(Staking::quick_power_of(&3), 0); - assert_eq!(Staking::quick_power_of(&4), 0); - - // 1 stakes 1 RING. - assert_ok!(Staking::stake(RuntimeOrigin::signed(1), UNIT, 0, Vec::new())); - assert_eq!(Staking::quick_power_of(&1), 500_000_000); - - // 2 stakes 1 KTON. - assert_ok!(Staking::stake(RuntimeOrigin::signed(2), 0, UNIT, Vec::new())); - assert_eq!(Staking::quick_power_of(&1), 500_000_000); - assert_eq!(Staking::quick_power_of(&2), 500_000_000); - - // 3 stakes 1 deposit. - assert_ok!(Deposit::lock(RuntimeOrigin::signed(3), UNIT, 1)); - assert_ok!(Staking::stake(RuntimeOrigin::signed(3), 0, 0, vec![0])); - assert_eq!(Staking::quick_power_of(&1), 250_000_000); - assert_eq!(Staking::quick_power_of(&2), 500_000_000); - assert_eq!(Staking::quick_power_of(&3), 250_000_000); - - // 4 stakes 1 KTON. - assert_ok!(Staking::stake(RuntimeOrigin::signed(4), 0, UNIT, Vec::new())); - assert_eq!(Staking::quick_power_of(&1), 250_000_000); - assert_eq!(Staking::quick_power_of(&2), 250_000_000); - assert_eq!(Staking::quick_power_of(&3), 250_000_000); - assert_eq!(Staking::quick_power_of(&4), 250_000_000); - - // 1 unstakes 1 RING. - assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), UNIT, 0, Vec::new())); - assert_eq!(Staking::quick_power_of(&1), 0); - assert_eq!(Staking::quick_power_of(&2), 250_000_000); - assert_eq!(Staking::quick_power_of(&3), 500_000_000); - assert_eq!(Staking::quick_power_of(&4), 250_000_000); - - // 2 unstakes 1 KTON. - assert_ok!(Staking::unstake(RuntimeOrigin::signed(2), 0, UNIT, Vec::new())); - assert_eq!(Staking::quick_power_of(&1), 0); - assert_eq!(Staking::quick_power_of(&2), 0); - assert_eq!(Staking::quick_power_of(&3), 500_000_000); - assert_eq!(Staking::quick_power_of(&4), 500_000_000); - - // 3 unstakes 1 deposit. - assert_ok!(Deposit::lock(RuntimeOrigin::signed(3), UNIT, 1)); - assert_ok!(Staking::unstake(RuntimeOrigin::signed(3), 0, 0, vec![0])); - assert_eq!(Staking::quick_power_of(&1), 0); - assert_eq!(Staking::quick_power_of(&2), 0); - assert_eq!(Staking::quick_power_of(&3), 0); - assert_eq!(Staking::quick_power_of(&4), 500_000_000); - - // 4 unstakes 1 KTON. - assert_ok!(Staking::unstake(RuntimeOrigin::signed(4), 0, UNIT, Vec::new())); - assert_eq!(Staking::quick_power_of(&1), 0); - assert_eq!(Staking::quick_power_of(&2), 0); - assert_eq!(Staking::quick_power_of(&3), 0); - assert_eq!(Staking::quick_power_of(&4), 0); - }); -} - #[test] fn elect_should_work() { ExtBuilder::default().collator_count(3).build().execute_with(|| { (1..=5).for_each(|i| { - assert_ok!(Staking::stake( - RuntimeOrigin::signed(i), - i as Balance * UNIT, - UNIT, - Vec::new() - )); + assert_ok!(Staking::stake(RuntimeOrigin::signed(i), i as Balance * UNIT, Vec::new())); assert_ok!(Staking::collect(RuntimeOrigin::signed(i), Perbill::zero())); assert_ok!(Staking::nominate(RuntimeOrigin::signed(i), i)); }); (6..=10).for_each(|i| { - assert_ok!(Staking::stake( - RuntimeOrigin::signed(i), - 0, - (11 - i as Balance) * UNIT, - Vec::new() - )); + assert_ok!(Staking::stake(RuntimeOrigin::signed(i), i as Balance * UNIT, Vec::new())); assert_ok!(Staking::nominate(RuntimeOrigin::signed(i), i - 5)); }); assert_eq!(Staking::elect().unwrap(), vec![5, 4, 3]); }); - ExtBuilder::default().collator_count(3).build().execute_with(|| { - (1..=5).for_each(|i| { - assert_ok!(Staking::stake( - RuntimeOrigin::signed(i), - i as Balance * UNIT, - 0, - Vec::new() - )); - assert_ok!(Staking::collect(RuntimeOrigin::signed(i), Perbill::zero())); - assert_ok!(Staking::nominate(RuntimeOrigin::signed(i), i)); - }); - (6..=10).for_each(|i| { - assert_ok!(Staking::stake( - RuntimeOrigin::signed(i), - UNIT, - (11 - i as Balance) * UNIT, - Vec::new() - )); - assert_ok!(Staking::nominate(RuntimeOrigin::signed(i), i - 5)); - }); - - assert_eq!(Staking::elect().unwrap(), vec![1, 2, 3]); - }); } #[test] fn payout_should_work() { ExtBuilder::default().collator_count(5).build().execute_with(|| { (1..=5).for_each(|i| { - assert_ok!(Staking::stake( - RuntimeOrigin::signed(i), - 0, - i as Balance * UNIT, - Vec::new() - )); + assert_ok!(Staking::stake(RuntimeOrigin::signed(i), i as Balance * UNIT, Vec::new())); assert_ok!(Staking::collect(RuntimeOrigin::signed(i), Perbill::from_percent(i * 10))); assert_ok!(Staking::nominate(RuntimeOrigin::signed(i), i)); }); (6..=10).for_each(|i| { assert_ok!(Staking::stake( RuntimeOrigin::signed(i), - 0, (11 - i as Balance) * UNIT, Vec::new() )); assert_ok!(Staking::nominate(RuntimeOrigin::signed(i), i - 5)); }); new_session(); - (1..=10).for_each(|i| assert_eq!(Balances::free_balance(i), 1_000 * UNIT)); + (1..=10).for_each(|i| { + assert_eq!( + Balances::free_balance(i), + (1_000 - if i < 6 { i } else { 11 - i }) as Balance * UNIT + ) + }); let session_duration = Duration::new(12 * 600, 0).as_millis(); Efflux::time(session_duration - >::get() as Moment); @@ -613,25 +465,29 @@ fn payout_should_work() { new_session(); payout(); - let rewards = vec![ - 364298724080145719490, - 680024276867030965392, - 947176684881602914390, - 1165755919271402550091, - 1335761993442622950820, - 1092896174426229508197, - 777170622950819672131, - 510018214936247723133, - 291438979672131147541, - 121432905646630236794, + let rewards = [ + 182149362040072859745, + 340012143096539162113, + 473588342440801457194, + 582877959635701275045, + 667880995628415300546, + 546448087213114754098, + 388585306229508196721, + 255009107468123861566, + 145719489836065573771, + 60716453916211293261, ]; assert_eq!( - rewards, - (1..=10).map(|i| Balances::free_balance(i) - 1_000 * UNIT).collect::>() + rewards.as_slice(), + (1..=10) + .map(|i| Balances::free_balance(i) + - (1_000 - if i < 6 { i } else { 11 - i }) as Balance * UNIT) + .collect::>() ); assert_eq_error_rate!( PayoutFraction::get() - * dc_inflation::issuing_in_period(session_duration, Timestamp::now()).unwrap(), + * dc_inflation::issuing_in_period(session_duration, Timestamp::now()).unwrap() + / 2, rewards.iter().sum::(), // Error rate 1 RING. UNIT @@ -640,19 +496,13 @@ fn payout_should_work() { ExtBuilder::default().inflation_type(1).collator_count(5).build().execute_with(|| { (1..=5).for_each(|i| { - assert_ok!(Staking::stake( - RuntimeOrigin::signed(i), - 0, - i as Balance * UNIT, - Vec::new() - )); + assert_ok!(Staking::stake(RuntimeOrigin::signed(i), i as Balance * UNIT, Vec::new())); assert_ok!(Staking::collect(RuntimeOrigin::signed(i), Perbill::from_percent(i * 10))); assert_ok!(Staking::nominate(RuntimeOrigin::signed(i), i)); }); (6..=10).for_each(|i| { assert_ok!(Staking::stake( RuntimeOrigin::signed(i), - 0, (11 - i as Balance) * UNIT, Vec::new() )); @@ -660,7 +510,12 @@ fn payout_should_work() { }); new_session(); new_session(); - (1..=10).for_each(|i| assert_eq!(Balances::free_balance(i), 1_000 * UNIT)); + (1..=10).for_each(|i| { + assert_eq!( + Balances::free_balance(i), + (1_000 - if i < 6 { i } else { 11 - i }) as Balance * UNIT + ) + }); let total_issuance = Balances::total_issuance(); let session_duration = Duration::new(12 * 600, 0).as_millis(); @@ -669,28 +524,27 @@ fn payout_should_work() { new_session(); payout(); - let rewards = vec![ - 499999998800000000000, - 933333320000000000000, - 1300000000000000000000, - 1599999999200000000000, - 1833333336000000000000, - 1499999999400000000000, - 1066666680000000000000, - 700000000000000000000, - 399999999600000000000, - 166666663000000000000, + let rewards = [ + 249999999400000000000, + 466666666400000000000, + 650000000000000000000, + 799999999600000000000, + 916666666500000000000, + 749999999700000000000, + 533333332800000000000, + 350000000000000000000, + 199999999800000000000, + 83333333000000000000, ]; assert_eq!( - rewards, - (1..=10).map(|i| Balances::free_balance(i) - 1_000 * UNIT).collect::>() + rewards.as_slice(), + (1..=10) + .map(|i| Balances::free_balance(i) + - (1_000 - if i < 6 { i } else { 11 - i }) as Balance * UNIT) + .collect::>() ); assert_eq!(Balances::total_issuance(), total_issuance); - assert_eq!( - Balances::free_balance(&Treasury::account_id()), - 1_000_000 * UNIT - rewards.iter().sum::() - ); assert_ok!(Balances::transfer_all( RuntimeOrigin::signed(Treasury::account_id()), @@ -711,8 +565,9 @@ fn payout_should_work() { }) .collect::>(), vec![ - Event::Unpaid { staker: 6, amount: 7499999997000000000000 }, - Event::Unpaid { staker: 1, amount: 2499999994000000000000 } + Event::Unpaid { who: 0, amount: 5000000000000000000000 }, + Event::Unpaid { who: 6, amount: 3749999998500000000000 }, + Event::Unpaid { who: 1, amount: 1249999997000000000000 } ] ); }); @@ -722,20 +577,14 @@ fn payout_should_work() { fn auto_payout_should_work() { ExtBuilder::default().collator_count(2).build().execute_with(|| { (1..=2).for_each(|i| { - assert_ok!(Staking::stake( - RuntimeOrigin::signed(i), - 0, - i as Balance * UNIT, - Vec::new() - )); + assert_ok!(Staking::stake(RuntimeOrigin::signed(i), i as Balance * UNIT, Vec::new())); assert_ok!(Staking::collect(RuntimeOrigin::signed(i), Perbill::from_percent(i * 10))); assert_ok!(Staking::nominate(RuntimeOrigin::signed(i), i)); }); (3..=4).for_each(|i| { assert_ok!(Staking::stake( RuntimeOrigin::signed(i), - 0, - (11 - i as Balance) * UNIT, + (5 - i as Balance) * UNIT, Vec::new() )); assert_ok!(Staking::nominate(RuntimeOrigin::signed(i), i - 2)); @@ -746,25 +595,60 @@ fn auto_payout_should_work() { Efflux::time(>::get() as Moment); Staking::note_authors(&[1, 2]); new_session(); - (1..=4).for_each(|i| assert_eq!(Balances::free_balance(i), 1_000 * UNIT)); + (1..=4).for_each(|i| { + assert_eq!( + Balances::free_balance(i), + (1_000 - if i < 3 { i } else { 5 - i }) as Balance * UNIT + ) + }); Efflux::block(1); - assert_eq!(Balances::free_balance(1), 1000000607164541287188); - assert_eq!(Balances::free_balance(2), 1000000000000000000000); - assert_eq!(Balances::free_balance(3), 1000002428658163934426); - assert_eq!(Balances::free_balance(4), 1000000000000000000000); + assert_eq!( + [ + Balances::free_balance(1), + Balances::free_balance(2), + Balances::free_balance(3), + Balances::free_balance(4), + ], + [ + 999000607164541135398, + 998000000000000000000, + 998000910746811475409, + 999000000000000000000 + ] + ); Efflux::block(1); - assert_eq!(Balances::free_balance(1), 1000000607164541287188); - assert_eq!(Balances::free_balance(2), 1000001146866363084396); - assert_eq!(Balances::free_balance(3), 1000002428658163934426); - assert_eq!(Balances::free_balance(4), 1000001888956344869459); + assert_eq!( + [ + Balances::free_balance(1), + Balances::free_balance(2), + Balances::free_balance(3), + Balances::free_balance(4), + ], + [ + 999000607164541135398, + 998001113134992106860, + 998000910746811475409, + 999000404776360655738 + ] + ); Efflux::block(1); - assert_eq!(Balances::free_balance(1), 1000000607164541287188); - assert_eq!(Balances::free_balance(2), 1000001146866363084396); - assert_eq!(Balances::free_balance(3), 1000002428658163934426); - assert_eq!(Balances::free_balance(4), 1000001888956344869459); + assert_eq!( + [ + Balances::free_balance(1), + Balances::free_balance(2), + Balances::free_balance(3), + Balances::free_balance(4), + ], + [ + 999000607164541135398, + 998001113134992106860, + 998000910746811475409, + 999000404776360655738 + ] + ); }); } @@ -789,7 +673,7 @@ fn on_new_session_should_work() { ); assert_ok!(Staking::collect(RuntimeOrigin::signed(3), Perbill::zero())); - assert_ok!(Staking::stake(RuntimeOrigin::signed(3), 2 * UNIT, 0, Vec::new())); + assert_ok!(Staking::stake(RuntimeOrigin::signed(3), 2 * UNIT, Vec::new())); assert_ok!(Staking::nominate(RuntimeOrigin::signed(3), 3)); Staking::note_authors(&Session::validators()); @@ -813,7 +697,7 @@ fn on_new_session_should_work() { assert_ok!(Staking::chill(RuntimeOrigin::signed(3))); assert_ok!(Staking::collect(RuntimeOrigin::signed(4), Perbill::zero())); - assert_ok!(Staking::stake(RuntimeOrigin::signed(4), 2 * UNIT, 0, Vec::new())); + assert_ok!(Staking::stake(RuntimeOrigin::signed(4), 2 * UNIT, Vec::new())); assert_ok!(Staking::nominate(RuntimeOrigin::signed(4), 4)); Staking::note_authors(&Session::validators()); @@ -837,7 +721,7 @@ fn on_new_session_should_work() { assert_ok!(Staking::chill(RuntimeOrigin::signed(4))); assert_ok!(Staking::collect(RuntimeOrigin::signed(5), Perbill::zero())); - assert_ok!(Staking::stake(RuntimeOrigin::signed(5), 2 * UNIT, 0, Vec::new())); + assert_ok!(Staking::stake(RuntimeOrigin::signed(5), 2 * UNIT, Vec::new())); assert_ok!(Staking::nominate(RuntimeOrigin::signed(5), 5)); Staking::note_authors(&Session::validators()); @@ -860,33 +744,3 @@ fn on_new_session_should_work() { ); }); } - -#[test] -fn migration_curves_should_work() { - ExtBuilder::default().build().execute_with(|| { - System::set_block_number(10); - >::put(10); - - assert_eq!( - vec![0, 1, 7, 14, 21, 29, 30, 31, 999] - .into_iter() - .map(|x| { - System::set_block_number(10 + x * 24 * 60 * 60 / 12); - - format!("{:?}", >::get()) - }) - .collect::>(), - [ - "99.9995370370370371%", - "96.6666666666666667%", - "76.6666666666666667%", - "53.3333333333333334%", - "30%", - "3.3333333333333334%", - "0%", - "0%", - "0%" - ] - ); - }); -} diff --git a/precompile/metadata/abi/staking.json b/precompile/metadata/abi/staking.json index 8274c2672..b5e6bdc0b 100644 --- a/precompile/metadata/abi/staking.json +++ b/precompile/metadata/abi/staking.json @@ -130,11 +130,6 @@ "name": "ringAmount", "type": "uint256" }, - { - "internalType": "uint256", - "name": "ktonAmount", - "type": "uint256" - }, { "internalType": "uint16[]", "name": "depositIds", @@ -161,11 +156,6 @@ "name": "ringAmount", "type": "uint256" }, - { - "internalType": "uint256", - "name": "ktonAmount", - "type": "uint256" - }, { "internalType": "uint16[]", "name": "depositIds", @@ -255,13 +245,12 @@ "_0": "true on success, false otherwise." } }, - "stake(uint256,uint256,uint16[])": + "stake(uint256,uint16[])": { "details": "Add stakes to the staking pool.", "params": { "depositIds": "The deposit ids list", - "ktonAmount": "The amount of staking KTON asset", "ringAmount": "The amount of staking RING asset" }, "returns": @@ -269,13 +258,12 @@ "_0": "returns true on success, false otherwise." } }, - "unstake(uint256,uint256,uint16[])": + "unstake(uint256,uint16[])": { "details": "Withdraw stakes to the staking pool.", "params": { "depositIds": "The deposit ids list", - "ktonAmount": "The amount of staking KTON asset", "ringAmount": "The amount of staking RING asset" }, "returns": @@ -295,8 +283,8 @@ "nominate(address)": "b332180b", "payout(address)": "0b7e9c44", "restake(uint256,uint16[])": "1ed0818e", - "stake(uint256,uint256,uint16[])": "98e9fb50", - "unstake(uint256,uint256,uint16[])": "632efe00" + "stake(uint256,uint16[])": "88fd3d50", + "unstake(uint256,uint16[])": "0e198447" } } }, diff --git a/precompile/metadata/sol/staking.sol b/precompile/metadata/sol/staking.sol index 5457bf442..25f6bb95c 100644 --- a/precompile/metadata/sol/staking.sol +++ b/precompile/metadata/sol/staking.sol @@ -29,23 +29,19 @@ Staking constant STAKING_CONTRACT = Staking(STAKING_ADDRESS); interface Staking { /// @dev Add stakes to the staking pool. /// @param ringAmount The amount of staking RING asset - /// @param ktonAmount The amount of staking KTON asset /// @param depositIds The deposit ids list /// @return returns true on success, false otherwise. function stake( uint256 ringAmount, - uint256 ktonAmount, uint16[] memory depositIds ) external returns (bool); /// @dev Withdraw stakes to the staking pool. /// @param ringAmount The amount of staking RING asset - /// @param ktonAmount The amount of staking KTON asset /// @param depositIds The deposit ids list /// @return returns true on success, false otherwise. function unstake( uint256 ringAmount, - uint256 ktonAmount, uint16[] memory depositIds ) external returns (bool); diff --git a/precompile/staking/src/lib.rs b/precompile/staking/src/lib.rs index 012cd227a..931d6633d 100644 --- a/precompile/staking/src/lib.rs +++ b/precompile/staking/src/lib.rs @@ -53,11 +53,10 @@ where <::RuntimeCall as Dispatchable>::RuntimeOrigin: OriginTrait, <::Deposit as Stake>::Item: From, { - #[precompile::public("stake(uint256,uint256,uint16[])")] + #[precompile::public("stake(uint256,uint16[])")] fn stake( handle: &mut impl PrecompileHandle, ring_amount: U256, - kton_amount: U256, deposits: Vec, ) -> EvmResult { let origin = handle.context().caller.into(); @@ -68,18 +67,16 @@ where Some(origin).into(), darwinia_staking::Call::::stake { ring_amount: ring_amount.as_u128(), - kton_amount: kton_amount.as_u128(), deposits, }, )?; Ok(true) } - #[precompile::public("unstake(uint256,uint256,uint16[])")] + #[precompile::public("unstake(uint256,uint16[])")] fn unstake( handle: &mut impl PrecompileHandle, ring_amount: U256, - kton_amount: U256, deposits: Vec, ) -> EvmResult { let origin = handle.context().caller.into(); @@ -90,7 +87,6 @@ where Some(origin).into(), darwinia_staking::Call::::unstake { ring_amount: ring_amount.as_u128(), - kton_amount: kton_amount.as_u128(), deposits, }, )?; diff --git a/precompile/staking/src/mock.rs b/precompile/staking/src/mock.rs index a24b9b46f..92c39f686 100644 --- a/precompile/staking/src/mock.rs +++ b/precompile/staking/src/mock.rs @@ -192,7 +192,6 @@ impl pallet_evm::Config for Runtime { frame_support::parameter_types! { pub const PayoutFraction: sp_runtime::Perbill = sp_runtime::Perbill::from_percent(40); } - pub enum RingStaking {} impl darwinia_staking::Stake for RingStaking { type AccountId = AccountId; @@ -216,21 +215,19 @@ impl darwinia_staking::Stake for RingStaking { ) } } - pub enum KtonStaking {} impl darwinia_staking::Stake for KtonStaking { type AccountId = AccountId; type Item = Balance; - fn stake(_who: &Self::AccountId, _item: Self::Item) -> sp_runtime::DispatchResult { + fn stake(_: &Self::AccountId, _: Self::Item) -> sp_runtime::DispatchResult { Ok(()) } - fn unstake(_who: &Self::AccountId, _item: Self::Item) -> sp_runtime::DispatchResult { + fn unstake(_: &Self::AccountId, _: Self::Item) -> sp_runtime::DispatchResult { Ok(()) } } - impl darwinia_staking::Config for Runtime { type Currency = Balances; type Deposit = Deposit; @@ -240,7 +237,6 @@ impl darwinia_staking::Config for Runtime { type KtonStakerNotifier = (); type MaxDeposits = ::MaxDeposits; type MaxUnstakings = frame_support::traits::ConstU32<16>; - type MigrationCurve = (); type MinStakingDuration = frame_support::traits::ConstU64<3>; type Ring = RingStaking; type RuntimeEvent = RuntimeEvent; diff --git a/precompile/staking/src/tests.rs b/precompile/staking/src/tests.rs index 751f4a479..6ebefa1b5 100644 --- a/precompile/staking/src/tests.rs +++ b/precompile/staking/src/tests.rs @@ -25,7 +25,7 @@ use sp_runtime::Perbill; // moonbeam use precompile_utils::testing::PrecompileTesterExt; // substrate -use sp_core::{H160, U256}; +use sp_core::H160; fn precompiles() -> TestPrecompiles { PrecompilesValue::get() @@ -33,9 +33,9 @@ fn precompiles() -> TestPrecompiles { #[test] fn selectors() { - assert!(PCall::stake_selectors().contains(&0x98e9fb50)); - assert!(PCall::unstake_selectors().contains(&0x632efe00)); - assert!(PCall::restake_selectors().contains(&0x1ed0818e)); + assert!(PCall::stake_selectors().contains(&0x88FD3D50)); + assert!(PCall::unstake_selectors().contains(&0xE198447)); + assert!(PCall::restake_selectors().contains(&0x1ED0818E)); assert!(PCall::claim_selectors().contains(&0x4e71d92d)); assert!(PCall::nominate_selectors().contains(&0xb332180b)); assert!(PCall::collect_selectors().contains(&0x10a66536)); @@ -52,11 +52,7 @@ fn stake_unstake_restake() { .prepare_test( alice, Precompile, - PCall::stake { - ring_amount: 200.into(), - kton_amount: U256::zero(), - deposits: vec![], - }, + PCall::stake { ring_amount: 200.into(), deposits: vec![] }, ) .execute_returns(true); assert_eq!(Staking::ledger_of(alice).unwrap().staked_ring, 200); @@ -66,11 +62,7 @@ fn stake_unstake_restake() { .prepare_test( alice, Precompile, - PCall::unstake { - ring_amount: 200.into(), - kton_amount: U256::zero(), - deposits: vec![], - }, + PCall::unstake { ring_amount: 200.into(), deposits: vec![] }, ) .execute_returns(true); assert_eq!(Staking::ledger_of(alice).unwrap().staked_ring, 0); @@ -98,11 +90,7 @@ fn claim() { .prepare_test( alice, Precompile, - PCall::stake { - ring_amount: 200.into(), - kton_amount: U256::zero(), - deposits: vec![], - }, + PCall::stake { ring_amount: 200.into(), deposits: vec![] }, ) .execute_returns(true); @@ -111,11 +99,7 @@ fn claim() { .prepare_test( alice, Precompile, - PCall::unstake { - ring_amount: 200.into(), - kton_amount: U256::zero(), - deposits: vec![], - }, + PCall::unstake { ring_amount: 200.into(), deposits: vec![] }, ) .execute_returns(true); @@ -137,11 +121,7 @@ fn nominate() { .prepare_test( alice, Precompile, - PCall::stake { - ring_amount: 200.into(), - kton_amount: U256::zero(), - deposits: vec![], - }, + PCall::stake { ring_amount: 200.into(), deposits: vec![] }, ) .execute_returns(true); @@ -156,11 +136,7 @@ fn nominate() { .prepare_test( bob, Precompile, - PCall::stake { - ring_amount: 200.into(), - kton_amount: U256::zero(), - deposits: vec![], - }, + PCall::stake { ring_amount: 200.into(), deposits: vec![] }, ) .execute_returns(true); diff --git a/runtime/common/src/test.rs b/runtime/common/src/test.rs index 4090650cf..11dfef512 100644 --- a/runtime/common/src/test.rs +++ b/runtime/common/src/test.rs @@ -23,7 +23,7 @@ macro_rules! impl_account_migration_tests { // darwinia use super::mock::*; use darwinia_deposit::Deposit as DepositS; - use darwinia_staking::Ledger; + use darwinia_staking::migration::v2::OldLedger; // substrate use frame_support::{ assert_err, assert_ok, migration, Blake2_128Concat, StorageHasher, @@ -306,14 +306,7 @@ macro_rules! impl_account_migration_tests { ); >::insert( &from_pk, - Ledger { - staked_ring: 20, - staked_kton: 20, - staked_deposits: Default::default(), - unstaking_ring: Default::default(), - unstaking_kton: Default::default(), - unstaking_deposits: Default::default(), - }, + OldLedger { staked_ring: 20, ..Default::default() }, ); assert_ok!(migrate(from, to)); @@ -327,20 +320,10 @@ macro_rules! impl_account_migration_tests { 20 ); assert_eq!(Deposit::deposit_of(to).unwrap().len(), 2); - assert_eq!(Assets::maybe_balance(KTON_ID, to).unwrap(), 80); - assert_eq!( - Assets::maybe_balance( - KTON_ID, - darwinia_staking::account_id::() - ) - .unwrap(), - 20 - ); + assert_eq!(Assets::maybe_balance(KTON_ID, to).unwrap(), 100); assert_eq!(DarwiniaStaking::ledger_of(to).unwrap().staked_ring, 20); - assert_eq!(DarwiniaStaking::ledger_of(to).unwrap().staked_kton, 20); }); } - #[test] fn identities_should_work() { let (from, from_pk) = alice(); diff --git a/runtime/crab/src/lib.rs b/runtime/crab/src/lib.rs index 29a7854ff..7ead8416d 100644 --- a/runtime/crab/src/lib.rs +++ b/runtime/crab/src/lib.rs @@ -65,7 +65,7 @@ pub type Executive = frame_executive::Executive< frame_system::ChainContext, Runtime, AllPalletsWithSystem, - migration::CustomOnRuntimeUpgrade, + (migration::CustomOnRuntimeUpgrade, darwinia_staking::migration::v2::MigrateToV2), >; /// Runtime version. diff --git a/runtime/crab/src/pallets/staking.rs b/runtime/crab/src/pallets/staking.rs index 03c23b4e1..f9063551e 100644 --- a/runtime/crab/src/pallets/staking.rs +++ b/runtime/crab/src/pallets/staking.rs @@ -109,7 +109,6 @@ impl darwinia_staking::Config for Runtime { type KtonStakerNotifier = darwinia_staking::KtonStakerNotifier; type MaxDeposits = ::MaxDeposits; type MaxUnstakings = ConstU32<16>; - type MigrationCurve = darwinia_staking::MigrationCurve; type MinStakingDuration = MinStakingDuration; type Ring = RingStaking; type RuntimeEvent = RuntimeEvent; diff --git a/runtime/darwinia/src/lib.rs b/runtime/darwinia/src/lib.rs index 751faa327..3b8e5907e 100644 --- a/runtime/darwinia/src/lib.rs +++ b/runtime/darwinia/src/lib.rs @@ -65,7 +65,7 @@ pub type Executive = frame_executive::Executive< frame_system::ChainContext, Runtime, AllPalletsWithSystem, - migration::CustomOnRuntimeUpgrade, + (migration::CustomOnRuntimeUpgrade, darwinia_staking::migration::v2::MigrateToV2), >; /// Runtime version. diff --git a/runtime/darwinia/src/pallets/staking.rs b/runtime/darwinia/src/pallets/staking.rs index ea79ae18b..1d10f0e6a 100644 --- a/runtime/darwinia/src/pallets/staking.rs +++ b/runtime/darwinia/src/pallets/staking.rs @@ -120,7 +120,6 @@ impl darwinia_staking::Config for Runtime { type KtonStakerNotifier = darwinia_staking::KtonStakerNotifier; type MaxDeposits = ::MaxDeposits; type MaxUnstakings = ConstU32<16>; - type MigrationCurve = darwinia_staking::MigrationCurve; type MinStakingDuration = MinStakingDuration; type Ring = RingStaking; type RuntimeEvent = RuntimeEvent; diff --git a/runtime/pangolin/src/lib.rs b/runtime/pangolin/src/lib.rs index 3cf424bb8..a4328e7cf 100644 --- a/runtime/pangolin/src/lib.rs +++ b/runtime/pangolin/src/lib.rs @@ -66,7 +66,7 @@ pub type Executive = frame_executive::Executive< frame_system::ChainContext, Runtime, AllPalletsWithSystem, - migration::CustomOnRuntimeUpgrade, + (migration::CustomOnRuntimeUpgrade, darwinia_staking::migration::v2::MigrateToV2), >; /// Runtime version. diff --git a/runtime/pangolin/src/migration.rs b/runtime/pangolin/src/migration.rs index 786f2f1d8..0105631a1 100644 --- a/runtime/pangolin/src/migration.rs +++ b/runtime/pangolin/src/migration.rs @@ -29,11 +29,6 @@ impl frame_support::traits::OnRuntimeUpgrade for CustomOnRuntimeUpgrade { fn pre_upgrade() -> Result, sp_runtime::DispatchError> { log::info!("pre"); - >::iter().for_each(|(k, v)| { - log::info!("{k:?}"); - log::info!("{v:?}"); - }); - Ok(Vec::new()) } @@ -41,13 +36,6 @@ impl frame_support::traits::OnRuntimeUpgrade for CustomOnRuntimeUpgrade { fn post_upgrade(_state: Vec) -> Result<(), sp_runtime::DispatchError> { log::info!("post"); - >::iter().for_each(|(k, v)| { - log::info!("{k:?}"); - log::info!("{v:?}"); - - assert!(!v.is_empty()); - }); - Ok(()) } @@ -57,71 +45,6 @@ impl frame_support::traits::OnRuntimeUpgrade for CustomOnRuntimeUpgrade { } fn migrate() -> frame_support::weights::Weight { - let mut r = 0; - let mut w = 1; - let _ = - migration::clear_storage_prefix(b"MessageGadget", b"CommitmentContract", &[], None, None); - let lock_ids = [ - // Democracy lock. - *b"democrac", - // Fee market lock. - *b"da/feecr", - ]; - - >::iter().for_each(|(k, mut v)| { - if v.is_empty() { - // Clear the storage entry if the vector is empty. - - >::remove(k); - - w += 1; - } else { - // Find matching lock ids and remove them. - - let mut changed = false; - - v.retain(|l| { - if lock_ids.contains(&l.id) { - // Mark as changed, the storage entry needs to be updated. - changed = true; - - // To remove. - false - } else { - // To keep. - true - } - }); - - if changed { - if v.is_empty() { - // Clear the storage entry if the vector is empty. - - >::remove(k); - } else { - >::insert(k, v); - } - - w += 1; - } - } - - r += 1; - }); - - w += migration_helper::PalletCleaner { - name: b"EcdsaAuthority", - values: &[ - b"Authorities", - b"NextAuthorities", - b"Nonce", - b"AuthoritiesChangeToSign", - b"MessageRootToSign", - ], - maps: &[], - } - .remove_all(); - - // frame_support::weights::Weight::zero() - ::DbWeight::get().reads_writes(r as _, w as _) + frame_support::weights::Weight::zero() + // ::DbWeight::get().reads_writes(r as _, w as _) } diff --git a/runtime/pangolin/src/pallets/staking.rs b/runtime/pangolin/src/pallets/staking.rs index 072c136bd..de9baa44e 100644 --- a/runtime/pangolin/src/pallets/staking.rs +++ b/runtime/pangolin/src/pallets/staking.rs @@ -103,7 +103,6 @@ impl darwinia_staking::Config for Runtime { type KtonStakerNotifier = darwinia_staking::KtonStakerNotifier; type MaxDeposits = ::MaxDeposits; type MaxUnstakings = ConstU32<16>; - type MigrationCurve = darwinia_staking::MigrationCurve; type MinStakingDuration = ConstU32<{ 2 * MINUTES }>; type Ring = RingStaking; type RuntimeEvent = RuntimeEvent;