diff --git a/pallets/staking/src/lib.rs b/pallets/staking/src/lib.rs index beaef29ed..4674f6106 100644 --- a/pallets/staking/src/lib.rs +++ b/pallets/staking/src/lib.rs @@ -411,10 +411,7 @@ pub mod pallet { pallet_staking::Pallet::::ledger(StakingAccount::Controller(controller.clone())) .map_err(|_| Error::::NoThresholdKey)?; - let validator_id = ::ValidatorId::try_from(ledger.stash) - .or(Err(Error::::InvalidValidatorId))?; - - let signers_length = Self::ensure_not_signer_or_next_signer(&validator_id)?; + let signers_length = Self::ensure_not_signer_or_next_signer(&ledger.stash)?; pallet_staking::Pallet::::unbond(origin, value)?; @@ -430,10 +427,7 @@ pub mod pallet { pallet_staking::Pallet::::ledger(StakingAccount::Controller(controller.clone())) .map_err(|_| Error::::NoThresholdKey)?; - let validator_id = ::ValidatorId::try_from(ledger.stash) - .or(Err(Error::::InvalidValidatorId))?; - - let signers_length = Self::ensure_not_signer_or_next_signer(&validator_id)?; + let signers_length = Self::ensure_not_signer_or_next_signer(&ledger.stash)?; pallet_staking::Pallet::::chill(origin)?; @@ -452,10 +446,11 @@ pub mod pallet { pallet_staking::Pallet::::ledger(StakingAccount::Controller(controller.clone())) .map_err(|_| Error::::NoThresholdKey)?; - let validator_id = ::ValidatorId::try_from(ledger.stash) - .or(Err(Error::::InvalidValidatorId))?; + let validator_id = + ::ValidatorId::try_from(ledger.stash.clone()) + .or(Err(Error::::InvalidValidatorId))?; - let signers_length = Self::ensure_not_signer_or_next_signer(&validator_id)?; + let signers_length = Self::ensure_not_signer_or_next_signer(&ledger.stash)?; pallet_staking::Pallet::::withdraw_unbonded(origin, num_slashing_spans)?; // TODO: do not allow unbonding of validator if not enough validators https://github.com/entropyxyz/entropy-core/issues/942 @@ -572,16 +567,42 @@ pub mod pallet { /// Ensures that the current validator is not a signer or a next signer pub fn ensure_not_signer_or_next_signer( - validator_id: &::ValidatorId, + stash: &T::AccountId, ) -> Result { + let validator_id = ::ValidatorId::try_from(stash.clone()) + .or(Err(Error::::InvalidValidatorId))?; + let nominations = pallet_staking::Nominators::::get(stash) + .map_or_else(Vec::new, |x| x.targets.into_inner()); + let signers = Self::signers(); - ensure!(!signers.contains(validator_id), Error::::NoUnbondingWhenSigner); + ensure!(!signers.contains(&validator_id), Error::::NoUnbondingWhenSigner); + for nominated in &nominations { + let validator_id_nominated = + ::ValidatorId::try_from(nominated.clone()) + .or(Err(Error::::InvalidValidatorId))?; + ensure!( + !signers.contains(&validator_id_nominated), + Error::::NoUnbondingWhenSigner + ); + } + + ensure!(!signers.contains(&validator_id), Error::::NoUnbondingWhenSigner); if let Some(next_signers) = Self::next_signers() { ensure!( - !next_signers.next_signers.contains(validator_id), + !next_signers.next_signers.contains(&validator_id), Error::::NoUnbondingWhenNextSigner ); + + for nominated in &nominations { + let validator_id_nominated = + ::ValidatorId::try_from(nominated.clone()) + .or(Err(Error::::InvalidValidatorId))?; + ensure!( + !next_signers.next_signers.contains(&validator_id_nominated), + Error::::NoUnbondingWhenNextSigner + ); + } } Ok(signers.len() as u32) diff --git a/pallets/staking/src/mock.rs b/pallets/staking/src/mock.rs index 9eeb4cdab..036488544 100644 --- a/pallets/staking/src/mock.rs +++ b/pallets/staking/src/mock.rs @@ -396,7 +396,7 @@ impl pallet_parameters::Config for Test { pub fn new_test_ext() -> sp_io::TestExternalities { let mut t = system::GenesisConfig::::default().build_storage().unwrap(); let pallet_balances = pallet_balances::GenesisConfig:: { - balances: vec![(1, 100), (2, 100), (3, 100), (4, 100), (7, 100), (8, 100)], + balances: vec![(1, 100), (2, 100), (3, 100), (4, 100), (7, 100), (8, 100), (101, 200)], }; let pallet_staking_extension = pallet_staking_extension::GenesisConfig:: { // (ValidatorID, (AccountId, X25519PublicKey, TssServerURL)) diff --git a/pallets/staking/src/tests.rs b/pallets/staking/src/tests.rs index a1c905e90..29ce8a8b4 100644 --- a/pallets/staking/src/tests.rs +++ b/pallets/staking/src/tests.rs @@ -521,6 +521,18 @@ fn it_stops_chill_when_signer_or_next_signer() { Signers::::put(vec![7]); start_active_era(1); + assert_ok!(FrameStaking::bond( + RuntimeOrigin::signed(101), + 100u64, + pallet_staking::RewardDestination::Account(1), + )); + // test nominating flow + assert_ok!(FrameStaking::nominate(RuntimeOrigin::signed(101), vec![7])); + assert_noop!( + Staking::unbond(RuntimeOrigin::signed(101), 100u64), + Error::::NoUnbondingWhenSigner + ); + assert_ok!(FrameStaking::bond( RuntimeOrigin::signed(7), 100u64, @@ -544,5 +556,11 @@ fn it_stops_chill_when_signer_or_next_signer() { Staking::chill(RuntimeOrigin::signed(8)), Error::::NoUnbondingWhenNextSigner ); + + assert_ok!(FrameStaking::nominate(RuntimeOrigin::signed(101), vec![8])); + assert_noop!( + Staking::unbond(RuntimeOrigin::signed(101), 100u64), + Error::::NoUnbondingWhenNextSigner + ); }); }