Kind Realm (renderable)
Name v1
Namespace gnoswap / gov / staker
Exported functions 12
Module gno.land/r/gnoswap/gov/staker/v1
gno 0.9 emission_reward_state.gno gno
⧉
1 package staker 2 3 import ( 4 "errors" 5 6 "gno.land/p/gnoswap/consts/v1" 7 gnsmath "gno.land/p/gnoswap/gnsmath/v1" 8 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.
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.
u256 "gno.land/p/gnoswap/uint256/v1"
9 "gno.land/r/gnoswap/gov/staker"
10 )
11
12 type EmissionRewardStateResolver struct {
13 *staker.EmissionRewardState
14 }
15
16 // NewEmissionRewardStateResolver wraps an on-chain emission reward state for
17 // reward calculation and stake/claim updates.
18 //
19 // Parameters:
20 // - emissionRewardState: persisted reward state to expose through the resolver
21 //
22 // Returns:
23 // - *EmissionRewardStateResolver: resolver backed by emissionRewardState
24 func NewEmissionRewardStateResolver(emissionRewardState *staker.EmissionRewardState) *EmissionRewardStateResolver {
25 return &EmissionRewardStateResolver{emissionRewardState}
26 }
27
28 // IsClaimable checks if rewards can be claimed at the given timestamp.
29 // Rewards are claimable only when currentTimestamp is later than the stored
30 // claimed timestamp.
31 //
32 // Parameters:
33 // - currentTimestamp: timestamp at which claimability is evaluated
34 //
35 // Returns:
36 // - bool: true when currentTimestamp is greater than the last claimed timestamp
37 func (self *EmissionRewardStateResolver) IsClaimable(currentTimestamp int64 ) bool {
38 return self.GetClaimedTimestamp() < currentTimestamp
39 }
40
41 // GetClaimableRewardAmount calculates the total amount of rewards that can be claimed.
42 // It combines newly earned rewards with accumulated rewards not yet claimed.
43 //
44 // Parameters:
45 // - accumulatedRewardX128PerStake: system-wide accumulated reward per stake, scaled by 2^128
46 // - currentTimestamp: timestamp through which newly earned rewards are calculated
47 //
48 // Returns:
49 // - int64: total claimable amount, including accumulated-but-unclaimed and newly earned rewards
50 // - error: nil on success; an error propagated from reward calculation otherwise
51 func (self *EmissionRewardStateResolver) GetClaimableRewardAmount(
52 accumulatedRewardX128PerStake *u256.Uint,
53 currentTimestamp int64 ,
54 ) ( int64 , error ) {
55 rewardAmount, err := self.calculateClaimableRewards(accumulatedRewardX128PerStake, currentTimestamp)
56 if err != nil {
57 return 0 , err
58 }
59
60 accumulatedUnclaimedReward := gnsmath.SafeSubInt64(
61 self.GetAccumulatedRewardAmount(),
62 self.GetClaimedRewardAmount(),
63 )
64
65 return gnsmath.SafeAddInt64(accumulatedUnclaimedReward, rewardAmount), nil
66 }
67
68 // calculateClaimableRewards calculates newly earned rewards since the last update.
69 // Uses the difference between current and stored reward debt to calculate earnings.
70 //
71 // Parameters:
72 // - accumulatedRewardX128PerStake: current system-wide accumulated reward per stake
73 // - currentTimestamp: current timestamp
74 //
75 // Returns:
76 // - int64: newly earned reward amount since last update
77 // - error: nil on success, error if calculation fails
78 func (self *EmissionRewardStateResolver) calculateClaimableRewards(
79 accumulatedRewardX128PerStake *u256.Uint,
80 currentTimestamp int64 ,
81 ) ( int64 , error ) {
82 stakedAmount := self.GetStakedAmount()
83
84 // Don't calculate rewards for past timestamps or when nothing is staked
85 if currentTimestamp < self.GetAccumulatedTimestamp() || stakedAmount == 0 {
86 return 0 , nil
87 }
88
89 // Calculate the difference in accumulated rewards per stake since last update
90 // Using modular arithmetic for accumulator values - underflow is allowed and handled correctly
91 rewardDebtDeltaX128 := u256.Zero().Sub(
92 accumulatedRewardX128PerStake,
93 self.GetRewardDebtX128(),
94 )
95
96 // Calculate reward amount by multiplying reward debt delta by staked amount and dividing by Q128
97 // rewardAmount = (rewardDebtDeltaX128 * stakedAmount) / Q128
98 rewardAmount := u256.MulDiv(
99 rewardDebtDeltaX128,
100 u256.NewUintFromInt64(stakedAmount),
101 consts.Q128(),
102 )
103 return gnsmath.SafeConvertToInt64(rewardAmount), nil
104 }
105
106 // addStake increases the staked amount for this address.
107 // This method should be called when a user increases their stake.
108 //
109 // Parameters:
110 // - amount: amount of stake to add
111 func (self *EmissionRewardStateResolver) addStake(amount int64 ) error {
112 if amount < 0 {
113 return errors.New(errAmountMustBeNonNegative)
114 }
115 self.SetStakedAmount(gnsmath.SafeAddInt64(self.GetStakedAmount(), amount))
116 return nil
117 }
118
119 // removeStake decreases the staked amount for this address.
120 // This method should be called when a user decreases their stake.
121 //
122 // Parameters:
123 // - amount: amount of stake to remove
124 func (self *EmissionRewardStateResolver) removeStake(amount int64 ) error {
125 if amount < 0 {
126 return errors.New(errAmountMustBeNonNegative)
127 }
128 if amount > self.GetStakedAmount() {
129 return errors.New(errRemoveAmountExceedsStaked)
130 }
131 self.SetStakedAmount(gnsmath.SafeSubInt64(self.GetStakedAmount(), amount))
132 return nil
133 }
134
135 // claimRewards processes reward claiming and updates the claim state.
136 // This method validates claimability and transfers accumulated rewards to claimed status.
137 //
138 // Parameters:
139 // - currentTimestamp: current timestamp
140 //
141 // Returns:
142 // - int64: amount of rewards claimed (0 if already claimed at this timestamp)
143 // - error: always nil in the current implementation
144 func (self *EmissionRewardStateResolver) claimRewards(currentTimestamp int64 ) ( int64 , error ) {
145 if !self.IsClaimable(currentTimestamp) {
146 return 0 , nil
147 }
148
149 accumulatedRewardAmount := self.GetAccumulatedRewardAmount()
150 previousClaimedAmount := self.GetClaimedRewardAmount()
151 claimableAmount := gnsmath.SafeSubInt64(accumulatedRewardAmount, previousClaimedAmount)
152
153 self.SetClaimedRewardAmount(accumulatedRewardAmount)
154 self.SetClaimedTimestamp(currentTimestamp)
155
156 return claimableAmount, nil
157 }
158
159 // updateRewardDebtX128 updates the reward debt and accumulates new rewards.
160 // This method should be called before any stake changes to ensure accurate reward tracking.
161 //
162 // Parameters:
163 // - accumulatedRewardX128PerStake: current system-wide accumulated reward per stake
164 // - currentTimestamp: current timestamp
165 func (self *EmissionRewardStateResolver) updateRewardDebtX128(
166 accumulatedRewardX128PerStake *u256.Uint,
167 currentTimestamp int64 ,
168 ) error {
169 rewardAmount, err := self.calculateClaimableRewards(accumulatedRewardX128PerStake, currentTimestamp)
170 if err != nil {
171 return err
172 }
173
174 // Accumulate newly earned rewards
175 if rewardAmount != 0 {
176 self.SetAccumulatedRewardAmount(gnsmath.SafeAddInt64(self.GetAccumulatedRewardAmount(), rewardAmount))
177 }
178
179 // Deep copy to avoid aliasing with external state
180 self.SetRewardDebtX128(accumulatedRewardX128PerStake.Clone())
181 self.SetAccumulatedTimestamp(currentTimestamp)
182 return nil
183 }
184
185 // addStakeWithUpdateRewardDebtX128 adds stake and updates reward debt in one operation.
186 // This ensures rewards are properly calculated before the stake change takes effect.
187 //
188 // Parameters:
189 // - amount: amount of stake to add
190 // - accumulatedRewardX128PerStake: current system-wide accumulated reward per stake
191 // - currentTimestamp: current timestamp
192 func (self *EmissionRewardStateResolver) addStakeWithUpdateRewardDebtX128(
193 amount int64 ,
194 accumulatedRewardX128PerStake *u256.Uint,
195 currentTimestamp int64 ,
196 ) error {
197 if err := self.updateRewardDebtX128(accumulatedRewardX128PerStake, currentTimestamp); err != nil {
198 return err
199 }
200 return self.addStake(amount)
201 }
202
203 // removeStakeWithUpdateRewardDebtX128 removes stake and updates reward debt in one operation.
204 // This ensures rewards are properly calculated before the stake change takes effect.
205 //
206 // Parameters:
207 // - amount: amount of stake to remove
208 // - accumulatedRewardX128PerStake: current system-wide accumulated reward per stake
209 // - currentTimestamp: current timestamp
210 func (self *EmissionRewardStateResolver) removeStakeWithUpdateRewardDebtX128(
211 amount int64 ,
212 accumulatedRewardX128PerStake *u256.Uint,
213 currentTimestamp int64 ,
214 ) error {
215 if err := self.updateRewardDebtX128(accumulatedRewardX128PerStake, currentTimestamp); err != nil {
216 return err
217 }
218 return self.removeStake(amount)
219 }
220
221 // claimRewardsWithUpdateRewardDebtX128 claims rewards and updates reward debt in one operation.
222 // This ensures all rewards are properly calculated before claiming.
223 //
224 // Parameters:
225 // - accumulatedRewardX128PerStake: current system-wide accumulated reward per stake
226 // - currentTimestamp: current timestamp
227 //
228 // Returns:
229 // - int64: amount of rewards claimed
230 // - error: nil on success, error if claiming fails
231 func (self *EmissionRewardStateResolver) claimRewardsWithUpdateRewardDebtX128(
232 accumulatedRewardX128PerStake *u256.Uint,
233 currentTimestamp int64 ,
234 ) ( int64 , error ) {
235 if err := self.updateRewardDebtX128(accumulatedRewardX128PerStake, currentTimestamp); err != nil {
236 return 0 , err
237 }
238 return self.claimRewards(currentTimestamp)
239 }
240