From e91cd9f49188e9a86f1e3552eb588c89a72fa15f Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Thu, 26 Sep 2019 17:49:31 +0800 Subject: [PATCH 01/10] add: reserve tuple --- srml/staking/src/lib.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/srml/staking/src/lib.rs b/srml/staking/src/lib.rs index c5f24d351..2209e1118 100644 --- a/srml/staking/src/lib.rs +++ b/srml/staking/src/lib.rs @@ -921,21 +921,20 @@ impl Module { let mut ledger = Self::ledger(&controller).unwrap(); // slash ring - let ring_imbalance = if ledger.total_ring.is_zero() { - >::zero() - } else { + let (ring_imbalance, _) = if !ledger.total_ring.is_zero() { let slashable_ring = slash_ratio * ledger.total_ring; let value_slashed = Self::slash_helper(&controller, &mut ledger, StakingBalance::Ring(slashable_ring)); - - T::Ring::slash(stash, value_slashed.0).0 - }; - let kton_imbalance = if ledger.total_kton.is_zero() { - >::zero() + T::Ring::slash(stash, value_slashed.0) } else { + (>::zero(), Zero::zero()) + }; + + let (kton_imbalance, _) = if !ledger.total_kton.is_zero() { let slashable_kton = slash_ratio * ledger.total_kton; let value_slashed = Self::slash_helper(&controller, &mut ledger, StakingBalance::Kton(slashable_kton)); - - T::Kton::slash(stash, value_slashed.1).0 + T::Kton::slash(stash, value_slashed.1) + } else { + (>::zero(), Zero::zero()) }; (ring_imbalance, kton_imbalance) From a36c27d7ad3670ad07396f87f9a531d2982246ba Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Fri, 27 Sep 2019 17:54:52 +0800 Subject: [PATCH 02/10] update: README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 11a9b1206..0fff4fde8 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ cargo install --git https://github.com/alexcrichton/wasm-gc ### Build -Building with darwinia builder: +Building with darwinia-builder: ```bash darwinia-builder --release --wasm ``` From be39dfc29ff1f9baac035d07f9d39052954f0184 Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Fri, 27 Sep 2019 17:55:18 +0800 Subject: [PATCH 03/10] ignore: `osxcross` --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index afdedf9ef..4be46023a 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ test-client .DS_Store # For cross compile +osxcross darwin-x86_64 darwin-x86_64.tar.gz linux-x86_64 From 3be60580b684c1fbacd2c27cbc9c281babe991e9 Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Sun, 29 Sep 2019 13:17:43 +0800 Subject: [PATCH 04/10] add: comment for macro `gen_pair_account` --- srml/staking/src/tests.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/srml/staking/src/tests.rs b/srml/staking/src/tests.rs index d9ea7f96d..f1d0e426c 100644 --- a/srml/staking/src/tests.rs +++ b/srml/staking/src/tests.rs @@ -5,6 +5,12 @@ use runtime_io::with_externalities; use srml_support::traits::{Currency, WithdrawReason, WithdrawReasons}; use srml_support::{assert_err, assert_ok}; +// gen_paired_account!(a(1), b(2), m(12)); +// will create stash `a` and controller `b` +// `a` has 100 Ring and 100 Kton +// promise for `m` month with 50 Ring and 50 Kton +// `m` can be ignore, and it wont perfrom `bond` action +// gen_paired_account!(a(1), b(2)); macro_rules! gen_paired_account { ($stash:ident($stash_id:expr), $controller:ident($controller_id:expr), $promise_month:ident($how_long:expr)) => { #[allow(non_snake_case, unused)] From c4f292915a172d34ee4aff8cc202920523437baa Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Tue, 8 Oct 2019 19:06:22 +0800 Subject: [PATCH 05/10] add: tests --- srml/staking/src/tests.rs | 104 ++++++++++++++++++++++++++++---------- 1 file changed, 76 insertions(+), 28 deletions(-) diff --git a/srml/staking/src/tests.rs b/srml/staking/src/tests.rs index f1d0e426c..e837f2376 100644 --- a/srml/staking/src/tests.rs +++ b/srml/staking/src/tests.rs @@ -6,7 +6,7 @@ use srml_support::traits::{Currency, WithdrawReason, WithdrawReasons}; use srml_support::{assert_err, assert_ok}; // gen_paired_account!(a(1), b(2), m(12)); -// will create stash `a` and controller `b` +// will create stash `a` and controller `b` // `a` has 100 Ring and 100 Kton // promise for `m` month with 50 Ring and 50 Kton // `m` can be ignore, and it wont perfrom `bond` action @@ -914,7 +914,7 @@ fn unbond_over_max_unlocking_chunks_should_fail() { #[test] fn unlock_value_should_be_increased_and_decreased_correctly() { with_externalities(&mut ExtBuilder::default().existential_deposit(0).build(), || { - // normal Ring + // normal Ring/Kton { let stash = 444; let controller = 555; @@ -930,52 +930,100 @@ fn unlock_value_should_be_increased_and_decreased_correctly() { )); assert_ok!(Staking::bond_extra( Origin::signed(stash), - StakingBalance::Ring(50 * COIN), + StakingBalance::Kton(50 * COIN), 0 )); - let mut ledger = Staking::ledger(&controller).unwrap(); + let mut unlocking = Staking::ledger(&controller).unwrap().unlocking; assert_ok!(Staking::unbond(Origin::signed(controller), StakingBalance::Ring(COIN))); - ledger.active_ring -= COIN; - ledger.unlocking = vec![UnlockChunk { + unlocking.push(UnlockChunk { value: StakingBalance::Ring(COIN), era: 3, is_time_deposit: false, - }]; - assert_eq!(&Staking::ledger(&controller).unwrap(), &ledger); - - start_era(3); + }); + assert_eq!(&Staking::ledger(&controller).unwrap().unlocking, &unlocking); + assert_ok!(Staking::unbond(Origin::signed(controller), StakingBalance::Kton(COIN))); + unlocking.push(UnlockChunk { + value: StakingBalance::Kton(COIN), + era: 3, + is_time_deposit: false, + }); + assert_eq!(&Staking::ledger(&controller).unwrap().unlocking, &unlocking); assert_ok!(Staking::unbond(Origin::signed(controller), StakingBalance::Ring(0))); - ledger.unlocking.push(UnlockChunk { + unlocking.push(UnlockChunk { value: StakingBalance::Ring(0), - era: 6, + era: 3, is_time_deposit: true, }); - assert_eq!(&Staking::ledger(&controller).unwrap(), &ledger); - assert_ok!(Staking::withdraw_unbonded(Origin::signed(controller))); - ledger.total_ring -= COIN; - ledger.unlocking.remove(0); - assert_eq!(&Staking::ledger(&controller).unwrap(), &ledger); - - start_era(6); - - assert_ok!(Staking::withdraw_unbonded(Origin::signed(controller))); - ledger.unlocking.remove(0); - assert_eq!(&Staking::ledger(&controller).unwrap(), &ledger); + assert_eq!(&Staking::ledger(&controller).unwrap().unlocking, &unlocking); + assert_ok!(Staking::unbond(Origin::signed(controller), StakingBalance::Kton(0))); + unlocking.push(UnlockChunk { + value: StakingBalance::Kton(0), + era: 3, + is_time_deposit: false, + }); + assert_eq!(&Staking::ledger(&controller).unwrap().unlocking, &unlocking); } // promise Ring { gen_paired_account!(stash(666), controller(777), promise_month(12)); - println!("{:#?}", Staking::ledger(&controller).unwrap()); - } + assert_ok!(Staking::bond_extra( + Origin::signed(stash), + StakingBalance::Ring(50 * COIN), + 36 + )); - // Kton - { - // + let mut unlocking = Staking::ledger(&controller).unwrap().unlocking; + + assert_ok!(Staking::unbond(Origin::signed(controller), StakingBalance::Ring(COIN))); + unlocking.push(UnlockChunk { + value: StakingBalance::Ring(0), + era: 3, + is_time_deposit: true, + }); + assert_eq!(&Staking::ledger(&controller).unwrap().unlocking, &unlocking); + + for month in [12, 36].iter() { + assert_ok!(Staking::unbond_with_punish( + Origin::signed(controller), + 20 * COIN, + month * MONTH_IN_SECONDS as u64 + )); + unlocking.push(UnlockChunk { + value: StakingBalance::Ring(20 * COIN), + era: 3, + is_time_deposit: true, + }); + assert_eq!(&Staking::ledger(&controller).unwrap().unlocking, &unlocking); + + assert_ok!(Staking::unbond_with_punish( + Origin::signed(controller), + 29 * COIN, + month * MONTH_IN_SECONDS as u64 + )); + unlocking.push(UnlockChunk { + value: StakingBalance::Ring(29 * COIN), + era: 3, + is_time_deposit: true, + }); + assert_eq!(&Staking::ledger(&controller).unwrap().unlocking, &unlocking); + + assert_ok!(Staking::unbond_with_punish( + Origin::signed(controller), + 50 * COIN, + month * MONTH_IN_SECONDS as u64 + )); + unlocking.push(UnlockChunk { + value: StakingBalance::Ring(1 * COIN), + era: 3, + is_time_deposit: true, + }); + assert_eq!(&Staking::ledger(&controller).unwrap().unlocking, &unlocking); + } } }); } From 7f7c80091c0063eb352141e7668e69b1a14127ed Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Tue, 8 Oct 2019 19:08:10 +0800 Subject: [PATCH 06/10] add: comments optimize: irrelevant operations after error checking --- srml/kton/src/lib.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/srml/kton/src/lib.rs b/srml/kton/src/lib.rs index b1e5a4849..4bb764427 100644 --- a/srml/kton/src/lib.rs +++ b/srml/kton/src/lib.rs @@ -226,10 +226,7 @@ impl Currency for Module { // TODO: add fee fn transfer(transactor: &T::AccountId, dest: &T::AccountId, value: Self::Balance) -> Result { - let from_balance = Self::free_balance(transactor); - let to_balance = Self::free_balance(dest); - - let new_from_balance = match from_balance.checked_sub(&value) { + let new_from_balance = match Self::free_balance(transactor).checked_sub(&value) { None => return Err("balance too low to send value"), Some(b) => b, }; @@ -238,7 +235,7 @@ impl Currency for Module { // NOTE: total stake being stored in the same type means that this could never overflow // but better to be safe than sorry. - let new_to_balance = match to_balance.checked_add(&value) { + let new_to_balance = match Self::free_balance(dest).checked_add(&value) { Some(b) => b, None => return Err("destination balance too high to receive value"), }; @@ -375,6 +372,7 @@ where { type Moment = T::BlockNumber; + // `amount` > `free_balance` is allowed fn set_lock( id: LockIdentifier, who: &T::AccountId, From 4e6ed27fe8fc613292ac245ef2b3f45cd567adb6 Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Tue, 8 Oct 2019 19:09:19 +0800 Subject: [PATCH 07/10] add: vesting for account `1` fix: make `COIN` public --- srml/kton/src/mock.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srml/kton/src/mock.rs b/srml/kton/src/mock.rs index f3944d574..f5acf607f 100644 --- a/srml/kton/src/mock.rs +++ b/srml/kton/src/mock.rs @@ -6,7 +6,7 @@ use srml_support::impl_outer_origin; use std::{cell::RefCell, collections::HashSet}; use substrate_primitives::{Blake2Hasher, H256}; -const COIN: u64 = 1_000_000_000; +pub const COIN: u64 = 1_000_000_000; thread_local! { static SESSION: RefCell<(Vec, HashSet)> = RefCell::new(Default::default()); @@ -116,7 +116,7 @@ impl ExtBuilder { (100, 2000 * balance_factor), (101, 2000 * balance_factor), ], - vesting: vec![], + vesting: vec![(1, 0, 4)], } .assimilate_storage(&mut t, &mut c); t.into() From 203befdaa0e92d425ca0b48b796d0a2322371b89 Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Wed, 9 Oct 2019 15:16:53 +0800 Subject: [PATCH 08/10] add: comments --- srml/kton/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/srml/kton/src/lib.rs b/srml/kton/src/lib.rs index 4bb764427..6a7c53892 100644 --- a/srml/kton/src/lib.rs +++ b/srml/kton/src/lib.rs @@ -445,6 +445,7 @@ where fn remove_lock(id: LockIdentifier, who: &T::AccountId) { let now = >::block_number(); >::mutate(who, |locks| { + // unexpired and mismatched id -> keep locks.retain(|lock| (lock.until > now) && (lock.id != id)); }); } From 9c3e9cd5d64a16b11bdfe48ebc7c980e9ac249fc Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Wed, 9 Oct 2019 17:28:41 +0800 Subject: [PATCH 09/10] refactoring: tests --- srml/kton/src/tests.rs | 227 +++++++++++++++++++++++++++++------------ 1 file changed, 160 insertions(+), 67 deletions(-) diff --git a/srml/kton/src/tests.rs b/srml/kton/src/tests.rs index 8acabffdc..c42c7ad7f 100644 --- a/srml/kton/src/tests.rs +++ b/srml/kton/src/tests.rs @@ -1,5 +1,5 @@ use super::*; -use mock::{ExtBuilder, Kton, Origin, System}; +use mock::{ExtBuilder, Kton, Origin, System, Test}; use runtime_io::with_externalities; use srml_support::traits::{Currency, LockIdentifier, WithdrawReason, WithdrawReasons}; use srml_support::{assert_err, assert_noop, assert_ok}; @@ -11,55 +11,138 @@ const ID_3: LockIdentifier = *b"3 "; #[test] fn transfer_should_work() { with_externalities(&mut ExtBuilder::default().existential_deposit(0).build(), || { - // - Kton::deposit_creating(&1001, 100); - assert_err!( - Kton::transfer(Origin::signed(1001), 1000, 500), - "balance too low to send value" - ); - assert_eq!(Kton::free_balance(&1000), 0); + let _ = Kton::deposit_creating(&666, 100); + + assert_ok!(Kton::transfer(Origin::signed(666), 777, 50)); + assert_eq!(Kton::total_balance(&666), 50); + assert_eq!(Kton::total_balance(&777), 50); + + assert_ok!(Kton::transfer(Origin::signed(666), 777, 50)); + assert_eq!(Kton::total_balance(&666), 0); + assert_eq!(Kton::total_balance(&777), 100); + + assert_ok!(Kton::transfer(Origin::signed(666), 777, 0)); }); } #[test] -fn lock_should_work() { +fn transfer_should_fail() { with_externalities(&mut ExtBuilder::default().existential_deposit(0).build(), || { - Kton::deposit_creating(&1001, 100); - Kton::set_lock(ID_1, &1001, 90, u64::max_value(), WithdrawReasons::all()); + let _ = Kton::deposit_creating(&777, 1); + assert_err!( + Kton::transfer(Origin::signed(666), 777, 50), + "balance too low to send value" + ); + + let _ = Kton::deposit_creating(&666, u64::max_value()); + assert_err!( + Kton::transfer(Origin::signed(777), 666, 1), + "destination balance too high to receive value" + ); + + assert_err!( + Kton::transfer(Origin::signed(1), 777, Kton::vesting_balance(&1)), + "vesting balance too high to send value" + ); + + Kton::set_lock(ID_1, &777, 1, u64::max_value(), WithdrawReasons::all()); assert_err!( - Kton::transfer(Origin::signed(1001), 1000, 20), + Kton::transfer(Origin::signed(777), 1, 1), "account liquidity restrictions prevent withdrawal" ); }); } #[test] -fn lock_removal_should_work() { +fn set_lock_should_work() { with_externalities(&mut ExtBuilder::default().existential_deposit(0).build(), || { - Kton::deposit_creating(&1001, 10); - Kton::set_lock(ID_1, &1001, u64::max_value(), u64::max_value(), WithdrawReasons::all()); - Kton::remove_lock(ID_1, &1001); - assert_ok!(>::transfer(&1001, &1002, 1)); + let lock_ids = [[0; 8], [1; 8], [2; 8], [3; 8]]; + let balance_per_lock = Kton::free_balance(&1) / (lock_ids.len() as u64); + + // account `1`'s vesting length + System::set_block_number(4); + + { + let mut locks = vec![]; + for lock_id in lock_ids.iter() { + Kton::set_lock(*lock_id, &1, balance_per_lock, u64::max_value(), WithdrawReasons::all()); + locks.push(BalanceLock { + id: *lock_id, + amount: balance_per_lock, + until: u64::max_value(), + reasons: WithdrawReasons::all(), + }); + assert_eq!(Kton::locks(&1), locks); + } + } + + for _ in 0..lock_ids.len() - 1 { + assert_ok!(Kton::transfer(Origin::signed(1), 2, balance_per_lock)); + } + assert_err!( + Kton::transfer(Origin::signed(1), 2, balance_per_lock), + "account liquidity restrictions prevent withdrawal" + ); }); } #[test] -fn lock_replacement_should_work() { +fn remove_lock_should_work() { with_externalities(&mut ExtBuilder::default().existential_deposit(0).build(), || { - Kton::deposit_creating(&1001, 10); - Kton::set_lock(ID_1, &1001, u64::max_value(), u64::max_value(), WithdrawReasons::all()); - Kton::set_lock(ID_1, &1001, 5, u64::max_value(), WithdrawReasons::all()); - assert_ok!(>::transfer(&1001, &1002, 1)); + Kton::set_lock(ID_1, &2, u64::max_value(), u64::max_value(), WithdrawReasons::all()); + Kton::set_lock( + ID_2, + &2, + u64::max_value(), + >::block_number() + 1, + WithdrawReasons::all(), + ); + // expired + Kton::set_lock( + ID_3, + &2, + u64::max_value(), + >::block_number(), + WithdrawReasons::all(), + ); + + Kton::remove_lock(ID_1, &2); + assert_err!( + Kton::transfer(Origin::signed(2), 1, 1), + "account liquidity restrictions prevent withdrawal" + ); + + Kton::remove_lock(ID_2, &2); + assert_ok!(Kton::transfer(Origin::signed(2), 1, 1)); }); } #[test] -fn double_locking_should_work() { +fn update_lock_should_work() { with_externalities(&mut ExtBuilder::default().existential_deposit(0).build(), || { - Kton::deposit_creating(&1001, 10); - Kton::set_lock(ID_1, &1001, 5, u64::max_value(), WithdrawReasons::all()); - Kton::set_lock(ID_2, &1001, 5, u64::max_value(), WithdrawReasons::all()); - assert_ok!(>::transfer(&1001, &1002, 1)); + let mut locks = vec![]; + for id in 0..10 { + // until > 1 + locks.push(BalanceLock { + id: [id; 8], + amount: 1, + until: 2, + reasons: WithdrawReasons::none(), + }); + Kton::set_lock([id; 8], &1, 1, 2, WithdrawReasons::none()); + } + let update_id = 4; + for amount in 32767..65535 { + let until = amount + 1; + locks[update_id as usize] = BalanceLock { + id: [update_id; 8], + amount, + until, + reasons: WithdrawReasons::all(), + }; + Kton::set_lock([update_id; 8], &1, amount, until, WithdrawReasons::all()); + assert_eq!(Kton::locks(&1), locks); + } }); } @@ -75,24 +158,57 @@ fn combination_locking_should_work() { } #[test] -fn lock_value_extension_should_work() { +fn extend_lock_should_work() { with_externalities(&mut ExtBuilder::default().existential_deposit(0).build(), || { - Kton::deposit_creating(&1001, 10); - Kton::set_lock(ID_1, &1001, 5, u64::max_value(), WithdrawReasons::all()); - assert_noop!( - >::transfer(&1001, &1002, 6), - "account liquidity restrictions prevent withdrawal" - ); - Kton::extend_lock(ID_1, &1001, 2, u64::max_value(), WithdrawReasons::all()); - assert_noop!( - >::transfer(&1001, &1002, 6), - "account liquidity restrictions prevent withdrawal" - ); - Kton::extend_lock(ID_1, &1001, 8, u64::max_value(), WithdrawReasons::all()); - assert_noop!( - >::transfer(&1001, &1002, 3), - "account liquidity restrictions prevent withdrawal" - ); + let mut locks = vec![]; + { + let amount = 1; + let until = 2; + let reasons = WithdrawReasons::none(); + for will_be_extended_id in 0..5 { + locks.push(BalanceLock { + id: [will_be_extended_id; 8], + amount, + until, + reasons, + }); + Kton::set_lock([will_be_extended_id; 8], &1, amount, until, reasons); + } + } + { + let amount = 100; + let until = 100; + let reasons = WithdrawReasons::all(); + for will_not_be_extended_id in 5..10 { + locks.push(BalanceLock { + id: [will_not_be_extended_id; 8], + amount, + until, + reasons, + }); + Kton::set_lock([will_not_be_extended_id; 8], &1, amount, until, reasons); + } + } + { + let new_amount = 50; + let new_until = 50; + let new_reasons = WithdrawReason::Transfer.into(); + for lock in locks.iter_mut() { + let BalanceLock { + id, + amount, + until, + reasons, + } = lock; + if *amount < new_amount { + *amount = new_amount; + *until = new_until; + *reasons = new_reasons; + } + Kton::extend_lock(*id, &1, new_amount, new_until, new_reasons); + } + assert_eq!(Kton::locks(&1), locks); + } }); } @@ -155,26 +271,3 @@ fn lock_reasons_extension_should_work() { ); }); } - -#[test] -fn balance_works() { - with_externalities(&mut ExtBuilder::default().build(), || { - let _ = Kton::deposit_creating(&1001, 100); - assert_eq!(Kton::free_balance(&1001), 100); - assert_eq!(Kton::reserved_balance(&1001), 0); - assert_eq!(Kton::total_balance(&1001), 100); - assert_eq!(Kton::free_balance(&1002), 0); - assert_eq!(Kton::reserved_balance(&1002), 0); - assert_eq!(Kton::total_balance(&1002), 0); - }); -} - -#[test] -fn balance_transfer_works() { - with_externalities(&mut ExtBuilder::default().build(), || { - let _ = Kton::deposit_creating(&1001, 111); - assert_ok!(Kton::transfer(Some(1001).into(), 1002, 69)); - assert_eq!(Kton::total_balance(&1001), 42); - assert_eq!(Kton::total_balance(&1002), 69); - }); -} From a2a5d228cdca029f34a80de42b403aea08eeb085 Mon Sep 17 00:00:00 2001 From: Xavier Lau Date: Fri, 11 Oct 2019 10:47:57 +0800 Subject: [PATCH 10/10] add: test --- srml/staking/src/tests.rs | 50 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/srml/staking/src/tests.rs b/srml/staking/src/tests.rs index e837f2376..b050145b7 100644 --- a/srml/staking/src/tests.rs +++ b/srml/staking/src/tests.rs @@ -1159,3 +1159,53 @@ fn yakio_q1() { assert_eq!(&Staking::ledger(&controller).unwrap(), &ledger); }); } + +// how to balance the power and calculate the reward if some validators have been chilled +#[test] +fn yakio_q2() { + fn run(with_new_era: bool) -> u64 { + let mut balance = 0; + with_externalities(&mut ExtBuilder::default().existential_deposit(0).build(), || { + gen_paired_account!(validator_1_stash(123), validator_1_controller(456), 0); + gen_paired_account!(validator_2_stash(234), validator_2_controller(567), 0); + gen_paired_account!(nominator_stash(345), nominator_controller(678), 0); + + assert_ok!(Staking::validate( + Origin::signed(validator_1_controller), + vec![0; 8], + 0, + 3 + )); + assert_ok!(Staking::validate( + Origin::signed(validator_2_controller), + vec![1; 8], + 0, + 3 + )); + assert_ok!(Staking::nominate( + Origin::signed(nominator_controller), + vec![validator_1_stash, validator_2_stash] + )); + + start_era(1); + assert_ok!(Staking::chill(Origin::signed(validator_1_controller))); + // assert_ok!(Staking::chill(Origin::signed(validator_2_controller))); + if with_new_era { + start_era(2); + } + Staking::reward_validator(&validator_1_stash, 1000 * COIN); + Staking::reward_validator(&validator_2_stash, 1000 * COIN); + + balance = Ring::free_balance(&nominator_stash); + }); + + balance + } + + let free_balance = run(false); + let free_balance_with_new_era = run(true); + + assert!(free_balance != 0); + assert!(free_balance_with_new_era != 0); + assert!(free_balance > free_balance_with_new_era); +}