Skip to content

Commit

Permalink
test: add debug message and position upper tick bound change
Browse files Browse the repository at this point in the history
- collect emission amount data from gns to emission
  • Loading branch information
onlyhyde committed Jan 9, 2025
1 parent d8330fe commit fe3922a
Show file tree
Hide file tree
Showing 10 changed files with 300 additions and 51 deletions.
94 changes: 93 additions & 1 deletion emission/distribution.gno
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ func init() {
distributionBpsPct.Set(strconv.Itoa(DEVOPS), 2000)
distributionBpsPct.Set(strconv.Itoa(COMMUNITY_POOL), 500)
distributionBpsPct.Set(strconv.Itoa(GOV_STAKER), 0)
addPerBlockMintUpdate(LIQUIDITY_STAKER, uint64(std.GetHeight()), 0)
addPerBlockMintUpdate(DEVOPS, uint64(std.GetHeight()), 0)
addPerBlockMintUpdate(COMMUNITY_POOL, uint64(std.GetHeight()), 0)
addPerBlockMintUpdate(GOV_STAKER, uint64(std.GetHeight()), 0)
}

// ChangeDistributionPctByAdmin changes the distribution percentage for the given targets.
Expand Down Expand Up @@ -146,12 +150,14 @@ func distributeToTarget(amount uint64) uint64 {
))
}

pct := uint64(iPct)
pct := iPct.(uint64)
distAmount := calculateAmount(amount, pct)
totalSent += distAmount

transferToTarget(targetInt, distAmount)

addPerBlockMintUpdate(targetInt, uint64(std.GetHeight()), distAmount)

return false
})

Expand Down Expand Up @@ -260,3 +266,89 @@ func ClearDistributedToGovStaker() {
func setDistributionBpsPct(target int, pct uint64) {
distributionBpsPct.Set(strconv.Itoa(target), pct)
}

var (
perBlockMintToStaker = avl.NewTree() // height => uint64
perBlockMintToGovStaker = avl.NewTree() // height => uint64
perBlockMintToCommunityPool = avl.NewTree() // height => uint64
)

func EmissionUpdatesToStaker(startHeight uint64, endHeight uint64) ([]uint64, []uint64) {
heights := make([]uint64, 0)
updates := make([]uint64, 0)

perBlockMintToStaker.ReverseIterate("", EncodeUint(startHeight-1), func(key string, value interface{}) bool {
heights = append(heights, DecodeUint(key))
updates = append(updates, value.(uint64))
return true
})

perBlockMintToStaker.Iterate(EncodeUint(startHeight), EncodeUint(endHeight), func(key string, value interface{}) bool {
heights = append(heights, DecodeUint(key))
updates = append(updates, value.(uint64))
return false
})

return heights, updates
}

func EmissionUpdatesToCommunityPool(startHeight uint64, endHeight uint64) ([]uint64, []uint64) {
heights := make([]uint64, 0)
updates := make([]uint64, 0)

perBlockMintToCommunityPool.ReverseIterate("", EncodeUint(startHeight-1), func(key string, value interface{}) bool {
heights = append(heights, DecodeUint(key))
updates = append(updates, value.(uint64))
return true
})

perBlockMintToCommunityPool.Iterate(EncodeUint(startHeight), EncodeUint(endHeight), func(key string, value interface{}) bool {
heights = append(heights, DecodeUint(key))
updates = append(updates, value.(uint64))
return false
})

return heights, updates
}

func EmissionUpdatesToGovStaker(startHeight uint64, endHeight uint64) ([]uint64, []uint64) {
heights := make([]uint64, 0)
updates := make([]uint64, 0)

perBlockMintToGovStaker.Iterate(EncodeUint(startHeight), EncodeUint(endHeight), func(key string, value interface{}) bool {
heights = append(heights, DecodeUint(key))
updates = append(updates, value.(uint64))
return false
})

perBlockMintToGovStaker.ReverseIterate("", EncodeUint(endHeight), func(key string, value interface{}) bool {
heights = append(heights, DecodeUint(key))
updates = append(updates, value.(uint64))
return true
})

return heights, updates
}

func addPerBlockMintUpdate(target int, height uint64, amount uint64) {
switch target {
case LIQUIDITY_STAKER:
perBlockMintToStaker.Set(EncodeUint(height), amount)
println("===========>[", height, "] To Staker : ", amount)
case DEVOPS:

case COMMUNITY_POOL:
perBlockMintToCommunityPool.Set(EncodeUint(height), amount)
println("[", height, "] To CommunityPool : ", amount)

case GOV_STAKER:
perBlockMintToGovStaker.Set(EncodeUint(height), amount)
println("[", height, "] To Gov Staker : ", amount)

default:
panic(addDetailToError(
errInvalidEmissionTarget,
ufmt.Sprintf("invalid target(%d)", target),
))
}
}
1 change: 0 additions & 1 deletion emission/emission.gno
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (

"gno.land/p/demo/ufmt"

"gno.land/r/gnoswap/v1/common"
"gno.land/r/gnoswap/v1/consts"
"gno.land/r/gnoswap/v1/gns"
)
Expand Down
19 changes: 19 additions & 0 deletions emission/utils.gno
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package emission

import (
"std"
"strconv"
"strings"

"gno.land/p/demo/ufmt"
pusers "gno.land/p/demo/users"
Expand Down Expand Up @@ -90,3 +92,20 @@ func assertSumDistributionPct(pct01, pct02, pct03, pct04 uint64) {
))
}
}

func EncodeUint(num uint64) string {
// Convert the value to a decimal string.
s := strconv.FormatUint(num, 10)

// Zero-pad to a total length of 20 characters.
zerosNeeded := 20 - len(s)
return strings.Repeat("0", zerosNeeded) + s
}

func DecodeUint(s string) uint64 {
num, err := strconv.ParseUint(s, 10, 64)
if err != nil {
panic(err)
}
return num
}
2 changes: 1 addition & 1 deletion position/getter.gno
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func PositionIsInRange(tokenId uint64) bool {
poolPath := position.poolKey
poolCurrentTick := pl.PoolGetSlot0Tick(poolPath)

if position.tickLower <= poolCurrentTick && poolCurrentTick <= position.tickUpper {
if position.tickLower <= poolCurrentTick && poolCurrentTick < position.tickUpper {
return true
}
return false
Expand Down
4 changes: 2 additions & 2 deletions staker/__TEST_staker_emission_and_external_incentive_test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func testPositionMintPos01Tier01(t *testing.T) {
"gno.land/r/gnoswap/v1/gns", // token0
"gno.land/r/demo/wugnot", // token1
fee3000, // fee
int32(0), // tickLower
int32(-60), // tickLower
int32(60), // tickUpper
"1000", // amount0Desired
"1000", // amount1Desired
Expand All @@ -141,7 +141,7 @@ func testPositionMintPos01Tier01(t *testing.T) {
uassert.Equal(t, uint64(1), gnsBalance(consts.EMISSION_ADDR))
uassert.Equal(t, uint64(1), lpTokenId)
uassert.Equal(t, gnft.MustOwnerOf(tid(lpTokenId)), users.Resolve(admin))
uassert.Equal(t, amount0, "0")
uassert.Equal(t, amount0, "1000")
uassert.Equal(t, amount1, "1000")

std.TestSkipHeights(1)
Expand Down
77 changes: 63 additions & 14 deletions staker/calculate_pool_position_reward.gno
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package staker

import (
"gno.land/r/gnoswap/v1/consts"
"gno.land/r/gnoswap/v1/gns"

u256 "gno.land/p/gnoswap/uint256"
"gno.land/r/gnoswap/v1/consts"
en "gno.land/r/gnoswap/v1/emission"
pn "gno.land/r/gnoswap/v1/position"
)

// Q96
Expand All @@ -24,10 +24,12 @@ type Reward struct {
ExternalPenalty map[string]uint64
}

// For Debug
func calcPositionRewardByWarmups(currentHeight uint64, tokenId uint64) []Reward {
deposit := deposits.Get(tokenId)
emissionUpdateHeights, emissionUpdates := gns.EmissionUpdates(deposit.lastCollectHeight, currentHeight)
internalRewards, internalPenalties, externalRewards, externalPenalties := CalcPositionReward(currentHeight, tokenId, deposits, pools, poolTier, emissionUpdateHeights, emissionUpdates)
emissionUpdateHeights, emissionUpdates := en.EmissionUpdatesToStaker(deposit.lastCollectHeight, currentHeight)
calcTierReward(currentHeight, emissionUpdateHeights, emissionUpdates)
internalRewards, internalPenalties, externalRewards, externalPenalties := CalcPositionReward(currentHeight, tokenId, deposits, pools, poolTier)

rewards := make([]Reward, len(internalRewards))
for i := range internalRewards {
Expand All @@ -42,10 +44,48 @@ func calcPositionRewardByWarmups(currentHeight uint64, tokenId uint64) []Reward
return rewards
}

func printWarmup(warmup *Warmup) {
println("Warmup : ", warmup.Index, ", BlockDuration : ", warmup.BlockDuration, ", NextWarmupHeight : ", warmup.NextWarmupHeight, ", WarmupRatio : ", warmup.WarmupRatio)
}

func printDeposit(deposit *Deposit, currentHeight, tokenId uint64) {
println("[", currentHeight, "],[", tokenId, "], Deposit : ", deposit.owner, ", path : ", deposit.targetPoolPath, ", tickLower : ", deposit.tickLower, ", tickUpper : ", deposit.tickUpper, ", liquidity : ", deposit.liquidity.ToString(), ", lastCollectHeight :", deposit.lastCollectHeight)
for _, warmup := range deposit.warmups {
printWarmup(&warmup)
}
}



var lastEmissionUpdateHeight uint64 = 0

func calcTierReward(currentHeight uint64, emissionUpdateHeights []uint64, emissionUpdateAmounts []uint64) {
// cache per-tier and per-pool rewards
poolTier.cacheReward(currentHeight, emissionUpdateHeights, emissionUpdateAmounts)
rewardCache := poolTier.rewardCacheOf(1)
rewardCache.Iterate(0, currentHeight, func(height uint64, reward interface{}) bool {
println("RewardCache : ", height, ", ", reward)
return false
})
}

func calcPositionReward(currentHeight uint64, tokenId uint64) Reward {
deposit := deposits.Get(tokenId)
emissionUpdateHeights, emissionUpdates := gns.EmissionUpdates(deposit.lastCollectHeight, currentHeight)
internalRewards, internalPenalties, externalRewards, externalPenalties := CalcPositionReward(currentHeight, tokenId, deposits, pools, poolTier, emissionUpdateHeights, emissionUpdates)
// TODO: For Debugging
printDeposit(deposit, currentHeight, tokenId)

println(">>>>>>>>>>>>> EmissionUpdatesToStaker")
// TODO:
println(">>>>>>>>>>>>> lastEmissionUpdateHeight : ", *poolTier.lastRewardCacheHeight, ", currentHeight : ", currentHeight)
emissionUpdateHeights, emissionUpdates := en.EmissionUpdatesToStaker(*poolTier.lastRewardCacheHeight, currentHeight)
accumulatedEmission := uint64(0)
for i := range emissionUpdateHeights {
accumulatedEmission += emissionUpdates[i]
println(emissionUpdateHeights[i], ", ", emissionUpdates[i], ", accumulatedEmission : ", accumulatedEmission)
}
calcTierReward(currentHeight, emissionUpdateHeights, emissionUpdates)

internalRewards, internalPenalties, externalRewards, externalPenalties := CalcPositionReward(currentHeight, tokenId, deposits, pools, poolTier)

internal := uint64(0)
for _, reward := range internalRewards {
Expand Down Expand Up @@ -79,10 +119,7 @@ func calcPositionReward(currentHeight uint64, tokenId uint64) Reward {
}
}

func CalcPositionReward(currentHeight uint64, tokenId uint64, deposits *Deposits, pools *Pools, poolTier *PoolTier, emissionUpdateHeights []uint64, emissionUpdates []uint64) ([]uint64, []uint64, []map[string]uint64, []map[string]uint64) {
// cache per-tier and per-pool rewards
poolTier.cacheReward(currentHeight, emissionUpdateHeights, emissionUpdates)

func CalcPositionReward(currentHeight uint64, tokenId uint64, deposits *Deposits, pools *Pools, poolTier *PoolTier) ([]uint64, []uint64, []map[string]uint64, []map[string]uint64) {
deposit := deposits.Get(tokenId)
poolPath := deposit.targetPoolPath

Expand All @@ -97,18 +134,30 @@ func CalcPositionReward(currentHeight uint64, tokenId uint64, deposits *Deposits
pool.cacheExternalReward(currentHeight)

// eligible(in-range) intervals for a position
upperTick := pool.ticks.Get(deposit.tickUpper)
lowerTick := pool.ticks.Get(deposit.tickLower)

tickUpper := deposit.tickUpper
tickLower := deposit.tickLower
token0, token1, _ := poolPathDivide(poolPath)
if token1 < token0 {
tickUpper, tickLower = -tickLower, -tickUpper
}
upperTick := pool.ticks.Get(tickUpper)
lowerTick := pool.ticks.Get(tickLower)
lastCollectHeight := deposit.lastCollectHeight

initialUpperCross := upperTick.previousCross(lastCollectHeight)
initialLowerCross := lowerTick.previousCross(lastCollectHeight)
println(">>>>>>>>>>>> initialUpperCross : ", initialUpperCross, ", initialLowerCross : ", initialLowerCross)
currentlyInRange := initialUpperCross && !initialLowerCross
println(">>>>>>>>>>>> currentlyInRange : ", currentlyInRange)

if pn.PositionIsInRange(tokenId) {
currentlyInRange = true
}

tickUpperCrosses := upperTick.crossInfo(lastCollectHeight, currentHeight)
tickLowerCrosses := lowerTick.crossInfo(lastCollectHeight, currentHeight)

println(">>>>>>> lastCollectHeight : ", lastCollectHeight, ", currentHeight : ", currentHeight, ", currentlyInRange : ", currentlyInRange, ", tickUpperCrosses : ", tickUpperCrosses, ", tickLowerCrosses : ", tickLowerCrosses)
internalRewards, internalPenalties := pool.InternalRewardOf(deposit).Calculate(int64(lastCollectHeight), int64(currentHeight), currentlyInRange, tickUpperCrosses, tickLowerCrosses)

externalRewards, externalPenalties := pool.ExternalRewardOf(deposit).Calculate(int64(lastCollectHeight), int64(currentHeight), currentlyInRange, tickUpperCrosses, tickLowerCrosses)
Expand Down
32 changes: 31 additions & 1 deletion staker/reward_calculation_pool_tier.gno
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ func (self *PoolTier) countOf(tier uint64) *UintTree {
default:
panic(addDetailToError(
errInvalidPoolTier,
ufmt.Sprintf("staker.gno__tier() || tier(%d) is not valid", tier),
ufmt.Sprintf("tier(%d) is not valid", tier),
))
}
}
Expand Down Expand Up @@ -480,10 +480,25 @@ func nextHeightUpdateI(
// iterate over denominator updates and cache reward for each block
func (self *PoolTier) cacheTierReward(tier uint64, startHeight, endHeight uint64, emissionUpdateHeights []uint64, emissionUpdates []uint64) {
rewardCache := self.rewardCacheOf(tier)
println("==============================================================")
println("tier [", tier, "] rewardCache size ", rewardCache.tree.Size())

countUpdateHeights, countUpdates := self.TierCountUpdates(tier, startHeight, endHeight)
ratioUpdateHeights, ratioUpdates := self.TierRatioUpdates(tier, startHeight, endHeight)

println("\t[emissionUpdateHeights] ")
for i, height := range emissionUpdateHeights {
println("\t[", height, "] ", emissionUpdates[i])
}
println("\t[countUpdateHeights] ")
for i, height := range countUpdateHeights {
println("\t[", height, "] ", countUpdates[i])
}
println("\t[ratioUpdateHeights] ")
for i, height := range ratioUpdateHeights {
println("\t[", height, "] ", ratioUpdates[i])
}

emissionUpdateI := 0
countUpdateI := 0
ratioUpdateI := 0
Expand All @@ -495,6 +510,10 @@ func (self *PoolTier) cacheTierReward(tier uint64, startHeight, endHeight uint64
currentRatio := ratioUpdates[ratioUpdateI]

for emissionUpdateI < len(emissionUpdateHeights) || countUpdateI < len(countUpdateHeights) || ratioUpdateI < len(ratioUpdateHeights) {
println("[Condition 1] emissionUpdateI < len(emissionUpdateHeights)", emissionUpdateI < len(emissionUpdateHeights))
println("[Condition 2] countUpdateI < len(countUpdateHeights)", countUpdateI < len(countUpdateHeights))
println("[Condition 3] ratioUpdateI < len(ratioUpdateHeights)", ratioUpdateI < len(ratioUpdateHeights))

currentHeight, emissionUpdateI, countUpdateI, ratioUpdateI = nextHeightUpdateI(
emissionUpdateHeights,
emissionUpdateI,
Expand All @@ -504,23 +523,32 @@ func (self *PoolTier) cacheTierReward(tier uint64, startHeight, endHeight uint64
ratioUpdateI,
)

println("currentHeight ", currentHeight, ", emissionUpdateI ", emissionUpdateI, ", countUpdateI ", countUpdateI, ", ratioUpdateI ", ratioUpdateI)

if emissionUpdateI < len(emissionUpdateHeights) {
currentEmission = emissionUpdates[emissionUpdateI]
println("emissionUpdateI < len(emissionUpdateHeights) ", currentEmission)
}
if countUpdateI < len(countUpdateHeights) {
currentCount = countUpdates[countUpdateI]
println("countUpdateI < len(countUpdateHeights) ", currentCount)
}
if ratioUpdateI < len(ratioUpdateHeights) {
currentRatio = ratioUpdates[ratioUpdateI]
println("ratioUpdateI < len(ratioUpdateHeights) ", currentRatio)
}

if currentCount == 0 {
rewardCache.Set(currentHeight, uint64(0))
println("set reward Cache [", currentHeight, "] ", uint64(0))
} else {
reward := currentEmission * currentRatio / currentCount / 100
rewardCache.Set(currentHeight, reward)
println("set reward Cache [", currentHeight, "] ", reward)
}

}
println("==============================================================")
}

// cacheReward calculates and caches rewards for all tiers within a height range.
Expand All @@ -532,7 +560,9 @@ func (self *PoolTier) cacheTierReward(tier uint64, startHeight, endHeight uint64
func (self *PoolTier) cacheReward(endHeight uint64, emissionUpdateHeights []uint64, emissionUpdates []uint64) {
startHeight := *self.lastRewardCacheHeight

println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ", *self.lastRewardCacheHeight)
for tier := uint64(1); tier <= 3; tier++ {
self.cacheTierReward(tier, startHeight, endHeight, emissionUpdateHeights, emissionUpdates)
}
*self.lastRewardCacheHeight = endHeight // TODO: Check Update Timeimg
}
Loading

0 comments on commit fe3922a

Please sign in to comment.