Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
add tests for accounts module
  • Loading branch information
wangjj9219 committed Jan 20, 2020
commit eaef70e9d49cc2cabb1cd55c07def0a7d71c91bf
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions modules/accounts/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pallet-transaction-payment = { git = "https://github.com/paritytech/substrate.gi
primitives = { package = "sp-core", git = "https://github.com/paritytech/substrate.git", default-features = false }
runtime-io = { package = "sp-io", git = "https://github.com/paritytech/substrate.git", default-features = false }
pallet-balances= { package = "pallet-balances", git = "https://github.com/paritytech/substrate.git", default-features = false }
pallet-timestamp= { package = "pallet-timestamp", git = "https://github.com/paritytech/substrate.git", default-features = false }


[features]
Expand Down
69 changes: 11 additions & 58 deletions modules/accounts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ use frame_support::{
IsSubType, Parameter,
};
use orml_traits::MultiCurrency;
use rstd::prelude::*;
use sp_runtime::{
traits::{Convert, SaturatedConversion, Saturating, SignedExtension, Zero},
traits::{SaturatedConversion, Saturating, SignedExtension, Zero},
transaction_validity::{
InvalidTransaction, TransactionPriority, TransactionValidity, TransactionValidityError, ValidTransaction,
},
};
//use support::{Ratio};
use rstd::prelude::*;

mod mock;
mod tests;

//type BalanceOf<T> = <<T as Trait>::Currency as MultiCurrency<<T as system::Trait>::AccountId>>::Balance;
type MomentOf<T> = <<T as Trait>::Time as Time>::Moment;
Expand Down Expand Up @@ -83,55 +85,6 @@ impl<T: Trait + Send + Sync> ChargeTransactionPayment<T> {
pub fn from(fee: PalletBalanceOf<T>) -> Self {
Self(fee)
}

/// Compute the final fee value for a particular transaction.
///
/// The final fee is composed of:
/// - _base_fee_: This is the minimum amount a user pays for a transaction.
/// - _len_fee_: This is the amount paid merely to pay for size of the transaction.
/// - _weight_fee_: This amount is computed based on the weight of the transaction. Unlike
/// size-fee, this is not input dependent and reflects the _complexity_ of the execution
/// and the time it consumes.
/// - _targeted_fee_adjustment_: This is a multiplier that can tune the final fee based on
/// the congestion of the network.
/// - (optional) _tip_: if included in the transaction, it will be added on top. Only signed
/// transactions can have a tip.
///
/// final_fee = base_fee + targeted_fee_adjustment(len_fee + weight_fee) + tip;
fn compute_fee(
len: u32,
info: <Self as SignedExtension>::DispatchInfo,
tip: PalletBalanceOf<T>,
) -> PalletBalanceOf<T>
where
PalletBalanceOf<T>: Sync + Send,
{
if info.pays_fee {
let len = <PalletBalanceOf<T>>::from(len);
let per_byte = <T as pallet_transaction_payment::Trait>::TransactionByteFee::get();
let len_fee = per_byte.saturating_mul(len);

let weight_fee = {
// cap the weight to the maximum defined in runtime, otherwise it will be the `Bounded`
// maximum of its data type, which is not desired.
let capped_weight = info.weight.min(<T as system::Trait>::MaximumBlockWeight::get());
<T as pallet_transaction_payment::Trait>::WeightToFee::convert(capped_weight)
};

// the adjustable part of the fee
let adjustable_fee = len_fee.saturating_add(weight_fee);
let targeted_fee_adjustment = <pallet_transaction_payment::Module<T>>::next_fee_multiplier();
// adjusted_fee = adjustable_fee + (adjustable_fee * targeted_fee_adjustment)
let adjusted_fee = targeted_fee_adjustment.saturated_multiply_accumulate(adjustable_fee);

let base_fee = <T as pallet_transaction_payment::Trait>::TransactionBaseFee::get();
let final_fee = base_fee.saturating_add(adjusted_fee).saturating_add(tip);

final_fee
} else {
tip
}
}
}

impl<T: Trait + Send + Sync> rstd::fmt::Debug for ChargeTransactionPayment<T> {
Expand Down Expand Up @@ -165,12 +118,16 @@ where
info: Self::DispatchInfo,
len: usize,
) -> TransactionValidity {
// pay any fees.
let tip = self.0;
let fee: PalletBalanceOf<T> =
pallet_transaction_payment::ChargeTransactionPayment::<T>::compute_fee(len as u32, info, tip);

// check call type
let call = match call.is_sub_type() {
Some(call) => call,
None => return Ok(ValidTransaction::default()),
};

// check call type
let skip_pay_fee = match call {
orml_currencies::Call::transfer(..) => {
// call try_free_transfer
Expand All @@ -183,10 +140,6 @@ where
_ => false,
};

// pay any fees.
let tip = self.0;
let fee: PalletBalanceOf<T> = Self::compute_fee(len as u32, info, tip);

// skip payment withdraw if match conditions
if !skip_pay_fee {
let imbalance = match <T as pallet_transaction_payment::Trait>::Currency::withdraw(
Expand Down
168 changes: 168 additions & 0 deletions modules/accounts/src/mock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
//! Mocks for the cdp treasury module.

#![cfg(test)]

use super::*;
use frame_support::{impl_outer_dispatch, impl_outer_origin, parameter_types};
use primitives::H256;
use sp_runtime::{
testing::Header,
traits::{ConvertInto, IdentityLookup},
Perbill,
};

impl_outer_origin! {
pub enum Origin for Runtime {}
}

impl_outer_dispatch! {
pub enum Call for Runtime where origin: Origin {
orml_currencies::Currencies,
}
}

parameter_types! {
pub const BlockHashCount: u64 = 250;
pub const MaximumBlockWeight: u32 = 1024;
pub const MaximumBlockLength: u32 = 2 * 1024;
pub const AvailableBlockRatio: Perbill = Perbill::one();
pub const ExistentialDeposit: u64 = 0;
pub const TransferFee: u64 = 0;
pub const CreationFee: u64 = 2;
pub const GetNativeCurrencyId: CurrencyId = ACA;
}

pub type AccountId = u64;
pub type BlockNumber = u64;
pub type Balance = u64;
pub type Amount = i64;
pub type CurrencyId = u32;
pub type Moment = u64;

pub const ALICE: AccountId = 0;
pub const BOB: AccountId = 1;
pub const ACA: CurrencyId = 0;
pub const AUSD: CurrencyId = 1;
pub const BTC: CurrencyId = 2;

#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Runtime;

impl system::Trait for Runtime {
type Origin = Origin;
type Index = u64;
type BlockNumber = BlockNumber;
type Call = ();
type Hash = H256;
type Hashing = ::sp_runtime::traits::BlakeTwo256;
type AccountId = AccountId;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type Event = ();
type BlockHashCount = BlockHashCount;
type MaximumBlockWeight = MaximumBlockWeight;
type MaximumBlockLength = MaximumBlockLength;
type AvailableBlockRatio = AvailableBlockRatio;
type Version = ();
type ModuleToIndex = ();
}

impl orml_tokens::Trait for Runtime {
type Event = ();
type Balance = Balance;
type Amount = Amount;
type CurrencyId = CurrencyId;
type ExistentialDeposit = ExistentialDeposit;
type DustRemoval = ();
}
pub type Tokens = orml_tokens::Module<Runtime>;

impl pallet_balances::Trait for Runtime {
type Balance = Balance;
type OnFreeBalanceZero = ();
type OnNewAccount = ();
type OnReapAccount = ();
type TransferPayment = ();
type DustRemoval = ();
type Event = ();
type ExistentialDeposit = ExistentialDeposit;
type TransferFee = TransferFee;
type CreationFee = CreationFee;
}
pub type PalletBalances = pallet_balances::Module<Runtime>;

pub type AdaptedBasicCurrency = orml_currencies::BasicCurrencyAdapter<Runtime, PalletBalances, Balance>;

impl orml_currencies::Trait for Runtime {
type Event = ();
type MultiCurrency = Tokens;
type NativeCurrency = AdaptedBasicCurrency;
type GetNativeCurrencyId = GetNativeCurrencyId;
}
pub type Currencies = orml_currencies::Module<Runtime>;

parameter_types! {
pub const MinimumPeriod: Moment = 5;
}

impl pallet_timestamp::Trait for Runtime {
type Moment = Moment;
type OnTimestampSet = ();
type MinimumPeriod = MinimumPeriod;
}
pub type TimeModule = pallet_timestamp::Module<Runtime>;

parameter_types! {
pub const TransactionBaseFee: Balance = 0;
pub const TransactionByteFee: Balance = 2;
}

impl pallet_transaction_payment::Trait for Runtime {
type Currency = PalletBalances;
type OnTransactionPayment = ();
type TransactionBaseFee = TransactionBaseFee;
type TransactionByteFee = TransactionByteFee;
type WeightToFee = ConvertInto;
type FeeMultiplierUpdate = ();
}
pub type PalletTransactionPayment = pallet_transaction_payment::Module<Runtime>;

parameter_types! {
pub const FreeTransferCount: u8 = 3;
pub const FreeTransferPeriod: Moment = 100;
}

impl Trait for Runtime {
type FreeTransferCount = FreeTransferCount;
type FreeTransferPeriod = FreeTransferPeriod;
type Time = TimeModule;
type Currency = Currencies;
type Call = Call;
}
pub type Accounts = Module<Runtime>;

pub struct ExtBuilder {
endowed_accounts: Vec<(AccountId, CurrencyId, Balance)>,
}

impl Default for ExtBuilder {
fn default() -> Self {
Self {
endowed_accounts: vec![(ALICE, ACA, 1000), (ALICE, AUSD, 1000), (ALICE, BTC, 1000)],
}
}
}

impl ExtBuilder {
pub fn build(self) -> runtime_io::TestExternalities {
let mut t = system::GenesisConfig::default().build_storage::<Runtime>().unwrap();

orml_tokens::GenesisConfig::<Runtime> {
endowed_accounts: self.endowed_accounts,
}
.assimilate_storage(&mut t)
.unwrap();

t.into()
}
}
40 changes: 40 additions & 0 deletions modules/accounts/src/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//! Unit tests for the accounts module.

#![cfg(test)]

use super::*;
use frame_support::{assert_noop, assert_ok};
use mock::{Accounts, Currencies, ExtBuilder, Origin, Runtime, TimeModule, ALICE, AUSD, BOB, BTC};
use sp_runtime::traits::OnFinalize;

#[test]
fn try_free_transfer_over_cap() {
ExtBuilder::default().build().execute_with(|| {
assert_eq!(TimeModule::now(), 0);
assert_eq!(Accounts::last_free_transfers(ALICE), vec![]);
assert_eq!(Accounts::try_free_transfer(&ALICE), true);
assert_eq!(Accounts::last_free_transfers(ALICE), vec![0]);
assert_eq!(Accounts::try_free_transfer(&ALICE), true);
assert_eq!(Accounts::last_free_transfers(ALICE), vec![0, 0]);
assert_eq!(Accounts::try_free_transfer(&ALICE), true);
assert_eq!(Accounts::last_free_transfers(ALICE), vec![0, 0, 0]);
assert_eq!(Accounts::try_free_transfer(&ALICE), false);
assert_eq!(Accounts::last_free_transfers(ALICE), vec![0, 0, 0]);
});
}

#[test]
fn remove_expired_entry() {
ExtBuilder::default().build().execute_with(|| {
assert_eq!(TimeModule::now(), 0);
assert_eq!(Accounts::last_free_transfers(ALICE), vec![]);
assert_eq!(Accounts::try_free_transfer(&ALICE), true);
assert_eq!(Accounts::try_free_transfer(&ALICE), true);
assert_eq!(Accounts::try_free_transfer(&ALICE), true);
assert_eq!(Accounts::last_free_transfers(ALICE), vec![0, 0, 0]);
assert_ok!(TimeModule::dispatch(pallet_timestamp::Call::set(100), Origin::NONE));
assert_eq!(TimeModule::now(), 100);
assert_eq!(Accounts::try_free_transfer(&ALICE), true);
assert_eq!(Accounts::last_free_transfers(ALICE), vec![100]);
});
}
5 changes: 0 additions & 5 deletions modules/cdp_treasury/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use super::*;
use frame_support::{impl_outer_origin, parameter_types};
use primitives::H256;
use sp_runtime::{testing::Header, traits::IdentityLookup, Perbill};
use support::Rate;

impl_outer_origin! {
pub enum Origin for Runtime {}
Expand All @@ -22,10 +21,6 @@ parameter_types! {
pub const CreationFee: u64 = 2;
pub const GetStableCurrencyId: CurrencyId = AUSD;
pub const GetNativeCurrencyId: CurrencyId = ACA;
pub const MinimumIncrementSize: Rate = Rate::from_rational(1, 20);
pub const AuctionTimeToClose: u64 = 100;
pub const AuctionDurationSoftCap: u64 = 2000;
pub const GetAmountAdjustment: Rate = Rate::from_rational(1, 2);
}

pub type AccountId = u64;
Expand Down