PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/r/gnoswap/staker/v1

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
v1
Namespace
gnoswap / staker
Files
28 (README)(gnomod.toml)
Exported functions
14
Module
gno.land/r/gnoswap/staker/v1
gno
0.9

Files (28)

  • README.mdmarkdown
  • gnomod.tomltoml
  • assert.gnogno
  • calculate_pool_position_reward.gnogno
  • consts.gnogno
  • doc.gnogno
  • emits.gnogno
  • errors.gnogno
  • event_info.gnogno
  • external_deposit_fee.gnogno
  • external_incentive.gnogno
  • external_token_list.gnogno
  • getter_utils.gnogno
  • getter.gnogno
  • init.gnogno
  • instance.gnogno
  • manage_pool_tier_and_warmup.gnogno
  • protocol_fee_unstaking.gnogno
  • render.gnogno
  • reward_calculation_incentives.gnogno
  • reward_calculation_pool_tier.gnogno
  • reward_calculation_pool.gnogno
  • reward_calculation_tick.gnogno
  • reward_calculation_warmup.gnogno
  • staker.gnogno
  • type.gnogno
  • unstaked_position.gnogno
  • utils.gnogno
  • unstaked_position.gnogno
    1package staker23import (4	"chain"5	"chain/runtime"6	"time"78

    Functions

    • NewDepositResolver(deposit *gno.land/r/gnoswap/staker.Deposit) *gno.land/r/gnoswap/staker/v1.DepositResolver

    • NewDeposits() *gno.land/r/gnoswap/staker/v1.Deposits

    • NewExternalIncentiveResolver(externalIncentive *gno.land/r/gnoswap/staker.ExternalIncentive) *gno.land/r/gnoswap/staker/v1.ExternalIncentiveResolver

    • NewExternalIncentives() *gno.land/r/gnoswap/staker/v1.ExternalIncentives

    • NewIncentivesResolver(incentives *gno.land/r/gnoswap/staker.Incentives) *gno.land/r/gnoswap/staker/v1.IncentivesResolver

    • NewPoolResolver(pool *gno.land/r/gnoswap/staker.Pool) *gno.land/r/gnoswap/staker/v1.PoolResolver

    • NewPools() *gno.land/r/gnoswap/staker/v1.Pools

    • NewPoolTier(pools *gno.land/r/gnoswap/staker/v1.Pools, currentTime int64, initialPoolPath string, getEmission func() (int64, .uverse.error), getHalvingBlocksInRange func(int64, int64) ([]int64, []int64, .uverse.error)) *gno.land/r/gnoswap/staker/v1.PoolTier

    • NewPoolTierBy(membership *gno.land/p/nt/bptree/v0.BPTree, tierRatio struct{Tier1 uint64; Tier2 uint64; Tier3 uint64}, counts [4]uint64, lastRewardCacheTimestamp int64, currentEmission int64, getEmission func() (int64, .uverse.error), getHalvingBlocksInRange func(int64, int64) ([]int64, []int64, .uverse.error)) *gno.land/r/gnoswap/staker/v1.PoolTier

    • NewStakerV1(stakerStore interface {AddAllowedToken func(int, .uverse.realm, string) .uverse.error; AddDeniedRewardToken func(int, .uverse.realm, string) .uverse.error; GetAllowedTokens func() []string; GetCurrentSwapBatch func() *gno.land/r/gnoswap/staker.SwapBatchProcessor; GetDeniedRewardTokens func() []string; GetDepositGnsAmount func() int64; GetDeposits func() *gno.land/p/nt/bptree/v0.BPTree; GetExternalIncentives func() *gno.land/p/nt/bptree/v0.BPTree; GetIncentiveCounter func() *gno.land/r/gnoswap/staker.Counter; GetMinimumRewardAmount func() int64; GetPendingProtocolFee func(string) int64; GetPendingProtocolFees func() map[string]int64; GetPoolTierCounts func() [4]uint64; GetPoolTierCurrentEmission func() int64; GetPoolTierGetEmission func() func() (int64, .uverse.error); GetPoolTierGetHalvingBlocksInRange func() func(int64, int64) ([]int64, []int64, .uverse.error); GetPoolTierLastRewardCacheTimestamp func() int64; GetPoolTierMemberships func() *gno.land/p/nt/bptree/v0.BPTree; GetPoolTierRatio func() gno.land/r/gnoswap/staker.TierRatio; GetPools func() *gno.land/p/nt/bptree/v0.BPTree; GetTokenSpecificMinimumRewards func() map[string]int64; GetTotalEmissionSent func() int64; GetUncollectedIncentiveCounts func() *gno.land/p/nt/bptree/v0.BPTree; GetUnstakedPositions func() *gno.land/p/nt/bptree/v0.BPTree; GetUnstakingFee func() uint64; GetWarmupTemplate func() []gno.land/r/gnoswap/staker.Warmup; HasAllowedTokensStoreKey func() bool; HasCurrentSwapBatchStoreKey func() bool; HasDeniedRewardTokensStoreKey func() bool; HasDepositGnsAmountStoreKey func() bool; HasDepositsStoreKey func() bool; HasExternalIncentivesStoreKey func() bool; HasIncentiveCounterStoreKey func() bool; HasMinimumRewardAmountStoreKey func() bool; HasPendingProtocolFeesStoreKey func() bool; HasPoolTierCountsStoreKey func() bool; HasPoolTierCurrentEmissionStoreKey func() bool; HasPoolTierGetEmissionStoreKey func() bool; HasPoolTierGetHalvingBlocksInRangeStoreKey func() bool; HasPoolTierLastRewardCacheTimestampStoreKey func() bool; HasPoolTierMembershipsStoreKey func() bool; HasPoolTierRatioStoreKey func() bool; HasPoolsStoreKey func() bool; HasTokenSpecificMinimumRewardsStoreKey func() bool; HasTotalEmissionSentStoreKey func() bool; HasUncollectedIncentiveCountsStoreKey func() bool; HasUnstakedPositionsStoreKey func() bool; HasUnstakingFeeStoreKey func() bool; HasWarmupTemplateStoreKey func() bool; NextIncentiveID func(.uverse.address, int64) string; RemoveAllowedToken func(int, .uverse.realm, string) .uverse.error; RemoveDeniedRewardToken func(int, .uverse.realm, string) .uverse.error; RemovePendingProtocolFee func(int, .uverse.realm, string) .uverse.error; RemoveTokenSpecificMinimumRewardItem func(int, .uverse.realm, string) .uverse.error; SetAllowedTokens func(int, .uverse.realm, []string) .uverse.error; SetCurrentSwapBatch func(int, .uverse.realm, *gno.land/r/gnoswap/staker.SwapBatchProcessor) .uverse.error; SetDepositGnsAmount func(int, .uverse.realm, int64) .uverse.error; SetDeposits func(int, .uverse.realm, *gno.land/p/nt/bptree/v0.BPTree) .uverse.error; SetExternalIncentives func(int, .uverse.realm, *gno.land/p/nt/bptree/v0.BPTree) .uverse.error; SetIncentiveCounter func(int, .uverse.realm, *gno.land/r/gnoswap/staker.Counter) .uverse.error; SetMinimumRewardAmount func(int, .uverse.realm, int64) .uverse.error; SetPendingProtocolFee func(int, .uverse.realm, string, int64) .uverse.error; SetPendingProtocolFees func(int, .uverse.realm, map[string]int64) .uverse.error; SetPoolTierCounts func(int, .uverse.realm, [4]uint64) .uverse.error; SetPoolTierCurrentEmission func(int, .uverse.realm, int64) .uverse.error; SetPoolTierGetEmission func(int, .uverse.realm, func() (int64, .uverse.error)) .uverse.error; SetPoolTierGetHalvingBlocksInRange func(int, .uverse.realm, func(int64, int64) ([]int64, []int64, .uverse.error)) .uverse.error; SetPoolTierLastRewardCacheTimestamp func(int, .uverse.realm, int64) .uverse.error; SetPoolTierMemberships func(int, .uverse.realm, *gno.land/p/nt/bptree/v0.BPTree) .uverse.error; SetPoolTierRatio func(int, .uverse.realm, gno.land/r/gnoswap/staker.TierRatio) .uverse.error; SetPools func(int, .uverse.realm, *gno.land/p/nt/bptree/v0.BPTree) .uverse.error; SetTokenSpecificMinimumRewardItem func(int, .uverse.realm, string, int64) .uverse.error; SetTokenSpecificMinimumRewards func(int, .uverse.realm, map[string]int64) .uverse.error; SetTotalEmissionSent func(int, .uverse.realm, int64) .uverse.error; SetUncollectedIncentiveCounts func(int, .uverse.realm, *gno.land/p/nt/bptree/v0.BPTree) .uverse.error; SetUnstakedPositions func(int, .uverse.realm, *gno.land/p/nt/bptree/v0.BPTree) .uverse.error; SetUnstakingFee func(int, .uverse.realm, uint64) .uverse.error; SetWarmupTemplate func(int, .uverse.realm, []gno.land/r/gnoswap/staker.Warmup) .uverse.error}, poolAccessor interface {ExistsPoolPath func(string) bool; GetSlot0SqrtPriceX96 func(string) string; GetSlot0Tick func(string) int32; SetSwapEndHook func(int, .uverse.realm, func(int, .uverse.realm, string) .uverse.error); SetSwapStartHook func(int, .uverse.realm, func(int, .uverse.realm, string, int64)); SetTickCrossHook func(int, .uverse.realm, func(int, .uverse.realm, string, int32, bool, int64))}, emissionAccessor interface {GetStakerEmissionAmountPerSecond func() (int64, .uverse.error); GetStakerEmissionAmountPerSecondInRange func(int64, int64) ([]int64, []int64, .uverse.error); MintAndDistributeGns func(int, .uverse.realm) (int64, bool); SetOnDistributionPctChangeCallback func(int, .uverse.realm, func(int, .uverse.realm, int64))}, nftAccessor interface {Approve func(int, .uverse.realm, .uverse.address, gno.land/p/nt/grc721/v0.TokenID) .uverse.error; Burn func(int, .uverse.realm, gno.land/p/nt/grc721/v0.TokenID); Exists func(gno.land/p/nt/grc721/v0.TokenID) bool; Mint func(int, .uverse.realm, .uverse.address, gno.land/p/nt/grc721/v0.TokenID) gno.land/p/nt/grc721/v0.TokenID; MustOwnerOf func(gno.land/p/nt/grc721/v0.TokenID) .uverse.address; OwnerOf func(gno.land/p/nt/grc721/v0.TokenID) (.uverse.address, .uverse.error); TotalSupply func() int64; TransferFrom func(int, .uverse.realm, .uverse.address, .uverse.address, gno.land/p/nt/grc721/v0.TokenID) .uverse.error})

    • NewTickCrossEventInfo(tickID int32, stakedLiquidityGross *gno.land/p/gnoswap/uint256/v1.Uint, stakedLiquidityDelta *gno.land/p/gnoswap/int256/v1.Int, outsideAccumulation *gno.land/p/gnoswap/uint256/v1.Uint) *gno.land/r/gnoswap/staker/v1.tickCrossEventInfo

    • NewTickResolver(tick *gno.land/r/gnoswap/staker.Tick) *gno.land/r/gnoswap/staker/v1.TickResolver

    • NewUnstakedPositions() *gno.land/r/gnoswap/staker/v1.UnstakedPositions

    • TierRatioFromCounts(tier1Count uint64, tier2Count uint64, tier3Count uint64) struct{Tier1 uint64; Tier2 uint64; Tier3 uint64}

    Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

    Rendered

    RenderedRawgnoweb ↗
    This realm does not provide renderable output (vm/qrender → NoRenderDeclError). View on gnoweb ↗

    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.

    bptree "gno.land/p/nt/bptree/v0"
    9 ufmt "gno.land/p/nt/ufmt/v0"
    10
    11 "gno.land/p/gnoswap/gnsmath/v1"
    12 "gno.land/p/gnoswap/utils/v1"
    13
    14 sr "gno.land/r/gnoswap/staker"
    15)
    16
    17// UnstakedPositions manages exit checkpoints.
    18type UnstakedPositions struct {
    19 tree *bptree.BPTree
    20}
    21
    22// NewUnstakedPositions creates a new UnstakedPositions instance.
    23//
    24// Returns:
    25// - *UnstakedPositions: Empty exit-checkpoint manager backed by a new B+ tree.
    26func NewUnstakedPositions() *UnstakedPositions {
    27 return &UnstakedPositions{
    28 tree: sr.NewBPTreeN(16), // positionId -> *UnstakedPosition
    29 }
    30}
    31
    32// Has checks if a position ID has an exit checkpoint.
    33//
    34// Parameters:
    35// - positionId: Position ID whose exit-checkpoint membership is checked.
    36//
    37// Returns:
    38// - bool: true when an exit checkpoint exists for positionId; false otherwise.
    39func (self *UnstakedPositions) Has(positionId uint64) bool {
    40 return self.tree.Has(utils.EncodeUint64(positionId))
    41}
    42
    43// get retrieves an exit checkpoint by position ID, or nil when there is none.
    44func (self *UnstakedPositions) get(positionId uint64) *sr.UnstakedPosition {
    45 value := self.tree.Get(utils.EncodeUint64(positionId))
    46 if value == nil {
    47 return nil
    48 }
    49
    50 position, ok := value.(*sr.UnstakedPosition)
    51 if !ok {
    52 panic(ufmt.Sprintf("failed to cast value to *UnstakedPosition: %T", value))
    53 }
    54
    55 return position
    56}
    57
    58// set stores an exit checkpoint for a position ID.
    59func (self *UnstakedPositions) set(positionId uint64, position *sr.UnstakedPosition) {
    60 self.tree.Set(utils.EncodeUint64(positionId), position)
    61}
    62
    63// remove deletes an exit checkpoint by position ID.
    64func (self *UnstakedPositions) remove(positionId uint64) {
    65 self.tree.Remove(utils.EncodeUint64(positionId))
    66}
    67
    68// getUnstakedPositions returns the exit checkpoints backed by the store.
    69func (s *stakerV1) getUnstakedPositions() *UnstakedPositions {
    70 return &UnstakedPositions{tree: s.store.GetUnstakedPositions()}
    71}
    72
    73// uncollectedIncentiveCountOf returns how many checkpoints still owe the incentive.
    74//
    75// The count is per incentive, not per pool: one checkpoint that can never be funded would
    76// otherwise lock the refunds of every other incentive in the same pool.
    77func (s *stakerV1) uncollectedIncentiveCountOf(incentiveId string) int64 {
    78 value := s.store.GetUncollectedIncentiveCounts().Get(incentiveId)
    79 if value == nil {
    80 return 0
    81 }
    82
    83 count, ok := value.(int64)
    84 if !ok {
    85 panic(ufmt.Sprintf("failed to cast uncollected incentive count to int64: %T", value))
    86 }
    87
    88 return count
    89}
    90
    91// addUncollectedIncentiveCount moves the incentive's count by delta, dropping the entry at zero.
    92func (s *stakerV1) addUncollectedIncentiveCount(incentiveId string, delta int64) {
    93 addUncollectedIncentiveCountTo(s.store.GetUncollectedIncentiveCounts(), incentiveId, delta)
    94}
    95
    96func addUncollectedIncentiveCountTo(counts *bptree.BPTree, incentiveId string, delta int64) {
    97 count := int64(0)
    98 if value := counts.Get(incentiveId); value != nil {
    99 casted, ok := value.(int64)
    100 if !ok {
    101 panic(ufmt.Sprintf("failed to cast uncollected incentive count to int64: %T", value))
    102 }
    103 count = casted
    104 }
    105
    106 next := gnsmath.SafeAddInt64(count, delta)
    107 if next < 0 {
    108 panic(makeErrorWithDetails(
    109 errCalculationError,
    110 ufmt.Sprintf("uncollected count of incentive(%s) went negative", incentiveId),
    111 ))
    112 }
    113
    114 if next == 0 {
    115 counts.Remove(incentiveId)
    116 return
    117 }
    118
    119 counts.Set(incentiveId, next)
    120}
    121
    122// recordUnstakedPosition writes the exit checkpoint before the teardown touches the pool.
    123// The deposit's incentive index is brought up to date first, so the checkpoint owes exactly
    124// the incentives the position accrued from.
    125func (s *stakerV1) recordUnstakedPosition(_ int, rlm realm, positionId uint64, deposit *sr.Deposit, exitTime int64) *sr.UnstakedPosition {
    126 poolPath := deposit.TargetPoolPath()
    127
    128 pool, ok := s.getPools().Get(poolPath)
    129 if !ok {
    130 panic(makeErrorWithDetails(
    131 errDataNotFound,
    132 ufmt.Sprintf("pool(%s) does not exist", poolPath),
    133 ))
    134 }
    135
    136 poolResolver := NewPoolResolver(pool)
    137 depositResolver := NewDepositResolver(deposit)
    138
    139 lastUpdatedAt := depositResolver.LastExternalIncentiveUpdatedAt()
    140 if lastUpdatedAt < exitTime {
    141 poolResolver.IncentivesResolver().IterateIncentiveIdsByTime(lastUpdatedAt, exitTime, func(incentiveId string) bool {
    142 deposit.AddExternalIncentiveId(incentiveId)
    143 return false
    144 })
    145 deposit.SetLastExternalIncentiveUpdatedAt(exitTime)
    146 }
    147
    148 tier, tierRatio, tierCount, err := s.getPoolTier().tierContextOf(poolPath)
    149 if err != nil {
    150 panic(err)
    151 }
    152
    153 lowerTick := poolResolver.GetOrNewTick(deposit.TickLower())
    154 upperTick := poolResolver.GetOrNewTick(deposit.TickUpper())
    155 incentiveIds := deposit.GetExternalIncentiveIdList()
    156
    157 position := sr.NewUnstakedPosition(
    158 deposit,
    159 exitTime,
    160 poolResolver.CurrentTick(exitTime),
    161 lowerTick,
    162 upperTick,
    163 NewTickResolver(lowerTick).CurrentOutsideAccumulation(exitTime).ToString(),
    164 NewTickResolver(upperTick).CurrentOutsideAccumulation(exitTime).ToString(),
    165 tier,
    166 tierRatio,
    167 tierCount,
    168 s.GetUnstakingFee(),
    169 incentiveIds,
    170 )
    171
    172 s.getUnstakedPositions().set(positionId, position)
    173
    174 counts := s.store.GetUncollectedIncentiveCounts()
    175 for _, incentiveId := range incentiveIds {
    176 addUncollectedIncentiveCountTo(counts, incentiveId, 1)
    177 }
    178
    179 return position
    180}
    181
    182// dropUnstakedPositionIfCollected removes the checkpoint once every reward source is collected.
    183func (s *stakerV1) dropUnstakedPositionIfCollected(_ int, rlm realm, target *collectTarget) {
    184 if !target.checkpoint.FullyCollected() {
    185 return
    186 }
    187
    188 s.getUnstakedPositions().remove(target.positionId)
    189
    190 previousRealm := rlm.Previous()
    191 chain.Emit(
    192 "ClearUnstakedPosition",
    193 "prevAddr", previousRealm.Address().String(),
    194 "prevRealm", previousRealm.PkgPath(),
    195 "positionId", utils.FormatUint(target.positionId),
    196 "poolPath", target.deposit.TargetPoolPath(),
    197 "exitTime", utils.FormatInt(target.checkpoint.ExitTime()),
    198 "currentTime", utils.FormatInt(time.Now().Unix()),
    199 "currentHeight", utils.FormatInt(runtime.ChainHeight()),
    200 )
    201}
    202
    203// HasUnstakedPosition reports whether a position is staked no longer but still has uncollected rewards.
    204//
    205// Parameters:
    206// - positionId: Position ID whose exit-checkpoint membership is checked.
    207//
    208// Returns:
    209// - bool: true when positionId has an exit checkpoint; false otherwise.
    210func (s *stakerV1) HasUnstakedPosition(positionId uint64) bool {
    211 return s.getUnstakedPositions().Has(positionId)
    212}
    213
    214// GetUnstakedPositionExitTime returns when an unstaked position stopped accruing rewards.
    215//
    216// Parameters:
    217// - positionId: Position ID whose exit checkpoint is queried.
    218//
    219// Returns:
    220// - int64: Exit timestamp in Unix seconds.
    221// - error: Non-nil when positionId has no uncollected exit checkpoint; nil on success.
    222func (s *stakerV1) GetUnstakedPositionExitTime(positionId uint64) (int64, error) {
    223 position := s.getUnstakedPositions().get(positionId)
    224 if position == nil {
    225 return 0, ufmt.Errorf("%v: positionId(%d) has no uncollected reward", errDataNotFound, positionId)
    226 }
    227
    228 return position.ExitTime(), nil
    229}
    230
    231// GetUnstakedPositionPendingIncentives returns the incentives an unstaked position has yet to
    232// collect.
    233//
    234// Parameters:
    235// - positionId: Position ID whose pending incentive IDs are queried.
    236//
    237// Returns:
    238// - []string: External incentive IDs with rewards still pending for the checkpoint.
    239// - error: Non-nil when positionId has no uncollected exit checkpoint; nil on success.
    240func (s *stakerV1) GetUnstakedPositionPendingIncentives(positionId uint64) ([]string, error) {
    241 position := s.getUnstakedPositions().get(positionId)
    242 if position == nil {
    243 return nil, ufmt.Errorf("%v: positionId(%d) has no uncollected reward", errDataNotFound, positionId)
    244 }
    245
    246 return position.PendingIncentiveIdList(), nil
    247}
    248
    249// GetUncollectedIncentiveCount returns how many unstaked positions still owe a reward from the
    250// incentive; EndExternalIncentive is refused while it is non-zero.
    251//
    252// Parameters:
    253// - incentiveId: External incentive identifier whose outstanding checkpoint count is queried.
    254//
    255// Returns:
    256// - int64: Number of exit checkpoints still owing incentiveId; zero permits incentive finalization.
    257func (s *stakerV1) GetUncollectedIncentiveCount(incentiveId string) int64 {
    258 return s.uncollectedIncentiveCountOf(incentiveId)
    259}
    260
    *gno.land/r/gnoswap/staker/v1.stakerV1