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

unstaked_position.gno

8.79 Kb · 225 lines
  1package staker
  2
  3// UnstakedPosition is the exit checkpoint of a position that left the pool before collecting.
  4//
  5// It pins the pool state a later collect must reproduce the exit-time reward from: the tick
  6// observed at the exit, the two boundary ticks (which the unstake may prune from the pool),
  7// and the tier context (which a later tier change would otherwise re-rate the window with).
  8// Collection is per source, so the checkpoint tracks what is left and is dropped when nothing is.
  9type UnstakedPosition struct {
 10	deposit   *Deposit
 11	exitTime  int64
 12	exitTick  int32
 13	lowerTick *Tick
 14	upperTick *Tick
 15
 16	// Outside accumulations of the two boundary ticks at exitTime, as decimal strings. Entries
 17	// before exitTime can no longer change, but the one at exitTime can be overwritten by a tick
 18	// cross later in the same block, so it is pinned rather than read back.
 19	lowerOutsideAcc string
 20	upperOutsideAcc string
 21
 22	tier      uint64
 23	tierRatio uint64
 24	tierCount uint64
 25
 26	// unstakingFee is the staking-reward fee rate in force at exitTime. The window closed under
 27	// it, so a later rate change must not apply retroactively at collect time.
 28	unstakingFee uint64
 29
 30	emissionCollected   bool
 31	pendingIncentiveIds map[string]bool
 32}
 33
 34// NewUnstakedPosition creates an exit checkpoint owing every reward source of the deposit.
 35//
 36// Parameters:
 37//   - deposit: Deposit state captured when the position leaves the pool.
 38//   - exitTime: Unix timestamp when staking ended and this checkpoint's reward window stopped.
 39//   - exitTick: Pool tick observed at exitTime for reconstructing in-range rewards.
 40//   - lowerTick: Snapshot of the position's lower boundary tick, retained if the live pool prunes it.
 41//   - upperTick: Snapshot of the position's upper boundary tick, retained if the live pool prunes it.
 42//   - lowerOutsideAcc: Decimal-encoded outside reward-ratio accumulation of the lower tick at exitTime.
 43//   - upperOutsideAcc: Decimal-encoded outside reward-ratio accumulation of the upper tick at exitTime.
 44//   - tier: Pool emission tier at exitTime; zero denotes that the pool was not tiered.
 45//   - tierRatio: Tier reward-share ratio, in its stored scaled form, at exitTime.
 46//   - tierCount: Number of pools sharing the tier at exitTime for dividing tier rewards.
 47//   - unstakingFee: Staking-reward fee rate in basis points at exitTime (0-1,000; 100 = 1%).
 48//   - pendingIncentiveIds: External incentive IDs whose rewards are still owed by the position.
 49//
 50// Returns:
 51//   - position: New exit checkpoint retaining the deposit and exit-time reward context; emission is initially uncollected and every supplied incentive is pending.
 52func NewUnstakedPosition(
 53	deposit *Deposit,
 54	exitTime int64,
 55	exitTick int32,
 56	lowerTick *Tick,
 57	upperTick *Tick,
 58	lowerOutsideAcc string,
 59	upperOutsideAcc string,
 60	tier uint64,
 61	tierRatio uint64,
 62	tierCount uint64,
 63	unstakingFee uint64,
 64	pendingIncentiveIds []string,
 65) *UnstakedPosition {
 66	// Allocated here so this realm owns it; a map built by the caller is readonly tainted.
 67	pending := make(map[string]bool)
 68	for _, incentiveId := range pendingIncentiveIds {
 69		pending[incentiveId] = true
 70	}
 71
 72	return &UnstakedPosition{
 73		deposit:             deposit,
 74		exitTime:            exitTime,
 75		exitTick:            exitTick,
 76		lowerTick:           lowerTick,
 77		upperTick:           upperTick,
 78		lowerOutsideAcc:     lowerOutsideAcc,
 79		upperOutsideAcc:     upperOutsideAcc,
 80		tier:                tier,
 81		tierRatio:           tierRatio,
 82		tierCount:           tierCount,
 83		unstakingFee:        unstakingFee,
 84		pendingIncentiveIds: pending,
 85	}
 86}
 87
 88// Deposit returns the deposit snapshot captured when this position was unstaked.
 89//
 90// Returns:
 91//   - deposit: Stored deposit state, including its owner, pool, liquidity, ticks, warmups, and collected reward fields.
 92func (u *UnstakedPosition) Deposit() *Deposit { return u.deposit }
 93
 94// ExitTime returns the timestamp at which the position stopped accruing rewards.
 95//
 96// Returns:
 97//   - exitTime: Unix timestamp pinned as the end of this position's reward-accrual window.
 98func (u *UnstakedPosition) ExitTime() int64 { return u.exitTime }
 99
100// ExitTick returns the pool tick observed at ExitTime.
101//
102// Returns:
103//   - exitTick: Tick value used to determine the position's in-range status at the exit checkpoint.
104func (u *UnstakedPosition) ExitTick() int32 { return u.exitTick }
105
106// LowerTick returns the position's lower boundary tick snapshot.
107//
108// Returns:
109//   - lowerTick: Stored lower boundary tick used when calculating rewards for this exit checkpoint.
110func (u *UnstakedPosition) LowerTick() *Tick { return u.lowerTick }
111
112// UpperTick returns the position's upper boundary tick snapshot.
113//
114// Returns:
115//   - upperTick: Stored upper boundary tick used when calculating rewards for this exit checkpoint.
116func (u *UnstakedPosition) UpperTick() *Tick { return u.upperTick }
117
118// LowerOutsideAcc returns the lower boundary tick's outside accumulation at ExitTime.
119//
120// Returns:
121//   - lowerOutsideAcc: Decimal-encoded reward-ratio accumulation outside the lower boundary at exit.
122func (u *UnstakedPosition) LowerOutsideAcc() string { return u.lowerOutsideAcc }
123
124// UpperOutsideAcc returns the upper boundary tick's outside accumulation at ExitTime.
125//
126// Returns:
127//   - upperOutsideAcc: Decimal-encoded reward-ratio accumulation outside the upper boundary at exit.
128func (u *UnstakedPosition) UpperOutsideAcc() string { return u.upperOutsideAcc }
129
130// Tier returns the pool's emission tier at ExitTime, or 0 when it was not tiered.
131//
132// Returns:
133//   - tier: Tier identifier pinned at exit; zero means no emission tier applied.
134func (u *UnstakedPosition) Tier() uint64 { return u.tier }
135
136// TierRatio returns the tier's emission ratio at ExitTime.
137//
138// Returns:
139//   - tierRatio: Stored scaled reward-share ratio for the pinned tier at exit.
140func (u *UnstakedPosition) TierRatio() uint64 { return u.tierRatio }
141
142// TierCount returns how many pools shared the tier at ExitTime.
143//
144// Returns:
145//   - tierCount: Number of pools in the pinned tier when the position exited.
146func (u *UnstakedPosition) TierCount() uint64 { return u.tierCount }
147
148// UnstakingFee returns the staking-reward fee rate in force at ExitTime.
149//
150// Returns:
151//   - unstakingFee: Fee rate pinned for this exit in basis points (0-1,000; 100 = 1%).
152func (u *UnstakedPosition) UnstakingFee() uint64 { return u.unstakingFee }
153
154// EmissionCollected reports whether the emission reward has been collected.
155//
156// Returns:
157//   - collected: True after MarkEmissionCollected has been called; false while the internal reward remains pending.
158func (u *UnstakedPosition) EmissionCollected() bool { return u.emissionCollected }
159
160// MarkEmissionCollected records that the emission reward has been collected.
161func (u *UnstakedPosition) MarkEmissionCollected() { u.emissionCollected = true }
162
163// HasPendingIncentiveId reports whether the incentive is still to be collected.
164//
165// Parameters:
166//   - incentiveId: External incentive identifier to look up in this checkpoint's pending set.
167//
168// Returns:
169//   - pending: True when incentiveId is currently pending; false when it is absent or the pending set is nil.
170func (u *UnstakedPosition) HasPendingIncentiveId(incentiveId string) bool {
171	if u.pendingIncentiveIds == nil {
172		return false
173	}
174
175	return u.pendingIncentiveIds[incentiveId]
176}
177
178// PendingIncentiveIdList returns the incentives still to be collected.
179//
180// Returns:
181//   - incentiveIds: IDs currently present in the pending set; iteration order is unspecified.
182func (u *UnstakedPosition) PendingIncentiveIdList() []string {
183	incentiveIds := make([]string, 0, len(u.pendingIncentiveIds))
184	for incentiveId := range u.pendingIncentiveIds {
185		incentiveIds = append(incentiveIds, incentiveId)
186	}
187
188	return incentiveIds
189}
190
191// PendingIncentiveCount returns how many incentives are still to be collected.
192//
193// Returns:
194//   - count: Number of external incentive IDs currently pending in the checkpoint.
195func (u *UnstakedPosition) PendingIncentiveCount() int {
196	return len(u.pendingIncentiveIds)
197}
198
199// HasPendingIncentives reports whether any incentive is still to be collected.
200//
201// Returns:
202//   - pending: True when at least one external incentive ID remains pending; false otherwise.
203func (u *UnstakedPosition) HasPendingIncentives() bool {
204	return len(u.pendingIncentiveIds) > 0
205}
206
207// MarkIncentiveCollected records that the incentive has been collected.
208//
209// Parameters:
210//   - incentiveId: External incentive identifier to remove from the pending set.
211func (u *UnstakedPosition) MarkIncentiveCollected(incentiveId string) {
212	if u.pendingIncentiveIds == nil {
213		return
214	}
215
216	delete(u.pendingIncentiveIds, incentiveId)
217}
218
219// FullyCollected reports whether every reward source has been collected.
220//
221// Returns:
222//   - collected: True only when the internal emission flag is set and no external incentive IDs remain pending.
223func (u *UnstakedPosition) FullyCollected() bool {
224	return u.emissionCollected && !u.HasPendingIncentives()
225}