From 0bf4278d0a1f07966549f76afc73006198810d2f Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Tue, 16 Apr 2024 03:15:09 +0800 Subject: [PATCH 1/6] Remove unstake duration --- pallet/account-migration/src/benchmarking.rs | 3 +- pallet/account-migration/src/lib.rs | 37 +-- pallet/account-migration/src/mock.rs | 2 - pallet/staking/src/benchmarking.rs | 55 +--- pallet/staking/src/lib.rs | 223 ++--------------- pallet/staking/src/migration/v2.rs | 28 ++- pallet/staking/src/mock.rs | 16 -- pallet/staking/src/tests.rs | 234 ++++++------------ pallet/staking/src/weights.rs | 84 ------- pallet/staking/traits/src/lib.rs | 2 +- precompile/staking/src/lib.rs | 32 --- precompile/staking/src/mock.rs | 2 - precompile/staking/src/tests.rs | 47 +--- runtime/common/src/test.rs | 2 +- runtime/crab/src/pallets/staking.rs | 4 - runtime/crab/src/weights/darwinia_staking.rs | 35 --- runtime/darwinia/src/pallets/staking.rs | 4 - .../darwinia/src/weights/darwinia_staking.rs | 35 --- runtime/pangolin/src/pallets/staking.rs | 2 - .../pangolin/src/weights/darwinia_staking.rs | 35 --- 20 files changed, 131 insertions(+), 751 deletions(-) diff --git a/pallet/account-migration/src/benchmarking.rs b/pallet/account-migration/src/benchmarking.rs index f92f845aa..967879e6e 100644 --- a/pallet/account-migration/src/benchmarking.rs +++ b/pallet/account-migration/src/benchmarking.rs @@ -126,8 +126,7 @@ mod benchmarks { Default::default(), Default::default() ); - ::MaxUnstakings::get() - as usize + 16 ]), ..Default::default() }, diff --git a/pallet/account-migration/src/lib.rs b/pallet/account-migration/src/lib.rs index db70bcfda..50d5c53bb 100644 --- a/pallet/account-migration/src/lib.rs +++ b/pallet/account-migration/src/lib.rs @@ -463,7 +463,16 @@ pub mod pallet { migration::put_storage_value(b"Identity", b"Registrars", &[], rs); } - if let Some(mut l) = >::take(from) { + if let Some(l) = >::take(from) { + if l.staked_ring > 0 { + as Currency<_>>::transfer( + to, + &darwinia_staking::account_id(), + l.staked_ring, + AllowDeath, + )?; + } + if let Some(ds) = >::take(from) { as Currency<_>>::transfer( to, @@ -477,33 +486,9 @@ pub mod pallet { ); } - let now = >::block_number(); - - l.unstaking_ring.retain(|(_, t)| t > &now); - - let staking_pot = darwinia_staking::account_id(); - let r = l.staked_ring + l.unstaking_ring.iter().map(|(r, _)| r).sum::(); - - // To calculated the worst case in benchmark. - debug_assert!(r > 0); - - if r > 0 { - as Currency<_>>::transfer( - to, - &staking_pot, - r, - AllowDeath, - )?; - } - >::insert( to, - Ledger { - staked_ring: l.staked_ring, - staked_deposits: l.staked_deposits, - unstaking_ring: l.unstaking_ring, - unstaking_deposits: l.unstaking_deposits, - }, + Ledger { ring: l.staked_ring, deposits: l.staked_deposits }, ); } diff --git a/pallet/account-migration/src/mock.rs b/pallet/account-migration/src/mock.rs index b2b6df46e..fdacda554 100644 --- a/pallet/account-migration/src/mock.rs +++ b/pallet/account-migration/src/mock.rs @@ -167,8 +167,6 @@ impl darwinia_staking::Config for Runtime { type KtonRewardDistributionContract = (); type KtonStakerNotifier = (); type MaxDeposits = (); - type MaxUnstakings = (); - type MinStakingDuration = (); type Ring = Dummy; type RuntimeEvent = RuntimeEvent; type ShouldEndSession = (); diff --git a/pallet/staking/src/benchmarking.rs b/pallet/staking/src/benchmarking.rs index 4e604c122..f6f01c8ef 100644 --- a/pallet/staking/src/benchmarking.rs +++ b/pallet/staking/src/benchmarking.rs @@ -36,7 +36,7 @@ mod benchmarks { where T: Config + darwinia_deposit::Config, { - (0..count.min(<::MaxUnstakings>::get()) as u8) + (0..count.min(<::MaxDeposits>::get()) as u16) .map(|x| { >::lock( RawOrigin::Signed(who.to_owned()).into(), @@ -62,7 +62,7 @@ mod benchmarks { // Worst-case scenario: // - // The total number of deposit items has reached `Config::MaxUnstakings`. + // The total number of deposit items has reached `darwinia_deposits::Config::MaxDeposits`. #[extrinsic_call] _(RawOrigin::Signed(a), UNIT, deposits); } @@ -81,60 +81,11 @@ mod benchmarks { // Worst-case scenario: // - // The total number of deposit items has reached `Config::MaxUnstakings`. + // The total number of deposit items has reached `darwinia_deposits::Config::MaxDeposits`. #[extrinsic_call] _(RawOrigin::Signed(a), UNIT, deposits); } - #[benchmark] - fn restake(x: Linear<0, 1_023>) { - let a = frame_benchmarking::whitelisted_caller(); - - // Remove `+ 1` after https://github.com/paritytech/substrate/pull/13655. - ::Ring::make_free_balance_be(&a, 1_024 * UNIT + 1); - ::Kton::mint(&a, UNIT).unwrap(); - - let deposits = deposit_for::(&a, x); - - >::stake(RawOrigin::Signed(a.clone()).into(), UNIT, deposits.clone()).unwrap(); - >::unstake(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, deposits); - } - - #[benchmark] - fn claim() { - let a = frame_benchmarking::whitelisted_caller(); - - // Remove `+ 1` after https://github.com/paritytech/substrate/pull/13655. - ::Ring::make_free_balance_be(&a, 1_024 * UNIT + 1); - ::Kton::mint(&a, UNIT).unwrap(); - - let deposits = deposit_for::(&a, ::MaxUnstakings::get()); - - >::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(), - ); - - assert!(>::contains_key(&a)); - - // Worst-case scenario: - // - // The total number of deposit items has reached `Config::MaxUnstakings`. - // In addition, all `RING` and `KTON` should be claimed, to make ledger get killed. - #[extrinsic_call] - _(RawOrigin::Signed(a.clone())); - - assert!(!>::contains_key(&a)); - } - #[benchmark] fn collect() { let a = frame_benchmarking::whitelisted_caller(); diff --git a/pallet/staking/src/lib.rs b/pallet/staking/src/lib.rs index 89de74106..225760e1b 100644 --- a/pallet/staking/src/lib.rs +++ b/pallet/staking/src/lib.rs @@ -135,18 +135,10 @@ pub mod pallet { /// Pass [`pallet_session::Config::ShouldEndSession`]'s result to here. type ShouldEndSession: Get; - /// Minimum time to stake at least. - #[pallet::constant] - type MinStakingDuration: Get>; - /// Maximum deposit count. #[pallet::constant] type MaxDeposits: Get; - /// Maximum unstaking/unbonding count. - #[pallet::constant] - type MaxUnstakings: Get; - /// The address of KTON reward distribution contract. #[pallet::constant] type KtonRewardDistributionContract: Get; @@ -373,18 +365,13 @@ pub mod pallet { } else { >::inc_consumers(&who)?; - *l = Some(Ledger { - staked_ring: Default::default(), - staked_deposits: Default::default(), - unstaking_ring: Default::default(), - unstaking_deposits: Default::default(), - }); + *l = Some(Ledger { ring: Default::default(), deposits: Default::default() }); l.as_mut().expect("[pallet::staking] `l` must be some; qed") }; if ring_amount != 0 { - Self::stake_ring(&who, &mut l.staked_ring, ring_amount)?; + Self::stake_ring(&who, &mut l.ring, ring_amount)?; } for d in deposits.clone() { @@ -417,60 +404,28 @@ pub mod pallet { let l = l.as_mut().ok_or(>::NotStaker)?; if ring_amount != 0 { - Self::unstake_ring(&mut l.staked_ring, &mut l.unstaking_ring, ring_amount)?; - } + l.ring = l + .ring + .checked_sub(ring_amount) + .ok_or("[pallet::staking] `u128` must not be overflowed; qed")?; - for d in deposits { - Self::unstake_deposit(l, d)?; - } - - DispatchResult::Ok(()) - })?; - - Ok(()) - } - - /// Cancel the `unstake` operation. - /// - /// Re-stake the unstaking assets immediately. - #[pallet::call_index(2)] - #[pallet::weight(::WeightInfo::restake(deposits.len() as _))] - pub fn restake( - origin: OriginFor, - ring_amount: Balance, - deposits: Vec>, - ) -> DispatchResult { - let who = ensure_signed(origin)?; - - if ring_amount == 0 && deposits.is_empty() { - return Ok(()); - } - - >::try_mutate(&who, |l| { - let l = l.as_mut().ok_or(>::NotStaker)?; - - if ring_amount != 0 { - Self::restake_ring(&mut l.staked_ring, &mut l.unstaking_ring, ring_amount)?; + ::Ring::unstake(&who, ring_amount)?; } for d in deposits { - Self::restake_deposit(l, d)?; + l.deposits.remove( + l.deposits + .iter() + .position(|d_| d_ == &d) + .ok_or(>::DepositNotFound)?, + ); + + T::Deposit::unstake(&who, d)?; } DispatchResult::Ok(()) })?; - Ok(()) - } - - /// Claim the stakes from the pallet/contract account. - #[pallet::call_index(3)] - #[pallet::weight(::WeightInfo::claim())] - pub fn claim(origin: OriginFor) -> DispatchResult { - let who = ensure_signed(origin)?; - - // Deposit doesn't need to be claimed. - Self::claim_unstakings(&who)?; Self::try_clean_ledger_of(&who); Ok(()) @@ -578,140 +533,11 @@ pub mod pallet { ) -> DispatchResult { T::Deposit::stake(who, deposit)?; - ledger.staked_deposits.try_push(deposit).map_err(|_| >::ExceedMaxDeposits)?; - - Ok(()) - } - - fn unstake_ring( - staked: &mut Balance, - unstaking: &mut BoundedVec<(Balance, BlockNumberFor), T::MaxUnstakings>, - amount: Balance, - ) -> DispatchResult { - *staked = staked - .checked_sub(amount) - .ok_or("[pallet::staking] `u128` must not be overflowed; qed")?; - - unstaking - .try_push(( - amount, - >::block_number() + T::MinStakingDuration::get(), - )) - .map_err(|_| >::ExceedMaxUnstakings)?; + ledger.deposits.try_push(deposit).map_err(|_| >::ExceedMaxDeposits)?; Ok(()) } - fn unstake_deposit(ledger: &mut Ledger, deposit: DepositId) -> DispatchResult { - ledger - .unstaking_deposits - .try_push(( - ledger.staked_deposits.remove( - ledger - .staked_deposits - .iter() - .position(|d| d == &deposit) - .ok_or(>::DepositNotFound)?, - ), - >::block_number() + T::MinStakingDuration::get(), - )) - .map_err(|_| >::ExceedMaxUnstakings)?; - - Ok(()) - } - - fn restake_ring( - staked: &mut Balance, - unstaking: &mut BoundedVec<(Balance, BlockNumberFor), T::MaxUnstakings>, - mut amount: Balance, - ) -> DispatchResult { - let mut actual_restake = 0; - - // Cancel the latest `unstake` first. - while let Some((u, _)) = unstaking.last_mut() { - if let Some(k) = u.checked_sub(amount) { - actual_restake += amount; - *u = k; - - if k == 0 { - unstaking - .pop() - .ok_or("[pallet::staking] record must exist, due to `last_mut`; qed")?; - } - - break; - } else { - actual_restake += *u; - amount -= *u; - - unstaking - .pop() - .ok_or("[pallet::staking] record must exist, due to `last_mut`; qed")?; - } - } - - *staked += actual_restake; - - Ok(()) - } - - fn restake_deposit(ledger: &mut Ledger, deposit: DepositId) -> DispatchResult { - ledger - .staked_deposits - .try_push( - ledger - .unstaking_deposits - .remove( - ledger - .unstaking_deposits - .iter() - .position(|(d, _)| d == &deposit) - .ok_or(>::DepositNotFound)?, - ) - .0, - ) - .map_err(|_| >::ExceedMaxDeposits)?; - - Ok(()) - } - - fn claim_unstakings(who: &T::AccountId) -> DispatchResult { - >::try_mutate(who, |l| { - let l = l.as_mut().ok_or(>::NotStaker)?; - let now = >::block_number(); - let mut r_claimed = 0; - - l.unstaking_ring.retain(|(a, t)| { - if t <= &now { - r_claimed += a; - - false - } else { - true - } - }); - ::Ring::unstake(who, r_claimed)?; - - let mut d_claimed = Vec::new(); - - l.unstaking_deposits.retain(|(d, t)| { - if t <= &now { - d_claimed.push(*d); - - false - } else { - true - } - }); - - for d in d_claimed { - T::Deposit::unstake(who, d)?; - } - - Ok(()) - }) - } - fn try_clean_ledger_of(who: &T::AccountId) { let _ = >::try_mutate(who, |maybe_l| { let l = maybe_l.as_mut().ok_or(())?; @@ -743,8 +569,8 @@ pub mod pallet { pub fn stake_of(who: &T::AccountId) -> Balance { >::get(who) .map(|l| { - l.staked_ring - + l.staked_deposits + l.ring + + l.deposits .into_iter() // We don't care if the deposit exists here. // It was guaranteed by the `stake`/`unstake`/`restake` functions. @@ -973,23 +799,16 @@ where T: Config, { /// Staked RING. - pub staked_ring: Balance, + pub ring: Balance, /// Staked deposits. - pub staked_deposits: BoundedVec, ::MaxDeposits>, - /// The RING in unstaking process. - pub unstaking_ring: BoundedVec<(Balance, BlockNumberFor), T::MaxUnstakings>, - /// The deposit in unstaking process. - pub unstaking_deposits: BoundedVec<(DepositId, BlockNumberFor), T::MaxUnstakings>, + pub deposits: BoundedVec, ::MaxDeposits>, } impl Ledger where T: Config, { fn is_empty(&self) -> bool { - self.staked_ring == 0 - && self.staked_deposits.is_empty() - && self.unstaking_ring.is_empty() - && self.unstaking_deposits.is_empty() + self.ring == 0 && self.deposits.is_empty() } } diff --git a/pallet/staking/src/migration/v2.rs b/pallet/staking/src/migration/v2.rs index 00fe97b7a..353240d49 100644 --- a/pallet/staking/src/migration/v2.rs +++ b/pallet/staking/src/migration/v2.rs @@ -33,9 +33,9 @@ where 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>, + pub unstaking_ring: BoundedVec<(Balance, BlockNumberFor), ConstU32<16>>, + pub unstaking_kton: BoundedVec<(Balance, BlockNumberFor), ConstU32<16>>, + pub unstaking_deposits: BoundedVec<(DepositId, BlockNumberFor), ConstU32<16>>, } #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, RuntimeDebug)] @@ -83,19 +83,27 @@ where >::kill(); >::kill(); >::translate::, _>(|a, o| { - w += 2; + w += 6; + let unstaking_ring = o.unstaking_ring.into_iter().fold(0, |s, (v, _)| s + v); + + // Release the unstaking RING immediately. + if unstaking_ring != 0 { + let _ = ::Ring::unstake(&a, unstaking_ring); + } + + // Release all KTON immediately. 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, - }) + // Release the unstaking deposits immediately. + for (d, _) in o.unstaking_deposits { + let _ = T::Deposit::unstake(&a, d); + } + + Some(Ledger { ring: o.staked_ring, deposits: o.staked_deposits }) }); >::translate_values::, _>(|o| { w += 1; diff --git a/pallet/staking/src/mock.rs b/pallet/staking/src/mock.rs index db2cbab44..8a5168b60 100644 --- a/pallet/staking/src/mock.rs +++ b/pallet/staking/src/mock.rs @@ -295,8 +295,6 @@ impl darwinia_staking::Config for Runtime { type KtonRewardDistributionContract = (); type KtonStakerNotifier = (); type MaxDeposits = ::MaxDeposits; - type MaxUnstakings = frame_support::traits::ConstU32<16>; - type MinStakingDuration = frame_support::traits::ConstU64<3>; type Ring = RingStaking; type RuntimeEvent = RuntimeEvent; type ShouldEndSession = ShouldEndSession; @@ -317,20 +315,6 @@ frame_support::construct_runtime! { } } -pub trait ZeroDefault { - fn default() -> Self; -} -impl ZeroDefault for darwinia_staking::Ledger { - fn default() -> Self { - Self { - staked_ring: Default::default(), - staked_deposits: Default::default(), - unstaking_ring: Default::default(), - unstaking_deposits: Default::default(), - } - } -} - pub enum Efflux {} impl Efflux { pub fn time(milli_secs: Moment) { diff --git a/pallet/staking/src/tests.rs b/pallet/staking/src/tests.rs index 1da057a96..377dfa3c8 100644 --- a/pallet/staking/src/tests.rs +++ b/pallet/staking/src/tests.rs @@ -20,7 +20,7 @@ use core::time::Duration; // darwinia use crate::{mock::*, *}; -use darwinia_deposit::Error as DepositError; +use darwinia_deposit::{Deposit as DepositS, Error as DepositError}; use dc_types::UNIT; // substrate use frame_support::{assert_noop, assert_ok, BoundedVec}; @@ -124,7 +124,7 @@ fn stake_should_work() { assert_eq!(System::account(1).consumers, 1); assert_eq!( Staking::ledger_of(1).unwrap(), - Ledger { staked_ring: UNIT, ..ZeroDefault::default() } + Ledger { ring: UNIT, deposits: Default::default() } ); assert_eq!(Balances::free_balance(1), 999 * UNIT); @@ -140,11 +140,7 @@ fn stake_should_work() { assert_ok!(Staking::stake(RuntimeOrigin::signed(1), 0, vec![0])); assert_eq!( Staking::ledger_of(1).unwrap(), - Ledger { - staked_ring: UNIT, - staked_deposits: BoundedVec::truncate_from(vec![0]), - ..ZeroDefault::default() - } + Ledger { ring: UNIT, deposits: BoundedVec::truncate_from(vec![0]) } ); // Stake 500 RING and 2 deposits. @@ -155,11 +151,7 @@ fn stake_should_work() { assert_eq!(Balances::free_balance(1), 98 * UNIT); assert_eq!( Staking::ledger_of(1).unwrap(), - Ledger { - staked_ring: 501 * UNIT, - staked_deposits: BoundedVec::truncate_from(vec![0, 1, 2]), - ..ZeroDefault::default() - } + Ledger { ring: 501 * UNIT, deposits: BoundedVec::truncate_from(vec![0, 1, 2]) } ); }); } @@ -174,23 +166,43 @@ fn unstake_should_work() { assert_eq!(Balances::free_balance(1), 994 * UNIT); assert_eq!( Staking::ledger_of(1).unwrap(), - Ledger { - staked_ring: 3 * UNIT, - staked_deposits: BoundedVec::truncate_from(vec![0, 1, 2]), - ..ZeroDefault::default() - } + Ledger { ring: 3 * UNIT, deposits: BoundedVec::truncate_from(vec![0, 1, 2]) } + ); + assert_eq!( + Deposit::deposit_of(1).unwrap(), + ::MaxDeposits>>::truncate_from( + vec![ + DepositS { + id: 0, + value: UNIT, + start_time: 3, + expired_time: 2635200003, + in_use: true + }, + DepositS { + id: 1, + value: UNIT, + start_time: 3, + expired_time: 2635200003, + in_use: true + }, + DepositS { + id: 2, + value: UNIT, + start_time: 3, + expired_time: 2635200003, + in_use: true + } + ] + ) ); // Unstake 1 RING. assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), UNIT, Vec::new())); + assert_eq!(Balances::free_balance(1), 995 * UNIT); assert_eq!( Staking::ledger_of(1).unwrap(), - Ledger { - staked_ring: 2 * UNIT, - staked_deposits: BoundedVec::truncate_from(vec![0, 1, 2]), - unstaking_ring: BoundedVec::truncate_from(vec![(UNIT, 6)]), - ..ZeroDefault::default() - } + Ledger { ring: 2 * UNIT, deposits: BoundedVec::truncate_from(vec![0, 1, 2]) } ); // Unstake invalid deposit. @@ -204,151 +216,51 @@ fn unstake_should_work() { assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), 0, vec![1])); assert_eq!( Staking::ledger_of(1).unwrap(), - Ledger { - staked_ring: 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, 7)]) - } - ); - - // Unstake 2 RING and 2 deposits. - Efflux::block(1); - 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, 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); - }); -} - -#[test] -fn restake_should_work() { - ExtBuilder::default().build().execute_with(|| { - 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, 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, Vec::new())); - Efflux::block(1); - assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), UNIT, Vec::new())); - assert_eq!(Balances::free_balance(1), 994 * UNIT); - assert_eq!( - Staking::ledger_of(1).unwrap(), - Ledger { - unstaking_ring: BoundedVec::truncate_from(vec![(UNIT, 6), (UNIT, 7), (UNIT, 8)]), - unstaking_deposits: BoundedVec::truncate_from(vec![(0, 6), (1, 6), (2, 6)]), - ..ZeroDefault::default() - } - ); - - // Restake 1.5 RING. - assert_ok!(Staking::restake(RuntimeOrigin::signed(1), 3 * UNIT / 2, Vec::new())); - assert_eq!( - Staking::ledger_of(1).unwrap(), - Ledger { - staked_ring: 3 * UNIT / 2, - unstaking_ring: BoundedVec::truncate_from(vec![(UNIT, 6), (UNIT / 2, 7)]), - unstaking_deposits: BoundedVec::truncate_from(vec![(0, 6), (1, 6), (2, 6)]), - ..ZeroDefault::default() - } - ); - - // Restake invalid deposit. - assert_noop!( - Staking::unstake(RuntimeOrigin::signed(1), 0, vec![3]), - >::DepositNotFound - ); - - // Restake 1 deposit. - assert_ok!(Staking::restake(RuntimeOrigin::signed(1), 0, vec![1])); - assert_eq!( - Staking::ledger_of(1).unwrap(), - Ledger { - staked_ring: 3 * UNIT / 2, - staked_deposits: BoundedVec::truncate_from(vec![1]), - unstaking_ring: BoundedVec::truncate_from(vec![(UNIT, 6), (UNIT / 2, 7)]), - unstaking_deposits: BoundedVec::truncate_from(vec![(0, 6), (2, 6)]), - ..ZeroDefault::default() - } + Ledger { ring: 2 * UNIT, deposits: BoundedVec::truncate_from(vec![0, 2]) } ); - - // Restake 1.5 RING and 2 deposits. - Efflux::block(1); - assert_ok!(Staking::restake(RuntimeOrigin::signed(1), 3 * UNIT / 2, vec![0, 2])); assert_eq!( - Staking::ledger_of(1).unwrap(), - Ledger { - staked_ring: 3 * UNIT, - staked_deposits: BoundedVec::truncate_from(vec![1, 0, 2]), - ..ZeroDefault::default() - } - ); - }); -} - -#[test] -fn claim_should_work() { - ExtBuilder::default().build().execute_with(|| { - 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, vec![0, 1, 2])); - assert_eq!(System::account(1).consumers, 2); - assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), UNIT, Vec::new())); - Efflux::block(1); - assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), 0, vec![0])); - Efflux::block(1); - assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), UNIT, vec![1, 2])); - assert_eq!(Balances::free_balance(1), 995 * UNIT); - assert_eq!( - Staking::ledger_of(1).unwrap(), - Ledger { - unstaking_ring: BoundedVec::truncate_from(vec![(UNIT, 6), (UNIT, 8)]), - unstaking_deposits: BoundedVec::truncate_from(vec![(0, 7), (1, 8), (2, 8)]), - ..ZeroDefault::default() - } - ); - - 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, 8)]), - unstaking_deposits: BoundedVec::truncate_from(vec![(0, 7), (1, 8), (2, 8)]), - ..ZeroDefault::default() - } + Deposit::deposit_of(1).unwrap(), + ::MaxDeposits>>::truncate_from( + vec![ + DepositS { + id: 0, + value: UNIT, + start_time: 3, + expired_time: 2635200003, + in_use: true + }, + DepositS { + id: 1, + value: UNIT, + start_time: 3, + expired_time: 2635200003, + in_use: false + }, + DepositS { + id: 2, + value: UNIT, + start_time: 3, + expired_time: 2635200003, + in_use: true + } + ] + ) ); + // Unstake 2 RING and 2 deposits. Efflux::block(1); - assert_ok!(Staking::claim(RuntimeOrigin::signed(1))); - assert_eq!(System::account(1).consumers, 2); + assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), 2 * UNIT, vec![0, 2])); + assert!(Staking::ledger_of(1).is_none()); assert_eq!( - Staking::ledger_of(1).unwrap(), - Ledger { - unstaking_ring: BoundedVec::truncate_from(vec![(UNIT, 8)]), - unstaking_deposits: BoundedVec::truncate_from(vec![(1, 8), (2, 8)]), - ..ZeroDefault::default() - } + Deposit::deposit_of(1).unwrap(), + ::MaxDeposits>>::truncate_from( + vec![ + DepositS { id: 0, value: UNIT, start_time: 3, expired_time: 2635200003, in_use: false }, + DepositS { id: 1, value: UNIT, start_time: 3, expired_time: 2635200003, in_use: false }, + DepositS { id: 2, value: UNIT, start_time: 3, expired_time: 2635200003, in_use: false } + ] + ) ); - - Efflux::block(2); - assert_ok!(Staking::claim(RuntimeOrigin::signed(1))); - assert_eq!(System::account(1).consumers, 1); - assert_eq!(Balances::free_balance(1), 997 * UNIT); - assert!(Staking::ledger_of(1).is_none()); }); } diff --git a/pallet/staking/src/weights.rs b/pallet/staking/src/weights.rs index 09896a781..397832e76 100644 --- a/pallet/staking/src/weights.rs +++ b/pallet/staking/src/weights.rs @@ -54,8 +54,6 @@ use core::marker::PhantomData; pub trait WeightInfo { fn stake(x: u32, ) -> Weight; fn unstake(x: u32, ) -> Weight; - fn restake(x: u32, ) -> Weight; - fn claim() -> Weight; fn collect() -> Weight; fn nominate() -> Weight; fn chill() -> Weight; @@ -114,47 +112,6 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } - /// Storage: `DarwiniaStaking::Ledgers` (r:1 w:1) - /// Proof: `DarwiniaStaking::Ledgers` (`max_values`: None, `max_size`: Some(1833), added: 4308, mode: `MaxEncodedLen`) - /// Storage: `DarwiniaStaking::RingPool` (r:1 w:1) - /// Proof: `DarwiniaStaking::RingPool` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `DarwiniaStaking::KtonPool` (r:1 w:1) - /// Proof: `DarwiniaStaking::KtonPool` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Deposit::Deposits` (r:1 w:0) - /// Proof: `Deposit::Deposits` (`max_values`: None, `max_size`: Some(26150), added: 28625, mode: `MaxEncodedLen`) - /// The range of component `x` is `[0, 1023]`. - fn restake(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1693` - // Estimated: `29615` - // Minimum execution time: 10_061 nanoseconds. - Weight::from_parts(43_375_019, 0) - .saturating_add(Weight::from_parts(29615, 0)) - // Standard Error: 750 - .saturating_add(Weight::from_parts(3_582, 0).saturating_mul(x.into())) - .saturating_add(T::DbWeight::get().reads(4_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) - } - /// Storage: `DarwiniaStaking::Ledgers` (r:1 w:1) - /// Proof: `DarwiniaStaking::Ledgers` (`max_values`: None, `max_size`: Some(1833), added: 4308, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(166), added: 2641, mode: `MaxEncodedLen`) - /// Storage: `Assets::Account` (r:2 w:2) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) - /// Storage: `Deposit::Deposits` (r:1 w:1) - /// Proof: `Deposit::Deposits` (`max_values`: None, `max_size`: Some(26150), added: 28625, mode: `MaxEncodedLen`) - fn claim() -> Weight { - // Proof Size summary in bytes: - // Measured: `2215` - // Estimated: `29615` - // Minimum execution time: 87_073 nanoseconds. - Weight::from_parts(89_352_000, 0) - .saturating_add(Weight::from_parts(29615, 0)) - .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(6_u64)) - } /// Storage: `DarwiniaStaking::Collators` (r:1 w:1) /// Proof: `DarwiniaStaking::Collators` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `MaxEncodedLen`) fn collect() -> Weight { @@ -277,47 +234,6 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } - /// Storage: `DarwiniaStaking::Ledgers` (r:1 w:1) - /// Proof: `DarwiniaStaking::Ledgers` (`max_values`: None, `max_size`: Some(1833), added: 4308, mode: `MaxEncodedLen`) - /// Storage: `DarwiniaStaking::RingPool` (r:1 w:1) - /// Proof: `DarwiniaStaking::RingPool` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `DarwiniaStaking::KtonPool` (r:1 w:1) - /// Proof: `DarwiniaStaking::KtonPool` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Deposit::Deposits` (r:1 w:0) - /// Proof: `Deposit::Deposits` (`max_values`: None, `max_size`: Some(26150), added: 28625, mode: `MaxEncodedLen`) - /// The range of component `x` is `[0, 1023]`. - fn restake(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1693` - // Estimated: `29615` - // Minimum execution time: 10_061 nanoseconds. - Weight::from_parts(43_375_019, 0) - .saturating_add(Weight::from_parts(29615, 0)) - // Standard Error: 750 - .saturating_add(Weight::from_parts(3_582, 0).saturating_mul(x.into())) - .saturating_add(RocksDbWeight::get().reads(4_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) - } - /// Storage: `DarwiniaStaking::Ledgers` (r:1 w:1) - /// Proof: `DarwiniaStaking::Ledgers` (`max_values`: None, `max_size`: Some(1833), added: 4308, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) - /// Storage: `Assets::Asset` (r:1 w:1) - /// Proof: `Assets::Asset` (`max_values`: None, `max_size`: Some(166), added: 2641, mode: `MaxEncodedLen`) - /// Storage: `Assets::Account` (r:2 w:2) - /// Proof: `Assets::Account` (`max_values`: None, `max_size`: Some(114), added: 2589, mode: `MaxEncodedLen`) - /// Storage: `Deposit::Deposits` (r:1 w:1) - /// Proof: `Deposit::Deposits` (`max_values`: None, `max_size`: Some(26150), added: 28625, mode: `MaxEncodedLen`) - fn claim() -> Weight { - // Proof Size summary in bytes: - // Measured: `2215` - // Estimated: `29615` - // Minimum execution time: 87_073 nanoseconds. - Weight::from_parts(89_352_000, 0) - .saturating_add(Weight::from_parts(29615, 0)) - .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(6_u64)) - } /// Storage: `DarwiniaStaking::Collators` (r:1 w:1) /// Proof: `DarwiniaStaking::Collators` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `MaxEncodedLen`) fn collect() -> Weight { diff --git a/pallet/staking/traits/src/lib.rs b/pallet/staking/traits/src/lib.rs index 11b31a35d..2ca6967bc 100644 --- a/pallet/staking/traits/src/lib.rs +++ b/pallet/staking/traits/src/lib.rs @@ -47,7 +47,7 @@ pub trait Stake { + Copy + Debug + Default - + From + + From + PartialEq + FullCodec + MaxEncodedLen diff --git a/precompile/staking/src/lib.rs b/precompile/staking/src/lib.rs index 931d6633d..1eb4706a3 100644 --- a/precompile/staking/src/lib.rs +++ b/precompile/staking/src/lib.rs @@ -93,38 +93,6 @@ where Ok(true) } - #[precompile::public("restake(uint256,uint16[])")] - fn restake( - handle: &mut impl PrecompileHandle, - ring_amount: U256, - deposits: Vec, - ) -> EvmResult { - let origin = handle.context().caller.into(); - let deposits = deposits.into_iter().map(|i| i.into()).collect(); - - RuntimeHelper::::try_dispatch( - handle, - Some(origin).into(), - darwinia_staking::Call::::restake { - ring_amount: ring_amount.as_u128(), - deposits, - }, - )?; - Ok(true) - } - - #[precompile::public("claim()")] - fn claim(handle: &mut impl PrecompileHandle) -> EvmResult { - let origin = handle.context().caller.into(); - - RuntimeHelper::::try_dispatch( - handle, - Some(origin).into(), - darwinia_staking::Call::::claim {}, - )?; - Ok(true) - } - #[precompile::public("collect(uint32)")] fn collect(handle: &mut impl PrecompileHandle, commission: u32) -> EvmResult { let origin = handle.context().caller.into(); diff --git a/precompile/staking/src/mock.rs b/precompile/staking/src/mock.rs index 92c39f686..8b5817f5a 100644 --- a/precompile/staking/src/mock.rs +++ b/precompile/staking/src/mock.rs @@ -236,8 +236,6 @@ impl darwinia_staking::Config for Runtime { type KtonRewardDistributionContract = (); type KtonStakerNotifier = (); type MaxDeposits = ::MaxDeposits; - type MaxUnstakings = frame_support::traits::ConstU32<16>; - type MinStakingDuration = frame_support::traits::ConstU64<3>; type Ring = RingStaking; type RuntimeEvent = RuntimeEvent; type ShouldEndSession = (); diff --git a/precompile/staking/src/tests.rs b/precompile/staking/src/tests.rs index 6ebefa1b5..dda93804b 100644 --- a/precompile/staking/src/tests.rs +++ b/precompile/staking/src/tests.rs @@ -19,7 +19,7 @@ // darwinia use crate::mock::{ Account::{Alice, Bob, Precompile}, - ExtBuilder, PCall, PrecompilesValue, Runtime, Staking, System, TestPrecompiles, + ExtBuilder, PCall, PrecompilesValue, Runtime, Staking, TestPrecompiles, }; use sp_runtime::Perbill; // moonbeam @@ -35,8 +35,6 @@ fn precompiles() -> TestPrecompiles { fn selectors() { 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)); assert!(PCall::chill_selectors().contains(&0x2b8a3ae6)); @@ -55,7 +53,7 @@ fn stake_unstake_restake() { PCall::stake { ring_amount: 200.into(), deposits: vec![] }, ) .execute_returns(true); - assert_eq!(Staking::ledger_of(alice).unwrap().staked_ring, 200); + assert_eq!(Staking::ledger_of(alice).unwrap().ring, 200); // unstake precompiles() @@ -65,47 +63,6 @@ fn stake_unstake_restake() { PCall::unstake { ring_amount: 200.into(), deposits: vec![] }, ) .execute_returns(true); - assert_eq!(Staking::ledger_of(alice).unwrap().staked_ring, 0); - assert_eq!(Staking::ledger_of(alice).unwrap().unstaking_ring.len(), 1); - - // restake - precompiles() - .prepare_test( - alice, - Precompile, - PCall::restake { ring_amount: 200.into(), deposits: vec![] }, - ) - .execute_returns(true); - assert_eq!(Staking::ledger_of(alice).unwrap().staked_ring, 200); - assert_eq!(Staking::ledger_of(alice).unwrap().unstaking_ring.len(), 0); - }); -} - -#[test] -fn claim() { - let alice: H160 = Alice.into(); - ExtBuilder::default().with_balances(vec![(alice, 300)]).build().execute_with(|| { - // stake - precompiles() - .prepare_test( - alice, - Precompile, - PCall::stake { ring_amount: 200.into(), deposits: vec![] }, - ) - .execute_returns(true); - - // unstake - precompiles() - .prepare_test( - alice, - Precompile, - PCall::unstake { ring_amount: 200.into(), deposits: vec![] }, - ) - .execute_returns(true); - - // You have to wait for MinStakingDuration to claim - System::set_block_number(5); - precompiles().prepare_test(alice, Precompile, PCall::claim {}).execute_returns(true); assert!(Staking::ledger_of(alice).is_none()); }); } diff --git a/runtime/common/src/test.rs b/runtime/common/src/test.rs index 11dfef512..4caf6cc9d 100644 --- a/runtime/common/src/test.rs +++ b/runtime/common/src/test.rs @@ -321,7 +321,7 @@ macro_rules! impl_account_migration_tests { ); assert_eq!(Deposit::deposit_of(to).unwrap().len(), 2); 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().ring, 20); }); } #[test] diff --git a/runtime/crab/src/pallets/staking.rs b/runtime/crab/src/pallets/staking.rs index f9063551e..76c51f47f 100644 --- a/runtime/crab/src/pallets/staking.rs +++ b/runtime/crab/src/pallets/staking.rs @@ -23,8 +23,6 @@ use frame_support::traits::Currency; fast_runtime_or_not!(DURATION, BlockNumber, 5 * MINUTES, 14 * DAYS); -type MinStakingDuration = ConstU32<{ DURATION }>; - pub enum RingStaking {} impl darwinia_staking::Stake for RingStaking { type AccountId = AccountId; @@ -108,8 +106,6 @@ impl darwinia_staking::Config for Runtime { type KtonRewardDistributionContract = darwinia_staking::KtonRewardDistributionContract; type KtonStakerNotifier = darwinia_staking::KtonStakerNotifier; type MaxDeposits = ::MaxDeposits; - type MaxUnstakings = ConstU32<16>; - type MinStakingDuration = MinStakingDuration; type Ring = RingStaking; type RuntimeEvent = RuntimeEvent; type ShouldEndSession = ShouldEndSession; diff --git a/runtime/crab/src/weights/darwinia_staking.rs b/runtime/crab/src/weights/darwinia_staking.rs index 6c218fc33..590d2384e 100644 --- a/runtime/crab/src/weights/darwinia_staking.rs +++ b/runtime/crab/src/weights/darwinia_staking.rs @@ -109,41 +109,6 @@ impl darwinia_staking::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(7)) } - /// Storage: `DarwiniaStaking::Ledgers` (r:1 w:1) - /// Proof: `DarwiniaStaking::Ledgers` (`max_values`: None, `max_size`: Some(1833), added: 4308, mode: `MaxEncodedLen`) - /// Storage: `DarwiniaStaking::RingPool` (r:1 w:1) - /// Proof: `DarwiniaStaking::RingPool` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Deposit::Deposits` (r:1 w:0) - /// Proof: `Deposit::Deposits` (`max_values`: None, `max_size`: Some(26150), added: 28625, mode: `MaxEncodedLen`) - /// The range of component `x` is `[0, 1023]`. - fn restake(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1570` - // Estimated: `29615` - // Minimum execution time: 9_000_000 picoseconds. - Weight::from_parts(53_542_194, 0) - .saturating_add(Weight::from_parts(0, 29615)) - // Standard Error: 966 - .saturating_add(Weight::from_parts(4_864, 0).saturating_mul(x.into())) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(2)) - } - /// Storage: `DarwiniaStaking::Ledgers` (r:1 w:1) - /// Proof: `DarwiniaStaking::Ledgers` (`max_values`: None, `max_size`: Some(1833), added: 4308, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) - /// Storage: `Deposit::Deposits` (r:1 w:1) - /// Proof: `Deposit::Deposits` (`max_values`: None, `max_size`: Some(26150), added: 28625, mode: `MaxEncodedLen`) - fn claim() -> Weight { - // Proof Size summary in bytes: - // Measured: `1658` - // Estimated: `29615` - // Minimum execution time: 81_000_000 picoseconds. - Weight::from_parts(83_000_000, 0) - .saturating_add(Weight::from_parts(0, 29615)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) - } /// Storage: `DarwiniaStaking::Collators` (r:1 w:1) /// Proof: `DarwiniaStaking::Collators` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `MaxEncodedLen`) fn collect() -> Weight { diff --git a/runtime/darwinia/src/pallets/staking.rs b/runtime/darwinia/src/pallets/staking.rs index 1d10f0e6a..82cceb2ed 100644 --- a/runtime/darwinia/src/pallets/staking.rs +++ b/runtime/darwinia/src/pallets/staking.rs @@ -23,8 +23,6 @@ use frame_support::traits::Currency; fast_runtime_or_not!(DURATION, BlockNumber, 5 * MINUTES, 14 * DAYS); -type MinStakingDuration = ConstU32<{ DURATION }>; - pub enum RingStaking {} impl darwinia_staking::Stake for RingStaking { type AccountId = AccountId; @@ -119,8 +117,6 @@ impl darwinia_staking::Config for Runtime { type KtonRewardDistributionContract = darwinia_staking::KtonRewardDistributionContract; type KtonStakerNotifier = darwinia_staking::KtonStakerNotifier; type MaxDeposits = ::MaxDeposits; - type MaxUnstakings = ConstU32<16>; - type MinStakingDuration = MinStakingDuration; type Ring = RingStaking; type RuntimeEvent = RuntimeEvent; type ShouldEndSession = ShouldEndSession; diff --git a/runtime/darwinia/src/weights/darwinia_staking.rs b/runtime/darwinia/src/weights/darwinia_staking.rs index 23bf73a78..ebc10730e 100644 --- a/runtime/darwinia/src/weights/darwinia_staking.rs +++ b/runtime/darwinia/src/weights/darwinia_staking.rs @@ -109,41 +109,6 @@ impl darwinia_staking::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(7)) } - /// Storage: `DarwiniaStaking::Ledgers` (r:1 w:1) - /// Proof: `DarwiniaStaking::Ledgers` (`max_values`: None, `max_size`: Some(1833), added: 4308, mode: `MaxEncodedLen`) - /// Storage: `DarwiniaStaking::RingPool` (r:1 w:1) - /// Proof: `DarwiniaStaking::RingPool` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Deposit::Deposits` (r:1 w:0) - /// Proof: `Deposit::Deposits` (`max_values`: None, `max_size`: Some(26150), added: 28625, mode: `MaxEncodedLen`) - /// The range of component `x` is `[0, 1023]`. - fn restake(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1637` - // Estimated: `29615` - // Minimum execution time: 10_000_000 picoseconds. - Weight::from_parts(52_307_173, 0) - .saturating_add(Weight::from_parts(0, 29615)) - // Standard Error: 931 - .saturating_add(Weight::from_parts(5_747, 0).saturating_mul(x.into())) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(2)) - } - /// Storage: `DarwiniaStaking::Ledgers` (r:1 w:1) - /// Proof: `DarwiniaStaking::Ledgers` (`max_values`: None, `max_size`: Some(1833), added: 4308, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) - /// Storage: `Deposit::Deposits` (r:1 w:1) - /// Proof: `Deposit::Deposits` (`max_values`: None, `max_size`: Some(26150), added: 28625, mode: `MaxEncodedLen`) - fn claim() -> Weight { - // Proof Size summary in bytes: - // Measured: `1725` - // Estimated: `29615` - // Minimum execution time: 81_000_000 picoseconds. - Weight::from_parts(81_000_000, 0) - .saturating_add(Weight::from_parts(0, 29615)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) - } /// Storage: `DarwiniaStaking::Collators` (r:1 w:1) /// Proof: `DarwiniaStaking::Collators` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `MaxEncodedLen`) fn collect() -> Weight { diff --git a/runtime/pangolin/src/pallets/staking.rs b/runtime/pangolin/src/pallets/staking.rs index de9baa44e..251f986c2 100644 --- a/runtime/pangolin/src/pallets/staking.rs +++ b/runtime/pangolin/src/pallets/staking.rs @@ -102,8 +102,6 @@ impl darwinia_staking::Config for Runtime { type KtonRewardDistributionContract = darwinia_staking::KtonRewardDistributionContract; type KtonStakerNotifier = darwinia_staking::KtonStakerNotifier; type MaxDeposits = ::MaxDeposits; - type MaxUnstakings = ConstU32<16>; - type MinStakingDuration = ConstU32<{ 2 * MINUTES }>; type Ring = RingStaking; type RuntimeEvent = RuntimeEvent; type ShouldEndSession = ShouldEndSession; diff --git a/runtime/pangolin/src/weights/darwinia_staking.rs b/runtime/pangolin/src/weights/darwinia_staking.rs index 85f5c3714..07b1d4b49 100644 --- a/runtime/pangolin/src/weights/darwinia_staking.rs +++ b/runtime/pangolin/src/weights/darwinia_staking.rs @@ -109,41 +109,6 @@ impl darwinia_staking::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(7)) } - /// Storage: `DarwiniaStaking::Ledgers` (r:1 w:1) - /// Proof: `DarwiniaStaking::Ledgers` (`max_values`: None, `max_size`: Some(1833), added: 4308, mode: `MaxEncodedLen`) - /// Storage: `DarwiniaStaking::RingPool` (r:1 w:1) - /// Proof: `DarwiniaStaking::RingPool` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Deposit::Deposits` (r:1 w:0) - /// Proof: `Deposit::Deposits` (`max_values`: None, `max_size`: Some(26150), added: 28625, mode: `MaxEncodedLen`) - /// The range of component `x` is `[0, 1023]`. - fn restake(x: u32, ) -> Weight { - // Proof Size summary in bytes: - // Measured: `1637` - // Estimated: `29615` - // Minimum execution time: 9_000_000 picoseconds. - Weight::from_parts(53_351_430, 0) - .saturating_add(Weight::from_parts(0, 29615)) - // Standard Error: 969 - .saturating_add(Weight::from_parts(4_963, 0).saturating_mul(x.into())) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(2)) - } - /// Storage: `DarwiniaStaking::Ledgers` (r:1 w:1) - /// Proof: `DarwiniaStaking::Ledgers` (`max_values`: None, `max_size`: Some(1833), added: 4308, mode: `MaxEncodedLen`) - /// Storage: `System::Account` (r:1 w:1) - /// Proof: `System::Account` (`max_values`: None, `max_size`: Some(116), added: 2591, mode: `MaxEncodedLen`) - /// Storage: `Deposit::Deposits` (r:1 w:1) - /// Proof: `Deposit::Deposits` (`max_values`: None, `max_size`: Some(26150), added: 28625, mode: `MaxEncodedLen`) - fn claim() -> Weight { - // Proof Size summary in bytes: - // Measured: `1725` - // Estimated: `29615` - // Minimum execution time: 81_000_000 picoseconds. - Weight::from_parts(82_000_000, 0) - .saturating_add(Weight::from_parts(0, 29615)) - .saturating_add(T::DbWeight::get().reads(3)) - .saturating_add(T::DbWeight::get().writes(3)) - } /// Storage: `DarwiniaStaking::Collators` (r:1 w:1) /// Proof: `DarwiniaStaking::Collators` (`max_values`: None, `max_size`: Some(32), added: 2507, mode: `MaxEncodedLen`) fn collect() -> Weight { From 8ef837ac8618559bab25aef5585ffa9789c80e1b Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Tue, 16 Apr 2024 04:01:02 +0800 Subject: [PATCH 2/6] Rate limit --- node/src/chain_spec/crab.rs | 2 + node/src/chain_spec/darwinia.rs | 2 + pallet/staking/src/benchmarking.rs | 9 ++++ pallet/staking/src/lib.rs | 42 +++++++++++++++- pallet/staking/src/migration/v2.rs | 4 +- pallet/staking/src/mock.rs | 1 + pallet/staking/src/tests.rs | 49 +++++++++++++++++-- pallet/staking/src/weights.rs | 7 +++ precompile/staking/src/mock.rs | 20 +++++--- runtime/crab/src/weights/darwinia_staking.rs | 3 ++ .../darwinia/src/weights/darwinia_staking.rs | 3 ++ .../pangolin/src/weights/darwinia_staking.rs | 3 ++ 12 files changed, 133 insertions(+), 12 deletions(-) diff --git a/node/src/chain_spec/crab.rs b/node/src/chain_spec/crab.rs index 01aac09e2..05b98d28a 100644 --- a/node/src/chain_spec/crab.rs +++ b/node/src/chain_spec/crab.rs @@ -200,6 +200,7 @@ pub fn genesis_config() -> ChainSpec { darwinia_staking: DarwiniaStakingConfig { now: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(), elapsed_time: 0, + max_unstake_ring: 10_000_000 * UNIT, collator_count: 6, collators: collators .iter() @@ -303,6 +304,7 @@ fn testnet_genesis( darwinia_staking: DarwiniaStakingConfig { now: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(), elapsed_time: 0, + max_unstake_ring: 10_000_000 * UNIT, collator_count: collators.len() as _, collators: collators.iter().map(|(a, _)| (a.to_owned(), UNIT)).collect(), }, diff --git a/node/src/chain_spec/darwinia.rs b/node/src/chain_spec/darwinia.rs index c1cc9fc1d..247871b15 100644 --- a/node/src/chain_spec/darwinia.rs +++ b/node/src/chain_spec/darwinia.rs @@ -196,6 +196,7 @@ pub fn genesis_config() -> ChainSpec { darwinia_staking: DarwiniaStakingConfig { now: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(), elapsed_time: 0, + max_unstake_ring: 10_000_000 * UNIT, collator_count: 5, collators: collators .iter() @@ -301,6 +302,7 @@ fn testnet_genesis( darwinia_staking: DarwiniaStakingConfig { now: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(), elapsed_time: 0, + max_unstake_ring: 10_000_000 * UNIT, collator_count: collators.len() as _, collators: collators.iter().map(|(a, _)| (a.to_owned(), UNIT)).collect(), }, diff --git a/pallet/staking/src/benchmarking.rs b/pallet/staking/src/benchmarking.rs index f6f01c8ef..71b7d971d 100644 --- a/pallet/staking/src/benchmarking.rs +++ b/pallet/staking/src/benchmarking.rs @@ -158,6 +158,15 @@ mod benchmarks { _(RawOrigin::Signed(sender), a); } + #[benchmark] + fn set_max_unstake_ring() { + // Worst-case scenario: + // + // Set max unstake ring successfully. + #[extrinsic_call] + _(RawOrigin::Root, 1); + } + #[benchmark] fn set_collator_count() { // Worst-case scenario: diff --git a/pallet/staking/src/lib.rs b/pallet/staking/src/lib.rs index 225760e1b..6d4e9fbaa 100644 --- a/pallet/staking/src/lib.rs +++ b/pallet/staking/src/lib.rs @@ -166,8 +166,8 @@ pub mod pallet { pub enum Error { /// Exceed maximum deposit count. ExceedMaxDeposits, - /// Exceed maximum unstaking/unbonding count. - ExceedMaxUnstakings, + /// Exceed maximum unstake amount. + ExceedMaxUnstakeAmount, /// Deposit not found. DepositNotFound, /// You are not a staker. @@ -282,6 +282,20 @@ pub mod pallet { #[pallet::getter(fn elapsed_time)] pub type ElapsedTime = StorageValue<_, Moment, ValueQuery>; + /// Max unstake RING limit. + /// + /// The maximum RING amount that can be unstaked in a session. + #[pallet::storage] + #[pallet::getter(fn max_unstake_ring)] + pub type MaxUnstakeRing = StorageValue<_, Balance, ValueQuery>; + + /// Unstake accumulator. + /// + /// Tracks the total RING amount being unstaked in a session. + #[pallet::storage] + #[pallet::getter(fn accumulate_unstake)] + pub type AccumulateUnstake = StorageValue<_, Balance, ValueQuery>; + #[derive(DefaultNoBound)] #[pallet::genesis_config] pub struct GenesisConfig { @@ -289,6 +303,8 @@ pub mod pallet { pub now: Moment, /// The running time of Darwinia1. pub elapsed_time: Moment, + /// Max unstake RING limit. + pub max_unstake_ring: Balance, /// Genesis collator count. pub collator_count: u32, /// Genesis collator preferences. @@ -304,6 +320,7 @@ pub mod pallet { >::put(self.now); >::put(self.elapsed_time); + >::put(self.max_unstake_ring); >::put(self.collator_count); self.collators.iter().for_each(|(who, ring_amount)| { @@ -400,6 +417,8 @@ pub mod pallet { return Ok(()); } + let mut acc = >::get().saturating_add(ring_amount); + >::try_mutate(&who, |l| { let l = l.as_mut().ok_or(>::NotStaker)?; @@ -413,6 +432,8 @@ pub mod pallet { } for d in deposits { + acc = acc.saturating_add(T::Deposit::amount(&who, d).unwrap_or_default()); + l.deposits.remove( l.deposits .iter() @@ -426,6 +447,12 @@ pub mod pallet { DispatchResult::Ok(()) })?; + if acc <= >::get() { + >::put(acc); + } else { + Err(>::ExceedMaxUnstakeAmount)?; + } + Self::try_clean_ledger_of(&who); Ok(()) @@ -493,6 +520,17 @@ pub mod pallet { Ok(()) } + /// Set max unstake RING limit. + #[pallet::call_index(9)] + #[pallet::weight(::WeightInfo::set_max_unstake_ring())] + pub fn set_max_unstake_ring(origin: OriginFor, amount: Balance) -> DispatchResult { + ensure_root(origin)?; + + >::put(amount); + + Ok(()) + } + /// Set collator count. /// /// This will apply to the incoming session. diff --git a/pallet/staking/src/migration/v2.rs b/pallet/staking/src/migration/v2.rs index 353240d49..863a377e2 100644 --- a/pallet/staking/src/migration/v2.rs +++ b/pallet/staking/src/migration/v2.rs @@ -2,6 +2,7 @@ use core::marker::PhantomData; // darwinia use crate::*; +use dc_types::UNIT; // substrate use frame_support::traits::OnRuntimeUpgrade; #[cfg(feature = "try-runtime")] @@ -77,11 +78,12 @@ where return T::DbWeight::get().reads(r); } - let mut w = 4; + let mut w = 5; >::kill(); >::kill(); >::kill(); + >::put(10_000_000 * UNIT); >::translate::, _>(|a, o| { w += 6; diff --git a/pallet/staking/src/mock.rs b/pallet/staking/src/mock.rs index 8a5168b60..2ab28137f 100644 --- a/pallet/staking/src/mock.rs +++ b/pallet/staking/src/mock.rs @@ -368,6 +368,7 @@ impl ExtBuilder { .assimilate_storage(&mut storage) .unwrap(); darwinia_staking::GenesisConfig:: { + max_unstake_ring: 100 * UNIT, collator_count: self.collator_count, collators: if self.genesis_collator { (1..=self.collator_count).map(|i| (i, UNIT)).collect() diff --git a/pallet/staking/src/tests.rs b/pallet/staking/src/tests.rs index 377dfa3c8..6769fd3ab 100644 --- a/pallet/staking/src/tests.rs +++ b/pallet/staking/src/tests.rs @@ -199,6 +199,7 @@ fn unstake_should_work() { // Unstake 1 RING. assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), UNIT, Vec::new())); + assert_eq!(Staking::accumulate_unstake(), UNIT); assert_eq!(Balances::free_balance(1), 995 * UNIT); assert_eq!( Staking::ledger_of(1).unwrap(), @@ -214,6 +215,7 @@ fn unstake_should_work() { // Unstake 1 deposit. Efflux::block(1); assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), 0, vec![1])); + assert_eq!(Staking::accumulate_unstake(), 2 * UNIT); assert_eq!( Staking::ledger_of(1).unwrap(), Ledger { ring: 2 * UNIT, deposits: BoundedVec::truncate_from(vec![0, 2]) } @@ -250,17 +252,58 @@ fn unstake_should_work() { // Unstake 2 RING and 2 deposits. Efflux::block(1); assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), 2 * UNIT, vec![0, 2])); + assert_eq!(Staking::accumulate_unstake(), 6 * UNIT); assert!(Staking::ledger_of(1).is_none()); assert_eq!( Deposit::deposit_of(1).unwrap(), ::MaxDeposits>>::truncate_from( vec![ - DepositS { id: 0, value: UNIT, start_time: 3, expired_time: 2635200003, in_use: false }, - DepositS { id: 1, value: UNIT, start_time: 3, expired_time: 2635200003, in_use: false }, - DepositS { id: 2, value: UNIT, start_time: 3, expired_time: 2635200003, in_use: false } + DepositS { + id: 0, + value: UNIT, + start_time: 3, + expired_time: 2635200003, + in_use: false + }, + DepositS { + id: 1, + value: UNIT, + start_time: 3, + expired_time: 2635200003, + in_use: false + }, + DepositS { + id: 2, + value: UNIT, + start_time: 3, + expired_time: 2635200003, + in_use: false + } ] ) ); + + // Prepare rate limit test data. + assert_ok!(Deposit::lock(RuntimeOrigin::signed(1), 94 * UNIT + 1, 1)); + assert_ok!(Staking::stake(RuntimeOrigin::signed(1), 94 * UNIT + 1, vec![3])); + + // Unstake 94 UNIT + 1. + assert_noop!( + Staking::unstake(RuntimeOrigin::signed(1), 94 * UNIT + 1, Vec::new()), + >::ExceedMaxUnstakeAmount + ); + + // Unstake 94 UNIT + 1. + assert_noop!( + Staking::unstake(RuntimeOrigin::signed(1), 0, vec![3]), + >::ExceedMaxUnstakeAmount + ); + + // Unstake RING(94 UNIT + 1) and deposit(94 UNIT + 1). + assert_noop!( + Staking::unstake(RuntimeOrigin::signed(1), 94 * UNIT + 1, vec![3]), + >::ExceedMaxUnstakeAmount + ); }); } diff --git a/pallet/staking/src/weights.rs b/pallet/staking/src/weights.rs index 397832e76..51dc53194 100644 --- a/pallet/staking/src/weights.rs +++ b/pallet/staking/src/weights.rs @@ -58,6 +58,7 @@ pub trait WeightInfo { fn nominate() -> Weight; fn chill() -> Weight; fn payout() -> Weight; + fn set_max_unstake_ring() -> Weight; fn set_collator_count() -> Weight; } @@ -171,6 +172,9 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } + fn set_max_unstake_ring() -> Weight { + Default::default() + } /// Storage: `DarwiniaStaking::CollatorCount` (r:0 w:1) /// Proof: `DarwiniaStaking::CollatorCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn set_collator_count() -> Weight { @@ -293,6 +297,9 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } + fn set_max_unstake_ring() -> Weight { + Default::default() + } /// Storage: `DarwiniaStaking::CollatorCount` (r:0 w:1) /// Proof: `DarwiniaStaking::CollatorCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn set_collator_count() -> Weight { diff --git a/precompile/staking/src/mock.rs b/precompile/staking/src/mock.rs index 8b5817f5a..0b492f7b7 100644 --- a/precompile/staking/src/mock.rs +++ b/precompile/staking/src/mock.rs @@ -268,16 +268,24 @@ impl ExtBuilder { } pub(crate) fn build(self) -> sp_io::TestExternalities { - let mut t = >::default() - .build_storage() - .expect("Frame system builds valid default genesis config"); + let mut storage = + >::default().build_storage().unwrap(); pallet_balances::GenesisConfig:: { balances: self.balances } - .assimilate_storage(&mut t) - .expect("Pallet balances storage can be assimilated"); + .assimilate_storage(&mut storage) + .unwrap(); + darwinia_staking::GenesisConfig:: { + max_unstake_ring: 500, + collator_count: 1, + ..Default::default() + } + .assimilate_storage(&mut storage) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(storage); - let mut ext = sp_io::TestExternalities::new(t); ext.execute_with(|| System::set_block_number(1)); + ext } } diff --git a/runtime/crab/src/weights/darwinia_staking.rs b/runtime/crab/src/weights/darwinia_staking.rs index 590d2384e..cfd61b156 100644 --- a/runtime/crab/src/weights/darwinia_staking.rs +++ b/runtime/crab/src/weights/darwinia_staking.rs @@ -168,6 +168,9 @@ impl darwinia_staking::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) } + fn set_max_unstake_ring() -> Weight { + Default::default() + } /// Storage: `DarwiniaStaking::CollatorCount` (r:0 w:1) /// Proof: `DarwiniaStaking::CollatorCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn set_collator_count() -> Weight { diff --git a/runtime/darwinia/src/weights/darwinia_staking.rs b/runtime/darwinia/src/weights/darwinia_staking.rs index ebc10730e..412514971 100644 --- a/runtime/darwinia/src/weights/darwinia_staking.rs +++ b/runtime/darwinia/src/weights/darwinia_staking.rs @@ -168,6 +168,9 @@ impl darwinia_staking::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().reads(35)) .saturating_add(T::DbWeight::get().writes(2)) } + fn set_max_unstake_ring() -> Weight { + Default::default() + } /// Storage: `DarwiniaStaking::CollatorCount` (r:0 w:1) /// Proof: `DarwiniaStaking::CollatorCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn set_collator_count() -> Weight { diff --git a/runtime/pangolin/src/weights/darwinia_staking.rs b/runtime/pangolin/src/weights/darwinia_staking.rs index 07b1d4b49..cf8708ca7 100644 --- a/runtime/pangolin/src/weights/darwinia_staking.rs +++ b/runtime/pangolin/src/weights/darwinia_staking.rs @@ -168,6 +168,9 @@ impl darwinia_staking::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) } + fn set_max_unstake_ring() -> Weight { + Default::default() + } /// Storage: `DarwiniaStaking::CollatorCount` (r:0 w:1) /// Proof: `DarwiniaStaking::CollatorCount` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn set_collator_count() -> Weight { From da7282fb77a6e72dd73396c13ae50d0dcf2e913c Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Tue, 16 Apr 2024 04:03:54 +0800 Subject: [PATCH 3/6] Better name --- pallet/staking/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pallet/staking/src/lib.rs b/pallet/staking/src/lib.rs index 6d4e9fbaa..90eaf03ad 100644 --- a/pallet/staking/src/lib.rs +++ b/pallet/staking/src/lib.rs @@ -594,9 +594,9 @@ pub mod pallet { /// Update the record of block production. pub fn note_authors(authors: &[T::AccountId]) { - >::mutate(|(sum, map)| { + >::mutate(|(total, map)| { authors.iter().cloned().for_each(|c| { - *sum += One::one(); + *total += One::one(); map.entry(c).and_modify(|p_| *p_ += One::one()).or_insert(One::one()); }); @@ -621,9 +621,9 @@ pub mod pallet { pub fn distribute_session_reward(amount: Balance) { let reward_to_ring = amount.saturating_div(2); let reward_to_kton = amount.saturating_sub(reward_to_ring); - let (sum, map) = >::take(); - let actual_reward_to_ring = map.into_iter().fold(0, |s, (c, p)| { - let r = Perbill::from_rational(p, sum) * reward_to_ring; + let (total, map) = >::take(); + let actual_reward_to_ring = map.into_iter().fold(0, |s, (c, b)| { + let r = Perbill::from_rational(b, total) * reward_to_ring; >::mutate(c, |u| *u = u.map(|u| u + r).or(Some(r))); From c59955ed815cbc1c086b051dbe37ca39b42d29c2 Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Tue, 16 Apr 2024 13:59:17 +0800 Subject: [PATCH 4/6] Fix --- node/src/chain_spec/pangolin.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/node/src/chain_spec/pangolin.rs b/node/src/chain_spec/pangolin.rs index af266abc8..85e151dfb 100644 --- a/node/src/chain_spec/pangolin.rs +++ b/node/src/chain_spec/pangolin.rs @@ -174,6 +174,7 @@ pub fn genesis_config() -> ChainSpec { darwinia_staking: DarwiniaStakingConfig { now: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(), elapsed_time: 0, + max_unstake_ring: 10_000_000 * UNIT, collator_count: 3, collators: vec![ (array_bytes::hex_n_into_unchecked::<_, _, 20>(C1), UNIT), @@ -291,6 +292,7 @@ fn testnet_genesis( darwinia_staking: DarwiniaStakingConfig { now: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(), elapsed_time: 0, + max_unstake_ring: 10_000_000 * UNIT, collator_count: collators.len() as _, collators: collators.iter().map(|(a, _)| (a.to_owned(), UNIT)).collect(), }, From f584143ff7a0c68d20657b30c3d193f1edafebcb Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Wed, 17 Apr 2024 16:17:16 +0800 Subject: [PATCH 5/6] Dynamic rate limit --- node/src/chain_spec/crab.rs | 4 +- node/src/chain_spec/darwinia.rs | 4 +- node/src/chain_spec/pangolin.rs | 4 +- pallet/staking/src/benchmarking.rs | 2 +- pallet/staking/src/lib.rs | 116 +++++++++--- pallet/staking/src/migration/v2.rs | 2 +- pallet/staking/src/mock.rs | 2 +- pallet/staking/src/tests.rs | 174 ++++++++---------- pallet/staking/src/weights.rs | 6 +- precompile/staking/src/mock.rs | 2 +- runtime/crab/src/weights/darwinia_staking.rs | 2 +- .../darwinia/src/weights/darwinia_staking.rs | 2 +- .../pangolin/src/weights/darwinia_staking.rs | 2 +- 13 files changed, 182 insertions(+), 140 deletions(-) diff --git a/node/src/chain_spec/crab.rs b/node/src/chain_spec/crab.rs index 05b98d28a..c720844bc 100644 --- a/node/src/chain_spec/crab.rs +++ b/node/src/chain_spec/crab.rs @@ -200,7 +200,7 @@ pub fn genesis_config() -> ChainSpec { darwinia_staking: DarwiniaStakingConfig { now: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(), elapsed_time: 0, - max_unstake_ring: 10_000_000 * UNIT, + rate_limit: 20_000_000 * UNIT, collator_count: 6, collators: collators .iter() @@ -304,7 +304,7 @@ fn testnet_genesis( darwinia_staking: DarwiniaStakingConfig { now: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(), elapsed_time: 0, - max_unstake_ring: 10_000_000 * UNIT, + rate_limit: 20_000_000 * UNIT, collator_count: collators.len() as _, collators: collators.iter().map(|(a, _)| (a.to_owned(), UNIT)).collect(), }, diff --git a/node/src/chain_spec/darwinia.rs b/node/src/chain_spec/darwinia.rs index 247871b15..b86debe47 100644 --- a/node/src/chain_spec/darwinia.rs +++ b/node/src/chain_spec/darwinia.rs @@ -196,7 +196,7 @@ pub fn genesis_config() -> ChainSpec { darwinia_staking: DarwiniaStakingConfig { now: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(), elapsed_time: 0, - max_unstake_ring: 10_000_000 * UNIT, + rate_limit: 20_000_000 * UNIT, collator_count: 5, collators: collators .iter() @@ -302,7 +302,7 @@ fn testnet_genesis( darwinia_staking: DarwiniaStakingConfig { now: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(), elapsed_time: 0, - max_unstake_ring: 10_000_000 * UNIT, + rate_limit: 20_000_000 * UNIT, collator_count: collators.len() as _, collators: collators.iter().map(|(a, _)| (a.to_owned(), UNIT)).collect(), }, diff --git a/node/src/chain_spec/pangolin.rs b/node/src/chain_spec/pangolin.rs index 85e151dfb..361b466d5 100644 --- a/node/src/chain_spec/pangolin.rs +++ b/node/src/chain_spec/pangolin.rs @@ -174,7 +174,7 @@ pub fn genesis_config() -> ChainSpec { darwinia_staking: DarwiniaStakingConfig { now: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(), elapsed_time: 0, - max_unstake_ring: 10_000_000 * UNIT, + rate_limit: 20_000_000 * UNIT, collator_count: 3, collators: vec![ (array_bytes::hex_n_into_unchecked::<_, _, 20>(C1), UNIT), @@ -292,7 +292,7 @@ fn testnet_genesis( darwinia_staking: DarwiniaStakingConfig { now: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(), elapsed_time: 0, - max_unstake_ring: 10_000_000 * UNIT, + rate_limit: 20_000_000 * UNIT, collator_count: collators.len() as _, collators: collators.iter().map(|(a, _)| (a.to_owned(), UNIT)).collect(), }, diff --git a/pallet/staking/src/benchmarking.rs b/pallet/staking/src/benchmarking.rs index 71b7d971d..90d2e1f98 100644 --- a/pallet/staking/src/benchmarking.rs +++ b/pallet/staking/src/benchmarking.rs @@ -159,7 +159,7 @@ mod benchmarks { } #[benchmark] - fn set_max_unstake_ring() { + fn set_rate_limit() { // Worst-case scenario: // // Set max unstake ring successfully. diff --git a/pallet/staking/src/lib.rs b/pallet/staking/src/lib.rs index 90eaf03ad..8c3a872a3 100644 --- a/pallet/staking/src/lib.rs +++ b/pallet/staking/src/lib.rs @@ -166,8 +166,8 @@ pub mod pallet { pub enum Error { /// Exceed maximum deposit count. ExceedMaxDeposits, - /// Exceed maximum unstake amount. - ExceedMaxUnstakeAmount, + /// Exceed rate limit. + ExceedRateLimit, /// Deposit not found. DepositNotFound, /// You are not a staker. @@ -282,19 +282,19 @@ pub mod pallet { #[pallet::getter(fn elapsed_time)] pub type ElapsedTime = StorageValue<_, Moment, ValueQuery>; - /// Max unstake RING limit. + /// Rate limit. /// - /// The maximum RING amount that can be unstaked in a session. + /// The maximum amount of RING that can be staked or unstaked in one session. #[pallet::storage] - #[pallet::getter(fn max_unstake_ring)] - pub type MaxUnstakeRing = StorageValue<_, Balance, ValueQuery>; + #[pallet::getter(fn rate_limit)] + pub type RateLimit = StorageValue<_, Balance, ValueQuery>; - /// Unstake accumulator. + /// Rate limit state. /// - /// Tracks the total RING amount being unstaked in a session. + /// Tracks the rate limit state in a session. #[pallet::storage] - #[pallet::getter(fn accumulate_unstake)] - pub type AccumulateUnstake = StorageValue<_, Balance, ValueQuery>; + #[pallet::getter(fn rate_limit_state)] + pub type RateLimitState = StorageValue<_, RateLimiter, ValueQuery>; #[derive(DefaultNoBound)] #[pallet::genesis_config] @@ -303,8 +303,8 @@ pub mod pallet { pub now: Moment, /// The running time of Darwinia1. pub elapsed_time: Moment, - /// Max unstake RING limit. - pub max_unstake_ring: Balance, + /// Rate limit. + pub rate_limit: Balance, /// Genesis collator count. pub collator_count: u32, /// Genesis collator preferences. @@ -320,7 +320,7 @@ pub mod pallet { >::put(self.now); >::put(self.elapsed_time); - >::put(self.max_unstake_ring); + >::put(self.rate_limit); >::put(self.collator_count); self.collators.iter().for_each(|(who, ring_amount)| { @@ -376,7 +376,7 @@ pub mod pallet { return Ok(()); } - >::try_mutate(&who, |l| { + let flow_in_amount = >::try_mutate(&who, |l| { let l = if let Some(l) = l { l } else { @@ -386,18 +386,29 @@ pub mod pallet { l.as_mut().expect("[pallet::staking] `l` must be some; qed") }; + let mut v = ring_amount; if ring_amount != 0 { Self::stake_ring(&who, &mut l.ring, ring_amount)?; } for d in deposits.clone() { + v = v.saturating_add(T::Deposit::amount(&who, d).unwrap_or_default()); + Self::stake_deposit(&who, l, d)?; } - DispatchResult::Ok(()) + >::Ok(v) })?; + if let Some(r) = + >::get().flow_in(flow_in_amount, >::get()) + { + >::put(r); + } else { + Err(>::ExceedRateLimit)?; + } + Self::deposit_event(Event::Staked { who, ring_amount, deposits }); Ok(()) @@ -417,10 +428,9 @@ pub mod pallet { return Ok(()); } - let mut acc = >::get().saturating_add(ring_amount); - - >::try_mutate(&who, |l| { + let flow_out_amount = >::try_mutate(&who, |l| { let l = l.as_mut().ok_or(>::NotStaker)?; + let mut v = ring_amount; if ring_amount != 0 { l.ring = l @@ -432,7 +442,7 @@ pub mod pallet { } for d in deposits { - acc = acc.saturating_add(T::Deposit::amount(&who, d).unwrap_or_default()); + v = v.saturating_add(T::Deposit::amount(&who, d).unwrap_or_default()); l.deposits.remove( l.deposits @@ -444,13 +454,15 @@ pub mod pallet { T::Deposit::unstake(&who, d)?; } - DispatchResult::Ok(()) + >::Ok(v) })?; - if acc <= >::get() { - >::put(acc); + if let Some(r) = + >::get().flow_out(flow_out_amount, >::get()) + { + >::put(r); } else { - Err(>::ExceedMaxUnstakeAmount)?; + Err(>::ExceedRateLimit)?; } Self::try_clean_ledger_of(&who); @@ -522,11 +534,11 @@ pub mod pallet { /// Set max unstake RING limit. #[pallet::call_index(9)] - #[pallet::weight(::WeightInfo::set_max_unstake_ring())] - pub fn set_max_unstake_ring(origin: OriginFor, amount: Balance) -> DispatchResult { + #[pallet::weight(::WeightInfo::set_rate_limit())] + pub fn set_rate_limit(origin: OriginFor, amount: Balance) -> DispatchResult { ensure_root(origin)?; - >::put(amount); + >::put(amount); Ok(()) } @@ -676,6 +688,7 @@ pub mod pallet { /// Prepare the session state. pub fn prepare_new_session(index: u32) -> Option> { + >::kill(); >::shift_exposure_cache_states(); #[allow(deprecated)] @@ -810,6 +823,57 @@ where } } +/// Staking rate limiter. +#[derive(Clone, Debug, PartialEq, Encode, Decode, MaxEncodedLen, TypeInfo)] +pub enum RateLimiter { + /// Positive balance. + Pos(Balance), + /// Negative balance. + Neg(Balance), +} +impl RateLimiter { + fn flow_in(self, amount: Balance, limit: Balance) -> Option { + match self { + Self::Pos(v) => v.checked_add(amount).filter(|&v| v <= limit).map(Self::Pos), + Self::Neg(v) => + if v >= amount { + Some(Self::Neg(v - amount)) + } else { + let v = amount - v; + + if v <= limit { + Some(Self::Pos(v)) + } else { + None + } + }, + } + } + + fn flow_out(self, amount: Balance, limit: Balance) -> Option { + match self { + Self::Pos(v) => + if v >= amount { + Some(Self::Pos(v - amount)) + } else { + let v = amount - v; + + if v <= limit { + Some(Self::Neg(v)) + } else { + None + } + }, + Self::Neg(v) => v.checked_add(amount).filter(|&new_v| new_v <= limit).map(Self::Neg), + } + } +} +impl Default for RateLimiter { + fn default() -> Self { + Self::Pos(0) + } +} + /// Exposure cache's state. #[allow(missing_docs)] #[cfg_attr(any(test, feature = "runtime-benchmarks", feature = "try-runtime"), derive(PartialEq))] diff --git a/pallet/staking/src/migration/v2.rs b/pallet/staking/src/migration/v2.rs index 863a377e2..bf2e34201 100644 --- a/pallet/staking/src/migration/v2.rs +++ b/pallet/staking/src/migration/v2.rs @@ -83,7 +83,7 @@ where >::kill(); >::kill(); >::kill(); - >::put(10_000_000 * UNIT); + >::put(10_000_000 * UNIT); >::translate::, _>(|a, o| { w += 6; diff --git a/pallet/staking/src/mock.rs b/pallet/staking/src/mock.rs index 2ab28137f..2891070f8 100644 --- a/pallet/staking/src/mock.rs +++ b/pallet/staking/src/mock.rs @@ -368,7 +368,7 @@ impl ExtBuilder { .assimilate_storage(&mut storage) .unwrap(); darwinia_staking::GenesisConfig:: { - max_unstake_ring: 100 * UNIT, + rate_limit: 100 * UNIT, collator_count: self.collator_count, collators: if self.genesis_collator { (1..=self.collator_count).map(|i| (i, UNIT)).collect() diff --git a/pallet/staking/src/tests.rs b/pallet/staking/src/tests.rs index 6769fd3ab..d6a4f6f7b 100644 --- a/pallet/staking/src/tests.rs +++ b/pallet/staking/src/tests.rs @@ -20,7 +20,7 @@ use core::time::Duration; // darwinia use crate::{mock::*, *}; -use darwinia_deposit::{Deposit as DepositS, Error as DepositError}; +use darwinia_deposit::Error as DepositError; use dc_types::UNIT; // substrate use frame_support::{assert_noop, assert_ok, BoundedVec}; @@ -118,6 +118,7 @@ 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!(Staking::rate_limit_state(), RateLimiter::Pos(0)); // Stake 1 RING. assert_ok!(Staking::stake(RuntimeOrigin::signed(1), UNIT, Vec::new())); @@ -127,6 +128,7 @@ fn stake_should_work() { Ledger { ring: UNIT, deposits: Default::default() } ); assert_eq!(Balances::free_balance(1), 999 * UNIT); + assert_eq!(Staking::rate_limit_state(), RateLimiter::Pos(UNIT)); // Stake invalid deposit. assert_noop!( @@ -142,17 +144,19 @@ fn stake_should_work() { Staking::ledger_of(1).unwrap(), Ledger { ring: UNIT, deposits: BoundedVec::truncate_from(vec![0]) } ); + assert_eq!(Staking::rate_limit_state(), RateLimiter::Pos(2 * UNIT)); - // Stake 500 RING and 2 deposits. + // Stake 2 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, vec![1, 2])); - assert_eq!(Balances::free_balance(1), 98 * UNIT); + 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, vec![1, 2])); + assert_eq!(Balances::free_balance(1), 994 * UNIT); assert_eq!( Staking::ledger_of(1).unwrap(), - Ledger { ring: 501 * UNIT, deposits: BoundedVec::truncate_from(vec![0, 1, 2]) } + Ledger { ring: 3 * UNIT, deposits: BoundedVec::truncate_from(vec![0, 1, 2]) } ); + assert_eq!(Staking::rate_limit_state(), RateLimiter::Pos(6 * UNIT)); }); } @@ -164,42 +168,19 @@ fn unstake_should_work() { assert_ok!(Deposit::lock(RuntimeOrigin::signed(1), UNIT, 1)); assert_ok!(Staking::stake(RuntimeOrigin::signed(1), 3 * UNIT, vec![0, 1, 2])); assert_eq!(Balances::free_balance(1), 994 * UNIT); + assert_eq!(Staking::rate_limit_state(), RateLimiter::Pos(6 * UNIT)); assert_eq!( Staking::ledger_of(1).unwrap(), Ledger { ring: 3 * UNIT, deposits: BoundedVec::truncate_from(vec![0, 1, 2]) } ); assert_eq!( - Deposit::deposit_of(1).unwrap(), - ::MaxDeposits>>::truncate_from( - vec![ - DepositS { - id: 0, - value: UNIT, - start_time: 3, - expired_time: 2635200003, - in_use: true - }, - DepositS { - id: 1, - value: UNIT, - start_time: 3, - expired_time: 2635200003, - in_use: true - }, - DepositS { - id: 2, - value: UNIT, - start_time: 3, - expired_time: 2635200003, - in_use: true - } - ] - ) + Deposit::deposit_of(1).unwrap().into_iter().map(|d| d.in_use).collect::>(), + [true, true, true] ); // Unstake 1 RING. assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), UNIT, Vec::new())); - assert_eq!(Staking::accumulate_unstake(), UNIT); + assert_eq!(Staking::rate_limit_state(), RateLimiter::Pos(5 * UNIT)); assert_eq!(Balances::free_balance(1), 995 * UNIT); assert_eq!( Staking::ledger_of(1).unwrap(), @@ -215,94 +196,49 @@ fn unstake_should_work() { // Unstake 1 deposit. Efflux::block(1); assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), 0, vec![1])); - assert_eq!(Staking::accumulate_unstake(), 2 * UNIT); + assert_eq!(Staking::rate_limit_state(), RateLimiter::Pos(4 * UNIT)); assert_eq!( Staking::ledger_of(1).unwrap(), Ledger { ring: 2 * UNIT, deposits: BoundedVec::truncate_from(vec![0, 2]) } ); assert_eq!( - Deposit::deposit_of(1).unwrap(), - ::MaxDeposits>>::truncate_from( - vec![ - DepositS { - id: 0, - value: UNIT, - start_time: 3, - expired_time: 2635200003, - in_use: true - }, - DepositS { - id: 1, - value: UNIT, - start_time: 3, - expired_time: 2635200003, - in_use: false - }, - DepositS { - id: 2, - value: UNIT, - start_time: 3, - expired_time: 2635200003, - in_use: true - } - ] - ) + Deposit::deposit_of(1).unwrap().into_iter().map(|d| d.in_use).collect::>(), + [true, false, true] ); // Unstake 2 RING and 2 deposits. Efflux::block(1); assert_ok!(Staking::unstake(RuntimeOrigin::signed(1), 2 * UNIT, vec![0, 2])); - assert_eq!(Staking::accumulate_unstake(), 6 * UNIT); + assert_eq!(Staking::rate_limit_state(), RateLimiter::Pos(0)); assert!(Staking::ledger_of(1).is_none()); assert_eq!( - Deposit::deposit_of(1).unwrap(), - ::MaxDeposits>>::truncate_from( - vec![ - DepositS { - id: 0, - value: UNIT, - start_time: 3, - expired_time: 2635200003, - in_use: false - }, - DepositS { - id: 1, - value: UNIT, - start_time: 3, - expired_time: 2635200003, - in_use: false - }, - DepositS { - id: 2, - value: UNIT, - start_time: 3, - expired_time: 2635200003, - in_use: false - } - ] - ) + Deposit::deposit_of(1).unwrap().into_iter().map(|d| d.in_use).collect::>(), + [false, false, false] ); // Prepare rate limit test data. - assert_ok!(Deposit::lock(RuntimeOrigin::signed(1), 94 * UNIT + 1, 1)); - assert_ok!(Staking::stake(RuntimeOrigin::signed(1), 94 * UNIT + 1, vec![3])); + assert_ok!(Deposit::lock(RuntimeOrigin::signed(1), 100 * UNIT + 1, 1)); + >::put(200 * UNIT + 2); + assert_ok!(Staking::stake(RuntimeOrigin::signed(1), 100 * UNIT + 1, vec![3])); + >::put(100 * UNIT); + >::kill(); - // Unstake 94 UNIT + 1. + // Unstake 100 UNIT + 1. assert_noop!( - Staking::unstake(RuntimeOrigin::signed(1), 94 * UNIT + 1, Vec::new()), - >::ExceedMaxUnstakeAmount + Staking::unstake(RuntimeOrigin::signed(1), 100 * UNIT + 1, Vec::new()), + >::ExceedRateLimit ); - // Unstake 94 UNIT + 1. + // Unstake 100 UNIT + 1. assert_noop!( Staking::unstake(RuntimeOrigin::signed(1), 0, vec![3]), - >::ExceedMaxUnstakeAmount + >::ExceedRateLimit ); - // Unstake RING(94 UNIT + 1) and deposit(94 UNIT + 1). + // Unstake RING(100 UNIT + 1) and deposit(100 UNIT + 1). assert_noop!( - Staking::unstake(RuntimeOrigin::signed(1), 94 * UNIT + 1, vec![3]), - >::ExceedMaxUnstakeAmount + Staking::unstake(RuntimeOrigin::signed(1), 100 * UNIT + 1, vec![3]), + >::ExceedRateLimit ); }); } @@ -699,3 +635,45 @@ fn on_new_session_should_work() { ); }); } + +#[test] +fn rate_limiter_should_work() { + let r = RateLimiter::default(); + let r = r.flow_in(UNIT, 3 * UNIT).unwrap(); + + assert_eq!(r, RateLimiter::Pos(UNIT)); + + let r = r.flow_in(2 * UNIT, 3 * UNIT).unwrap(); + + assert_eq!(r, RateLimiter::Pos(3 * UNIT)); + assert!(r.clone().flow_in(1, 3 * UNIT).is_none()); + + let r = r.flow_out(UNIT, 3 * UNIT).unwrap(); + + assert_eq!(r, RateLimiter::Pos(2 * UNIT)); + + let r = r.flow_out(2 * UNIT, 3 * UNIT).unwrap(); + + assert_eq!(r, RateLimiter::Pos(0)); + + let r = r.flow_out(UNIT, 3 * UNIT).unwrap(); + + assert_eq!(r, RateLimiter::Neg(UNIT)); + + let r = r.flow_out(2 * UNIT, 3 * UNIT).unwrap(); + + assert_eq!(r, RateLimiter::Neg(3 * UNIT)); + assert!(r.clone().flow_out(1, 3 * UNIT).is_none()); + + let r = r.flow_in(UNIT, 3 * UNIT).unwrap(); + + assert_eq!(r, RateLimiter::Neg(2 * UNIT)); + + let r = r.flow_in(2 * UNIT, 3 * UNIT).unwrap(); + + assert_eq!(r, RateLimiter::Neg(0)); + + let r = r.flow_in(UNIT, 3 * UNIT).unwrap(); + + assert_eq!(r, RateLimiter::Pos(UNIT)); +} diff --git a/pallet/staking/src/weights.rs b/pallet/staking/src/weights.rs index 51dc53194..da3e8102b 100644 --- a/pallet/staking/src/weights.rs +++ b/pallet/staking/src/weights.rs @@ -58,7 +58,7 @@ pub trait WeightInfo { fn nominate() -> Weight; fn chill() -> Weight; fn payout() -> Weight; - fn set_max_unstake_ring() -> Weight; + fn set_rate_limit() -> Weight; fn set_collator_count() -> Weight; } @@ -172,7 +172,7 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - fn set_max_unstake_ring() -> Weight { + fn set_rate_limit() -> Weight { Default::default() } /// Storage: `DarwiniaStaking::CollatorCount` (r:0 w:1) @@ -297,7 +297,7 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - fn set_max_unstake_ring() -> Weight { + fn set_rate_limit() -> Weight { Default::default() } /// Storage: `DarwiniaStaking::CollatorCount` (r:0 w:1) diff --git a/precompile/staking/src/mock.rs b/precompile/staking/src/mock.rs index 0b492f7b7..e9855f3e0 100644 --- a/precompile/staking/src/mock.rs +++ b/precompile/staking/src/mock.rs @@ -275,7 +275,7 @@ impl ExtBuilder { .assimilate_storage(&mut storage) .unwrap(); darwinia_staking::GenesisConfig:: { - max_unstake_ring: 500, + rate_limit: 500, collator_count: 1, ..Default::default() } diff --git a/runtime/crab/src/weights/darwinia_staking.rs b/runtime/crab/src/weights/darwinia_staking.rs index cfd61b156..a5a4babcd 100644 --- a/runtime/crab/src/weights/darwinia_staking.rs +++ b/runtime/crab/src/weights/darwinia_staking.rs @@ -168,7 +168,7 @@ impl darwinia_staking::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) } - fn set_max_unstake_ring() -> Weight { + fn set_rate_limit() -> Weight { Default::default() } /// Storage: `DarwiniaStaking::CollatorCount` (r:0 w:1) diff --git a/runtime/darwinia/src/weights/darwinia_staking.rs b/runtime/darwinia/src/weights/darwinia_staking.rs index 412514971..f1b33afb0 100644 --- a/runtime/darwinia/src/weights/darwinia_staking.rs +++ b/runtime/darwinia/src/weights/darwinia_staking.rs @@ -168,7 +168,7 @@ impl darwinia_staking::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().reads(35)) .saturating_add(T::DbWeight::get().writes(2)) } - fn set_max_unstake_ring() -> Weight { + fn set_rate_limit() -> Weight { Default::default() } /// Storage: `DarwiniaStaking::CollatorCount` (r:0 w:1) diff --git a/runtime/pangolin/src/weights/darwinia_staking.rs b/runtime/pangolin/src/weights/darwinia_staking.rs index cf8708ca7..4098e3c0c 100644 --- a/runtime/pangolin/src/weights/darwinia_staking.rs +++ b/runtime/pangolin/src/weights/darwinia_staking.rs @@ -168,7 +168,7 @@ impl darwinia_staking::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().reads(4)) .saturating_add(T::DbWeight::get().writes(2)) } - fn set_max_unstake_ring() -> Weight { + fn set_rate_limit() -> Weight { Default::default() } /// Storage: `DarwiniaStaking::CollatorCount` (r:0 w:1) From ede7488260e5c01138fc2b057ff8943a56363718 Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Wed, 17 Apr 2024 16:24:03 +0800 Subject: [PATCH 6/6] More test --- pallet/staking/src/migration/v2.rs | 2 +- pallet/staking/src/tests.rs | 49 ++++++++++++++---------------- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/pallet/staking/src/migration/v2.rs b/pallet/staking/src/migration/v2.rs index bf2e34201..35de094a8 100644 --- a/pallet/staking/src/migration/v2.rs +++ b/pallet/staking/src/migration/v2.rs @@ -83,7 +83,7 @@ where >::kill(); >::kill(); >::kill(); - >::put(10_000_000 * UNIT); + >::put(20_000_000 * UNIT); >::translate::, _>(|a, o| { w += 6; diff --git a/pallet/staking/src/tests.rs b/pallet/staking/src/tests.rs index d6a4f6f7b..865657c61 100644 --- a/pallet/staking/src/tests.rs +++ b/pallet/staking/src/tests.rs @@ -639,41 +639,38 @@ fn on_new_session_should_work() { #[test] fn rate_limiter_should_work() { let r = RateLimiter::default(); - let r = r.flow_in(UNIT, 3 * UNIT).unwrap(); + let r = r.flow_in(1, 3).unwrap(); + assert_eq!(r, RateLimiter::Pos(1)); - assert_eq!(r, RateLimiter::Pos(UNIT)); + let r = r.flow_in(2, 3).unwrap(); + assert_eq!(r, RateLimiter::Pos(3)); + assert!(r.clone().flow_in(1, 3).is_none()); - let r = r.flow_in(2 * UNIT, 3 * UNIT).unwrap(); - - assert_eq!(r, RateLimiter::Pos(3 * UNIT)); - assert!(r.clone().flow_in(1, 3 * UNIT).is_none()); - - let r = r.flow_out(UNIT, 3 * UNIT).unwrap(); - - assert_eq!(r, RateLimiter::Pos(2 * UNIT)); - - let r = r.flow_out(2 * UNIT, 3 * UNIT).unwrap(); + let r = r.flow_out(1, 3).unwrap(); + assert_eq!(r, RateLimiter::Pos(2)); + let r = r.flow_out(2, 3).unwrap(); assert_eq!(r, RateLimiter::Pos(0)); - let r = r.flow_out(UNIT, 3 * UNIT).unwrap(); - - assert_eq!(r, RateLimiter::Neg(UNIT)); + let r = r.flow_out(1, 3).unwrap(); + assert_eq!(r, RateLimiter::Neg(1)); - let r = r.flow_out(2 * UNIT, 3 * UNIT).unwrap(); + let r = r.flow_out(2, 3).unwrap(); + assert_eq!(r, RateLimiter::Neg(3)); + assert!(r.clone().flow_out(1, 3).is_none()); - assert_eq!(r, RateLimiter::Neg(3 * UNIT)); - assert!(r.clone().flow_out(1, 3 * UNIT).is_none()); - - let r = r.flow_in(UNIT, 3 * UNIT).unwrap(); - - assert_eq!(r, RateLimiter::Neg(2 * UNIT)); - - let r = r.flow_in(2 * UNIT, 3 * UNIT).unwrap(); + let r = r.flow_in(1, 3).unwrap(); + assert_eq!(r, RateLimiter::Neg(2)); + let r = r.flow_in(2, 3).unwrap(); assert_eq!(r, RateLimiter::Neg(0)); - let r = r.flow_in(UNIT, 3 * UNIT).unwrap(); + let r = r.flow_in(1, 3).unwrap(); + assert_eq!(r, RateLimiter::Pos(1)); + + let r = RateLimiter::Pos(3); + assert_eq!(r.flow_out(6, 3).unwrap(), RateLimiter::Neg(3)); - assert_eq!(r, RateLimiter::Pos(UNIT)); + let r = RateLimiter::Neg(3); + assert_eq!(r.flow_in(6, 3).unwrap(), RateLimiter::Pos(3)); }