Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

deposit.gno

18.04 Kb · 533 lines
  1package staker
  2
  3import (
  4	"math"
  5
  6	u256 "gno.land/p/gnoswap/uint256/v1"
  7)
  8
  9type Deposit struct {
 10	warmups                        []Warmup         // warmup information
 11	liquidity                      *u256.Uint       // liquidity
 12	targetPoolPath                 string           // staked position's pool path
 13	owner                          address          // owner address
 14	stakeTime                      int64            // staked time
 15	internalRewardLastCollectTime  int64            // last collect time for internal reward
 16	collectedInternalReward        int64            // collected internal reward
 17	collectedExternalRewards       map[string]int64 // collected external reward by incentive id (incentiveID -> int64)
 18	externalRewardLastCollectTimes map[string]int64 // last collect time for external rewards by incentive id (incentiveID -> int64)
 19	externalIncentiveIds           map[string]bool  // external incentive ids for this deposit (incentiveID -> bool)
 20	lastExternalIncentiveUpdatedAt int64            // last time when external incentive ids were synced
 21	tickLower                      int32            // tick lower
 22	tickUpper                      int32            // tick upper
 23}
 24
 25// Owner returns the address that owns the staked position.
 26//
 27// Returns:
 28//   - owner: Address recorded as the deposit owner.
 29func (d *Deposit) Owner() address {
 30	return d.owner
 31}
 32
 33// SetOwner updates the address recorded as the deposit owner.
 34//
 35// Parameters:
 36//   - owner: Address that should own the deposit.
 37func (d *Deposit) SetOwner(owner address) {
 38	d.owner = owner
 39}
 40
 41// TargetPoolPath returns the pool path associated with the staked position.
 42//
 43// Returns:
 44//   - targetPoolPath: Pool identifier used to resolve the position's pool.
 45func (d *Deposit) TargetPoolPath() string {
 46	return d.targetPoolPath
 47}
 48
 49// SetTargetPoolPath updates the pool path associated with the staked position.
 50//
 51// Parameters:
 52//   - targetPoolPath: Pool identifier to associate with the deposit.
 53func (d *Deposit) SetTargetPoolPath(targetPoolPath string) {
 54	d.targetPoolPath = targetPoolPath
 55}
 56
 57// Liquidity returns the LP liquidity recorded for the deposit.
 58//
 59// Returns:
 60//   - liquidity: Liquidity amount represented by the staked position.
 61func (d *Deposit) Liquidity() *u256.Uint {
 62	return d.liquidity
 63}
 64
 65// SetLiquidity replaces the LP liquidity recorded for the deposit.
 66//
 67// Parameters:
 68//   - liquidity: New liquidity amount; the setter copies this value into the deposit.
 69func (d *Deposit) SetLiquidity(liquidity *u256.Uint) {
 70	d.liquidity = u256.Zero().Set(liquidity)
 71}
 72
 73// StakeTime returns the Unix timestamp at which the position was staked.
 74//
 75// Returns:
 76//   - stakeTime: Stake start time in Unix seconds.
 77func (d *Deposit) StakeTime() int64 {
 78	return d.stakeTime
 79}
 80
 81// SetStakeTime updates the Unix timestamp at which the position was staked.
 82//
 83// Parameters:
 84//   - stakeTime: Stake start time in Unix seconds.
 85func (d *Deposit) SetStakeTime(stakeTime int64) {
 86	d.stakeTime = stakeTime
 87}
 88
 89// InternalRewardLastCollectTime returns the internal-reward collection cursor.
 90//
 91// Returns:
 92//   - internalRewardLastCollectTime: Last internal reward collection time in Unix seconds.
 93func (d *Deposit) InternalRewardLastCollectTime() int64 {
 94	return d.internalRewardLastCollectTime
 95}
 96
 97// SetInternalRewardLastCollectTime updates the internal-reward collection cursor.
 98//
 99// Parameters:
100//   - internalRewardLastCollectTime: New last internal reward collection time in Unix seconds.
101func (d *Deposit) SetInternalRewardLastCollectTime(internalRewardLastCollectTime int64) {
102	d.internalRewardLastCollectTime = internalRewardLastCollectTime
103}
104
105// CollectedInternalReward returns the cumulative internal reward recorded for the deposit.
106//
107// Returns:
108//   - collectedInternalReward: Accumulated internal reward amount in the reward token's smallest units.
109func (d *Deposit) CollectedInternalReward() int64 {
110	return d.collectedInternalReward
111}
112
113// SetCollectedInternalReward replaces the cumulative internal reward recorded for the deposit.
114//
115// Parameters:
116//   - collectedInternalReward: Cumulative internal reward amount in the reward token's smallest units.
117func (d *Deposit) SetCollectedInternalReward(collectedInternalReward int64) {
118	d.collectedInternalReward = collectedInternalReward
119}
120
121// CollectedExternalRewards returns cumulative external rewards keyed by incentive ID.
122//
123// Returns:
124//   - collectedExternalRewards: Map from incentive ID to the amount collected for that incentive.
125func (d *Deposit) CollectedExternalRewards() map[string]int64 {
126	return d.collectedExternalRewards
127}
128
129// SetCollectedExternalRewards replaces the cumulative external-reward map.
130//
131// Parameters:
132//   - collectedExternalRewards: Map from incentive ID to its collected reward amount.
133func (d *Deposit) SetCollectedExternalRewards(collectedExternalRewards map[string]int64) {
134	d.collectedExternalRewards = collectedExternalRewards
135}
136
137// GetCollectedExternalReward returns the collected external reward for the given incentive ID.
138// Returns 0 if the incentive ID does not exist.
139//
140// Parameters:
141//   - incentiveID: External incentive ID whose collected amount should be looked up.
142//
143// Returns:
144//   - reward: Collected amount for the incentive, or 0 when the ID is absent.
145//   - exists: True when the map contains incentiveID; false when it is absent.
146func (d *Deposit) GetCollectedExternalReward(incentiveID string) (int64, bool) {
147	reward, exists := d.collectedExternalRewards[incentiveID]
148	if !exists {
149		return 0, false
150	}
151
152	return reward, true
153}
154
155// SetCollectedExternalReward records the cumulative amount collected for one incentive.
156//
157// Parameters:
158//   - incentiveID: External incentive ID whose collected amount should be set.
159//   - reward: Cumulative collected amount for incentiveID.
160func (d *Deposit) SetCollectedExternalReward(incentiveID string, reward int64) {
161	if d.collectedExternalRewards == nil {
162		d.collectedExternalRewards = make(map[string]int64)
163	}
164
165	d.collectedExternalRewards[incentiveID] = reward
166}
167
168// ExternalRewardLastCollectTimes returns per-incentive external collection cursors.
169//
170// Returns:
171//   - externalRewardLastCollectTimes: Map from incentive ID to its last collection time in Unix seconds.
172func (d *Deposit) ExternalRewardLastCollectTimes() map[string]int64 {
173	return d.externalRewardLastCollectTimes
174}
175
176// SetExternalRewardLastCollectTimes replaces the per-incentive external collection cursors.
177//
178// Parameters:
179//   - externalRewardLastCollectTimes: Map from incentive ID to its last collection time in Unix seconds.
180func (d *Deposit) SetExternalRewardLastCollectTimes(externalRewardLastCollectTimes map[string]int64) {
181	d.externalRewardLastCollectTimes = externalRewardLastCollectTimes
182}
183
184// GetExternalRewardLastCollectTime returns the last collect time for the given incentive ID.
185// Returns 0 if the incentive ID does not exist.
186//
187// Parameters:
188//   - incentiveID: External incentive ID whose collection cursor should be looked up.
189//
190// Returns:
191//   - time: Last collection time for the incentive in Unix seconds, or 0 when the ID is absent.
192//   - exists: True when the map contains incentiveID; false when it is absent.
193func (d *Deposit) GetExternalRewardLastCollectTime(incentiveID string) (int64, bool) {
194	time, exists := d.externalRewardLastCollectTimes[incentiveID]
195	if !exists {
196		return 0, false
197	}
198
199	return time, true
200}
201
202// SetExternalRewardLastCollectTime records the collection cursor for one incentive.
203//
204// Parameters:
205//   - incentiveID: External incentive ID whose cursor should be set.
206//   - currentTime: New collection time for incentiveID in Unix seconds.
207func (d *Deposit) SetExternalRewardLastCollectTime(incentiveID string, currentTime int64) {
208	if d.externalRewardLastCollectTimes == nil {
209		d.externalRewardLastCollectTimes = make(map[string]int64)
210	}
211
212	d.externalRewardLastCollectTimes[incentiveID] = currentTime
213}
214
215// TickLower returns the lower signed tick boundary of the staked position.
216//
217// Returns:
218//   - tickLower: Lower tick boundary used by the position's price range.
219func (d *Deposit) TickLower() int32 {
220	return d.tickLower
221}
222
223// SetTickLower updates the lower signed tick boundary of the staked position.
224//
225// Parameters:
226//   - tickLower: Lower tick boundary to store for the position's price range.
227func (d *Deposit) SetTickLower(tickLower int32) {
228	d.tickLower = tickLower
229}
230
231// TickUpper returns the upper signed tick boundary of the staked position.
232//
233// Returns:
234//   - tickUpper: Upper tick boundary used by the position's price range.
235func (d *Deposit) TickUpper() int32 {
236	return d.tickUpper
237}
238
239// SetTickUpper updates the upper signed tick boundary of the staked position.
240//
241// Parameters:
242//   - tickUpper: Upper tick boundary to store for the position's price range.
243func (d *Deposit) SetTickUpper(tickUpper int32) {
244	d.tickUpper = tickUpper
245}
246
247// ExternalIncentiveIds returns the deposit's indexed external incentive IDs.
248//
249// Returns:
250//   - externalIncentiveIds: Map from each indexed incentive ID to its membership flag.
251func (d *Deposit) ExternalIncentiveIds() map[string]bool {
252	return d.externalIncentiveIds
253}
254
255// SetExternalIncentiveIds replaces the deposit's indexed external incentive IDs.
256//
257// Parameters:
258//   - externalIncentiveIds: Map of incentive IDs to their membership flags.
259func (d *Deposit) SetExternalIncentiveIds(externalIncentiveIds map[string]bool) {
260	d.externalIncentiveIds = externalIncentiveIds
261}
262
263// AddExternalIncentiveId adds an external incentive id to the deposit.
264//
265// Parameters:
266//   - incentiveId: External incentive ID to add to the deposit's index.
267func (d *Deposit) AddExternalIncentiveId(incentiveId string) {
268	if d.externalIncentiveIds == nil {
269		d.externalIncentiveIds = make(map[string]bool)
270	}
271
272	d.externalIncentiveIds[incentiveId] = true
273}
274
275// HasExternalIncentiveId checks if the deposit has the given external incentive id.
276//
277// Parameters:
278//   - incentiveId: External incentive ID whose membership should be checked.
279//
280// Returns:
281//   - hasIncentive: True when incentiveId is indexed on the deposit; false otherwise.
282func (d *Deposit) HasExternalIncentiveId(incentiveId string) bool {
283	if d.externalIncentiveIds == nil {
284		return false
285	}
286
287	return d.externalIncentiveIds[incentiveId]
288}
289
290// RemoveExternalIncentiveId removes an external incentive id from the deposit.
291//
292// Parameters:
293//   - incentiveId: External incentive ID to remove from the deposit's index.
294func (d *Deposit) RemoveExternalIncentiveId(incentiveId string) {
295	if d.externalIncentiveIds == nil {
296		return
297	}
298
299	delete(d.externalIncentiveIds, incentiveId)
300}
301
302// GetExternalIncentiveIdList returns a list of external incentive ids for the deposit.
303//
304// Returns:
305//   - incentiveIds: Slice containing the incentive IDs currently indexed on the deposit; order follows map iteration and is not guaranteed.
306func (d *Deposit) GetExternalIncentiveIdList() []string {
307	if d.externalIncentiveIds == nil {
308		return []string{}
309	}
310
311	ids := make([]string, 0, len(d.externalIncentiveIds))
312
313	for incentiveId := range d.externalIncentiveIds {
314		ids = append(ids, incentiveId)
315	}
316
317	return ids
318}
319
320// IterateExternalIncentiveIds iterates over external incentive IDs without allocating a slice.
321// The callback function receives each incentive ID and should return false to continue iteration,
322// or true to stop early. This method is more memory-efficient than GetExternalIncentiveIdList
323// for cases where you only need to process IDs sequentially.
324//
325// Parameters:
326//   - fn: Callback invoked with each indexed incentive ID; return true to stop iteration early or false to continue.
327func (d *Deposit) IterateExternalIncentiveIds(fn func(incentiveId string) bool) {
328	if d.externalIncentiveIds == nil {
329		return
330	}
331
332	for incentiveId := range d.externalIncentiveIds {
333		if fn(incentiveId) {
334			return
335		}
336	}
337}
338
339// Warmups returns a copy of the deposit's warmup schedule.
340//
341// Returns:
342//   - warmups: Warmup tiers applied to rewards for this deposit, or nil when no schedule is stored.
343func (d *Deposit) Warmups() []Warmup {
344	return cloneWarmups(d.warmups)
345}
346
347// SetWarmups replaces the deposit's warmup schedule with a copied slice.
348//
349// Parameters:
350//   - warmups: Warmup tiers to use for subsequent reward calculations.
351func (d *Deposit) SetWarmups(warmups []Warmup) {
352	d.warmups = cloneWarmups(warmups)
353}
354
355// LastExternalIncentiveUpdatedAt returns the timestamp of the last external-incentive index refresh.
356//
357// Returns:
358//   - timestamp: Last refresh time in Unix seconds.
359func (d *Deposit) LastExternalIncentiveUpdatedAt() int64 {
360	return d.lastExternalIncentiveUpdatedAt
361}
362
363// SetLastExternalIncentiveUpdatedAt updates the external-incentive index refresh timestamp.
364//
365// Parameters:
366//   - timestamp: Refresh time to record in Unix seconds.
367func (d *Deposit) SetLastExternalIncentiveUpdatedAt(timestamp int64) {
368	d.lastExternalIncentiveUpdatedAt = timestamp
369}
370
371// Clone returns a deep copy of the deposit.
372//
373// Returns:
374//   - deposit: Deep copy of the deposit, or nil when the receiver is nil.
375func (d *Deposit) Clone() *Deposit {
376	if d == nil {
377		return nil
378	}
379
380	return &Deposit{
381		warmups:                        cloneWarmups(d.warmups),
382		liquidity:                      d.liquidity.Clone(),
383		targetPoolPath:                 d.targetPoolPath,
384		owner:                          d.owner,
385		stakeTime:                      d.stakeTime,
386		internalRewardLastCollectTime:  d.internalRewardLastCollectTime,
387		collectedInternalReward:        d.collectedInternalReward,
388		collectedExternalRewards:       cloneStringInt64Map(d.collectedExternalRewards),
389		externalRewardLastCollectTimes: cloneStringInt64Map(d.externalRewardLastCollectTimes),
390		externalIncentiveIds:           cloneStringBoolMap(d.externalIncentiveIds),
391		lastExternalIncentiveUpdatedAt: d.lastExternalIncentiveUpdatedAt,
392		tickLower:                      d.tickLower,
393		tickUpper:                      d.tickUpper,
394	}
395}
396
397// NewDeposit creates a deposit for a staked LP position and initializes its reward cursors and maps.
398//
399// Parameters:
400//   - owner: Address that owns the staked position.
401//   - targetPoolPath: Pool identifier associated with the position.
402//   - liquidity: LP liquidity amount represented by the position.
403//   - currentTime: Staking and initial reward-cursor time in Unix seconds.
404//   - tickLower: Lower signed tick boundary of the position's range.
405//   - tickUpper: Upper signed tick boundary of the position's range.
406//   - warmups: Warmup schedule to apply to this position's rewards.
407//
408// Returns:
409//   - deposit: Newly initialized deposit containing the supplied position and warmup state.
410func NewDeposit(
411	owner address,
412	targetPoolPath string,
413	liquidity *u256.Uint,
414	currentTime int64,
415	tickLower, tickUpper int32,
416	warmups []Warmup,
417) *Deposit {
418	return &Deposit{
419		owner:                          owner,
420		targetPoolPath:                 targetPoolPath,
421		liquidity:                      liquidity,
422		warmups:                        warmups,
423		stakeTime:                      currentTime,
424		tickLower:                      tickLower,
425		tickUpper:                      tickUpper,
426		internalRewardLastCollectTime:  currentTime,
427		externalRewardLastCollectTimes: make(map[string]int64),
428		collectedInternalReward:        0,
429		collectedExternalRewards:       make(map[string]int64),
430		externalIncentiveIds:           make(map[string]bool),
431		lastExternalIncentiveUpdatedAt: 0,
432	}
433}
434
435type Warmup struct {
436	TimeDuration   int64
437	NextWarmupTime int64 // time when this warmup period ends
438	WarmupRatio    uint64
439}
440
441// NewWarmup creates one warmup tier.
442//
443// Parameters:
444//   - timeDuration: Duration of this tier in seconds.
445//   - nextWarmupTime: Unix timestamp at which this tier ends.
446//   - warmupRatio: Percentage of the calculated reward credited to the position, from 0 to 100.
447//
448// Returns:
449//   - warmup: Warmup tier initialized with the supplied duration, end time, and ratio.
450func NewWarmup(timeDuration, nextWarmupTime int64, warmupRatio uint64) Warmup {
451	return Warmup{
452		TimeDuration:   timeDuration,
453		NextWarmupTime: nextWarmupTime,
454		WarmupRatio:    warmupRatio,
455	}
456}
457
458// SetNextWarmupTime updates the Unix timestamp at which this warmup tier ends.
459//
460// Parameters:
461//   - nextWarmupTime: Tier end time in Unix seconds.
462func (w *Warmup) SetNextWarmupTime(nextWarmupTime int64) {
463	w.NextWarmupTime = nextWarmupTime
464}
465
466// SetWarmupRatio updates the percentage of calculated reward credited to the position.
467//
468// Parameters:
469//   - warmupRatio: Reward percentage for this tier, expressed from 0 to 100.
470func (w *Warmup) SetWarmupRatio(warmupRatio uint64) {
471	w.WarmupRatio = warmupRatio
472}
473
474// SetTimeDuration updates the duration of this warmup tier.
475//
476// Parameters:
477//   - timeDuration: Tier duration in seconds.
478func (w *Warmup) SetTimeDuration(timeDuration int64) {
479	w.TimeDuration = timeDuration
480}
481
482// DefaultWarmupTemplate returns the built-in four-tier warmup schedule.
483//
484// Returns:
485//   - warmups: Template with 5-day, 10-day, 30-day, and final-unbounded tiers using 30%, 50%, 70%, and 100% ratios; NextWarmupTime values are zero until instantiated.
486func DefaultWarmupTemplate() []Warmup {
487	secondsInDay := int64(86400)
488	secondsIn5Days := int64(5 * secondsInDay)
489	secondsIn10Days := int64(10 * secondsInDay)
490	secondsIn30Days := int64(30 * secondsInDay)
491
492	// NextWarmupTime is set to 0 for template.
493	// They will be set by InstantiateWarmup()
494	return []Warmup{
495		{
496			TimeDuration: secondsIn5Days,
497			// NextWarmupTime will be set based on currentTime
498			// NextWarmupTime: currentTime + secondsIn5Days,
499			WarmupRatio: 30,
500		},
501		{
502			TimeDuration: secondsIn10Days,
503			// NextWarmupTime will be set based on currentTime
504			// NextWarmupTime: currentTime + secondsIn10Days,
505			WarmupRatio: 50,
506		},
507		{
508			TimeDuration: secondsIn30Days,
509			// NextWarmupTime will be set based on currentTime
510			// NextWarmupTime: currentTime + secondsIn30Days,
511			WarmupRatio: 70,
512		},
513		{
514			TimeDuration: math.MaxInt64,
515			// NextWarmupTime will be set to math.MaxInt64
516			// NextWarmupTime: math.MaxInt64,
517			WarmupRatio: 100,
518		},
519	}
520}
521
522const (
523	GNS_PATH    string = "gno.land/r/gnoswap/gns.GNS"
524	WUGNOT_PATH string = "gno.land/r/gnoland/wugnot.wugnot"
525)
526
527// DefaultAllowedTokens returns the token paths accepted by the staker's default configuration.
528//
529// Returns:
530//   - tokenPaths: Slice containing the GNS and wrapped-GNOT token paths.
531func DefaultAllowedTokens() []string {
532	return []string{GNS_PATH, WUGNOT_PATH}
533}