Skip to content

Commit

Permalink
add reward ratio calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
mconcat committed Jan 15, 2025
1 parent b1ce569 commit b2f1f5b
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 20 deletions.
7 changes: 7 additions & 0 deletions staker/calculate_pool_position_reward.gno
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"gno.land/r/gnoswap/v1/consts"
"gno.land/r/gnoswap/v1/gns"
en "gno.land/r/gnoswap/v1/emission"
pn "gno.land/r/gnoswap/v1/position"
pl "gno.land/r/gnoswap/v1/pool"

u256 "gno.land/p/gnoswap/uint256"
)
Expand Down Expand Up @@ -93,13 +95,18 @@ type CalcPositionRewardParam struct {
TokenId uint64
}



func CalcPositionReward(param CalcPositionRewardParam) []Reward {


// cache per-pool rewards in the internal incentive(tiers)
param.PoolTier.cacheReward(param.CurrentHeight, param.Pools)

deposit := param.Deposits.Get(param.TokenId)
poolPath := deposit.targetPoolPath


pool, ok := param.Pools.Get(poolPath)
if !ok {
pool = NewPool(poolPath, param.CurrentHeight)
Expand Down
1 change: 1 addition & 0 deletions staker/reward_calculation_canonical_env_test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ func (self *canonicalRewardState) EmulateCalcPositionReward(tokenId uint64) ([]u
deposit := deposits.Get(tokenId)
poolPath := deposit.targetPoolPath


pool, ok := pools.Get(poolPath)
if !ok {
pool = NewPool(poolPath, currentHeight)
Expand Down
38 changes: 19 additions & 19 deletions staker/reward_calculation_canonical_test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func Setup(t *testing.T) *canonicalRewardState {
return NewCanonicalRewardState(t, pools, deposits, TickCrossHook)
}

func TestSimple(t *testing.T) {
func TestCanonicalSimple(t *testing.T) {
canonical := Setup(t)

gnousdc := test_gnousdc
Expand Down Expand Up @@ -50,7 +50,7 @@ func TestSimple(t *testing.T) {
}

// To check precision error
func TestLargeStakedLiquidity(t *testing.T) {
func TestCanonicalLargeStakedLiquidity(t *testing.T) {
canonical := Setup(t)

gnousdc := test_gnousdc
Expand All @@ -75,7 +75,7 @@ func TestLargeStakedLiquidity(t *testing.T) {
}

// To check precision error
func TestLargeStakedLiquidity_2(t *testing.T) {
func TestCanonicalLargeStakedLiquidity_2(t *testing.T) {
canonical := Setup(t)

gnousdc := test_gnousdc
Expand Down Expand Up @@ -119,7 +119,7 @@ func TestLargeStakedLiquidity_2(t *testing.T) {
}

// Tests simple case with tick crossing
func TestTickCross_0(t *testing.T) {
func TestCanonicalTickCross_0(t *testing.T) {
canonical := Setup(t)

gnousdc := GetPoolPath(wugnotPath, gnsPath, 3000)
Expand Down Expand Up @@ -197,7 +197,7 @@ func TestTickCross_0(t *testing.T) {
}

// Tests tick crossing with lazy evaluation of position reward
func TestTickCross_1(t *testing.T) {
func TestCanonicalTickCross_1(t *testing.T) {
canonical := Setup(t)

gnousdc := GetPoolPath(wugnotPath, gnsPath, 3000)
Expand Down Expand Up @@ -248,7 +248,7 @@ func TestTickCross_1(t *testing.T) {
}

// Test tick crossing with multiple positions with same tick, same liquidity
func TestTickCross_2(t *testing.T) {
func TestCanonicalTickCross_2(t *testing.T) {
canonical := Setup(t)

gnousdc := GetPoolPath(wugnotPath, gnsPath, 3000)
Expand Down Expand Up @@ -310,7 +310,7 @@ func TestTickCross_2(t *testing.T) {
}

// Test tick crossing with multiple positions with same tick, different liquidity
func TestTickCross_3(t *testing.T) {
func TestCanonicalTickCross_3(t *testing.T) {
canonical := Setup(t)

gnousdc := GetPoolPath(wugnotPath, gnsPath, 3000)
Expand Down Expand Up @@ -372,7 +372,7 @@ func TestTickCross_3(t *testing.T) {
}

// Test tick crossing with multiple positions with different tick, same liquidity
func TestTickCross_4(t *testing.T) {
func TestCanonicalTickCross_4(t *testing.T) {
canonical := Setup(t)

gnousdc := GetPoolPath(wugnotPath, gnsPath, 3000)
Expand Down Expand Up @@ -443,7 +443,7 @@ func TestTickCross_4(t *testing.T) {
}

// Test tick crossing at tick boundaries, forward direction
func TestTickCross_5(t *testing.T) {
func TestCanonicalTickCross_5(t *testing.T) {
canonical := Setup(t)

gnousdc := GetPoolPath(wugnotPath, gnsPath, 3000)
Expand Down Expand Up @@ -513,7 +513,7 @@ func TestTickCross_5(t *testing.T) {
}

// Test tick crossing at tick boundaries, backward direction
func TestTickCross_6(t *testing.T) {
func TestCanonicalTickCross_6(t *testing.T) {
canonical := Setup(t)

gnousdc := GetPoolPath(wugnotPath, gnsPath, 3000)
Expand Down Expand Up @@ -571,7 +571,7 @@ func TestTickCross_6(t *testing.T) {
canonical.AssertEmulatedRewardOf(0, 0)
}

func TestExternalReward_1(t *testing.T) {
func TestCanonicalExternalReward_1(t *testing.T) {
canonical := Setup(t)

gnousdc := GetPoolPath(wugnotPath, gnsPath, 3000)
Expand Down Expand Up @@ -599,7 +599,7 @@ func TestExternalReward_1(t *testing.T) {
canonical.AssertEmulatedExternalRewardOf(uint64(0), incentiveId, expected)
}

func TestMultiplePool_1(t *testing.T) {
func TestCanonicalMultiplePool_1(t *testing.T) {
canonical := Setup(t)

gnousdc := GetPoolPath(wugnotPath, gnsPath, 3000)
Expand Down Expand Up @@ -662,7 +662,7 @@ func TestMultiplePool_1(t *testing.T) {
canonical.AssertEmulatedRewardOf(1, expected/2)
}

func TestMultiplePool_2(t *testing.T) {
func TestCanonicalMultiplePool_2(t *testing.T) {
canonical := Setup(t)

gnousdc := GetPoolPath(wugnotPath, gnsPath, 3000)
Expand Down Expand Up @@ -746,7 +746,7 @@ func TestMultiplePool_2(t *testing.T) {
}

// Large number of blocks passed
func TestLargeBlocksPassed(t *testing.T) {
func TestCanonicalLargeBlocksPassed(t *testing.T) {
canonical := Setup(t)

gnousdc := GetPoolPath(wugnotPath, gnsPath, 3000)
Expand Down Expand Up @@ -780,7 +780,7 @@ func GetPoolPath(token0Path, token1Path string, fee uint32) string {
return ufmt.Sprintf("%s:%s:%d", token0Path, token1Path, fee)
}

func TestWarmup_1(t *testing.T) {
func TestCanonicalWarmup_1(t *testing.T) {
modifyWarmup(0, 10)
modifyWarmup(1, 10)
modifyWarmup(2, 10)
Expand Down Expand Up @@ -860,7 +860,7 @@ func TestWarmup_1(t *testing.T) {
canonical.AssertEmulatedRewardOf(0, expected*10)
}

func TestWarmup_2(t *testing.T) {
func TestCanonicalWarmup_2(t *testing.T) {
modifyWarmup(0, 10)
modifyWarmup(1, 10)
modifyWarmup(2, 10)
Expand Down Expand Up @@ -943,7 +943,7 @@ func TestWarmup_2(t *testing.T) {
// randomized

// Test tick crossing at tick boundaries, random direction
func TestTickCross_7(t *testing.T) {
func TestCanonicalTickCross_7(t *testing.T) {
canonical := Setup(t)

gnousdc := GetPoolPath(wugnotPath, gnsPath, 3000)
Expand Down Expand Up @@ -987,7 +987,7 @@ func TestTickCross_7(t *testing.T) {

// Test tick crossing with multiple positions with different tick, different liquidity
// Equivalence test
func TestTickCross_8(t *testing.T) {
func TestCanonicalTickCross_8(t *testing.T) {
canonical := Setup(t)

gnousdc := GetPoolPath(wugnotPath, gnsPath, 3000)
Expand Down Expand Up @@ -1046,7 +1046,7 @@ func TestTickCross_8(t *testing.T) {

// Test tick crossing with multiple positions with different tick, different liquidity, emulated reward flushed for every 100 blocks
// Equivalence test
func TestTickCross_9(t *testing.T) {
func TestCanonicalTickCross_9(t *testing.T) {
canonical := Setup(t)

gnousdc := GetPoolPath(wugnotPath, gnsPath, 3000)
Expand Down
113 changes: 113 additions & 0 deletions staker/reward_calculation_pool.gno
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ type Pool struct {
incentives Incentives

ticks *Ticks

// BlockNumber / TotalStake accumulation, Q128.
globalRewardRatioAccumulation *u256.Uint
lastGlobalRewardRatioAccumulationHeight *uint64
}

func NewPool(poolPath string, currentHeight uint64) *Pool {
Expand All @@ -95,6 +99,8 @@ func NewPool(poolPath string, currentHeight uint64) *Pool {
lastRewardCacheHeight: &currentHeight,
incentives: NewIncentives(currentHeight),
ticks: NewTicks(),
globalRewardRatioAccumulation: u256.Zero(),
lastGlobalRewardRatioAccumulationHeight: &currentHeight,
}
}

Expand Down Expand Up @@ -137,6 +143,7 @@ func (self *Pool) cacheRewardPerLiquidityUnit(startHeight, endHeight uint64, cur
if *self.lastUnclaimableHeight != 0 {
self.endInternalUnclaimablePeriod(startHeight)
*self.tierRewardTotal = currentTierReward
println(" ->tierRewardTotal : ", *self.tierRewardTotal)
self.startInternalUnclaimablePeriod(startHeight)
}

Expand Down Expand Up @@ -214,6 +221,34 @@ func (self *Pool) cacheExternalReward(endHeight uint64) {
})
}

// returns the old global reward ratio accumulation
func (self *Pool) updateGlobalRewardRatioAccumulation(currentHeight uint64, currentStakedLiquidity *u256.Uint) *u256.Uint {
println("[[updateGlobalRewardRatioAccumulation]]")
println(" currentHeight : ", currentHeight)
println(" lastGlobalRewardRatioAccumulationHeight : ", *self.lastGlobalRewardRatioAccumulationHeight)
blockDiff := currentHeight - *self.lastGlobalRewardRatioAccumulationHeight
println(" blockDiff : ", blockDiff)
oldAcc := self.globalRewardRatioAccumulation
println(" oldAcc : ", oldAcc.ToString())
if blockDiff == 0 {
return oldAcc
}

acc := u256.NewUint(blockDiff)
acc = acc.Mul(acc, q128)
println(" currentStakedLiquidity : ", currentStakedLiquidity.ToString())
acc = acc.Div(acc, currentStakedLiquidity)

println(" acc : ", acc.ToString())

self.globalRewardRatioAccumulation = oldAcc.Add(oldAcc, acc)
println(" self.globalRewardRatioAccumulation : ", self.globalRewardRatioAccumulation.ToString())
*self.lastGlobalRewardRatioAccumulationHeight = currentHeight
println(" lastGlobalRewardRatioAccumulationHeight : ", *self.lastGlobalRewardRatioAccumulationHeight)
println("[[updateGlobalRewardRatioAccumulation]] End")
return oldAcc
}

type ExternalRewardState struct {
pool *Pool
deposit *Deposit
Expand Down Expand Up @@ -406,6 +441,9 @@ func (self *InternalRewardState) ApplyWarmup() {
reward := u256.Zero()
totalReward := u256.Zero().Div(self.rewards[i], q192)


println("totalReward : ", totalReward.ToString())

reward = reward.Mul(self.rewards[i], u256.NewUint(warmup.WarmupRatio))
reward = reward.Div(reward, u256.NewUint(100))
reward = reward.Div(reward, q192)
Expand All @@ -417,6 +455,13 @@ func (self *InternalRewardState) ApplyWarmup() {
}
}

func abs(x int64) uint64 {
if x < 0 {
return uint64(-x)
}
return uint64(x)
}

func (self *InternalRewardState) TickCrossesToInternalReward(startHeight, endHeight int64, currentlyInRange bool, tickUpperCrosses []int64, tickLowerCrosses []int64) {

for _, warmup := range self.deposit.warmups {
Expand All @@ -428,6 +473,44 @@ func (self *InternalRewardState) TickCrossesToInternalReward(startHeight, endHei
}

if endHeight < warmup.NextWarmupHeight {
// testing
upperTick := self.deposit.tickUpper
lowerTick := self.deposit.tickLower
upperCross := tickUpperCrosses[len(tickUpperCrosses)-1]
lowerCross := tickLowerCrosses[len(tickLowerCrosses)-1]
upperHeight := abs(upperCross)
lowerHeight := abs(lowerCross)
var currentTick int32
if upperHeight == lowerHeight {
if upperCross != lowerCross {
currentTick = (upperTick + lowerTick) / 2 // denoting inrange
} else if upperCross < 0 {
currentTick = lowerTick - 1
} else {
currentTick = upperTick + 1
}
} else if upperHeight > lowerHeight {
if upperCross < 0 {
if lowerCross < 0 {
currentTick = lowerTick - 1
} else {
currentTick = (upperTick + lowerTick) / 2
}
} else {
currentTick = upperTick + 1
}
} else {
if lowerCross < 0 {
currentTick = lowerTick - 1
} else {
if upperCross < 0 {
currentTick = (upperTick + lowerTick) / 2
} else {
currentTick = upperTick + 1
}
}
}

// fully submerged in the current warmup
currentlyInRange, tickUpperCrosses, tickLowerCrosses = ForEachEligibleInterval(
startHeight,
Expand All @@ -438,6 +521,36 @@ func (self *InternalRewardState) TickCrossesToInternalReward(startHeight, endHei
self.AccumulateReward,
)

// checking if global reward ratio logic is correct
globalAcc := self.pool.globalRewardRatioAccumulation
lowerAcc := self.pool.ticks.Get(self.deposit.tickLower).CurrentOutsideAccumulation(uint64(endHeight))
upperAcc := self.pool.ticks.Get(self.deposit.tickUpper).CurrentOutsideAccumulation(uint64(endHeight))
println("globalAcc : ", globalAcc.ToString(), ", lowerAcc : ", lowerAcc.ToString(), ", upperAcc : ", upperAcc.ToString())
var rewardAcc *u256.Uint

if currentTick < lowerTick {
println("currentTick < lowerTick")
rewardAcc = u256.Zero().Sub(lowerAcc, upperAcc)
} else if currentTick >= upperTick {
println("currentTick >= upperTick")
rewardAcc = u256.Zero().Sub(upperAcc, lowerAcc)
} else {
println("currentTick >= lowerTick && currentTick < upperTick")
globalAcc := self.pool.globalRewardRatioAccumulation
rewardAcc = u256.Zero().Sub(globalAcc, lowerAcc)
rewardAcc = rewardAcc.Sub(rewardAcc, upperAcc)
}

println("rewardAcc : ", rewardAcc.ToString())
rewardAcc = rewardAcc.Mul(rewardAcc, self.deposit.liquidity)
println("rewardAcc : ", rewardAcc.ToString())
currentReward := uint64(1000000000) // *self.pool.tierRewardTotal
println("currentReward : ", currentReward)
rewardAcc = rewardAcc.Mul(rewardAcc, u256.NewUint(currentReward))
println("rewardAcc : ", rewardAcc.ToString())
rewardAcc = rewardAcc.Div(rewardAcc, q128)
println("rewardAcc : ", rewardAcc.ToString())

// done
break
}
Expand Down
Loading

0 comments on commit b2f1f5b

Please sign in to comment.