Spending Pools
Overview
Spending pools are KIRA’s native token distribution system, providing a way to distribute a pooled amount of one or multiple tokens to a predefined set of accounts at a predefined rate over a specific period. They can operate in two distinct modes for the rate of distribution: a fixed rate mode and a dynamic rate mode, providing flexibility and customization options for different use cases.
Spending pools are an essential tool for incentivizing network actors such as developers or community managers for their contributions. They are permissionless, allowing any KIRA account to create one and associate it with one or more "owners," which can be governance-defined roles or individual KIRA accounts. Accounts that are eligible to claim rewards from the spending pool are called "beneficiaries" and can also be defined as roles or individual KIRA accounts. One of the primary use cases for spending pools is the distribution of Universal Basic Income to KIRA consensus nodes and governance members. Additionally, they are also utilized by the Staking Collective module as a means to redistribute staking rewards.
Distribution Rates
Static Mode
This spending pool mechanism is straightforward - it consists of a distribution rate and a period. Instead of tracking the exact amount owed to each account over time, it simply keeps track of the last time that an account has made a claim within the claiming period. This information is sufficient to calculate an account's current entitlement by multiplying the distribution rate by the time elapsed since the last claim. Spending pools can accommodate the distribution of multiple different tokens. Any token can be deposited and their individual distribution rate
can be accurately set, ensuring that the tokens are distributed as intended over the claiming period.
If a token is deposited into the pool but its static rate is not defined, it will not be distributed to any beneficiaries (similar to setting its rate to zero).
Dynamic Mode
The dynamic token rate mechanism, enabled by the dynamic-rate
field, allows for the proper distribution of tokens over the claiming period, even when the amount of tokens deposited within that period is unpredictable or fluctuating, which would otherwise require continuous rate adjustments. If dynamic-rate
is set to false
, the spending pool operates in the static rate
mode. When it is enabled, the dynamic-rate-period
field determines how often the token rates are recalculated, measured in seconds (Unix).
In this mode, rates of distribution are re-adjusted at the end of each dynamic-rate-period
to ensure the complete allocation of pooled funds by the conclusion of the subsequent period. Therefore, any fund contributions made to the pool after the rate recalibration will effectively be accounted for in the following period. For beneficiaries, it is essential to make a claim at least once within the current dynamic-rate-period
, and ideally at its closure in order to get the full entitlement; beneficiaries who fail to claim their due rewards within a dynamic period effectively forfeit their share (or remaining share) for that period, which is then redistributed in the next period's calculations. It also implies that beneficiaries who register cannot claim during the ongoing period and must wait until the next one to starts to do so, to effectively receive tokens from the pool. The Staking Collectives module is an example of where this mechanism is necessary, as it works in conjunction with the Spending Pool module to redistribute staking rewards which are unpredictable by nature.
Claiming Period
The simplicity of the spending pool mechanism also allows for flexibility in claiming. Unlike traditional wage systems where one typically has to wait until the end of a specific period (usually a month) to receive their earnings, with a spending pool, an account can claim multiple times within the defined claiming period. This allows for a more dynamic and responsive distribution of funds, catering to the needs of the beneficiaries while still ensuring that the tokens are being distributed properly. The claim-start
and claim-end
parameters define the claiming period during which tokens can be claimed from the pool, providing a precise and transparent system for all parties involved.
claim-end
can be set to 0
to indicate that there is no predetermined end date for the claiming period, allowing beneficiaries to claim their rewards until the spending pool’s funds are fully distributed.
Claiming Process
To request funds from a spending pool, a beneficiary must be registered. The beneficiary can then send a transaction to request the funds they are entitled to receive. There are several conditions that must be met in order for the funds to be distributed:
- The current block time must be within the period defined by the
claim-start
andclaim-end
properties. - The spending pool must have a sufficient balance. If the pool does not have enough funds, pooled token will not be sent in any amount. If the pool has sufficient funds, the exact amount owed will be sent to the beneficiary.
- If the claiming period or the dynamic claim period has elapsed and the funds have not been claimed by the beneficiary they are forfeited.
If all of these conditions are met, the funds will be distributed to the beneficiary.
Claim Expiry
The claim-expiry
parameter sets a critical window within which beneficiaries are required to claim their rewards, preserving the integrity of reward calculations amid potential rate changes over time. Should a beneficiary not engage within this window, rewards succeeding the deadline are excluded from subsequent claim calculation. This mechanism ensures that rewards are accurately and fairly distributed even if pool owners operate rate changes, and it underscores the importance of regular claims to secure entitled benefits. Beneficiaries must therefore remain proactive in claiming within each designated period to uphold the system's equitable distribution of rewards
The proposal-distribute-spending-pool
command enables the spending pool’s owners to enforce funds distribution. This command is particularly useful before modifying the fixed distribution rate to avoid misdistribution.
Distribution Weights
Individual token distribution rates can be set for specific accounts and/or roles using weights. For example, if a specific account's or a role’s weight
is set to 2
, it will receive tokens at 2x the base rate (static or dynamic) compared to other accounts. Weights can also be decimal values, such as 0.5
, which will reduce the token rate for the associated account or role by half. All distribution rates are set to 1
by default.
It's worth noting that any changes made to the weights of registered beneficiaries will result in the recalculation of global token rates, ensuring that the modified rate for one account does not impact the entitlements of others. This means for instance that if the weight for an account is increased, the global rate is increased accordingly, rather than decreasing entitlements for every other account. This mechanism makes sense from an HR management standpoint, as it allows for proper management of wages among different members of a community or team, ensuring that each person is compensated fairly for their contributions.
Parameters
Spending Pool
NAME | TYPE | EXAMPLE | DESCRIPTION |
---|---|---|---|
name | string | "Dev salary" | Unique identifier for the spending pool. |
claim_start | uint64 | 1610000000 | Unix timestamp of the start of the claiming period. |
claim_end | uint64 | 1620000000 | Unix timestamp of the end of the claiming period. |
claim_expiry | uint64 | 2592000 | Time in seconds after which unclaimed funds are no longer accountable. |
rates | []string | 1ukex,0.8ueth | Rate of distribution in the smallest token denomination per 1 second. This value can be a float number smaller than the actual denomination. |
vote_quorum | uint64 | 51 | Pool-specific percentage of owner accounts that must vote YES or NO for any of the pool proposals to be valid. |
vote_period | uint64 | 600 | Period of time in seconds that any of the pool proposals must last before passing or being rejected. |
vote_enactment | uint64 | 300 | Period of time that must pass before any of the pool proposals are enacted. |
owners | PermInfo | List of accounts/roles with governance control over the pool. | |
beneficiaries | WeightedPermInfo | Set of accounts/roles with their respective weights eligible for funds distribution. | |
balances | []string | 100000ukex,20ueth | Array of balances in the pool. |
dynamic_rate | bool | false | Flag to define if the distribution rate is dynamic. |
dynamic_rate_period | uint64 | 86400 | Time in seconds defining the recalculation period for dynamic rates. |
last_dynamic_rate_calc_time | uint64 | 1615000000 | Timestamp of the last dynamic rate calculation. |
PermInfo type
NAME | TYPE | EXAMPLE | DESCRIPTION |
---|---|---|---|
owner_roles | []uint64 | 1,2 | Array of role identifiers for pool ownership. |
owner_accounts | []string | kira1yq8l...,kira1o9dl... | Array of account addresses with ownership privileges. |
WeightedPermInfo type
NAME | TYPE | EXAMPLE | DESCRIPTION |
---|---|---|---|
roles | []WeightedRole | Array of roles with associated weights. | |
accounts | []WeightedAccount | Array of accounts with associated weights. |
WeightedRole type
NAME | TYPE | EXAMPLE | DESCRIPTION | |
---|---|---|---|---|
role | uint64 | 1 | Identifier for a specific role. | |
weight | float | 1.2 | Dedicated weight for this role in the funds distribution calculation. |
WeightedAccount type
NAME | TYPE | EXAMPLE | DESCRIPTION |
---|---|---|---|
account | string | kira1yq8l... | Account address. |
weight | float | 0.5 | Dedicated weight of the account in the funds distribution calculation. |
CLI Syntax & Examples
Each CLI command and proposal process in KIRA requires specific permissions. These permissions must be added to the account's whitelist or obtained as sudo permissions for direct changes. Refer to the Roles & Permissions documentation for more details.
$SIGNER
represents the transaction signer's account name or address. For instructions on setting common flags as environment variables, such as $FLAGS_TX
and $FLAGS_QR
, see the CLI Guide page.
- Transactions
- Queries
- Governance
Transactions
create-spending-pool | Creates a new spending pool. |
---|---|
proposal-spending-pool-update | Proposes modifications to a pool. |
deposit-spending-pool | Allows depositing tokens to the pool. |
register-spending-pool-beneficiary | Registers a beneficiary account. |
claim-spending-pool | Beneficiaries claim tokens. |
proposal-spending-pool-withdraw | Proposes withdrawal from the pool. |
proposal-distribute-spending-pool | Proposes distribution to beneficiaries. |
Create Spending Pool
Create a new spending pool using the create-spending-pool
command.
Flags
$NAME
: Name of the spending pool registry.$CLAIMSTART
: The exact start time after which tokens can be claimed from the pool, expressed in seconds (Unix time).$CLAIMEND
: The exact end time before which tokens can be claimed from the pool, expressed in seconds (Unix time).$RATES
: Decimal rate of distribution in the smallest token denomination per second. Format:<rate><denom>,...
, e.g:0.5ukex
.$VOTEQUORUM
: Pool specific percentage of owner accounts that must vote YES or NO for a proposal to be valid.$VOTEPERIOD
: Time in seconds for which a pool proposal must last before being accepted or rejected.$VOTEENACTMENT
: Time in seconds before a passed pool proposal is enacted.$OWNERROLES
: List of roles controlling the pool via proposals, e.g:1,2,...
$OWNERACCOUNTS
: List of account addresses controlling the pool via proposals. Format:kira1yq8l(...),...
$BENEFICIARYROLES
: List of roles eligible for funds distribution, e.g:3,4,...
$BENEFICIARYROLEWEIGHTS
: Respective token distribution rate multiplier for beneficiary roles, e.g:1,1.2,…
$BENEFICIARYACCOUNTS
: List of account addresses eligible for funds distribution. Format:kira1mig9(...),...
$BENEFICIARYACCOUNTWEIGHTS
: Token distribution rate multiplier for specific accounts, e.g:0.5,…
$DYNAMICRATE
: Boolean flag to enable dynamic rate calculation.$DYNAMICRATEPERIOD
: Dynamic period in seconds (Unix time).
sekaid tx spending create-spending-pool \
--from=$SIGNER $FLAGS_TX \
--name=$NAME --claim-start=$CLAIMSTART --claim-end=$CLAIMEND --rates=$RATES \
--vote-quorum=$VOTEQUORUM --vote-period=$VOTEPERIOD --vote-enactment=$VOTEENACTMENT \
--owner-roles=$OWNERROLES --owner-accounts=$OWNERACCOUNTS \
--beneficiary-roles=$BENEFICIARYROLES --beneficiary-role-weights=$BENEFICIARYROLEWEIGHTS \
--beneficiary-accounts=$BENEFICIARYACCOUNTS --beneficiary-account-weights=$BENEFICIARYACCOUNTWEIGHTS \
--dynamic-rate=$DYNAMICRATE --dynamic-rate-period=$DYNAMICRATEPERIOD
Deposit to a Spending Pool
Deposit tokens to a spending pool using the deposit-spending-pool
command.
Flags
$NAME
: Name of the spending pool registry.$AMOUNTS
: Coin denomination and amount to be deposited. Format:<amount><denom>
, e.g.,20000ukex
.
sekaid tx spending deposit-spending-pool \
--from=$SIGNER $FLAGS_TX \
--name=$NAME --amount=$AMOUNTS
Register as Beneficiary
Register as a beneficiary using the register-spending-pool-beneficiary
command.
Flags
$NAME
: Name of the spending pool registry.
sekaid tx spending register-spending-pool-beneficiary \
--from=$SIGNER $FLAGS_TX \
--name=$NAME
Claim Funds From Spending Pool
Beneficiaries can claim their entitled funds using the claim-spending-pool
command, provided they are registered. Claims cannot be processed if the claim period has expired or if the pool lacks adequate funds.
Flags
$NAME
: Name of the spending pool registry.
sekaid tx spending claim-spending-pool \
--from=$SIGNER $FLAGS_TX \
--name=$NAME
Queries
pool-names | Retrieve a list of all existing pool names. |
---|---|
pool-by-name | Retrieve details of a specific pool by its name. |
pool-proposals | Retrieve a list of all pool proposals. |
pools-by-account | Retrieve a list of pool names where a specific account can register or claim tokens. |
List Pool Names
Retrieve a list of all existing pool names.
sekaid query spending pool-names $FLAGS_QR | jq
Query Pool by Name
Retrieve details of a specific pool by its name.
Args
$NAME
: The name of the pool to query.
sekaid query spending pool-by-name $NAME $FLAGS_QR | jq
List Pool Proposals
Retrieve a list of all pool proposals.
sekaid query spending pool-proposals $FLAGS_QR | jq
List Pools for a Specific Account
Retrieve a list of pool names where a specific KIRA account can register as a beneficiary or claim tokens from.
Args
$BENEFICIARYACCOUNT
: The KIRA account to check.
sekaid query spending pools-by-account $BENEFICIARYACCOUNT $FLAGS_QR | jq
Governance
The operation and parameters of a spending pool is controlled through custom proposals that can only be raised and voted on by the pool's owners. Any KIRA account can create a spending pool and seed it with funds, becoming the first owner in the list. The owner of the spending pool can then assign additional owners, define the rules of the pool's operation, and designate beneficiaries who can claim the pooled tokens.
proposal-spending-pool-update | Proposes modifications to a pool. |
---|---|
proposal-spending-pool-withdraw | Proposes withdrawal from the pool. |
proposal-distribute-spending-pool | Proposes distribution to beneficiaries. |
Propose Pool Update
Propose an update to a spending pool using the proposal-spending-pool-update
command. This function allows to add new owners or beneficiaries, or to edit any of the pool's existing properties.
Flags
$TITLE
: The title of the proposal.$DESCRIPTION
: Description of the proposal.$NAME
: Name of the spending pool registry.$CLAIMSTART
: The exact start time after which tokens can be claimed from the pool, expressed in seconds (Unix time).$CLAIMEND
: The exact end time before which tokens can be claimed from the pool, expressed in seconds (Unix time).$RATES
: Decimal rate of distribution in the smallest token denomination per second. Format:<rate><denom>,...
(e.g.,0.5ukex
).$VOTEQUORUM
: Pool specific percentage of owner accounts that must vote YES or NO for a proposal to be valid.$VOTEPERIOD
: Time in seconds for which a pool proposal must last before being accepted or rejected.$VOTEENACTMENT
: Time in seconds before a passed pool proposal is enacted.$OWNERROLES
: List of roles controlling the pool via proposals, e.g:1,2,...
$OWNERACCOUNTS
: List of account addresses controlling the pool via proposals. Format:kira1yq8l(...),...
$BENEFICIARYROLES
: List of roles eligible for funds distribution, e.g:3,4,...
$BENEFICIARYROLEWEIGHTS
: Respective token distribution rate multiplier for beneficiary roles, e.g:1,1.2,…
$BENEFICIARYACCOUNTS
: List of account addresses eligible for funds distribution. Format:kira1mig9(...),...
$BENEFICIARYACCOUNTWEIGHTS
: Token distribution rate multiplier for specific accounts, e.g:0.5,…
$DYNAMICRATE
: Boolean flag to enable dynamic rate calculation.$DYNAMICRATEPERIOD
: Dynamic period in seconds (Unix time).
sekaid tx spending proposal-update-spending-pool \
--from=$SIGNER $FLAGS_TX \
--title=$TITLE --description=$DESCRIPTION \
--name=$NAME --claim-start=$CLAIMSTART --claim-end=$CLAIMEND --rates=$RATES \
--vote-quorum=$VOTEQUORUM --vote-period=$VOTEPERIOD --vote-enactment=$VOTEENACTMENT \
--owner-accounts=$OWNERACCOUNTS --owner-roles=$OWNERROLES \
--beneficiary-roles=$BENEFICIARYROLES --beneficiary-role-weights=$BENEFICIARYROLEWEIGHTS \
--beneficiary-accounts=$BENEFICIARYACCOUNTS --beneficiary-account-weights=$BENEFICIARYACCOUNTWEIGHTS \
--dynamic-rate=$DYNAMICRATE --dynamic-rate-period=$DYNAMICRATEPERIOD
Withdraw Funds From Spending Pool
To create a proposal allowing the withdrawal of funds from the pool to one or more specified accounts, a pool owner can use the proposal-spending-pool-withdraw
command. Withdrawal is only possible if the receiving accounts are on the list of registered beneficiaries.
Flags
$TITLE
: The title of the proposal.$DESCRIPTION
: Description of the proposal.$NAME
: Name of the spending pool registry.$BENEFICIARYACCOUNTS
: List of account addresses eligible for funds distribution. Format:kira1mig9(...),...
.$AMOUNTS
: Coin denomination and amount to be withdrawn. Format:<amount><denom>
, e.g.,1000ukex
.
sekaid tx spending proposal-withdraw-spending-pool \
--from=$SIGNER $FLAGS_TX \
--title=$TITLE --description=$DESCRIPTION \
--name=$NAME -beneficiary-accounts=$BENEFICIARYACCOUNTS --amount=$AMOUNTS
Force Funds Distribution
To force the distribution of tokens to all registered beneficiaries, a pool owner can use the proposal-distribute-spending-pool
command. This function should be used before making upgrades to a pool.
Flags
$TITLE
: The title of the proposal.$DESCRIPTION
: Description of the proposal.$NAME
: Name of the spending pool registry.
sekaid tx spending proposal-distribute-spending-pool \
--from=$SIGNER $FLAGS_TX \
--title=$TITLE --description=$DESCRIPTION \
--name=$NAME