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/gov/staker/v1

Realm
Open in gnoweb ↗

Overview

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

Files (25)

  • README.mdmarkdown
  • gnomod.tomltoml
  • assert.gnogno
  • consts.gnogno
  • delegation_manager.gnogno
  • delegation_withdraw.gnogno
  • delegation.gnogno
  • doc.gnogno
  • emission_reward_manager.gnogno
  • emission_reward_state.gnogno
  • emits.gnogno
  • errors.gnogno
  • getter_utils.gnogno
  • getter.gnogno
  • init.gnogno
  • instance.gnogno
  • launchpad_project_deposits.gnogno
  • protocol_fee_reward_manager.gnogno
  • protocol_fee_reward_state.gnogno
  • render.gnogno
  • staker_delegate.gnogno
  • staker_delegation_snapshot.gnogno
  • staker_reward.gnogno
  • state.gnogno
  • util.gnogno
  • protocol_fee_reward_state.gnogno
    1package staker23import (4	"errors"56	"gno.land/p/gnoswap/consts/v1"7	"gno.land/p/gnoswap/gnsmath/v1"8

    Functions

    • NewDelegation(id int64, delegateFrom string, delegateTo string, delegateAmount int64, createdHeight int64, createdAt int64) *gno.land/r/gnoswap/gov/staker.Delegation

    • NewDelegationManagerResolver(delegationManager *gno.land/r/gnoswap/gov/staker.DelegationManager) *gno.land/r/gnoswap/gov/staker/v1.DelegationManagerResolver

    • NewDelegationResolver(delegation *gno.land/r/gnoswap/gov/staker.Delegation) *gno.land/r/gnoswap/gov/staker/v1.DelegationResolver

    • NewDelegationWithdraw(delegationID int64, unDelegateAmount int64, createdHeight int64, createdAt int64, unDelegationLockupPeriod int64) struct{delegationID int64; unDelegateAmount int64; unDelegatedHeight int64; unDelegatedAt int64; collectedAmount int64; collectableTime int64; collectedAt int64; collected bool}

    • NewDelegationWithdrawResolver(withdraw *gno.land/r/gnoswap/gov/staker.DelegationWithdraw) *gno.land/r/gnoswap/gov/staker/v1.DelegationWithdrawResolver

    • NewDelegationWithdrawWithoutLockup(delegationID int64, unDelegateAmount int64, createdHeight int64, createdAt int64) struct{delegationID int64; unDelegateAmount int64; unDelegatedHeight int64; unDelegatedAt int64; collectedAmount int64; collectableTime int64; collectedAt int64; collected bool}

    • NewEmissionRewardManagerResolver(emissionRewardManager *gno.land/r/gnoswap/gov/staker.EmissionRewardManager) *gno.land/r/gnoswap/gov/staker/v1.EmissionRewardManagerResolver

    • NewEmissionRewardStateResolver(emissionRewardState *gno.land/r/gnoswap/gov/staker.EmissionRewardState) *gno.land/r/gnoswap/gov/staker/v1.EmissionRewardStateResolver

    • NewGovStakerV1(store interface {GetAllDelegations func() *gno.land/p/nt/bptree/v0.BPTree; GetDelegation func(int64) (*gno.land/r/gnoswap/gov/staker.Delegation, bool); GetDelegationCounter func() *gno.land/r/gnoswap/gov/staker.Counter; GetDelegationManager func() *gno.land/r/gnoswap/gov/staker.DelegationManager; GetEmissionRewardManager func() *gno.land/r/gnoswap/gov/staker.EmissionRewardManager; GetLaunchpadProjectDeposits func() *gno.land/r/gnoswap/gov/staker.LaunchpadProjectDeposits; GetProtocolFeeRewardManager func() *gno.land/r/gnoswap/gov/staker.ProtocolFeeRewardManager; GetTotalDelegatedAmount func() int64; GetTotalDelegationHistory func() *gno.land/r/gnoswap/gov/staker.UintTree; GetTotalLockedAmount func() int64; GetUnDelegationLockupPeriod func() int64; GetUserDelegationHistory func() *gno.land/p/nt/bptree/v0.BPTree; HasDelegation func(int64) bool; HasDelegationCounterStoreKey func() bool; HasDelegationManagerStoreKey func() bool; HasDelegationsStoreKey func() bool; HasEmissionRewardManagerStoreKey func() bool; HasLaunchpadProjectDepositsStoreKey func() bool; HasProtocolFeeRewardManagerStoreKey func() bool; HasTotalDelegatedAmountStoreKey func() bool; HasTotalDelegationHistoryStoreKey func() bool; HasTotalLockedAmountStoreKey func() bool; HasUnDelegationLockupPeriodStoreKey func() bool; HasUserDelegationHistoryStoreKey func() bool; RemoveDelegation func(int, .uverse.realm, int64) .uverse.error; SetDelegation func(int, .uverse.realm, int64, *gno.land/r/gnoswap/gov/staker.Delegation) .uverse.error; SetDelegationCounter func(int, .uverse.realm, *gno.land/r/gnoswap/gov/staker.Counter) .uverse.error; SetDelegationManager func(int, .uverse.realm, *gno.land/r/gnoswap/gov/staker.DelegationManager) .uverse.error; SetDelegations func(int, .uverse.realm, *gno.land/p/nt/bptree/v0.BPTree) .uverse.error; SetEmissionRewardManager func(int, .uverse.realm, *gno.land/r/gnoswap/gov/staker.EmissionRewardManager) .uverse.error; SetLaunchpadProjectDeposits func(int, .uverse.realm, *gno.land/r/gnoswap/gov/staker.LaunchpadProjectDeposits) .uverse.error; SetProtocolFeeRewardManager func(int, .uverse.realm, *gno.land/r/gnoswap/gov/staker.ProtocolFeeRewardManager) .uverse.error; SetTotalDelegatedAmount func(int, .uverse.realm, int64) .uverse.error; SetTotalDelegationHistory func(int, .uverse.realm, *gno.land/r/gnoswap/gov/staker.UintTree) .uverse.error; SetTotalLockedAmount func(int, .uverse.realm, int64) .uverse.error; SetUnDelegationLockupPeriod func(int, .uverse.realm, int64) .uverse.error; SetUserDelegationHistory func(int, .uverse.realm, *gno.land/p/nt/bptree/v0.BPTree) .uverse.error}) interface {CleanStakerDelegationSnapshotByAdmin func(int, .uverse.realm, int64, .uverse.address); CollectEmissionReward func(int, .uverse.realm); CollectEmissionRewardFromLaunchPad func(int, .uverse.realm, .uverse.address); CollectProtocolFeeReward func(int, .uverse.realm, string); CollectProtocolFeeRewardFromLaunchPad func(int, .uverse.realm, .uverse.address, string); CollectReward func(int, .uverse.realm); CollectRewardFromLaunchPad func(int, .uverse.realm, .uverse.address); CollectUndelegatedGns func(int, .uverse.realm) int64; Delegate func(int, .uverse.realm, .uverse.address, int64, string) int64; ExistsDelegation func(int64) bool; GetClaimableRewardByAddress func(.uverse.address) (int64, map[string]int64, .uverse.error); GetClaimableRewardByLaunchpad func(.uverse.address) (int64, map[string]int64, .uverse.error); GetClaimableRewardByRewardID func(string) (int64, map[string]int64, .uverse.error); GetCollectableWithdrawAmount func(int64) int64; GetDelegationWithdrawCount func(int64) int; GetDelegationWithdraws func(int64, int, int) ([]gno.land/r/gnoswap/gov/staker.DelegationWithdraw, .uverse.error); GetDelegations func() *gno.land/p/nt/bptree/rotree/v0.ReadOnlyTree; GetDelegatorDelegations func(.uverse.address) *gno.land/p/nt/bptree/rotree/v0.ReadOnlyTree; GetEmissionAccumulatedTimestamp func() int64; GetEmissionAccumulatedX128PerStake func() *gno.land/p/gnoswap/uint256/v1.Uint; GetEmissionDistributedAmount func() int64; GetLaunchpadProjectDeposit func(string) (int64, bool); GetProtocolFeeAccumulatedTimestamp func() int64; GetProtocolFeeAccumulatedX128PerStake func(string) *gno.land/p/gnoswap/uint256/v1.Uint; GetProtocolFeeAmount func(string) int64; GetTotalDelegated func() int64; GetTotalDelegationAmountAtSnapshot func(int64) (int64, bool); GetTotalLockedAmount func() int64; GetTotalxGnsSupply func() int64; GetUnDelegationLockupPeriod func() int64; GetUserDelegationAmountAtSnapshot func(.uverse.address, int64) (int64, bool); GetUserDelegationIDs func(.uverse.address, .uverse.address) []int64; HasDelegationSnapshotsKey func() bool; Redelegate func(int, .uverse.realm, .uverse.address, .uverse.address, int64) int64; Render func(string) string; SetAmountByProjectWallet func(int, .uverse.realm, .uverse.address, int64, bool); SetUnDelegationLockupPeriodByAdmin func(int, .uverse.realm, int64); Undelegate func(int, .uverse.realm, .uverse.address, int64) int64}

    • NewLaunchpadProjectDepositsResolver(launchpadProjectDeposits *gno.land/r/gnoswap/gov/staker.LaunchpadProjectDeposits) *gno.land/r/gnoswap/gov/staker/v1.LaunchpadProjectDepositsResolver

    • NewProtocolFeeRewardManagerResolver(manager *gno.land/r/gnoswap/gov/staker.ProtocolFeeRewardManager) *gno.land/r/gnoswap/gov/staker/v1.ProtocolFeeRewardManagerResolver

    • NewProtocolFeeRewardStateResolver(protocolFeeRewardState *gno.land/r/gnoswap/gov/staker.ProtocolFeeRewardState) *gno.land/r/gnoswap/gov/staker/v1.ProtocolFeeRewardStateResolver

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

    Rendered

    RenderedRawgnoweb ↗

    Render unavailable

    rate limit exceeded — the render query is served by the Gnoland archive RPC.

    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.

    u256 "gno.land/p/gnoswap/uint256/v1"
    9
    10 "gno.land/r/gnoswap/gov/staker"
    11)
    12
    13// ProtocolFeeRewardStateResolver settles one staker's protocol fee rewards.
    14//
    15// A staker's reward for a token is the sum, over the segments between their stake
    16// events, of the stake held during the segment times the growth of the token's
    17// accumulated fee per stake across it. Segments are folded in event order, so the work
    18// of settling a token is proportional to the staker's own stake changes since the token
    19// was last settled, never to the number of tokens.
    20type ProtocolFeeRewardStateResolver struct {
    21 *staker.ProtocolFeeRewardState
    22}
    23
    24// NewProtocolFeeRewardStateResolver wraps one staker's protocol fee reward state
    25// with settlement operations.
    26//
    27// Parameters:
    28// - protocolFeeRewardState: staker reward state to resolve and mutate.
    29//
    30// Returns:
    31// - *ProtocolFeeRewardStateResolver: resolver backed by protocolFeeRewardState.
    32func NewProtocolFeeRewardStateResolver(protocolFeeRewardState *staker.ProtocolFeeRewardState) *ProtocolFeeRewardStateResolver {
    33 return &ProtocolFeeRewardStateResolver{
    34 ProtocolFeeRewardState: protocolFeeRewardState,
    35 }
    36}
    37
    38// protocolFeeAccumulatorView reads a token accumulator as it stands, optionally
    39// extended in memory with buckets that are still pending on the protocol fee realm.
    40// The extension lets a query report what a collect would pay without folding anything.
    41type protocolFeeAccumulatorView struct {
    42 accumulator *staker.ProtocolFeeTokenAccumulator // nil when the token was never folded
    43 // extraEpochs and extraValues hold projected history entries, in ascending epoch order
    44 extraEpochs []int64
    45 extraValues []*u256.Uint
    46 // current is the latest accumulated value, projection included
    47 current *u256.Uint
    48 // firstEpoch is the first epoch a fee was folded for, projection included, or -1
    49 firstEpoch int64
    50 // foldedEpoch is the last epoch whose fees are known to be fully folded, or -1
    51 foldedEpoch int64
    52 // currentEpoch is the accrual epoch in force on the manager
    53 currentEpoch int64
    54}
    55
    56// at returns the accumulated value after the fees of the latest known epoch at or
    57// before epoch.
    58func (v *protocolFeeAccumulatorView) at(epoch int64) *u256.Uint {
    59 for i := len(v.extraEpochs) - 1; i >= 0; i-- {
    60 if v.extraEpochs[i] <= epoch {
    61 return v.extraValues[i]
    62 }
    63 }
    64
    65 if v.accumulator == nil {
    66 return u256.Zero()
    67 }
    68
    69 return v.accumulator.GetAccumulatedX128PerStakeAt(epoch)
    70}
    71
    72// protocolFeeTokenSettlement is the in-memory working copy of a token's settlement
    73// state. It is written back only on a collect, so queries never touch storage.
    74type protocolFeeTokenSettlement struct {
    75 eventCursor int64
    76 segmentStakedAmount int64
    77 segmentStartX128 *u256.Uint
    78 earnedX128 *u256.Uint
    79}
    80
    81// loadTokenSettlement returns the settlement state of tokenPath, initialising it when
    82// the token was never settled for this staker.
    83//
    84// A fresh state skips every stake event at or before the accumulator's first epoch:
    85// the accumulator was zero throughout, so those segments earned nothing and the open
    86// segment can start at the last of them. When no fee was folded at all, the skip
    87// covers every event, but only once every closed epoch is known to be folded: a
    88// bucket still pending from a closed epoch could later credit one of those events,
    89// so until then they are settled one by one through settleEvents, which is gated by
    90// foldedEpoch and yields nothing while the accumulator stays at zero.
    91func (p *ProtocolFeeRewardStateResolver) loadTokenSettlement(tokenPath string, view *protocolFeeAccumulatorView) *protocolFeeTokenSettlement {
    92 if tokenState, ok := p.GetTokenState(tokenPath); ok {
    93 return &protocolFeeTokenSettlement{
    94 eventCursor: tokenState.GetEventCursor(),
    95 segmentStakedAmount: tokenState.GetSegmentStakedAmount(),
    96 segmentStartX128: tokenState.GetSegmentStartX128().Clone(),
    97 earnedX128: tokenState.GetEarnedX128().Clone(),
    98 }
    99 }
    100
    101 settlement := &protocolFeeTokenSettlement{
    102 eventCursor: 0,
    103 segmentStakedAmount: 0,
    104 segmentStartX128: u256.Zero(),
    105 earnedX128: u256.Zero(),
    106 }
    107
    108 eventCount := p.GetStakeEventCount()
    109 if view.firstEpoch < 0 {
    110 if view.foldedEpoch >= view.currentEpoch-1 {
    111 // No fee was ever folded and nothing from a closed epoch is pending, so
    112 // every recorded event earned nothing.
    113 settlement.eventCursor = eventCount
    114 settlement.segmentStakedAmount = p.GetStakedAmount()
    115 }
    116 return settlement
    117 }
    118
    119 // Stake events are appended in epoch order, so the last event at or before
    120 // firstEpoch is found by binary search: the lookup costs O(log n) reads no matter
    121 // how many stake changes the staker made since the token's first fee.
    122 lo, hi := int64(0), eventCount
    123 for lo < hi {
    124 mid := lo + (hi-lo)/2
    125 event, ok := p.GetStakeEvent(mid)
    126 if !ok {
    127 break
    128 }
    129 if event.GetEpoch() <= view.firstEpoch {
    130 lo = mid + 1
    131 } else {
    132 hi = mid
    133 }
    134 }
    135
    136 if lo > 0 {
    137 if event, ok := p.GetStakeEvent(lo - 1); ok {
    138 settlement.eventCursor = lo
    139 settlement.segmentStakedAmount = event.GetStakedAmount()
    140 }
    141 }
    142
    143 return settlement
    144}
    145
    146// settleEvents folds up to maxEvents pending stake events into the settlement. An
    147// event can only be folded once the epoch before it is fully folded on the
    148// accumulator, because the segment it closes ends at that epoch's value. A maxEvents
    149// of zero or less folds every event it can. Returns true when no event is left pending.
    150func (p *ProtocolFeeRewardStateResolver) settleEvents(settlement *protocolFeeTokenSettlement, view *protocolFeeAccumulatorView, maxEvents int64) bool {
    151 eventCount := p.GetStakeEventCount()
    152 processed := int64(0)
    153
    154 for settlement.eventCursor < eventCount {
    155 if maxEvents > 0 && processed >= maxEvents {
    156 return false
    157 }
    158
    159 event, ok := p.GetStakeEvent(settlement.eventCursor)
    160 if !ok {
    161 return false
    162 }
    163 if event.GetEpoch()-1 > view.foldedEpoch {
    164 return false
    165 }
    166
    167 segmentEndX128 := view.at(event.GetEpoch() - 1)
    168 settlement.earnedX128 = u256.Zero().Add(
    169 settlement.earnedX128,
    170 segmentRewardX128(settlement.segmentStakedAmount, settlement.segmentStartX128, segmentEndX128),
    171 )
    172 settlement.segmentStartX128 = segmentEndX128.Clone()
    173 settlement.segmentStakedAmount = event.GetStakedAmount()
    174 settlement.eventCursor++
    175 processed++
    176 }
    177
    178 return true
    179}
    180
    181// closeOpenSegment folds the open segment up to the accumulator's latest value. It may
    182// only be called once every stake event is settled, so that the open segment really
    183// ends at the present.
    184func closeOpenSegment(settlement *protocolFeeTokenSettlement, view *protocolFeeAccumulatorView) {
    185 settlement.earnedX128 = u256.Zero().Add(
    186 settlement.earnedX128,
    187 segmentRewardX128(settlement.segmentStakedAmount, settlement.segmentStartX128, view.current),
    188 )
    189 settlement.segmentStartX128 = view.current.Clone()
    190}
    191
    192// takeReward removes the whole-unit part of the earned reward from the settlement and
    193// returns it. The sub-unit remainder stays earned so that no fee share is lost.
    194func takeReward(settlement *protocolFeeTokenSettlement) int64 {
    195 rewardX128 := u256.Zero().Rsh(settlement.earnedX128, 128)
    196 reward := gnsmath.SafeConvertToInt64(rewardX128)
    197 settlement.earnedX128 = u256.Zero().Sub(settlement.earnedX128, u256.Zero().Lsh(rewardX128, 128))
    198
    199 return reward
    200}
    201
    202// segmentRewardX128 returns stakedAmount times the accumulator growth across a segment.
    203func segmentRewardX128(stakedAmount int64, startX128, endX128 *u256.Uint) *u256.Uint {
    204 if stakedAmount <= 0 || !endX128.Gt(startX128) {
    205 return u256.Zero()
    206 }
    207
    208 growthX128 := u256.Zero().Sub(endX128, startX128)
    209
    210 return u256.Zero().Mul(growthX128, u256.NewUintFromInt64(stakedAmount))
    211}
    212
    213// storeTokenSettlement writes the settlement back to the staker's state.
    214func (p *ProtocolFeeRewardStateResolver) storeTokenSettlement(tokenPath string, settlement *protocolFeeTokenSettlement) {
    215 tokenState, ok := p.GetTokenState(tokenPath)
    216 if !ok {
    217 tokenState = staker.NewProtocolFeeTokenRewardState(settlement.eventCursor, settlement.segmentStakedAmount, settlement.segmentStartX128)
    218 tokenState.SetEarnedX128(settlement.earnedX128)
    219 p.SetTokenState(tokenPath, tokenState)
    220 return
    221 }
    222
    223 tokenState.SetSegment(settlement.eventCursor, settlement.segmentStakedAmount, settlement.segmentStartX128)
    224 tokenState.SetEarnedX128(settlement.earnedX128)
    225}
    226
    227// claimTokenReward settles tokenPath and returns the reward collected.
    228//
    229// Up to maxEvents stake events are folded; whatever is settled by then is paid, and
    230// the rest stays pending for a later collect. A maxEvents of zero or less folds
    231// everything.
    232func (p *ProtocolFeeRewardStateResolver) claimTokenReward(tokenPath string, view *protocolFeeAccumulatorView, maxEvents int64) (int64, error) {
    233 // A token that never collected a fee has nothing to settle; skipping it keeps the
    234 // staker's state free of an entry per token merely queried.
    235 if _, ok := p.GetTokenState(tokenPath); !ok && view.firstEpoch < 0 {
    236 return 0, nil
    237 }
    238
    239 settlement := p.loadTokenSettlement(tokenPath, view)
    240
    241 if p.settleEvents(settlement, view, maxEvents) {
    242 closeOpenSegment(settlement, view)
    243 }
    244
    245 reward := takeReward(settlement)
    246 p.storeTokenSettlement(tokenPath, settlement)
    247
    248 if reward > 0 {
    249 if tokenState, ok := p.GetTokenState(tokenPath); ok {
    250 tokenState.SetClaimedReward(gnsmath.SafeAddInt64(tokenState.GetClaimedReward(), reward))
    251 }
    252 }
    253
    254 return reward, nil
    255}
    256
    257// getClaimableReward returns what a collect of tokenPath would pay right now, without
    258// changing any state.
    259func (p *ProtocolFeeRewardStateResolver) getClaimableReward(tokenPath string, view *protocolFeeAccumulatorView) int64 {
    260 settlement := p.loadTokenSettlement(tokenPath, view)
    261
    262 if p.settleEvents(settlement, view, 0) {
    263 closeOpenSegment(settlement, view)
    264 }
    265
    266 return gnsmath.SafeConvertToInt64(u256.Zero().Div(settlement.earnedX128, consts.Q128()))
    267}
    268
    269// addStake increases the staked amount and records the change from epoch on.
    270func (p *ProtocolFeeRewardStateResolver) addStake(amount int64, epoch int64) error {
    271 if amount <= 0 {
    272 return errors.New(errAmountMustBePositive)
    273 }
    274
    275 stakedAmount := gnsmath.SafeAddInt64(p.GetStakedAmount(), amount)
    276 p.SetStakedAmount(stakedAmount)
    277 p.AppendStakeEvent(epoch, stakedAmount)
    278
    279 return nil
    280}
    281
    282// removeStake decreases the staked amount and records the change from epoch on.
    283func (p *ProtocolFeeRewardStateResolver) removeStake(amount int64, epoch int64) error {
    284 if amount < 0 {
    285 return errors.New(errAmountMustBeNonNegative)
    286 }
    287 if amount > p.GetStakedAmount() {
    288 return errors.New(errRemoveAmountExceedsStaked)
    289 }
    290
    291 stakedAmount := gnsmath.SafeSubInt64(p.GetStakedAmount(), amount)
    292 p.SetStakedAmount(stakedAmount)
    293 p.AppendStakeEvent(epoch, stakedAmount)
    294
    295 return nil
    296}
    297
    298// IsClaimable reports whether every token may be collected at once at currentTimestamp.
    299//
    300// Parameters:
    301// - currentTimestamp: current Unix timestamp used to compare the last collection.
    302//
    303// Returns:
    304// - bool: true when currentTimestamp is later than the state's claimed timestamp.
    305func (p *ProtocolFeeRewardStateResolver) IsClaimable(currentTimestamp int64) bool {
    306 return p.GetClaimedTimestamp() < currentTimestamp
    307}
    308