From 1e2f55a4335665c6b0c2f27063451cdc978f8f3a Mon Sep 17 00:00:00 2001 From: Wu Minzhe Date: Tue, 2 Jul 2019 20:42:46 +0800 Subject: [PATCH] Add some kton tests --- Cargo.lock | 1 + srml/token/kton/Cargo.toml | 2 + srml/token/kton/src/lib.rs | 4 + srml/token/kton/src/mock.rs | 152 ++++++++++++++++++++++ srml/token/kton/src/tests.rs | 245 +++++++++++++++++++++++++++++++++++ 5 files changed, 404 insertions(+) create mode 100644 srml/token/kton/src/mock.rs create mode 100644 srml/token/kton/src/tests.rs diff --git a/Cargo.lock b/Cargo.lock index 3478d32ce..aec854682 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -737,6 +737,7 @@ dependencies = [ "sr-io 2.0.0 (git+https://github.com/paritytech/substrate.git)", "sr-primitives 2.0.0 (git+https://github.com/paritytech/substrate.git)", "sr-std 2.0.0 (git+https://github.com/paritytech/substrate.git)", + "srml-balances 2.0.0 (git+https://github.com/paritytech/substrate.git)", "srml-support 2.0.0 (git+https://github.com/paritytech/substrate.git)", "srml-system 2.0.0 (git+https://github.com/paritytech/substrate.git)", "srml-timestamp 2.0.0 (git+https://github.com/paritytech/substrate.git)", diff --git a/srml/token/kton/Cargo.toml b/srml/token/kton/Cargo.toml index fcda95845..fa06181fc 100644 --- a/srml/token/kton/Cargo.toml +++ b/srml/token/kton/Cargo.toml @@ -16,6 +16,7 @@ system = { package = "srml-system", git = 'https://github.com/paritytech/substra timestamp = { package = "srml-timestamp", git = 'https://github.com/paritytech/substrate.git', default-features = false } substrate-primitives = { git = 'https://github.com/paritytech/substrate.git', default-features = false } dsupport = { package = "evo-support", path = "../../support", default-features = false } +balances = { package = "srml-balances", git = 'https://github.com/paritytech/substrate.git', default-features = false } [dev-dependencies] runtime_io = { package = "sr-io", git = 'https://github.com/paritytech/substrate.git' } @@ -35,4 +36,5 @@ std = [ "timestamp/std", "substrate-primitives/std", "dsupport/std", + "balances/std", ] diff --git a/srml/token/kton/src/lib.rs b/srml/token/kton/src/lib.rs index b1d1a7571..cb126beae 100644 --- a/srml/token/kton/src/lib.rs +++ b/srml/token/kton/src/lib.rs @@ -23,7 +23,11 @@ use dsupport::traits::SystemCurrency; mod imbalance; use imbalance::{NegativeImbalance, PositiveImbalance}; +mod mock; +mod tests; + const DEPOSIT_ID: LockIdentifier = *b"lockkton"; +const DECIMALS: u64 = 1000000000; /// Struct to encode the vesting schedule of an individual account. #[derive(Encode, Decode, Copy, Clone, PartialEq, Eq)] diff --git a/srml/token/kton/src/mock.rs b/srml/token/kton/src/mock.rs new file mode 100644 index 000000000..14f8bfa6e --- /dev/null +++ b/srml/token/kton/src/mock.rs @@ -0,0 +1,152 @@ +#![cfg(test)] +extern crate runtime_io; +use primitives::BuildStorage; +use primitives::{traits::{IdentityLookup}, testing::{Header}}; +use substrate_primitives::{H256, Blake2Hasher}; +use srml_support::impl_outer_origin; +use crate::{GenesisConfig, Module, Trait}; +use super::*; + +impl_outer_origin!{ + pub enum Origin for Test {} +} + +#[derive(Clone, PartialEq, Eq, Debug)] +// Runtime +pub struct Test; + +impl system::Trait for Test { + type Origin = Origin; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = ::primitives::traits::BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type Event = (); +} + +impl timestamp::Trait for Test { + type Moment = u64; + type OnTimestampSet = (); +} + + +impl balances::Trait for Test { + type Balance = u64; + type OnFreeBalanceZero = (); + type OnNewAccount = (); + type Event = (); + type TransactionPayment = (); + type TransferPayment = (); + type DustRemoval = (); +} + +impl Trait for Test { + type Balance = u64; + type Currency = balances::Module; + type Event = (); + type OnMinted = (); + type OnRemoval = (); + type SystemRefund = (); +} + +pub struct ExtBuilder { + transaction_base_fee: u64, + transaction_byte_fee: u64, + existential_deposit: u64, + transfer_fee: u64, + creation_fee: u64, + sys_acc: u64, +} + +impl Default for ExtBuilder { + fn default() -> Self { + Self { + transaction_base_fee: 0, + transaction_byte_fee: 0, + existential_deposit: 0, + transfer_fee: 0, + creation_fee: 0, + sys_acc: 0 + } + } +} + +impl ExtBuilder { + pub fn existential_deposit(mut self, existential_deposit: u64) -> Self { + self.existential_deposit = existential_deposit; + self + } + + #[allow(dead_code)] + pub fn transfer_fee(mut self, transfer_fee: u64) -> Self { + self.transfer_fee = transfer_fee; + self + } + pub fn creation_fee(mut self, creation_fee: u64) -> Self { + self.creation_fee = creation_fee; + self + } + pub fn transaction_fees(mut self, base_fee: u64, byte_fee: u64) -> Self { + self.transaction_base_fee = base_fee; + self.transaction_byte_fee = byte_fee; + self + } + + + pub fn build(self) -> runtime_io::TestExternalities { + let (mut t, mut c) = system::GenesisConfig::::default().build_storage().unwrap(); + let balance_factor = if self.existential_deposit > 0 { + 1000 * DECIMALS + } else { + 1 * DECIMALS + }; + + let _ = timestamp::GenesisConfig:: { + minimum_period: 5, + }.assimilate_storage(&mut t, &mut c); + + let _ = balances::GenesisConfig:: { + balances: vec![ + (1, 10 * balance_factor), + (2, 20 * balance_factor), + (3, 300 * balance_factor), + (4, 400 * balance_factor), + (10, balance_factor), + (11, balance_factor * 1000), // 1 m + (20, balance_factor), + (21, balance_factor * 2000), // 2 m + (30, balance_factor), + (31, balance_factor * 2000), // 2 m + (40, balance_factor), + (41, balance_factor * 2000), // 2 m + (100, 200000 * balance_factor), + (101, 200000 * balance_factor), + ], + transaction_base_fee: self.transaction_base_fee, + transaction_byte_fee: self.transaction_byte_fee, + existential_deposit: self.existential_deposit, + transfer_fee: self.transfer_fee, + creation_fee: self.creation_fee, + vesting: vec![], + }.assimilate_storage(&mut t, &mut c); + + let _ = GenesisConfig:: { + sys_acc: 42, + balances: vec![ + (1, 10 * balance_factor), + ], + vesting: vec![], + }.assimilate_storage(&mut t, &mut c); + + t.into() + + } +} + +pub type System = system::Module; +pub type Ring = balances::Module; +pub type Timestamp = timestamp::Module; +pub type Kton = Module; diff --git a/srml/token/kton/src/tests.rs b/srml/token/kton/src/tests.rs new file mode 100644 index 000000000..886706907 --- /dev/null +++ b/srml/token/kton/src/tests.rs @@ -0,0 +1,245 @@ +#![cfg(test)] + +use mock::{ExtBuilder, Kton, Origin, Ring, System, Test, Timestamp}; +use balances::BalanceLock; +use runtime_io::with_externalities; +use srml_support::{assert_err, assert_noop, assert_ok}; +use srml_support::traits::{ Currency, Imbalance }; + +use super::*; + +#[inline] +fn compute_dividend_of(acc: u64) -> i128 { + let kton_balance = Kton::free_balance(&acc) as u64; + let paid_out = Kton::reward_paid_out(&acc); + let reward_per_share = Kton::reward_per_share() as u64; + let should_withdraw = i128::from(reward_per_share * kton_balance) - paid_out; + should_withdraw +} + +#[inline] +fn set_reward_per_share_hundred(acc: u64) { + Kton::deposit(Origin::signed(acc), 100000 * DECIMALS, 36); + // now acc has 36 unit kton + // 360 of 1200 flow into ktoner pool + // Kton::transfer_to_system(Origin::signed(101), 3600 * DECIMALS); + // reward_per_share = 3600 / 36 = 100 + // assert_eq!(Kton::reward_per_share(), 100 * DECIMALS); +} + + +#[test] +fn ext_builer_should_work() { + // test existential_deposit setting + with_externalities(&mut ExtBuilder::default() + .existential_deposit(0).build(), || { + assert_eq!(Ring::free_balance(&1), 10 * DECIMALS); + }); + + with_externalities(&mut ExtBuilder::default() + .existential_deposit(1).build(), || { + assert_eq!(Ring::free_balance(&1), 10000 * DECIMALS); + }); +} + +#[test] +fn check_sys_acc() { + with_externalities(&mut ExtBuilder::default() + .build(), || { + let sys_acc = Kton::sys_acc(); + assert_eq!(sys_acc, 42_u64); + }); +} + +#[test] +fn test_reward_to_pot() { + with_externalities(&mut ExtBuilder::default() + .build(), || { + assert_eq!(Kton::total_issuance(), 10 * DECIMALS); + + let sys_acc = Kton::sys_acc(); + assert_eq!(Ring::total_issuance(), 407734 * DECIMALS); + assert_eq!(Kton::system_revenue(&sys_acc), 0); + + Kton::reward_to_pot(10 * DECIMALS); + assert_eq!(Ring::total_issuance(), 407744 * DECIMALS); + assert_eq!(Kton::system_revenue(&sys_acc), 10 * DECIMALS); + assert_eq!(Kton::reward_per_share(), 1); + + Kton::reward_to_pot(10 * DECIMALS); + assert_eq!(Ring::total_issuance(), 407754 * DECIMALS); + assert_eq!(Kton::system_revenue(&sys_acc), 20 * DECIMALS); + assert_eq!(Kton::reward_per_share(), 2); + }); +} + +#[test] +fn test_set_free_balance() { + with_externalities(&mut ExtBuilder::default() + .build(), || { + assert_eq!(Kton::total_issuance(), 10 * DECIMALS); + assert_eq!(Kton::free_balance(&11), 0); + + // 某个账户的余额变动后,total issuance要不要也改变? + Kton::set_free_balance(&11, 10 * DECIMALS); + assert_eq!(Kton::free_balance(&11), 10 * DECIMALS); + assert_eq!(Kton::total_issuance(), 20 * DECIMALS); + }); +} + +#[test] +fn test_make_free_balance_be() { + with_externalities(&mut ExtBuilder::default() + .build(), || { + assert_eq!(Kton::free_balance(&1), 10 * DECIMALS); + assert_eq!(Kton::reward_paid_out(&1), 0); + + >::put(1); + Kton::make_free_balance_be(&1, 10 * DECIMALS); + assert_eq!(Kton::free_balance(&1), 10 * DECIMALS); + assert_eq!(Kton::reward_paid_out(&1), (10 * DECIMALS) as i128); + + // 重设RewardPerShare后,再次调用make_free_balance_be后,这个账户上的奖励 + // 包不包含之前给的奖励? + >::put(3); + Kton::make_free_balance_be(&1, 10 * DECIMALS); + assert_eq!(Kton::free_balance(&1), 10 * DECIMALS); + assert_eq!(Kton::reward_paid_out(&1), (30 * DECIMALS) as i128); + }); +} + +#[test] +fn check_deposit_ring_related_balance() { + with_externalities(&mut ExtBuilder::default() + .build(), || { + Kton::deposit(Origin::signed(100), 10000 * DECIMALS, 12); + + let kton_balance = Kton::free_balance(&100); + assert_eq!(kton_balance, 1 * DECIMALS); + + Kton::deposit(Origin::signed(101), 100000 * DECIMALS, 36); + assert_eq!(Kton::free_balance(&101), 36 * DECIMALS); + }); +} + +//#[test] +//fn check_deposit_status() { +// with_externalities(&mut ExtBuilder::default() +// .existential_deposit(1).build(), || { +// // the initial free_balance of 11 is 100; +// Kton::deposit(Origin::signed(11), 100000, 36); +// // ensure locked ring can not be withdrew +// // 900001 = 1000k - 100k +// assert_eq!(Kton::free_balance(&11), 36); +// // lock liquidity +// assert_noop!(Ring::transfer(Origin::signed(11), 1001, 900001), "account liquidity restrictions prevent withdrawal"); +// +// let now = Timestamp::now(); +// // check deposit info +// assert_eq!(Kton::deposit_ledger(&11), Some(Deposit { +// total_deposit: 100000, +// deposit_list: vec![DepositInfo { +// month: 36, +// start_at: now, +// value: 100000, +// unit_interest: 0, +// claimed: false, +// }], +// })); +// +// // check ring locks +// assert_eq!(Ring::locks(&11), vec![ring::BalanceLock { id: DEPOSIT_ID, amount: 100000_u64, until: u64::max_value(), reasons: WithdrawReasons::all() }]); +// +// Kton::deposit(Origin::signed(11), 200000, 36); +// assert_eq!(Kton::free_balance(&11), 108); +// assert_eq!(Kton::total_issuance(), 108); +// +// assert_eq!(Kton::deposit_ledger(&11), Some(Deposit { +// total_deposit: 300000, +// deposit_list: vec![ +// DepositInfo { +// month: 36, +// start_at: now, +// value: 100000, +// unit_interest: 0, +// claimed: false, +// }, +// DepositInfo { +// month: 36, +// start_at: now, +// value: 200000, +// unit_interest: 0, +// claimed: false, +// }], +// })); +// +// // check ring locks +// assert_eq!(Ring::locks(&11), vec![ring::BalanceLock { id: DEPOSIT_ID, amount: 300000_u64, until: u64::max_value(), reasons: WithdrawReasons::all() }]); +// }, +// ); +//} +// +//#[test] +//fn check_reward_per_share() { +// with_externalities(&mut ExtBuilder::default() +// .existential_deposit(1).build(), || { +// Kton::deposit(Origin::signed(11), 100000, 36); +// // now acc 11 has 36 unit kton +// // 360 of 1200 flow into ktoner pool +// Kton::transfer_to_system(Origin::signed(101), 360); +// // reward_per_share = 360 / 36 = 10 +// assert_eq!(Kton::reward_per_share(), 10); +// // kton total_issurance = 72 +// // kton_balance of acc 101 is 36 +// Kton::deposit(Origin::signed(101), 100000, 36); +// // 720 of 2400 flow into ktoner pool +// Kton::transfer_to_system(Origin::signed(11), 720); +// // reward_per_share = 10 + 720 / 72 = 20 +// assert_eq!(Kton::reward_per_share(), 20); +// // old_price * new_balance = 10 * 36 = 360 +// assert_eq!(Kton::reward_paidout(&101), 360); +// +// // acc 11 should withdraw 360 ring as reward +// assert_eq!(compute_dividend_of(101), 360_i128); +// +// Kton::transfer(Origin::signed(101), 2, 36); +// assert_eq!(Kton::free_balance(&101), 0); +// assert_eq!(Kton::free_balance(&2), 36); +// // after transfer, reward stick to these ktons +// // still belongs to acc 11, not acc 2 +// assert_eq!(compute_dividend_of(101), 360_i128); +// assert_eq!(compute_dividend_of(2), 0_i128); +// }); +//} +// +//#[test] +//fn check_acc_claim_reward() { +// with_externalities(&mut ExtBuilder::default() +// .existential_deposit(1).build(), || { +// +// let ring_total_issuance = Ring::total_issuance(); +// set_reward_per_share_hundred(11); +// // now reward_per_share is 100 +// // acc 11 has 1 kton +// assert_eq!(compute_dividend_of(11), 3600); +// // no change on total_issuance of ring +// assert_eq!(Ring::total_issuance(), ring_total_issuance); +// // air drop 1000 ring to acc 101 +// // note: -1000 +// >::insert(&101, -1000); +// let ring_balance_acc_101 = Ring::free_balance(&101); +// assert_eq!(compute_dividend_of(101), 1000); +// +// Kton::claim_reward(Origin::signed(101)); +// assert_eq!(Ring::free_balance(&101), ring_balance_acc_101); +// +// // air drop 10000 ring to acc 12 +// >::insert(&12, -10000); +// let ring_balance_acc_12 = Ring::free_balance(&12); +// assert_eq!(compute_dividend_of(12), 10000); +// Kton::claim_reward(Origin::signed(12)); +// assert_eq!(Ring::free_balance(&12), ring_balance_acc_12 + 9000); +// }); +//} +// +//