From c6e4c931a360548e0577599f0c70267af882d355 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sat, 9 Mar 2024 08:52:18 +0100 Subject: [PATCH 01/41] force unbond in staking --- substrate/frame/staking/src/pallet/impls.rs | 82 ++++++++++++++- substrate/frame/staking/src/pallet/mod.rs | 106 ++++++-------------- 2 files changed, 111 insertions(+), 77 deletions(-) diff --git a/substrate/frame/staking/src/pallet/impls.rs b/substrate/frame/staking/src/pallet/impls.rs index d42456e53b13d..9e07cfceb21e5 100644 --- a/substrate/frame/staking/src/pallet/impls.rs +++ b/substrate/frame/staking/src/pallet/impls.rs @@ -51,7 +51,7 @@ use crate::{ election_size_tracker::StaticTracker, log, slashing, weights::WeightInfo, ActiveEraInfo, BalanceOf, EraInfo, EraPayout, Exposure, ExposureOf, Forcing, IndividualExposure, MaxNominationsOf, MaxWinnersOf, Nominations, NominationsQuota, PositiveImbalanceOf, - RewardDestination, SessionInterface, StakingLedger, ValidatorPrefs, + RewardDestination, SessionInterface, StakingLedger, UnlockChunk, ValidatorPrefs, }; use super::pallet::*; @@ -1100,6 +1100,86 @@ impl Pallet { ) -> Exposure> { EraInfo::::get_full_exposure(era, account) } + + /// Chill a stash account. + pub(crate) fn do_unbond( + controller: T::AccountId, + value: BalanceOf, + ) -> Result, DispatchError> { + let unlocking = Self::ledger(Controller(controller.clone())).map(|l| l.unlocking.len())?; + + // if there are no unlocking chunks available, try to withdraw chunks older than + // `BondingDuration` to proceed with the unbonding. + let maybe_withdraw_weight = { + if unlocking == T::MaxUnlockingChunks::get() as usize { + let real_num_slashing_spans = + Self::slashing_spans(&controller).map_or(0, |s| s.iter().count()); + Some(Self::do_withdraw_unbonded(&controller, real_num_slashing_spans as u32)?) + } else { + None + } + }; + + // we need to fetch the ledger again because it may have been mutated in the call + // to `Self::do_withdraw_unbonded` above. + let mut ledger = Self::ledger(Controller(controller.clone()))?; + let mut value = value.min(ledger.active); + let stash = ledger.stash.clone(); + + ensure!( + ledger.unlocking.len() < T::MaxUnlockingChunks::get() as usize, + Error::::NoMoreChunks, + ); + + if !value.is_zero() { + ledger.active -= value; + + // Avoid there being a dust balance left in the staking system. + if ledger.active < T::Currency::minimum_balance() { + value += ledger.active; + ledger.active = Zero::zero(); + } + + let min_active_bond = if Nominators::::contains_key(&stash) { + MinNominatorBond::::get() + } else if Validators::::contains_key(&stash) { + MinValidatorBond::::get() + } else { + Zero::zero() + }; + + // Make sure that the user maintains enough active bond for their role. + // If a user runs into this error, they should chill first. + ensure!(ledger.active >= min_active_bond, Error::::InsufficientBond); + + // Note: in case there is no current era it is fine to bond one era more. + let era = Self::current_era() + .unwrap_or(0) + .defensive_saturating_add(T::BondingDuration::get()); + if let Some(chunk) = ledger.unlocking.last_mut().filter(|chunk| chunk.era == era) { + // To keep the chunk count down, we only keep one chunk per era. Since + // `unlocking` is a FiFo queue, if a chunk exists for `era` we know that it will + // be the last one. + chunk.value = chunk.value.defensive_saturating_add(value) + } else { + ledger + .unlocking + .try_push(UnlockChunk { value, era }) + .map_err(|_| Error::::NoMoreChunks)?; + }; + // NOTE: ledger must be updated prior to calling `Self::weight_of`. + ledger.update()?; + + // update this staker in the sorted list, if they exist in it. + if T::VoterList::contains(&stash) { + let _ = T::VoterList::on_update(&stash, Self::weight_of(&stash)).defensive(); + } + + Self::deposit_event(Event::::Unbonded { stash, amount: value }); + } + + Ok(maybe_withdraw_weight) + } } impl Pallet { diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index 1bf8bd8b09cb7..0b33c22c7622e 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -24,8 +24,8 @@ use frame_election_provider_support::{ use frame_support::{ pallet_prelude::*, traits::{ - Currency, Defensive, DefensiveSaturating, EnsureOrigin, EstimateNextNewSession, Get, - LockableCurrency, OnUnbalanced, UnixTime, + Currency, Defensive, EnsureOrigin, EstimateNextNewSession, Get, LockableCurrency, + OnUnbalanced, UnixTime, }, weights::Weight, BoundedVec, @@ -50,7 +50,7 @@ use crate::{ slashing, weights::WeightInfo, AccountIdLookupOf, ActiveEraInfo, BalanceOf, EraPayout, EraRewardPoints, Exposure, ExposurePage, Forcing, MaxNominationsOf, NegativeImbalanceOf, Nominations, NominationsQuota, PositiveImbalanceOf, RewardDestination, SessionInterface, - StakingLedger, UnappliedSlash, UnlockChunk, ValidatorPrefs, + StakingLedger, UnappliedSlash, ValidatorPrefs, }; // The speculative number of spans are used as an input of the weight annotation of @@ -1035,79 +1035,7 @@ pub mod pallet { #[pallet::compact] value: BalanceOf, ) -> DispatchResultWithPostInfo { let controller = ensure_signed(origin)?; - let unlocking = - Self::ledger(Controller(controller.clone())).map(|l| l.unlocking.len())?; - - // if there are no unlocking chunks available, try to withdraw chunks older than - // `BondingDuration` to proceed with the unbonding. - let maybe_withdraw_weight = { - if unlocking == T::MaxUnlockingChunks::get() as usize { - let real_num_slashing_spans = - Self::slashing_spans(&controller).map_or(0, |s| s.iter().count()); - Some(Self::do_withdraw_unbonded(&controller, real_num_slashing_spans as u32)?) - } else { - None - } - }; - - // we need to fetch the ledger again because it may have been mutated in the call - // to `Self::do_withdraw_unbonded` above. - let mut ledger = Self::ledger(Controller(controller))?; - let mut value = value.min(ledger.active); - let stash = ledger.stash.clone(); - - ensure!( - ledger.unlocking.len() < T::MaxUnlockingChunks::get() as usize, - Error::::NoMoreChunks, - ); - - if !value.is_zero() { - ledger.active -= value; - - // Avoid there being a dust balance left in the staking system. - if ledger.active < T::Currency::minimum_balance() { - value += ledger.active; - ledger.active = Zero::zero(); - } - - let min_active_bond = if Nominators::::contains_key(&stash) { - MinNominatorBond::::get() - } else if Validators::::contains_key(&stash) { - MinValidatorBond::::get() - } else { - Zero::zero() - }; - - // Make sure that the user maintains enough active bond for their role. - // If a user runs into this error, they should chill first. - ensure!(ledger.active >= min_active_bond, Error::::InsufficientBond); - - // Note: in case there is no current era it is fine to bond one era more. - let era = Self::current_era() - .unwrap_or(0) - .defensive_saturating_add(T::BondingDuration::get()); - if let Some(chunk) = ledger.unlocking.last_mut().filter(|chunk| chunk.era == era) { - // To keep the chunk count down, we only keep one chunk per era. Since - // `unlocking` is a FiFo queue, if a chunk exists for `era` we know that it will - // be the last one. - chunk.value = chunk.value.defensive_saturating_add(value) - } else { - ledger - .unlocking - .try_push(UnlockChunk { value, era }) - .map_err(|_| Error::::NoMoreChunks)?; - }; - // NOTE: ledger must be updated prior to calling `Self::weight_of`. - ledger.update()?; - - // update this staker in the sorted list, if they exist in it. - if T::VoterList::contains(&stash) { - let _ = T::VoterList::on_update(&stash, Self::weight_of(&stash)).defensive(); - } - - Self::deposit_event(Event::::Unbonded { stash, amount: value }); - } - + let maybe_withdraw_weight = Self::do_unbond(controller, value)?; let actual_weight = if let Some(withdraw_weight) = maybe_withdraw_weight { Some(T::WeightInfo::unbond().saturating_add(withdraw_weight)) } else { @@ -1980,6 +1908,32 @@ pub mod pallet { Ok(Some(T::WeightInfo::deprecate_controller_batch(controllers.len() as u32)).into()) } + + /// Forcefully Unbonds by Chilling first + /// Emits `Unbonded`. + #[pallet::call_index(29)] + #[pallet::weight( + T::WeightInfo::withdraw_unbonded_kill(SPECULATIVE_NUM_SPANS).saturating_add(T::WeightInfo::unbond())) + ] + pub fn force_unbond( + origin: OriginFor, + #[pallet::compact] value: BalanceOf, + ) -> DispatchResultWithPostInfo { + let controller = ensure_signed(origin)?; + + let ledger = Self::ledger(StakingAccount::Controller(controller.clone()))?; + + Self::chill_stash(&ledger.stash); + + let maybe_withdraw_weight = Self::do_unbond(controller, value)?; + let actual_weight = if let Some(withdraw_weight) = maybe_withdraw_weight { + Some(T::WeightInfo::unbond().saturating_add(withdraw_weight)) + } else { + Some(T::WeightInfo::unbond()) + }; + + Ok(actual_weight.into()) + } } } From 12e62a90e1254673d5d420a3ea479503e822e457 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Tue, 12 Mar 2024 11:36:57 +0100 Subject: [PATCH 02/41] check to see if controller wants to fully unbond test and benchmark --- prdoc/pr_3629.prdoc | 10 +++++ substrate/frame/staking/src/benchmarking.rs | 26 +++++++++++++ substrate/frame/staking/src/pallet/mod.rs | 18 +++++++-- substrate/frame/staking/src/tests.rs | 43 +++++++++++++++++++++ substrate/frame/staking/src/weights.rs | 39 +++++++++++++++++++ 5 files changed, 132 insertions(+), 4 deletions(-) create mode 100644 prdoc/pr_3629.prdoc diff --git a/prdoc/pr_3629.prdoc b/prdoc/pr_3629.prdoc new file mode 100644 index 0000000000000..b04ae3c7acc74 --- /dev/null +++ b/prdoc/pr_3629.prdoc @@ -0,0 +1,10 @@ +title: "[pallet_staking] Staking `force_unbond`" + +doc: + - audience: Runtime Dev + description: | + Force unbond when staking such that to fully unbond as a validator or nominator, chilled occurs first + before unbonding + +crates: + - name: pallet-staking diff --git a/substrate/frame/staking/src/benchmarking.rs b/substrate/frame/staking/src/benchmarking.rs index a83060873973c..541c8e3f4b068 100644 --- a/substrate/frame/staking/src/benchmarking.rs +++ b/substrate/frame/staking/src/benchmarking.rs @@ -953,6 +953,32 @@ benchmarks! { assert_eq!(MinCommission::::get(), Perbill::from_percent(100)); } + force_unbond { + // clean up any existing state. + clear_validators_and_nominators::(); + + // setup the worst case list scenario. + let total_issuance = T::Currency::total_issuance(); + // the weight the nominator will start at. The value used here is expected to be + // significantly higher than the first position in a list (e.g. the first bag threshold). + let origin_weight = BalanceOf::::try_from(952_994_955_240_703u128) + .map_err(|_| "balance expected to be a u128") + .unwrap(); + let scenario = ListScenario::::new(origin_weight, false)?; + + let stash = scenario.origin_stash1.clone(); + let controller = scenario.origin_controller1.clone(); + let ledger = Ledger::::get(&controller).ok_or("ledger not created before")?; + let original_bonded: BalanceOf = ledger.active; + + whitelist_account!(controller); + }: _(RawOrigin::Signed(controller.clone()), original_bonded) + verify { + let ledger = Ledger::::get(&controller).ok_or("ledger not created after")?; + let new_bonded: BalanceOf = ledger.active; + assert!(original_bonded > new_bonded); + } + impl_benchmark_test_suite!( Staking, crate::mock::ExtBuilder::default().has_stakers(true), diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index 0b33c22c7622e..e5c44744e3236 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -1913,7 +1913,7 @@ pub mod pallet { /// Emits `Unbonded`. #[pallet::call_index(29)] #[pallet::weight( - T::WeightInfo::withdraw_unbonded_kill(SPECULATIVE_NUM_SPANS).saturating_add(T::WeightInfo::unbond())) + T::WeightInfo::withdraw_unbonded_kill(SPECULATIVE_NUM_SPANS).saturating_add(T::WeightInfo::force_unbond())) ] pub fn force_unbond( origin: OriginFor, @@ -1923,13 +1923,23 @@ pub mod pallet { let ledger = Self::ledger(StakingAccount::Controller(controller.clone()))?; - Self::chill_stash(&ledger.stash); + let min_active_bond = if Nominators::::contains_key(&ledger.stash) { + MinNominatorBond::::get() + } else if Validators::::contains_key(&ledger.stash) { + MinValidatorBond::::get() + } else { + Zero::zero() + }; + + if (ledger.active - value) <= min_active_bond { + Self::chill_stash(&ledger.stash); + } let maybe_withdraw_weight = Self::do_unbond(controller, value)?; let actual_weight = if let Some(withdraw_weight) = maybe_withdraw_weight { - Some(T::WeightInfo::unbond().saturating_add(withdraw_weight)) + Some(T::WeightInfo::force_unbond().saturating_add(withdraw_weight)) } else { - Some(T::WeightInfo::unbond()) + Some(T::WeightInfo::force_unbond()) }; Ok(actual_weight.into()) diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs index 3725c9e3c2c5b..f8ec41d4c53e0 100644 --- a/substrate/frame/staking/src/tests.rs +++ b/substrate/frame/staking/src/tests.rs @@ -4069,6 +4069,49 @@ fn test_multi_page_payout_stakers_by_page() { }); } +#[test] +fn force_unbond_works() { + // + // * Should test + // * Given an account being bonded [and chosen as a validator](not mandatory) + // * it can force unbond a portion of its funds from the stash account. + ExtBuilder::default().nominate(false).build_and_execute(|| { + // Set payee to stash. + assert_ok!(Staking::set_payee(RuntimeOrigin::signed(11), RewardDestination::Stash)); + + // Give account 11 some large free balance greater than total + let _ = Balances::make_free_balance_be(&11, 1000000); + + // confirm that 10 is a normal validator and gets paid at the end of the era. + mock::start_active_era(1); + + // Initial state of 11 + assert_eq!( + Staking::ledger(11.into()).unwrap(), + StakingLedgerInspect { + stash: 11, + total: 1000, + active: 1000, + unlocking: Default::default(), + legacy_claimed_rewards: bounded_vec![], + } + ); + + mock::start_active_era(2); + assert_eq!(active_era(), 2); + + // unbonding without chilling fails + assert_noop!( + Staking::unbond(RuntimeOrigin::signed(11), 1000), + Error::::InsufficientBond, + ); + + // Force Unbond all of the funds in stash which makes the call to chill first. + let res = Staking::force_unbond(RuntimeOrigin::signed(11), 1000); + assert!(res.is_ok()); + }) +} + #[test] fn test_multi_page_payout_stakers_backward_compatible() { // Test that payout_stakers work in general and that it pays the correct amount of reward. diff --git a/substrate/frame/staking/src/weights.rs b/substrate/frame/staking/src/weights.rs index 6f729e08ba5c8..ae3d3acc2d2c0 100644 --- a/substrate/frame/staking/src/weights.rs +++ b/substrate/frame/staking/src/weights.rs @@ -80,6 +80,7 @@ pub trait WeightInfo { fn chill_other() -> Weight; fn force_apply_min_commission() -> Weight; fn set_min_commission() -> Weight; + fn force_unbond() -> Weight; } /// Weights for `pallet_staking` using the Substrate node and recommended hardware. @@ -802,6 +803,10 @@ impl WeightInfo for SubstrateWeight { Weight::from_parts(3_334_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } + + fn force_unbond() -> Weight { + todo!() + } } // For backwards compatibility and tests. @@ -1523,4 +1528,38 @@ impl WeightInfo for () { Weight::from_parts(3_334_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:1 w:1) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `Staking::MinNominatorBond` (r:1 w:0) + /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Staking::Validators` (r:1 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `Staking::CounterForNominators` (r:1 w:1) + /// Proof: `Staking::CounterForNominators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:2 w:2) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:1 w:1) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) + /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) + fn force_unbond() -> Weight { + // Proof Size summary in bytes: + // Measured: `2122` + // Estimated: `6248` + // Minimum execution time: 76_000_000 picoseconds. + Weight::from_parts(78_000_000, 0) + .saturating_add(Weight::from_parts(0, 6248)) + .saturating_add(RocksDbWeight::get().reads(13)) + .saturating_add(RocksDbWeight::get().writes(8)) + } } From 345b2fa9162553a9f8a8caa9f8fa90cd5281fd79 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Tue, 12 Mar 2024 11:40:48 +0100 Subject: [PATCH 03/41] comment --- substrate/frame/staking/src/pallet/impls.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/staking/src/pallet/impls.rs b/substrate/frame/staking/src/pallet/impls.rs index 9e07cfceb21e5..c96404626759f 100644 --- a/substrate/frame/staking/src/pallet/impls.rs +++ b/substrate/frame/staking/src/pallet/impls.rs @@ -1101,7 +1101,7 @@ impl Pallet { EraInfo::::get_full_exposure(era, account) } - /// Chill a stash account. + /// Unbonds a controller. pub(crate) fn do_unbond( controller: T::AccountId, value: BalanceOf, From 0b8ef9ee9064898090b86192e3f5fd6845fc48aa Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Tue, 12 Mar 2024 11:46:11 +0100 Subject: [PATCH 04/41] unimplemented force_unbond --- polkadot/runtime/westend/src/weights/pallet_staking.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/polkadot/runtime/westend/src/weights/pallet_staking.rs b/polkadot/runtime/westend/src/weights/pallet_staking.rs index 7a641e36a126b..0fc440e46d2f4 100644 --- a/polkadot/runtime/westend/src/weights/pallet_staking.rs +++ b/polkadot/runtime/westend/src/weights/pallet_staking.rs @@ -800,4 +800,8 @@ impl pallet_staking::WeightInfo for WeightInfo { .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } + + fn force_unbond() -> Weight { + todo!() + } } From df5c1867d0e5a41851384c2a4824c248a3761d61 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sun, 24 Mar 2024 16:06:02 +0100 Subject: [PATCH 05/41] full unbond instead --- .../westend/src/weights/pallet_staking.rs | 2 +- prdoc/pr_3629.prdoc | 10 ------- prdoc/pr_3811.prdoc | 10 +++++++ substrate/frame/staking/src/benchmarking.rs | 4 +-- substrate/frame/staking/src/pallet/mod.rs | 27 +++++-------------- substrate/frame/staking/src/tests.rs | 4 +-- substrate/frame/staking/src/weights.rs | 6 ++--- 7 files changed, 25 insertions(+), 38 deletions(-) delete mode 100644 prdoc/pr_3629.prdoc create mode 100644 prdoc/pr_3811.prdoc diff --git a/polkadot/runtime/westend/src/weights/pallet_staking.rs b/polkadot/runtime/westend/src/weights/pallet_staking.rs index 0fc440e46d2f4..265a1754c2e75 100644 --- a/polkadot/runtime/westend/src/weights/pallet_staking.rs +++ b/polkadot/runtime/westend/src/weights/pallet_staking.rs @@ -801,7 +801,7 @@ impl pallet_staking::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().writes(1)) } - fn force_unbond() -> Weight { + fn full_unbond() -> Weight { todo!() } } diff --git a/prdoc/pr_3629.prdoc b/prdoc/pr_3629.prdoc deleted file mode 100644 index b04ae3c7acc74..0000000000000 --- a/prdoc/pr_3629.prdoc +++ /dev/null @@ -1,10 +0,0 @@ -title: "[pallet_staking] Staking `force_unbond`" - -doc: - - audience: Runtime Dev - description: | - Force unbond when staking such that to fully unbond as a validator or nominator, chilled occurs first - before unbonding - -crates: - - name: pallet-staking diff --git a/prdoc/pr_3811.prdoc b/prdoc/pr_3811.prdoc new file mode 100644 index 0000000000000..b1918cea2946d --- /dev/null +++ b/prdoc/pr_3811.prdoc @@ -0,0 +1,10 @@ +title: "[pallet_staking] Staking `full_unbond`" + +doc: + - audience: Runtime Dev + description: | + Full unbond when staking such that to fully unbond as a validator or nominator, chilled occurs first + before unbonding + +crates: + - name: pallet-staking diff --git a/substrate/frame/staking/src/benchmarking.rs b/substrate/frame/staking/src/benchmarking.rs index 541c8e3f4b068..d174a4e945c5a 100644 --- a/substrate/frame/staking/src/benchmarking.rs +++ b/substrate/frame/staking/src/benchmarking.rs @@ -953,7 +953,7 @@ benchmarks! { assert_eq!(MinCommission::::get(), Perbill::from_percent(100)); } - force_unbond { + full_unbond { // clean up any existing state. clear_validators_and_nominators::(); @@ -972,7 +972,7 @@ benchmarks! { let original_bonded: BalanceOf = ledger.active; whitelist_account!(controller); - }: _(RawOrigin::Signed(controller.clone()), original_bonded) + }: _(RawOrigin::Signed(controller.clone())) verify { let ledger = Ledger::::get(&controller).ok_or("ledger not created after")?; let new_bonded: BalanceOf = ledger.active; diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index e5c44744e3236..961ae6aed80c1 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -1909,37 +1909,24 @@ pub mod pallet { Ok(Some(T::WeightInfo::deprecate_controller_batch(controllers.len() as u32)).into()) } - /// Forcefully Unbonds by Chilling first + /// Fully Unbonds by Chilling first /// Emits `Unbonded`. #[pallet::call_index(29)] #[pallet::weight( - T::WeightInfo::withdraw_unbonded_kill(SPECULATIVE_NUM_SPANS).saturating_add(T::WeightInfo::force_unbond())) + T::WeightInfo::withdraw_unbonded_kill(SPECULATIVE_NUM_SPANS).saturating_add(T::WeightInfo::full_unbond())) ] - pub fn force_unbond( - origin: OriginFor, - #[pallet::compact] value: BalanceOf, - ) -> DispatchResultWithPostInfo { + pub fn full_unbond(origin: OriginFor) -> DispatchResultWithPostInfo { let controller = ensure_signed(origin)?; let ledger = Self::ledger(StakingAccount::Controller(controller.clone()))?; - let min_active_bond = if Nominators::::contains_key(&ledger.stash) { - MinNominatorBond::::get() - } else if Validators::::contains_key(&ledger.stash) { - MinValidatorBond::::get() - } else { - Zero::zero() - }; - - if (ledger.active - value) <= min_active_bond { - Self::chill_stash(&ledger.stash); - } + Self::chill_stash(&ledger.stash); - let maybe_withdraw_weight = Self::do_unbond(controller, value)?; + let maybe_withdraw_weight = Self::do_unbond(controller, ledger.active)?; let actual_weight = if let Some(withdraw_weight) = maybe_withdraw_weight { - Some(T::WeightInfo::force_unbond().saturating_add(withdraw_weight)) + Some(T::WeightInfo::full_unbond().saturating_add(withdraw_weight)) } else { - Some(T::WeightInfo::force_unbond()) + Some(T::WeightInfo::full_unbond()) }; Ok(actual_weight.into()) diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs index f8ec41d4c53e0..1fa707f6aacd4 100644 --- a/substrate/frame/staking/src/tests.rs +++ b/substrate/frame/staking/src/tests.rs @@ -4070,7 +4070,7 @@ fn test_multi_page_payout_stakers_by_page() { } #[test] -fn force_unbond_works() { +fn full_unbond_works() { // // * Should test // * Given an account being bonded [and chosen as a validator](not mandatory) @@ -4107,7 +4107,7 @@ fn force_unbond_works() { ); // Force Unbond all of the funds in stash which makes the call to chill first. - let res = Staking::force_unbond(RuntimeOrigin::signed(11), 1000); + let res = Staking::full_unbond(RuntimeOrigin::signed(11)); assert!(res.is_ok()); }) } diff --git a/substrate/frame/staking/src/weights.rs b/substrate/frame/staking/src/weights.rs index ae3d3acc2d2c0..fc5af412aade3 100644 --- a/substrate/frame/staking/src/weights.rs +++ b/substrate/frame/staking/src/weights.rs @@ -80,7 +80,7 @@ pub trait WeightInfo { fn chill_other() -> Weight; fn force_apply_min_commission() -> Weight; fn set_min_commission() -> Weight; - fn force_unbond() -> Weight; + fn full_unbond() -> Weight; } /// Weights for `pallet_staking` using the Substrate node and recommended hardware. @@ -804,7 +804,7 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes(1_u64)) } - fn force_unbond() -> Weight { + fn full_unbond() -> Weight { todo!() } } @@ -1552,7 +1552,7 @@ impl WeightInfo for () { /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - fn force_unbond() -> Weight { + fn full_unbond() -> Weight { // Proof Size summary in bytes: // Measured: `2122` // Estimated: `6248` From 66d9b61ea73f1481fae79527b536d8adf2777391 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Tue, 9 Apr 2024 16:25:30 +0100 Subject: [PATCH 06/41] implicit chill when unbonding --- Cargo.lock | 59 ++++++++++----------- substrate/frame/staking/src/pallet/impls.rs | 3 +- substrate/frame/staking/src/pallet/mod.rs | 21 ++++---- substrate/frame/staking/src/tests.rs | 6 --- 4 files changed, 42 insertions(+), 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9989bc3194084..0ed457ee5a29a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2623,9 +2623,9 @@ dependencies = [ [[package]] name = "clap-num" -version = "1.0.2" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488557e97528174edaa2ee268b23a809e0c598213a4bbcb4f34575a46fda147e" +checksum = "0e063d263364859dc54fb064cedb7c122740cd4733644b14b176c097f51e8ab7" dependencies = [ "num-traits", ] @@ -2844,11 +2844,10 @@ checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "colored" -version = "2.0.4" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" +checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" dependencies = [ - "is-terminal", "lazy_static", "windows-sys 0.48.0", ] @@ -3354,9 +3353,9 @@ dependencies = [ [[package]] name = "crc" -version = "3.2.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2b432c56615136f8dba245fed7ec3d5518c500a31108661067e61e72fe7e6bc" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" dependencies = [ "crc-catalog", ] @@ -6308,9 +6307,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.26" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" dependencies = [ "bytes", "fnv", @@ -6916,9 +6915,9 @@ checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" [[package]] name = "jsonrpsee" -version = "0.22.2" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f3ae45a64cfc0882934f963be9431b2a165d667f53140358181f262aca0702" +checksum = "4a95f7cc23d5fab0cdeeaf6bad8c8f5e7a3aa7f0d211957ea78232b327ab27b0" dependencies = [ "jsonrpsee-core", "jsonrpsee-http-client", @@ -6932,9 +6931,9 @@ dependencies = [ [[package]] name = "jsonrpsee-client-transport" -version = "0.22.2" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455fc882e56f58228df2aee36b88a1340eafd707c76af2fa68cf94b37d461131" +checksum = "6b1736cfa3845fd9f8f43751f2b8e0e83f7b6081e754502f7d63b6587692cc83" dependencies = [ "futures-util", "http", @@ -6953,9 +6952,9 @@ dependencies = [ [[package]] name = "jsonrpsee-core" -version = "0.22.2" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75568f4f9696e3a47426e1985b548e1a9fcb13372a5e320372acaf04aca30d1" +checksum = "82030d038658974732103e623ba2e0abec03bbbe175b39c0a2fafbada60c5868" dependencies = [ "anyhow", "async-lock 3.3.0", @@ -6979,9 +6978,9 @@ dependencies = [ [[package]] name = "jsonrpsee-http-client" -version = "0.22.2" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e7a95e346f55df84fb167b7e06470e196e7d5b9488a21d69c5d9732043ba7ba" +checksum = "36a06ef0de060005fddf772d54597bb6a8b0413da47dcffd304b0306147b9678" dependencies = [ "async-trait", "hyper", @@ -6999,22 +6998,22 @@ dependencies = [ [[package]] name = "jsonrpsee-proc-macros" -version = "0.22.2" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ca066e73dd70294aebc5c2675d8ffae43be944af027c857ce0d4c51785f014" +checksum = "69fc56131589f82e57805f7338b87023db4aafef813555708b159787e34ad6bc" dependencies = [ "heck 0.4.1", "proc-macro-crate 3.0.0", "proc-macro2", "quote", - "syn 2.0.53", + "syn 1.0.109", ] [[package]] name = "jsonrpsee-server" -version = "0.22.2" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e29c1bd1f9bba83c864977c73404e505f74f730fa0db89dd490ec174e36d7f0" +checksum = "d85be77fe5b2a94589e3164fb780017f7aff7d646b49278c0d0346af16975c8e" dependencies = [ "futures-util", "http", @@ -7036,9 +7035,9 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.22.2" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3467fd35feeee179f71ab294516bdf3a81139e7aeebdd860e46897c12e1a3368" +checksum = "9a48fdc1202eafc51c63e00406575e59493284ace8b8b61aa16f3a6db5d64f1a" dependencies = [ "anyhow", "beef", @@ -7049,9 +7048,9 @@ dependencies = [ [[package]] name = "jsonrpsee-ws-client" -version = "0.22.2" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ca71e74983f624c0cb67828e480a981586074da8ad3a2f214c6a3f884edab9" +checksum = "c5ce25d70a8e4d3cc574bbc3cad0137c326ad64b194793d5e7bbdd3fa4504181" dependencies = [ "http", "jsonrpsee-client-transport", @@ -17314,9 +17313,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.11.1" +version = "2.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "788745a868b0e751750388f4e6546eb921ef714a4317fa6954f7cde114eb2eb7" +checksum = "7c453e59a955f81fb62ee5d596b450383d699f152d350e9d23a0db2adb78e4c0" dependencies = [ "bitvec", "cfg-if", @@ -17328,9 +17327,9 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.11.1" +version = "2.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dc2f4e8bc344b9fc3d5f74f72c2e55bfc38d28dc2ebc69c194a3df424e4d9ac" +checksum = "18cf6c6447f813ef19eb450e985bcce6705f9ce7660db221b59093d15c79c4b7" dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", diff --git a/substrate/frame/staking/src/pallet/impls.rs b/substrate/frame/staking/src/pallet/impls.rs index 4e70ba6963cce..e4cd6c0c78676 100644 --- a/substrate/frame/staking/src/pallet/impls.rs +++ b/substrate/frame/staking/src/pallet/impls.rs @@ -52,8 +52,7 @@ use crate::{ BalanceOf, EraInfo, EraPayout, Exposure, ExposureOf, Forcing, IndividualExposure, LedgerIntegrityState, MaxNominationsOf, MaxWinnersOf, Nominations, NominationsQuota, PositiveImbalanceOf, RewardDestination, SessionInterface, StakingLedger, ValidatorPrefs, - MaxNominationsOf, MaxWinnersOf, Nominations, NominationsQuota, PositiveImbalanceOf, - RewardDestination, SessionInterface, StakingLedger, UnlockChunk, ValidatorPrefs, + UnlockChunk }; use super::pallet::*; diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index 2a8cec9ea66d7..9389b9794f594 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -23,11 +23,9 @@ use frame_election_provider_support::{ }; use frame_support::{ pallet_prelude::*, - traits::{ - Currency, Defensive, DefensiveSaturating, EnsureOrigin, EstimateNextNewSession, Get, + traits::{EnsureOrigin, EstimateNextNewSession, Get, InspectLockableCurrency, LockableCurrency, OnUnbalanced, UnixTime, WithdrawReasons, - Currency, Defensive, EnsureOrigin, EstimateNextNewSession, Get, LockableCurrency, - OnUnbalanced, UnixTime, + Currency, Defensive, }, weights::Weight, BoundedVec, @@ -52,10 +50,7 @@ use crate::{ slashing, weights::WeightInfo, AccountIdLookupOf, ActiveEraInfo, BalanceOf, EraPayout, EraRewardPoints, Exposure, ExposurePage, Forcing, LedgerIntegrityState, MaxNominationsOf, NegativeImbalanceOf, Nominations, NominationsQuota, PositiveImbalanceOf, RewardDestination, - SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk, ValidatorPrefs, - EraRewardPoints, Exposure, ExposurePage, Forcing, MaxNominationsOf, NegativeImbalanceOf, - Nominations, NominationsQuota, PositiveImbalanceOf, RewardDestination, SessionInterface, - StakingLedger, UnappliedSlash, ValidatorPrefs, + SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk, ValidatorPrefs }; // The speculative number of spans are used as an input of the weight annotation of @@ -1043,7 +1038,15 @@ pub mod pallet { #[pallet::compact] value: BalanceOf, ) -> DispatchResultWithPostInfo { let controller = ensure_signed(origin)?; + + let ledger = Self::ledger(StakingAccount::Controller(controller.clone()))?; + + if value == ledger.total { + Self::chill_stash(&ledger.stash); + } + let maybe_withdraw_weight = Self::do_unbond(controller, value)?; + let actual_weight = if let Some(withdraw_weight) = maybe_withdraw_weight { Some(T::WeightInfo::unbond().saturating_add(withdraw_weight)) } else { @@ -2021,7 +2024,7 @@ pub mod pallet { /// Fully Unbonds by Chilling first /// Emits `Unbonded`. - #[pallet::call_index(29)] + #[pallet::call_index(30)] #[pallet::weight( T::WeightInfo::withdraw_unbonded_kill(SPECULATIVE_NUM_SPANS).saturating_add(T::WeightInfo::full_unbond())) ] diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs index 546025e27db49..e41192e837569 100644 --- a/substrate/frame/staking/src/tests.rs +++ b/substrate/frame/staking/src/tests.rs @@ -4100,12 +4100,6 @@ fn full_unbond_works() { mock::start_active_era(2); assert_eq!(active_era(), 2); - // unbonding without chilling fails - assert_noop!( - Staking::unbond(RuntimeOrigin::signed(11), 1000), - Error::::InsufficientBond, - ); - // Force Unbond all of the funds in stash which makes the call to chill first. let res = Staking::full_unbond(RuntimeOrigin::signed(11)); assert!(res.is_ok()); From 0292c5faa8cade68fb45cc9a7e859625ab36e208 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Tue, 9 Apr 2024 16:27:51 +0100 Subject: [PATCH 07/41] fmt --- substrate/frame/staking/src/pallet/impls.rs | 4 ++-- substrate/frame/staking/src/pallet/mod.rs | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/substrate/frame/staking/src/pallet/impls.rs b/substrate/frame/staking/src/pallet/impls.rs index e4cd6c0c78676..1e341888aec4b 100644 --- a/substrate/frame/staking/src/pallet/impls.rs +++ b/substrate/frame/staking/src/pallet/impls.rs @@ -51,8 +51,8 @@ use crate::{ election_size_tracker::StaticTracker, log, slashing, weights::WeightInfo, ActiveEraInfo, BalanceOf, EraInfo, EraPayout, Exposure, ExposureOf, Forcing, IndividualExposure, LedgerIntegrityState, MaxNominationsOf, MaxWinnersOf, Nominations, NominationsQuota, - PositiveImbalanceOf, RewardDestination, SessionInterface, StakingLedger, ValidatorPrefs, - UnlockChunk + PositiveImbalanceOf, RewardDestination, SessionInterface, StakingLedger, UnlockChunk, + ValidatorPrefs, }; use super::pallet::*; diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index 9389b9794f594..7e6f769e26963 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -23,9 +23,9 @@ use frame_election_provider_support::{ }; use frame_support::{ pallet_prelude::*, - traits::{EnsureOrigin, EstimateNextNewSession, Get, - InspectLockableCurrency, LockableCurrency, OnUnbalanced, UnixTime, WithdrawReasons, - Currency, Defensive, + traits::{ + Currency, Defensive, EnsureOrigin, EstimateNextNewSession, Get, InspectLockableCurrency, + LockableCurrency, OnUnbalanced, UnixTime, WithdrawReasons, }, weights::Weight, BoundedVec, @@ -50,7 +50,7 @@ use crate::{ slashing, weights::WeightInfo, AccountIdLookupOf, ActiveEraInfo, BalanceOf, EraPayout, EraRewardPoints, Exposure, ExposurePage, Forcing, LedgerIntegrityState, MaxNominationsOf, NegativeImbalanceOf, Nominations, NominationsQuota, PositiveImbalanceOf, RewardDestination, - SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk, ValidatorPrefs + SessionInterface, StakingLedger, UnappliedSlash, UnlockChunk, ValidatorPrefs, }; // The speculative number of spans are used as an input of the weight annotation of From 4d449bf8b972ad69d3c3a9423210ae175d384b49 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Wed, 10 Apr 2024 13:56:31 +0100 Subject: [PATCH 08/41] no need for outright chill since unbond does chilling implicitly before unbonding all amount --- substrate/frame/nomination-pools/test-staking/src/lib.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/substrate/frame/nomination-pools/test-staking/src/lib.rs b/substrate/frame/nomination-pools/test-staking/src/lib.rs index d84e09e32ba35..32d32a35e271f 100644 --- a/substrate/frame/nomination-pools/test-staking/src/lib.rs +++ b/substrate/frame/nomination-pools/test-staking/src/lib.rs @@ -151,14 +151,6 @@ fn pool_lifecycle_e2e() { ] ); - // as soon as all members have left, the depositor can try to unbond, but since the - // min-nominator intention is set, they must chill first. - assert_noop!( - Pools::unbond(RuntimeOrigin::signed(10), 10, 50), - pallet_staking::Error::::InsufficientBond - ); - - assert_ok!(Pools::chill(RuntimeOrigin::signed(10), 1)); assert_ok!(Pools::unbond(RuntimeOrigin::signed(10), 10, 50)); assert_eq!( From a026b88d2964f843965ae8897ad333f8e6888f39 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Thu, 18 Apr 2024 12:31:03 +0100 Subject: [PATCH 09/41] test, benchmark and pr doc --- prdoc/pr_3811.prdoc | 9 ++-- substrate/frame/staking/src/benchmarking.rs | 7 +-- substrate/frame/staking/src/tests.rs | 55 +++++++++++++++++++++ 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/prdoc/pr_3811.prdoc b/prdoc/pr_3811.prdoc index b1918cea2946d..9ebce5e6691f3 100644 --- a/prdoc/pr_3811.prdoc +++ b/prdoc/pr_3811.prdoc @@ -1,10 +1,13 @@ -title: "[pallet_staking] Staking `full_unbond`" +title: "Chill and Full Unbond in [pallet_staking]" doc: - audience: Runtime Dev description: | - Full unbond when staking such that to fully unbond as a validator or nominator, chilled occurs first - before unbonding + Introduces a new `full_unbond` extrinsic to forcefully chill and unbond the full value + bonded + + It also modifies the `unbond` extrinsic by forcefully chilling and unbonding the full value + if the value to be unbonded is the total of what is bonded crates: - name: pallet-staking diff --git a/substrate/frame/staking/src/benchmarking.rs b/substrate/frame/staking/src/benchmarking.rs index c2d6e9f4fe2ca..42511f9a8236a 100644 --- a/substrate/frame/staking/src/benchmarking.rs +++ b/substrate/frame/staking/src/benchmarking.rs @@ -275,16 +275,17 @@ benchmarks! { let stash = scenario.origin_stash1.clone(); let controller = scenario.origin_controller1.clone(); - let amount = origin_weight - scenario.dest_weight; + //let amount = origin_weight - scenario.dest_weight; let ledger = Ledger::::get(&controller).ok_or("ledger not created before")?; let original_bonded: BalanceOf = ledger.active; whitelist_account!(controller); - }: _(RawOrigin::Signed(controller.clone()), amount) + }: _(RawOrigin::Signed(controller.clone()), original_bonded) verify { let ledger = Ledger::::get(&controller).ok_or("ledger not created after")?; let new_bonded: BalanceOf = ledger.active; - assert!(original_bonded > new_bonded); + assert!(new_bonded == BalanceOf::::try_from(0u128).map_err(|_| "balance expected to be a u128") + .unwrap()); } // Withdraw only updates the ledger diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs index e41192e837569..d7e77c17dd87f 100644 --- a/substrate/frame/staking/src/tests.rs +++ b/substrate/frame/staking/src/tests.rs @@ -4103,6 +4103,61 @@ fn full_unbond_works() { // Force Unbond all of the funds in stash which makes the call to chill first. let res = Staking::full_unbond(RuntimeOrigin::signed(11)); assert!(res.is_ok()); + + assert_eq!( + *staking_events().last().unwrap(), + Event::Unbonded { stash: 11, amount: 1000 } + ); + assert_eq!( + *staking_events().get(staking_events().len() - 2).unwrap(), + Event::Chilled { stash: 11 } + ); + }) +} + +#[test] +fn unbond_with_chill_works() { + // + // * Should test + // * Given an account being bonded [and chosen as a validator](not mandatory) + // * it can force unbond a portion of its funds from the stash account. + ExtBuilder::default().nominate(false).build_and_execute(|| { + // Set payee to stash. + assert_ok!(Staking::set_payee(RuntimeOrigin::signed(11), RewardDestination::Stash)); + + // Give account 11 some large free balance greater than total + let _ = Balances::make_free_balance_be(&11, 1000000); + + // confirm that 10 is a normal validator and gets paid at the end of the era. + mock::start_active_era(1); + + // Initial state of 11 + assert_eq!( + Staking::ledger(11.into()).unwrap(), + StakingLedgerInspect { + stash: 11, + total: 1000, + active: 1000, + unlocking: Default::default(), + legacy_claimed_rewards: bounded_vec![], + } + ); + + mock::start_active_era(2); + assert_eq!(active_era(), 2); + + // Unbond all amount by ensuring chilling + let res = Staking::unbond(RuntimeOrigin::signed(11), 1000); + assert!(res.is_ok()); + + assert_eq!( + *staking_events().last().unwrap(), + Event::Unbonded { stash: 11, amount: 1000 } + ); + assert_eq!( + *staking_events().get(staking_events().len() - 2).unwrap(), + Event::Chilled { stash: 11 } + ); }) } From 269934e35fbdaa23bf553e814cd03000ab1ce182 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Thu, 18 Apr 2024 12:31:47 +0100 Subject: [PATCH 10/41] fmt --- substrate/frame/staking/src/tests.rs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs index d7e77c17dd87f..bbf2b6c3d6219 100644 --- a/substrate/frame/staking/src/tests.rs +++ b/substrate/frame/staking/src/tests.rs @@ -4104,10 +4104,7 @@ fn full_unbond_works() { let res = Staking::full_unbond(RuntimeOrigin::signed(11)); assert!(res.is_ok()); - assert_eq!( - *staking_events().last().unwrap(), - Event::Unbonded { stash: 11, amount: 1000 } - ); + assert_eq!(*staking_events().last().unwrap(), Event::Unbonded { stash: 11, amount: 1000 }); assert_eq!( *staking_events().get(staking_events().len() - 2).unwrap(), Event::Chilled { stash: 11 } @@ -4150,10 +4147,7 @@ fn unbond_with_chill_works() { let res = Staking::unbond(RuntimeOrigin::signed(11), 1000); assert!(res.is_ok()); - assert_eq!( - *staking_events().last().unwrap(), - Event::Unbonded { stash: 11, amount: 1000 } - ); + assert_eq!(*staking_events().last().unwrap(), Event::Unbonded { stash: 11, amount: 1000 }); assert_eq!( *staking_events().get(staking_events().len() - 2).unwrap(), Event::Chilled { stash: 11 } From 507a617b51886c04c53f52f3398d9719aa4893a3 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sat, 20 Apr 2024 21:50:45 +0100 Subject: [PATCH 11/41] nit --- .../westend/src/weights/pallet_staking.rs | 33 ++++++++++++++++++- substrate/frame/staking/src/benchmarking.rs | 4 +-- substrate/frame/staking/src/pallet/mod.rs | 1 - substrate/frame/staking/src/weights.rs | 33 ++++++++++++++++++- 4 files changed, 66 insertions(+), 5 deletions(-) diff --git a/polkadot/runtime/westend/src/weights/pallet_staking.rs b/polkadot/runtime/westend/src/weights/pallet_staking.rs index 28b8b86327968..5c3cf7005948c 100644 --- a/polkadot/runtime/westend/src/weights/pallet_staking.rs +++ b/polkadot/runtime/westend/src/weights/pallet_staking.rs @@ -827,7 +827,38 @@ impl pallet_staking::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().writes(4)) } + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:1 w:1) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `Staking::MinNominatorBond` (r:1 w:0) + /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Staking::Validators` (r:1 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `Staking::CounterForNominators` (r:1 w:1) + /// Proof: `Staking::CounterForNominators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:2 w:2) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:1 w:1) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) + /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) fn full_unbond() -> Weight { - todo!() + // Proof Size summary in bytes: + // Measured: `2122` + // Estimated: `6248` + // Minimum execution time: 76_000_000 picoseconds. + Weight::from_parts(78_000_000, 0) + .saturating_add(Weight::from_parts(0, 6248)) + .saturating_add(T::DbWeight::get().reads(13)) + .saturating_add(T::DbWeight::get().writes(8)) } } diff --git a/substrate/frame/staking/src/benchmarking.rs b/substrate/frame/staking/src/benchmarking.rs index 42511f9a8236a..709571e2fdba9 100644 --- a/substrate/frame/staking/src/benchmarking.rs +++ b/substrate/frame/staking/src/benchmarking.rs @@ -275,7 +275,6 @@ benchmarks! { let stash = scenario.origin_stash1.clone(); let controller = scenario.origin_controller1.clone(); - //let amount = origin_weight - scenario.dest_weight; let ledger = Ledger::::get(&controller).ok_or("ledger not created before")?; let original_bonded: BalanceOf = ledger.active; @@ -986,7 +985,8 @@ benchmarks! { verify { let ledger = Ledger::::get(&controller).ok_or("ledger not created after")?; let new_bonded: BalanceOf = ledger.active; - assert!(original_bonded > new_bonded); + assert!(new_bonded == BalanceOf::::try_from(0u128).map_err(|_| "balance expected to be a u128") + .unwrap()); } impl_benchmark_test_suite!( diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index 7e6f769e26963..6a69fde7a55c4 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -2030,7 +2030,6 @@ pub mod pallet { ] pub fn full_unbond(origin: OriginFor) -> DispatchResultWithPostInfo { let controller = ensure_signed(origin)?; - let ledger = Self::ledger(StakingAccount::Controller(controller.clone()))?; Self::chill_stash(&ledger.stash); diff --git a/substrate/frame/staking/src/weights.rs b/substrate/frame/staking/src/weights.rs index 03c7cb596cb79..cb200d90df380 100644 --- a/substrate/frame/staking/src/weights.rs +++ b/substrate/frame/staking/src/weights.rs @@ -836,8 +836,39 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().writes(4_u64)) } + /// Storage: `Staking::Ledger` (r:1 w:1) + /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:1 w:1) + /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) + /// Storage: `Staking::MinNominatorBond` (r:1 w:0) + /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Staking::Validators` (r:1 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `Staking::CounterForNominators` (r:1 w:1) + /// Proof: `Staking::CounterForNominators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:2 w:2) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:1 w:1) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) + /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::CurrentEra` (r:1 w:0) + /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::Bonded` (r:1 w:0) + /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Balances::Locks` (r:1 w:1) + /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) + /// Storage: `Balances::Freezes` (r:1 w:0) + /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) fn full_unbond() -> Weight { - todo!() + // Proof Size summary in bytes: + // Measured: `2122` + // Estimated: `6248` + // Minimum execution time: 76_000_000 picoseconds. + Weight::from_parts(78_000_000, 0) + .saturating_add(Weight::from_parts(0, 6248)) + .saturating_add(T::DbWeight::get().reads(13)) + .saturating_add(T::DbWeight::get().writes(8)) } } From a6731a6748eb73ff646515ceae8fd2ed9b8488c4 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Wed, 1 May 2024 13:01:20 +0100 Subject: [PATCH 12/41] fix test --- .../test-staking-e2e/src/lib.rs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs index 83083c912094b..03ddef4fbd124 100644 --- a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs +++ b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs @@ -340,18 +340,8 @@ fn ledger_consistency_active_balance_below_ed() { execute_with(ext, || { assert_eq!(Staking::ledger(11.into()).unwrap().active, 1000); - // unbonding total of active stake fails because the active ledger balance would fall - // below the `MinNominatorBond`. - assert_noop!( - Staking::unbond(RuntimeOrigin::signed(11), 1000), - Error::::InsufficientBond - ); - - // however, chilling works as expected. - assert_ok!(Staking::chill(RuntimeOrigin::signed(11))); - - // now unbonding the full active balance works, since remainder of the active balance is - // not enforced to be below `MinNominatorBond` if the stash has been chilled. + // unbonding total of active stake passes because Chill occurs implicitly when unbonding + // full amount assert_ok!(Staking::unbond(RuntimeOrigin::signed(11), 1000)); // the active balance of the ledger entry is 0, while total balance is 1000 until From 62766c2073b25c31197b8d4916feb49f1844e081 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Wed, 1 May 2024 13:16:29 +0100 Subject: [PATCH 13/41] nit --- .../election-provider-multi-phase/test-staking-e2e/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs index 5d4da902121f1..69dd411951bfb 100644 --- a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs +++ b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs @@ -20,7 +20,7 @@ mod mock; pub(crate) const LOG_TARGET: &str = "tests::e2e-epm"; -use frame_support::{assert_err, assert_noop, assert_ok}; +use frame_support::{assert_err, assert_ok}; use mock::*; use sp_core::Get; use sp_runtime::Perbill; From f1b87f936276bd596d1e27ffd12808a04c122623 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sat, 25 May 2024 20:20:52 +0100 Subject: [PATCH 14/41] nit --- substrate/frame/staking/src/ledger.rs | 2 +- substrate/frame/staking/src/pallet/mod.rs | 3 +-- substrate/frame/staking/src/slashing.rs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/substrate/frame/staking/src/ledger.rs b/substrate/frame/staking/src/ledger.rs index 294918376d82c..67a86b86226cf 100644 --- a/substrate/frame/staking/src/ledger.rs +++ b/substrate/frame/staking/src/ledger.rs @@ -35,7 +35,7 @@ use frame_support::{ defensive, ensure, traits::{Defensive, LockableCurrency}, }; -use sp_staking::{StakingAccount, StakingInterface}; +use sp_staking::StakingAccount; use sp_std::prelude::*; use crate::{ diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index 5956363d5bbfe..bf1d97796c4c7 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -38,8 +38,7 @@ use sp_runtime::{ use sp_staking::{ EraIndex, Page, SessionIndex, - StakingAccount::{self, Controller, Stash}, - StakingInterface, + StakingAccount::{self, Controller, Stash} }; use sp_std::prelude::*; diff --git a/substrate/frame/staking/src/slashing.rs b/substrate/frame/staking/src/slashing.rs index 1fe608cd3358b..f831f625957d4 100644 --- a/substrate/frame/staking/src/slashing.rs +++ b/substrate/frame/staking/src/slashing.rs @@ -64,7 +64,7 @@ use sp_runtime::{ traits::{Saturating, Zero}, DispatchResult, RuntimeDebug, }; -use sp_staking::{EraIndex, StakingInterface}; +use sp_staking::EraIndex; use sp_std::vec::Vec; /// The proportion of the slashing reward to be paid out on the first slashing detection. From 6de38331fb68abce8f74f3afa849860e4be29c80 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sun, 7 Jul 2024 19:45:08 +0100 Subject: [PATCH 15/41] modifications, remove full_unbond impl --- .../westend/src/weights/pallet_staking.rs | 35 ---------- prdoc/pr_3811.prdoc | 5 +- substrate/frame/staking/src/benchmarking.rs | 27 ------- substrate/frame/staking/src/pallet/mod.rs | 22 ------ substrate/frame/staking/src/tests.rs | 43 ------------ substrate/frame/staking/src/weights.rs | 70 ------------------- 6 files changed, 1 insertion(+), 201 deletions(-) diff --git a/polkadot/runtime/westend/src/weights/pallet_staking.rs b/polkadot/runtime/westend/src/weights/pallet_staking.rs index 5c3cf7005948c..393fa0b37176a 100644 --- a/polkadot/runtime/westend/src/weights/pallet_staking.rs +++ b/polkadot/runtime/westend/src/weights/pallet_staking.rs @@ -826,39 +826,4 @@ impl pallet_staking::WeightInfo for WeightInfo { .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) } - - /// Storage: `Staking::Ledger` (r:1 w:1) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `Staking::Nominators` (r:1 w:1) - /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) - /// Storage: `Staking::MinNominatorBond` (r:1 w:0) - /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Staking::Validators` (r:1 w:0) - /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) - /// Storage: `Staking::CounterForNominators` (r:1 w:1) - /// Proof: `Staking::CounterForNominators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListNodes` (r:2 w:2) - /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListBags` (r:1 w:1) - /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) - /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) - /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::CurrentEra` (r:1 w:0) - /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::Bonded` (r:1 w:0) - /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - fn full_unbond() -> Weight { - // Proof Size summary in bytes: - // Measured: `2122` - // Estimated: `6248` - // Minimum execution time: 76_000_000 picoseconds. - Weight::from_parts(78_000_000, 0) - .saturating_add(Weight::from_parts(0, 6248)) - .saturating_add(T::DbWeight::get().reads(13)) - .saturating_add(T::DbWeight::get().writes(8)) - } } diff --git a/prdoc/pr_3811.prdoc b/prdoc/pr_3811.prdoc index 9ebce5e6691f3..0c1f2571dc491 100644 --- a/prdoc/pr_3811.prdoc +++ b/prdoc/pr_3811.prdoc @@ -3,10 +3,7 @@ title: "Chill and Full Unbond in [pallet_staking]" doc: - audience: Runtime Dev description: | - Introduces a new `full_unbond` extrinsic to forcefully chill and unbond the full value - bonded - - It also modifies the `unbond` extrinsic by forcefully chilling and unbonding the full value + Modifies the `unbond` extrinsic by forcefully chilling and unbonding the full value if the value to be unbonded is the total of what is bonded crates: diff --git a/substrate/frame/staking/src/benchmarking.rs b/substrate/frame/staking/src/benchmarking.rs index 709571e2fdba9..bb218b4c655dd 100644 --- a/substrate/frame/staking/src/benchmarking.rs +++ b/substrate/frame/staking/src/benchmarking.rs @@ -962,33 +962,6 @@ benchmarks! { assert_eq!(Staking::::inspect_bond_state(&stash), Ok(LedgerIntegrityState::Ok)); } - full_unbond { - // clean up any existing state. - clear_validators_and_nominators::(); - - // setup the worst case list scenario. - let total_issuance = T::Currency::total_issuance(); - // the weight the nominator will start at. The value used here is expected to be - // significantly higher than the first position in a list (e.g. the first bag threshold). - let origin_weight = BalanceOf::::try_from(952_994_955_240_703u128) - .map_err(|_| "balance expected to be a u128") - .unwrap(); - let scenario = ListScenario::::new(origin_weight, false)?; - - let stash = scenario.origin_stash1.clone(); - let controller = scenario.origin_controller1.clone(); - let ledger = Ledger::::get(&controller).ok_or("ledger not created before")?; - let original_bonded: BalanceOf = ledger.active; - - whitelist_account!(controller); - }: _(RawOrigin::Signed(controller.clone())) - verify { - let ledger = Ledger::::get(&controller).ok_or("ledger not created after")?; - let new_bonded: BalanceOf = ledger.active; - assert!(new_bonded == BalanceOf::::try_from(0u128).map_err(|_| "balance expected to be a u128") - .unwrap()); - } - impl_benchmark_test_suite!( Staking, crate::mock::ExtBuilder::default().has_stakers(true), diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index dd728d172ec6b..c516d834c23cc 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -2087,28 +2087,6 @@ pub mod pallet { ); Ok(()) } - - /// Fully Unbonds by Chilling first - /// Emits `Unbonded`. - #[pallet::call_index(30)] - #[pallet::weight( - T::WeightInfo::withdraw_unbonded_kill(SPECULATIVE_NUM_SPANS).saturating_add(T::WeightInfo::full_unbond())) - ] - pub fn full_unbond(origin: OriginFor) -> DispatchResultWithPostInfo { - let controller = ensure_signed(origin)?; - let ledger = Self::ledger(StakingAccount::Controller(controller.clone()))?; - - Self::chill_stash(&ledger.stash); - - let maybe_withdraw_weight = Self::do_unbond(controller, ledger.active)?; - let actual_weight = if let Some(withdraw_weight) = maybe_withdraw_weight { - Some(T::WeightInfo::full_unbond().saturating_add(withdraw_weight)) - } else { - Some(T::WeightInfo::full_unbond()) - }; - - Ok(actual_weight.into()) - } } } diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs index eaa2c35d260ef..c38ba0a139531 100644 --- a/substrate/frame/staking/src/tests.rs +++ b/substrate/frame/staking/src/tests.rs @@ -4130,49 +4130,6 @@ fn test_multi_page_payout_stakers_by_page() { }); } -#[test] -fn full_unbond_works() { - // - // * Should test - // * Given an account being bonded [and chosen as a validator](not mandatory) - // * it can force unbond a portion of its funds from the stash account. - ExtBuilder::default().nominate(false).build_and_execute(|| { - // Set payee to stash. - assert_ok!(Staking::set_payee(RuntimeOrigin::signed(11), RewardDestination::Stash)); - - // Give account 11 some large free balance greater than total - let _ = Balances::make_free_balance_be(&11, 1000000); - - // confirm that 10 is a normal validator and gets paid at the end of the era. - mock::start_active_era(1); - - // Initial state of 11 - assert_eq!( - Staking::ledger(11.into()).unwrap(), - StakingLedgerInspect { - stash: 11, - total: 1000, - active: 1000, - unlocking: Default::default(), - legacy_claimed_rewards: bounded_vec![], - } - ); - - mock::start_active_era(2); - assert_eq!(active_era(), 2); - - // Force Unbond all of the funds in stash which makes the call to chill first. - let res = Staking::full_unbond(RuntimeOrigin::signed(11)); - assert!(res.is_ok()); - - assert_eq!(*staking_events().last().unwrap(), Event::Unbonded { stash: 11, amount: 1000 }); - assert_eq!( - *staking_events().get(staking_events().len() - 2).unwrap(), - Event::Chilled { stash: 11 } - ); - }) -} - #[test] fn unbond_with_chill_works() { // diff --git a/substrate/frame/staking/src/weights.rs b/substrate/frame/staking/src/weights.rs index cb200d90df380..cd4e7f973ce33 100644 --- a/substrate/frame/staking/src/weights.rs +++ b/substrate/frame/staking/src/weights.rs @@ -83,7 +83,6 @@ pub trait WeightInfo { fn force_apply_min_commission() -> Weight; fn set_min_commission() -> Weight; fn restore_ledger() -> Weight; - fn full_unbond() -> Weight; } /// Weights for `pallet_staking` using the Substrate node and recommended hardware. @@ -835,41 +834,6 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } - - /// Storage: `Staking::Ledger` (r:1 w:1) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `Staking::Nominators` (r:1 w:1) - /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) - /// Storage: `Staking::MinNominatorBond` (r:1 w:0) - /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Staking::Validators` (r:1 w:0) - /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) - /// Storage: `Staking::CounterForNominators` (r:1 w:1) - /// Proof: `Staking::CounterForNominators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListNodes` (r:2 w:2) - /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListBags` (r:1 w:1) - /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) - /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) - /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::CurrentEra` (r:1 w:0) - /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::Bonded` (r:1 w:0) - /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - fn full_unbond() -> Weight { - // Proof Size summary in bytes: - // Measured: `2122` - // Estimated: `6248` - // Minimum execution time: 76_000_000 picoseconds. - Weight::from_parts(78_000_000, 0) - .saturating_add(Weight::from_parts(0, 6248)) - .saturating_add(T::DbWeight::get().reads(13)) - .saturating_add(T::DbWeight::get().writes(8)) - } } // For backwards compatibility and tests. @@ -1620,38 +1584,4 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } - /// Storage: `Staking::Ledger` (r:1 w:1) - /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) - /// Storage: `Staking::Nominators` (r:1 w:1) - /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) - /// Storage: `Staking::MinNominatorBond` (r:1 w:0) - /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) - /// Storage: `Staking::Validators` (r:1 w:0) - /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) - /// Storage: `Staking::CounterForNominators` (r:1 w:1) - /// Proof: `Staking::CounterForNominators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListNodes` (r:2 w:2) - /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListBags` (r:1 w:1) - /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) - /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) - /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::CurrentEra` (r:1 w:0) - /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) - /// Storage: `Staking::Bonded` (r:1 w:0) - /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) - /// Storage: `Balances::Locks` (r:1 w:1) - /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) - /// Storage: `Balances::Freezes` (r:1 w:0) - /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - fn full_unbond() -> Weight { - // Proof Size summary in bytes: - // Measured: `2122` - // Estimated: `6248` - // Minimum execution time: 76_000_000 picoseconds. - Weight::from_parts(78_000_000, 0) - .saturating_add(Weight::from_parts(0, 6248)) - .saturating_add(RocksDbWeight::get().reads(13)) - .saturating_add(RocksDbWeight::get().writes(8)) - } } From 88f5c35618777c67a12a5d11e2e1549a1ae6f042 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Wed, 10 Jul 2024 10:45:27 +0100 Subject: [PATCH 16/41] fix test --- .../frame/nomination-pools/test-delegate-stake/src/lib.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs b/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs index 51f6470f90d02..1eab5a06e1a84 100644 --- a/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs +++ b/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs @@ -158,14 +158,6 @@ fn pool_lifecycle_e2e() { ] ); - // as soon as all members have left, the depositor can try to unbond, but since the - // min-nominator intention is set, they must chill first. - assert_noop!( - Pools::unbond(RuntimeOrigin::signed(10), 10, 50), - pallet_staking::Error::::InsufficientBond - ); - - assert_ok!(Pools::chill(RuntimeOrigin::signed(10), 1)); assert_ok!(Pools::unbond(RuntimeOrigin::signed(10), 10, 50)); assert_eq!( From 7d28f7251af0dd51a1ed77fb87a9f16f308df11b Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Thu, 11 Jul 2024 10:46:19 +0100 Subject: [PATCH 17/41] fix test --- .../frame/nomination-pools/test-transfer-stake/src/lib.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/substrate/frame/nomination-pools/test-transfer-stake/src/lib.rs b/substrate/frame/nomination-pools/test-transfer-stake/src/lib.rs index c0c526ea33fc1..8fa1b7905a918 100644 --- a/substrate/frame/nomination-pools/test-transfer-stake/src/lib.rs +++ b/substrate/frame/nomination-pools/test-transfer-stake/src/lib.rs @@ -226,13 +226,6 @@ fn destroy_pool_with_erroneous_consumer() { // move to era 1 CurrentEra::::set(Some(1)); - // depositor need to chill before unbonding - assert_noop!( - Pools::unbond(RuntimeOrigin::signed(10), 10, 50), - pallet_staking::Error::::InsufficientBond - ); - - assert_ok!(Pools::chill(RuntimeOrigin::signed(10), 1)); assert_ok!(Pools::unbond(RuntimeOrigin::signed(10), 10, 50)); assert_eq!( From 52ad45f32646f0bc342759de137e0f897a11b455 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sun, 11 Aug 2024 21:59:53 +0100 Subject: [PATCH 18/41] corrections based on review --- substrate/frame/staking/src/benchmarking.rs | 3 +-- substrate/frame/staking/src/ledger.rs | 3 +-- substrate/frame/staking/src/pallet/mod.rs | 2 +- substrate/frame/staking/src/slashing.rs | 3 +-- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/substrate/frame/staking/src/benchmarking.rs b/substrate/frame/staking/src/benchmarking.rs index 9009bfd8e6887..e9557de72b472 100644 --- a/substrate/frame/staking/src/benchmarking.rs +++ b/substrate/frame/staking/src/benchmarking.rs @@ -282,8 +282,7 @@ benchmarks! { verify { let ledger = Ledger::::get(&controller).ok_or("ledger not created after")?; let new_bonded: BalanceOf = ledger.active; - assert!(new_bonded == BalanceOf::::try_from(0u128).map_err(|_| "balance expected to be a u128") - .unwrap()); + assert!(new_bonded == Zero::zero()); } // Withdraw only updates the ledger diff --git a/substrate/frame/staking/src/ledger.rs b/substrate/frame/staking/src/ledger.rs index 294918376d82c..6965149e44b85 100644 --- a/substrate/frame/staking/src/ledger.rs +++ b/substrate/frame/staking/src/ledger.rs @@ -35,8 +35,7 @@ use frame_support::{ defensive, ensure, traits::{Defensive, LockableCurrency}, }; -use sp_staking::{StakingAccount, StakingInterface}; -use sp_std::prelude::*; +use sp_staking::StakingAccount; use crate::{ BalanceOf, Bonded, Config, Error, Ledger, Pallet, Payee, RewardDestination, StakingLedger, diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index 8a5e4e30d4d2d..6e808386f4e17 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -1095,7 +1095,7 @@ pub mod pallet { let ledger = Self::ledger(StakingAccount::Controller(controller.clone()))?; - if value == ledger.total { + if value >= ledger.total { Self::chill_stash(&ledger.stash); } diff --git a/substrate/frame/staking/src/slashing.rs b/substrate/frame/staking/src/slashing.rs index d1e21e87f9e9c..bab0310f8bf4c 100644 --- a/substrate/frame/staking/src/slashing.rs +++ b/substrate/frame/staking/src/slashing.rs @@ -65,8 +65,7 @@ use sp_runtime::{ traits::{Saturating, Zero}, DispatchResult, RuntimeDebug, }; -use sp_staking::{EraIndex, StakingInterface}; -use sp_std::vec::Vec; +use sp_staking::EraIndex; /// The proportion of the slashing reward to be paid out on the first slashing detection. /// This is f_1 in the paper. From bf9680a34eba7aad9893c68dba00dcfaa6123dfd Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sun, 11 Aug 2024 22:27:08 +0100 Subject: [PATCH 19/41] fmt --- substrate/frame/staking/src/pallet/mod.rs | 2 +- substrate/frame/staking/src/tests.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index 6e808386f4e17..0ede46947b23f 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -39,7 +39,7 @@ use sp_runtime::{ use sp_staking::{ EraIndex, Page, SessionIndex, - StakingAccount::{self, Controller, Stash} + StakingAccount::{self, Controller, Stash}, }; mod impls; diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs index a6147f8eeaf17..91ac9dfb5a41f 100644 --- a/substrate/frame/staking/src/tests.rs +++ b/substrate/frame/staking/src/tests.rs @@ -8038,7 +8038,7 @@ mod ledger_recovery { assert_eq!(Balances::balance_locked(crate::STAKING_ID, &333), lock_333_before); // OK assert_eq!(Bonded::::get(&333), Some(444)); // OK assert!(Payee::::get(&333).is_some()); // OK - // however, ledger associated with its controller was killed. + // however, ledger associated with its controller was killed. assert!(Ledger::::get(&444).is_none()); // NOK // side effects on 444 - ledger, bonded, payee, lock should be completely removed. From 14212e85b878a3c8b82e683e487df35bab8dca96 Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Tue, 13 Aug 2024 13:14:23 +0000 Subject: [PATCH 20/41] ".git/.scripts/commands/bench/bench.sh" --subcommand=pallet --runtime=westend --target_dir=polkadot --pallet=pallet_staking --- .../westend/src/weights/pallet_staking.rs | 326 ++++++++++-------- 1 file changed, 176 insertions(+), 150 deletions(-) diff --git a/polkadot/runtime/westend/src/weights/pallet_staking.rs b/polkadot/runtime/westend/src/weights/pallet_staking.rs index 393fa0b37176a..1772ae7e52210 100644 --- a/polkadot/runtime/westend/src/weights/pallet_staking.rs +++ b/polkadot/runtime/westend/src/weights/pallet_staking.rs @@ -17,9 +17,9 @@ //! Autogenerated weights for `pallet_staking` //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 -//! DATE: 2024-03-27, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2024-08-13, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `runner-h2rr8wx7-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! HOSTNAME: `runner-696hpswk-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` //! WASM-EXECUTION: `Compiled`, CHAIN: `Some("westend-dev")`, DB CACHE: 1024 // Executed Command: @@ -52,6 +52,8 @@ impl pallet_staking::WeightInfo for WeightInfo { /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:1) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) @@ -60,18 +62,20 @@ impl pallet_staking::WeightInfo for WeightInfo { /// Proof: `Staking::Payee` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn bond() -> Weight { // Proof Size summary in bytes: - // Measured: `1009` + // Measured: `1042` // Estimated: `4764` - // Minimum execution time: 40_585_000 picoseconds. - Weight::from_parts(41_800_000, 0) + // Minimum execution time: 53_872_000 picoseconds. + Weight::from_parts(54_837_000, 0) .saturating_add(Weight::from_parts(0, 4764)) - .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) } /// Storage: `Staking::Bonded` (r:1 w:0) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:1) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) @@ -82,41 +86,47 @@ impl pallet_staking::WeightInfo for WeightInfo { /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) fn bond_extra() -> Weight { // Proof Size summary in bytes: - // Measured: `1921` + // Measured: `1954` // Estimated: `8877` - // Minimum execution time: 81_809_000 picoseconds. - Weight::from_parts(84_387_000, 0) + // Minimum execution time: 106_553_000 picoseconds. + Weight::from_parts(108_740_000, 0) .saturating_add(Weight::from_parts(0, 8877)) - .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(7)) } /// Storage: `Staking::Ledger` (r:1 w:1) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) /// Storage: `Staking::Bonded` (r:1 w:0) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) - /// Storage: `Staking::Nominators` (r:1 w:0) + /// Storage: `Staking::Validators` (r:1 w:0) + /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: `Staking::Nominators` (r:1 w:1) /// Proof: `Staking::Nominators` (`max_values`: None, `max_size`: Some(558), added: 3033, mode: `MaxEncodedLen`) - /// Storage: `Staking::MinNominatorBond` (r:1 w:0) - /// Proof: `Staking::MinNominatorBond` (`max_values`: Some(1), `max_size`: Some(16), added: 511, mode: `MaxEncodedLen`) + /// Storage: `Staking::CounterForNominators` (r:1 w:1) + /// Proof: `Staking::CounterForNominators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListNodes` (r:2 w:2) + /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) + /// Storage: `VoterList::ListBags` (r:1 w:1) + /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) + /// Storage: `VoterList::CounterForListNodes` (r:1 w:1) + /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Staking::CurrentEra` (r:1 w:0) /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListNodes` (r:3 w:3) - /// Proof: `VoterList::ListNodes` (`max_values`: None, `max_size`: Some(154), added: 2629, mode: `MaxEncodedLen`) - /// Storage: `VoterList::ListBags` (r:2 w:2) - /// Proof: `VoterList::ListBags` (`max_values`: None, `max_size`: Some(82), added: 2557, mode: `MaxEncodedLen`) fn unbond() -> Weight { // Proof Size summary in bytes: - // Measured: `2128` - // Estimated: `8877` - // Minimum execution time: 89_419_000 picoseconds. - Weight::from_parts(91_237_000, 0) - .saturating_add(Weight::from_parts(0, 8877)) - .saturating_add(T::DbWeight::get().reads(12)) - .saturating_add(T::DbWeight::get().writes(7)) + // Measured: `2054` + // Estimated: `6248` + // Minimum execution time: 113_047_000 picoseconds. + Weight::from_parts(115_589_000, 0) + .saturating_add(Weight::from_parts(0, 6248)) + .saturating_add(T::DbWeight::get().reads(13)) + .saturating_add(T::DbWeight::get().writes(8)) } /// Storage: `Staking::Ledger` (r:1 w:1) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) @@ -124,23 +134,27 @@ impl pallet_staking::WeightInfo for WeightInfo { /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::CurrentEra` (r:1 w:0) /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) /// Storage: `NominationPools::ReversePoolIdLookup` (r:1 w:0) /// Proof: `NominationPools::ReversePoolIdLookup` (`max_values`: None, `max_size`: Some(44), added: 2519, mode: `MaxEncodedLen`) + /// Storage: `DelegatedStaking::Agents` (r:1 w:0) + /// Proof: `DelegatedStaking::Agents` (`max_values`: None, `max_size`: Some(120), added: 2595, mode: `MaxEncodedLen`) /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_update(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1223` + // Measured: `1260` // Estimated: `4764` - // Minimum execution time: 45_152_000 picoseconds. - Weight::from_parts(46_460_819, 0) + // Minimum execution time: 63_527_000 picoseconds. + Weight::from_parts(66_163_803, 0) .saturating_add(Weight::from_parts(0, 4764)) - // Standard Error: 972 - .saturating_add(Weight::from_parts(55_473, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(6)) + // Standard Error: 1_725 + .saturating_add(Weight::from_parts(63_491, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(8)) .saturating_add(T::DbWeight::get().writes(2)) } /// Storage: `Staking::Ledger` (r:1 w:1) @@ -151,6 +165,8 @@ impl pallet_staking::WeightInfo for WeightInfo { /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Staking::SlashingSpans` (r:1 w:1) /// Proof: `Staking::SlashingSpans` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Staking::VirtualStakers` (r:1 w:1) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) @@ -174,15 +190,15 @@ impl pallet_staking::WeightInfo for WeightInfo { /// The range of component `s` is `[0, 100]`. fn withdraw_unbonded_kill(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2127 + s * (4 ±0)` + // Measured: `2160 + s * (4 ±0)` // Estimated: `6248 + s * (4 ±0)` - // Minimum execution time: 82_762_000 picoseconds. - Weight::from_parts(91_035_077, 0) + // Minimum execution time: 109_844_000 picoseconds. + Weight::from_parts(117_215_337, 0) .saturating_add(Weight::from_parts(0, 6248)) - // Standard Error: 3_771 - .saturating_add(Weight::from_parts(1_217_871, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(13)) - .saturating_add(T::DbWeight::get().writes(11)) + // Standard Error: 3_932 + .saturating_add(Weight::from_parts(1_339_593, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(14)) + .saturating_add(T::DbWeight::get().writes(12)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) .saturating_add(Weight::from_parts(0, 4).saturating_mul(s.into())) } @@ -210,10 +226,10 @@ impl pallet_staking::WeightInfo for WeightInfo { /// Proof: `Staking::CounterForValidators` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn validate() -> Weight { // Proof Size summary in bytes: - // Measured: `1301` + // Measured: `1334` // Estimated: `4556` - // Minimum execution time: 50_555_000 picoseconds. - Weight::from_parts(52_052_000, 0) + // Minimum execution time: 64_759_000 picoseconds. + Weight::from_parts(67_816_000, 0) .saturating_add(Weight::from_parts(0, 4556)) .saturating_add(T::DbWeight::get().reads(11)) .saturating_add(T::DbWeight::get().writes(5)) @@ -227,13 +243,13 @@ impl pallet_staking::WeightInfo for WeightInfo { /// The range of component `k` is `[1, 128]`. fn kick(k: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1778 + k * (572 ±0)` + // Measured: `1811 + k * (572 ±0)` // Estimated: `4556 + k * (3033 ±0)` - // Minimum execution time: 35_037_000 picoseconds. - Weight::from_parts(35_081_878, 0) + // Minimum execution time: 43_706_000 picoseconds. + Weight::from_parts(46_409_062, 0) .saturating_add(Weight::from_parts(0, 4556)) - // Standard Error: 5_473 - .saturating_add(Weight::from_parts(6_667_924, 0).saturating_mul(k.into())) + // Standard Error: 7_440 + .saturating_add(Weight::from_parts(7_597_643, 0).saturating_mul(k.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(k.into()))) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(k.into()))) @@ -264,13 +280,13 @@ impl pallet_staking::WeightInfo for WeightInfo { /// The range of component `n` is `[1, 16]`. fn nominate(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1797 + n * (102 ±0)` + // Measured: `1830 + n * (102 ±0)` // Estimated: `6248 + n * (2520 ±0)` - // Minimum execution time: 62_098_000 picoseconds. - Weight::from_parts(60_154_061, 0) + // Minimum execution time: 81_530_000 picoseconds. + Weight::from_parts(80_008_921, 0) .saturating_add(Weight::from_parts(0, 6248)) - // Standard Error: 19_257 - .saturating_add(Weight::from_parts(3_839_855, 0).saturating_mul(n.into())) + // Standard Error: 20_758 + .saturating_add(Weight::from_parts(4_879_581, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(12)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(6)) @@ -294,10 +310,10 @@ impl pallet_staking::WeightInfo for WeightInfo { /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn chill() -> Weight { // Proof Size summary in bytes: - // Measured: `1747` + // Measured: `1780` // Estimated: `6248` - // Minimum execution time: 54_993_000 picoseconds. - Weight::from_parts(56_698_000, 0) + // Minimum execution time: 71_166_000 picoseconds. + Weight::from_parts(73_018_000, 0) .saturating_add(Weight::from_parts(0, 6248)) .saturating_add(T::DbWeight::get().reads(9)) .saturating_add(T::DbWeight::get().writes(6)) @@ -310,10 +326,10 @@ impl pallet_staking::WeightInfo for WeightInfo { /// Proof: `Staking::Payee` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn set_payee() -> Weight { // Proof Size summary in bytes: - // Measured: `865` + // Measured: `898` // Estimated: `4556` - // Minimum execution time: 18_100_000 picoseconds. - Weight::from_parts(18_547_000, 0) + // Minimum execution time: 24_282_000 picoseconds. + Weight::from_parts(25_107_000, 0) .saturating_add(Weight::from_parts(0, 4556)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -326,10 +342,10 @@ impl pallet_staking::WeightInfo for WeightInfo { /// Proof: `Staking::Payee` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) fn update_payee() -> Weight { // Proof Size summary in bytes: - // Measured: `932` + // Measured: `965` // Estimated: `4556` - // Minimum execution time: 23_428_000 picoseconds. - Weight::from_parts(24_080_000, 0) + // Minimum execution time: 31_756_000 picoseconds. + Weight::from_parts(32_513_000, 0) .saturating_add(Weight::from_parts(0, 4556)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(1)) @@ -340,10 +356,10 @@ impl pallet_staking::WeightInfo for WeightInfo { /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) fn set_controller() -> Weight { // Proof Size summary in bytes: - // Measured: `865` + // Measured: `898` // Estimated: `8122` - // Minimum execution time: 21_159_000 picoseconds. - Weight::from_parts(21_706_000, 0) + // Minimum execution time: 27_997_000 picoseconds. + Weight::from_parts(28_388_000, 0) .saturating_add(Weight::from_parts(0, 8122)) .saturating_add(T::DbWeight::get().reads(3)) .saturating_add(T::DbWeight::get().writes(3)) @@ -354,8 +370,8 @@ impl pallet_staking::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_910_000 picoseconds. - Weight::from_parts(2_003_000, 0) + // Minimum execution time: 2_405_000 picoseconds. + Weight::from_parts(2_518_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -365,8 +381,8 @@ impl pallet_staking::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_076_000 picoseconds. - Weight::from_parts(7_349_000, 0) + // Minimum execution time: 7_983_000 picoseconds. + Weight::from_parts(8_359_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -376,8 +392,8 @@ impl pallet_staking::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_067_000 picoseconds. - Weight::from_parts(7_389_000, 0) + // Minimum execution time: 8_104_000 picoseconds. + Weight::from_parts(8_446_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -387,8 +403,8 @@ impl pallet_staking::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 7_148_000 picoseconds. - Weight::from_parts(7_446_000, 0) + // Minimum execution time: 7_992_000 picoseconds. + Weight::from_parts(8_402_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -399,11 +415,11 @@ impl pallet_staking::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_025_000 picoseconds. - Weight::from_parts(2_229_953, 0) + // Minimum execution time: 2_680_000 picoseconds. + Weight::from_parts(2_911_441, 0) .saturating_add(Weight::from_parts(0, 0)) - // Standard Error: 67 - .saturating_add(Weight::from_parts(11_785, 0).saturating_mul(v.into())) + // Standard Error: 80 + .saturating_add(Weight::from_parts(12_281, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().writes(1)) } /// Storage: `Staking::Ledger` (r:1502 w:1502) @@ -415,13 +431,13 @@ impl pallet_staking::WeightInfo for WeightInfo { /// The range of component `i` is `[0, 751]`. fn deprecate_controller_batch(i: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `680 + i * (227 ±0)` + // Measured: `713 + i * (227 ±0)` // Estimated: `990 + i * (7132 ±0)` - // Minimum execution time: 4_321_000 picoseconds. - Weight::from_parts(4_407_000, 0) + // Minimum execution time: 5_246_000 picoseconds. + Weight::from_parts(5_419_000, 0) .saturating_add(Weight::from_parts(0, 990)) - // Standard Error: 37_239 - .saturating_add(Weight::from_parts(21_300_598, 0).saturating_mul(i.into())) + // Standard Error: 38_609 + .saturating_add(Weight::from_parts(25_536_342, 0).saturating_mul(i.into())) .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(i.into()))) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(i.into()))) .saturating_add(Weight::from_parts(0, 7132).saturating_mul(i.into())) @@ -432,6 +448,8 @@ impl pallet_staking::WeightInfo for WeightInfo { /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:1) /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:1) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) @@ -457,15 +475,15 @@ impl pallet_staking::WeightInfo for WeightInfo { /// The range of component `s` is `[0, 100]`. fn force_unstake(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2127 + s * (4 ±0)` + // Measured: `2160 + s * (4 ±0)` // Estimated: `6248 + s * (4 ±0)` - // Minimum execution time: 78_908_000 picoseconds. - Weight::from_parts(84_886_373, 0) + // Minimum execution time: 103_154_000 picoseconds. + Weight::from_parts(109_675_241, 0) .saturating_add(Weight::from_parts(0, 6248)) - // Standard Error: 3_376 - .saturating_add(Weight::from_parts(1_217_850, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(13)) - .saturating_add(T::DbWeight::get().writes(12)) + // Standard Error: 3_119 + .saturating_add(Weight::from_parts(1_294_761, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(14)) + .saturating_add(T::DbWeight::get().writes(13)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) .saturating_add(Weight::from_parts(0, 4).saturating_mul(s.into())) } @@ -474,13 +492,13 @@ impl pallet_staking::WeightInfo for WeightInfo { /// The range of component `s` is `[1, 1000]`. fn cancel_deferred_slash(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `66639` - // Estimated: `70104` - // Minimum execution time: 136_389_000 picoseconds. - Weight::from_parts(1_207_241_524, 0) - .saturating_add(Weight::from_parts(0, 70104)) - // Standard Error: 77_138 - .saturating_add(Weight::from_parts(6_443_948, 0).saturating_mul(s.into())) + // Measured: `66672` + // Estimated: `70137` + // Minimum execution time: 139_478_000 picoseconds. + Weight::from_parts(1_204_265_791, 0) + .saturating_add(Weight::from_parts(0, 70137)) + // Standard Error: 76_582 + .saturating_add(Weight::from_parts(6_444_670, 0).saturating_mul(s.into())) .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } @@ -498,6 +516,8 @@ impl pallet_staking::WeightInfo for WeightInfo { /// Proof: `Staking::CurrentEra` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) /// Storage: `Staking::ErasValidatorReward` (r:1 w:0) /// Proof: `Staking::ErasValidatorReward` (`max_values`: None, `max_size`: Some(28), added: 2503, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:65 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:65 w:65) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:65 w:0) @@ -515,15 +535,15 @@ impl pallet_staking::WeightInfo for WeightInfo { /// The range of component `n` is `[0, 64]`. fn payout_stakers_alive_staked(n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `8249 + n * (396 ±0)` - // Estimated: `10779 + n * (3774 ±0)` - // Minimum execution time: 130_222_000 picoseconds. - Weight::from_parts(167_236_150, 0) - .saturating_add(Weight::from_parts(0, 10779)) - // Standard Error: 34_051 - .saturating_add(Weight::from_parts(39_899_917, 0).saturating_mul(n.into())) - .saturating_add(T::DbWeight::get().reads(14)) - .saturating_add(T::DbWeight::get().reads((6_u64).saturating_mul(n.into()))) + // Measured: `8282 + n * (396 ±0)` + // Estimated: `10812 + n * (3774 ±0)` + // Minimum execution time: 168_522_000 picoseconds. + Weight::from_parts(219_020_888, 0) + .saturating_add(Weight::from_parts(0, 10812)) + // Standard Error: 48_731 + .saturating_add(Weight::from_parts(51_731_369, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(15)) + .saturating_add(T::DbWeight::get().reads((7_u64).saturating_mul(n.into()))) .saturating_add(T::DbWeight::get().writes(4)) .saturating_add(T::DbWeight::get().writes((3_u64).saturating_mul(n.into()))) .saturating_add(Weight::from_parts(0, 3774).saturating_mul(n.into())) @@ -532,6 +552,8 @@ impl pallet_staking::WeightInfo for WeightInfo { /// Proof: `Staking::Ledger` (`max_values`: None, `max_size`: Some(1091), added: 3566, mode: `MaxEncodedLen`) /// Storage: `Staking::Bonded` (r:1 w:0) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `Balances::Freezes` (r:1 w:0) @@ -543,16 +565,18 @@ impl pallet_staking::WeightInfo for WeightInfo { /// The range of component `l` is `[1, 32]`. fn rebond(l: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `1922 + l * (5 ±0)` + // Measured: `1955 + l * (5 ±0)` // Estimated: `8877` - // Minimum execution time: 79_136_000 picoseconds. - Weight::from_parts(82_129_497, 0) + // Minimum execution time: 102_683_000 picoseconds. + Weight::from_parts(105_464_619, 0) .saturating_add(Weight::from_parts(0, 8877)) - // Standard Error: 3_867 - .saturating_add(Weight::from_parts(75_156, 0).saturating_mul(l.into())) - .saturating_add(T::DbWeight::get().reads(9)) + // Standard Error: 4_547 + .saturating_add(Weight::from_parts(74_062, 0).saturating_mul(l.into())) + .saturating_add(T::DbWeight::get().reads(10)) .saturating_add(T::DbWeight::get().writes(7)) } + /// Storage: `Staking::VirtualStakers` (r:1 w:1) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Staking::Bonded` (r:1 w:1) /// Proof: `Staking::Bonded` (`max_values`: None, `max_size`: Some(72), added: 2547, mode: `MaxEncodedLen`) /// Storage: `Staking::Ledger` (r:1 w:1) @@ -582,15 +606,15 @@ impl pallet_staking::WeightInfo for WeightInfo { /// The range of component `s` is `[1, 100]`. fn reap_stash(s: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `2127 + s * (4 ±0)` + // Measured: `2160 + s * (4 ±0)` // Estimated: `6248 + s * (4 ±0)` - // Minimum execution time: 89_375_000 picoseconds. - Weight::from_parts(91_224_907, 0) + // Minimum execution time: 114_062_000 picoseconds. + Weight::from_parts(116_816_439, 0) .saturating_add(Weight::from_parts(0, 6248)) - // Standard Error: 3_424 - .saturating_add(Weight::from_parts(1_219_542, 0).saturating_mul(s.into())) - .saturating_add(T::DbWeight::get().reads(12)) - .saturating_add(T::DbWeight::get().writes(11)) + // Standard Error: 3_918 + .saturating_add(Weight::from_parts(1_320_712, 0).saturating_mul(s.into())) + .saturating_add(T::DbWeight::get().reads(13)) + .saturating_add(T::DbWeight::get().writes(12)) .saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(s.into()))) .saturating_add(Weight::from_parts(0, 4).saturating_mul(s.into())) } @@ -633,14 +657,14 @@ impl pallet_staking::WeightInfo for WeightInfo { fn new_era(v: u32, n: u32, ) -> Weight { // Proof Size summary in bytes: // Measured: `0 + n * (716 ±0) + v * (3594 ±0)` - // Estimated: `456136 + n * (3566 ±4) + v * (3566 ±0)` - // Minimum execution time: 520_905_000 picoseconds. - Weight::from_parts(523_771_000, 0) + // Estimated: `456136 + n * (3566 ±0) + v * (3566 ±0)` + // Minimum execution time: 663_657_000 picoseconds. + Weight::from_parts(666_131_000, 0) .saturating_add(Weight::from_parts(0, 456136)) - // Standard Error: 2_142_714 - .saturating_add(Weight::from_parts(68_631_588, 0).saturating_mul(v.into())) - // Standard Error: 213_509 - .saturating_add(Weight::from_parts(19_343_025, 0).saturating_mul(n.into())) + // Standard Error: 2_210_227 + .saturating_add(Weight::from_parts(70_783_765, 0).saturating_mul(v.into())) + // Standard Error: 220_237 + .saturating_add(Weight::from_parts(23_255_367, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(184)) .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(n.into()))) @@ -669,15 +693,15 @@ impl pallet_staking::WeightInfo for WeightInfo { /// The range of component `n` is `[500, 1000]`. fn get_npos_voters(v: u32, n: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `3108 + n * (907 ±0) + v * (391 ±0)` + // Measured: `3141 + n * (907 ±0) + v * (391 ±0)` // Estimated: `456136 + n * (3566 ±0) + v * (3566 ±0)` - // Minimum execution time: 36_848_619_000 picoseconds. - Weight::from_parts(37_362_442_000, 0) + // Minimum execution time: 43_956_452_000 picoseconds. + Weight::from_parts(44_256_010_000, 0) .saturating_add(Weight::from_parts(0, 456136)) - // Standard Error: 415_031 - .saturating_add(Weight::from_parts(5_204_987, 0).saturating_mul(v.into())) - // Standard Error: 415_031 - .saturating_add(Weight::from_parts(4_132_636, 0).saturating_mul(n.into())) + // Standard Error: 487_315 + .saturating_add(Weight::from_parts(6_350_105, 0).saturating_mul(v.into())) + // Standard Error: 487_315 + .saturating_add(Weight::from_parts(5_225_313, 0).saturating_mul(n.into())) .saturating_add(T::DbWeight::get().reads(179)) .saturating_add(T::DbWeight::get().reads((5_u64).saturating_mul(v.into()))) .saturating_add(T::DbWeight::get().reads((4_u64).saturating_mul(n.into()))) @@ -692,13 +716,13 @@ impl pallet_staking::WeightInfo for WeightInfo { /// The range of component `v` is `[500, 1000]`. fn get_npos_targets(v: u32, ) -> Weight { // Proof Size summary in bytes: - // Measured: `946 + v * (50 ±0)` + // Measured: `979 + v * (50 ±0)` // Estimated: `3510 + v * (2520 ±0)` - // Minimum execution time: 2_512_817_000 picoseconds. - Weight::from_parts(119_401_374, 0) + // Minimum execution time: 2_892_450_000 picoseconds. + Weight::from_parts(11_255_802, 0) .saturating_add(Weight::from_parts(0, 3510)) - // Standard Error: 8_463 - .saturating_add(Weight::from_parts(4_860_364, 0).saturating_mul(v.into())) + // Standard Error: 10_077 + .saturating_add(Weight::from_parts(5_832_436, 0).saturating_mul(v.into())) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(v.into()))) .saturating_add(Weight::from_parts(0, 2520).saturating_mul(v.into())) @@ -721,8 +745,8 @@ impl pallet_staking::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_686_000 picoseconds. - Weight::from_parts(3_881_000, 0) + // Minimum execution time: 4_462_000 picoseconds. + Weight::from_parts(4_705_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(7)) } @@ -744,8 +768,8 @@ impl pallet_staking::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 3_143_000 picoseconds. - Weight::from_parts(3_424_000, 0) + // Minimum execution time: 3_953_000 picoseconds. + Weight::from_parts(4_235_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(7)) } @@ -773,10 +797,10 @@ impl pallet_staking::WeightInfo for WeightInfo { /// Proof: `VoterList::CounterForListNodes` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) fn chill_other() -> Weight { // Proof Size summary in bytes: - // Measured: `1870` + // Measured: `1903` // Estimated: `6248` - // Minimum execution time: 66_946_000 picoseconds. - Weight::from_parts(69_382_000, 0) + // Minimum execution time: 86_556_000 picoseconds. + Weight::from_parts(89_010_000, 0) .saturating_add(Weight::from_parts(0, 6248)) .saturating_add(T::DbWeight::get().reads(12)) .saturating_add(T::DbWeight::get().writes(6)) @@ -787,10 +811,10 @@ impl pallet_staking::WeightInfo for WeightInfo { /// Proof: `Staking::Validators` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) fn force_apply_min_commission() -> Weight { // Proof Size summary in bytes: - // Measured: `658` + // Measured: `691` // Estimated: `3510` - // Minimum execution time: 11_278_000 picoseconds. - Weight::from_parts(11_603_000, 0) + // Minimum execution time: 15_787_000 picoseconds. + Weight::from_parts(16_424_000, 0) .saturating_add(Weight::from_parts(0, 3510)) .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) @@ -801,11 +825,13 @@ impl pallet_staking::WeightInfo for WeightInfo { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 1_963_000 picoseconds. - Weight::from_parts(2_077_000, 0) + // Minimum execution time: 2_544_000 picoseconds. + Weight::from_parts(2_612_000, 0) .saturating_add(Weight::from_parts(0, 0)) .saturating_add(T::DbWeight::get().writes(1)) } + /// Storage: `Staking::VirtualStakers` (r:1 w:0) + /// Proof: `Staking::VirtualStakers` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`) /// Storage: `Balances::Locks` (r:1 w:1) /// Proof: `Balances::Locks` (`max_values`: None, `max_size`: Some(1299), added: 3774, mode: `MaxEncodedLen`) /// Storage: `System::Account` (r:1 w:1) @@ -818,12 +844,12 @@ impl pallet_staking::WeightInfo for WeightInfo { /// Proof: `Balances::Freezes` (`max_values`: None, `max_size`: Some(67), added: 2542, mode: `MaxEncodedLen`) fn restore_ledger() -> Weight { // Proof Size summary in bytes: - // Measured: `1014` + // Measured: `1047` // Estimated: `4764` - // Minimum execution time: 40_258_000 picoseconds. - Weight::from_parts(41_210_000, 0) + // Minimum execution time: 55_406_000 picoseconds. + Weight::from_parts(56_832_000, 0) .saturating_add(Weight::from_parts(0, 4764)) - .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().reads(6)) .saturating_add(T::DbWeight::get().writes(4)) } } From f19177fb67bd9aca12028e562f6fff90f4c7d42c Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sun, 25 Aug 2024 08:02:24 +0100 Subject: [PATCH 21/41] nit --- prdoc/pr_3811.prdoc | 3 ++- .../election-provider-multi-phase/test-staking-e2e/src/lib.rs | 4 ++-- substrate/frame/staking/src/tests.rs | 3 +-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/prdoc/pr_3811.prdoc b/prdoc/pr_3811.prdoc index 0c1f2571dc491..cd9582582c1f7 100644 --- a/prdoc/pr_3811.prdoc +++ b/prdoc/pr_3811.prdoc @@ -1,4 +1,4 @@ -title: "Chill and Full Unbond in [pallet_staking]" +title: "Implicit chill when full unbounding in [pallet_staking]" doc: - audience: Runtime Dev @@ -8,3 +8,4 @@ doc: crates: - name: pallet-staking + bump: minor diff --git a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs index 14fdfcedfa6d5..4f42b28e7eaaa 100644 --- a/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs +++ b/substrate/frame/election-provider-multi-phase/test-staking-e2e/src/lib.rs @@ -245,8 +245,8 @@ fn ledger_consistency_active_balance_below_ed() { execute_with(ext, || { assert_eq!(Staking::ledger(11.into()).unwrap().active, 1000); - // unbonding total of active stake passes because Chill occurs implicitly when unbonding - // full amount + // unbonding total of active stake passes because chill occurs implicitly when unbonding + // full amount. assert_ok!(Staking::unbond(RuntimeOrigin::signed(11), 1000)); // the active balance of the ledger entry is 0, while total balance is 1000 until diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs index 91ac9dfb5a41f..0d27a7157ee2c 100644 --- a/substrate/frame/staking/src/tests.rs +++ b/substrate/frame/staking/src/tests.rs @@ -4135,8 +4135,7 @@ fn test_multi_page_payout_stakers_by_page() { #[test] fn unbond_with_chill_works() { - // - // * Should test + // Should test: // * Given an account being bonded [and chosen as a validator](not mandatory) // * it can force unbond a portion of its funds from the stash account. ExtBuilder::default().nominate(false).build_and_execute(|| { From aca4c8f2c0d06da1e478bf89f2fdf6d6e49c7ebf Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sat, 14 Sep 2024 11:27:40 +0100 Subject: [PATCH 22/41] add chill weight to unbond --- substrate/frame/staking/src/pallet/mod.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index 0ede46947b23f..bc5ce964d8722 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -1095,19 +1095,18 @@ pub mod pallet { let ledger = Self::ledger(StakingAccount::Controller(controller.clone()))?; + let mut total_weight = T::WeightInfo::unbond(); + if value >= ledger.total { Self::chill_stash(&ledger.stash); + total_weight = total_weight.saturating_add(T::WeightInfo::chill()); } - let maybe_withdraw_weight = Self::do_unbond(controller, value)?; - - let actual_weight = if let Some(withdraw_weight) = maybe_withdraw_weight { - Some(T::WeightInfo::unbond().saturating_add(withdraw_weight)) - } else { - Some(T::WeightInfo::unbond()) - }; + if let Some(withdraw_weight) = Self::do_unbond(controller, value)? { + total_weight = total_weight.saturating_add(withdraw_weight); + } - Ok(actual_weight.into()) + Ok(Some(total_weight).into()) } /// Remove any unlocked chunks from the `unlocking` queue from our management. From 38705e6d2077d648183d0d9dba33bb341610bc71 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sat, 14 Sep 2024 11:35:34 +0100 Subject: [PATCH 23/41] revert unsolicited changes --- substrate/frame/staking/src/pallet/impls.rs | 5 ----- substrate/frame/staking/src/tests.rs | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/substrate/frame/staking/src/pallet/impls.rs b/substrate/frame/staking/src/pallet/impls.rs index 56fd2861094b0..2d2c028194d9a 100644 --- a/substrate/frame/staking/src/pallet/impls.rs +++ b/substrate/frame/staking/src/pallet/impls.rs @@ -1163,11 +1163,6 @@ impl Pallet { EraInfo::::get_full_exposure(era, account) } - /// Whether `who` is a virtual staker whose funds are managed by another pallet. - pub(crate) fn is_virtual_staker(who: &T::AccountId) -> bool { - VirtualStakers::::contains_key(who) - } - /// Unbonds a controller. pub(crate) fn do_unbond( controller: T::AccountId, diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs index 0d27a7157ee2c..ebab46ca5b2ba 100644 --- a/substrate/frame/staking/src/tests.rs +++ b/substrate/frame/staking/src/tests.rs @@ -8037,7 +8037,7 @@ mod ledger_recovery { assert_eq!(Balances::balance_locked(crate::STAKING_ID, &333), lock_333_before); // OK assert_eq!(Bonded::::get(&333), Some(444)); // OK assert!(Payee::::get(&333).is_some()); // OK - // however, ledger associated with its controller was killed. + // however, ledger associated with its controller was killed. assert!(Ledger::::get(&444).is_none()); // NOK // side effects on 444 - ledger, bonded, payee, lock should be completely removed. From 95e61d0f0b6ed2c22bb9bc505cdb143cd8d55df3 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sat, 14 Sep 2024 11:38:12 +0100 Subject: [PATCH 24/41] revert benchmarks according to Ankan --- substrate/frame/staking/src/benchmarking.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/substrate/frame/staking/src/benchmarking.rs b/substrate/frame/staking/src/benchmarking.rs index e9557de72b472..1f8580d7a3e67 100644 --- a/substrate/frame/staking/src/benchmarking.rs +++ b/substrate/frame/staking/src/benchmarking.rs @@ -274,15 +274,16 @@ benchmarks! { let stash = scenario.origin_stash1.clone(); let controller = scenario.origin_controller1.clone(); + let amount = origin_weight - scenario.dest_weight; let ledger = Ledger::::get(&controller).ok_or("ledger not created before")?; let original_bonded: BalanceOf = ledger.active; whitelist_account!(controller); - }: _(RawOrigin::Signed(controller.clone()), original_bonded) + }: _(RawOrigin::Signed(controller.clone()), amount) verify { let ledger = Ledger::::get(&controller).ok_or("ledger not created after")?; let new_bonded: BalanceOf = ledger.active; - assert!(new_bonded == Zero::zero()); + assert!(original_bonded > new_bonded); } // Withdraw only updates the ledger From 45363638fd088149fea38e88c955da577bbfa6e0 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Tue, 17 Sep 2024 00:31:44 +0100 Subject: [PATCH 25/41] revert --- substrate/frame/staking/src/ledger.rs | 2 +- substrate/frame/staking/src/pallet/mod.rs | 5 +++-- substrate/frame/staking/src/slashing.rs | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/substrate/frame/staking/src/ledger.rs b/substrate/frame/staking/src/ledger.rs index 6965149e44b85..dc4b4fc326b81 100644 --- a/substrate/frame/staking/src/ledger.rs +++ b/substrate/frame/staking/src/ledger.rs @@ -35,7 +35,7 @@ use frame_support::{ defensive, ensure, traits::{Defensive, LockableCurrency}, }; -use sp_staking::StakingAccount; +use sp_staking::{StakingAccount, StakingInterface}; use crate::{ BalanceOf, Bonded, Config, Error, Ledger, Pallet, Payee, RewardDestination, StakingLedger, diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index 8d9227ee72ea0..eca95f2aa12fb 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -25,8 +25,8 @@ use frame_election_provider_support::{ use frame_support::{ pallet_prelude::*, traits::{ - Currency, Defensive, EnsureOrigin, EstimateNextNewSession, Get, InspectLockableCurrency, - LockableCurrency, OnUnbalanced, UnixTime, WithdrawReasons, + Currency, Defensive, EnsureOrigin, EstimateNextNewSession, Get, + InspectLockableCurrency, LockableCurrency, OnUnbalanced, UnixTime, WithdrawReasons, }, weights::Weight, BoundedVec, @@ -40,6 +40,7 @@ use sp_runtime::{ use sp_staking::{ EraIndex, Page, SessionIndex, StakingAccount::{self, Controller, Stash}, + StakingInterface, }; mod impls; diff --git a/substrate/frame/staking/src/slashing.rs b/substrate/frame/staking/src/slashing.rs index bab0310f8bf4c..9bc8197c50b3e 100644 --- a/substrate/frame/staking/src/slashing.rs +++ b/substrate/frame/staking/src/slashing.rs @@ -65,7 +65,7 @@ use sp_runtime::{ traits::{Saturating, Zero}, DispatchResult, RuntimeDebug, }; -use sp_staking::EraIndex; +use sp_staking::{EraIndex, StakingInterface}; /// The proportion of the slashing reward to be paid out on the first slashing detection. /// This is f_1 in the paper. From 06e8563b1bac5d490ca3ac058396598141d4a5f2 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Tue, 17 Sep 2024 00:43:15 +0100 Subject: [PATCH 26/41] fmt --- substrate/frame/staking/src/pallet/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index eca95f2aa12fb..e0cd4723d97d3 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -25,8 +25,8 @@ use frame_election_provider_support::{ use frame_support::{ pallet_prelude::*, traits::{ - Currency, Defensive, EnsureOrigin, EstimateNextNewSession, Get, - InspectLockableCurrency, LockableCurrency, OnUnbalanced, UnixTime, WithdrawReasons, + Currency, Defensive, EnsureOrigin, EstimateNextNewSession, Get, InspectLockableCurrency, + LockableCurrency, OnUnbalanced, UnixTime, WithdrawReasons, }, weights::Weight, BoundedVec, From 2fc715aa078e40b47eed17d73ba78d92030a02a3 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Thu, 3 Oct 2024 18:48:04 +0100 Subject: [PATCH 27/41] code review changes --- substrate/frame/staking/src/pallet/mod.rs | 4 ++-- substrate/frame/staking/src/tests.rs | 24 ++++++++++++++++++----- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index e0cd4723d97d3..b1031e80d559f 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -1087,7 +1087,7 @@ pub mod pallet { /// See also [`Call::withdraw_unbonded`]. #[pallet::call_index(2)] #[pallet::weight( - T::WeightInfo::withdraw_unbonded_kill(SPECULATIVE_NUM_SPANS).saturating_add(T::WeightInfo::unbond())) + T::WeightInfo::withdraw_unbonded_kill(SPECULATIVE_NUM_SPANS).saturating_add(T::WeightInfo::unbond()).saturating_add(T::WeightInfo::chill())) ] pub fn unbond( origin: OriginFor, @@ -1101,7 +1101,7 @@ pub mod pallet { if value >= ledger.total { Self::chill_stash(&ledger.stash); - total_weight = total_weight.saturating_add(T::WeightInfo::chill()); + total_weight.saturating_accrue(T::WeightInfo::chill()); } if let Some(withdraw_weight) = Self::do_unbond(controller, value)? { diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs index ebab46ca5b2ba..33300bbd54958 100644 --- a/substrate/frame/staking/src/tests.rs +++ b/substrate/frame/staking/src/tests.rs @@ -4167,11 +4167,25 @@ fn unbond_with_chill_works() { let res = Staking::unbond(RuntimeOrigin::signed(11), 1000); assert!(res.is_ok()); - assert_eq!(*staking_events().last().unwrap(), Event::Unbonded { stash: 11, amount: 1000 }); - assert_eq!( - *staking_events().get(staking_events().len() - 2).unwrap(), - Event::Chilled { stash: 11 } - ); + assert!(matches!( + staking_events_since_last_call().as_slice(), + &[ + Event::StakersElected, + Event::EraPaid { + era_index: 0, + validator_payout: 11075, + remainder: 33225, + }, + Event::StakersElected, + Event::EraPaid { + era_index: 1, + validator_payout: 11075, + remainder: 33225, + }, + Event::Chilled { stash: 11 }, + Event::Unbonded { stash: 11, amount:1000} + ] + )); }) } From 766458c26b5da927ca4e025f75a93596de297661 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Thu, 3 Oct 2024 18:49:01 +0100 Subject: [PATCH 28/41] fmt --- substrate/frame/staking/src/tests.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs index 33300bbd54958..853bb1423fe54 100644 --- a/substrate/frame/staking/src/tests.rs +++ b/substrate/frame/staking/src/tests.rs @@ -4171,19 +4171,11 @@ fn unbond_with_chill_works() { staking_events_since_last_call().as_slice(), &[ Event::StakersElected, - Event::EraPaid { - era_index: 0, - validator_payout: 11075, - remainder: 33225, - }, + Event::EraPaid { era_index: 0, validator_payout: 11075, remainder: 33225 }, Event::StakersElected, - Event::EraPaid { - era_index: 1, - validator_payout: 11075, - remainder: 33225, - }, + Event::EraPaid { era_index: 1, validator_payout: 11075, remainder: 33225 }, Event::Chilled { stash: 11 }, - Event::Unbonded { stash: 11, amount:1000} + Event::Unbonded { stash: 11, amount: 1000 } ] )); }) @@ -8051,7 +8043,7 @@ mod ledger_recovery { assert_eq!(Balances::balance_locked(crate::STAKING_ID, &333), lock_333_before); // OK assert_eq!(Bonded::::get(&333), Some(444)); // OK assert!(Payee::::get(&333).is_some()); // OK - // however, ledger associated with its controller was killed. + // however, ledger associated with its controller was killed. assert!(Ledger::::get(&444).is_none()); // NOK // side effects on 444 - ledger, bonded, payee, lock should be completely removed. From 9c62abcb29a37b5035a60af58f3be9d599afb8f7 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sat, 26 Oct 2024 09:16:14 +0100 Subject: [PATCH 29/41] nits --- prdoc/pr_3811.prdoc | 2 +- substrate/frame/staking/src/pallet/mod.rs | 12 +++++++----- substrate/frame/staking/src/tests.rs | 10 ++++++---- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/prdoc/pr_3811.prdoc b/prdoc/pr_3811.prdoc index cd9582582c1f7..1b457b80285c3 100644 --- a/prdoc/pr_3811.prdoc +++ b/prdoc/pr_3811.prdoc @@ -3,7 +3,7 @@ title: "Implicit chill when full unbounding in [pallet_staking]" doc: - audience: Runtime Dev description: | - Modifies the `unbond` extrinsic by forcefully chilling and unbonding the full value + Modifies the `unbond` extrinsic to forcefully chill stash when unbonding if the value to be unbonded is the total of what is bonded crates: diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index af311c43c3fe7..2a6bb5f53dab4 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -1070,6 +1070,8 @@ pub mod pallet { /// period ends. If this leaves an amount actively bonded less than /// [`asset::existential_deposit`], then it is increased to the full amount. /// + /// The stash may be chilled if the ledger total amount falls to 0 after unbonding. + /// /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. /// /// Once the unlock period is done, you can call `withdraw_unbonded` to actually move @@ -1097,12 +1099,12 @@ pub mod pallet { let ledger = Self::ledger(StakingAccount::Controller(controller.clone()))?; - let mut total_weight = T::WeightInfo::unbond(); - - if value >= ledger.total { + let mut total_weight = if value >= ledger.total { Self::chill_stash(&ledger.stash); - total_weight.saturating_accrue(T::WeightInfo::chill()); - } + T::WeightInfo::chill() + } else { + Zero::zero() + }; if let Some(withdraw_weight) = Self::do_unbond(controller, value)? { total_weight.saturating_accrue(withdraw_weight); diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs index e42922e02abb3..019e58ddcf4bd 100644 --- a/substrate/frame/staking/src/tests.rs +++ b/substrate/frame/staking/src/tests.rs @@ -4148,8 +4148,8 @@ fn test_multi_page_payout_stakers_by_page() { #[test] fn unbond_with_chill_works() { // Should test: - // * Given an account being bonded [and chosen as a validator](not mandatory) - // * it can force unbond a portion of its funds from the stash account. + // * Given a bunded account + // * it can full unbond all portion of its funds from the stash account. ExtBuilder::default().nominate(false).build_and_execute(|| { // Set payee to stash. assert_ok!(Staking::set_payee(RuntimeOrigin::signed(11), RewardDestination::Stash)); @@ -4172,12 +4172,13 @@ fn unbond_with_chill_works() { } ); + assert!(Validators::::contains_key(11)); + mock::start_active_era(2); assert_eq!(active_era(), 2); // Unbond all amount by ensuring chilling - let res = Staking::unbond(RuntimeOrigin::signed(11), 1000); - assert!(res.is_ok()); + assert_ok!(Staking::unbond(RuntimeOrigin::signed(11), 1000)); assert!(matches!( staking_events_since_last_call().as_slice(), @@ -4190,6 +4191,7 @@ fn unbond_with_chill_works() { Event::Unbonded { stash: 11, amount: 1000 } ] )); + assert!(!Validators::::contains_key(11)); }) } From 30b23d11d6bff97d91988de9ba6f515fe91f6b59 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sat, 26 Oct 2024 09:53:01 +0100 Subject: [PATCH 30/41] nit --- substrate/frame/staking/src/pallet/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index 2a6bb5f53dab4..90745895e9b74 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -25,7 +25,7 @@ use frame_election_provider_support::{ use frame_support::{ pallet_prelude::*, traits::{ - Defensive, DefensiveSaturating, EnsureOrigin, EstimateNextNewSession, Get, + Defensive, EnsureOrigin, EstimateNextNewSession, Get, InspectLockableCurrency, LockableCurrency, OnUnbalanced, UnixTime, }, weights::Weight, From 05f25f97e4babf9fdb00f4d8eceb2a2a62db11f6 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sat, 26 Oct 2024 09:53:26 +0100 Subject: [PATCH 31/41] nit --- substrate/frame/staking/src/pallet/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index 90745895e9b74..9e675849f4c84 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -25,8 +25,8 @@ use frame_election_provider_support::{ use frame_support::{ pallet_prelude::*, traits::{ - Defensive, EnsureOrigin, EstimateNextNewSession, Get, - InspectLockableCurrency, LockableCurrency, OnUnbalanced, UnixTime, + Defensive, EnsureOrigin, EstimateNextNewSession, Get, InspectLockableCurrency, + LockableCurrency, OnUnbalanced, UnixTime, }, weights::Weight, BoundedVec, From c47d381e369bc7922515d2d0923974d1fe421365 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sat, 23 Nov 2024 11:48:24 +0100 Subject: [PATCH 32/41] fix merge conflicts --- substrate/frame/staking/src/pallet/impls.rs | 23 ++++-- substrate/frame/staking/src/pallet/mod.rs | 84 +++------------------ 2 files changed, 24 insertions(+), 83 deletions(-) diff --git a/substrate/frame/staking/src/pallet/impls.rs b/substrate/frame/staking/src/pallet/impls.rs index 86bdeb2b52dbe..7bcc82b8fb041 100644 --- a/substrate/frame/staking/src/pallet/impls.rs +++ b/substrate/frame/staking/src/pallet/impls.rs @@ -1170,14 +1170,15 @@ impl Pallet { controller: T::AccountId, value: BalanceOf, ) -> Result, DispatchError> { - let unlocking = Self::ledger(Controller(controller.clone())).map(|l| l.unlocking.len())?; + let unlocking = + Self::ledger(Controller(controller.clone())).map(|l| l.unlocking.len())?; // if there are no unlocking chunks available, try to withdraw chunks older than // `BondingDuration` to proceed with the unbonding. let maybe_withdraw_weight = { if unlocking == T::MaxUnlockingChunks::get() as usize { let real_num_slashing_spans = - Self::slashing_spans(&controller).map_or(0, |s| s.iter().count()); + SlashingSpans::::get(&controller).map_or(0, |s| s.iter().count()); Some(Self::do_withdraw_unbonded(&controller, real_num_slashing_spans as u32)?) } else { None @@ -1186,14 +1187,14 @@ impl Pallet { // we need to fetch the ledger again because it may have been mutated in the call // to `Self::do_withdraw_unbonded` above. - let mut ledger = Self::ledger(Controller(controller.clone()))?; + let mut ledger = Self::ledger(Controller(controller))?; let mut value = value.min(ledger.active); let stash = ledger.stash.clone(); ensure!( - ledger.unlocking.len() < T::MaxUnlockingChunks::get() as usize, - Error::::NoMoreChunks, - ); + ledger.unlocking.len() < T::MaxUnlockingChunks::get() as usize, + Error::::NoMoreChunks, + ); if !value.is_zero() { ledger.active -= value; @@ -1217,7 +1218,7 @@ impl Pallet { ensure!(ledger.active >= min_active_bond, Error::::InsufficientBond); // Note: in case there is no current era it is fine to bond one era more. - let era = Self::current_era() + let era = CurrentEra::::get() .unwrap_or(0) .defensive_saturating_add(T::BondingDuration::get()); if let Some(chunk) = ledger.unlocking.last_mut().filter(|chunk| chunk.era == era) { @@ -1242,7 +1243,13 @@ impl Pallet { Self::deposit_event(Event::::Unbonded { stash, amount: value }); } - Ok(maybe_withdraw_weight) + let actual_weight = if let Some(withdraw_weight) = maybe_withdraw_weight { + Some(T::WeightInfo::unbond().saturating_add(withdraw_weight)) + } else { + Some(T::WeightInfo::unbond()) + }; + + Ok(actual_weight) } } diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index bc93a0a06307b..ae4d6f1acce58 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -1241,87 +1241,21 @@ pub mod pallet { #[pallet::compact] value: BalanceOf, ) -> DispatchResultWithPostInfo { let controller = ensure_signed(origin)?; - let unlocking = - Self::ledger(Controller(controller.clone())).map(|l| l.unlocking.len())?; - - // if there are no unlocking chunks available, try to withdraw chunks older than - // `BondingDuration` to proceed with the unbonding. - let maybe_withdraw_weight = { - if unlocking == T::MaxUnlockingChunks::get() as usize { - let real_num_slashing_spans = - SlashingSpans::::get(&controller).map_or(0, |s| s.iter().count()); - Some(Self::do_withdraw_unbonded(&controller, real_num_slashing_spans as u32)?) - } else { - None - } - }; - - // we need to fetch the ledger again because it may have been mutated in the call - // to `Self::do_withdraw_unbonded` above. - let mut ledger = Self::ledger(Controller(controller))?; - let mut value = value.min(ledger.active); - let stash = ledger.stash.clone(); - - ensure!( - ledger.unlocking.len() < T::MaxUnlockingChunks::get() as usize, - Error::::NoMoreChunks, - ); - - if !value.is_zero() { - ledger.active -= value; - - // Avoid there being a dust balance left in the staking system. - if ledger.active < asset::existential_deposit::() { - value += ledger.active; - ledger.active = Zero::zero(); - } - let min_active_bond = if Nominators::::contains_key(&stash) { - MinNominatorBond::::get() - } else if Validators::::contains_key(&stash) { - MinValidatorBond::::get() - } else { - Zero::zero() - }; - - // Make sure that the user maintains enough active bond for their role. - // If a user runs into this error, they should chill first. - ensure!(ledger.active >= min_active_bond, Error::::InsufficientBond); - - // Note: in case there is no current era it is fine to bond one era more. - let era = CurrentEra::::get() - .unwrap_or(0) - .defensive_saturating_add(T::BondingDuration::get()); - if let Some(chunk) = ledger.unlocking.last_mut().filter(|chunk| chunk.era == era) { - // To keep the chunk count down, we only keep one chunk per era. Since - // `unlocking` is a FiFo queue, if a chunk exists for `era` we know that it will - // be the last one. - chunk.value = chunk.value.defensive_saturating_add(value) - } else { - ledger - .unlocking - .try_push(UnlockChunk { value, era }) - .map_err(|_| Error::::NoMoreChunks)?; - }; - // NOTE: ledger must be updated prior to calling `Self::weight_of`. - ledger.update()?; - - // update this staker in the sorted list, if they exist in it. - if T::VoterList::contains(&stash) { - let _ = T::VoterList::on_update(&stash, Self::weight_of(&stash)).defensive(); - } - - Self::deposit_event(Event::::Unbonded { stash, amount: value }); - } + let ledger = Self::ledger(StakingAccount::Controller(controller.clone()))?; - let actual_weight = if let Some(withdraw_weight) = maybe_withdraw_weight { - Some(T::WeightInfo::unbond().saturating_add(withdraw_weight)) + let mut total_weight = if value >= ledger.total { + Self::chill_stash(&ledger.stash); + T::WeightInfo::chill() } else { - Some(T::WeightInfo::unbond()) + Zero::zero() }; + if let Some(withdraw_weight) = Self::do_unbond(controller, value)? { + total_weight.saturating_accrue(withdraw_weight); + } - Ok(actual_weight.into()) + Ok(Some(total_weight).into()) } /// Remove any unlocked chunks from the `unlocking` queue from our management. From 67034ab12f540e9b29069ca4f97489399554e7cd Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sat, 23 Nov 2024 11:49:09 +0100 Subject: [PATCH 33/41] fmt --- substrate/frame/staking/src/pallet/impls.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/substrate/frame/staking/src/pallet/impls.rs b/substrate/frame/staking/src/pallet/impls.rs index 7bcc82b8fb041..8e6b6c52e6bfe 100644 --- a/substrate/frame/staking/src/pallet/impls.rs +++ b/substrate/frame/staking/src/pallet/impls.rs @@ -1170,8 +1170,7 @@ impl Pallet { controller: T::AccountId, value: BalanceOf, ) -> Result, DispatchError> { - let unlocking = - Self::ledger(Controller(controller.clone())).map(|l| l.unlocking.len())?; + let unlocking = Self::ledger(Controller(controller.clone())).map(|l| l.unlocking.len())?; // if there are no unlocking chunks available, try to withdraw chunks older than // `BondingDuration` to proceed with the unbonding. @@ -1192,9 +1191,9 @@ impl Pallet { let stash = ledger.stash.clone(); ensure!( - ledger.unlocking.len() < T::MaxUnlockingChunks::get() as usize, - Error::::NoMoreChunks, - ); + ledger.unlocking.len() < T::MaxUnlockingChunks::get() as usize, + Error::::NoMoreChunks, + ); if !value.is_zero() { ledger.active -= value; From e65b72846f926dbbdb9dd2063f702037eac732b6 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sat, 25 Jan 2025 11:16:00 +0100 Subject: [PATCH 34/41] merge conflict resolving --- substrate/frame/staking/src/pallet/impls.rs | 2 +- substrate/frame/staking/src/pallet/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/frame/staking/src/pallet/impls.rs b/substrate/frame/staking/src/pallet/impls.rs index 8e7a90807f28a..2dfc1bf0ade16 100644 --- a/substrate/frame/staking/src/pallet/impls.rs +++ b/substrate/frame/staking/src/pallet/impls.rs @@ -52,7 +52,7 @@ use crate::{ asset, election_size_tracker::StaticTracker, log, slashing, weights::WeightInfo, ActiveEraInfo, BalanceOf, EraInfo, EraPayout, Exposure, ExposureOf, Forcing, IndividualExposure, LedgerIntegrityState, MaxNominationsOf, MaxWinnersOf, Nominations, NominationsQuota, - PositiveImbalanceOf, RewardDestination, SessionInterface, StakingLedger, ValidatorPrefs, + PositiveImbalanceOf, RewardDestination, SessionInterface, StakingLedger, UnlockChunk, ValidatorPrefs, STAKING_ID, }; use alloc::{boxed::Box, vec, vec::Vec}; diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index f78c86a41f4c2..d594d8c1d7998 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -29,7 +29,7 @@ use frame_support::{ hold::{Balanced as FunHoldBalanced, Mutate as FunHoldMutate}, Mutate as FunMutate, }, - Defensive, DefensiveSaturating, EnsureOrigin, EstimateNextNewSession, Get, + Defensive, EnsureOrigin, EstimateNextNewSession, Get, InspectLockableCurrency, OnUnbalanced, UnixTime, }, weights::Weight, From a187b0daf1d40ce0313eb25c90073dbc142f4af7 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sat, 25 Jan 2025 11:16:43 +0100 Subject: [PATCH 35/41] fmt --- substrate/frame/staking/src/pallet/impls.rs | 4 ++-- substrate/frame/staking/src/pallet/mod.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/substrate/frame/staking/src/pallet/impls.rs b/substrate/frame/staking/src/pallet/impls.rs index 2dfc1bf0ade16..3606c0a3fa2de 100644 --- a/substrate/frame/staking/src/pallet/impls.rs +++ b/substrate/frame/staking/src/pallet/impls.rs @@ -52,8 +52,8 @@ use crate::{ asset, election_size_tracker::StaticTracker, log, slashing, weights::WeightInfo, ActiveEraInfo, BalanceOf, EraInfo, EraPayout, Exposure, ExposureOf, Forcing, IndividualExposure, LedgerIntegrityState, MaxNominationsOf, MaxWinnersOf, Nominations, NominationsQuota, - PositiveImbalanceOf, RewardDestination, SessionInterface, StakingLedger, UnlockChunk, ValidatorPrefs, - STAKING_ID, + PositiveImbalanceOf, RewardDestination, SessionInterface, StakingLedger, UnlockChunk, + ValidatorPrefs, STAKING_ID, }; use alloc::{boxed::Box, vec, vec::Vec}; diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index d594d8c1d7998..7008fbf905169 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -29,8 +29,8 @@ use frame_support::{ hold::{Balanced as FunHoldBalanced, Mutate as FunHoldMutate}, Mutate as FunMutate, }, - Defensive, EnsureOrigin, EstimateNextNewSession, Get, - InspectLockableCurrency, OnUnbalanced, UnixTime, + Defensive, EnsureOrigin, EstimateNextNewSession, Get, InspectLockableCurrency, + OnUnbalanced, UnixTime, }, weights::Weight, BoundedVec, From 936b12f85e0a845c956c0550cbe29923c04c3945 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Mon, 27 Jan 2025 10:56:36 +0100 Subject: [PATCH 36/41] nit conversation --- substrate/frame/nomination-pools/test-transfer-stake/src/lib.rs | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 substrate/frame/nomination-pools/test-transfer-stake/src/lib.rs diff --git a/substrate/frame/nomination-pools/test-transfer-stake/src/lib.rs b/substrate/frame/nomination-pools/test-transfer-stake/src/lib.rs deleted file mode 100644 index e69de29bb2d1d..0000000000000 From 66ce2ed0e1738c1c0e3041d4c377cc86db93c2f6 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Tue, 28 Jan 2025 13:59:32 +0100 Subject: [PATCH 37/41] assert to ensure Validators is not present in the count of all validators --- substrate/frame/staking/src/tests.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/substrate/frame/staking/src/tests.rs b/substrate/frame/staking/src/tests.rs index d92a8692257c3..4d8585dab32e8 100644 --- a/substrate/frame/staking/src/tests.rs +++ b/substrate/frame/staking/src/tests.rs @@ -4269,6 +4269,8 @@ fn unbond_with_chill_works() { mock::start_active_era(2); assert_eq!(active_era(), 2); + assert_eq!(Validators::::count(), 3); + // Unbond all amount by ensuring chilling assert_ok!(Staking::unbond(RuntimeOrigin::signed(11), 1000)); @@ -4284,6 +4286,9 @@ fn unbond_with_chill_works() { ] )); assert!(!Validators::::contains_key(11)); + + assert!(Nominators::::get(11).is_none()); + assert_eq!(Validators::::count(), 2); }) } From 7b89287cb9449a9b12cfcd19b5b4b9f2fafd240d Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sat, 22 Feb 2025 21:02:45 +0100 Subject: [PATCH 38/41] fix test --- substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs | 2 +- substrate/frame/staking/src/pallet/impls.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs b/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs index ad16bca625fe7..ca8b104ca4920 100644 --- a/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs +++ b/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs @@ -177,7 +177,7 @@ fn pool_lifecycle_e2e() { pool_events_since_last_call(), vec![ PoolsEvent::PoolNominatorChilled { pool_id: 1, caller: 10 }, - PoolsEvent::Unbonded { member: 10, pool_id: 1, points: 50, balance: 50, era: 6 } + PoolsEvent::Unbonded { member: 10, pool_id: 1, points: 50, balance: 50, era: 6 }, ] ); diff --git a/substrate/frame/staking/src/pallet/impls.rs b/substrate/frame/staking/src/pallet/impls.rs index de672d01420f1..0fe2cec20dc15 100644 --- a/substrate/frame/staking/src/pallet/impls.rs +++ b/substrate/frame/staking/src/pallet/impls.rs @@ -50,7 +50,7 @@ use crate::{ BalanceOf, BoundedExposuresOf, EraInfo, EraPayout, Exposure, Forcing, IndividualExposure, LedgerIntegrityState, MaxNominationsOf, MaxWinnersOf, MaxWinnersPerPageOf, Nominations, NominationsQuota, PositiveImbalanceOf, RewardDestination, SessionInterface, SnapshotStatus, - StakingLedger, ValidatorPrefs, STAKING_ID, + UnlockChunk, StakingLedger, ValidatorPrefs, STAKING_ID, }; use alloc::{boxed::Box, vec, vec::Vec}; From 21c0d3ea00312bef702b999533f790062147f733 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sat, 22 Feb 2025 21:03:12 +0100 Subject: [PATCH 39/41] fmt --- substrate/frame/staking/src/pallet/impls.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substrate/frame/staking/src/pallet/impls.rs b/substrate/frame/staking/src/pallet/impls.rs index 0fe2cec20dc15..6dcb882e4d55f 100644 --- a/substrate/frame/staking/src/pallet/impls.rs +++ b/substrate/frame/staking/src/pallet/impls.rs @@ -50,7 +50,7 @@ use crate::{ BalanceOf, BoundedExposuresOf, EraInfo, EraPayout, Exposure, Forcing, IndividualExposure, LedgerIntegrityState, MaxNominationsOf, MaxWinnersOf, MaxWinnersPerPageOf, Nominations, NominationsQuota, PositiveImbalanceOf, RewardDestination, SessionInterface, SnapshotStatus, - UnlockChunk, StakingLedger, ValidatorPrefs, STAKING_ID, + StakingLedger, UnlockChunk, ValidatorPrefs, STAKING_ID, }; use alloc::{boxed::Box, vec, vec::Vec}; From 16ebaddc12a9cbb24c0706f54139033fb973ffd2 Mon Sep 17 00:00:00 2001 From: dharjeezy Date: Sat, 22 Feb 2025 22:14:45 +0100 Subject: [PATCH 40/41] fmt --- substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs b/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs index ca8b104ca4920..e412120fedfc2 100644 --- a/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs +++ b/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs @@ -176,7 +176,6 @@ fn pool_lifecycle_e2e() { assert_eq!( pool_events_since_last_call(), vec![ - PoolsEvent::PoolNominatorChilled { pool_id: 1, caller: 10 }, PoolsEvent::Unbonded { member: 10, pool_id: 1, points: 50, balance: 50, era: 6 }, ] ); From d2e016eca346fe45669fc5de7137e13da4084b50 Mon Sep 17 00:00:00 2001 From: command-bot <> Date: Sat, 1 Mar 2025 07:09:25 +0000 Subject: [PATCH 41/41] ".git/.scripts/commands/fmt/fmt.sh" --- .../frame/nomination-pools/test-delegate-stake/src/lib.rs | 4 +--- substrate/frame/staking/src/pallet/mod.rs | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs b/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs index e412120fedfc2..103e38b57f0cf 100644 --- a/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs +++ b/substrate/frame/nomination-pools/test-delegate-stake/src/lib.rs @@ -175,9 +175,7 @@ fn pool_lifecycle_e2e() { ); assert_eq!( pool_events_since_last_call(), - vec![ - PoolsEvent::Unbonded { member: 10, pool_id: 1, points: 50, balance: 50, era: 6 }, - ] + vec![PoolsEvent::Unbonded { member: 10, pool_id: 1, points: 50, balance: 50, era: 6 },] ); // waiting another bonding duration: diff --git a/substrate/frame/staking/src/pallet/mod.rs b/substrate/frame/staking/src/pallet/mod.rs index 20d3016a151b4..2033c2f645ea5 100644 --- a/substrate/frame/staking/src/pallet/mod.rs +++ b/substrate/frame/staking/src/pallet/mod.rs @@ -28,8 +28,8 @@ use frame_support::{ hold::{Balanced as FunHoldBalanced, Mutate as FunHoldMutate}, Inspect, Mutate, Mutate as FunMutate, }, - Contains, Defensive, DefensiveSaturating, EnsureOrigin, EstimateNextNewSession, Get, - InspectLockableCurrency, Nothing, OnUnbalanced, UnixTime, + Contains, Defensive, DefensiveSaturating, EnsureOrigin, EstimateNextNewSession, Get, + InspectLockableCurrency, Nothing, OnUnbalanced, UnixTime, }, weights::Weight, BoundedBTreeSet, BoundedVec,