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_manager.gnogno
    1package staker23import (4	"errors"5	"math"67	"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// ProtocolFeeRewardManagerResolver drives the ProtocolFeeRewardManager.
    14//
    15// Stake changes only move the epoch, the total stake history and the staker's own
    16// event list. Fees are folded into a token's accumulator when that token is collected,
    17// each accrual bucket against the total stake in force during its epoch.
    18type ProtocolFeeRewardManagerResolver struct {
    19 *staker.ProtocolFeeRewardManager
    20}
    21
    22// NewProtocolFeeRewardManagerResolver wraps the shared protocol-fee reward manager.
    23//
    24// Parameters:
    25// - manager: Protocol-fee reward state to resolve and mutate.
    26//
    27// Returns:
    28// - *ProtocolFeeRewardManagerResolver: resolver operating on manager's accounting state.
    29func NewProtocolFeeRewardManagerResolver(manager *staker.ProtocolFeeRewardManager) *ProtocolFeeRewardManagerResolver {
    30 return &ProtocolFeeRewardManagerResolver{
    31 ProtocolFeeRewardManager: manager,
    32 }
    33}
    34
    35// addStake records that rewardID staked amount more from epoch on.
    36//
    37// epoch is the accrual epoch protocol_fee just opened for this change, so it must not
    38// be older than the epoch in force.
    39func (self *ProtocolFeeRewardManagerResolver) addStake(rewardID string, amount int64, epoch int64) error {
    40 if amount <= 0 {
    41 return errors.New(errAmountMustBePositive)
    42 }
    43 if epoch < self.GetCurrentEpoch() {
    44 return errors.New(errInvalidAccrualEpoch)
    45 }
    46
    47 currentTotal := self.GetTotalStakedAmount()
    48 if currentTotal > math.MaxInt64-amount {
    49 return errors.New(errTotalStakedAmountOverflow)
    50 }
    51
    52 rewardState, ok, err := self.GetRewardState(rewardID)
    53 if err != nil {
    54 return err
    55 }
    56 if !ok {
    57 rewardState = staker.NewProtocolFeeRewardState()
    58 }
    59
    60 resolvedState := NewProtocolFeeRewardStateResolver(rewardState)
    61 if err := resolvedState.addStake(amount, epoch); err != nil {
    62 return err
    63 }
    64
    65 self.recordTotalStakedAmount(epoch, gnsmath.SafeAddInt64(currentTotal, amount))
    66 self.SetRewardState(rewardID, rewardState)
    67
    68 return nil
    69}
    70
    71// removeStake records that rewardID staked amount less from epoch on.
    72func (self *ProtocolFeeRewardManagerResolver) removeStake(rewardID string, amount int64, epoch int64) error {
    73 if amount < 0 {
    74 return errors.New(errAmountMustBeNonNegative)
    75 }
    76 if epoch < self.GetCurrentEpoch() {
    77 return errors.New(errInvalidAccrualEpoch)
    78 }
    79
    80 updatedTotal := gnsmath.SafeSubInt64(self.GetTotalStakedAmount(), amount)
    81 if updatedTotal < 0 {
    82 return errors.New(errRemoveAmountExceedsTotalStaked)
    83 }
    84
    85 rewardState, ok, err := self.GetRewardState(rewardID)
    86 if err != nil {
    87 return err
    88 }
    89 if !ok {
    90 rewardState = staker.NewProtocolFeeRewardState()
    91 }
    92
    93 resolvedState := NewProtocolFeeRewardStateResolver(rewardState)
    94 if err := resolvedState.removeStake(amount, epoch); err != nil {
    95 return err
    96 }
    97
    98 self.recordTotalStakedAmount(epoch, updatedTotal)
    99 self.SetRewardState(rewardID, rewardState)
    100
    101 return nil
    102}
    103
    104func (self *ProtocolFeeRewardManagerResolver) recordTotalStakedAmount(epoch int64, totalStakedAmount int64) {
    105 self.SetCurrentEpoch(epoch)
    106 self.SetTotalStakedAmount(totalStakedAmount)
    107 self.SetTotalStakedAmountAt(epoch, totalStakedAmount)
    108}
    109
    110// applyAccrualBuckets folds consumed accrual buckets of tokenPath into its accumulator.
    111//
    112// epochs and amounts are parallel and in ascending epoch order. Each amount is divided
    113// by the total stake in force during its epoch; with nothing staked the amount is
    114// dropped, the same policy the emission accumulator applies. exhausted reports that
    115// no bucket is left pending, which lets the accumulator mark every closed epoch as
    116// fully folded.
    117func (self *ProtocolFeeRewardManagerResolver) applyAccrualBuckets(
    118 tokenPath string,
    119 epochs []int64,
    120 amounts []int64,
    121 exhausted bool,
    122 currentTimestamp int64,
    123) error {
    124 if len(epochs) != len(amounts) {
    125 return errors.New(errInvalidAccrualBuckets)
    126 }
    127
    128 accumulator, ok := self.GetTokenAccumulator(tokenPath)
    129 if !ok {
    130 if len(epochs) == 0 {
    131 return nil
    132 }
    133 accumulator = staker.NewProtocolFeeTokenAccumulator()
    134 self.SetTokenAccumulator(tokenPath, accumulator)
    135 }
    136
    137 currentX128 := accumulator.GetAccumulatedX128PerStake().Clone()
    138 feeAmount := accumulator.GetProtocolFeeAmount()
    139 lastEpoch := int64(-1)
    140
    141 for i, epoch := range epochs {
    142 if epoch < lastEpoch || epoch > self.GetCurrentEpoch() {
    143 return errors.New(errInvalidAccrualBuckets)
    144 }
    145 lastEpoch = epoch
    146
    147 amount := amounts[i]
    148 if amount < 0 {
    149 return errors.New(errInvalidAccrualBuckets)
    150 }
    151 feeAmount = gnsmath.SafeAddInt64(feeAmount, amount)
    152
    153 totalStakedAmount := self.GetTotalStakedAmountAt(epoch)
    154 if totalStakedAmount <= 0 || amount == 0 {
    155 continue
    156 }
    157
    158 // Scale the amount by 2^128 before dividing by the total stake. The amount
    159 // fits in 63 bits, so the product fits in 191 bits and cannot overflow.
    160 amountX128 := u256.Zero().Lsh(u256.NewUintFromInt64(amount), 128)
    161 perStakeX128 := u256.Zero().Div(amountX128, u256.NewUintFromInt64(totalStakedAmount))
    162 currentX128 = u256.Zero().Add(currentX128, perStakeX128)
    163
    164 accumulator.SetAccumulatedX128PerStakeAt(epoch, currentX128)
    165 }
    166
    167 accumulator.SetProtocolFeeAmount(feeAmount)
    168
    169 // Every epoch before the one in force is closed, so it is fully folded once no bucket
    170 // is left. Otherwise only the epochs up to the last consumed bucket are complete.
    171 foldedEpoch := accumulator.GetFoldedEpoch()
    172 if exhausted {
    173 foldedEpoch = maxInt64(foldedEpoch, self.GetCurrentEpoch()-1)
    174 } else if lastEpoch >= 0 {
    175 foldedEpoch = maxInt64(foldedEpoch, minInt64(lastEpoch, self.GetCurrentEpoch()-1))
    176 }
    177 accumulator.SetFoldedEpoch(foldedEpoch)
    178
    179 self.SetAccumulatedTimestamp(currentTimestamp)
    180
    181 return nil
    182}
    183
    184// accumulatorView returns a read view of tokenPath's accumulator.
    185//
    186// With pendingComplete false the view reflects the accumulator exactly as folded so
    187// far, which is what a collect must settle against. With pendingComplete true the
    188// given buckets are the whole pending set of the token: they are projected on top, as
    189// applyAccrualBuckets would fold them, and every closed epoch counts as folded, which
    190// is what an exhaustive fold would leave behind. A query uses the latter so that it
    191// reports what a collect would pay even when a previous bounded fold consumed exactly
    192// its limit and left foldedEpoch behind the epoch in force.
    193func (self *ProtocolFeeRewardManagerResolver) accumulatorView(tokenPath string, pendingEpochs []int64, pendingAmounts []int64, pendingComplete bool) *protocolFeeAccumulatorView {
    194 view := &protocolFeeAccumulatorView{
    195 extraEpochs: []int64{},
    196 extraValues: []*u256.Uint{},
    197 current: u256.Zero(),
    198 firstEpoch: -1,
    199 foldedEpoch: -1,
    200 currentEpoch: self.GetCurrentEpoch(),
    201 }
    202
    203 if accumulator, ok := self.GetTokenAccumulator(tokenPath); ok {
    204 view.accumulator = accumulator
    205 view.current = accumulator.GetAccumulatedX128PerStake().Clone()
    206 view.firstEpoch = accumulator.GetFirstEpoch()
    207 view.foldedEpoch = accumulator.GetFoldedEpoch()
    208 }
    209
    210 if pendingComplete {
    211 // Projecting the whole pending set folds every closed epoch.
    212 view.foldedEpoch = maxInt64(view.foldedEpoch, view.currentEpoch-1)
    213 }
    214
    215 for i, epoch := range pendingEpochs {
    216 totalStakedAmount := self.GetTotalStakedAmountAt(epoch)
    217 if totalStakedAmount <= 0 || pendingAmounts[i] <= 0 {
    218 continue
    219 }
    220
    221 amountX128 := u256.Zero().Lsh(u256.NewUintFromInt64(pendingAmounts[i]), 128)
    222 perStakeX128 := u256.Zero().Div(amountX128, u256.NewUintFromInt64(totalStakedAmount))
    223 view.current = u256.Zero().Add(view.current, perStakeX128)
    224 view.extraEpochs = append(view.extraEpochs, epoch)
    225 view.extraValues = append(view.extraValues, view.current.Clone())
    226 if view.firstEpoch < 0 {
    227 view.firstEpoch = epoch
    228 }
    229 }
    230
    231 return view
    232}
    233
    234// claimTokenReward settles tokenPath for rewardID and returns the reward collected.
    235// See ProtocolFeeRewardStateResolver.claimTokenReward for the maxEvents bound.
    236func (self *ProtocolFeeRewardManagerResolver) claimTokenReward(rewardID string, tokenPath string, maxEvents int64) (int64, error) {
    237 rewardState, ok, err := self.GetRewardState(rewardID)
    238 if err != nil {
    239 return 0, err
    240 }
    241 if !ok {
    242 return 0, nil
    243 }
    244
    245 resolvedState := NewProtocolFeeRewardStateResolver(rewardState)
    246 reward, err := resolvedState.claimTokenReward(tokenPath, self.accumulatorView(tokenPath, nil, nil, false), maxEvents)
    247 if err != nil {
    248 return 0, err
    249 }
    250
    251 self.SetRewardState(rewardID, rewardState)
    252
    253 return reward, nil
    254}
    255
    256// claimRewards settles every folded token for rewardID and returns the reward
    257// collected per token. Its cost grows with the number of tokens that ever collected a
    258// fee; claimTokenReward is the bounded alternative.
    259func (self *ProtocolFeeRewardManagerResolver) claimRewards(rewardID string, currentTimestamp int64) (map[string]int64, error) {
    260 rewards := make(map[string]int64)
    261
    262 rewardState, ok, err := self.GetRewardState(rewardID)
    263 if err != nil {
    264 return nil, err
    265 }
    266 if !ok {
    267 return rewards, nil
    268 }
    269
    270 resolvedState := NewProtocolFeeRewardStateResolver(rewardState)
    271 if !resolvedState.IsClaimable(currentTimestamp) {
    272 return rewards, nil
    273 }
    274
    275 for _, tokenPath := range self.GetTokenPaths() {
    276 reward, err := resolvedState.claimTokenReward(tokenPath, self.accumulatorView(tokenPath, nil, nil, false), 0)
    277 if err != nil {
    278 return nil, err
    279 }
    280 rewards[tokenPath] = reward
    281 }
    282
    283 resolvedState.SetClaimedTimestamp(currentTimestamp)
    284 self.SetRewardState(rewardID, rewardState)
    285
    286 return rewards, nil
    287}
    288
    289// GetClaimableRewardAmount returns what collecting tokenPath for rewardID would pay,
    290// with the given pending buckets projected on top of the accumulator.
    291// Parameters:
    292// - rewardID: Identifier of the staker whose claimable reward is quoted.
    293// - tokenPath: Token path whose claimable protocol-fee reward is quoted.
    294// - pendingEpochs: Pending bucket epochs projected on the accumulator.
    295// - pendingAmounts: Pending fee amounts parallel to pendingEpochs.
    296//
    297// Returns:
    298// - int64: protocol-fee amount that collecting tokenPath would pay in token base units.
    299// - error: nil on success; non-nil when reward-state lookup or projection fails.
    300func (self *ProtocolFeeRewardManagerResolver) GetClaimableRewardAmount(rewardID string, tokenPath string, pendingEpochs []int64, pendingAmounts []int64) (int64, error) {
    301 rewardState, ok, err := self.GetRewardState(rewardID)
    302 if err != nil {
    303 return 0, err
    304 }
    305 if !ok {
    306 return 0, nil
    307 }
    308
    309 resolvedState := NewProtocolFeeRewardStateResolver(rewardState)
    310
    311 return resolvedState.getClaimableReward(tokenPath, self.accumulatorView(tokenPath, pendingEpochs, pendingAmounts, true)), nil
    312}
    313
    314func maxInt64(a, b int64) int64 {
    315 if a > b {
    316 return a
    317 }
    318 return b
    319}
    320
    321func minInt64(a, b int64) int64 {
    322 if a < b {
    323 return a
    324 }
    325 return b
    326}
    327