README.md
Emission
GNS token emission and distribution system.
Overview
The emission system controls creation and distribution of new GNS tokens with a deflationary model featuring periodic halvings, ensuring predictable and decreasing supply growth over 12 years. For more details, check out docs.
Token Economics
- Total Supply Cap: 1,000,000,000 GNS
- Initial Minted: 100,000,000 GNS, pre-minted to the configured
ADMINrole address during GNS realm initialization - To Be Minted: 900,000,000 GNS over 12 years
- Halving Period: Every 2 years (63,072,000 seconds)
- Halving Reduction: 50% decrease in emission rate
- Distribution: Automatic during protocol activity
Configuration
- Distribution Ratios (modifiable by admin or governance):
- Liquidity Staker: 75% (default)
- DevOps: 20% (default)
- Community Pool: 5% (default)
- Governance Staker: 0% (default)
- Start Time: Unix timestamp. It may be changed while the configured timestamp is still in the future; once active, it cannot be changed.
Core Features
Emission Schedule
Implements Bitcoin-style halving model:
- Year 1-2: 100% emission rate
- Year 3-4: 50% emission rate
- Year 5-6: 25% emission rate
- Year 7-8: 12.5% emission rate
- Year 9-12: 6.25% emission rate
Distribution Mechanism
When triggered by protocol activity:
- Calculates elapsed time since last distribution
- Mints GNS based on the current timestamp range and halving-year rates
- Distributes to targets per configured ratios
- Carries forward any undistributed amounts
If emission is halted, MintAndDistributeGns returns (0, false) without
panicking. A caller that requires emission must explicitly handle that result.
Key Functions
MintAndDistributeGns
Mints and distributes GNS tokens automatically.
SetDistributionStartTime
Sets or reschedules the emission start timestamp before distribution is active. The timestamp must be positive and in the future; after the configured start time has been reached, the timestamp is immutable.
ChangeDistributionPct
Updates distribution percentages (admin or governance only).
GetDistributionBpsPct
Returns current distribution percentage in basis points for a target, or an error if the target is invalid.
Gnoweb
Render("") shows distribution dates in UTC, GNS amounts with six decimal places,
allocation percentages, and cumulative distributions for the four recipients.
Staker and governance-staker counters since their last accounting clear are shown
separately: these allocations have already been transferred and are not wallet
balances or user-claimable rewards. Unsupported paths return 404.
Technical Details
Timestamp-Based Emission
The following is a conceptual view of the schedule:
emissionPerSecond = baseEmission / (2^halvingCount)
amountToMint = emissionPerSecond * elapsedSeconds
The implementation uses integer, piecewise rates. For each halving year
intersecting the inclusive mint range [fromTimestamp, toTimestamp], it
initializes yearAmountPerSecond as
floor(yearDistributionAmount / SECONDS_IN_YEAR) and multiplies that rate by
the inclusive number of seconds. The mint range is clamped to the 12-year
schedule end. When a range reaches a year end, the remaining integer amount
(including division dust) is added so that the year's allocation is exhausted.
Halving Calculation
Halving years are determined by the schedule's year boundaries; the conceptual form is:
halvingCount = floor(timeSinceStart / halvingPeriod)
Distribution Targets
- Liquidity Staker: Rewards for LP providers
- DevOps: Development and operations fund
- Community Pool: Community-governed treasury
- Governance Staker: GNS staking rewards (currently 0%)
Usage
1// Set emission start (admin/governance; timestamp must be in the future)
2SetDistributionStartTime(cross(cur), futureStartTimestamp)
3
4// Trigger emission (called automatically by protocol flows)
5amount, ok := MintAndDistributeGns(cross(cur))
6
7// Update distribution ratios
8ChangeDistributionPct(
9 cross(cur),
10 7000, // 70% to liquidity stakers
11 2000, // 20% to devops
12 1000, // 10% to community pool
13 0, // 0% to governance stakers
14)
15
16// Query distribution info
17stakerPct, err := GetDistributionBpsPct(LIQUIDITY_STAKER)
18if err != nil {
19 panic(err)
20}
21accumulated := GetAccuDistributedToStaker()
22rate, err := GetStakerEmissionAmountPerSecond()
23if err != nil {
24 panic(err)
25}
Security
- Start time may be rescheduled while still in the future and is immutable once active
- Distribution percentages must sum to 10000 (100%)
- A halted
MintAndDistributeGnscall returnsfalse; no automatic cross-module cascade occurs - If staker cache invalidation is required, keep the optional distribution-change callback registered
- Leftover tracking carries undistributed amounts forward
- Halving is enforced at protocol level