Skip to content

Commit

Permalink
GSW-1662 feat able to collect deposit gns by project and each single …
Browse files Browse the repository at this point in the history
…deposit (#347)

* fix: testcase wrong tier

* GSW-1662 feat: able to collect deposit gns by project and single deposit
  • Loading branch information
r3v4s authored Oct 8, 2024
1 parent ae41762 commit 85146cb
Show file tree
Hide file tree
Showing 3 changed files with 358 additions and 24 deletions.
161 changes: 158 additions & 3 deletions launchpad/launchpad_deposit.gno
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func DepositGns(
//
// returns collected gns amount
func CollectDepositGns() uint64 {
calculateDepositReward() // uncomment this line if L#208 `CollectReward` is removed
calculateDepositReward()

caller := std.PrevRealm().Addr()
userDeposits := depositsByUser[caller]
Expand Down Expand Up @@ -201,15 +201,170 @@ func CollectDepositGns() uint64 {
xgns.Burn(a2u(consts.LAUNCHPAD_ADDR), gnsToUser)
gns.Transfer(a2u(caller), gnsToUser)

// umcomment L#147 `calculateDepositReward()`
// CollectReward()
return gnsToUser // return accumulated gns amount being withdrawn
}

return 0
}

// CollectDepositGnsByProjectId collect deposited gns of certain project by caller
// - gns will be transfered from the `launchpad` to caller
// - launchpad's xgns will be burned
//
// returns collected gns amount
func CollectDepositGnsByProjectId(projectId string) uint64 {
project, exist := projects[projectId]
if !exist {
println("NO PROJECT FOR THIS ID", projectId)
return 0
}

caller := std.PrevRealm().Addr()
if _, exist := depositsByUserByProject[caller]; !exist {
println("NO DEPOSIT FOR THIS USER", caller)
return 0
}

depositIds, exist := depositsByUserByProject[caller][projectId]
if !exist {
println("NO DEPOSIT FOR THIS PROJECT", projectId, " FOR UESR", caller)
return 0
}

calculateDepositReward()

gnsToUser := uint64(0)
for _, depositId := range depositIds {
deposit := deposits[depositId]

// check active
project, exist := projects[deposit.projectId]
if !exist {
panic(ufmt.Sprintf("SHOULD_NOT_HAPPEN__project not found: %s", deposit.projectId))
}

tier := getTier(project, deposit.tier)
if checkTierActive(project, tier) {
println("CollectDepositGns()_STILL ACTIVE TIER", deposit.tier)
continue
}

// collected
if deposit.depositCollectHeight != 0 {
continue
}

deposit.depositCollectHeight = uint64(std.GetHeight())
deposit.depositCollectTime = uint64(time.Now().Unix())
deposits[deposit.id] = deposit

gnsToUser += deposit.amount

// update gov_staker contract's variable to calculate proejct's recipient's reward
gs.SetAmountByProjectWallet(project.recipient, deposit.amount, false) // subtract

// update tier
tier.depositAmount -= deposit.amount
tier.participant -= 1

// update project
project = setTier(project, deposit.tier, tier)
project.actualDepositAmount -= deposit.amount
project.actualParticipant -= 1
projects[deposit.projectId] = project

// emit event for each deposit
std.Emit(
"CollectDepositGns",
"m_prevRealm", prevRealm(),
"depositId", depositId,
"amount", ufmt.Sprintf("%d", deposit.amount),
)
}

if gnsToUser > 0 {
xgns.Burn(a2u(consts.LAUNCHPAD_ADDR), gnsToUser)
gns.Transfer(a2u(caller), gnsToUser)

return gnsToUser // return accumulated gns amount being withdrawn
}

return 0
}

// CollectDepositGnsByDepositId collect deposited gns of certain deposit
// - gns will be transfered from the `launchpad` to caller
// - launchpad's xgns will be burned
//
// returns collected gns amount
func CollectDepositGnsByDepositId(depositId string) uint64 {
deposit, exist := deposits[depositId]
if !exist {
println("DEPOSIT NOT FOUND", depositId)
return 0
}

project, exist := projects[deposit.projectId]
if !exist {
println("NO PROJECT FOR THIS ID", deposit.projectId)
return 0
}

caller := std.PrevRealm().Addr()
if _, exist := depositsByUserByProject[caller]; !exist {
println("NO DEPOSIT FOR THIS USER", caller)
return 0
}

calculateDepositReward()

// check active
tier := getTier(project, deposit.tier)
if checkTierActive(project, tier) {
println("CollectDepositGns()_STILL ACTIVE TIER", deposit.tier)
return 0
}

// collected
if deposit.depositCollectHeight != 0 {
return 0
}

deposit.depositCollectHeight = uint64(std.GetHeight())
deposit.depositCollectTime = uint64(time.Now().Unix())
deposits[deposit.id] = deposit

// update gov_staker contract's variable to calculate proejct's recipient's reward
gs.SetAmountByProjectWallet(project.recipient, deposit.amount, false) // subtract

// update tier
tier.depositAmount -= deposit.amount
tier.participant -= 1

// update project
project = setTier(project, deposit.tier, tier)
project.actualDepositAmount -= deposit.amount
project.actualParticipant -= 1
projects[deposit.projectId] = project

// emit event for each deposit
std.Emit(
"CollectDepositGns",
"m_prevRealm", prevRealm(),
"depositId", depositId,
"amount", ufmt.Sprintf("%d", deposit.amount),
)

if deposit.amount > 0 {
xgns.Burn(a2u(consts.LAUNCHPAD_ADDR), deposit.amount)
gns.Transfer(a2u(caller), deposit.amount)

return deposit.amount //
}

return 0
}

func getProjectIdFromTierId(tierId string) string {
// input: gno.land/r/gnoswap/gns:123:30
// output: gno.land/r/gnoswap/gns:123
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func TestCreateProject(t *testing.T) {
std.TestSkipHeights(1)
}

func TestDepositGnsToTier90(t *testing.T) {
func TestDepositGnsToTier180(t *testing.T) {
std.TestSetRealm(gsaRealm)
gns.Transfer(a2u(user01), uint64(1_000_000)) // to deposit
// transfer some grc20 tokens to bypass project condition
Expand All @@ -61,59 +61,59 @@ func TestDepositGnsToTier90(t *testing.T) {

// skip some blocks to make project active
std.TestSkipHeights(4)
depositId := DepositGns("gno.land/r/onbloc/obl:124:90", uint64(1_000_000))
shouldEQ(t, depositId, `gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`)
depositId := DepositGns("gno.land/r/onbloc/obl:124:180", uint64(1_000_000))
shouldEQ(t, depositId, `gno.land/r/onbloc/obl:124:180:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`)
std.TestSkipHeights(1)
}

func TestCollectRewardByDepositId(t *testing.T) {
std.TestSetRealm(user01Realm)

t.Run("claim reward before 7 days(for 90day tier's init reward)", func(t *testing.T) {
reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`)
t.Run("claim reward before 14 days(for 180day tier's init reward)", func(t *testing.T) {
reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:180:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`)
shouldEQ(t, reward, uint64(0))
std.TestSkipHeights(1)
println()
})

t.Run("claim reward before 7 days(for 90day tier's init reward)", func(t *testing.T) {
t.Run("claim reward before 14 days(for 180day tier's init reward)", func(t *testing.T) {
std.TestSkipHeights(123)
reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`)
reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:180:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`)
shouldEQ(t, reward, uint64(0))
std.TestSkipHeights(1)
println()
})

t.Run("claim after 7 days", func(t *testing.T) {
std.TestSkipHeights(int64(TIMESTAMP_7DAYS) / 2)
reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`)
shouldEQ(t, reward, uint64(15562035))
t.Run("claim after 14 days", func(t *testing.T) {
std.TestSkipHeights(int64(TIMESTAMP_14DAYS) / 2)
reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:180:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`)
shouldEQ(t, reward, uint64(54455786))
println()
})

t.Run("no more claim in same block", func(t *testing.T) {
reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`)
reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:180:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`)
shouldEQ(t, reward, uint64(0))
println()
})

t.Run("wait 1 more block, then claim", func(t *testing.T) {
std.TestSkipHeights(1)
reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`)
shouldEQ(t, reward, uint64(51))
reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:180:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`)
shouldEQ(t, reward, uint64(90))
println()
})

t.Run("90day tier is over", func(t *testing.T) {
std.TestSkipHeights(int64(TIMESTAMP_90DAYS) / 2)
reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`)
shouldEQ(t, reward, uint64(184437911))
t.Run("180day tier is over", func(t *testing.T) {
std.TestSkipHeights(int64(TIMESTAMP_180DAYS) / 2)
reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:180:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`)
shouldEQ(t, reward, uint64(645544122))
println()
})

t.Run("more block after 90 days", func(t *testing.T) {
std.TestSkipHeights(int64(TIMESTAMP_90DAYS) / 2)
reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:90:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`)
t.Run("more block after 180 days", func(t *testing.T) {
std.TestSkipHeights(int64(TIMESTAMP_180DAYS) / 2)
reward := CollectRewardByDepositId(`gno.land/r/onbloc/obl:124:180:g1w4ek2u3sx9047h6lta047h6lta047h6lh0ssfv:129`)
shouldEQ(t, reward, uint64(0))
println()
})
Expand Down
Loading

0 comments on commit 85146cb

Please sign in to comment.