Search Apps Documentation Source Content File Folder Download Copy Actions Download 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}