If you are a nomination pool member, you may already know that when you join a NominationPool, your funds are transferred from your account to the pooled account (in other words, you lose the ownership of these funds). We can call this Transfer and Stake
strategy. In return, you are assigned some points which you use later to claim your funds.
A side effect of this is, you cannot use your funds in the pool for governance.
We had been working to fix this issue by keeping the funds held in member account itself and giving the right to stake it to the pool account (see #3905). We call this Delegate and Stake
strategy.
This is already live on Westend (testnet).
The audit identified couple of follow-up issues that I am currently addressing and expect it to be merged very soon. Once done, these changes could go live as soon as in early August on Polkadot/Kusama.
Use the runtime api NominationPoolsApi_member_total_balance
that takes AccountId
as input and returns Balance
.
Use the runtime api NominationPoolsApi_pool_balance
that takes PoolId
as input and returns Balance
.
Use the runtime api NominationPoolsApi_member_needs_delegate_migration
that takes AccountId
as input, and returns true
if user is not migrated yet.
You can find more information about this in the lazy slashes section.
Check if a user has pending slash by using the runtime api NominationPoolsApi_member_pending_slash
that returns a Balance
. If the returned value is greater than 0, the extrinsic nominationPools.apply_slash(memberAccount)
can be dispatched. The origin is rewarded with part of the slash based on the slash reward configuration of the runtime.
Following conditions should pass for a member to be migrated:
NominationPoolsApi_member_total_balance
) is above ED.Bonded
in pallet-staking
.Next, check if user needs to be migrated with the runtime api NominationPoolsApi_member_needs_delegate_migration
. If it returns true
, the extrinsic nominationPools.migrateDelegation(memberAccount)
can be dispatched. If successful, any transaction fee would be refunded.
In most cases, a pool member don't have to do anything. Their funds would be migrated automatically by a bot script via a permissionless extrinsic. However there are cases where your migration can fail and they might need to resolve those issues before migrating.
Cases where migration would fail:
Unfortunately, because of the way funds are locked, a direct staker would not be able to use the pools anymore. More details here.
To be able to migrate your pool funds, following are the steps I recommend:
The first two steps can already be taken to avoid the migration failure when these changes are deployed on Polkadot and Kusama.
if your balance is zero and your pool contribution is below ED in the pool, you will need to top up your account before you can migrate your pool funds.
// TODO Integrate a way to migrate in staking dashboard and document that as well.
nominationPools.migrateDelegation(memberAccount)
. The fee is refunded if transaction is successful.After migration, the pool account becomes a virtual staking account
. What that means is, they do not stake with their own funds, but gets delegation from other accounts.
There is a new pallet into the runtime pallet-delegated-staking
that manages all the delegation.
Nomination pools uses pallet-delegated-staking
to switch from
pallet-staking
pallet-staking
as a virtual staking account
.// TODO: try using as less new terms as possible.
Currently whenever there is a slashing event, pool members affected are slashed eagerly. Since the funds are only in the pool account, only one account needs to be slashed per pool. With the new DelegateStake
feature, pool funds are spread all its members and each member need to be slashed proportionally. This would be an unbounded operation therefore not feasible.
Instead, with DelegateStake
, we apply slashes to pool members lazily. Internally, we keep account of how much a pool and its members needs to be slashed. There is a permissionless extrinsic to apply any pending slash to the pool member. If successful, the caller gets part of slash as reward (if configured), incentivising free market bots to monitor and apply slashes swiftly.
The advantage is, the slashing (computation) cost is spread over multiple blocks.
A disadvantage is that a member might have more funds in their account locked than their actual pool contribution, which they can use to vote, until these pending slashes are applied.
There is a runtime api to help with checking if a user has any pending slash NominationPoolsApi_member_pending_slash
.
Migration happens in two stages:
The following steps is what happens when a pool is migrated
pallet-staking
. See storage item VirtualStakers
.Agent
in pallet-delegation-staking
. The pallet keeps track of total funds delegated, and any pending slashes to the pool account, among other things.ProxyDelegator
, a new pot account of pallet-delegated-staking
. ProxyDelegator
delegates back to pool account and is later used by pool members to migrate their funds into their own accounts.Members can migrate their funds in the pool (that temporarily exists in ProxyDelegator
). The funds are transferred to the member account with a hold.
pallet-staking
uses the deprecated currency locks which can overlap with holds used by the pools after migration. This unfortunately means
normal stakers
(both nominators and validators) on pallet-staking
won't be able to bond their funds in the pool. If we don't disable this, an account could potentially stake the same fund twice.
For existing accounts who are both in pool and are normal stakers would need to withdraw all their funds from staking in order to migrate their delegation.
In future, we will migrate staking funds to use the same holds
mechanism that is used by the pools and re-enable accounts to do both. In the meanwhile, if a user wants to do both, I suggest to use/create a separate account and use that for directly staking.