diff --git a/frame/offences/benchmarking/src/lib.rs b/frame/offences/benchmarking/src/lib.rs index e7c61bfd989b4..d424cfc751eef 100644 --- a/frame/offences/benchmarking/src/lib.rs +++ b/frame/offences/benchmarking/src/lib.rs @@ -208,8 +208,10 @@ fn make_offenders_im_online(num_offenders: u32, num_nominators: u32) #[cfg(test)] fn check_events::Event>>(expected: I) { - let events = System::::events() .into_iter() - .map(|frame_system::EventRecord { event, .. }| event).collect::>(); + let events = System::::events() + .into_iter() + .map(|frame_system::EventRecord { event, .. }| event) + .collect::>(); let expected = expected.collect::>(); let lengths = (events.len(), expected.len()); let length_mismatch = if lengths.0 != lengths.1 { @@ -273,13 +275,19 @@ benchmarks! { let bond_amount: u32 = UniqueSaturatedInto::::unique_saturated_into(bond_amount::()); let slash_amount = slash_fraction * bond_amount; let reward_amount = slash_amount * (1 + n) / 2; + let slash = |id| core::iter::once( + ::Event::from(StakingEvent::::Slash(id, BalanceOf::::from(slash_amount))) + ); + let chill = |id| core::iter::once( + ::Event::from(StakingEvent::::Chilled(id)) + ); let mut slash_events = raw_offenders.into_iter() .flat_map(|offender| { - core::iter::once(offender.stash).chain(offender.nominator_stashes.into_iter()) + let nom_slashes = offender.nominator_stashes.into_iter().flat_map(|nom| slash(nom)); + chill(offender.stash.clone()) + .chain(slash(offender.stash)) + .chain(nom_slashes) }) - .map(|stash| ::Event::from( - StakingEvent::::Slash(stash, BalanceOf::::from(slash_amount)) - )) .collect::>(); let reward_events = reporters.into_iter() .flat_map(|reporter| vec![ @@ -289,8 +297,9 @@ benchmarks! { ).into() ]); - // rewards are applied after first offender and it's nominators - let slash_rest = slash_events.split_off(1 + n as usize); + // Rewards are applied after first offender and it's nominators. + // We split after: offender slash + offender chill + nominator slashes. + let slash_rest = slash_events.split_off(2 + n as usize); // make sure that all slashes have been applied #[cfg(test)] @@ -338,6 +347,7 @@ benchmarks! { + 1 // offence + 2 // reporter (reward + endowment) + 1 // offenders slashed + + 1 // offenders chilled + n // nominators slashed ); } @@ -372,6 +382,7 @@ benchmarks! { + 1 // offence + 2 // reporter (reward + endowment) + 1 // offenders slashed + + 1 // offenders chilled + n // nominators slashed ); } diff --git a/frame/staking/src/lib.rs b/frame/staking/src/lib.rs index ec7da1be18714..1f22275bde9c3 100644 --- a/frame/staking/src/lib.rs +++ b/frame/staking/src/lib.rs @@ -1329,6 +1329,9 @@ pub mod pallet { Kicked(T::AccountId, T::AccountId), /// The election failed. No new era is planned. StakingElectionFailed, + /// An account has stopped participating as either a validator or nominator. + /// \[stash\] + Chilled(T::AccountId), } #[pallet::error] @@ -2523,8 +2526,11 @@ impl Pallet { /// Chill a stash account. fn chill_stash(stash: &T::AccountId) { - Self::do_remove_validator(stash); - Self::do_remove_nominator(stash); + let chilled_as_validator = Self::do_remove_validator(stash); + let chilled_as_nominator = Self::do_remove_nominator(stash); + if chilled_as_validator || chilled_as_nominator { + Self::deposit_event(Event::::Chilled(stash.clone())); + } } /// Actually make a payment to a staker. This uses the currency's reward function @@ -3014,10 +3020,15 @@ impl Pallet { /// This function will remove a nominator from the `Nominators` storage map, /// and keep track of the `CounterForNominators`. - pub fn do_remove_nominator(who: &T::AccountId) { + /// + /// Returns true if `who` was removed from `Nominators`, otherwise false. + pub fn do_remove_nominator(who: &T::AccountId) -> bool { if Nominators::::contains_key(who) { Nominators::::remove(who); CounterForNominators::::mutate(|x| x.saturating_dec()); + true + } else { + false } } @@ -3034,10 +3045,15 @@ impl Pallet { /// This function will remove a validator from the `Validators` storage map, /// and keep track of the `CounterForValidators`. - pub fn do_remove_validator(who: &T::AccountId) { + /// + /// Returns true if `who` was removed from `Validators`, otherwise false. + pub fn do_remove_validator(who: &T::AccountId) -> bool { if Validators::::contains_key(who) { Validators::::remove(who); CounterForValidators::::mutate(|x| x.saturating_dec()); + true + } else { + false } } }