From 81ab7f5e11e98e083adcfbc3ed3f5e3a61d2fed7 Mon Sep 17 00:00:00 2001 From: Wu Minzhe Date: Fri, 26 Jul 2019 10:41:31 +0800 Subject: [PATCH] extract reward module --- Cargo.lock | 21 ++ Cargo.toml | 1 + node/cli/src/chain_spec.rs | 28 ++- node/runtime/Cargo.toml | 3 +- node/runtime/src/lib.rs | 5 + node/runtime/wasm/Cargo.lock | 1 + srml/kton/src/lib.rs | 274 ++----------------------- srml/reward/Cargo.toml | 43 ++++ srml/reward/src/lib.rs | 312 +++++++++++++++++++++++++++++ srml/{kton => reward}/src/mock.rs | 3 +- srml/{kton => reward}/src/tests.rs | 116 +++++------ srml/staking/Cargo.toml | 2 + srml/staking/src/lib.rs | 8 +- srml/try/Cargo.toml | 2 +- 14 files changed, 487 insertions(+), 332 deletions(-) create mode 100644 srml/reward/Cargo.toml create mode 100644 srml/reward/src/lib.rs rename srml/{kton => reward}/src/mock.rs (98%) rename srml/{kton => reward}/src/tests.rs (70%) diff --git a/Cargo.lock b/Cargo.lock index b13fc4f3e..40a0d1301 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -746,6 +746,26 @@ dependencies = [ "substrate-primitives 2.0.0 (git+https://github.com/paritytech/substrate.git)", ] +[[package]] +name = "evo-reward" +version = "0.1.0" +dependencies = [ + "evo-support 0.1.0", + "node-runtime 0.1.0", + "parity-codec 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "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)", + "substrate-keyring 2.0.0 (git+https://github.com/paritytech/substrate.git)", + "substrate-primitives 2.0.0 (git+https://github.com/paritytech/substrate.git)", +] + [[package]] name = "evo-staking" version = "0.1.0" @@ -2227,6 +2247,7 @@ name = "node-runtime" version = "0.1.0" dependencies = [ "evo-kton 0.1.0", + "evo-reward 0.1.0", "evo-staking 0.1.0", "integer-sqrt 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "node-primitives 2.0.0", diff --git a/Cargo.toml b/Cargo.toml index bd3b7b5c4..82cf4892f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,6 +60,7 @@ members = [ "srml/support", "srml/aura", "srml/try", + "srml/reward", ] exclude = ["node/runtime/wasm"] diff --git a/node/cli/src/chain_spec.rs b/node/cli/src/chain_spec.rs index d5db35409..b142a65f5 100644 --- a/node/cli/src/chain_spec.rs +++ b/node/cli/src/chain_spec.rs @@ -25,6 +25,7 @@ use node_runtime::{ Perbill, SECS_PER_BLOCK, KtonConfig, SessionConfig, SessionKeys, StakerStatus, StakingConfig, SudoConfig, SystemConfig, TimestampConfig, + RewardConfig, }; pub use node_runtime::GenesisConfig; use primitives::{crypto::UncheckedInto, ed25519, Pair, sr25519}; @@ -109,12 +110,7 @@ fn staging_testnet_config_genesis() -> GenesisConfig { vesting: vec![], }), kton: Some(KtonConfig { - ring_balances: endowed_accounts.iter().cloned() - .map(|k| (k, ENDOWMENT, 12)) - .chain(initial_authorities.iter().map(|x| (x.0.clone(), ENDOWMENT, 12))) - .collect(), vesting: vec![], - sys_acc: hex!["984d592d15d930ac36e6716407fbed3f7d1e2e62bc11f8429345f8b8b0dfc107"].unchecked_into(), }), indices: Some(IndicesConfig { ids: endowed_accounts.iter().cloned() @@ -153,6 +149,15 @@ fn staging_testnet_config_genesis() -> GenesisConfig { grandpa: Some(GrandpaConfig { authorities: initial_authorities.iter().map(|x| (x.3.clone(), 1)).collect(), }), + reward: Some(RewardConfig { + ring_balances: endowed_accounts.iter().cloned() + .map(|k| (k, ENDOWMENT, 12)) + .chain(initial_authorities.iter().map(|x| (x.0.clone(), ENDOWMENT, 12))) + .collect(), + + sys_acc: hex!["984d592d15d930ac36e6716407fbed3f7d1e2e62bc11f8429345f8b8b0dfc107"].unchecked_into(), + }), + } } @@ -242,12 +247,7 @@ pub fn testnet_genesis( vesting: vec![], }), kton: Some(KtonConfig { - ring_balances: endowed_accounts.iter().cloned() - .map(|k| (k, ENDOWMENT, 12)) - .chain(initial_authorities.iter().map(|x| (x.0.clone(), ENDOWMENT, 12))) - .collect(), vesting: vec![], - sys_acc: hex!["984d592d15d930ac36e6716407fbed3f7d1e2e62bc11f8429345f8b8b0dfc107"].unchecked_into(), }), session: Some(SessionConfig { validators: initial_authorities.iter().map(|x| x.1.clone()).collect(), @@ -285,6 +285,14 @@ pub fn testnet_genesis( grandpa: Some(GrandpaConfig { authorities: initial_authorities.iter().map(|x| (x.3.clone(), 1)).collect(), }), + reward: Some(RewardConfig { + ring_balances: endowed_accounts.iter().cloned() + .map(|k| (k, ENDOWMENT, 12)) + .chain(initial_authorities.iter().map(|x| (x.0.clone(), ENDOWMENT, 12))) + .collect(), + + sys_acc: hex!["984d592d15d930ac36e6716407fbed3f7d1e2e62bc11f8429345f8b8b0dfc107"].unchecked_into(), + }), } } diff --git a/node/runtime/Cargo.toml b/node/runtime/Cargo.toml index 1a769ff07..f0e2b463e 100644 --- a/node/runtime/Cargo.toml +++ b/node/runtime/Cargo.toml @@ -41,7 +41,7 @@ substrate-keyring = { git = 'https://github.com/paritytech/substrate.git', optio kton = { package = "evo-kton", path = '../../srml/kton', default-features = false} staking = { package = "evo-staking", path = "../../srml/staking", default-features = false} aura = { package = "srml-aura", path = "../../srml/aura", default-features = false } -#aura = { package = "srml-aura", path = "../../srml/aura", default-features = false} +reward = { package = "evo-reward", path = "../../srml/reward", default-features = false} [features] default = ["std"] @@ -80,4 +80,5 @@ std = [ "substrate-keyring", "offchain-primitives/std", "kton/std", + "reward/std", ] diff --git a/node/runtime/src/lib.rs b/node/runtime/src/lib.rs index 7422db1c0..ebd118bfc 100644 --- a/node/runtime/src/lib.rs +++ b/node/runtime/src/lib.rs @@ -175,6 +175,11 @@ impl kton::Trait for Runtime { type SystemRefund = (); } +impl reward::Trait for Runtime { + type Currency = Kton; + type RewardCurrency = Balances; + type Event = Event; +} impl timestamp::Trait for Runtime { type Moment = u64; diff --git a/node/runtime/wasm/Cargo.lock b/node/runtime/wasm/Cargo.lock index 4a9814c1b..667b5c065 100644 --- a/node/runtime/wasm/Cargo.lock +++ b/node/runtime/wasm/Cargo.lock @@ -516,6 +516,7 @@ dependencies = [ "parity-codec 4.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "safe-mix 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "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-support 2.0.0 (git+https://github.com/paritytech/substrate.git)", diff --git a/srml/kton/src/lib.rs b/srml/kton/src/lib.rs index fbcba5597..9e3b84195 100644 --- a/srml/kton/src/lib.rs +++ b/srml/kton/src/lib.rs @@ -16,17 +16,12 @@ use srml_support::traits::{ }; use substrate_primitives::U256; use system::ensure_signed; - -#[cfg(feature = "std")] -use runtime_io::with_storage; +use dsupport::traits::OnAccountBalanceChanged; // customed -use dsupport::traits::SystemCurrency; use imbalance::{NegativeImbalance, PositiveImbalance}; mod imbalance; -mod mock; -mod tests; const DEPOSIT_ID: LockIdentifier = *b"lockkton"; @@ -108,15 +103,8 @@ decl_event!( Currency = CurrencyOf, Moment = < T as timestamp::Trait>::Moment, { - /// lock ring for getting kton - /// Balance is for kton - /// Currency is for ring - NewDeposit(Moment, AccountId, Balance, Currency), /// Transfer succeeded (from, to, value, fees). TokenTransfer(AccountId, AccountId, Balance), - /// Claim Reward - RewardClaim(AccountId, Currency), - WithdrawDeposit(AccountId, Currency, Moment, bool), } ); @@ -124,20 +112,6 @@ decl_event!( decl_storage! { trait Store for Module as Kton { - pub DepositLedger get(deposit_ledger): map T::AccountId => Option, T::Balance, T::Moment>>; - - // reward you can get per kton - pub RewardPerShare get(reward_per_share): CurrencyOf; - // reward already paid to each ktoner - pub RewardPaidOut get(reward_paid_out): map T::AccountId => i128; - - pub SysAcc get(sys_acc) config(): T::AccountId; - - /// system revenue - /// same to balance in ring - /// TODO: it's ugly, ready for hacking - pub SysRevenuePot get(system_revenue): map T::AccountId => CurrencyOf; - /// For Currency and LockableCurrency Trait /// The total `units issued in the system. // like `existential_deposit`, but always set to 0 @@ -156,26 +130,7 @@ decl_storage! { pub Vesting get(vesting): map T::AccountId => Option>; } add_extra_genesis { - // for ring - config(ring_balances): Vec<(T::AccountId, CurrencyOf, u32)>; config(vesting): Vec <(T::AccountId, T::BlockNumber, T::BlockNumber)>; - build( | - storage: & mut primitives::StorageOverlay, - _: & mut primitives::ChildrenStorageOverlay, - config: & GenesisConfig - | { - with_storage(storage, || { - for &(ref depositor, balance, months) in &config.ring_balances { - assert!(T::Currency::free_balance(&depositor) >= balance); - let _ = >::deposit( - T::Origin::from(Some(depositor.clone()).into()), - balance, - months - ); - - } - }); - }); } } @@ -183,56 +138,6 @@ decl_module! { pub struct Module for enum Call where origin: T::Origin { fn deposit_event() = default; - - pub fn deposit(origin, value: CurrencyOf, months: u32) { - ensure!(!months.is_zero() && months <= 36, "months must be at least 1"); - let transactor = ensure_signed(origin)?; - if >::exists(&transactor) { - return Err("Already deposited."); - } - - let free_currency = T::Currency::free_balance(&transactor); - let value = value.min(free_currency); - - let now = >::now(); - - let kton_return = Self::compute_kton_balance(months, value).unwrap(); - - let individual_deposit = IndividualDeposit {month: months, start_at: now.clone(), value: value, balance: kton_return, claimed: false}; - let deposit = Deposit {total: value, deposit_list: vec![individual_deposit]}; - - Self::update_deposit(&transactor, &deposit); - - let positive_imbalance = Self::deposit_creating(&transactor, kton_return); - T::OnMinted::on_unbalanced(positive_imbalance); - Self::deposit_event(RawEvent::NewDeposit(now, transactor, kton_return, value)); - } - - - fn deposit_extra(origin, additional_value: CurrencyOf, months: u32) { - ensure!(!months.is_zero() && months <= 36, "months must be at least 1"); - let transactor = ensure_signed(origin)?; - let mut deposit = Self::deposit_ledger(&transactor).ok_or("Use fn deposit instead.")?; - - let now = >::now(); - let free_currency = T::Currency::free_balance(&transactor); - - if let Some(extra) = free_currency.checked_sub(&deposit.total) { - let extra = extra.min(additional_value); - deposit.total += extra; - - let kton_return = Self::compute_kton_balance(months, extra).unwrap(); - let individual_deposit = IndividualDeposit {month: months, start_at: now.clone(), value: extra.clone(), balance: kton_return, claimed: false}; - deposit.deposit_list.push(individual_deposit); - Self::update_deposit(&transactor, &deposit); - - let positive_imbalance = Self::deposit_creating(&transactor, kton_return); - T::OnMinted::on_unbalanced(positive_imbalance); - Self::deposit_event(RawEvent::NewDeposit(now, transactor, kton_return, extra)); - } - } - - pub fn transfer(origin, dest: ::Source, #[compact] value: T::Balance @@ -242,61 +147,10 @@ decl_module! { >::transfer(&transactor, &dest, value)?; } - - - pub fn claim_reward(origin) { - let transactor = ensure_signed(origin)?; - let value_can_withdraw = Self::reward_can_withdraw(&transactor); - if !value_can_withdraw.is_zero() { - Self::update_reward_paid_out(&transactor, value_can_withdraw, false); - T::Currency::transfer(&Self::sys_acc(), &transactor, value_can_withdraw)?; - Self::deposit_event(RawEvent::RewardClaim(transactor, value_can_withdraw)); - } - } } - - - } impl Module { - fn update_deposit(who: &T::AccountId, deposit: &Deposit, T::Balance, T::Moment>) { - T::Currency::set_lock( - DEPOSIT_ID, - &who, - deposit.total, - // u32::max_value().into(), - T::BlockNumber::max_value(), - WithdrawReasons::all(), - ); - >::insert(who, deposit); - } - - - fn convert_to_paid_out(value: T::Balance) -> CurrencyOf { - let value: u64 = value.try_into().unwrap_or_default() as u64; - let additional_reward_paid_out: CurrencyOf = Self::reward_per_share() * value.try_into().unwrap_or_default(); - additional_reward_paid_out - } - - fn compute_kton_balance(months: u32, value: CurrencyOf) -> Option { - let months = months as u64; - let value = value.try_into().unwrap_or_default() as u64; - - if !months.is_zero() { - let no = U256::from(67_u128).pow(U256::from(months)); - let de = U256::from(66_u128).pow(U256::from(months)); - - let quotient = no / de; - let remainder = no % de; - let res = U256::from(value) * (U256::from(1000) * (quotient - 1) + U256::from(1000) * remainder / de) / U256::from(1970000); - - Some(res.as_u64().try_into().unwrap_or_default()) - } else { - None - } - } - pub fn vesting_balance(who: &T::AccountId) -> T::Balance { if let Some(v) = Self::vesting(who) { Self::free_balance(who) @@ -319,19 +173,6 @@ impl Module { >::insert(who, balance); UpdateBalanceOutcome::Updated } - - /// update one's reward_paid_out - /// is_refund true -, means giving out reward - /// is_refund false + - fn update_reward_paid_out(who: &T::AccountId, value: CurrencyOf, is_refund: bool) { - let value = i128::from(value.try_into().unwrap_or_default() as u64); - let reward_paid_out = Self::reward_paid_out(who); - if is_refund { - >::insert(who, reward_paid_out - value); - } else { - >::insert(who, reward_paid_out + value); - } - } } @@ -411,14 +252,6 @@ impl Currency for Module { }; if transactor != dest { - // settle transactor reward - let from_should_withdraw = Self::convert_to_paid_out(value); - #[cfg(test)] - runtime_io::print(from_should_withdraw.try_into().unwrap_or_default() as u64); - Self::update_reward_paid_out(transactor, from_should_withdraw, true); - // settle dest reward - Self::update_reward_paid_out(dest, from_should_withdraw, false); - Self::set_free_balance(transactor, new_from_balance); Self::set_free_balance(dest, new_to_balance); @@ -435,12 +268,13 @@ impl Currency for Module { reason: WithdrawReason, liveness: ExistenceRequirement, ) -> result::Result { - if let Some(new_balance) = Self::free_balance(who).checked_sub(&value) { + let old_balance = Self::free_balance(who); + if let Some(new_balance) = old_balance.checked_sub(&value) { if liveness == ExistenceRequirement::KeepAlive && new_balance < Self::minimum_balance() { return Err("payment would kill account"); } - let additional_reward_paid_out = Self::convert_to_paid_out(value); - Self::update_reward_paid_out(who, additional_reward_paid_out, true); + // add here + OnAccountBalanceChanged::on_changed(who, old_balance, new_balance); Self::ensure_can_withdraw(who, value, reason, new_balance)?; Self::set_free_balance(who, new_balance); @@ -458,8 +292,8 @@ impl Currency for Module { let free_balance = Self::free_balance(who); let free_slash = cmp::min(free_balance, value); - let additional_reward_paid_out = Self::convert_to_paid_out(free_slash); - Self::update_reward_paid_out(who, additional_reward_paid_out, true); + // add here + OnAccountBalanceChanged::on_changed(who, free_balance, free_balance - free_slash); Self::set_free_balance(who, free_balance - free_slash); let remaining_slash = value - free_slash; @@ -481,9 +315,12 @@ impl Currency for Module { if Self::total_balance(who).is_zero() { return Err("beneficiary account must pre-exist"); } - let additional_reward_paid_out = Self::convert_to_paid_out(value); - Self::update_reward_paid_out(who, additional_reward_paid_out, false); - Self::set_free_balance(who, Self::free_balance(who) + value); + //add here + let old_balance = Self::free_balance(who); + let new_balance = old_balance + value; + OnAccountBalanceChanged::on_changed(who, old_balance, new_balance); + + Self::set_free_balance(who, new_balance); Ok(PositiveImbalance::new(value)) } @@ -491,7 +328,11 @@ impl Currency for Module { who: &T::AccountId, value: Self::Balance, ) -> Self::PositiveImbalance { - let (imbalance, _) = Self::make_free_balance_be(who, Self::free_balance(who) + value); + let old_balance = Self::free_balance(who); + let new_balance = old_balance + value; + OnAccountBalanceChanged::on_changed(who, old_balance, new_balance); + + let (imbalance, _) = Self::make_free_balance_be(who, new_balance); if let SignedImbalance::Positive(p) = imbalance { p @@ -508,15 +349,8 @@ impl Currency for Module { let original = Self::free_balance(who); let imbalance = if original <= balance { - // update reward paid out - let additional_reward_paid_out = Self::convert_to_paid_out(balance - original); - Self::update_reward_paid_out(who, additional_reward_paid_out, false); - SignedImbalance::Positive(PositiveImbalance::new(balance - original)) } else { - // update reward paid out - let additional_reward_paid_out = Self::convert_to_paid_out(original - balance); - Self::update_reward_paid_out(who, additional_reward_paid_out, true); SignedImbalance::Negative(NegativeImbalance::new(original - balance)) }; @@ -626,75 +460,3 @@ impl LockableCurrency for Module } } -impl SystemCurrency> for Module { - // all of ring -// type CurrencyOf = CurrencyOf; - type PositiveImbalanceOf = PositiveImbalanceOf; - type NegativeImbalanceOf = NegativeImbalanceOf; - - fn reward_to_pot(value: CurrencyOf) { - let sys_acc = Self::sys_acc(); - let positive = T::Currency::deposit_creating(&sys_acc, value); - - // update reward-per-share - let total_issuance: u64 = Self::total_issuance().try_into().unwrap_or_default() as u64; - //TODO: if kton total_issuance is super high - // this will be zero - let additional_reward_per_share = value / total_issuance.try_into().unwrap_or_default(); - >::mutate(|r| *r += additional_reward_per_share); - - >::insert(&sys_acc, Self::system_revenue(&sys_acc) + value); - - // re-balance - T::SystemRefund::on_unbalanced(positive); - } - - - // PUB IMMUTABLE - fn reward_can_withdraw(who: &T::AccountId) -> CurrencyOf { - let free_balance = Self::free_balance(who); - let max_should_withdraw = Self::convert_to_paid_out(free_balance); - let max_should_withdraw: u64 = max_should_withdraw.try_into().unwrap_or_default() as u64; - let should_withdraw = i128::from(max_should_withdraw) - Self::reward_paid_out(who); - if should_withdraw <= 0 { - 0.into() - } else { - u64::try_from(should_withdraw).unwrap_or_default().try_into().unwrap_or_default() - } - } - - /// pay system fee with reward - fn withdraw_from_sys_reward( - who: &T::AccountId, - value: CurrencyOf) - -> result::Result<(Self::NegativeImbalanceOf, Self::NegativeImbalanceOf), &'static str> { - let can_withdraw_value = Self::reward_can_withdraw(who); - - let mut system_imbalance = Self::NegativeImbalanceOf::zero(); - let mut acc_imbalance = Self::NegativeImbalanceOf::zero(); - - let withdraw_value = value.min(can_withdraw_value); - - if withdraw_value > 0.into() { - let paid_out_new = match Self::reward_paid_out(who).checked_add(i128::from(withdraw_value.try_into().unwrap_or_default() as u64)) { - Some(v) => v, - None => return Err("wrong with paidout"), - }; - - >::insert(who, paid_out_new); - system_imbalance = T::Currency::slash(&Self::sys_acc(), withdraw_value).0; - } - - if value > withdraw_value { - let new_value = value - withdraw_value; - acc_imbalance = T::Currency::withdraw( - who, - new_value, - WithdrawReason::Fee, - ExistenceRequirement::KeepAlive)?; - } - - Ok((system_imbalance, acc_imbalance)) - } -} - diff --git a/srml/reward/Cargo.toml b/srml/reward/Cargo.toml new file mode 100644 index 000000000..35149d197 --- /dev/null +++ b/srml/reward/Cargo.toml @@ -0,0 +1,43 @@ +[package] +name = "evo-reward" +version = "0.1.0" +authors = ["Darwinia Network "] +edition = "2018" + +[dependencies] +serde = { version = "1.0", optional = true } +safe-mix = { version = "1.0", default-features = false} +parity-codec = { version = "4.1.1", default-features = false, features = ["derive"] } +substrate-keyring = { git = 'https://github.com/paritytech/substrate.git', optional = true } +rstd = { package = "sr-std", git = 'https://github.com/paritytech/substrate.git', default-features = false } +primitives = { package = "sr-primitives", git = 'https://github.com/paritytech/substrate.git', default-features = false } +srml-support = { git = 'https://github.com/paritytech/substrate.git', default-features = false } +system = { package = "srml-system", git = 'https://github.com/paritytech/substrate.git', default-features = false } +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 } +balances = { package = "srml-balances", git = 'https://github.com/paritytech/substrate.git', default-features = false } +dsupport = { package = "evo-support", path = "../support", default-features = false } +runtime_io = { package = "sr-io", git = 'https://github.com/paritytech/substrate.git' } + +[dev-dependencies] +substrate-primitives = { git = 'https://github.com/paritytech/substrate.git' } +balances = { package = "srml-balances", git = 'https://github.com/paritytech/substrate.git' } +node-runtime = { path = "../../node/runtime" } + +[features] +default = ["std"] +std = [ + "serde", + "safe-mix/std", + "substrate-keyring", + "parity-codec/std", + "rstd/std", + "srml-support/std", + "primitives/std", + "system/std", + "timestamp/std", + "substrate-primitives/std", + "balances/std", + "runtime_io/std", + "dsupport/std", +] diff --git a/srml/reward/src/lib.rs b/srml/reward/src/lib.rs new file mode 100644 index 000000000..28d4a1204 --- /dev/null +++ b/srml/reward/src/lib.rs @@ -0,0 +1,312 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +use parity_codec::{Decode, Encode}; +use primitives::traits::{ + CheckedSub, Zero, Bounded +}; + +use rstd::prelude::*; +use rstd::{result, convert::{ TryInto, TryFrom}}; +use srml_support::{decl_event, decl_module, decl_storage, StorageMap, StorageValue, ensure}; +use srml_support::traits::{ + Currency, ExistenceRequirement, Imbalance, LockableCurrency, LockIdentifier, + WithdrawReason, WithdrawReasons, +}; +use substrate_primitives::U256; +use system::ensure_signed; +use dsupport::traits::OnAccountBalanceChanged; +use dsupport::traits::OnDilution; + +#[cfg(feature = "std")] +use runtime_io::with_storage; + +mod mock; +mod tests; + +const DEPOSIT_ID: LockIdentifier = *b"lockkton"; + +#[derive(Encode, Decode, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct BalanceLock { + pub id: LockIdentifier, + pub amount: Balance, + pub until: BlockNumber, + pub reasons: WithdrawReasons, +} + + +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct IndividualDeposit { + pub month: u32, + pub start_at: Moment, + pub value: Currency, + pub balance: Balance, + pub claimed: bool, +} + +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Decode, Default)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct Deposit { + pub total: Currency, + pub deposit_list: Vec>, +} + +type CurrencyBalanceOf = <::Currency as Currency<::AccountId>>::Balance; +type RewardCurrencyBalanceOf = <::RewardCurrency as Currency<::AccountId>>::Balance; + +pub type RewardCurrencyNegativeImbalanceOf = <::RewardCurrency as Currency<::AccountId>>::NegativeImbalance; +pub type RewardCurrencyPositiveImbalanceOf = <::RewardCurrency as Currency<::AccountId>>::PositiveImbalance; + +pub trait Trait: timestamp::Trait { + type Currency: Currency; + type RewardCurrency: LockableCurrency; + + type Event: From> + Into<::Event>; +} + +decl_event!( + pub enum Event where + < T as system::Trait>::AccountId, + Balance = CurrencyBalanceOf, + Currency = RewardCurrencyBalanceOf, + Moment = < T as timestamp::Trait>::Moment, + { + /// lock ring for getting kton + NewDeposit(Moment, AccountId, Balance, Currency), + + /// Claim Reward + RewardClaim(AccountId, Currency), + } +); + +decl_storage! { + trait Store for Module as Reward { + pub DepositLedger get(deposit_ledger): map T::AccountId => Option, CurrencyBalanceOf, T::Moment>>; + + pub SysAcc get(sys_acc) config(): T::AccountId; + + // reward you can get per kton + pub RewardPerShare get(reward_per_share): RewardCurrencyBalanceOf; + + // reward already paid to each ktoner + pub RewardPaidOut get(reward_paid_out): map T::AccountId => i128; + + /// system revenue + /// same to balance in ring + /// TODO: it's ugly, ready for hacking + pub SysRevenuePot get(system_revenue): map T::AccountId => RewardCurrencyBalanceOf; + + + } + add_extra_genesis { + // for ring + config(ring_balances): Vec<(T::AccountId, RewardCurrencyBalanceOf, u32)>; + build( | + storage: & mut primitives::StorageOverlay, + _: & mut primitives::ChildrenStorageOverlay, + config: & GenesisConfig + | { + with_storage(storage, || { + for &(ref depositor, balance, months) in &config.ring_balances { + assert!(T::RewardCurrency::free_balance(&depositor) >= balance); + let _ = >::deposit( + T::Origin::from(Some(depositor.clone()).into()), + balance, + months + ); + + } + }); + }); + + + } +} + +decl_module! { + pub struct Module for enum Call where origin: T::Origin { + fn deposit_event() = default; + + pub fn deposit(origin, value: RewardCurrencyBalanceOf, months: u32) { + ensure!(!months.is_zero() && months <= 36, "months must be at least 1"); + let transactor = ensure_signed(origin)?; + if >::exists(&transactor) { + return Err("Already deposited."); + } + + let free_currency = T::RewardCurrency::free_balance(&transactor); + let value = value.min(free_currency); + + let now = >::now(); + + let kton_return = Self::compute_kton_balance(months, value).unwrap(); + + let individual_deposit = IndividualDeposit {month: months, start_at: now.clone(), value: value, balance: kton_return, claimed: false}; + let deposit = Deposit {total: value, deposit_list: vec![individual_deposit]}; + + Self::update_deposit(&transactor, &deposit); + + let _positive_imbalance = T::Currency::deposit_into_existing(&transactor, kton_return); + Self::deposit_event(RawEvent::NewDeposit(now, transactor, kton_return, value)); + } + + fn deposit_extra(origin, additional_value: RewardCurrencyBalanceOf, months: u32) { + ensure!(!months.is_zero() && months <= 36, "months must be at least 1"); + let transactor = ensure_signed(origin)?; + let mut deposit = Self::deposit_ledger(&transactor).ok_or("Use fn deposit instead.")?; + + let now = >::now(); + let free_currency = T::RewardCurrency::free_balance(&transactor); + + if let Some(extra) = free_currency.checked_sub(&deposit.total) { + let extra = extra.min(additional_value); + deposit.total += extra; + + let kton_return = Self::compute_kton_balance(months, extra).unwrap(); + let individual_deposit = IndividualDeposit {month: months, start_at: now.clone(), value: extra.clone(), balance: kton_return, claimed: false}; + deposit.deposit_list.push(individual_deposit); + Self::update_deposit(&transactor, &deposit); + + let _positive_imbalance = T::Currency::deposit_into_existing(&transactor, kton_return); + Self::deposit_event(RawEvent::NewDeposit(now, transactor, kton_return, extra)); + } + } + + pub fn claim_reward(origin) { + let transactor = ensure_signed(origin)?; + let value_can_withdraw = Self::reward_can_withdraw(&transactor); + if !value_can_withdraw.is_zero() { + Self::update_reward_paid_out(&transactor, value_can_withdraw); + T::RewardCurrency::transfer(&Self::sys_acc(), &transactor, value_can_withdraw)?; + Self::deposit_event(RawEvent::RewardClaim(transactor, value_can_withdraw)); + } + } + } +} + + +impl Module { + + fn update_deposit(who: &T::AccountId, deposit: &Deposit, CurrencyBalanceOf, T::Moment>) { + T::RewardCurrency::set_lock( + DEPOSIT_ID, + &who, + deposit.total, + // u32::max_value().into(), + T::BlockNumber::max_value(), + WithdrawReasons::all() + ); + >::insert(who, deposit); + } + + fn compute_kton_balance(months: u32, value: RewardCurrencyBalanceOf) -> Option> { + let months = months as u64; + let value = value.try_into().unwrap_or_default() as u64; + + if !months.is_zero() { + let no = U256::from(67_u128).pow(U256::from(months)); + let de = U256::from(66_u128). pow(U256::from(months)); + + let quotient = no / de; + let remainder = no % de; + let res = U256::from(value) * (U256::from(1000) * (quotient - 1) + U256::from(1000) * remainder / de) / U256::from(1970000); + + Some(res.as_u64().try_into().unwrap_or_default()) + } else { + None + } + + } + + fn convert_to_paid_out(value: CurrencyBalanceOf) -> RewardCurrencyBalanceOf { + let value: u64 = value.try_into().unwrap_or_default() as u64; + let additional_reward_paid_out: RewardCurrencyBalanceOf = Self::reward_per_share() * value.try_into().unwrap_or_default(); + additional_reward_paid_out + } + + /// update one's reward_paid_out + fn update_reward_paid_out(who: &T::AccountId, value: RewardCurrencyBalanceOf) { + let value = i128::from(value.try_into().unwrap_or_default() as u64); + let reward_paid_out = Self::reward_paid_out(who); + >::insert(who, reward_paid_out + value); + } + + pub fn reward_to_pot(value: RewardCurrencyBalanceOf) { + let sys_acc = Self::sys_acc(); + let positive = T::RewardCurrency::deposit_creating(&sys_acc, value); + + // update reward-per-share + let total_issuance: u64 = T::Currency::total_issuance().try_into().unwrap_or_default() as u64; + //TODO: if kton total_issuance is super high + // this will be zero + let additional_reward_per_share = value / total_issuance.try_into().unwrap_or_default(); + >::mutate(|r| *r += additional_reward_per_share); + + >::insert(&sys_acc, Self::system_revenue(&sys_acc) + value); + } + + // PUB IMMUTABLE + fn reward_can_withdraw(who: &T::AccountId) -> RewardCurrencyBalanceOf { + let free_balance = T::Currency::free_balance(who); + let max_should_withdraw = Self::convert_to_paid_out(free_balance); + let max_should_withdraw: u64 = max_should_withdraw.try_into().unwrap_or_default() as u64; + let should_withdraw = i128::from(max_should_withdraw) - Self::reward_paid_out(who); + if should_withdraw <= 0 { + 0.into() + } else { + u64::try_from(should_withdraw).unwrap_or_default().try_into().unwrap_or_default() + } + + } + + /// pay system fee with reward + fn withdraw_from_sys_reward(who: &T::AccountId, value: RewardCurrencyBalanceOf) + -> result::Result<(RewardCurrencyNegativeImbalanceOf, RewardCurrencyNegativeImbalanceOf), &'static str> { + + let can_withdraw_value = Self::reward_can_withdraw(who); + + let mut system_imbalance = RewardCurrencyNegativeImbalanceOf::::zero(); + let mut acc_imbalance = RewardCurrencyNegativeImbalanceOf::::zero(); + + let withdraw_value = value.min(can_withdraw_value); + + if withdraw_value > 0.into() { + let paid_out_new = match Self::reward_paid_out(who).checked_add(i128::from(withdraw_value.try_into().unwrap_or_default() as u64)) { + Some(v) => v, + None => return Err("wrong with paidout"), + }; + + >::insert(who, paid_out_new); + system_imbalance = T::RewardCurrency::slash(&Self::sys_acc(), withdraw_value).0; + } + + if value > withdraw_value { + let new_value = value - withdraw_value; + acc_imbalance = T::RewardCurrency::withdraw( + who, + new_value, + WithdrawReason::Fee, + ExistenceRequirement::KeepAlive)?; + } + + Ok((system_imbalance, acc_imbalance)) + } + +} + +/// reward(ring minted) +impl OnDilution> for Module { + fn on_dilution(minted: RewardCurrencyBalanceOf) { + Self::reward_to_pot(minted); + } +} + +/// account kton balance changed +impl OnAccountBalanceChanged> for Module { + fn on_changed(who: &T::AccountId, old: CurrencyBalanceOf, new: CurrencyBalanceOf) { + // update reward paid out + let additional_reward_paid_out = Self::convert_to_paid_out(new-old); + Self::update_reward_paid_out(who, additional_reward_paid_out); + } +} diff --git a/srml/kton/src/mock.rs b/srml/reward/src/mock.rs similarity index 98% rename from srml/kton/src/mock.rs rename to srml/reward/src/mock.rs index be56b28fc..879aaf30c 100644 --- a/srml/kton/src/mock.rs +++ b/srml/reward/src/mock.rs @@ -198,4 +198,5 @@ impl ExtBuilder { pub type System = system::Module; pub type Ring = balances::Module; pub type Timestamp = timestamp::Module; -pub type Kton = Module; +pub type Kton = kton::Module; +pub type Reward = Module; diff --git a/srml/kton/src/tests.rs b/srml/reward/src/tests.rs similarity index 70% rename from srml/kton/src/tests.rs rename to srml/reward/src/tests.rs index 555ea5a99..8d3c70df4 100644 --- a/srml/kton/src/tests.rs +++ b/srml/reward/src/tests.rs @@ -5,7 +5,7 @@ use runtime_io::with_externalities; use srml_support::{assert_err, assert_noop, assert_ok}; use srml_support::traits::{Currency, ExistenceRequirement, Imbalance, WithdrawReason, WithdrawReasons}; -use mock::{ExtBuilder, Kton, Origin, Ring, System, Test, Timestamp}; +use mock::{ExtBuilder, Reward, Kton, Origin, Ring, System, Test, Timestamp}; use node_runtime::{COIN, MILLI}; use super::*; @@ -18,15 +18,15 @@ fn approximate_equal(real: u128, ideal: u128) -> bool { #[inline] fn deposit_pre() { - Kton::deposit(Origin::signed(11), 100000, 12); - Kton::deposit(Origin::signed(21), 100000, 36); + Reward::deposit(Origin::signed(11), 100000, 12); + Reward::deposit(Origin::signed(21), 100000, 36); } #[inline] fn deposit_with_decimals_pre() { // acc deposit 100w ring - Kton::deposit(Origin::signed(11), 10_000_000_000 * COIN, 12); - Kton::deposit(Origin::signed(21), 1_000_000_000 * COIN, 36); + Reward::deposit(Origin::signed(11), 10_000_000_000 * COIN, 12); + Reward::deposit(Origin::signed(21), 1_000_000_000 * COIN, 36); } #[test] @@ -67,8 +67,8 @@ fn deposit_and_deposit_extra_should_work() { deposit_pre(); assert_eq!(Kton::free_balance(&11), 10); assert_eq!(Kton::free_balance(&21), 36); - assert_err!(Kton::deposit(Origin::signed(11), 10000, 12), "Already deposited."); - Kton::deposit_extra(Origin::signed(11), 10000, 12); + assert_err!(Reward::deposit(Origin::signed(11), 10000, 12), "Already deposited."); + Reward::deposit_extra(Origin::signed(11), 10000, 12); assert_eq!(Kton::free_balance(&11), 11); }); } @@ -95,12 +95,12 @@ fn reward_per_share_not_zero() { // acc 91 and 92 deposit 10k ring for 12 months // in return, acc 91 and 92 will get 1 kton let old_total_issuance = Kton::total_issuance(); - Kton::deposit(Origin::signed(91), 10_000 * COIN, 12); - Kton::deposit(Origin::signed(92), 10_000 * COIN, 12); + Reward::deposit(Origin::signed(91), 10_000 * COIN, 12); + Reward::deposit(Origin::signed(92), 10_000 * COIN, 12); assert_eq!(Kton::total_issuance(), old_total_issuance + 2 * COIN); - Kton::reward_to_pot(225000 * COIN); - assert_eq!(Kton::reward_per_share(), 3000); + Reward::reward_to_pot(225000 * COIN); + assert_eq!(Reward::reward_per_share(), 3000); } #[test] @@ -110,20 +110,20 @@ fn reward_per_share_should_work() { // reward_per_share 3000 reward_per_share_not_zero(); - assert_eq!(Kton::reward_per_share(), 3000); + assert_eq!(Reward::reward_per_share(), 3000); assert_eq!(Kton::free_balance(&91), 1 * COIN); // acc 91 and 92 can withdraw 3k ring as reward - assert_eq!(Kton::reward_can_withdraw(&91), 3000 * COIN); - assert_eq!(Kton::reward_can_withdraw(&91), 3000 * COIN); + assert_eq!(Reward::reward_can_withdraw(&91), 3000 * COIN); + assert_eq!(Reward::reward_can_withdraw(&91), 3000 * COIN); - Kton::deposit(Origin::signed(93), 10_000 * COIN, 12); + Reward::deposit(Origin::signed(93), 10_000 * COIN, 12); // acc 93 has got 1 kton and reward_per_share is 3000 - assert_eq!(Kton::reward_paid_out(&93), 3000 * COIN as i128); + assert_eq!(Reward::reward_paid_out(&93), 3000 * COIN as i128); // after acc 93 has got kton // there is no system revenue // so acc 93 should withdraw 0 - assert_eq!(Kton::reward_can_withdraw(&93), 0); + assert_eq!(Reward::reward_can_withdraw(&93), 0); }); } @@ -133,18 +133,18 @@ fn transfer_should_work() { .existential_deposit(MILLI).build(), || { // reward_per_share 3000 reward_per_share_not_zero(); - Kton::deposit(Origin::signed(93), 10_000 * COIN, 12); + Reward::deposit(Origin::signed(93), 10_000 * COIN, 12); // acc 93 has got 1 kton and reward_per_share is 3000 - assert_eq!(Kton::reward_paid_out(&93), 3000 * COIN as i128); - assert_eq!(Kton::reward_can_withdraw(&93), 0); + assert_eq!(Reward::reward_paid_out(&93), 3000 * COIN as i128); + assert_eq!(Reward::reward_can_withdraw(&93), 0); // new things happen! // reward_per_share now change to assert_eq!(Kton::total_issuance(), 76 * COIN); - Kton::reward_to_pot(76000 * COIN); - assert_eq!(Ring::free_balance(&Kton::sys_acc()), 301000 * COIN); - assert_eq!(Kton::reward_per_share(), 4000); - assert_eq!(Kton::reward_can_withdraw(&93), 1000 * COIN); + Reward::reward_to_pot(76000 * COIN); + assert_eq!(Ring::free_balance(&Reward::sys_acc()), 301000 * COIN); + assert_eq!(Reward::reward_per_share(), 4000); + assert_eq!(Reward::reward_can_withdraw(&93), 1000 * COIN); // before transfer: // acc 93 has 1 kton and can withdraw 1000 ring @@ -154,17 +154,17 @@ fn transfer_should_work() { // acc 94 has 1 kton and can withdraw 0 ring assert_eq!(Kton::free_balance(&93), 1 * COIN); assert_eq!(Kton::free_balance(&94), 0); - assert_eq!(Kton::reward_can_withdraw(&93), 1000 * COIN); - assert_eq!(Kton::reward_can_withdraw(&94), 0); + assert_eq!(Reward::reward_can_withdraw(&93), 1000 * COIN); + assert_eq!(Reward::reward_can_withdraw(&94), 0); - assert_eq!(Kton::reward_paid_out(&93), 3000 * COIN as i128); + assert_eq!(Reward::reward_paid_out(&93), 3000 * COIN as i128); Kton::transfer(Origin::signed(93), 94, 1 * COIN); - assert_eq!(Kton::reward_paid_out(&93), -1000 * COIN as i128); + assert_eq!(Reward::reward_paid_out(&93), -1000 * COIN as i128); assert_eq!(Kton::free_balance(&93), 0); assert_eq!(Kton::free_balance(&94), 1 * COIN); - assert_eq!(Kton::reward_can_withdraw(&93), 1000 * COIN); - assert_eq!(Kton::reward_can_withdraw(&94), 0); + assert_eq!(Reward::reward_can_withdraw(&93), 1000 * COIN); + assert_eq!(Reward::reward_can_withdraw(&94), 0); }); } @@ -176,13 +176,13 @@ fn withdraw_reward_should_work() { // acc 91 and 92 have 1 kton reward_per_share_not_zero(); - assert_eq!(Kton::reward_can_withdraw(&91), 3000 * COIN); + assert_eq!(Reward::reward_can_withdraw(&91), 3000 * COIN); let old_91_free_balance = Ring::free_balance(&91); - let old_sys_free_balance = Ring::free_balance(&Kton::sys_acc()); - Kton::claim_reward(Origin::signed(91)); - assert_eq!(Kton::reward_can_withdraw(&91), 0); + let old_sys_free_balance = Ring::free_balance(&Reward::sys_acc()); + Reward::claim_reward(Origin::signed(91)); + assert_eq!(Reward::reward_can_withdraw(&91), 0); assert_eq!(Ring::free_balance(&91), old_91_free_balance + 3000 * COIN); - assert_eq!(Ring::free_balance(&Kton::sys_acc()), old_sys_free_balance - 3000 * COIN); + assert_eq!(Ring::free_balance(&Reward::sys_acc()), old_sys_free_balance - 3000 * COIN); }); } @@ -201,8 +201,8 @@ fn make_free_balance_be_should_work() { let old_total_issuance = Kton::total_issuance(); Kton::make_free_balance_be(&94, 1 * COIN); assert_eq!(Kton::free_balance(&94), 1 * COIN); - assert_eq!(Kton::reward_paid_out(&94), 3000 * COIN as i128); - assert_eq!(Kton::reward_can_withdraw(&94), 0); + assert_eq!(Reward::reward_paid_out(&94), 3000 * COIN as i128); + assert_eq!(Reward::reward_can_withdraw(&94), 0); assert_eq!(Kton::total_issuance(), old_total_issuance + 1 * COIN); // before: @@ -211,13 +211,13 @@ fn make_free_balance_be_should_work() { // acc 91 has 0 kton and 3k rewrd_paid_out // total_issuance - 1 let old_total_issuance = Kton::total_issuance(); - assert_eq!(Kton::reward_paid_out(&91), 0 as i128); - assert_eq!(Kton::reward_can_withdraw(&91), 3000 * COIN); + assert_eq!(Reward::reward_paid_out(&91), 0 as i128); + assert_eq!(Reward::reward_can_withdraw(&91), 3000 * COIN); Kton::make_free_balance_be(&91, 0); assert_eq!(Kton::free_balance(&91), 0); - assert_eq!(Kton::reward_paid_out(&91), -3000 * COIN as i128); - assert_eq!(Kton::reward_can_withdraw(&91), 3000 * COIN); + assert_eq!(Reward::reward_paid_out(&91), -3000 * COIN as i128); + assert_eq!(Reward::reward_can_withdraw(&91), 3000 * COIN); assert_eq!(Kton::total_issuance(), old_total_issuance - 1 * COIN); }); } @@ -236,13 +236,13 @@ fn withdraw_in_currency_should_work() { // acc 91 has 0 kton and 3k rewrd_paid_out // total_issuance - 1 let old_total_issuance = Kton::total_issuance(); - assert_eq!(Kton::reward_paid_out(&91), 0 as i128); - assert_eq!(Kton::reward_can_withdraw(&91), 3000 * COIN); + assert_eq!(Reward::reward_paid_out(&91), 0 as i128); + assert_eq!(Reward::reward_can_withdraw(&91), 3000 * COIN); Kton::withdraw(&91, 1 * COIN, WithdrawReason::Fee, ExistenceRequirement::KeepAlive); assert_eq!(Kton::free_balance(&91), 0); - assert_eq!(Kton::reward_paid_out(&91), -3000 * COIN as i128); - assert_eq!(Kton::reward_can_withdraw(&91), 3000 * COIN); + assert_eq!(Reward::reward_paid_out(&91), -3000 * COIN as i128); + assert_eq!(Reward::reward_can_withdraw(&91), 3000 * COIN); assert_eq!(Kton::total_issuance(), old_total_issuance - 1 * COIN); }); } @@ -261,13 +261,13 @@ fn slash_should_work() { // acc 91 has 0 kton and 3k rewrd_paid_out // total_issuance - 1 let old_total_issuance = Kton::total_issuance(); - assert_eq!(Kton::reward_paid_out(&91), 0 as i128); - assert_eq!(Kton::reward_can_withdraw(&91), 3000 * COIN); + assert_eq!(Reward::reward_paid_out(&91), 0 as i128); + assert_eq!(Reward::reward_can_withdraw(&91), 3000 * COIN); Kton::slash(&91, 1 * COIN); assert_eq!(Kton::free_balance(&91), 0); - assert_eq!(Kton::reward_paid_out(&91), -3000 * COIN as i128); - assert_eq!(Kton::reward_can_withdraw(&91), 3000 * COIN); + assert_eq!(Reward::reward_paid_out(&91), -3000 * COIN as i128); + assert_eq!(Reward::reward_can_withdraw(&91), 3000 * COIN); assert_eq!(Kton::total_issuance(), old_total_issuance - 1 * COIN); }); } @@ -293,12 +293,12 @@ fn deposit_into_existing_should_work() { // total_issuance + 1 let old_total_issuance = Kton::total_issuance(); assert_eq!(Kton::free_balance(&91), 1 * COIN); - assert_eq!(Kton::reward_paid_out(&91), 0 as i128); - assert_eq!(Kton::reward_can_withdraw(&91), 3000 * COIN); + assert_eq!(Reward::reward_paid_out(&91), 0 as i128); + assert_eq!(Reward::reward_can_withdraw(&91), 3000 * COIN); Kton::deposit_into_existing(&91, 1 * COIN); assert_eq!(Kton::free_balance(&91), 2 * COIN); - assert_eq!(Kton::reward_paid_out(&91), 3000 * COIN as i128); - assert_eq!(Kton::reward_can_withdraw(&91), 3000 * COIN); + assert_eq!(Reward::reward_paid_out(&91), 3000 * COIN as i128); + assert_eq!(Reward::reward_can_withdraw(&91), 3000 * COIN); assert_eq!(Kton::total_issuance(), old_total_issuance + 1 * COIN); }); } @@ -320,12 +320,12 @@ fn deposit_creating_should_work() { // total_issuance + 1 let old_total_issuance = Kton::total_issuance(); assert_eq!(Kton::free_balance(&94), 0); - assert_eq!(Kton::reward_paid_out(&94), 0 as i128); - assert_eq!(Kton::reward_can_withdraw(&94), 0); + assert_eq!(Reward::reward_paid_out(&94), 0 as i128); + assert_eq!(Reward::reward_can_withdraw(&94), 0); Kton::deposit_creating(&94, 1 * COIN); assert_eq!(Kton::free_balance(&94), 1 * COIN); - assert_eq!(Kton::reward_paid_out(&94), 3000 * COIN as i128); - assert_eq!(Kton::reward_can_withdraw(&94), 0); + assert_eq!(Reward::reward_paid_out(&94), 3000 * COIN as i128); + assert_eq!(Reward::reward_can_withdraw(&94), 0); assert_eq!(Kton::total_issuance(), old_total_issuance + 1 * COIN); }); -} \ No newline at end of file +} diff --git a/srml/staking/Cargo.toml b/srml/staking/Cargo.toml index c1a2bcf31..a9f710bc1 100644 --- a/srml/staking/Cargo.toml +++ b/srml/staking/Cargo.toml @@ -16,6 +16,7 @@ srml-support = { git = 'https://github.com/paritytech/substrate.git', default-fe system = { package = "srml-system", git = 'https://github.com/paritytech/substrate.git', default-features = false } session = { package = "srml-session",git = 'https://github.com/paritytech/substrate.git', default-features = false } dsupport = { package = "evo-support", path = "../support", default-features = false } +reward = { package = "evo-reward", path = "../srml/reward", default-features = false } [dev-dependencies] substrate-primitives = { git = 'https://github.com/paritytech/substrate.git' } @@ -41,4 +42,5 @@ std = [ "session/std", "system/std", "dsupport/std", + "reward/std", ] diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index 0f9f46f43..b7c09724c 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -42,7 +42,6 @@ use srml_support::{ }; use system::ensure_signed; -use dsupport::traits::SystemCurrency; use phragmen::{ACCURACY, elect, equalize, ExtendedBalance}; @@ -218,10 +217,9 @@ type ExpoMap = BTreeMap< pub const DEFAULT_SESSIONS_PER_ERA: u32 = 3; pub const DEFAULT_BONDING_DURATION: u32 = 1; -pub trait Trait: system::Trait + session::Trait { +pub trait Trait: system::Trait + session::Trait + reward::Trait { /// The staking balance. - type Currency: LockableCurrency + - SystemCurrency>::Balance>; + type Currency: LockableCurrency; // Customed: for ring type RewardCurrency: Currency; @@ -709,7 +707,7 @@ impl Module { } Self::deposit_event(RawEvent::Reward(block_reward_per_validator)); - T::Currency::reward_to_pot(reward); + as reward::Trait>::reward_to_pot(reward); // TODO: reward to treasury } diff --git a/srml/try/Cargo.toml b/srml/try/Cargo.toml index a99584636..f1d5038c6 100644 --- a/srml/try/Cargo.toml +++ b/srml/try/Cargo.toml @@ -17,7 +17,7 @@ rstd = { package = "sr-std", git = "https://github.com/paritytech/substrate", de sr-primitives = { git = "https://github.com/paritytech/substrate", default-features = false } support = { package = "srml-support", git = "https://github.com/paritytech/substrate", default-features = false } system = { package = "srml-system", git = "https://github.com/paritytech/substrate", default-features = false } -sr-io = { git = "https://github.com/paritytech/substrate", default-features = false } +sr-io = { git = "https://github.com/paritytech/substrate.git", default-features = false } [dev-dependencies] support = { package = "srml-support", git = 'https://github.com/paritytech/substrate.git' }