use crate::traits::{
fungible::{Inspect, Mutate},
tokens::{
DepositConsequence, Fortitude, Precision, Preservation, Provenance, WithdrawConsequence,
},
};
use core::fmt::Debug;
use sp_arithmetic::traits::AtLeast8BitUnsigned;
use sp_runtime::traits::{Bounded, Zero};
pub fn mint_into_success<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let initial_total_issuance = T::total_issuance();
let initial_active_issuance = T::active_issuance();
let account_0 = AccountId::from(0);
let account_1 = AccountId::from(1);
let amount_0 = T::minimum_balance();
let amount_1 = T::minimum_balance() + 5.into();
T::mint_into(&account_0, amount_0).unwrap();
T::mint_into(&account_1, amount_1).unwrap();
assert_eq!(T::total_balance(&account_0), amount_0);
assert_eq!(T::total_balance(&account_1), amount_1);
assert_eq!(T::balance(&account_0), amount_0);
assert_eq!(T::balance(&account_1), amount_1);
assert_eq!(T::total_issuance(), initial_total_issuance + amount_0 + amount_1);
assert_eq!(T::active_issuance(), initial_active_issuance + amount_0 + amount_1);
}
pub fn mint_into_overflow<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let initial_total_issuance = T::total_issuance();
let initial_active_issuance = T::active_issuance();
let account = AccountId::from(10);
let amount = T::Balance::max_value() - 5.into() - initial_total_issuance;
T::mint_into(&account, amount).unwrap();
T::mint_into(&account, 10.into()).unwrap_err();
assert_eq!(T::total_balance(&account), amount);
assert_eq!(T::balance(&account), amount);
assert_eq!(T::total_issuance(), initial_total_issuance + amount);
assert_eq!(T::active_issuance(), initial_active_issuance + amount);
}
pub fn mint_into_below_minimum<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
if T::minimum_balance() == T::Balance::zero() {
return
}
let initial_total_issuance = T::total_issuance();
let initial_active_issuance = T::active_issuance();
let account = AccountId::from(10);
let amount = T::minimum_balance() - 1.into();
T::mint_into(&account, amount).unwrap_err();
assert_eq!(T::total_balance(&account), T::Balance::zero());
assert_eq!(T::balance(&account), T::Balance::zero());
assert_eq!(T::total_issuance(), initial_total_issuance);
assert_eq!(T::active_issuance(), initial_active_issuance);
}
pub fn burn_from_exact_success<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let initial_total_issuance = T::total_issuance();
let initial_active_issuance = T::active_issuance();
let account = AccountId::from(5);
let initial_balance = T::minimum_balance() + 10.into();
T::mint_into(&account, initial_balance).unwrap();
let amount_to_burn = T::Balance::from(5);
let preservation = Preservation::Expendable;
let precision = Precision::Exact;
let force = Fortitude::Polite;
T::burn_from(&account, amount_to_burn, preservation, precision, force).unwrap();
assert_eq!(T::balance(&account), initial_balance - amount_to_burn);
assert_eq!(T::total_balance(&account), initial_balance - amount_to_burn);
assert_eq!(T::total_issuance(), initial_total_issuance + initial_balance - amount_to_burn);
assert_eq!(T::active_issuance(), initial_active_issuance + initial_balance - amount_to_burn);
}
pub fn burn_from_best_effort_success<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let initial_total_issuance = T::total_issuance();
let initial_active_issuance = T::active_issuance();
let account = AccountId::from(5);
let initial_balance = T::minimum_balance() + 10.into();
T::mint_into(&account, initial_balance).unwrap();
let force = Fortitude::Polite;
let reducible_balance = T::reducible_balance(&account, Preservation::Expendable, force);
let amount_to_burn = reducible_balance + 5.into();
let preservation = Preservation::Expendable;
let precision = Precision::BestEffort;
assert!(amount_to_burn > reducible_balance);
assert!(amount_to_burn > T::balance(&account));
T::burn_from(&account, amount_to_burn, preservation, precision, force).unwrap();
assert_eq!(T::balance(&account), initial_balance - reducible_balance);
assert_eq!(T::total_balance(&account), initial_balance - reducible_balance);
assert_eq!(T::total_issuance(), initial_total_issuance + initial_balance - reducible_balance);
assert_eq!(T::active_issuance(), initial_active_issuance + initial_balance - reducible_balance);
}
pub fn burn_from_exact_insufficient_funds<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let account = AccountId::from(5);
let initial_balance = T::minimum_balance() + 10.into();
T::mint_into(&account, initial_balance).unwrap();
let initial_total_issuance = T::total_issuance();
let initial_active_issuance = T::active_issuance();
let amount_to_burn = initial_balance + 10.into();
let preservation = Preservation::Expendable;
let precision = Precision::Exact;
let force = Fortitude::Polite;
T::burn_from(&account, amount_to_burn, preservation, precision, force).unwrap_err();
assert_eq!(T::balance(&account), initial_balance);
assert_eq!(T::total_balance(&account), initial_balance);
assert_eq!(T::total_issuance(), initial_total_issuance);
assert_eq!(T::active_issuance(), initial_active_issuance);
}
pub fn restore_success<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let account_0 = AccountId::from(0);
let account_1 = AccountId::from(1);
let amount_0 = T::minimum_balance();
let amount_1 = T::minimum_balance() + 5.into();
let initial_total_issuance = T::total_issuance();
let initial_active_issuance = T::active_issuance();
T::restore(&account_0, amount_0).unwrap();
T::restore(&account_1, amount_1).unwrap();
assert_eq!(T::total_balance(&account_0), amount_0);
assert_eq!(T::total_balance(&account_1), amount_1);
assert_eq!(T::balance(&account_0), amount_0);
assert_eq!(T::balance(&account_1), amount_1);
assert_eq!(T::total_issuance(), initial_total_issuance + amount_0 + amount_1);
assert_eq!(T::active_issuance(), initial_active_issuance + amount_0 + amount_1);
}
pub fn restore_overflow<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let initial_total_issuance = T::total_issuance();
let initial_active_issuance = T::active_issuance();
let account = AccountId::from(10);
let amount = T::Balance::max_value() - 5.into() - initial_total_issuance;
T::restore(&account, amount).unwrap();
T::restore(&account, 10.into()).unwrap_err();
assert_eq!(T::total_balance(&account), amount);
assert_eq!(T::balance(&account), amount);
assert_eq!(T::total_issuance(), initial_total_issuance + amount);
assert_eq!(T::active_issuance(), initial_active_issuance + amount);
}
pub fn restore_below_minimum<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
if T::minimum_balance() == T::Balance::zero() {
return
}
let account = AccountId::from(10);
let amount = T::minimum_balance() - 1.into();
let initial_total_issuance = T::total_issuance();
let initial_active_issuance = T::active_issuance();
T::restore(&account, amount).unwrap_err();
assert_eq!(T::total_balance(&account), T::Balance::zero());
assert_eq!(T::balance(&account), T::Balance::zero());
assert_eq!(T::total_issuance(), initial_total_issuance);
assert_eq!(T::active_issuance(), initial_active_issuance);
}
pub fn shelve_success<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let initial_total_issuance = T::total_issuance();
let initial_active_issuance = T::active_issuance();
let account = AccountId::from(5);
let initial_balance = T::minimum_balance() + 10.into();
T::restore(&account, initial_balance).unwrap();
let amount_to_shelve = T::Balance::from(5);
T::shelve(&account, amount_to_shelve).unwrap();
assert_eq!(T::balance(&account), initial_balance - amount_to_shelve);
assert_eq!(T::total_balance(&account), initial_balance - amount_to_shelve);
assert_eq!(T::total_issuance(), initial_total_issuance + initial_balance - amount_to_shelve);
assert_eq!(T::active_issuance(), initial_active_issuance + initial_balance - amount_to_shelve);
}
pub fn shelve_insufficient_funds<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let initial_total_issuance = T::total_issuance();
let initial_active_issuance = T::active_issuance();
let account = AccountId::from(5);
let initial_balance = T::minimum_balance() + 10.into();
T::restore(&account, initial_balance).unwrap();
let amount_to_shelve = initial_balance + 10.into();
T::shelve(&account, amount_to_shelve).unwrap_err();
assert_eq!(T::balance(&account), initial_balance);
assert_eq!(T::total_balance(&account), initial_balance);
assert_eq!(T::total_issuance(), initial_total_issuance + initial_balance);
assert_eq!(T::active_issuance(), initial_active_issuance + initial_balance);
}
pub fn transfer_success<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let initial_total_issuance = T::total_issuance();
let initial_active_issuance = T::active_issuance();
let account_0 = AccountId::from(0);
let account_1 = AccountId::from(1);
let initial_balance = T::minimum_balance() + 10.into();
T::set_balance(&account_0, initial_balance);
T::set_balance(&account_1, initial_balance);
let transfer_amount = T::Balance::from(3);
T::transfer(&account_0, &account_1, transfer_amount, Preservation::Expendable).unwrap();
assert_eq!(T::total_balance(&account_0), initial_balance - transfer_amount);
assert_eq!(T::total_balance(&account_1), initial_balance + transfer_amount);
assert_eq!(T::balance(&account_0), initial_balance - transfer_amount);
assert_eq!(T::balance(&account_1), initial_balance + transfer_amount);
assert_eq!(T::total_issuance(), initial_total_issuance + initial_balance * 2.into());
assert_eq!(T::active_issuance(), initial_active_issuance + initial_balance * 2.into());
}
pub fn transfer_expendable_all<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let initial_total_issuance = T::total_issuance();
let initial_active_issuance = T::active_issuance();
let account_0 = AccountId::from(0);
let account_1 = AccountId::from(1);
let initial_balance = T::minimum_balance() + 10.into();
T::set_balance(&account_0, initial_balance);
T::set_balance(&account_1, initial_balance);
let preservation = Preservation::Expendable;
let transfer_amount = initial_balance;
T::transfer(&account_0, &account_1, transfer_amount, preservation).unwrap();
assert_eq!(T::total_balance(&account_0), T::Balance::zero());
assert_eq!(T::total_balance(&account_1), initial_balance * 2.into());
assert_eq!(T::balance(&account_0), T::Balance::zero());
assert_eq!(T::balance(&account_1), initial_balance * 2.into());
assert_eq!(T::total_issuance(), initial_total_issuance + initial_balance * 2.into());
assert_eq!(T::active_issuance(), initial_active_issuance + initial_balance * 2.into());
}
pub fn transfer_expendable_dust<T, AccountId>(dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
if T::minimum_balance() == T::Balance::zero() {
return
}
let account_0 = AccountId::from(10);
let account_1 = AccountId::from(20);
let initial_balance = T::minimum_balance() + 10.into();
T::set_balance(&account_0, initial_balance);
T::set_balance(&account_1, initial_balance);
let initial_total_issuance = T::total_issuance();
let initial_active_issuance = T::active_issuance();
let initial_dust_trap_balance = match dust_trap.clone() {
Some(dust_trap) => T::total_balance(&dust_trap),
None => T::Balance::zero(),
};
let preservation = Preservation::Expendable;
let transfer_amount = T::Balance::from(11);
T::transfer(&account_0, &account_1, transfer_amount, preservation).unwrap();
assert_eq!(T::total_balance(&account_0), T::Balance::zero());
assert_eq!(T::total_balance(&account_1), initial_balance + transfer_amount);
assert_eq!(T::balance(&account_0), T::Balance::zero());
assert_eq!(T::balance(&account_1), initial_balance + transfer_amount);
match dust_trap {
Some(dust_trap) => {
assert_eq!(T::total_issuance(), initial_total_issuance);
assert_eq!(T::active_issuance(), initial_active_issuance);
assert_eq!(
T::total_balance(&dust_trap),
initial_dust_trap_balance + T::minimum_balance() - 1.into()
);
assert_eq!(
T::balance(&dust_trap),
initial_dust_trap_balance + T::minimum_balance() - 1.into()
);
},
None => {
assert_eq!(
T::total_issuance(),
initial_total_issuance - T::minimum_balance() + 1.into()
);
assert_eq!(
T::active_issuance(),
initial_active_issuance - T::minimum_balance() + 1.into()
);
},
}
}
pub fn transfer_protect_preserve<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
if T::minimum_balance() == T::Balance::zero() {
return
}
let initial_total_issuance = T::total_issuance();
let initial_active_issuance = T::active_issuance();
let account_0 = AccountId::from(0);
let account_1 = AccountId::from(1);
let initial_balance = T::minimum_balance() + 10.into();
T::set_balance(&account_0, initial_balance);
T::set_balance(&account_1, initial_balance);
let preservation = Preservation::Protect;
let transfer_amount = initial_balance;
T::transfer(&account_0, &account_1, transfer_amount, preservation).unwrap_err();
assert_eq!(T::total_balance(&account_0), initial_balance);
assert_eq!(T::total_balance(&account_1), initial_balance);
assert_eq!(T::balance(&account_0), initial_balance);
assert_eq!(T::balance(&account_1), initial_balance);
assert_eq!(T::total_issuance(), initial_total_issuance + initial_balance * 2.into());
assert_eq!(T::active_issuance(), initial_active_issuance + initial_balance * 2.into());
let preservation = Preservation::Preserve;
T::transfer(&account_0, &account_1, transfer_amount, preservation).unwrap_err();
assert_eq!(T::total_balance(&account_0), initial_balance);
assert_eq!(T::total_balance(&account_1), initial_balance);
assert_eq!(T::balance(&account_0), initial_balance);
assert_eq!(T::balance(&account_1), initial_balance);
assert_eq!(T::total_issuance(), initial_total_issuance + initial_balance * 2.into());
assert_eq!(T::active_issuance(), initial_active_issuance + initial_balance * 2.into());
}
pub fn set_balance_mint_success<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let initial_total_issuance = T::total_issuance();
let initial_active_issuance = T::active_issuance();
let account = AccountId::from(10);
let initial_balance = T::minimum_balance() + 10.into();
T::mint_into(&account, initial_balance).unwrap();
let increase_amount: T::Balance = 5.into();
let new = T::set_balance(&account, initial_balance + increase_amount);
let expected_new = initial_balance + increase_amount;
assert_eq!(new, expected_new);
assert_eq!(T::total_balance(&account), expected_new);
assert_eq!(T::balance(&account), expected_new);
assert_eq!(T::total_issuance(), initial_total_issuance + expected_new);
assert_eq!(T::active_issuance(), initial_active_issuance + expected_new);
}
pub fn set_balance_burn_success<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let initial_total_issuance = T::total_issuance();
let initial_active_issuance = T::active_issuance();
let account = AccountId::from(10);
let initial_balance = T::minimum_balance() + 10.into();
T::mint_into(&account, initial_balance).unwrap();
let burn_amount: T::Balance = 5.into();
let new = T::set_balance(&account, initial_balance - burn_amount);
let expected_new = initial_balance - burn_amount;
assert_eq!(new, expected_new);
assert_eq!(T::total_balance(&account), expected_new);
assert_eq!(T::balance(&account), expected_new);
assert_eq!(T::total_issuance(), initial_total_issuance + expected_new);
assert_eq!(T::active_issuance(), initial_active_issuance + expected_new);
}
pub fn can_deposit_success<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let account = AccountId::from(10);
let initial_balance = T::minimum_balance() + 10.into();
T::mint_into(&account, initial_balance).unwrap();
let ret = T::can_deposit(&account, 5.into(), Provenance::Minted);
assert_eq!(ret, DepositConsequence::Success);
}
pub fn can_deposit_below_minimum<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
if T::minimum_balance() < 2.into() {
return
}
let account = AccountId::from(10);
let ret = T::can_deposit(&account, T::minimum_balance() - 1.into(), Provenance::Minted);
assert_eq!(ret, DepositConsequence::BelowMinimum);
}
pub fn can_deposit_overflow<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let account = AccountId::from(10);
let initial_balance = T::Balance::max_value() - 5.into() - T::total_issuance();
T::mint_into(&account, initial_balance).unwrap();
let ret = T::can_deposit(&account, 10.into(), Provenance::Minted);
assert_eq!(ret, DepositConsequence::Overflow);
}
pub fn can_withdraw_success<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let account = AccountId::from(10);
let initial_balance = T::minimum_balance() + 10.into();
T::mint_into(&account, initial_balance).unwrap();
let ret = T::can_withdraw(&account, 5.into());
assert_eq!(ret, WithdrawConsequence::Success);
}
pub fn can_withdraw_reduced_to_zero<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
if T::minimum_balance() == T::Balance::zero() {
return
}
let account = AccountId::from(10);
let initial_balance = T::minimum_balance();
T::mint_into(&account, initial_balance).unwrap();
let ret = T::can_withdraw(&account, 1.into());
assert_eq!(ret, WithdrawConsequence::ReducedToZero(T::minimum_balance() - 1.into()));
}
pub fn can_withdraw_balance_low<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
if T::minimum_balance() == T::Balance::zero() {
return
}
let account = AccountId::from(10);
let other_account = AccountId::from(100);
let initial_balance = T::minimum_balance() + 5.into();
T::mint_into(&account, initial_balance).unwrap();
T::mint_into(&other_account, initial_balance * 2.into()).unwrap();
let ret = T::can_withdraw(&account, initial_balance + 1.into());
assert_eq!(ret, WithdrawConsequence::BalanceLow);
}
pub fn reducible_balance_expendable<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let account = AccountId::from(10);
let initial_balance = T::minimum_balance() + 10.into();
T::mint_into(&account, initial_balance).unwrap();
let ret = T::reducible_balance(&account, Preservation::Expendable, Fortitude::Polite);
assert_eq!(ret, initial_balance);
}
pub fn reducible_balance_protect_preserve<T, AccountId>(_dust_trap: Option<AccountId>)
where
T: Mutate<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let account = AccountId::from(10);
let initial_balance = T::minimum_balance() + 10.into();
T::mint_into(&account, initial_balance).unwrap();
let ret = T::reducible_balance(&account, Preservation::Protect, Fortitude::Polite);
assert_eq!(ret, initial_balance - T::minimum_balance());
let ret = T::reducible_balance(&account, Preservation::Preserve, Fortitude::Polite);
assert_eq!(ret, initial_balance - T::minimum_balance());
}