Skip to content

Commit

Permalink
[MOON-1745] re-add status Leaving as deprecated (#1702)
Browse files Browse the repository at this point in the history
* merge master

* fix tests

* fix toJSON
  • Loading branch information
nbaztec authored and Crystalin committed Jul 21, 2022
1 parent 36095d5 commit 4b12902
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 3 deletions.
48 changes: 47 additions & 1 deletion pallets/parachain-staking/src/delegation_requests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::pallet::{
BalanceOf, CandidateInfo, Config, DelegationScheduledRequests, DelegatorState, Error, Event,
Pallet, Round, RoundIndex, Total,
};
use crate::Delegator;
use crate::{Delegator, DelegatorStatus};
use frame_support::ensure;
use frame_support::traits::Get;
use frame_support::{dispatch::DispatchResultWithPostInfo, RuntimeDebug};
Expand Down Expand Up @@ -342,6 +342,13 @@ impl<T: Config> Pallet<T> {
let now = <Round<T>>::get().current;
let when = now.saturating_add(T::LeaveDelegatorsDelay::get());

// lazy migration for DelegatorStatus::Leaving
#[allow(deprecated)]
if matches!(state.status, DelegatorStatus::Leaving(_)) {
state.status = DelegatorStatus::Active;
<DelegatorState<T>>::insert(delegator.clone(), state.clone());
}

// it is assumed that a multiple delegations to the same collator does not exist, else this
// will cause a bug - the last duplicate delegation update will be the only one applied.
let mut existing_revoke_count = 0;
Expand Down Expand Up @@ -398,6 +405,15 @@ impl<T: Config> Pallet<T> {
let mut state = <DelegatorState<T>>::get(&delegator).ok_or(<Error<T>>::DelegatorDNE)?;
let mut updated_scheduled_requests = vec![];

// backwards compatible handling for DelegatorStatus::Leaving
#[allow(deprecated)]
if matches!(state.status, DelegatorStatus::Leaving(_)) {
state.status = DelegatorStatus::Active;
<DelegatorState<T>>::insert(delegator.clone(), state.clone());
Self::deposit_event(Event::DelegatorExitCancelled { delegator });
return Ok(().into());
}

// pre-validate that all delegations have a Revoke request.
for bond in &state.delegations.0 {
let collator = bond.owner.clone();
Expand Down Expand Up @@ -444,6 +460,36 @@ impl<T: Config> Pallet<T> {
);
let now = <Round<T>>::get().current;

// backwards compatible handling for DelegatorStatus::Leaving
#[allow(deprecated)]
if let DelegatorStatus::Leaving(when) = state.status {
ensure!(
<Round<T>>::get().current >= when,
Error::<T>::DelegatorCannotLeaveYet
);

for bond in state.delegations.0.clone() {
if let Err(error) = Self::delegator_leaves_candidate(
bond.owner.clone(),
delegator.clone(),
bond.amount,
) {
log::warn!(
"STORAGE CORRUPTED \nDelegator leaving collator failed with error: {:?}",
error
);
}

Self::delegation_remove_request_with_state(&bond.owner, &delegator, &mut state);
}
<DelegatorState<T>>::remove(&delegator);
Self::deposit_event(Event::DelegatorLeft {
delegator,
unstaked_amount: state.total,
});
return Ok(().into());
}

let mut validated_scheduled_requests = vec![];
// pre-validate that all delegations have a Revoke request that can be executed now.
for bond in &state.delegations.0 {
Expand Down
120 changes: 119 additions & 1 deletion pallets/parachain-staking/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ use crate::{
assert_eq_events, assert_eq_last_events, assert_event_emitted, assert_last_event,
assert_tail_eq, set::OrderedSet, AtStake, Bond, BottomDelegations, CandidateInfo,
CandidateMetadata, CandidatePool, CapacityStatus, CollatorStatus, DelegationScheduledRequests,
Delegations, DelegatorAdded, Error, Event, Range, TopDelegations, DELEGATOR_LOCK_ID,
Delegations, DelegatorAdded, DelegatorState, DelegatorStatus, Error, Event, Range,
TopDelegations, DELEGATOR_LOCK_ID,
};
use frame_support::{assert_noop, assert_ok};
use sp_runtime::{traits::Zero, DispatchError, ModuleError, Perbill, Percent};
Expand Down Expand Up @@ -9451,3 +9452,120 @@ mod jit_migrate_reserve_to_locks_tests {
// * other tests around lquidity checks (can't bond_more if not enough unlocked amount, etc)
// * request cancellation
}
#[allow(deprecated)]
#[test]
fn test_delegator_with_deprecated_status_leaving_can_schedule_leave_delegators_as_fix() {
ExtBuilder::default()
.with_balances(vec![(1, 20), (2, 40)])
.with_candidates(vec![(1, 20)])
.with_delegations(vec![(2, 1, 10)])
.build()
.execute_with(|| {
<DelegatorState<Test>>::mutate(2, |value| {
value.as_mut().map(|mut state| {
state.status = DelegatorStatus::Leaving(2);
})
});
let state = <DelegatorState<Test>>::get(2);
assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_)));

assert_ok!(ParachainStaking::schedule_leave_delegators(Origin::signed(
2
)));
assert!(<DelegationScheduledRequests<Test>>::get(1)
.iter()
.any(|r| r.delegator == 2 && matches!(r.action, DelegationAction::Revoke(_))));
assert_last_event!(MetaEvent::ParachainStaking(Event::DelegatorExitScheduled {
round: 1,
delegator: 2,
scheduled_exit: 3
}));

let state = <DelegatorState<Test>>::get(2);
assert!(matches!(state.unwrap().status, DelegatorStatus::Active));
});
}

#[allow(deprecated)]
#[test]
fn test_delegator_with_deprecated_status_leaving_can_cancel_leave_delegators_as_fix() {
ExtBuilder::default()
.with_balances(vec![(1, 20), (2, 40)])
.with_candidates(vec![(1, 20)])
.with_delegations(vec![(2, 1, 10)])
.build()
.execute_with(|| {
<DelegatorState<Test>>::mutate(2, |value| {
value.as_mut().map(|mut state| {
state.status = DelegatorStatus::Leaving(2);
})
});
let state = <DelegatorState<Test>>::get(2);
assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_)));

assert_ok!(ParachainStaking::cancel_leave_delegators(Origin::signed(2)));
assert_last_event!(MetaEvent::ParachainStaking(Event::DelegatorExitCancelled {
delegator: 2
}));

let state = <DelegatorState<Test>>::get(2);
assert!(matches!(state.unwrap().status, DelegatorStatus::Active));
});
}

#[allow(deprecated)]
#[test]
fn test_delegator_with_deprecated_status_leaving_can_execute_leave_delegators_as_fix() {
ExtBuilder::default()
.with_balances(vec![(1, 20), (2, 40)])
.with_candidates(vec![(1, 20)])
.with_delegations(vec![(2, 1, 10)])
.build()
.execute_with(|| {
<DelegatorState<Test>>::mutate(2, |value| {
value.as_mut().map(|mut state| {
state.status = DelegatorStatus::Leaving(2);
})
});
let state = <DelegatorState<Test>>::get(2);
assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_)));

roll_to(10);
assert_ok!(ParachainStaking::execute_leave_delegators(
Origin::signed(2),
2,
1
));
assert_event_emitted!(Event::DelegatorLeft {
delegator: 2,
unstaked_amount: 10
});

let state = <DelegatorState<Test>>::get(2);
assert!(state.is_none());
});
}

#[allow(deprecated)]
#[test]
fn test_delegator_with_deprecated_status_leaving_cannot_execute_leave_delegators_early_no_fix() {
ExtBuilder::default()
.with_balances(vec![(1, 20), (2, 40)])
.with_candidates(vec![(1, 20)])
.with_delegations(vec![(2, 1, 10)])
.build()
.execute_with(|| {
<DelegatorState<Test>>::mutate(2, |value| {
value.as_mut().map(|mut state| {
state.status = DelegatorStatus::Leaving(2);
})
});
let state = <DelegatorState<Test>>::get(2);
assert!(matches!(state.unwrap().status, DelegatorStatus::Leaving(_)));

assert_noop!(
ParachainStaking::execute_leave_delegators(Origin::signed(2), 2, 1),
Error::<Test>::DelegatorCannotLeaveYet
);
});
}
4 changes: 4 additions & 0 deletions pallets/parachain-staking/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1211,10 +1211,14 @@ impl<A: Clone, B: Copy> From<CollatorCandidate<A, B>> for CollatorSnapshot<A, B>
}
}

#[allow(deprecated)]
#[derive(Clone, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
pub enum DelegatorStatus {
/// Active with no scheduled exit
Active,
/// Schedule exit to revoke all ongoing delegations
#[deprecated(note = "must only be used for backwards compatibility reasons")]
Leaving(RoundIndex),
}

#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/test-staking/test-delegator-join.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ describeDevMoonbeam("Staking - Delegator Join - valid request", (context) => {
],
id: ethan.address,
lessTotal: 0,
status: "Active",
status: { active: null },
total: numberToHex(MIN_GLMR_DELEGATOR),
});
});
Expand Down

0 comments on commit 4b12902

Please sign in to comment.