Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion tokens/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ use orml_traits::{
arithmetic::{self, Signed},
currency::TransferAll,
BalanceStatus, GetByKey, LockIdentifier, MultiCurrency, MultiCurrencyExtended, MultiLockableCurrency,
MultiReservableCurrency, OnDust,
MultiReservableCurrency, OnDust, Happened,
};

mod imbalances;
Expand Down Expand Up @@ -201,6 +201,12 @@ pub mod module {
/// Handler to burn or transfer account's dust
type OnDust: OnDust<Self::AccountId, Self::CurrencyId, Self::Balance>;

/// Handler for when an account was created
type OnNewTokenAccount: Happened<(Self::AccountId, Self::CurrencyId)>;

/// Handler for when an account was created
type OnKilledTokenAccount: Happened<(Self::AccountId, Self::CurrencyId)>;

#[pallet::constant]
type MaxLocks: Get<u32>;

Expand Down Expand Up @@ -704,9 +710,11 @@ impl<T: Config> Pallet<T> {
// Ignore the result, because if it failed then there are remaining consumers,
// and the account storage in frame_system shouldn't be reaped.
let _ = frame_system::Pallet::<T>::dec_providers(who);
T::OnKilledTokenAccount::happened(&(who.clone(), currency_id));
} else if !existed && exists {
// if new, increase account provider
frame_system::Pallet::<T>::inc_providers(who);
T::OnNewTokenAccount::happened(&(who.clone(), currency_id));
}

if let Some(endowed) = maybe_endowed {
Expand Down
42 changes: 42 additions & 0 deletions tokens/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,43 @@ parameter_type_with_key! {
};
}

thread_local! {
pub static CREATED: RefCell<Vec<(AccountId, CurrencyId)>> = RefCell::new(vec![]);
pub static KILLED: RefCell<Vec<(AccountId, CurrencyId)>> = RefCell::new(vec![]);
}

pub struct TrackCreatedAccounts;
impl TrackCreatedAccounts {
pub fn accounts() -> Vec<(AccountId, CurrencyId)> {
CREATED.with(|accounts| accounts.borrow().clone())
}

pub fn reset() {
CREATED.with(|accounts| { accounts.replace(vec![]); });
}
}
impl Happened<(AccountId, CurrencyId)> for TrackCreatedAccounts {
fn happened((who, currency): &(AccountId, CurrencyId)) {
CREATED.with(|accounts| { accounts.borrow_mut().push((who.clone(), *currency)); });
}
}

pub struct TrackKilledAccounts;
impl TrackKilledAccounts {
pub fn accounts() -> Vec<(AccountId, CurrencyId)> {
KILLED.with(|accounts| accounts.borrow().clone())
}

pub fn reset() {
KILLED.with(|accounts| { accounts.replace(vec![]); });
}
}
impl Happened<(AccountId, CurrencyId)> for TrackKilledAccounts {
fn happened((who, currency): &(AccountId, CurrencyId)) {
KILLED.with(|accounts| { accounts.borrow_mut().push((who.clone(), *currency)); });
}
}

parameter_types! {
pub DustReceiver: AccountId = PalletId(*b"orml/dst").into_account();
pub MaxLocks: u32 = 2;
Expand All @@ -238,6 +275,8 @@ impl Config for Runtime {
type ExistentialDeposits = ExistentialDeposits;
type OnDust = TransferDust<Runtime, DustReceiver>;
type MaxLocks = MaxLocks;
type OnNewTokenAccount = TrackCreatedAccounts;
type OnKilledTokenAccount = TrackKilledAccounts;
type DustRemovalWhitelist = MockDustRemovalWhitelist;
}
pub type TreasuryCurrencyAdapter = <Runtime as pallet_treasury::Config>::Currency;
Expand Down Expand Up @@ -299,6 +338,9 @@ impl ExtBuilder {
.unwrap();
}

TrackCreatedAccounts::reset();
TrackKilledAccounts::reset();

let mut ext = sp_io::TestExternalities::new(t);
ext.execute_with(|| System::set_block_number(1));
ext
Expand Down
23 changes: 23 additions & 0 deletions tokens/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ fn transfer_should_work() {
Error::<Runtime>::ExistentialDeposit,
);
assert_ok!(Tokens::transfer(Some(ALICE).into(), CHARLIE, DOT, 2));
assert_eq!(TrackCreatedAccounts::accounts(), vec![(CHARLIE, DOT)]);

// imply AllowDeath
assert!(Accounts::<Runtime>::contains_key(ALICE, DOT));
Expand Down Expand Up @@ -131,6 +132,7 @@ fn transfer_all_allow_death_should_work() {
assert!(Accounts::<Runtime>::contains_key(ALICE, DOT));
assert_eq!(Tokens::free_balance(DOT, &ALICE), 100);
assert_ok!(Tokens::transfer_all(Some(ALICE).into(), CHARLIE, DOT, false));
assert_eq!(TrackCreatedAccounts::accounts(), vec![(CHARLIE, DOT)]);
System::assert_last_event(Event::Tokens(crate::Event::Transfer {
currency_id: DOT,
from: ALICE,
Expand All @@ -139,6 +141,7 @@ fn transfer_all_allow_death_should_work() {
}));
assert!(!Accounts::<Runtime>::contains_key(ALICE, DOT));
assert_eq!(Tokens::free_balance(DOT, &ALICE), 0);
assert_eq!(TrackKilledAccounts::accounts(), vec![(ALICE, DOT)]);

assert_ok!(Tokens::set_lock(ID_1, DOT, &BOB, 50));
assert_eq!(Tokens::accounts(&BOB, DOT).frozen, 50);
Expand Down Expand Up @@ -176,6 +179,7 @@ fn force_transfer_should_work() {
amount: 100,
}));
assert!(!Accounts::<Runtime>::contains_key(ALICE, DOT));
assert_eq!(TrackKilledAccounts::accounts(), vec![(ALICE, DOT)]);
assert_eq!(Tokens::free_balance(DOT, &ALICE), 0);
assert_eq!(Tokens::free_balance(DOT, &BOB), 200);
});
Expand Down Expand Up @@ -2419,3 +2423,22 @@ fn fungibles_mutate_convert_should_work() {
);
});
}

#[test]
fn lifecycle_callbacks_are_activated() {
ExtBuilder::default()
.build()
.execute_with(|| {
assert_ok!(Tokens::set_balance(RawOrigin::Root.into(), ALICE, DOT, 200, 0));
assert_eq!(TrackCreatedAccounts::accounts(), vec![(ALICE, DOT)]);

assert_ok!(Tokens::set_balance(RawOrigin::Root.into(), ALICE, BTC, 200, 0));
assert_eq!(TrackCreatedAccounts::accounts(), vec![(ALICE, DOT), (ALICE, BTC)]);

assert_ok!(Tokens::transfer_all(Some(ALICE).into(), CHARLIE, BTC, false));
assert_eq!(TrackCreatedAccounts::accounts(), vec![
(ALICE, DOT), (ALICE, BTC), (CHARLIE, BTC)
]);
assert_eq!(TrackKilledAccounts::accounts(), vec![(ALICE, BTC)]);
})
}
3 changes: 2 additions & 1 deletion traits/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ use serde::{Deserialize, Serialize};
pub use auction::{Auction, AuctionHandler, AuctionInfo, OnNewBidResult};
pub use currency::{
BalanceStatus, BasicCurrency, BasicCurrencyExtended, BasicLockableCurrency, BasicReservableCurrency,
LockIdentifier, MultiCurrency, MultiCurrencyExtended, MultiLockableCurrency, MultiReservableCurrency, OnDust,
LockIdentifier, MultiCurrency, MultiCurrencyExtended, MultiLockableCurrency, MultiReservableCurrency,
OnDust,
};
pub use data_provider::{DataFeeder, DataProvider, DataProviderExtended};
pub use get_by_key::GetByKey;
Expand Down
Loading