From 471b49b09fd0d2a3057090ab0720f4e39faed5c5 Mon Sep 17 00:00:00 2001 From: Harald Heckmann Date: Fri, 21 Apr 2023 12:06:26 +0200 Subject: [PATCH] Add Freeze/Thaw events and tests (#13779) * Add Freeze/Thaw events and tests * Remove duplicate docstring * Correct spelling error * Cargo fmt * Use proper punctuation in docstring Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com> --------- Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com> Co-authored-by: parity-processbot <> --- frame/balances/src/lib.rs | 15 +++++++ frame/balances/src/tests/fungible_tests.rs | 46 ++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/frame/balances/src/lib.rs b/frame/balances/src/lib.rs index 74aec1f2d2..6835d3c814 100644 --- a/frame/balances/src/lib.rs +++ b/frame/balances/src/lib.rs @@ -337,6 +337,10 @@ pub mod pallet { Locked { who: T::AccountId, amount: T::Balance }, /// Some balance was unlocked. Unlocked { who: T::AccountId, amount: T::Balance }, + /// Some balance was frozen. + Frozen { who: T::AccountId, amount: T::Balance }, + /// Some balance was thawed. + Thawed { who: T::AccountId, amount: T::Balance }, } #[pallet::error] @@ -1084,7 +1088,10 @@ pub mod pallet { who: &T::AccountId, freezes: BoundedSlice, T::MaxFreezes>, ) -> DispatchResult { + let mut prev_frozen = Zero::zero(); + let mut after_frozen = Zero::zero(); let (_, maybe_dust) = Self::mutate_account(who, |b| { + prev_frozen = b.frozen; b.frozen = Zero::zero(); for l in Locks::::get(who).iter() { b.frozen = b.frozen.max(l.amount); @@ -1092,6 +1099,7 @@ pub mod pallet { for l in freezes.iter() { b.frozen = b.frozen.max(l.amount); } + after_frozen = b.frozen; })?; debug_assert!(maybe_dust.is_none(), "Not altering main balance; qed"); if freezes.is_empty() { @@ -1099,6 +1107,13 @@ pub mod pallet { } else { Freezes::::insert(who, freezes); } + if prev_frozen > after_frozen { + let amount = prev_frozen.saturating_sub(after_frozen); + Self::deposit_event(Event::Thawed { who: who.clone(), amount }); + } else if after_frozen > prev_frozen { + let amount = after_frozen.saturating_sub(prev_frozen); + Self::deposit_event(Event::Frozen { who: who.clone(), amount }); + } Ok(()) } diff --git a/frame/balances/src/tests/fungible_tests.rs b/frame/balances/src/tests/fungible_tests.rs index 1280868853..185396019b 100644 --- a/frame/balances/src/tests/fungible_tests.rs +++ b/frame/balances/src/tests/fungible_tests.rs @@ -397,3 +397,49 @@ fn unholding_frees_hold_slot() { assert_ok!(Balances::hold(&TestId::Baz, &1, 10)); }); } + +#[test] +fn emit_events_with_changing_freezes() { + ExtBuilder::default().build_and_execute_with(|| { + let _ = Balances::set_balance(&1, 100); + System::reset_events(); + + // Freeze = [] --> [10] + assert_ok!(Balances::set_freeze(&TestId::Foo, &1, 10)); + assert_eq!(events(), [RuntimeEvent::Balances(crate::Event::Frozen { who: 1, amount: 10 })]); + + // Freeze = [10] --> [15] + assert_ok!(Balances::set_freeze(&TestId::Foo, &1, 15)); + assert_eq!(events(), [RuntimeEvent::Balances(crate::Event::Frozen { who: 1, amount: 5 })]); + + // Freeze = [15] --> [15, 20] + assert_ok!(Balances::set_freeze(&TestId::Bar, &1, 20)); + assert_eq!(events(), [RuntimeEvent::Balances(crate::Event::Frozen { who: 1, amount: 5 })]); + + // Freeze = [15, 20] --> [17, 20] + assert_ok!(Balances::set_freeze(&TestId::Foo, &1, 17)); + for event in events() { + match event { + RuntimeEvent::Balances(crate::Event::Frozen { .. }) => { + assert!(false, "unexpected freeze event") + }, + RuntimeEvent::Balances(crate::Event::Thawed { .. }) => { + assert!(false, "unexpected thaw event") + }, + _ => continue, + } + } + + // Freeze = [17, 20] --> [17, 15] + assert_ok!(Balances::set_freeze(&TestId::Bar, &1, 15)); + assert_eq!(events(), [RuntimeEvent::Balances(crate::Event::Thawed { who: 1, amount: 3 })]); + + // Freeze = [17, 15] --> [15] + assert_ok!(Balances::thaw(&TestId::Foo, &1)); + assert_eq!(events(), [RuntimeEvent::Balances(crate::Event::Thawed { who: 1, amount: 2 })]); + + // Freeze = [15] --> [] + assert_ok!(Balances::thaw(&TestId::Bar, &1)); + assert_eq!(events(), [RuntimeEvent::Balances(crate::Event::Thawed { who: 1, amount: 15 })]); + }); +}