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
fee_collectormodule account by default, or to the PoA module account if configured (see Fee Routing Setup) -
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 PoA 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):- PoA module account 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 the PoA module account to 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
Fee Routing Setup
PoA has its own module account for collecting fees. Enabling the PoA module account is recommended to keep fee accounting isolated and accurate. If not enabled, fees are deposited into the standardfee_collector account by default.
To enable the PoA module account, two wiring changes are required:
1. Register the PoA Module Account
Registerpoatypes.ModuleName in the maccPerms map passed to authkeeper.NewAccountKeeper:
simapp/app.go
2. Configure the Ante Handler
UseWithFeeRecipientModule on NewDeductFeeDecorator to route fees to the PoA module account:
simapp/ante.go
WithFeeRecipientModule is backwards compatible — omitting it defaults to the standard fee_collector behavior.
Security Considerations
- Decimal Precision:
- Uses DecCoins to prevent dust accumulation
- Validators track fractional amounts
- Remainders preserved across withdrawals
- Prevents rounding errors from accumulating