v1 source realm
package v1 manages liquidity mining rewards for GnoSwap positions.
View source
Staker
Liquidity mining and reward distribution for LP positions.
Overview
Staker manages distribution of internal (GNS emission) and external (user-provided) rewards to staked LP positions, with time-weighted rewards and warmup periods.
Configuration
- Deposit GNS Amount: 1,000 GNS for external incentives (default)
- Minimum Reward Amount: 1,000 tokens (default)
- Unstaking Fee: 1% (default)
- Pool Tiers: 1, 2, or 3 (assigned per pool)
- Warmup Schedule: 30/50/70/100% over 30/60/90 days
- External Token Whitelist: Approved reward tokens
Core Features
Internal Rewards (GNS Emission)
- Allocated to tiered pools (tiers 1, 2, 3)
- Split across tiers by TierRatio
- Distributed proportionally to in-range liquidity
- Unclaimed rewards go to community pool
External Rewards (User Incentives)
- Created for specific pools
- Constant reward per block
- Proportional to staked liquidity
- Unclaimed rewards returned to creator
Warmup Periods
Every staked position progresses through warmup periods:
- 0-30 days: 30% rewards (70% to community/creator)
- 30-60 days: 50% rewards (50% to community/creator)
- 60-90 days: 70% rewards (30% to community/creator)
- 90+ days: 100% rewards
Key Functions
StakeToken
Stakes LP position NFT to earn rewards.
UnStakeToken
Unstakes position and collects all rewards.
CollectReward
Collects accumulated rewards without unstaking.
CreateExternalIncentive
Creates external reward program for specific pool.
EndExternalIncentive
Ends incentive program and returns unused rewards.
Reward Calculation Logic
Tier Ratio Distribution
Emission split across tiers based on active pools:
If only tier 1 has pools: [100%, 0%, 0%]
If tiers 1 & 3 have pools: [80%, 0%, 20%]
If tiers 1 & 2 have pools: [70%, 30%, 0%]
If all tiers have pools: [50%, 30%, 20%]
Mathematical representation:
TierRatio(t) =
[1, 0, 0] if Count(2) = 0 ∧ Count(3) = 0
[0.8, 0, 0.2] if Count(2) = 0
[0.7, 0.3, 0] if Count(3) = 0
[0.5, 0.3, 0.2] otherwise
Pool Reward Formula
poolReward(pool) = (emission × TierRatio[tier(pool)]) / Count(tier(pool))
Where emission is calculated as:
emission = GNSEmissionPerSecond × (avgMsPerBlock/1000) × StakerEmissionRatio
Position Reward Calculation
The reward for each position is calculated through:
- Cache pool rewards up to current block
- Retrieve position state from deposit records
- Calculate internal rewards if pool is tiered
- Calculate external rewards for active incentives
- Apply warmup penalties based on stake duration
Mathematical formula for total reward ratio:
TotalRewardRatio(s,e) = Σ[i=0 to m-1] ΔRaw(αᵢ, βᵢ) × rᵢ
where:
αᵢ = max(s, Hᵢ₋₁)
βᵢ = min(e, Hᵢ)
ΔRaw(a, b) = CalcRaw(b) - CalcRaw(a)
CalcRaw(h) =
L(h) - U(h) if tick(h) < ℓ
U(h) - L(h) if tick(h) ≥ u
G(h) - (L(h) + U(h)) otherwise
where:
L(h) = tickLower.OutsideAccumulation(h)
U(h) = tickUpper.OutsideAccumulation(h)
G(h) = globalRewardRatioAccumulation(h)
ℓ = tickLower.id
u = tickUpper.id
Final position reward:
finalReward = TotalRewardRatio × poolReward × positionLiquidity
= ∫[s to e] (poolReward × positionLiquidity) / TotalStakedLiquidity(h) dh
Tick Cross Hook
When price crosses an initialized tick with staked positions:
- Updates staked liquidity - Adjusts total staked liquidity
- Updates reward accumulation - Recalculates
globalRewardRatioAccumulation - Manages unclaimable periods - Starts/ends periods with no in-range liquidity
- Updates tick accumulation - Adjusts
CurrentOutsideAccumulation
The globalRewardRatioAccumulation tracks the integral:
globalRewardRatioAccumulation = ∫ 1/TotalStakedLiquidity(h) dh
This integral is only computed when TotalStakedLiquidity(h) ≠ 0, enabling precise reward calculation even as liquidity changes.
Reward State Tracking
The system maintains:
- Global accumulation: Tracks reward ratio across all positions
- Tick accumulation: Tracks rewards "outside" each tick
- Position state: Individual reward calculation parameters
Usage
1// Stake existing position
2StakeToken(123, "g1referrer...")
3
4// Create external incentive
5CreateExternalIncentive(
6 "gno.land/r/demo/bar:gno.land/r/demo/baz:3000",
7 "gno.land/r/demo/reward",
8 "1000000000", // 1000 tokens
9 startTime,
10 endTime,
11)
12
13// Collect rewards without unstaking
14CollectReward(123)
15
16// Unstake and collect all rewards
17UnStakeToken(123)
Security
- Positions locked during staking
- External incentives require GNS deposit
- Warmup periods prevent gaming
- Unclaimed rewards properly redirected
- Hook integration ensures accurate tracking
package v1 manages liquidity mining rewards for GnoSwap positions.
The staker distributes GNS emissions and external incentives to liquidity providers based on their position size, price range, and staking duration. It supports both internal GNS rewards and external token incentives.
Rewards are calculated per-tick and accumulate over time, with automatic compounding and fee collection integration.
5
const GNS_TOKEN_KEY, WUGNOT_TOKEN_KEY
const AllTierCount, Tier1, Tier2, Tier3
const NOT_EMISSION_TARGET_TIER
const ZERO_ADDRESS
17
func DecodeInt64
Actionfunc DecodeUint
ActionDecodeUint converts a zero-padded string back into a uint64 number.
Parameters: - s (string): The zero-padded string.
Returns: - uint64: The decoded number.
Panics: - If the string cannot be parsed into a uint64.
Example: Input: "00000000000000012345" Output: 12345
func EncodeInt64
Actionfunc EncodeUint
ActionEncodeUint converts a uint64 number into a zero-padded 20-character string.
Parameters: - num (uint64): The number to encode.
Returns: - string: A zero-padded string representation of the number.
Example: Input: 12345 Output: "00000000000000012345"
func TierRatioFromCounts
ActionTierRatioFromCounts calculates the ratio distribution for each tier based on pool counts.
Parameters: - tier1Count (uint64): Number of pools in tier 1. - tier2Count (uint64): Number of pools in tier 2. - tier3Count (uint64): Number of pools in tier 3.
Returns: - TierRatio: The ratio distribution across tier 1, 2, and 3, scaled up by 100.
func NewDepositResolver
Actionfunc NewDeposits
ActionNewDeposits creates a new Deposits instance.
func NewExternalIncentiveResolver
ActionNewExternalIncentive creates a new external incentive
func NewExternalIncentives
ActionNewExternalIncentives creates a new ExternalIncentives instance.
func NewIncentivesResolver
Actionfunc NewPoolResolver
ActionNewPool creates a new pool with the given poolPath and currentHeight.
func NewPoolTier
Action1func NewPoolTier(pools *Pools, currentTime int64, initialPoolPath string, getEmission func() int64, getHalvingBlocksInRange func(start, end int64) ([]int64, []int64)) *PoolTierNewPoolTier creates a new PoolTier instance with single initial 1 tier pool.
Parameters: - pools: The pool collection. - currentTime: The current block time. - initialPoolPath: The path of the initial pool. - getEmission: A function that returns the current emission to the staker contract. - getHalvingBlocksInRange: A function that returns a list of halving blocks within the interval [start, end) in ascending order.
Returns: - *PoolTier: The new PoolTier instance.
func NewPoolTierBy
Actionfunc NewPools
Actionfunc NewTickResolver
Actionfunc NewStakerV1
Actionfunc NewTickCrossEventInfo
Action12
type CalcPositionRewardParam
structCalcPositionRewardParam is a struct for calculating position reward
type DepositResolver
structMethods on DepositResolver
func CollectedExternalReward
method on DepositResolverfunc ExternalRewardLastCollectTime
method on DepositResolverExternalRewardLastCollectTime returns the last collect time for the external reward for the given incentive ID. If the last collect time is 0, it returns the staked time.
func FindWarmup
method on DepositResolverfunc GetWarmup
method on DepositResolverfunc InternalRewardLastCollectTime
method on DepositResolverInternalRewardLastCollectTime returns the last collect time for the internal reward. If the last collect time is 0, it returns the staked time.
type Deposits
structDeposits manages all staked positions.
Methods on Deposits
func Has
method on DepositsHas checks if a position ID exists in deposits.
func Iterate
method on Deposits1func (self *Deposits) Iterate(start uint64, end uint64, fn func(positionId uint64, deposit *sr.Deposit) bool)Iterate traverses deposits within the specified range.
func IterateByPoolPath
method on Depositsfunc Size
method on DepositsSize returns the number of deposits.
type ExternalIncentiveResolver
structtype ExternalIncentives
structExternalIncentives manages external incentive programs.
type IncentivesResolver
structMethods on IncentivesResolver
func Get
method on IncentivesResolverGet incentive by incentiveId
func GetIncentiveResolver
method on IncentivesResolvertype PoolResolver
structMethods on PoolResolver
func CalculateRawRewardForPosition
method on PoolResolver1func (self *PoolResolver) CalculateRawRewardForPosition(currentTime int64, currentTick int32, deposit *sr.Deposit) *u256.UintCalculates reward for a position *without* considering debt or warmup It calculates the theoretical total reward for the position if it has been staked since the pool creation
func CurrentGlobalRewardRatioAccumulation
method on PoolResolver1func (self *PoolResolver) CurrentGlobalRewardRatioAccumulation(currentTime int64) (time int64, acc string)Get the latest global reward ratio accumulation in [0, currentTime] range. Returns the time and the accumulation.
func CurrentReward
method on PoolResolverGet the latest reward in [0, currentTime] range. Returns the reward.
func CurrentStakedLiquidity
method on PoolResolverfunc CurrentTick
method on PoolResolverGet the latest tick in [0, currentTime] range. Returns the tick.
func IncentivesResolver
method on PoolResolverfunc IsExternallyIncentivizedPool
method on PoolResolverIsExternallyIncentivizedPool returns true if the pool has any active external incentives.
func RewardStateOf
method on PoolResolverRewardStateOf initializes a new RewardState for the given deposit.
func TickResolver
method on PoolResolvertype PoolTier
struct 1type PoolTier struct {
2 membership *bptree.BPTree // poolPath -> tier(1, 2, 3)
3
4 tierRatio sr.TierRatio
5
6 counts [AllTierCount]uint64
7
8 lastRewardCacheTimestamp int64
9
10 currentEmission int64
11
12 // returns current emission.
13 getEmission func() int64
14 // Returns a list of halving timestamps and their emission amounts within the interval [start, end) in ascending order.
15 // The first return value is a list of timestamps where halving occurs.
16 // The second return value is a list of emission amounts corresponding to each halving timestamp.
17 getHalvingBlocksInRange func(start, end int64) ([]int64, []int64)
18}PoolTier manages pool counts, ratios, and rewards for different tiers.
Fields: - membership: Tracks which tier a pool belongs to (poolPath -> blockNumber -> tier).
Methods: - CurrentCount: Returns the current count of pools in a tier at a specific timestamp. - CurrentRatio: Returns the current ratio for a tier at a specific timestamp. - CurrentTier: Returns the tier of a specific pool at a given timestamp. - CurrentReward: Retrieves the reward for a tier at a specific timestamp. - changeTier: Updates the tier of a pool and recalculates ratios.
Methods on PoolTier
func CurrentAllTierCounts
method on PoolTierCurrentAllTierCounts returns the current count of pools in each tier.
func CurrentCount
method on PoolTierCurrentCount returns the current count of pools in the given tier.
func CurrentReward
method on PoolTierCurrentReward returns the current per-pool reward for the given tier.
func CurrentRewardPerPool
method on PoolTierfunc CurrentTier
method on PoolTierCurrentTier returns the tier of the given pool.
func IsInternallyIncentivizedPool
method on PoolTierIsInternallyIncentivizedPool returns true if the pool is in a tier.
type Pools
structPools represents the global pool storage
Methods on Pools
func Get
method on PoolsGet returns the pool for the given poolPath
func GetPoolOrNil
method on PoolsGetPoolOrNil returns the pool for the given poolPath, or returns nil if it does not exist
func Has
method on PoolsHas returns true if the pool exists for the given poolPath
func IterateAll
method on Poolstype Reward
structReward is a struct for storing reward for a position. Internal reward is the GNS reward, external reward is the reward for other incentives. Penalties are the amount that is deducted from the reward due to the position's warmup.
type RewardState
structRewardState is a struct for storing the intermediate state for reward calculation.
type TickResolver
structMethods on TickResolver
func CurrentOutsideAccumulation
method on TickResolverCurrentOutsideAccumulation returns the latest outside accumulation for the tick
25
- chain stdlib
- chain/runtime stdlib
- errors stdlib
- gno.land/p/gnoswap/deps/grc721 package
- gno.land/p/gnoswap/gnsmath package
- gno.land/p/gnoswap/int256 package
- gno.land/p/gnoswap/rbac package
- gno.land/p/gnoswap/uint256 package
- gno.land/p/gnoswap/utils package
- gno.land/p/nt/bptree/v0 package
- gno.land/p/nt/ufmt/v0 package
- gno.land/r/gnoswap/access realm
- gno.land/r/gnoswap/common realm
- gno.land/r/gnoswap/emission realm
- gno.land/r/gnoswap/gns realm
- gno.land/r/gnoswap/halt realm
- gno.land/r/gnoswap/position realm
- gno.land/r/gnoswap/protocol_fee realm
- gno.land/r/gnoswap/rbac realm
- gno.land/r/gnoswap/referral realm
- gno.land/r/gnoswap/staker realm
- math stdlib
- strconv stdlib
- strings stdlib
- time stdlib