Namada uses the automatically-compounding variant of F1 fee distribution.
Rewards are given to validators for voting on finalizing blocks: the fund for these rewards can come from minting (creating new tokens). The amount that is minted depends on how much is staked and our desired yearly inflation. When the total of the tokens staked is very low, the return rate per validator needs to increase, but as the total amount of stake rises, validators will receive less rewards. Once we have acquired the desired stake percentage, the amount minted will just be the desired yearly inflation.
The validator and the delegator must have agreed on a commission rate between themselves. Delegators pay out rewards to validators based on a mutually-determined commission rate that both parties must have agreed upon beforehand. The minted rewards are auto-bonded and only transferred when the funds are unbonded. Once we have calculated the total that needs to be minted at the end of the epoch, we split the minted tokens according to the stake the relevant validators and delegators contributed and distribute them to validators and their delegators. This is similar to what Cosmos does.
Consider a system with
- a canonical singular staking unit of account.
- a set of validators .
- a set of delegations , each to a particular validator and in a particular (initial) amount.
- epoched proof-of-stake, where changes are applied as follows:
- bonding after the pipeline length
- unbonding after the unbonding length
- rewards are paid out at the end of each epoch, to wit, in each epoch , is paid out to validator
- slashing is applied as described in slashing.
We wish to approximate as exactly as possible the following ideal delegator reward distribution system:
- At each epoch, for a validator , iterate over all of the delegations to that validator. Update each delegation , as follows. where and respectively denote the reward and stake of validator at epoch .
- Similarly, multiply the validator's voting power by the same factor , which should now equal the sum of their revised-amount delegations.
In this system, rewards are automatically rebonded to delegations, increasing the delegation amounts and validator voting powers accordingly.
However, we wish to implement this without actually needing to iterate over all delegations each block, since this is too computationally expensive. We can exploit this constant multiplicative factor which does not vary per delegation to perform this calculation lazily, storing only a constant amount of data per validator per epoch, and calculate revised amounts for each individual delegation only when a delegation changes.
We will demonstrate this for a delegation to a validator . Let denote the stake of at epoch .
For two epochs and with , define the function as
Denote as . The function has a useful property.
One may calculate the accumulated changes upto epoch as
If we know the delegation upto epoch , the delegation at epoch is obtained by the following formula,
Using property ,
Clearly, the quantity does not depend on the delegation . Thus, for a given validator, we need only store this product at each epoch , with which updated amounts for all delegations can be calculated.
The product at the end of each epoch is updated as follows.
updateProducts :: HashMap<Address, HashMap<Epoch, Float>> -> HashSet<Address> -> Epoch -> HashMap<BondId, Token::amount>> updateProducts validatorProducts activeSet currentEpoch = let stake = PoS.readValidatorTotalDeltas validator currentEpoch reward = PoS.reward stake currentEpoch entries = lookup validatorProducts validator lastProduct = lookup entries (Epoch (currentEpoch - 1)) in insert currentEpoch (product*(1+rsratio)) entries
Commission is charged by a validator on the rewards coming from delegations. These are set as percentages by the validator, who may charge any commission they wish between 0-100%.
Let c_V(e)DVep_nc_V(e)Ve, including for self-bonds. The validator can change the commission rate at any point, subject to a maximum rate of change per epoch, which is a constant specified when the validator is created and immutable once validator creation has been accepted.
While rewards are given out at the end of every epoch, voting power is only updated after the pipeline offset. According to the proof-of-stake system, at the current epoch
e, the validator sets an only be updated for epoch
e + pipeline_offset, and it should remain unchanged from epoch
e + pipeline_offset - 1. Updating voting power in the current epoch would violate this rule.
Slashes should lead to punishment for delegators who were contributing voting power to the validator at the height of the infraction, as if the delegations were iterated over and slashed individually.
This can be implemented as a negative inflation rate for a particular block.
Instant redelegation is not supported. Redelegations must wait the unbonding period.