Concept
Spending pools are KIRAβs native token distribution system, providing a way to distribute a pooled amount of one or multiple tokens to a defined 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.
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.
Parameters
Rates (static)
The 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 an account made a claim within the claiming period. This information is sufficient to calculate an account's current entitlement by multiplying the 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).
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 to receive their earnings, with a spending pool, an account can claim multiple times within the 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 Expiry
The claim-expiry parameter is a maximum period during which an account is required to make a claim in order to stay registered in the pool. This is necessary because if the distribution rate changes over time and an account hasn't made a claim in a while, the system is not able to accurately calculate the amount owed to the account. By enforcing a claim expiry, inactive accounts can be removed from the pool, as they will need to pay a transaction fee from time to time in order to remain active and continue receiving rewards from the pool. For example, if the claim expiry is set to 3 months, any account that has not made a claim within the last 3 months will be automatically unregistered from the pool.
The proposal-distribute-spending-pool command enables a spending poolβs governance to enforce distribution. This command is particularly useful to avoid misdistribution when modifying the fixed distribution rate.
Rates (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 fluctuates, 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).
The main difference is that in dynamic mode users entitlements are "pipelined," meaning that claiming actually withdraws entitlements from the previous dynamic-rate-period using its respective dynamic rates, and the current dynamic-rate-period's entitlement will be redeemable at the next one. The spending pool still calculates an account's entitlement by multiplying the dynamic rates by the time elapsed since the last claim, allowing an account to make multiple claims during a given dynamic-rate-period. However, and most importantly, dynamic rates of a respective dynamic-rate-period N are set so that all pooled tokens at the end of that period should theoretically be fully distributed at the end of the next dynamic-rate-period N+1 (and no longer at the end of the poolβs claiming period). This means that any token that hasn't been claimed before the end of dynamic-rate-period N will be redistributed during dynamic-rate-period N+1. In essence, the dynamic period becomes the claim expiry, and if an account doesn't claim its tokens in time, they will be lost and mutualized. This also means that beneficiaries who register cannot instantly start claiming and must wait until the next dynamic period starts 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, to a designated set of beneficiaries.
Distribution weights
Individual token distribution rates can be set for specific accounts and/or roles using weights. For example, if an 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 token 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 the 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.
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 and claim-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, the claim expiration period, or the dynamic claim period has elapsed and the funds have not been claimed by the beneficiary, the funds will not be sent.
If all of these conditions are met, the funds will be distributed to the beneficiary.
CLI functions description
tx/spending
create-spending-pool - Creates a new spending pool. Sender becomes owner and must provide a unique name.
deposit-spending-pool - Allows any account to deposit any tokens to the pool.
register-spending-pool-beneficiary - Registers as a beneficiary account.
proposal-spending-pool-update - Creates a proposal to modify an existing spending pool.
claim-spending-pool - Claim tokens from the pool. Only beneficiaries can send this transaction. Funds can only be claimed within a certain period and if certain conditions are met.
proposal-spending-pool-withdraw - Creates a proposal allowing withdrawal of funds from the pool to specified accounts. Withdrawal is only possible to registered beneficiaries.
proposal-distribute-spending-pool - Forces distribution of tokens to all registered beneficiaries.
query/spending
pool-names - Lists all existing pool names.
pool-by-name - Query a pool using its name.
pool-proposals - Query all existing pool proposals.
pools-by-account - Lists all pool names where specific account can register its claim or otherwise claim tokens from.
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 flags configuration section
Creating a spending pool
To create a new spending pool, an account can use the create-spending-pool command. This function can be sent by any account, and the account sending the transaction automatically becomes the pool owner.
Bash
Copy
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-accounts=$OWNERACCOUNTS --owner-roles=$OWNERROLES \
--beneficiary-accounts=$BENEFICIARYACCOUNTS --beneficiary-roles=$BENEFICIARYROLES
Bash
Copy
# Example
sekaid tx spending proposal-update-spending-pool \
--from=$SIGNER $FLAGS_TX \
--name="ValidatorRewardsPool" --claim-start=$(($(date -u +%s))) --claim-end=0 \
--rates=0.1ukex \
--vote-quorum="33" --vote-period="60" --vote-enactment="30" \
--owner-roles="" --owner-accounts=validator \
--beneficiary-roles="1" --beneficiary-accounts=""
Depositing token to a spending pool
To deposit tokens to an existing spending pool, an account can use the deposit-spending-pool command. Any KIRA address can call this function and deposit tokens. Only the asset defined by the token field of the pool can be deposited to the pool.
Bash
Copy
sekaid tx spending deposit-spending-pool \
--from=$SIGNER $FLAGS_TX \
--name=$NAME --amount=$AMOUNTS
Bash
Copy
sekaid tx spending deposit-spending-pool \
--from=$SIGNER $FLAGS_TX \
--name="ValidatorRewardsPool" --amount=1000000ukex
Registering as beneficiary
To register an account as a beneficiary, which makes it eligible for claims, an account can use the register-spending-pool-beneficiary command.
Bash
Copy
sekaid tx spending register-spending-pool-beneficiary \
--from=$SIGNER $FLAGS_TX \
--name=$NAME
Updating an existing spending pool via proposal
To create a proposal to modify an existing spending pool, an account can use the proposal-spending-pool-update command. This function allows the account to add new owners or beneficiaries, or to edit any of the pool's existing properties.
Bash
Copy
sekaid tx spending proposal-update-spending-pool \
--from=$SIGNER $FLAGS_TX \
--title=$TITLE--description=$DESCRIPTION \
--name=$NAME --claim-start=$CLAIMSTART --claim-end=$CLAIMEND \
--token=$TOKEN --rate=$RATE \
--vote-quorum=$VOTEQUORUM --vote-period=$VOTEPERIOD --vote-enactment=$VOTEENACTMENT \
--owner-accounts=$OWNERACCOUNTS --owner-roles=$OWNERROLES \
--beneficiary-accounts=$BENEFICIARYACCOUNTS --beneficiary-roles=$BENEFICIARYROLES
Bash
Copy
# Example
sekaid tx spending proposal-update-spending-pool \
--from=$SIGNER $FLAGS_TX \
--title="title" --description="change rate from 0.1 to 0.5" \
--name="ValidatorRewardsPool" --claim-start=$(($(date -u +%s))) --claim-end=0 \
--token="ukex" --rate=0.5 \
--vote-quorum="33" --vote-period="60" --vote-enactment="30" \
--owner-roles="" --owner-accounts=validator \
--beneficiary-roles="1" --beneficiary-accounts=""
Claiming tokens
To request the funds they are entitled to, a beneficiary account can use the claim-spending-pool command. In order to use this command, the beneficiary account must have already registered and it must be present in the claims array of the pool. The funds can only be claimed within a certain period, as defined by the claims property and the current distribution rate. The pool must also have a sufficient balance of the specific token as defined by the tokens property. If these conditions are met, the exact amount owed to the beneficiary will be sent to their account. If the claim expiration period has elapsed or the pool does not have enough funds, the funds will not be sent to the beneficiary.
Bash
Copy
sekaid tx spending claim-spending-pool \
--from=$SIGNER $FLAGS_TX \
--name=$NAME
Withdraw pool via proposal
To force the distribution of tokens to all beneficiaries registered in the claims array, an account can use the proposal-distribute-spending-pool command. This function should be automatically triggered before upgrades are executed.
Bash
Copy
sekaid tx spending proposal-spending-pool-withdraw \
--from=$SIGNER $FLAGS_TX \
--title=$PROPOSAL_TITLE --description=$PROPOSAL_DESCR \
--name=$NAME --beneficiary-accounts=$BENEFICIARYACCOUNTS --amount=$AMOUNT
Force pool distribution via proposal
To create a proposal allowing the withdrawal of funds from the pool to one or more specified accounts, an account can use the proposal-spending-pool-withdraw command. Withdrawal is only possible if the receiving accounts are on the list of registered beneficiaries.
Bash
Copy
sekaid tx spending proposal-spending-pool-distribution \
--from=$SIGNER $FLAGS_TX \
--title=$TITLE --description=$DESCRIPTION --name=$NAME
Queries
List pool names
To get a list of all pool names, an account can use the pool-names command.
Bash
Copy
sekaid query spending pool-names $FLAGS_QR | jq
Querying a specific pool
To get detailed information about a specific pool, an account can use the pool-by-name command and specify the name of the pool they want to query.
Bash
Copy
sekaid query spending pool-by-name $NAME $FLAGS_QR | jq
List of pool proposals
To get a list of all pool proposals, an account can use the pool-proposals command.
Bash
Copy
sekaid query spending pool-proposals $NAME $FLAGS_QR | jq
List of pools for a specific account
To get a list of pool names where a specific KIRA account can register as beneficiary or claim tokens from, an account can use the query-pools-by-account command and specify the KIRA account they want to check.
Note: this CLI only accept one address.
Bash
Copy
sekaid query spending pools-by-account $BENEFICIARYACCOUNTS $FLAGS_QR | jq