Lines
99.77 %
Functions
100 %
Branches
// Copyright (C) Moondance Labs Ltd.
// This file is part of Tanssi.
// Tanssi 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.
// Tanssi 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 Tanssi. If not, see <http://www.gnu.org/licenses/>
use crate::{assert_eq_last_events, candidate::EligibleCandidate, SortedEligibleCandidates};
use super::*;
pool_test!(
fn self_delegation_below_minimum<P>() {
ExtBuilder::default().build().execute_with(|| {
let requested_amount = MinimumSelfDelegation::get() - 1;
let final_amount = round_down(
requested_amount,
P::shares_to_stake_or_init(&ACCOUNT_CANDIDATE_1, Shares(1))
.unwrap()
.0,
);
FullDelegation {
candidate: ACCOUNT_CANDIDATE_1,
delegator: ACCOUNT_CANDIDATE_1,
request_amount: requested_amount,
expected_increase: final_amount,
..default()
}
.test::<P>();
assert_eq_events!(vec![
Event::IncreasedStake {
stake_diff: round_down(requested_amount, 2),
},
Event::UpdatedCandidatePosition {
stake: round_down(requested_amount, 2),
self_delegation: round_down(requested_amount, 2),
before: None,
after: None,
Event::RequestedDelegate {
pool: P::target_pool(),
pending: round_down(requested_amount, 2),
Event::DecreasedStake {
stake_diff: round_down(requested_amount, 2) - final_amount,
stake: final_amount,
self_delegation: final_amount,
P::event_staked(ACCOUNT_CANDIDATE_1, ACCOUNT_CANDIDATE_1, 9, final_amount),
Event::ExecutedDelegate {
staked: final_amount,
released: round_down(requested_amount, 2) - final_amount,
]);
})
fn self_delegation_above_minimum<P>() {
let requested_amount = MinimumSelfDelegation::get();
FullUndelegation {
request_amount: SharesOrStake::Stake(requested_amount * 2),
expected_removed: requested_amount * 2,
expected_leaving: round_down(requested_amount * 2, 3),
// delegation 1
after: Some(0),
P::event_staked(ACCOUNT_CANDIDATE_1, ACCOUNT_CANDIDATE_1, 10, final_amount),
// delegation 2
stake: round_down(requested_amount * 2, 2),
self_delegation: round_down(requested_amount * 2, 2),
before: Some(0),
// undelegation
stake_diff: requested_amount * 2,
stake: 0,
self_delegation: 0,
Event::RequestedUndelegate {
from: P::target_pool(),
pending: round_down(requested_amount * 2, 3),
released: 2,
Event::ExecutedUndelegate {
released: round_down(requested_amount * 2, 3)
#[test]
fn many_candidates_mixed_pools() {
let share = InitialAutoCompoundingShareValue::get();
// for simplicity we consider shares of both pools have the same value.
assert_eq!(
InitialAutoCompoundingShareValue::get(),
InitialManualClaimShareValue::get()
struct Action {
candidate: AccountId,
delegator: AccountId,
join: bool,
auto: bool,
amount: Balance,
total_stake: Balance,
total_self: Balance,
rank_before: Option<u32>,
rank_after: Option<u32>,
fn perform_actions(actions: &[Action]) {
for action in actions {
match action {
Action {
join: true,
auto: true,
..
} => {
candidate: action.candidate,
delegator: action.delegator,
request_amount: action.amount,
expected_increase: action.amount,
.test::<pools::AutoCompounding<Runtime>>();
assert_eq_last_events!(vec![
Event::<Runtime>::IncreasedStake {
stake_diff: action.amount,
stake: action.total_stake,
self_delegation: action.total_self,
before: action.rank_before,
after: action.rank_after,
pool: ActivePoolKind::AutoCompounding,
pending: action.amount,
Event::StakedAutoCompounding {
shares: action.amount / share,
stake: action.amount,
staked: action.amount,
released: 0,
])
auto: false,
.test::<pools::ManualRewards<Runtime>>();
pool: ActivePoolKind::ManualRewards,
Event::StakedManualRewards {
join: false,
request_amount: SharesOrStake::Stake(action.amount),
expected_removed: action.amount,
expected_leaving: round_down(action.amount, 3),
Event::<Runtime>::DecreasedStake {
from: ActivePoolKind::AutoCompounding,
pending: round_down(action.amount, 3),
released: action.amount - round_down(action.amount, 3),
released: round_down(action.amount, 3),
_ => todo!(),
perform_actions(&[
amount: share * 11,
total_stake: share * 11,
total_self: share * 11,
rank_before: None,
rank_after: Some(0),
candidate: ACCOUNT_CANDIDATE_2,
delegator: ACCOUNT_CANDIDATE_2,
amount: share * 10,
total_stake: share * 10,
total_self: share * 10,
rank_after: Some(1),
delegator: ACCOUNT_DELEGATOR_1,
amount: share * 3,
total_stake: share * 13,
rank_before: Some(1),
delegator: ACCOUNT_DELEGATOR_2,
amount: share,
total_stake: share * 12,
candidate: ACCOUNT_DELEGATOR_1,
rank_after: Some(2),
candidate: ACCOUNT_DELEGATOR_2,
rank_after: None, // list is full
SortedEligibleCandidates::<Runtime>::get().into_inner(),
vec![
EligibleCandidate {
stake: share * 13,
stake: share * 12,
stake: share * 11,
]
// We make candidate 1 leave, which doesn't make the out of list
// candidate back in the list.
perform_actions(&[Action {
total_stake: share * 1,
total_self: 0,
rank_after: None,
}]);
// It needs to be done manually.
assert_ok!(Staking::update_candidate_position(
RuntimeOrigin::signed(ACCOUNT_DELEGATOR_2),
vec![ACCOUNT_DELEGATOR_2]
));
stake: share * 10,