NominationPools¶
Calls¶
bond_extra¶
Bond extra
more funds from origin
into the pool to which they already belong.
Additional funds can come from either the free balance of the account, of from the
accumulated rewards, see [BondExtra
].
Bonding extra funds implies an automatic payout of all pending rewards as well.
Attributes¶
Name | Type |
---|---|
extra | BondExtra<BalanceOf<T>> |
Python¶
call = substrate.compose_call(
'NominationPools', 'bond_extra', {
'extra': {
'FreeBalance': 'u128',
'Rewards': None,
},
}
)
chill¶
Chill on behalf of the pool.
The dispatch origin of this call must be signed by the pool nominator or the pool
root role, same as [Pallet::nominate
].
This directly forward the call to the staking pallet, on behalf of the pool bonded account.
Attributes¶
Name | Type |
---|---|
pool_id | PoolId |
Python¶
call = substrate.compose_call(
'NominationPools', 'chill', {'pool_id': 'u32'}
)
claim_payout¶
A bonded member can use this to claim their payout based on the rewards that the pool has accumulated since their last claimed payout (OR since joining if this is there first time claiming rewards). The payout will be transferred to the member's account.
The member will earn rewards pro rata based on the members stake vs the sum of the members in the pools stake. Rewards do not "expire".
Attributes¶
No attributes
Python¶
call = substrate.compose_call(
'NominationPools', 'claim_payout', {}
)
create¶
Create a new delegation pool.
# Arguments
amount
- The amount of funds to delegate to the pool. This also acts of a sort of deposit since the pools creator cannot fully unbond funds until the pool is being destroyed.index
- A disambiguation index for creating the account. Likely only useful when creating multiple pools in the same extrinsic.root
- The account to set as [PoolRoles::root
].nominator
- The account to set as the [PoolRoles::nominator
].state_toggler
- The account to set as the [PoolRoles::state_toggler
].
# Note
In addition to amount
, the caller will transfer the existential deposit; so the caller
needs at have at least amount + existential_deposit
transferrable.
Attributes¶
Name | Type |
---|---|
amount | BalanceOf<T> |
root | T::AccountId |
nominator | T::AccountId |
state_toggler | T::AccountId |
Python¶
call = substrate.compose_call(
'NominationPools', 'create', {
'amount': 'u128',
'nominator': 'AccountId',
'root': 'AccountId',
'state_toggler': 'AccountId',
}
)
join¶
Stake funds with a pool. The amount to bond is transferred from the member to the pools account and immediately increases the pools bond.
# Note
- An account can only be a member of a single pool.
- An account cannot join the same pool multiple times.
- This call will not dust the member account, so the member must have at least
existential deposit + amount
in their account. - Only a pool with [
PoolState::Open
] can be joined
Attributes¶
Name | Type |
---|---|
amount | BalanceOf<T> |
pool_id | PoolId |
Python¶
call = substrate.compose_call(
'NominationPools', 'join', {'amount': 'u128', 'pool_id': 'u32'}
)
nominate¶
Nominate on behalf of the pool.
The dispatch origin of this call must be signed by the pool nominator or the pool root role.
This directly forward the call to the staking pallet, on behalf of the pool bonded account.
Attributes¶
Name | Type |
---|---|
pool_id | PoolId |
validators | Vec<T::AccountId> |
Python¶
call = substrate.compose_call(
'NominationPools', 'nominate', {
'pool_id': 'u32',
'validators': ['AccountId'],
}
)
pool_withdraw_unbonded¶
Call withdraw_unbonded
for the pools account. This call can be made by any account.
This is useful if their are too many unlocking chunks to call unbond
, and some
can be cleared by withdrawing. In the case there are too many unlocking chunks, the user
would probably see an error like NoMoreChunks
emitted from the staking system when
they attempt to unbond.
Attributes¶
Name | Type |
---|---|
pool_id | PoolId |
num_slashing_spans | u32 |
Python¶
call = substrate.compose_call(
'NominationPools', 'pool_withdraw_unbonded', {
'num_slashing_spans': 'u32',
'pool_id': 'u32',
}
)
set_configs¶
Update configurations for the nomination pools. The origin for this call must be Root.
# Arguments
min_join_bond
- Set [MinJoinBond
].min_create_bond
- Set [MinCreateBond
].max_pools
- Set [MaxPools
].max_members
- Set [MaxPoolMembers
].max_members_per_pool
- Set [MaxPoolMembersPerPool
].
Attributes¶
Name | Type |
---|---|
min_join_bond | ConfigOp<BalanceOf<T>> |
min_create_bond | ConfigOp<BalanceOf<T>> |
max_pools | ConfigOp<u32> |
max_members | ConfigOp<u32> |
max_members_per_pool | ConfigOp<u32> |
Python¶
call = substrate.compose_call(
'NominationPools', 'set_configs', {
'max_members': {
'Noop': None,
'Remove': None,
'Set': 'u32',
},
'max_members_per_pool': {
'Noop': None,
'Remove': None,
'Set': 'u32',
},
'max_pools': {
'Noop': None,
'Remove': None,
'Set': 'u32',
},
'min_create_bond': {
'Noop': None,
'Remove': None,
'Set': 'u128',
},
'min_join_bond': {
'Noop': None,
'Remove': None,
'Set': 'u128',
},
}
)
set_metadata¶
Set a new metadata for the pool.
The dispatch origin of this call must be signed by the state toggler, or the root role of the pool.
Attributes¶
Name | Type |
---|---|
pool_id | PoolId |
metadata | Vec<u8> |
Python¶
call = substrate.compose_call(
'NominationPools', 'set_metadata', {
'metadata': 'Bytes',
'pool_id': 'u32',
}
)
set_state¶
Set a new state for the pool.
If a pool is already in the Destroying
state, then under no condition can its state
change again.
The dispatch origin of this call must be either:
- signed by the state toggler, or the root role of the pool,
- if the pool conditions to be open are NOT met (as described by
ok_to_be_open
), and then the state of the pool can be permissionlessly changed toDestroying
.
Attributes¶
Name | Type |
---|---|
pool_id | PoolId |
state | PoolState |
Python¶
call = substrate.compose_call(
'NominationPools', 'set_state', {
'pool_id': 'u32',
'state': (
'Open',
'Blocked',
'Destroying',
),
}
)
unbond¶
Unbond up to unbonding_points
of the member_account
's funds from the pool. It
implicitly collects the rewards one last time, since not doing so would mean some
rewards would be forfeited.
Under certain conditions, this call can be dispatched permissionlessly (i.e. by any account).
# Conditions for a permissionless dispatch.
- The pool is blocked and the caller is either the root or state-toggler. This is refereed to as a kick.
- The pool is destroying and the member is not the depositor.
- The pool is destroying, the member is the depositor and no other members are in the pool.
## Conditions for permissioned dispatch (i.e. the caller is also the
member_account
):
- The caller is not the depositor.
- The caller is the depositor, the pool is destroying and no other members are in the pool.
# Note
If there are too many unlocking chunks to unbond with the pool account,
[Call::pool_withdraw_unbonded
] can be called to try and minimize unlocking chunks. If
there are too many unlocking chunks, the result of this call will likely be the
NoMoreChunks
error from the staking system.
Attributes¶
Name | Type |
---|---|
member_account | T::AccountId |
unbonding_points | BalanceOf<T> |
Python¶
call = substrate.compose_call(
'NominationPools', 'unbond', {
'member_account': 'AccountId',
'unbonding_points': 'u128',
}
)
update_roles¶
Update the roles of the pool.
The root is the only entity that can change any of the roles, including itself, excluding the depositor, who can never change.
It emits an event, notifying UIs of the role change. This event is quite relevant to most pool members and they should be informed of changes to pool roles.
Attributes¶
Name | Type |
---|---|
pool_id | PoolId |
new_root | ConfigOp<T::AccountId> |
new_nominator | ConfigOp<T::AccountId> |
new_state_toggler | ConfigOp<T::AccountId> |
Python¶
call = substrate.compose_call(
'NominationPools', 'update_roles', {
'new_nominator': {
'Noop': None,
'Remove': None,
'Set': 'AccountId',
},
'new_root': {
'Noop': None,
'Remove': None,
'Set': 'AccountId',
},
'new_state_toggler': {
'Noop': None,
'Remove': None,
'Set': 'AccountId',
},
'pool_id': 'u32',
}
)
withdraw_unbonded¶
Withdraw unbonded funds from member_account
. If no bonded funds can be unbonded, an
error is returned.
Under certain conditions, this call can be dispatched permissionlessly (i.e. by any account).
# Conditions for a permissionless dispatch
- The pool is in destroy mode and the target is not the depositor.
- The target is the depositor and they are the only member in the sub pools.
- The pool is blocked and the caller is either the root or state-toggler.
# Conditions for permissioned dispatch
- The caller is the target and they are not the depositor.
# Note
If the target is the depositor, the pool will be destroyed.
Attributes¶
Name | Type |
---|---|
member_account | T::AccountId |
num_slashing_spans | u32 |
Python¶
call = substrate.compose_call(
'NominationPools', 'withdraw_unbonded', {
'member_account': 'AccountId',
'num_slashing_spans': 'u32',
}
)
Events¶
Bonded¶
A member has became bonded in a pool.
Attributes¶
Name | Type | Composition |
---|---|---|
member | T::AccountId |
AccountId |
pool_id | PoolId |
u32 |
bonded | BalanceOf<T> |
u128 |
joined | bool |
bool |
Created¶
A pool has been created.
Attributes¶
Name | Type | Composition |
---|---|---|
depositor | T::AccountId |
AccountId |
pool_id | PoolId |
u32 |
Destroyed¶
A pool has been destroyed.
Attributes¶
Name | Type | Composition |
---|---|---|
pool_id | PoolId |
u32 |
MemberRemoved¶
A member has been removed from a pool.
The removal can be voluntary (withdrawn all unbonded funds) or involuntary (kicked).
Attributes¶
Name | Type | Composition |
---|---|---|
pool_id | PoolId |
u32 |
member | T::AccountId |
AccountId |
PaidOut¶
A payout has been made to a member.
Attributes¶
Name | Type | Composition |
---|---|---|
member | T::AccountId |
AccountId |
pool_id | PoolId |
u32 |
payout | BalanceOf<T> |
u128 |
PoolSlashed¶
The active balance of pool pool_id
has been slashed to balance
.
Attributes¶
Name | Type | Composition |
---|---|---|
pool_id | PoolId |
u32 |
balance | BalanceOf<T> |
u128 |
RolesUpdated¶
The roles of a pool have been updated to the given new roles. Note that the depositor can never change.
Attributes¶
Name | Type | Composition |
---|---|---|
root | Option<T::AccountId> |
(None, 'AccountId') |
state_toggler | Option<T::AccountId> |
(None, 'AccountId') |
nominator | Option<T::AccountId> |
(None, 'AccountId') |
StateChanged¶
The state of a pool has changed
Attributes¶
Name | Type | Composition |
---|---|---|
pool_id | PoolId |
u32 |
new_state | PoolState |
('Open', 'Blocked', 'Destroying') |
Unbonded¶
A member has unbonded from their pool.
balance
is the corresponding balance of the number of points that has been requested to be unbonded (the argument of theunbond
transaction) from the bonded pool.points
is the number of points that are issued as a result ofbalance
being dissolved into the corresponding unbonding pool.era
is the era in which the balance will be unbonded. In the absence of slashing, these values will match. In the presence of slashing, the number of points that are issued in the unbonding pool will be less than the amount requested to be unbonded.
Attributes¶
Name | Type | Composition |
---|---|---|
member | T::AccountId |
AccountId |
pool_id | PoolId |
u32 |
balance | BalanceOf<T> |
u128 |
points | BalanceOf<T> |
u128 |
era | EraIndex |
u32 |
UnbondingPoolSlashed¶
The unbond pool at era
of pool pool_id
has been slashed to balance
.
Attributes¶
Name | Type | Composition |
---|---|---|
pool_id | PoolId |
u32 |
era | EraIndex |
u32 |
balance | BalanceOf<T> |
u128 |
Withdrawn¶
A member has withdrawn from their pool.
The given number of points
have been dissolved in return of balance
.
Similar to Unbonded
event, in the absence of slashing, the ratio of point to balance
will be 1.
Attributes¶
Name | Type | Composition |
---|---|---|
member | T::AccountId |
AccountId |
pool_id | PoolId |
u32 |
balance | BalanceOf<T> |
u128 |
points | BalanceOf<T> |
u128 |
Storage functions¶
BondedPools¶
Storage for bonded pools.
Python¶
result = substrate.query(
'NominationPools', 'BondedPools', ['u32']
)
Return value¶
{
'member_counter': 'u32',
'points': 'u128',
'roles': {
'depositor': 'AccountId',
'nominator': (None, 'AccountId'),
'root': (None, 'AccountId'),
'state_toggler': (None, 'AccountId'),
},
'state': ('Open', 'Blocked', 'Destroying'),
}
CounterForBondedPools¶
Counter for the related counted storage map
Python¶
result = substrate.query(
'NominationPools', 'CounterForBondedPools', []
)
Return value¶
'u32'
CounterForMetadata¶
Counter for the related counted storage map
Python¶
result = substrate.query(
'NominationPools', 'CounterForMetadata', []
)
Return value¶
'u32'
CounterForPoolMembers¶
Counter for the related counted storage map
Python¶
result = substrate.query(
'NominationPools', 'CounterForPoolMembers', []
)
Return value¶
'u32'
CounterForReversePoolIdLookup¶
Counter for the related counted storage map
Python¶
result = substrate.query(
'NominationPools', 'CounterForReversePoolIdLookup', []
)
Return value¶
'u32'
CounterForRewardPools¶
Counter for the related counted storage map
Python¶
result = substrate.query(
'NominationPools', 'CounterForRewardPools', []
)
Return value¶
'u32'
CounterForSubPoolsStorage¶
Counter for the related counted storage map
Python¶
result = substrate.query(
'NominationPools', 'CounterForSubPoolsStorage', []
)
Return value¶
'u32'
LastPoolId¶
Ever increasing number of all pools created so far.
Python¶
result = substrate.query(
'NominationPools', 'LastPoolId', []
)
Return value¶
'u32'
MaxPoolMembers¶
Maximum number of members that can exist in the system. If None
, then the count
members are not bound on a system wide basis.
Python¶
result = substrate.query(
'NominationPools', 'MaxPoolMembers', []
)
Return value¶
'u32'
MaxPoolMembersPerPool¶
Maximum number of members that may belong to pool. If None
, then the count of
members is not bound on a per pool basis.
Python¶
result = substrate.query(
'NominationPools', 'MaxPoolMembersPerPool', []
)
Return value¶
'u32'
MaxPools¶
Maximum number of nomination pools that can exist. If None
, then an unbounded number of
pools can exist.
Python¶
result = substrate.query(
'NominationPools', 'MaxPools', []
)
Return value¶
'u32'
Metadata¶
Metadata for the pool.
Python¶
result = substrate.query(
'NominationPools', 'Metadata', ['u32']
)
Return value¶
'Bytes'
MinCreateBond¶
Minimum bond required to create a pool.
This is the amount that the depositor must put as their initial stake in the pool, as an indication of "skin in the game".
This is the value that will always exist in the staking ledger of the pool bonded account while all other accounts leave.
Python¶
result = substrate.query(
'NominationPools', 'MinCreateBond', []
)
Return value¶
'u128'
MinJoinBond¶
Minimum amount to bond to join a pool.
Python¶
result = substrate.query(
'NominationPools', 'MinJoinBond', []
)
Return value¶
'u128'
PoolMembers¶
Active members.
Python¶
result = substrate.query(
'NominationPools', 'PoolMembers', ['AccountId']
)
Return value¶
{
'last_recorded_reward_counter': 'u128',
'points': 'u128',
'pool_id': 'u32',
'unbonding_eras': 'scale_info::607',
}
ReversePoolIdLookup¶
A reverse lookup from the pool's account id to its id.
This is only used for slashing. In all other instances, the pool id is used, and the accounts are deterministically derived from it.
Python¶
result = substrate.query(
'NominationPools', 'ReversePoolIdLookup', ['AccountId']
)
Return value¶
'u32'
RewardPools¶
Reward pools. This is where there rewards for each pool accumulate. When a members payout is claimed, the balance comes out fo the reward pool. Keyed by the bonded pools account.
Python¶
result = substrate.query(
'NominationPools', 'RewardPools', ['u32']
)
Return value¶
{
'last_recorded_reward_counter': 'u128',
'last_recorded_total_payouts': 'u128',
'total_rewards_claimed': 'u128',
}
SubPoolsStorage¶
Groups of unbonding pools. Each group of unbonding pools belongs to a bonded pool, hence the name sub-pools. Keyed by the bonded pools account.
Python¶
result = substrate.query(
'NominationPools', 'SubPoolsStorage', ['u32']
)
Return value¶
{'no_era': {'balance': 'u128', 'points': 'u128'}, 'with_era': 'scale_info::615'}
Constants¶
MaxPointsToBalance¶
The maximum pool points-to-balance ratio that an open
pool can have.
This is important in the event slashing takes place and the pool's points-to-balance ratio becomes disproportional.
Moreover, this relates to the RewardCounter
type as well, as the arithmetic operations
are a function of number of points, and by setting this value to e.g. 10, you ensure
that the total number of points in the system are at most 10 times the total_issuance of
the chain, in the absolute worse case.
For a value of 10, the threshold would be a pool points-to-balance ratio of 10:1. Such a scenario would also be the equivalent of the pool being 90% slashed.
Value¶
10
Python¶
constant = substrate.get_constant('NominationPools', 'MaxPointsToBalance')
PalletId¶
The nomination pool's pallet id.
Value¶
'0x70792f6e6f706c73'
Python¶
constant = substrate.get_constant('NominationPools', 'PalletId')
Errors¶
AccountBelongsToOtherPool¶
An account is already delegating in another pool. An account may only belong to one pool at a time.
CanNotChangeState¶
The pools state cannot be changed.
CannotWithdrawAny¶
None of the funds can be withdrawn yet because the bonding duration has not passed.
Defensive¶
Some error occurred that should never happen. This should be reported to the maintainers.
DoesNotHavePermission¶
The caller does not have adequate permissions.
FullyUnbonding¶
The member is fully unbonded (and thus cannot access the bonded and reward pool anymore to, for example, collect rewards).
MaxPoolMembers¶
Too many members in the pool or system.
MaxPools¶
The system is maxed out on pools.
MaxUnbondingLimit¶
The member cannot unbond further chunks due to reaching the limit.
MetadataExceedsMaxLen¶
Metadata exceeds [Config::MaxMetadataLen
]
MinimumBondNotMet¶
The amount does not meet the minimum bond to either join or create a pool.
The depositor can never unbond to a value less than
Pallet::depositor_min_bond
. The caller does not have nominating
permissions for the pool. Members can never unbond to a value below MinJoinBond
.
NotDestroying¶
A pool must be in [PoolState::Destroying
] in order for the depositor to unbond or for
other members to be permissionlessly unbonded.
NotKickerOrDestroying¶
Either a) the caller cannot make a valid kick or b) the pool is not destroying.
NotNominator¶
The caller does not have nominating permissions for the pool.
NotOpen¶
The pool is not open to join
OverflowRisk¶
The transaction could not be executed due to overflow risk for the pool.
PartialUnbondNotAllowedPermissionlessly¶
Partial unbonding now allowed permissionlessly.
PoolMemberNotFound¶
An account is not a member.
PoolNotFound¶
A (bonded) pool id does not exist.
RewardPoolNotFound¶
A reward pool does not exist. In all cases this is a system logic error.
SubPoolsNotFound¶
A sub pool does not exist.