Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(DNM) Prevent users from both directly staking and joining pool #4804

Closed
wants to merge 29 commits into from

Conversation

Ank4n
Copy link
Contributor

@Ank4n Ank4n commented Jun 15, 2024

Context

Currently, an account can do both, directly stake, and join a pool.

With the migration of pools to DelegateStake (See #3905), the funds of pool members are locked in a different way than for direct stakers.

  • Pool member funds will use holds after migration.
  • pallet-staking uses deprecated locks (analogous to freeze) but they can overlap with holds.

Note that once we migrate pallet-staking to use fungibles, it will also start using non-overlapping holds.

Risk

This makes it possible for a direct staker to reuse the staked (frozen) funds to be used for participating in a pool (hold) as well. Essentially double staking with the same funds.

This is prevented currently by pallet-delegated-staking not allowing direct stakers to delegate, as well as by pallet-staking only taking free balance into account. But this is not documented well and a bit fragile.

Changes

A better way would be to make pool and staking mutually exclusive. This PR introduces a new config type Blacklist to pallet-nomination-pools and pallet-staking that can be configured to blacklist some accounts from participating in respective pallets. We then blacklist all pallet-staking stakers from participating in pools, and all pool members from participating in pallet-staking.

Note that there are 648 accounts in Polkadot and 321 accounts in Kusama who are both pool member and a staker. After this change, these accounts would not be able to bond extra funds to their stake but can still withdraw. Once they have withdrawn all their funds from pool, they would be able to bond additional funds to staking and vice versa.

@Ank4n Ank4n force-pushed the ankan/mutually-exclusive-pool-stakers branch from 54db650 to f77ddfc Compare June 15, 2024 21:34
@paritytech-cicd-pr
Copy link

The CI pipeline was cancelled due to failure one of the required jobs.
Job name: cargo-clippy
Logs: https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/6471123

@Ank4n Ank4n marked this pull request as ready for review June 17, 2024 15:17
@Ank4n Ank4n requested a review from a team as a code owner June 17, 2024 15:17
@Ank4n Ank4n added the T2-pallets This PR/Issue is related to a particular pallet. label Jun 17, 2024
Copy link
Contributor

@kianenigma kianenigma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sgtm

How much is the stake behind the 27 who are now double staked?

probably they will figure it out, but would be good to think as much as we can about how we can help them find their way out of this maze (without eg. talking to the extrinsics tab of PJS 🤭). Maybe a polkadot wiki page about pools can be updated about this.

@Ank4n
Copy link
Contributor Author

Ank4n commented Jun 19, 2024

My dirty script to count number of accounts doing both staking and pool was totally off. The number is much larger and yeah we will need to do a better communication about it (such as putting this info on polkadot wiki).

There are 648 accounts on Polkadot and 321 accounts on Kusama that are taking part in both.

github-merge-queue bot pushed a commit that referenced this pull request Jul 3, 2024
Related: #4804.
Fixes the try state error in Westend:
https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/6564522.
Passes here:
https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/6580393

## Context
Currently in Kusama and Polkadot, an account can do both, directly
stake, and join a pool.

With the migration of pools to `DelegateStake` (See
#3905), the funds of pool
members are locked in a different way than for direct stakers.
- Pool member funds uses `holds`.
- `pallet-staking` uses deprecated locks (analogous to freeze) which can
overlap with holds.

An existing delegator can stake directly since pallet-staking only uses
free balance. But once an account becomes staker, we cannot allow them
to be delegator as this risks an account to use already staked (frozen)
funds in pools.

When an account gets into a situation where it is participating in both
pools and staking, it would no longer would be able to add any extra
bond to the pool but they can still withdraw funds.

## Changes
- Add test for the above scenario.
- Removes the assumption that a delegator cannot be a staker.
@Ank4n Ank4n changed the title Prevent users from both directly staking and joining pool (DNM) Prevent users from both directly staking and joining pool Jul 4, 2024
TomaszWaszczyk pushed a commit to TomaszWaszczyk/polkadot-sdk that referenced this pull request Jul 7, 2024
…#4904)

Related: paritytech#4804.
Fixes the try state error in Westend:
https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/6564522.
Passes here:
https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/6580393

## Context
Currently in Kusama and Polkadot, an account can do both, directly
stake, and join a pool.

With the migration of pools to `DelegateStake` (See
paritytech#3905), the funds of pool
members are locked in a different way than for direct stakers.
- Pool member funds uses `holds`.
- `pallet-staking` uses deprecated locks (analogous to freeze) which can
overlap with holds.

An existing delegator can stake directly since pallet-staking only uses
free balance. But once an account becomes staker, we cannot allow them
to be delegator as this risks an account to use already staked (frozen)
funds in pools.

When an account gets into a situation where it is participating in both
pools and staking, it would no longer would be able to add any extra
bond to the pool but they can still withdraw funds.

## Changes
- Add test for the above scenario.
- Removes the assumption that a delegator cannot be a staker.
// alice cannot directly stake.
assert_noop!(
Staking::bond(RuntimeOrigin::signed(alice), 300, RewardDestination::Account(alice)),
StakingError::<T>::Blacklisted
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this error too dramatic. If I was a user and didn't know what Blacklisted meant in this context, I'd probably panic. Maybe we could rename it to Error::UnableToBond instead or something else?

@@ -1946,6 +1949,9 @@ pub mod pallet {
NotMigrated,
/// This call is not allowed in the current state of the pallet.
NotSupported,
/// Account is blacklisted from participation in pools. This may happen if the account is
/// staking in another way already.
Blacklisted,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned above, I think "BlackListed" may be too overwhelming for a end-user as it seems it's excluding the user from bonding/staking for malicious reasons. Maybe we could rename it to UnableToStake or something similar?

OTOH naming the config types as Blacklisted seems ok since that's internal to devs.

/// pools account and immediately increases the pools bond.
/// Stake funds with a pool. The amount to bond is delegated (or transferred based on
/// [`adapter::StakeStrategyType`]) from the member to the pool account and immediately
/// increases the pools bond.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// increases the pools bond.
/// increases the pool's bond.

@@ -3948,3 +3963,10 @@ impl<T: Config> sp_staking::OnStakingUpdate<T::AccountId, BalanceOf<T>> for Pall
}
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add some rustdoc to this struct?

@@ -1341,3 +1342,10 @@ impl<T: Config, const DISABLING_LIMIT_FACTOR: usize> DisablingStrategy<T>
Some(offender_idx)
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add rustdoc to this struct?

@@ -934,6 +946,9 @@ pub mod pallet {
NotEnoughFunds,
/// Operation not allowed for virtual stakers.
VirtualStakerNotAllowed,
/// Account is blacklisted and is only allowed to withdraw existing funds. This may happen
/// if the account is participating in staking in another way already.
Blacklisted,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as in comment above.

@Ank4n Ank4n marked this pull request as draft July 10, 2024 21:44
@Ank4n
Copy link
Contributor Author

Ank4n commented Jul 18, 2024

Closing this as will go ahead with this. Instead we will look to migrate staking pallet to use Fungible::holds.

@Ank4n Ank4n closed this Jul 18, 2024
TarekkMA pushed a commit to moonbeam-foundation/polkadot-sdk that referenced this pull request Aug 2, 2024
…#4904)

Related: paritytech#4804.
Fixes the try state error in Westend:
https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/6564522.
Passes here:
https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/6580393

## Context
Currently in Kusama and Polkadot, an account can do both, directly
stake, and join a pool.

With the migration of pools to `DelegateStake` (See
paritytech#3905), the funds of pool
members are locked in a different way than for direct stakers.
- Pool member funds uses `holds`.
- `pallet-staking` uses deprecated locks (analogous to freeze) which can
overlap with holds.

An existing delegator can stake directly since pallet-staking only uses
free balance. But once an account becomes staker, we cannot allow them
to be delegator as this risks an account to use already staked (frozen)
funds in pools.

When an account gets into a situation where it is participating in both
pools and staking, it would no longer would be able to add any extra
bond to the pool but they can still withdraw funds.

## Changes
- Add test for the above scenario.
- Removes the assumption that a delegator cannot be a staker.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T2-pallets This PR/Issue is related to a particular pallet.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants