Skip to content

Commit

Permalink
Merge pull request #136 from gnoswap-labs/GSW-709-fix-collect-reward
Browse files Browse the repository at this point in the history
GSW-709 fix: CollectReward()
  • Loading branch information
notJoon authored Dec 17, 2023
2 parents 29bf15a + 89ba6f6 commit e76115f
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ func TestApiGetRewardsByAddress(t *testing.T) {
// test1 reward check
gra := ApiGetRewardByAddress(test1)
jsonStr := gjson.Parse(gra)

shouldEQ(t, jsonStr.Get("response.data.0.incentiveType").String(), "INTERNAL")
shouldEQ(t, jsonStr.Get("response.data.0.targetPoolPath").String(), "gno.land/r/demo/bar:gno.land/r/demo/qux:500")
shouldEQ(t, jsonStr.Get("response.data.0.rewardTokenPath").String(), INTERNAL_REWARD_TOKEN_PATH)
Expand All @@ -141,6 +142,18 @@ func TestApiGetRewardsByAddress(t *testing.T) {
shouldEQ(t, jsonStr.Get("response.data.0.targetPoolPath").String(), "gno.land/r/demo/bar:gno.land/r/demo/qux:500")
shouldEQ(t, jsonStr.Get("response.data.1.rewardTokenPath").String(), "gno.land/r/demo/obl")
shouldEQ(t, jsonStr.Get("response.data.1.rewardTokenAmount").Int(), 648)
}

func TestCollectReward(t *testing.T) {
std.TestSetOrigCaller(test1)

// before claim
gnsOld := gns.BalanceOf(a2u(test1))
shouldEQ(t, gnsOld, 499999999999500)

CollectReward(1) // GNFT tokenId
gnsNew := gns.BalanceOf(a2u(test1))
shouldEQ(t, gnsNew, 499999999999584)

}

Expand All @@ -153,8 +166,8 @@ func TestUnstakeToken(t *testing.T) {
shouldEQ(t, gnft.OwnerOf(tid(1)), test1)

// check reward
shouldEQ(t, gns.BalanceOf(a2u(test1)), 499999999999584) // internal
shouldEQ(t, obl.BalanceOf(a2u(test1)), 499980000000648) // external
shouldEQ(t, gns.BalanceOf(a2u(test1)), 499999999999668) // internal
shouldEQ(t, obl.BalanceOf(a2u(test1)), 499980000001296) // external
}

{
Expand All @@ -165,8 +178,8 @@ func TestUnstakeToken(t *testing.T) {
shouldEQ(t, gnft.OwnerOf(tid(2)), test1)

// check reward
shouldEQ(t, gns.BalanceOf(a2u(test1)), 500000000000133) // internal
shouldEQ(t, obl.BalanceOf(a2u(test1)), 499980000004891) // external
shouldEQ(t, gns.BalanceOf(a2u(test1)), 500000000000217) // internal
shouldEQ(t, obl.BalanceOf(a2u(test1)), 499980000005539) // external
}
}

Expand Down
34 changes: 32 additions & 2 deletions staker/reward_math.gno
Original file line number Diff line number Diff line change
@@ -1,11 +1,39 @@
package staker

import (
"std"

"gno.land/p/demo/ufmt"

pos "gno.land/r/demo/position"
)

type claimedReward struct {
rewardTokenPath string
rewardTokenAmount bigint
}

type userClaimedReward map[std.Address][]claimedReward // address -> claimedReward{}
var userClaimedRewards = make(userClaimedReward)

func userClaimedRewardAmount(address std.Address, rewardTokenPath string, rewardAmount bigint) bigint {
claimedRewards, ok := userClaimedRewards[address]
if !ok {
return rewardAmount
}

var claimableAmount bigint
for _, claimedReward := range claimedRewards {
if claimedReward.rewardTokenPath == rewardTokenPath {
claimableAmount = rewardAmount - claimedReward.rewardTokenAmount
claimedReward.rewardTokenAmount += claimableAmount
}
}

userClaimedRewards[address] = claimedRewards
return claimableAmount
}

func rewardMathComputeInternalRewardAmount(tokenId uint64, deposit Deposit) uint64 {
// r3v4_xxx: calculate amount of `GNS` to be minted by every block
// 1. get block creation time (5s for now)
Expand Down Expand Up @@ -51,7 +79,8 @@ func rewardMathComputeInternalRewardAmount(tokenId uint64, deposit Deposit) uint
// #1: to convert `listTierRatio()` return value to percentage
// #2: to convert `getRewardRatio()` return value to percentage

return uint64(finalReward)
claimableReward := userClaimedRewardAmount(deposit.owner, INTERNAL_REWARD_TOKEN_PATH, finalReward)
return uint64(claimableReward)
}

func rewardMathComputeExternalRewardAmount(tokenId uint64, deposit Deposit, incentive Incentive) uint64 {
Expand Down Expand Up @@ -104,7 +133,8 @@ func rewardMathComputeExternalRewardAmount(tokenId uint64, deposit Deposit, ince
// why do we need to divide by 100
// to convert `getRewardRatio()` return value to percentage

return uint64(finalReward)
claimableReward := userClaimedRewardAmount(deposit.owner, incentive.rewardToken, finalReward)
return uint64(claimableReward)
}

func getPoolTotalStakedLiquidity(poolPath string) bigint {
Expand Down
32 changes: 22 additions & 10 deletions staker/staker.gno
Original file line number Diff line number Diff line change
Expand Up @@ -128,18 +128,30 @@ func StakeToken(tokenId uint64) (string, bigint, bigint) {
func CollectReward(
tokenId uint64, // LP TokenID
) {
// check whether tokenId is staked or not
_, exist := deposits[tokenId]
deposit, exist := deposits[tokenId]
require(exist, ufmt.Sprintf("[STAKER] staker.gno__CollectReward() || tokenId(%d) not staked", tokenId))

// check tokenId owner
require(
gnft.OwnerOf(tid(tokenId)) == GetOrigCaller(),
ufmt.Sprintf(
"[STAKER] staker.gno__CollectReward() || only owner can collect reward__gnft.OwnerOf(tid(tokenId(%d)))(%s) == GetOrigCaller()(%s)",
tokenId, gnft.OwnerOf(tid(tokenId)), GetOrigCaller(),
),
)
require(PrevRealmAddr() == deposit.owner, ufmt.Sprintf("[STAKER] staker.gno__CollectReward() || only owner(%s) can collect reward from tokenId(%d), PrevRealmAddr()(%s)", deposit.owner, tokenId, PrevRealmAddr()))

// poolPath to collect reward
poolPath := pos.PositionGetPositionPoolKey(tokenId)

// get all external reward list for this pool
for _, incentiveId := range poolIncentives[poolPath] {
incentive := incentives[incentiveId]
externalReward := rewardMathComputeExternalRewardAmount(tokenId, deposit, incentive) // external reward

transferByRegisterCall(incentive.rewardToken, deposit.owner, uint64(externalReward))

incentive.rewardAmount -= externalReward
incentives[incentiveId] = incentive
}

// default `Internal` reward
internalGNS := rewardMathComputeInternalRewardAmount(tokenId, deposit)

// transfer it
gns.TransferFrom(a2u(INTERNAL_REWARD_ACCOUNT), a2u(deposit.owner), uint64(internalGNS))
}

func UnstakeToken(tokenId uint64) (string, bigint, bigint) {
Expand Down

0 comments on commit e76115f

Please sign in to comment.