diff --git a/tokens/src/lib.rs b/tokens/src/lib.rs index 59be2f68b..b1d30c822 100644 --- a/tokens/src/lib.rs +++ b/tokens/src/lib.rs @@ -1054,19 +1054,19 @@ impl Pallet { TotalIssuance::::mutate(currency_id, |v| *v = new_total_issuance); } account.free = account.free.defensive_saturating_add(amount); - - >::PostDeposit::on_deposit( - currency_id, - who, - amount, - )?; - Self::deposit_event(Event::Deposited { - currency_id, - who: who.clone(), - amount, - }); Ok(()) - }) + })?; + >::PostDeposit::on_deposit( + currency_id, + who, + amount, + )?; + Self::deposit_event(Event::Deposited { + currency_id, + who: who.clone(), + amount, + }); + Ok(()) } } diff --git a/tokens/src/mock.rs b/tokens/src/mock.rs index ca5592c89..528eb69c9 100644 --- a/tokens/src/mock.rs +++ b/tokens/src/mock.rs @@ -327,8 +327,14 @@ impl PreDeposit { pub struct PostDeposit(marker::PhantomData); impl OnDeposit for PostDeposit { - fn on_deposit(_currency_id: T::CurrencyId, _account_id: &T::AccountId, _amount: T::Balance) -> DispatchResult { + fn on_deposit(currency_id: T::CurrencyId, account_id: &T::AccountId, amount: T::Balance) -> DispatchResult { ON_DEPOSIT_POSTHOOK_CALLS.with(|cell| *cell.borrow_mut() += 1); + let account_balance: AccountData = + tokens::Pallet::::accounts::(account_id.clone(), currency_id); + assert!( + account_balance.free.ge(&amount), + "Posthook must run after the account balance is updated." + ); Ok(()) } } @@ -359,12 +365,18 @@ impl PreTransfer { pub struct PostTransfer(marker::PhantomData); impl OnTransfer for PostTransfer { fn on_transfer( - _currency_id: T::CurrencyId, + currency_id: T::CurrencyId, _from: &T::AccountId, - _to: &T::AccountId, - _amount: T::Balance, + to: &T::AccountId, + amount: T::Balance, ) -> DispatchResult { ON_TRANSFER_POSTHOOK_CALLS.with(|cell| *cell.borrow_mut() += 1); + let account_balance: AccountData = + tokens::Pallet::::accounts::(to.clone(), currency_id); + assert!( + account_balance.free.ge(&amount), + "Posthook must run after the account balance is updated." + ); Ok(()) } } diff --git a/tokens/src/tests.rs b/tokens/src/tests.rs index baa96dd69..e1c51c8a3 100644 --- a/tokens/src/tests.rs +++ b/tokens/src/tests.rs @@ -1200,6 +1200,17 @@ fn deposit_hooks_work() { }); } +#[test] +fn post_deposit_can_use_new_balance() { + ExtBuilder::default().build().execute_with(|| { + let initial_balance = Tokens::free_balance(DOT, &CHARLIE); + // The following will fail unless Charlie's new balance can be used by the hook, + // because `initial_balance + 100` is higher than Charlie's initial balance. + // If this fails, the posthook is called too soon. + assert_ok!(Tokens::do_deposit(DOT, &CHARLIE, initial_balance + 100, false, true),); + }); +} + #[test] fn transfer_hooks_work() { ExtBuilder::default() @@ -1238,3 +1249,23 @@ fn transfer_hooks_work() { assert_eq!(PostTransfer::::calls(), initial_posthook_calls + 1); }); } + +#[test] +fn post_transfer_can_use_new_balance() { + ExtBuilder::default() + .balances(vec![(ALICE, DOT, 100)]) + .build() + .execute_with(|| { + let initial_balance = Tokens::free_balance(DOT, &CHARLIE); + // The following will fail unless Charlie's new balance can be used by the hook, + // because `initial_balance + 100` is higher than Charlie's initial balance. + // If this fails, the posthook is called too soon. + assert_ok!(Tokens::do_transfer( + DOT, + &ALICE, + &CHARLIE, + initial_balance + 100, + ExistenceRequirement::AllowDeath + )); + }); +}