Skip to content

Commit

Permalink
Merge pull request #131 from gnoswap-labs/GSW-698-allow-certain-addre…
Browse files Browse the repository at this point in the history
…ss-to-execute-end-external-only-when-time-is-over

GSW-698 feat: allow certain address to execute end external only when time is over
  • Loading branch information
notJoon authored Dec 15, 2023
2 parents e1b59c8 + 51fe620 commit 468e509
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 27 deletions.
13 changes: 13 additions & 0 deletions staker/_TEST_init_test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,19 @@ func shouldPanic(t *testing.T, f func()) {
f()
}

func shouldPanicWithMsg(t *testing.T, f func(), msg string) {
defer func() {
if r := recover(); r == nil {
t.Errorf("The code did not panic")
} else {
if r != msg {
t.Errorf("excepted panic(%v), got(%v)", msg, r)
}
}
}()
f()
}

func ugnotBalanceOf(addr std.Address) uint64 {
testBanker := std.GetBanker(std.BankerTypeRealmIssue)

Expand Down
6 changes: 3 additions & 3 deletions staker/_TEST_staker_collect_reward_test.gnoa
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func TestApiGetRewardsByAddress(t *testing.T) {
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)
shouldEQ(t, jsonStr.Get("response.data.0.rewardTokenAmount").Int(), 252)
shouldEQ(t, jsonStr.Get("response.data.0.rewardTokenAmount").Int(), 84)

shouldEQ(t, jsonStr.Get("response.data.1.incentiveType").String(), "EXTERNAL")
shouldEQ(t, jsonStr.Get("response.data.0.targetPoolPath").String(), "gno.land/r/demo/bar:gno.land/r/demo/qux:500")
Expand All @@ -153,7 +153,7 @@ func TestUnstakeToken(t *testing.T) {
shouldEQ(t, gnft.OwnerOf(tid(1)), test1)

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

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

// check reward
shouldEQ(t, gns.BalanceOf(a2u(test1)), 500000000001402) // internal
shouldEQ(t, gns.BalanceOf(a2u(test1)), 500000000000133) // internal
shouldEQ(t, obl.BalanceOf(a2u(test1)), 499980000004891) // external
}
}
Expand Down
6 changes: 3 additions & 3 deletions staker/_TEST_staker_one_external_native_test.gnoa
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ func TestApiGetRewardsByAddress(t *testing.T) {
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/foo:500")
shouldEQ(t, jsonStr.Get("response.data.0.rewardTokenPath").String(), INTERNAL_REWARD_TOKEN_PATH)
shouldEQ(t, jsonStr.Get("response.data.0.rewardTokenAmount").Int(), 252)
shouldEQ(t, jsonStr.Get("response.data.0.rewardTokenAmount").Int(), 84)

shouldEQ(t, jsonStr.Get("response.data.1.incentiveType").String(), "EXTERNAL")
shouldEQ(t, jsonStr.Get("response.data.0.targetPoolPath").String(), "gno.land/r/demo/bar:gno.land/r/demo/foo:500")
Expand All @@ -162,7 +162,7 @@ func TestUnstakeToken(t *testing.T) {
shouldEQ(t, gnft.OwnerOf(tid(1)), test1)

// check reward
shouldEQ(t, gns.BalanceOf(a2u(test1)), 499999999999752) // internal
shouldEQ(t, gns.BalanceOf(a2u(test1)), 499999999999584) // internal
shouldEQ(t, wugnot.BalanceOf(a2u(test1)), 324) // external
}

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

// check reward
shouldEQ(t, gns.BalanceOf(a2u(test1)), 500000000001402) // internal
shouldEQ(t, gns.BalanceOf(a2u(test1)), 500000000000133) // internal
shouldEQ(t, wugnot.BalanceOf(a2u(test1)), 2445) // external
}
}
Expand Down
6 changes: 3 additions & 3 deletions staker/_TEST_staker_one_external_test.gnoa
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func TestApiGetRewardsByAddress(t *testing.T) {
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/foo:500")
shouldEQ(t, jsonStr.Get("response.data.0.rewardTokenPath").String(), INTERNAL_REWARD_TOKEN_PATH)
shouldEQ(t, jsonStr.Get("response.data.0.rewardTokenAmount").Int(), 252)
shouldEQ(t, jsonStr.Get("response.data.0.rewardTokenAmount").Int(), 84)

shouldEQ(t, jsonStr.Get("response.data.1.incentiveType").String(), "EXTERNAL")
shouldEQ(t, jsonStr.Get("response.data.0.targetPoolPath").String(), "gno.land/r/demo/bar:gno.land/r/demo/foo:500")
Expand Down Expand Up @@ -178,7 +178,7 @@ func TestUnstakeToken(t *testing.T) {
shouldEQ(t, gnft.OwnerOf(tid(1)), test1)

// check reward
shouldEQ(t, gns.BalanceOf(a2u(test1)), 499999999999752) // internal
shouldEQ(t, gns.BalanceOf(a2u(test1)), 499999999999584) // internal
shouldEQ(t, obl.BalanceOf(a2u(test1)), 499990000000324) // external
}

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

// check reward
shouldEQ(t, gns.BalanceOf(a2u(test1)), 500000000001402) // internal
shouldEQ(t, gns.BalanceOf(a2u(test1)), 500000000000133) // internal
shouldEQ(t, obl.BalanceOf(a2u(test1)), 499990000002445) // external
}
}
Expand Down
20 changes: 15 additions & 5 deletions staker/_TEST_staker_one_increase_external_test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func TestApiGetRewardsByAddress(t *testing.T) {
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/foo:500")
shouldEQ(t, jsonStr.Get("response.data.0.rewardTokenPath").String(), INTERNAL_REWARD_TOKEN_PATH)
shouldEQ(t, jsonStr.Get("response.data.0.rewardTokenAmount").Int(), 252)
shouldEQ(t, jsonStr.Get("response.data.0.rewardTokenAmount").Int(), 84)

shouldEQ(t, jsonStr.Get("response.data.1.incentiveType").String(), "EXTERNAL")
shouldEQ(t, jsonStr.Get("response.data.0.targetPoolPath").String(), "gno.land/r/demo/bar:gno.land/r/demo/foo:500")
Expand All @@ -151,7 +151,7 @@ func TestUnstakeToken(t *testing.T) {
shouldEQ(t, gnft.OwnerOf(tid(1)), test1)

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

Expand All @@ -163,15 +163,25 @@ func TestUnstakeToken(t *testing.T) {
shouldEQ(t, gnft.OwnerOf(tid(2)), test1)

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

func TestEndExternalIncentive(t *testing.T) {
shouldEQ(t, len(incentives), 1)

std.TestSetOrigCaller(test1)
std.TestSkipHeights(9999999)
EndExternalIncentive(GetOrigCaller().String(), "gno.land/r/demo/bar:gno.land/r/demo/foo:500", "gno.land/r/demo/obl") // use same parameter as CreateExternalIncentive()

// incentive time isn't over yet
shouldPanicWithMsg(t, func() {
EndExternalIncentive(string(test1), "gno.land/r/demo/bar:gno.land/r/demo/foo:500", "gno.land/r/demo/obl")
}, "[STAKER] staker.gno__EndExternalIncentive() || cannot end incentive before endTimestamp(1242343920), current(1234567975)")

std.TestSkipHeights(1555188) // not yet, one more should be good to end incentive
std.TestSkipHeights(1)

EndExternalIncentive(string(test1), "gno.land/r/demo/bar:gno.land/r/demo/foo:500", "gno.land/r/demo/obl") // use same parameter as CreateExternalIncentive()
std.TestSkipHeights(1)

shouldEQ(t, len(incentives), 0)
Expand Down
39 changes: 26 additions & 13 deletions staker/staker.gno
Original file line number Diff line number Diff line change
Expand Up @@ -185,20 +185,33 @@ func EndExternalIncentive(refundee, targetPoolPath, rewardToken string) {
require(exist, ufmt.Sprintf("[STAKER] staker.gno__EndExternalIncentive() || cannot end non existent incentive(%s)", incentiveId))
require(GetTimestamp() >= incentive.endTimestamp, ufmt.Sprintf("[STAKER] staker.gno__EndExternalIncentive() || cannot end incentive before endTimestamp(%d), current(%d)", incentive.endTimestamp, GetTimestamp()))

require(incentive.refundee == std.GetOrigCaller(), "[STAKER] staker.gno__EndExternalIncentive() || only refundee can end incentive")

refund := incentive.rewardAmount

poolExternalReward := balanceOfByRegisterCall(incentive.rewardToken, GetOrigPkgAddr())
require(poolExternalReward >= refund, ufmt.Sprintf("[STAKER] staker.gno__EndExternalIncentive() || not enough poolExternalReward(%d) to refund(%d)", poolExternalReward, refund))

transferByRegisterCall(incentive.rewardToken, incentive.refundee, uint64(refund))

incentives = deleteFromIncentives(incentives, incentiveId)
for i, v := range poolIncentives[targetPoolPath] {
if v == incentiveId {
poolIncentives[targetPoolPath] = append(poolIncentives[targetPoolPath][:i], poolIncentives[targetPoolPath][i+1:]...)
// when incentive is ended
// 1. admin can end incentive without refund
// 2. refundee can end incentive with refund
switch GetOrigCaller() {
case std.Address("g16kvq0mra3atvr07lkdwc2x6jqmna8a4kt0e85d"): // ADMIN
// admin can end incentive without refund
incentives = deleteFromIncentives(incentives, incentiveId)
for i, v := range poolIncentives[targetPoolPath] {
if v == incentiveId {
poolIncentives[targetPoolPath] = append(poolIncentives[targetPoolPath][:i], poolIncentives[targetPoolPath][i+1:]...)
}
}
case incentive.refundee:
// refundee can end incentive with refund
refund := incentive.rewardAmount
poolLeftExternalRewardAmount := balanceOfByRegisterCall(incentive.rewardToken, GetOrigPkgAddr())
require(poolLeftExternalRewardAmount >= refund, ufmt.Sprintf("[STAKER] staker.gno__EndExternalIncentive() || not enough poolLeftExternalRewardAmount(%s_%d) to refund(%d)", incentive.rewardToken, poolLeftExternalRewardAmount, refund))
transferByRegisterCall(incentive.rewardToken, incentive.refundee, uint64(refund))

incentives = deleteFromIncentives(incentives, incentiveId)
for i, v := range poolIncentives[targetPoolPath] {
if v == incentiveId {
poolIncentives[targetPoolPath] = append(poolIncentives[targetPoolPath][:i], poolIncentives[targetPoolPath][i+1:]...)
}
}
default:
require(false, ufmt.Sprintf("[STAKER] staker.gno__EndExternalIncentive() || only refundee or admin can end incentive"))
}
}

Expand Down

0 comments on commit 468e509

Please sign in to comment.