Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
Emit event when changing total locked value in pallet-balances (#12287)
Browse files Browse the repository at this point in the history
* Emit Locked/Unlocked events

* Implement lock event tests

* Adhere to style guide

* Use saturating math

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* Fix typo

* Emit event on change locks and add tests

* Adjust event docstring

---------

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
Co-authored-by: parity-processbot <>
  • Loading branch information
sea212 and kianenigma committed Mar 24, 2023
1 parent 5766265 commit ea72382
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 0 deletions.
16 changes: 16 additions & 0 deletions frame/balances/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,10 @@ pub mod pallet {
Issued { amount: T::Balance },
/// Total issuance was decreased by `amount`, creating a debt to be balanced.
Rescinded { amount: T::Balance },
/// Some balance was locked.
Locked { who: T::AccountId, amount: T::Balance },
/// Some balance was unlocked.
Unlocked { who: T::AccountId, amount: T::Balance },
}

#[pallet::error]
Expand Down Expand Up @@ -1016,16 +1020,20 @@ pub mod pallet {
);
}
let freezes = Freezes::<T, I>::get(who);
let mut prev_frozen = Zero::zero();
let mut after_frozen = Zero::zero();
// TODO: Revisit this assumption. We no manipulate consumer/provider refs.
// No way this can fail since we do not alter the existential balances.
let res = Self::mutate_account(who, |b| {
prev_frozen = b.frozen;
b.frozen = Zero::zero();
for l in locks.iter() {
b.frozen = b.frozen.max(l.amount);
}
for l in freezes.iter() {
b.frozen = b.frozen.max(l.amount);
}
after_frozen = b.frozen;
});
debug_assert!(res.is_ok());
if let Ok((_, maybe_dust)) = res {
Expand Down Expand Up @@ -1053,6 +1061,14 @@ pub mod pallet {
);
}
}

if prev_frozen > after_frozen {
let amount = prev_frozen.saturating_sub(after_frozen);
Self::deposit_event(Event::Unlocked { who: who.clone(), amount });
} else if after_frozen > prev_frozen {
let amount = after_frozen.saturating_sub(prev_frozen);
Self::deposit_event(Event::Locked { who: who.clone(), amount });
}
}

/// Update the account entry for `who`, given the locks.
Expand Down
55 changes: 55 additions & 0 deletions frame/balances/src/tests/currency_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,61 @@ fn emit_events_with_reserve_and_unreserve() {
});
}

#[test]
fn emit_events_with_changing_locks() {
ExtBuilder::default().build_and_execute_with(|| {
let _ = Balances::deposit_creating(&1, 100);
System::reset_events();

// Locks = [] --> [10]
Balances::set_lock(*b"LOCK_000", &1, 10, WithdrawReasons::TRANSFER);
assert_eq!(events(), [RuntimeEvent::Balances(crate::Event::Locked { who: 1, amount: 10 })]);

// Locks = [10] --> [15]
Balances::set_lock(*b"LOCK_000", &1, 15, WithdrawReasons::TRANSFER);
assert_eq!(events(), [RuntimeEvent::Balances(crate::Event::Locked { who: 1, amount: 5 })]);

// Locks = [15] --> [15, 20]
Balances::set_lock(*b"LOCK_001", &1, 20, WithdrawReasons::TRANSACTION_PAYMENT);
assert_eq!(events(), [RuntimeEvent::Balances(crate::Event::Locked { who: 1, amount: 5 })]);

// Locks = [15, 20] --> [17, 20]
Balances::set_lock(*b"LOCK_000", &1, 17, WithdrawReasons::TRANSACTION_PAYMENT);
for event in events() {
match event {
RuntimeEvent::Balances(crate::Event::Locked { .. }) => {
assert!(false, "unexpected lock event")
},
RuntimeEvent::Balances(crate::Event::Unlocked { .. }) => {
assert!(false, "unexpected unlock event")
},
_ => continue,
}
}

// Locks = [17, 20] --> [17, 15]
Balances::set_lock(*b"LOCK_001", &1, 15, WithdrawReasons::TRANSFER);
assert_eq!(
events(),
[RuntimeEvent::Balances(crate::Event::Unlocked { who: 1, amount: 3 })]
);

// Locks = [17, 15] --> [15]
Balances::remove_lock(*b"LOCK_000", &1);
assert_eq!(
events(),
[RuntimeEvent::Balances(crate::Event::Unlocked { who: 1, amount: 2 })]
);

// Locks = [15] --> []
Balances::remove_lock(*b"LOCK_001", &1);
assert_eq!(
events(),
[RuntimeEvent::Balances(crate::Event::Unlocked { who: 1, amount: 15 })]
);
});
}

#[test]
fn emit_events_with_existential_deposit() {
ExtBuilder::default().existential_deposit(100).build_and_execute_with(|| {
Expand Down

0 comments on commit ea72382

Please sign in to comment.