mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-30 06:08:00 +00:00
15ae7cfef6
Went through the TODOs, removed a bunch, which are outdated or nothing more than a regular comment, documented a bunch more as actual tickets and made them FIXMEs and unified their structure (`FIXME #TICKETNO DESC` for local tickets, `FIXME: DESC LINK` for external tickets) for easier in-editor support. Further more remove unnecessary remarks and related old code that I noticed in that instance.
598 lines
22 KiB
Rust
598 lines
22 KiB
Rust
// Copyright 2017-2018 Parity Technologies (UK) Ltd.
|
|
// This file is part of Substrate.
|
|
|
|
// Substrate is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
|
|
// Substrate is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
//! Tests for the module.
|
|
|
|
#![cfg(test)]
|
|
|
|
use super::*;
|
|
use runtime_io::with_externalities;
|
|
use mock::{Balances, Session, Staking, System, Timestamp, Test, new_test_ext, Origin};
|
|
|
|
#[test]
|
|
fn note_null_offline_should_work() {
|
|
with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || {
|
|
assert_eq!(Staking::offline_slash_grace(), 0);
|
|
assert_eq!(Staking::slash_count(&10), 0);
|
|
assert_eq!(Balances::free_balance(&10), 1);
|
|
System::set_extrinsic_index(1);
|
|
assert_eq!(Staking::slash_count(&10), 0);
|
|
assert_eq!(Balances::free_balance(&10), 1);
|
|
assert!(Staking::forcing_new_era().is_none());
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn invulnerability_should_work() {
|
|
with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || {
|
|
assert_ok!(Staking::set_invulnerables(vec![10]));
|
|
Balances::set_free_balance(&10, 70);
|
|
assert_eq!(Staking::offline_slash_grace(), 0);
|
|
assert_eq!(Staking::slash_count(&10), 0);
|
|
assert_eq!(Balances::free_balance(&10), 70);
|
|
System::set_extrinsic_index(1);
|
|
Staking::on_offline_validator(10, 1);
|
|
assert_eq!(Staking::slash_count(&10), 0);
|
|
assert_eq!(Balances::free_balance(&10), 70);
|
|
assert!(Staking::forcing_new_era().is_none());
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn note_offline_should_work() {
|
|
with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || {
|
|
Balances::set_free_balance(&10, 70);
|
|
assert_eq!(Staking::offline_slash_grace(), 0);
|
|
assert_eq!(Staking::slash_count(&10), 0);
|
|
assert_eq!(Balances::free_balance(&10), 70);
|
|
System::set_extrinsic_index(1);
|
|
Staking::on_offline_validator(10, 1);
|
|
assert_eq!(Staking::slash_count(&10), 1);
|
|
assert_eq!(Balances::free_balance(&10), 50);
|
|
assert!(Staking::forcing_new_era().is_none());
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn note_offline_exponent_should_work() {
|
|
with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || {
|
|
Balances::set_free_balance(&10, 150);
|
|
assert_eq!(Staking::offline_slash_grace(), 0);
|
|
assert_eq!(Staking::slash_count(&10), 0);
|
|
assert_eq!(Balances::free_balance(&10), 150);
|
|
System::set_extrinsic_index(1);
|
|
Staking::on_offline_validator(10, 1);
|
|
assert_eq!(Staking::slash_count(&10), 1);
|
|
assert_eq!(Balances::free_balance(&10), 130);
|
|
System::set_extrinsic_index(1);
|
|
Staking::on_offline_validator(10, 1);
|
|
assert_eq!(Staking::slash_count(&10), 2);
|
|
assert_eq!(Balances::free_balance(&10), 90);
|
|
assert!(Staking::forcing_new_era().is_none());
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn note_offline_grace_should_work() {
|
|
with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || {
|
|
Balances::set_free_balance(&10, 70);
|
|
Balances::set_free_balance(&20, 70);
|
|
assert_ok!(Staking::set_offline_slash_grace(1));
|
|
assert_eq!(Staking::offline_slash_grace(), 1);
|
|
|
|
assert_eq!(Staking::slash_count(&10), 0);
|
|
assert_eq!(Balances::free_balance(&10), 70);
|
|
|
|
System::set_extrinsic_index(1);
|
|
Staking::on_offline_validator(10, 1);
|
|
assert_eq!(Staking::slash_count(&10), 1);
|
|
assert_eq!(Balances::free_balance(&10), 70);
|
|
assert_eq!(Staking::slash_count(&20), 0);
|
|
assert_eq!(Balances::free_balance(&20), 70);
|
|
|
|
System::set_extrinsic_index(1);
|
|
Staking::on_offline_validator(10, 1);
|
|
Staking::on_offline_validator(20, 1);
|
|
assert_eq!(Staking::slash_count(&10), 2);
|
|
assert_eq!(Balances::free_balance(&10), 50);
|
|
assert_eq!(Staking::slash_count(&20), 1);
|
|
assert_eq!(Balances::free_balance(&20), 70);
|
|
assert!(Staking::forcing_new_era().is_none());
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn note_offline_force_unstake_session_change_should_work() {
|
|
with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || {
|
|
Balances::set_free_balance(&10, 70);
|
|
Balances::set_free_balance(&20, 70);
|
|
assert_ok!(Staking::stake(Origin::signed(1)));
|
|
|
|
assert_eq!(Staking::slash_count(&10), 0);
|
|
assert_eq!(Balances::free_balance(&10), 70);
|
|
assert_eq!(Staking::intentions(), vec![10, 20, 1]);
|
|
assert_eq!(Session::validators(), vec![10, 20]);
|
|
|
|
System::set_extrinsic_index(1);
|
|
Staking::on_offline_validator(10, 1);
|
|
assert_eq!(Balances::free_balance(&10), 50);
|
|
assert_eq!(Staking::slash_count(&10), 1);
|
|
assert_eq!(Staking::intentions(), vec![10, 20, 1]);
|
|
|
|
System::set_extrinsic_index(1);
|
|
Staking::on_offline_validator(10, 1);
|
|
assert_eq!(Staking::intentions(), vec![1, 20]);
|
|
assert_eq!(Balances::free_balance(&10), 10);
|
|
assert!(Staking::forcing_new_era().is_some());
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn note_offline_auto_unstake_session_change_should_work() {
|
|
with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || {
|
|
Balances::set_free_balance(&10, 7000);
|
|
Balances::set_free_balance(&20, 7000);
|
|
assert_ok!(Staking::register_preferences(Origin::signed(10), 0, ValidatorPrefs { unstake_threshold: 1, validator_payment: 0 }));
|
|
|
|
assert_eq!(Staking::intentions(), vec![10, 20]);
|
|
|
|
System::set_extrinsic_index(1);
|
|
Staking::on_offline_validator(10, 1);
|
|
Staking::on_offline_validator(20, 1);
|
|
assert_eq!(Balances::free_balance(&10), 6980);
|
|
assert_eq!(Balances::free_balance(&20), 6980);
|
|
assert_eq!(Staking::intentions(), vec![10, 20]);
|
|
assert!(Staking::forcing_new_era().is_none());
|
|
|
|
System::set_extrinsic_index(1);
|
|
Staking::on_offline_validator(10, 1);
|
|
Staking::on_offline_validator(20, 1);
|
|
assert_eq!(Balances::free_balance(&10), 6940);
|
|
assert_eq!(Balances::free_balance(&20), 6940);
|
|
assert_eq!(Staking::intentions(), vec![20]);
|
|
assert!(Staking::forcing_new_era().is_some());
|
|
|
|
System::set_extrinsic_index(1);
|
|
Staking::on_offline_validator(20, 1);
|
|
assert_eq!(Balances::free_balance(&10), 6940);
|
|
assert_eq!(Balances::free_balance(&20), 6860);
|
|
assert_eq!(Staking::intentions(), vec![20]);
|
|
|
|
System::set_extrinsic_index(1);
|
|
Staking::on_offline_validator(20, 1);
|
|
assert_eq!(Balances::free_balance(&10), 6940);
|
|
assert_eq!(Balances::free_balance(&20), 6700);
|
|
assert_eq!(Staking::intentions(), vec![0u64; 0]);
|
|
});
|
|
}
|
|
|
|
|
|
#[test]
|
|
fn rewards_should_work() {
|
|
with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || {
|
|
assert_eq!(Staking::era_length(), 9);
|
|
assert_eq!(Staking::sessions_per_era(), 3);
|
|
assert_eq!(Staking::last_era_length_change(), 0);
|
|
assert_eq!(Staking::current_era(), 0);
|
|
assert_eq!(Session::current_index(), 0);
|
|
assert_eq!(Balances::total_balance(&10), 1);
|
|
|
|
System::set_block_number(3);
|
|
Timestamp::set_timestamp(15); // on time.
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Staking::current_era(), 0);
|
|
assert_eq!(Session::current_index(), 1);
|
|
assert_eq!(Balances::total_balance(&10), 11);
|
|
System::set_block_number(6);
|
|
Timestamp::set_timestamp(31); // a little late
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Staking::current_era(), 0);
|
|
assert_eq!(Session::current_index(), 2);
|
|
assert_eq!(Balances::total_balance(&10), 20); // less reward
|
|
System::set_block_number(9);
|
|
Timestamp::set_timestamp(50); // very late
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Staking::current_era(), 1);
|
|
assert_eq!(Session::current_index(), 3);
|
|
assert_eq!(Balances::total_balance(&10), 27); // much less reward
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn slashing_should_work() {
|
|
with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || {
|
|
assert_eq!(Staking::era_length(), 9);
|
|
assert_eq!(Staking::sessions_per_era(), 3);
|
|
assert_eq!(Staking::last_era_length_change(), 0);
|
|
assert_eq!(Staking::current_era(), 0);
|
|
assert_eq!(Session::current_index(), 0);
|
|
assert_eq!(Balances::total_balance(&10), 1);
|
|
|
|
System::set_block_number(3);
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Staking::current_era(), 0);
|
|
assert_eq!(Session::current_index(), 1);
|
|
assert_eq!(Balances::total_balance(&10), 11);
|
|
|
|
System::set_block_number(6);
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Staking::current_era(), 0);
|
|
assert_eq!(Session::current_index(), 2);
|
|
assert_eq!(Balances::total_balance(&10), 21);
|
|
|
|
System::set_block_number(7);
|
|
System::set_extrinsic_index(1);
|
|
Staking::on_offline_validator(10, 1);
|
|
Staking::on_offline_validator(20, 1);
|
|
assert_eq!(Balances::total_balance(&10), 1);
|
|
});
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
fn staking_should_work() {
|
|
with_externalities(&mut new_test_ext(0, 1, 2, 0, true, 0), || {
|
|
|
|
assert_eq!(Staking::era_length(), 2);
|
|
assert_eq!(Staking::validator_count(), 2);
|
|
assert_eq!(Session::validators(), vec![10, 20]);
|
|
|
|
assert_ok!(Staking::set_bonding_duration(2));
|
|
assert_eq!(Staking::bonding_duration(), 2);
|
|
|
|
// Block 1: Add three validators. No obvious change.
|
|
System::set_block_number(1);
|
|
assert_ok!(Staking::stake(Origin::signed(1)));
|
|
assert_ok!(Staking::stake(Origin::signed(2)));
|
|
assert_ok!(Staking::stake(Origin::signed(4)));
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Staking::current_era(), 0);
|
|
assert_eq!(Session::validators(), vec![10, 20]);
|
|
|
|
// Block 2: New validator set now.
|
|
System::set_block_number(2);
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Staking::current_era(), 1);
|
|
assert_eq!(Session::validators(), vec![4, 2]);
|
|
|
|
// Block 3: Unstake highest, introduce another staker. No change yet.
|
|
System::set_block_number(3);
|
|
assert_ok!(Staking::stake(Origin::signed(3)));
|
|
assert_ok!(Staking::unstake(Origin::signed(4), (Staking::intentions().iter().position(|&x| x == 4).unwrap() as u32).into()));
|
|
assert_eq!(Staking::current_era(), 1);
|
|
Session::check_rotate_session(System::block_number());
|
|
|
|
// Block 4: New era - validators change.
|
|
System::set_block_number(4);
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Staking::current_era(), 2);
|
|
assert_eq!(Session::validators(), vec![3, 2]);
|
|
|
|
// Block 5: Transfer stake from highest to lowest. No change yet.
|
|
System::set_block_number(5);
|
|
assert_ok!(Balances::transfer(Origin::signed(4), 1, 40));
|
|
Session::check_rotate_session(System::block_number());
|
|
|
|
// Block 6: Lowest now validator.
|
|
System::set_block_number(6);
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Session::validators(), vec![1, 3]);
|
|
|
|
// Block 7: Unstake three. No change yet.
|
|
System::set_block_number(7);
|
|
assert_ok!(Staking::unstake(Origin::signed(3), (Staking::intentions().iter().position(|&x| x == 3).unwrap() as u32).into()));
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Session::validators(), vec![1, 3]);
|
|
|
|
// Block 8: Back to one and two.
|
|
System::set_block_number(8);
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Session::validators(), vec![1, 2]);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn nominating_and_rewards_should_work() {
|
|
with_externalities(&mut new_test_ext(0, 1, 1, 0, true, 10), || {
|
|
assert_eq!(Staking::era_length(), 1);
|
|
assert_eq!(Staking::validator_count(), 2);
|
|
assert_eq!(Staking::bonding_duration(), 3);
|
|
assert_eq!(Session::validators(), vec![10, 20]);
|
|
|
|
System::set_block_number(1);
|
|
assert_ok!(Staking::stake(Origin::signed(1)));
|
|
assert_ok!(Staking::stake(Origin::signed(2)));
|
|
assert_ok!(Staking::stake(Origin::signed(3)));
|
|
assert_ok!(Staking::nominate(Origin::signed(4), 1));
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Staking::current_era(), 1);
|
|
assert_eq!(Session::validators(), vec![1, 3]); // 4 + 1, 3
|
|
assert_eq!(Balances::total_balance(&1), 10);
|
|
assert_eq!(Balances::total_balance(&2), 20);
|
|
assert_eq!(Balances::total_balance(&3), 30);
|
|
assert_eq!(Balances::total_balance(&4), 40);
|
|
|
|
System::set_block_number(2);
|
|
assert_ok!(Staking::unnominate(Origin::signed(4), 0));
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Staking::current_era(), 2);
|
|
assert_eq!(Session::validators(), vec![3, 2]);
|
|
assert_eq!(Balances::total_balance(&1), 16);
|
|
assert_eq!(Balances::total_balance(&2), 20);
|
|
assert_eq!(Balances::total_balance(&3), 60);
|
|
assert_eq!(Balances::total_balance(&4), 64);
|
|
|
|
System::set_block_number(3);
|
|
assert_ok!(Staking::stake(Origin::signed(4)));
|
|
assert_ok!(Staking::unstake(Origin::signed(3), (Staking::intentions().iter().position(|&x| x == 3).unwrap() as u32).into()));
|
|
assert_ok!(Staking::nominate(Origin::signed(3), 1));
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Session::validators(), vec![1, 4]);
|
|
assert_eq!(Balances::total_balance(&1), 16);
|
|
assert_eq!(Balances::total_balance(&2), 40);
|
|
assert_eq!(Balances::total_balance(&3), 80);
|
|
assert_eq!(Balances::total_balance(&4), 64);
|
|
|
|
System::set_block_number(4);
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Balances::total_balance(&1), 26);
|
|
assert_eq!(Balances::total_balance(&2), 40);
|
|
assert_eq!(Balances::total_balance(&3), 133);
|
|
assert_eq!(Balances::total_balance(&4), 128);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn rewards_with_off_the_table_should_work() {
|
|
with_externalities(&mut new_test_ext(0, 1, 1, 0, true, 10), || {
|
|
System::set_block_number(1);
|
|
assert_ok!(Staking::stake(Origin::signed(1)));
|
|
assert_ok!(Staking::nominate(Origin::signed(2), 1));
|
|
assert_ok!(Staking::stake(Origin::signed(3)));
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Session::validators(), vec![1, 3]); // 1 + 2, 3
|
|
assert_eq!(Balances::total_balance(&1), 10);
|
|
assert_eq!(Balances::total_balance(&2), 20);
|
|
assert_eq!(Balances::total_balance(&3), 30);
|
|
|
|
System::set_block_number(2);
|
|
assert_ok!(Staking::register_preferences(
|
|
Origin::signed(1),
|
|
(Staking::intentions().into_iter().position(|i| i == 1).unwrap() as u32).into(),
|
|
ValidatorPrefs { unstake_threshold: 3, validator_payment: 4 }
|
|
));
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Balances::total_balance(&1), 22);
|
|
assert_eq!(Balances::total_balance(&2), 37);
|
|
assert_eq!(Balances::total_balance(&3), 60);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn nominating_slashes_should_work() {
|
|
with_externalities(&mut new_test_ext(0, 2, 2, 0, true, 10), || {
|
|
assert_eq!(Staking::era_length(), 4);
|
|
assert_eq!(Staking::validator_count(), 2);
|
|
assert_eq!(Staking::bonding_duration(), 12);
|
|
assert_eq!(Session::validators(), vec![10, 20]);
|
|
|
|
System::set_block_number(2);
|
|
Session::check_rotate_session(System::block_number());
|
|
|
|
Timestamp::set_timestamp(15);
|
|
System::set_block_number(4);
|
|
assert_ok!(Staking::stake(Origin::signed(1)));
|
|
assert_ok!(Staking::stake(Origin::signed(3)));
|
|
assert_ok!(Staking::nominate(Origin::signed(2), 3));
|
|
assert_ok!(Staking::nominate(Origin::signed(4), 1));
|
|
Session::check_rotate_session(System::block_number());
|
|
|
|
assert_eq!(Staking::current_era(), 1);
|
|
assert_eq!(Session::validators(), vec![1, 3]); // 1 + 4, 3 + 2
|
|
assert_eq!(Balances::total_balance(&1), 10);
|
|
assert_eq!(Balances::total_balance(&2), 20);
|
|
assert_eq!(Balances::total_balance(&3), 30);
|
|
assert_eq!(Balances::total_balance(&4), 40);
|
|
|
|
System::set_block_number(5);
|
|
System::set_extrinsic_index(1);
|
|
Staking::on_offline_validator(1, 1);
|
|
Staking::on_offline_validator(3, 1);
|
|
assert_eq!(Balances::total_balance(&1), 0); //slashed
|
|
assert_eq!(Balances::total_balance(&2), 20); //not slashed
|
|
assert_eq!(Balances::total_balance(&3), 10); //slashed
|
|
assert_eq!(Balances::total_balance(&4), 30); //slashed
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn double_staking_should_fail() {
|
|
with_externalities(&mut new_test_ext(0, 1, 2, 0, true, 0), || {
|
|
System::set_block_number(1);
|
|
assert_ok!(Staking::stake(Origin::signed(1)));
|
|
assert_noop!(Staking::stake(Origin::signed(1)), "Cannot stake if already staked.");
|
|
assert_noop!(Staking::nominate(Origin::signed(1), 1), "Cannot nominate if already staked.");
|
|
assert_ok!(Staking::nominate(Origin::signed(2), 1));
|
|
assert_noop!(Staking::stake(Origin::signed(2)), "Cannot stake if already nominating.");
|
|
assert_noop!(Staking::nominate(Origin::signed(2), 1), "Cannot nominate if already nominating.");
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn staking_eras_work() {
|
|
with_externalities(&mut new_test_ext(0, 1, 2, 0, true, 0), || {
|
|
assert_eq!(Staking::era_length(), 2);
|
|
assert_eq!(Staking::sessions_per_era(), 2);
|
|
assert_eq!(Staking::last_era_length_change(), 0);
|
|
assert_eq!(Staking::current_era(), 0);
|
|
assert_eq!(Session::current_index(), 0);
|
|
|
|
// Block 1: No change.
|
|
System::set_block_number(1);
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Session::current_index(), 1);
|
|
assert_eq!(Staking::sessions_per_era(), 2);
|
|
assert_eq!(Staking::last_era_length_change(), 0);
|
|
assert_eq!(Staking::current_era(), 0);
|
|
|
|
// Block 2: Simple era change.
|
|
System::set_block_number(2);
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Session::current_index(), 2);
|
|
assert_eq!(Staking::sessions_per_era(), 2);
|
|
assert_eq!(Staking::last_era_length_change(), 0);
|
|
assert_eq!(Staking::current_era(), 1);
|
|
|
|
// Block 3: Schedule an era length change; no visible changes.
|
|
System::set_block_number(3);
|
|
assert_ok!(Staking::set_sessions_per_era(3));
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Session::current_index(), 3);
|
|
assert_eq!(Staking::sessions_per_era(), 2);
|
|
assert_eq!(Staking::last_era_length_change(), 0);
|
|
assert_eq!(Staking::current_era(), 1);
|
|
|
|
// Block 4: Era change kicks in.
|
|
System::set_block_number(4);
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Session::current_index(), 4);
|
|
assert_eq!(Staking::sessions_per_era(), 3);
|
|
assert_eq!(Staking::last_era_length_change(), 4);
|
|
assert_eq!(Staking::current_era(), 2);
|
|
|
|
// Block 5: No change.
|
|
System::set_block_number(5);
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Session::current_index(), 5);
|
|
assert_eq!(Staking::sessions_per_era(), 3);
|
|
assert_eq!(Staking::last_era_length_change(), 4);
|
|
assert_eq!(Staking::current_era(), 2);
|
|
|
|
// Block 6: No change.
|
|
System::set_block_number(6);
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Session::current_index(), 6);
|
|
assert_eq!(Staking::sessions_per_era(), 3);
|
|
assert_eq!(Staking::last_era_length_change(), 4);
|
|
assert_eq!(Staking::current_era(), 2);
|
|
|
|
// Block 7: Era increment.
|
|
System::set_block_number(7);
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Session::current_index(), 7);
|
|
assert_eq!(Staking::sessions_per_era(), 3);
|
|
assert_eq!(Staking::last_era_length_change(), 4);
|
|
assert_eq!(Staking::current_era(), 3);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn staking_balance_transfer_when_bonded_should_not_work() {
|
|
with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || {
|
|
Balances::set_free_balance(&1, 111);
|
|
assert_ok!(Staking::stake(Origin::signed(1)));
|
|
assert_noop!(Balances::transfer(Origin::signed(1), 2, 69), "cannot transfer illiquid funds");
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn deducting_balance_when_bonded_should_not_work() {
|
|
with_externalities(&mut new_test_ext(0, 1, 3, 1, false, 0), || {
|
|
Balances::set_free_balance(&1, 111);
|
|
<Bondage<Test>>::insert(1, 2);
|
|
System::set_block_number(1);
|
|
assert_eq!(Staking::unlock_block(&1), LockStatus::LockedUntil(2));
|
|
assert_noop!(Balances::reserve(&1, 69), "cannot transfer illiquid funds");
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn slash_value_calculation_does_not_overflow() {
|
|
with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || {
|
|
assert_eq!(Staking::era_length(), 9);
|
|
assert_eq!(Staking::sessions_per_era(), 3);
|
|
assert_eq!(Staking::last_era_length_change(), 0);
|
|
assert_eq!(Staking::current_era(), 0);
|
|
assert_eq!(Session::current_index(), 0);
|
|
assert_eq!(Balances::total_balance(&10), 1);
|
|
assert_eq!(Staking::intentions(), vec![10, 20]);
|
|
assert_eq!(Staking::offline_slash_grace(), 0);
|
|
|
|
// set validator preferences so the validator doesn't back down after
|
|
// slashing.
|
|
<ValidatorPreferences<Test>>::insert(10, ValidatorPrefs {
|
|
unstake_threshold: u32::max_value(),
|
|
validator_payment: 0,
|
|
});
|
|
|
|
System::set_block_number(3);
|
|
Session::check_rotate_session(System::block_number());
|
|
assert_eq!(Staking::current_era(), 0);
|
|
assert_eq!(Session::current_index(), 1);
|
|
assert_eq!(Balances::total_balance(&10), 11);
|
|
|
|
// the balance type is u64, so after slashing 64 times,
|
|
// the slash value should have overflowed. add a couple extra for
|
|
// good measure with the slash grace.
|
|
trait TypeEq {}
|
|
impl<A> TypeEq for (A, A) {}
|
|
fn assert_type_eq<A: TypeEq>() {}
|
|
assert_type_eq::<(u64, <Test as balances::Trait>::Balance)>();
|
|
|
|
Staking::on_offline_validator(10, 100);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn next_slash_value_calculation_does_not_overflow() {
|
|
with_externalities(&mut new_test_ext(0, 3, 3, 0, true, 10), || {
|
|
assert_eq!(Staking::era_length(), 9);
|
|
assert_eq!(Staking::sessions_per_era(), 3);
|
|
assert_eq!(Staking::last_era_length_change(), 0);
|
|
assert_eq!(Staking::current_era(), 0);
|
|
assert_eq!(Session::current_index(), 0);
|
|
assert_eq!(Balances::total_balance(&10), 1);
|
|
assert_eq!(Staking::intentions(), vec![10, 20]);
|
|
assert_eq!(Staking::offline_slash_grace(), 0);
|
|
|
|
// set validator preferences so the validator doesn't back down after
|
|
// slashing.
|
|
<ValidatorPreferences<Test>>::insert(10, ValidatorPrefs {
|
|
unstake_threshold: u32::max_value(),
|
|
validator_payment: 0,
|
|
});
|
|
|
|
// we have enough balance to cover the last slash before overflow
|
|
Balances::set_free_balance(&10, u64::max_value());
|
|
assert_eq!(Balances::total_balance(&10), u64::max_value());
|
|
|
|
// the balance type is u64, so after slashing 64 times,
|
|
// the slash value should have overflowed. add a couple extra for
|
|
// good measure with the slash grace.
|
|
trait TypeEq {}
|
|
impl<A> TypeEq for (A, A) {}
|
|
fn assert_type_eq<A: TypeEq>() {}
|
|
assert_type_eq::<(u64, <Test as balances::Trait>::Balance)>();
|
|
|
|
// the total slash value should overflow the balance type
|
|
// therefore the total validator balance should be slashed
|
|
Staking::on_offline_validator(10, 100);
|
|
|
|
assert_eq!(Balances::total_balance(&10), 0);
|
|
});
|
|
}
|