# Protocol Fee
Fee collection and distribution for protocol operations.
## Overview
The protocol-fee contract collects authorized fees from protocol operations and
distributes them to GovStaker and DevOps according to configured percentages.
## Configuration
- **Router Fee (initial/default)**: 0.15% of the swap amount; configured by the router, with an admin-or-governance range of 0–10%
- **Pool Creation Fee (initial/default)**: 100 GNS; configured by the pool and modifiable through governance
- **Withdrawal Fee (initial/default)**: 1% of LP fees claimed; configured by the pool and modifiable through governance
- **Unstaking Fee (initial/default)**: 1% of staking rewards; configured by the staker and modifiable by admin or governance
- **Distribution (default)**: 100% to GovStaker and 0% to DevOps
The operation-specific fees above are configured in their owning modules; they
are not protocol-fee distribution percentages.
## Fee Sources
1. **Swaps**: The router applies its configured swap fee (0.15% initially).
2. **Pool Creation**: The pool charges its configured creation fee (100 GNS initially).
3. **LP Withdrawals**: The pool charges its configured withdrawal fee (1% initially).
4. **Staking Claims**: The staker charges its configured unstaking fee (1% initially).
## Key Functions
### `DistributeProtocolFee`
Distributes accumulated fees to recipients.
### `SetDevOpsPct`
Sets the DevOps funding percentage.
### `SetGovStakerPct`
Sets the GovStaker funding percentage.
### `AddToProtocolFee`
Adds an approved fee amount to the distribution queue.
### `AdvanceAccrualEpoch`
Closes the accrual epoch in force and returns the new one. Called by gov/staker on every stake change, so fees are attributed to the stake distribution live when they arrived.
### `ConsumeAccrualBuckets`
Returns and clears up to `limit` of the oldest pending buckets of one token, as parallel epoch and amount slices. Called by gov/staker when that token is collected.
## Usage
```go
// Distribute accumulated fees
DistributeProtocolFee(cross(cur))
// Configure distribution
SetDevOpsPct(cross(cur), 2000) // 20% to DevOps
SetGovStakerPct(cross(cur), 8000) // 80% to GovStaker
// View tokens reserved for the next distribution
GetReservedTokens()
// View what gov/staker has not folded yet
GetAccrualEpoch()
GetAccrualPendingTokens()
GetAccrualBuckets(tokenPath, 0)
```
## Security
- Configuration changes are restricted to admin or governance; distribution is restricted to admin or gov/staker
- Automatic fee accumulation
- Multi-token support
- Transparent distribution tracking
NewProtocolFeeStateBy(protocolFeeStore interface {AddAccrualBucket func(int, .uverse.realm, string, int64, int64) .uverse.error; AddAccrualPendingToken func(int, .uverse.realm, string) .uverse.error; AddReservedToken func(int, .uverse.realm, string) .uverse.error; GetAccrualBuckets func(string, int) ([]int64, []int64); GetAccrualEpoch func() int64; GetAccrualPendingTokens func() []string; GetAccuToDevOps func() *gno.land/p/nt/bptree/v0.BPTree; GetAccuToDevOpsItem func(string) (int64, bool); GetAccuToGovStaker func() *gno.land/p/nt/bptree/v0.BPTree; GetAccuToGovStakerItem func(string) (int64, bool); GetDevOpsPct func() int64; GetDistributedToDevOpsHistory func() *gno.land/p/nt/bptree/v0.BPTree; GetDistributedToDevOpsHistoryItem func(string) (int64, bool); GetDistributedToGovStakerHistory func() *gno.land/p/nt/bptree/v0.BPTree; GetDistributedToGovStakerHistoryItem func(string) (int64, bool); GetReservedTokens func() []string; HasAccrualBucketsStoreKey func() bool; HasAccrualEpochStoreKey func() bool; HasAccrualPendingTokensStoreKey func() bool; HasAccuToDevOpsStoreKey func() bool; HasAccuToGovStakerStoreKey func() bool; HasDevOpsPctStoreKey func() bool; HasDistributedToDevOpsHistoryStoreKey func() bool; HasDistributedToGovStakerHistoryStoreKey func() bool; HasReservedToken func(string) bool; HasReservedTokensStoreKey func() bool; InitializeAccrualBuckets func(int, .uverse.realm) .uverse.error; InitializeAccrualEpoch func(int, .uverse.realm) .uverse.error; InitializeAccrualPendingTokens func(int, .uverse.realm) .uverse.error; InitializeAccuToDevOps func(int, .uverse.realm) .uverse.error; InitializeAccuToGovStaker func(int, .uverse.realm) .uverse.error; InitializeDevOpsPct func(int, .uverse.realm) .uverse.error; InitializeDistributedToDevOpsHistory func(int, .uverse.realm) .uverse.error; InitializeDistributedToGovStakerHistory func(int, .uverse.realm) .uverse.error; InitializeReservedTokens func(int, .uverse.realm) .uverse.error; RemoveAccrualBuckets func(int, .uverse.realm, string, []int64) .uverse.error; RemoveAccrualPendingToken func(int, .uverse.realm, string) .uverse.error; RemoveReservedToken func(int, .uverse.realm, string) .uverse.error; SetAccrualEpoch func(int, .uverse.realm, int64) .uverse.error; SetAccuToDevOpsItem func(int, .uverse.realm, string, int64) .uverse.error; SetAccuToGovStakerItem func(int, .uverse.realm, string, int64) .uverse.error; SetDevOpsPct func(int, .uverse.realm, int64) .uverse.error; SetDistributedToDevOpsHistoryItem func(int, .uverse.realm, string, int64) .uverse.error; SetDistributedToGovStakerHistoryItem func(int, .uverse.realm, string, int64) .uverse.error}) *gno.land/r/gnoswap/protocol_fee/v1.protocolFeeState
NewProtocolFeeV1(protocolFeeStore interface {AddAccrualBucket func(int, .uverse.realm, string, int64, int64) .uverse.error; AddAccrualPendingToken func(int, .uverse.realm, string) .uverse.error; AddReservedToken func(int, .uverse.realm, string) .uverse.error; GetAccrualBuckets func(string, int) ([]int64, []int64); GetAccrualEpoch func() int64; GetAccrualPendingTokens func() []string; GetAccuToDevOps func() *gno.land/p/nt/bptree/v0.BPTree; GetAccuToDevOpsItem func(string) (int64, bool); GetAccuToGovStaker func() *gno.land/p/nt/bptree/v0.BPTree; GetAccuToGovStakerItem func(string) (int64, bool); GetDevOpsPct func() int64; GetDistributedToDevOpsHistory func() *gno.land/p/nt/bptree/v0.BPTree; GetDistributedToDevOpsHistoryItem func(string) (int64, bool); GetDistributedToGovStakerHistory func() *gno.land/p/nt/bptree/v0.BPTree; GetDistributedToGovStakerHistoryItem func(string) (int64, bool); GetReservedTokens func() []string; HasAccrualBucketsStoreKey func() bool; HasAccrualEpochStoreKey func() bool; HasAccrualPendingTokensStoreKey func() bool; HasAccuToDevOpsStoreKey func() bool; HasAccuToGovStakerStoreKey func() bool; HasDevOpsPctStoreKey func() bool; HasDistributedToDevOpsHistoryStoreKey func() bool; HasDistributedToGovStakerHistoryStoreKey func() bool; HasReservedToken func(string) bool; HasReservedTokensStoreKey func() bool; InitializeAccrualBuckets func(int, .uverse.realm) .uverse.error; InitializeAccrualEpoch func(int, .uverse.realm) .uverse.error; InitializeAccrualPendingTokens func(int, .uverse.realm) .uverse.error; InitializeAccuToDevOps func(int, .uverse.realm) .uverse.error; InitializeAccuToGovStaker func(int, .uverse.realm) .uverse.error; InitializeDevOpsPct func(int, .uverse.realm) .uverse.error; InitializeDistributedToDevOpsHistory func(int, .uverse.realm) .uverse.error; InitializeDistributedToGovStakerHistory func(int, .uverse.realm) .uverse.error; InitializeReservedTokens func(int, .uverse.realm) .uverse.error; RemoveAccrualBuckets func(int, .uverse.realm, string, []int64) .uverse.error; RemoveAccrualPendingToken func(int, .uverse.realm, string) .uverse.error; RemoveReservedToken func(int, .uverse.realm, string) .uverse.error; SetAccrualEpoch func(int, .uverse.realm, int64) .uverse.error; SetAccuToDevOpsItem func(int, .uverse.realm, string, int64) .uverse.error; SetAccuToGovStakerItem func(int, .uverse.realm, string, int64) .uverse.error; SetDevOpsPct func(int, .uverse.realm, int64) .uverse.error; SetDistributedToDevOpsHistoryItem func(int, .uverse.realm, string, int64) .uverse.error; SetDistributedToGovStakerHistoryItem func(int, .uverse.realm, string, int64) .uverse.error}) interface {AddToProtocolFee func(int, .uverse.realm, string, int64) .uverse.error; AdvanceAccrualEpoch func(int, .uverse.realm) int64; ConsumeAccrualBuckets func(int, .uverse.realm, string, int) ([]int64, []int64); DistributeProtocolFee func(int, .uverse.realm); DistributeProtocolFeeByTokenPath func(int, .uverse.realm, string); GetAccrualBuckets func(string, int) ([]int64, []int64); GetAccrualEpoch func() int64; GetAccrualPendingTokens func() []string; GetAccuTransferToDevOpsByTokenPath func(string) int64; GetAccuTransferToGovStakerByTokenPath func(string) int64; GetAccuTransfersToDevOps func() map[string]int64; GetAccuTransfersToGovStaker func() map[string]int64; GetActualDistributedToDevOps func() map[string]int64; GetActualDistributedToDevOpsByTokenPath func(string) int64; GetActualDistributedToGovStaker func() map[string]int64; GetActualDistributedToGovStakerByTokenPath func(string) int64; GetDevOpsPct func() int64; GetGovStakerPct func() int64; GetReservedTokens func() []string; Render func(string) string; SetDevOpsPct func(int, .uverse.realm, int64); SetGovStakerPct func(int, .uverse.realm, int64)}
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.