Fee Distribution
Overview
The PoA module implements a custom fee distribution mechanism based on validator power. Unlike the standard Cosmos SDK x/distribution module, PoA uses a checkpoint-based system to allocate fees proportionally to validators without automatic distribution.How Fees Accumulate
Fees flow through the PoA system differently than standard Cosmos SDK:-
Block Fees: Transaction fees collected in each block go to the standard
fee_collectormodule account -
Checkpoint System: Allocated fees are updated for validators when:
- Any validator power changes
- Any validator withdraws fees
x/poa/keeper/distribution.go:18
Distribution Algorithm
Checkpoint-Based Allocation
The PoA module uses a checkpoint system to allocate fees fairly when validator power changes. Rather than distributing fees actively at every block, allocation efficiently happens at discrete checkpoints. Checkpoint Triggers:- Any validator power change (via
MsgUpdateValidators) - Any fee withdrawal (via
MsgWithdrawFees)
- = unallocated fees at checkpoint
- = current balance in the fee collector module account
- = sum of all previously- allocated fees across all validators (0 if no checkpoints have been done)
- = share allocated to validator at checkpoint
- = voting power of validator at checkpoint
- = sum of all validator powers
- = validator ‘s accumulated fees before checkpoint
- = validator ‘s accumulated fees after checkpoint
- = share allocated in this checkpoint
Example Checkpoint Sequence
Initial State (before checkpoint):- Fee collector balance: tokens
- Total allocated: tokens (from previous checkpoints)
- Validator A: , tokens allocated
- Validator B: , tokens allocated
- Total power:
MsgUpdateValidators to change power distribution to 30/70
Checkpoint Triggered (before power change takes effect):
- Calculate unallocated: tokens
-
Allocate shares based on current power (50/50):
- Validator A: tokens
- Validator B: tokens
-
Update accumulated fees:
- Validator A: tokens
- Validator B: tokens
- Update total allocated: tokens
- Validator A: (new power for future blocks)
- Validator B: (new power for future blocks)
- All 1000 tokens now allocated ()
- Each validator has updated available for withdrawal
DecCoins (decimal coins) to prevent rounding dust accumulation. Each validator tracks fractional amounts that are too small to withdraw.
Withdrawing Fees
MsgWithdrawFees (x/poa/keeper/msg_server.go:91)
Any validator operator can withdraw accumulated fees:
- Submit Withdrawal: Signed by operator address
- Checkpoint: System checkpoints all validators first (allocates any pending fees)
- Truncate: Decimal coins truncated to whole coins
- Transfer: Coins transferred from
fee_collectorto operator address - Update Tracking: Total allocated decreases by withdrawn amount
- Remainder: Decimal remainder stays in validator’s allocated balance
x/poa/keeper/distribution.go:106
Withdrawal Formula
When validator withdraws fees: Where:- = amount withdrawn (truncated to integer coins)
- = validator’s allocated fees before withdrawal
- = validator’s allocated fees after withdrawal (decimal remainder)
- = floor function (truncate decimals)
- = updated total allocated across all validators
Security Considerations
- Decimal Precision:
- Uses DecCoins to prevent dust accumulation
- Validators track fractional amounts
- Remainders preserved across withdrawals
- Prevents rounding errors from accumulating