Skip to content

Commit

Permalink
external reward works
Browse files Browse the repository at this point in the history
  • Loading branch information
mconcat committed Jan 17, 2025
1 parent 3bd080a commit 31641e1
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 276 deletions.
34 changes: 20 additions & 14 deletions staker/calculate_pool_position_reward.gno
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,6 @@ func CalcPositionReward(param CalcPositionRewardParam) []Reward {
param.Pools.Set(poolPath, pool)
}

// cacheInternalReward is called by poolTier.cacheReward
pool.cacheExternalReward(param.CurrentHeight)
// eligible(in-range) intervals for a position
// XXX: Tick ordering code, memoing for future
tickUpper := deposit.tickUpper
tickLower := deposit.tickLower
token0, token1, _ := poolPathDivide(poolPath)
Expand All @@ -121,24 +117,34 @@ func CalcPositionReward(param CalcPositionRewardParam) []Reward {

lastCollectHeight := deposit.lastCollectHeight

internalRewards, internalPenalties := pool.InternalRewardOf(deposit).Calculate(0/*testing, remove later*/, int64(lastCollectHeight), int64(param.CurrentHeight))
internalRewards, internalPenalties := pool.RewardStateOf(deposit).CalculateInternalReward(int64(lastCollectHeight), int64(param.CurrentHeight), pool.rewardCache)

//externalRewards, externalPenalties := pool.ExternalRewardOf(deposit).Calculate(int64(lastCollectHeight), int64(param.CurrentHeight))
allIncentives := pool.incentives.GetAllInHeights(int64(lastCollectHeight), int64(param.CurrentHeight))

externalRewards := make([]map[string]uint64, 4)
externalPenalties := make([]map[string]uint64, 4)
for i := range externalRewards {
externalRewards[i] = make(map[string]uint64)
externalPenalties[i] = make(map[string]uint64)
}

for _, incentive := range allIncentives {
externalReward, externalPenalty := pool.RewardStateOf(deposit).CalculateExternalReward(int64(lastCollectHeight), int64(param.CurrentHeight), incentive)

for i := range externalReward {
externalRewards[i][incentive.incentiveId] = externalReward[i]
externalPenalties[i][incentive.incentiveId] = externalPenalty[i]
}
}

rewards := make([]Reward, len(internalRewards))
for i := range internalRewards {
rewards[i] = Reward{
Internal: internalRewards[i],
InternalPenalty: internalPenalties[i],
External: externalRewards[i],
ExternalPenalty: externalPenalties[i],
}
/*
if externalRewards != nil {
if len(externalRewards[i]) > 0 {
rewards[i].External = externalRewards[i]
rewards[i].ExternalPenalty = externalPenalties[i]
}
}
*/
}
return rewards
}
Expand Down
63 changes: 31 additions & 32 deletions staker/reward_calculation_canonical_env_test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ func NewCanonicalRewardState(t *testing.T, pools *Pools, deposits *Deposits, tic
type emulatedGlobalState struct {
poolTier *PoolTier
pools *Pools
deposits *Depositsgit
deposits *Deposits
}

func (self *canonicalRewardState) isInRange(deposit *Deposit) bool {
Expand Down Expand Up @@ -256,51 +256,53 @@ func (self *canonicalRewardState) EmulateCalcPositionReward(tokenId uint64) ([]u
currentHeight := uint64(self.CurrentHeight())

// cache per-tier and per-pool rewards
println("###### cacheReward")
self.global.poolTier.cacheReward(currentHeight, self.global.pools)
println("###### cacheReward done")

deposit := self.global.deposits.Get(tokenId)
poolPath := deposit.targetPoolPath

pool, ok := self.global.pools.Get(poolPath)
if !ok {
println("[[[NewPool 1]]], ", poolPath)
pool = NewPool(poolPath, currentHeight, self.Pool[poolPath].tick)
self.global.pools.Set(poolPath, pool)
}

// cacheInternalReward is called by poolTier.cacheReward
pool.cacheExternalReward(currentHeight)

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

lastCollectHeight := deposit.lastCollectHeight

//initialUpperCross := upperTick.previousCross(lastCollectHeight)
//initialLowerCross := lowerTick.previousCross(lastCollectHeight)
internalRewards, internalPenalties := pool.RewardStateOf(deposit).CalculateInternalReward(int64(lastCollectHeight), int64(currentHeight), pool.rewardCache)

//currentlyInRange := initialUpperCross && !initialLowerCross

//tickUpperCrosses := upperTick.crossInfo(lastCollectHeight, currentHeight)
//tickLowerCrosses := lowerTick.crossInfo(lastCollectHeight, currentHeight)
externalRewards := make([]map[string]uint64, 4)
externalPenalties := make([]map[string]uint64, 4)
for i := range externalRewards {
externalRewards[i] = make(map[string]uint64)
externalPenalties[i] = make(map[string]uint64)
}

println("###### InternalRewardOf")
internalRewards, internalPenalties := pool.InternalRewardOf(deposit).Calculate(self.Pool[poolPath].tick, int64(lastCollectHeight), int64(currentHeight))
println("###### InternalRewardOf done")
allIncentives := pool.incentives.GetAllInHeights(int64(lastCollectHeight), int64(currentHeight))

for _, incentive := range allIncentives {
externalReward, externalPenalty := pool.RewardStateOf(deposit).CalculateExternalReward(int64(lastCollectHeight), int64(currentHeight), incentive)

//externalRewards, externalPenalties := pool.ExternalRewardOf(deposit).Calculate(int64(lastCollectHeight), int64(currentHeight), currentlyInRange, tickUpperCrosses, tickLowerCrosses)
for i := range externalReward {
externalRewards[i][incentive.incentiveId] = externalReward[i]
externalPenalties[i][incentive.incentiveId] = externalPenalty[i]
}
}

return internalRewards, internalPenalties, nil, nil
return internalRewards, internalPenalties, externalRewards, externalPenalties
}

func (self *canonicalRewardState) EmulatedRewardOf(depositId uint64) Reward {
// emissionUpdateHeights, emissionUpdates := self.EmissionUpdates(*self.global.poolTier.lastRewardCacheHeight, uint64(self.CurrentHeight()))

rewards, penalties, externalRewards, externalPenalties := self.EmulateCalcPositionReward(depositId)

println("[[[EmulatedRewardOf Start]]]")
println("rewards: ", rewards)
println("penalties: ", penalties)
println("externalRewards: ", externalRewards)
println("externalPenalties: ", externalPenalties)

deposit := self.global.deposits.Get(depositId)
deposit.lastCollectHeight = uint64(self.CurrentHeight())

Expand All @@ -314,14 +316,14 @@ func (self *canonicalRewardState) EmulatedRewardOf(depositId uint64) Reward {
}
external := make(map[string]uint64)
for _, er := range externalRewards {
for tokenId, reward := range er {
external[tokenId] += reward
for incentiveId, reward := range er {
external[incentiveId] += reward
}
}
externalPenalty := make(map[string]uint64)
for _, ep := range externalPenalties {
for tokenId, penalty := range ep {
externalPenalty[tokenId] += penalty
for incentiveId, penalty := range ep {
externalPenalty[incentiveId] += penalty
}
}

Expand Down Expand Up @@ -374,7 +376,6 @@ func (self *canonicalRewardState) StakeToken(tokenId uint64, targetPoolPath stri
self.global.deposits.Set(tokenId, deposit)

self.global.poolTier.cacheReward(currentHeight, self.global.pools)
pool.cacheExternalReward(currentHeight)

signedLiquidity := i256.FromUint256(deposit.liquidity)
if self.isInRange(deposit) {
Expand Down Expand Up @@ -489,7 +490,6 @@ func (self *canonicalRewardState) ChangePoolTier(poolPath string, tier uint64) {

// update global state
if !self.global.pools.Has(poolPath) {
println("[[[NewPool 2]]]", poolPath)
self.global.pools.Set(poolPath, NewPool(poolPath, uint64(self.CurrentHeight()), pool.tick))
}
self.global.poolTier.changeTier(uint64(self.CurrentHeight()), self.global.pools, poolPath, tier)
Expand All @@ -503,7 +503,6 @@ func (self *canonicalRewardState) CreatePool(poolPath string, initialTier uint64
incentive: make([]*ExternalIncentive, 0),
tickCrossHook: self.tickCrossHook,
}
println("[[[NewPool 3]]], ", poolPath)
self.global.pools.Set(poolPath, NewPool(poolPath, uint64(self.CurrentHeight()), initialTick))
self.global.poolTier.changeTier(uint64(self.CurrentHeight()), self.global.pools, poolPath, initialTier)
}
Expand Down Expand Up @@ -584,10 +583,10 @@ func (self *canonicalRewardState) AssertEmulatedRewardOf(depositId uint64, expec
}
}

func (self *canonicalRewardState) AssertEmulatedExternalRewardOf(depositId uint64, tokenId string, expected uint64) {
func (self *canonicalRewardState) AssertEmulatedExternalRewardOf(depositId uint64, incentiveId string, expected uint64) {
reward := self.EmulatedRewardOf(depositId)
if !isInErrorRange(expected, reward.External[tokenId]) {
self.t.Errorf("emulated external reward of %d mismatch: expected %d, got %d", depositId, expected, reward.External[tokenId])
if !isInErrorRange(expected, reward.External[incentiveId]) {
self.t.Errorf("emulated external reward of %d mismatch: expected %d, got %d", depositId, expected, reward.External[incentiveId])
}
}

Expand Down
126 changes: 27 additions & 99 deletions staker/reward_calculation_incentives.gno
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,13 @@ type Incentives struct {
byTime *avl.Tree // (startTime, endTime, creator, rewardToken) => ExternalIncentive
byHeight *avl.Tree // (startHeight, endHeight, creator, rewardToken) => ExternalIncentive
byCreator *avl.Tree // (creator, startHeight, endHeight, rewardToken) => ExternalIncentive

// incentiveBound *UintTree // blockNumber -> []IncentiveBound

// currentIncentives []string

//rewardCache *RewardCacheTree // blockNumber -> IncentiveRewardEntry
//lastRewardCacheHeight *uint64
}

func NewIncentives(currentHeight uint64) Incentives {
return Incentives{
byTime: avl.NewTree(),
byHeight: avl.NewTree(),
byCreator: avl.NewTree(),

// incentiveBound: NewUintTree(),

//rewardCache: NewRewardCacheTree(),
//lastRewardCacheHeight: &currentHeight,
}
}

Expand All @@ -64,6 +52,32 @@ func (self *Incentives) GetByIncentiveId(incentiveId string) (*ExternalIncentive
return value.(*ExternalIncentive), true
}

func (self *Incentives) GetAllInHeights(startHeight, endHeight int64) []*ExternalIncentive {
println("[[[GetAllInHeights Start]]]", startHeight, endHeight)

self.byHeight.Iterate(
"",
"",
func(key string, value interface{}) bool {
println("[[[GetAllInHeights Iterate]]]")
println("[[[key]]]", key)
println("[[[value]]]", value)
return false
},
)

incentives := make([]*ExternalIncentive, 0)
self.byHeight.Iterate(
EncodeUint(uint64(startHeight)),
EncodeUint(uint64(endHeight)),
func(key string, value interface{}) bool {
incentives = append(incentives, value.(*ExternalIncentive))
return false
},
)
return incentives
}

// MUST be called after std.GetHeight() > endHeight
func (self *Incentives) remove(incentive *ExternalIncentive) {
byTimeId := incentiveIdByTime(uint64(incentive.startTimestamp), uint64(incentive.endTimestamp), incentive.refundee, incentive.rewardToken)
Expand All @@ -73,27 +87,6 @@ func (self *Incentives) remove(incentive *ExternalIncentive) {
self.byHeight.Remove(byHeightId)
self.byCreator.Remove(byCreatorId)
}
/*
func (self *Incentives) GetBound(height uint64) []IncentiveBound {
value, ok := self.incentiveBound.Get(height)
if !ok {
return []IncentiveBound{}
}
return value.([]IncentiveBound)
}

// cacheReward() MUST be called before this function
func (self *Incentives) CurrentReward(currentHeight uint64) IncentiveRewardEntry {
value := self.rewardCache.CurrentReward(currentHeight)
if value == nil {
return IncentiveRewardEntry{
ActiveIncentives: []string{},
TotalStakedLiquidity: u256.Zero(),
}
}
return value.(IncentiveRewardEntry)
}
*/

func (self *Incentives) create(
creator std.Address,
Expand All @@ -112,69 +105,4 @@ func (self *Incentives) create(
self.byTime.Set(byTimeId, incentive)
self.byHeight.Set(byHeightId, incentive)
self.byCreator.Set(byCreatorId, incentive)
/*
startIncentiveBound := self.GetBound(uint64(incentive.startHeight))
startIncentiveBound = append(startIncentiveBound, IncentiveBound{
Incentive: *incentive,
IsEnter: true,
})
self.incentiveBound.Set(uint64(incentive.startHeight), startIncentiveBound)

endHeight := uint64(incentive.endHeight)
endIncentiveBound := self.GetBound(endHeight)
endIncentiveBound = append(endIncentiveBound, IncentiveBound{
Incentive: *incentive,
IsEnter: false,
})
self.incentiveBound.Set(endHeight, endIncentiveBound)
*/
}
/*
// endHeight MUST be less than or equal to the current block height
func (self *Incentives) cacheRewardPerLiquidityUnit(startHeight, endHeight uint64, stakedLiquidity *u256.Uint) {
currentReward := self.CurrentReward(startHeight)

self.incentiveBound.Iterate(startHeight, endHeight, func(key uint64, value interface{}) bool {
bound := value.([]IncentiveBound)
reward := IncentiveRewardEntry{
ActiveIncentives: make([]string, len(currentReward.ActiveIncentives)),
TotalStakedLiquidity: currentReward.TotalStakedLiquidity.Clone(),
}
for i, incentiveId := range currentReward.ActiveIncentives {
reward.ActiveIncentives[i] = incentiveId
}
for _, bound := range bound {
if bound.IsEnter {
reward.ActiveIncentives = append(reward.ActiveIncentives, bound.Incentive.incentiveId)
} else {
for i, incentiveId := range reward.ActiveIncentives {
if incentiveId == bound.Incentive.incentiveId {
reward.ActiveIncentives = append(reward.ActiveIncentives[:i], reward.ActiveIncentives[i+1:]...)
break
}
}
}
}
self.rewardCache.Set(key, reward)
currentReward = reward
return false
})
*self.lastRewardCacheHeight = endHeight
}

func (self *Incentives) updateRewardByLiquidityChange(currentHeight uint64, liquidity *u256.Uint) {
currentReward := self.CurrentReward(currentHeight)

entry := IncentiveRewardEntry{
ActiveIncentives: make([]string, len(currentReward.ActiveIncentives)),
TotalStakedLiquidity: liquidity.Clone(),
}

for i, incentiveId := range currentReward.ActiveIncentives {
entry.ActiveIncentives[i] = incentiveId
}

self.rewardCache.Set(currentHeight, entry)
}

*/
}
Loading

0 comments on commit 31641e1

Please sign in to comment.