Skip to main content

Distribution

ℹ️info

Terra's distribution module inherits from Cosmos SDK's distribution module. This document is a stub and mainly covers important Terra-specific notes on how it is used.

The distribution module describes a mechanism that tracks collected fees and passively distributes them to validators and delegators. Additionally, the distribution module defines the community pool, which is a pool of funds under the control of on-chain governance.

Concepts

Validator and delegator rewards

ℹ️info

Passive distribution means that validators and delegators need to manually collect their fee rewards by submitting withdrawal transactions.

Collected rewards are pooled globally and distrubuted to validators and delegators. Each validator has the opportunity to charge delegators commission on the rewards collected on behalf of the delegators. Fees are collected directly into a global reward pool and a validator proposer reward pool. Due to the nature of passive accounting, whenever changes to parameters which affect the rate of reward distribution occur, withdrawal of rewards must also occur.

State

This section was taken from the official Cosmos SDK docs, and placed here for your convenience to understand the distribution module's parameters and genesis variables.

FeePool

Fees are collected and stored in the FeePool until they can be distributed to validators and their delegators.

Note that the reward pool holds decimal coins (DecCoins) to allow for fractions of coins to be received from operations like inflation. When coins are distributed from the pool they are truncated back to sdk.Coins which are non-decimal.

Validator distribution

The following validator distribution information for the relevant validator is updated each time:

  • Delegation amount to a validator is updated.
  • A validator successfully proposes a block and receives a reward.
  • Any delegator withdraws from a validator or the validator withdraws its commission.

Delegation distribution

Each delegation distribution only needs to record the height at which it last withdrew fees. Because a delegation must withdraw fees each time its properties change (aka bonded tokens etc.), its properties will remain constant and the delegator's accumulation factor can be calculated passively knowing only the height of the last withdrawal and its current properties.

Message types

MsgSetWithdrawAddress


_4
type MsgSetWithdrawAddress struct {
_4
DelegatorAddress sdk.AccAddress `json:"delegator_address" yaml:"delegator_address"`
_4
WithdrawAddress sdk.AccAddress `json:"withdraw_address" yaml:"withdraw_address"`
_4
}

MsgWithdrawDelegatorReward


_5
// msg struct for delegation withdraw from a single validator
_5
type MsgWithdrawDelegatorReward struct {
_5
DelegatorAddress sdk.AccAddress `json:"delegator_address" yaml:"delegator_address"`
_5
ValidatorAddress sdk.ValAddress `json:"validator_address" yaml:"validator_address"`
_5
}

MsgWithdrawValidatorCommission


_3
type MsgWithdrawValidatorCommission struct {
_3
ValidatorAddress sdk.ValAddress `json:"validator_address" yaml:"validator_address"`
_3
}

MsgFundCommunityPool


_4
type MsgFundCommunityPool struct {
_4
Amount sdk.Coins `json:"amount" yaml:"amount"`
_4
Depositor sdk.AccAddress `json:"depositor" yaml:"depositor"`
_4
}

Proposals

CommunityPoolSpendProposal

The distribution module defines a special proposal that, upon being passed, disburses the coins specified in Amount to the Recipient account using funds from the community pool.


_6
type CommunityPoolSpendProposal struct {
_6
Title string `json:"title" yaml:"title"`
_6
Description string `json:"description" yaml:"description"`
_6
Recipient sdk.AccAddress `json:"recipient" yaml:"recipient"`
_6
Amount sdk.Coins `json:"amount" yaml:"amount"`
_6
}

Transitions

Begin-Block

This section derives from the official Cosmos SDK docs, and is placed here for your convenience to understand the distribution module's parameters.

At the beginning of each block, the distribution module will set the proposer for determining distribution during endblock and distribute rewards for the previous block.

The fees received are transferred to the Distribution ModuleAccount, which tracks the flow of coins in and out of the module. Fees are also allocated to the proposer, community fund, and global pool:

  • Proposer: When a validator is the proposer of a round, that validator and its delegators receive 1-5% of the fee rewards.
  • Global pool: The remainder of the funds is allocated to the global pool, where they are distributed proportionally by voting power to all bonded validators independent of whether they voted. This allocation is called social distribution. Social distribution is applied to the proposer validator in addition to the proposer reward.

The proposer reward is calculated from precommits Tendermint messages to incentivize validators to wait and include additional precommits in the block. All provision rewards are added to a provision reward pool, which each validator holds individually (ValidatorDistribution.ProvisionsRewardPool).


_21
func AllocateTokens(feesCollected sdk.Coins, feePool FeePool, proposer ValidatorDistribution,
_21
sumPowerPrecommitValidators, totalBondedTokens, communityTax,
_21
proposerCommissionRate sdk.Dec)
_21
_21
SendCoins(FeeCollectorAddr, DistributionModuleAccAddr, feesCollected)
_21
feesCollectedDec = MakeDecCoins(feesCollected)
_21
proposerReward = feesCollectedDec * (0.01 + 0.04
_21
* sumPowerPrecommitValidators / totalBondedTokens)
_21
_21
commission = proposerReward * proposerCommissionRate
_21
proposer.PoolCommission += commission
_21
proposer.Pool += proposerReward - commission
_21
_21
communityFunding = feesCollectedDec * communityTax
_21
feePool.CommunityFund += communityFunding
_21
_21
poolReceived = feesCollectedDec - proposerReward - communityFunding
_21
feePool.Pool += poolReceived
_21
_21
SetValidatorDistribution(proposer)
_21
SetFeePool(feePool)

Parameters

The subspace for the distribution module is distribution.


_8
type GenesisState struct {
_8
...
_8
CommunityTax sdk.Dec `json:"community_tax" yaml:"community_tax"`
_8
BaseProposerReward sdk.Dec `json:"base_proposer_reward" yaml:"base_proposer_reward"`
_8
BonusProposerReward sdk.Dec `json:"bonus_proposer_reward" yaml:"bonus_proposer_reward"`
_8
WithdrawAddrEnabled bool `json:"withdraw_addr_enabled"`
_8
...
_8
}

Genesis parameters

The genesis parameters for the crisis module outlined in the Genesis Builder Script are as follows:


_22
community_pool_allocation = TOTAL_ALLOCATION - pre_attack_allocation - \
_22
post_attack_allocation - validator_allocation - emergency_allocation
_22
_22
# Distribution: community pool
_22
genesis['app_state']['distribution']['fee_pool']['community_pool'] = [{
_22
'denom': DENOM_LUNA,
_22
'amount': str(community_pool_allocation)
_22
}]
_22
_22
# Distribution: set community tax to 0
_22
genesis['app_state']['distribution']['params'] = {
_22
'community_tax': '0.000000000000000000',
_22
'base_proposer_reward': '0.010000000000000000',
_22
'bonus_proposer_reward': '0.040000000000000000',
_22
'withdraw_addr_enabled': True
_22
}
_22
_22
# Distribution: module account registration
_22
add_module_account(
_22
genesis, 'distribution',
_22
'terra1jv65s3grqf6v6jl3dp4t6c9t9rk99cd8pm7utl',
_22
str(community_pool_allocation), [])

CommunityTax

  • type: Dec

BaseProposerReward

  • type: Dec

BonusProposerReward

  • type: Dec

WithdrawAddrEnabled

  • type: bool