Skip to content

Commit 3fcd3cf

Browse files
authored
fix(tokens): PostDeposit hook (#839)
* fix(tokens): PostDeposit hook * test(tokens): posthook correctness * fix(tokens): use `assert` instead of `ensure` in mock posthooks
1 parent 5803a01 commit 3fcd3cf

File tree

3 files changed

+59
-16
lines changed

3 files changed

+59
-16
lines changed

tokens/src/lib.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -1054,19 +1054,19 @@ impl<T: Config> Pallet<T> {
10541054
TotalIssuance::<T>::mutate(currency_id, |v| *v = new_total_issuance);
10551055
}
10561056
account.free = account.free.defensive_saturating_add(amount);
1057-
1058-
<T::CurrencyHooks as MutationHooks<T::AccountId, T::CurrencyId, T::Balance>>::PostDeposit::on_deposit(
1059-
currency_id,
1060-
who,
1061-
amount,
1062-
)?;
1063-
Self::deposit_event(Event::Deposited {
1064-
currency_id,
1065-
who: who.clone(),
1066-
amount,
1067-
});
10681057
Ok(())
1069-
})
1058+
})?;
1059+
<T::CurrencyHooks as MutationHooks<T::AccountId, T::CurrencyId, T::Balance>>::PostDeposit::on_deposit(
1060+
currency_id,
1061+
who,
1062+
amount,
1063+
)?;
1064+
Self::deposit_event(Event::Deposited {
1065+
currency_id,
1066+
who: who.clone(),
1067+
amount,
1068+
});
1069+
Ok(())
10701070
}
10711071
}
10721072

tokens/src/mock.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -327,8 +327,14 @@ impl<T: Config> PreDeposit<T> {
327327

328328
pub struct PostDeposit<T>(marker::PhantomData<T>);
329329
impl<T: Config> OnDeposit<T::AccountId, T::CurrencyId, T::Balance> for PostDeposit<T> {
330-
fn on_deposit(_currency_id: T::CurrencyId, _account_id: &T::AccountId, _amount: T::Balance) -> DispatchResult {
330+
fn on_deposit(currency_id: T::CurrencyId, account_id: &T::AccountId, amount: T::Balance) -> DispatchResult {
331331
ON_DEPOSIT_POSTHOOK_CALLS.with(|cell| *cell.borrow_mut() += 1);
332+
let account_balance: AccountData<T::Balance> =
333+
tokens::Pallet::<T>::accounts::<T::AccountId, T::CurrencyId>(account_id.clone(), currency_id);
334+
assert!(
335+
account_balance.free.ge(&amount),
336+
"Posthook must run after the account balance is updated."
337+
);
332338
Ok(())
333339
}
334340
}
@@ -359,12 +365,18 @@ impl<T: Config> PreTransfer<T> {
359365
pub struct PostTransfer<T>(marker::PhantomData<T>);
360366
impl<T: Config> OnTransfer<T::AccountId, T::CurrencyId, T::Balance> for PostTransfer<T> {
361367
fn on_transfer(
362-
_currency_id: T::CurrencyId,
368+
currency_id: T::CurrencyId,
363369
_from: &T::AccountId,
364-
_to: &T::AccountId,
365-
_amount: T::Balance,
370+
to: &T::AccountId,
371+
amount: T::Balance,
366372
) -> DispatchResult {
367373
ON_TRANSFER_POSTHOOK_CALLS.with(|cell| *cell.borrow_mut() += 1);
374+
let account_balance: AccountData<T::Balance> =
375+
tokens::Pallet::<T>::accounts::<T::AccountId, T::CurrencyId>(to.clone(), currency_id);
376+
assert!(
377+
account_balance.free.ge(&amount),
378+
"Posthook must run after the account balance is updated."
379+
);
368380
Ok(())
369381
}
370382
}

tokens/src/tests.rs

+31
Original file line numberDiff line numberDiff line change
@@ -1200,6 +1200,17 @@ fn deposit_hooks_work() {
12001200
});
12011201
}
12021202

1203+
#[test]
1204+
fn post_deposit_can_use_new_balance() {
1205+
ExtBuilder::default().build().execute_with(|| {
1206+
let initial_balance = Tokens::free_balance(DOT, &CHARLIE);
1207+
// The following will fail unless Charlie's new balance can be used by the hook,
1208+
// because `initial_balance + 100` is higher than Charlie's initial balance.
1209+
// If this fails, the posthook is called too soon.
1210+
assert_ok!(Tokens::do_deposit(DOT, &CHARLIE, initial_balance + 100, false, true),);
1211+
});
1212+
}
1213+
12031214
#[test]
12041215
fn transfer_hooks_work() {
12051216
ExtBuilder::default()
@@ -1238,3 +1249,23 @@ fn transfer_hooks_work() {
12381249
assert_eq!(PostTransfer::<Runtime>::calls(), initial_posthook_calls + 1);
12391250
});
12401251
}
1252+
1253+
#[test]
1254+
fn post_transfer_can_use_new_balance() {
1255+
ExtBuilder::default()
1256+
.balances(vec![(ALICE, DOT, 100)])
1257+
.build()
1258+
.execute_with(|| {
1259+
let initial_balance = Tokens::free_balance(DOT, &CHARLIE);
1260+
// The following will fail unless Charlie's new balance can be used by the hook,
1261+
// because `initial_balance + 100` is higher than Charlie's initial balance.
1262+
// If this fails, the posthook is called too soon.
1263+
assert_ok!(Tokens::do_transfer(
1264+
DOT,
1265+
&ALICE,
1266+
&CHARLIE,
1267+
initial_balance + 100,
1268+
ExistenceRequirement::AllowDeath
1269+
));
1270+
});
1271+
}

0 commit comments

Comments
 (0)