diff --git a/substrate/frame/staking/src/lib.rs b/substrate/frame/staking/src/lib.rs index 5084c6c4a8..d8740f44e7 100644 --- a/substrate/frame/staking/src/lib.rs +++ b/substrate/frame/staking/src/lib.rs @@ -897,6 +897,16 @@ decl_event!( /// An old slashing report from a prior era was discarded because it could /// not be processed. OldSlashingReportDiscarded(SessionIndex), + /// An account has bonded this amount. + /// + /// NOTE: This event is only emitted when funds are bonded via a dispatchable. Notably, + /// it will not be emitted for staking rewards when they are added to stake. + Bonded(AccountId, Balance), + /// An account has unbonded this amount. + Unbonded(AccountId, Balance), + /// An account has called `withdraw_unbonded` and removed unbonding chunks worth `Balance` + /// from the unlocking queue. + Withdrawn(AccountId, Balance), } ); @@ -967,6 +977,8 @@ decl_module! { /// /// The dispatch origin for this call must be _Signed_ by the stash account. /// + /// Emits `Bonded`. + /// /// # /// - Independent of the arguments. Moderate complexity. /// - O(1). @@ -1007,6 +1019,7 @@ decl_module! { let stash_balance = T::Currency::free_balance(&stash); let value = value.min(stash_balance); + Self::deposit_event(RawEvent::Bonded(stash.clone(), value)); let item = StakingLedger { stash, total: value, @@ -1026,6 +1039,8 @@ decl_module! { /// /// The dispatch origin for this call must be _Signed_ by the stash, not the controller. /// + /// Emits `Bonded`. + /// /// # /// - Independent of the arguments. Insignificant complexity. /// - O(1). @@ -1044,6 +1059,7 @@ decl_module! { let extra = extra.min(max_additional); ledger.total += extra; ledger.active += extra; + Self::deposit_event(RawEvent::Bonded(stash, extra)); Self::update_ledger(&controller, &ledger); } } @@ -1061,6 +1077,8 @@ decl_module! { /// /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. /// + /// Emits `Unbonded`. + /// /// See also [`Call::withdraw_unbonded`]. /// /// # @@ -1096,6 +1114,7 @@ decl_module! { let era = Self::current_era().unwrap_or(0) + T::BondingDuration::get(); ledger.unlocking.push(UnlockChunk { value, era }); Self::update_ledger(&controller, &ledger); + Self::deposit_event(RawEvent::Unbonded(ledger.stash.clone(), value)); } } @@ -1106,6 +1125,8 @@ decl_module! { /// /// The dispatch origin for this call must be _Signed_ by the controller, not the stash. /// + /// Emits `Withdrawn`. + /// /// See also [`Call::unbond`]. /// /// # @@ -1119,6 +1140,7 @@ decl_module! { fn withdraw_unbonded(origin) { let controller = ensure_signed(origin)?; let mut ledger = Self::ledger(&controller).ok_or(Error::::NotController)?; + let (stash, old_total) = (ledger.stash.clone(), ledger.total); if let Some(current_era) = Self::current_era() { ledger = ledger.consolidate_unlocked(current_era) } @@ -1126,9 +1148,7 @@ decl_module! { if ledger.unlocking.is_empty() && ledger.active.is_zero() { // This account must have called `unbond()` with some value that caused the active // portion to fall below existential deposit + will have no more unlocking chunks - // left. We can now safely remove this. - let stash = ledger.stash; - // remove all staking-related information. + // left. We can now safely remove all staking-related information. Self::kill_stash(&stash)?; // remove the lock. T::Currency::remove_lock(STAKING_ID, &stash); @@ -1136,6 +1156,14 @@ decl_module! { // This was the consequence of a partial unbond. just update the ledger and move on. Self::update_ledger(&controller, &ledger); } + + // `old_total` should never be less than the new total because + // `consolidate_unlocked` strictly subtracts balance. + if ledger.total < old_total { + // Already checked that this won't overflow by entry condition. + let value = old_total - ledger.total; + Self::deposit_event(RawEvent::Withdrawn(stash, value)); + } } /// Declare the desire to validate for the origin controller.