7
7
8
8
"gno.land/p/demo/avl"
9
9
10
+ ufmt "gno.land/p/demo/ufmt"
11
+
10
12
i256 "gno.land/p/gnoswap/int256"
11
13
u256 "gno.land/p/gnoswap/uint256"
12
14
)
@@ -57,6 +59,7 @@ type Pool struct {
57
59
// conceptually equal with Pool.liquidity but only for the staked positions
58
60
// updated each time when the pool crosses a staked tick
59
61
stakedLiquidity *UintTree // blockNumber -> *u256.Uint
62
+ lastUnclaimableHeight *uint64
60
63
61
64
// cache of the internal reward per liquidity for each pool in tier
62
65
// value: (internal reward / total staked liquidity) * Q192
@@ -72,6 +75,7 @@ func NewPool(poolPath string, currentHeight uint64) *Pool {
72
75
return &Pool{
73
76
poolPath: poolPath,
74
77
stakedLiquidity: NewUintTree(),
78
+ lastUnclaimableHeight: ¤tHeight,
75
79
rewardCache: NewRewardCacheTree(),
76
80
lastRewardCacheHeight: ¤tHeight,
77
81
incentives: NewIncentives(currentHeight),
@@ -402,6 +406,94 @@ func (self *Pool) modifyDeposit(tokenId uint64, liquidity *i256.Int, currentHeig
402
406
self.stakedLiquidity.Set(currentHeight, liquidityMathAddDelta(lastStakedLiquidity, liquidity))
403
407
}
404
408
409
+ func (self *Pool) UnclaimableInternalReward(poolTier *PoolTier, startHeight, endHeight uint64) uint64 {
410
+ tierRewardHeights, tierRewardUpdates := poolTier.TierRewardUpdates(self.poolPath, startHeight, endHeight)
411
+
412
+ currentTierReward := tierRewardUpdates[0]
413
+
414
+ unclaimable := uint64(0)
415
+
416
+ currentStakedLiquidity := self.CurrentStakedLiquidity(startHeight)
417
+
418
+ for i := 1; i < len(tierRewardHeights); i++ {
419
+ endHeight := tierRewardHeights[i]
420
+
421
+ currentStakedLiquidity = self.CurrentStakedLiquidity(startHeight)
422
+ self.stakedLiquidity.Iterate(startHeight, endHeight, func(height uint64, value interface{}) bool {
423
+ if currentStakedLiquidity.IsZero() {
424
+ unclaimable += currentTierReward * (height - startHeight)
425
+ }
426
+ startHeight = height
427
+ currentStakedLiquidity = value.(*u256.Uint)
428
+ return false
429
+ })
430
+
431
+ if currentStakedLiquidity.IsZero() {
432
+ unclaimable += currentTierReward * (endHeight - startHeight)
433
+ }
434
+
435
+ startHeight = endHeight
436
+ currentTierReward = tierRewardUpdates[i]
437
+ }
438
+
439
+ if currentStakedLiquidity.IsZero() {
440
+ unclaimable += currentTierReward * (endHeight - startHeight)
441
+ }
442
+
443
+ return unclaimable
444
+ }
445
+
446
+ func (self *Pool) UnclaimableExternalReward(incentiveId string, startHeight, endHeight uint64) uint64 {
447
+ incentive, ok := self.incentives.GetByIncentiveId(incentiveId)
448
+ if !ok {
449
+ return 0
450
+ }
451
+
452
+ if startHeight > uint64(incentive.endHeight) || endHeight < uint64(incentive.startHeight) {
453
+ return 0
454
+ }
455
+
456
+ if startHeight < uint64(incentive.startHeight) {
457
+ startHeight = uint64(incentive.startHeight)
458
+ }
459
+
460
+ if endHeight > uint64(incentive.endHeight) {
461
+ endHeight = uint64(incentive.endHeight)
462
+ }
463
+
464
+ rewardPerBlock := incentive.rewardPerBlock
465
+
466
+ unclaimable := uint64(0)
467
+
468
+ currentStakedLiquidity := self.CurrentStakedLiquidity(startHeight)
469
+
470
+ self.stakedLiquidity.Iterate(startHeight, endHeight, func(height uint64, value interface{}) bool {
471
+ if currentStakedLiquidity.IsZero() {
472
+ unclaimable += rewardPerBlock * (height - startHeight)
473
+ }
474
+ startHeight = height
475
+ currentStakedLiquidity = value.(*u256.Uint)
476
+ return false
477
+ })
478
+
479
+ if currentStakedLiquidity.IsZero() {
480
+ unclaimable += rewardPerBlock * (endHeight - startHeight)
481
+ }
482
+
483
+ return unclaimable
484
+ }
485
+
486
+ func (self *Pool) processUnclaimableReward(poolTier *PoolTier, endHeight uint64) (uint64, map[string]uint64) {
487
+ startHeight := *self.lastUnclaimableHeight
488
+ internalUnclaimable := self.UnclaimableInternalReward(poolTier, startHeight, endHeight)
489
+ externalUnclaimable := make(map[string]uint64)
490
+ for incentiveId := range self.incentives.CurrentReward(startHeight) {
491
+ externalUnclaimable[incentiveId] = self.UnclaimableExternalReward(incentiveId, startHeight, endHeight)
492
+ }
493
+ self.lastUnclaimableHeight = &endHeight
494
+ return internalUnclaimable, externalUnclaimable
495
+ }
496
+
405
497
// ============================================
406
498
// API/helpers
407
499
// ============================================
0 commit comments