launchpad_reward.gno
2.95 Kb · 112 lines
1package launchpad
2
3import (
4 "chain"
5 "chain/runtime"
6 "errors"
7 "time"
8
9 gnsmath "gno.land/p/gnoswap/gnsmath"
10 "gno.land/p/gnoswap/utils"
11
12 "gno.land/r/gnoswap/common"
13 "gno.land/r/gnoswap/halt"
14 "gno.land/r/gnoswap/launchpad"
15)
16
17// CollectRewardByDepositId collects reward from a specific deposit.
18//
19// Parameters:
20// - depositID: ID of the deposit to collect from
21//
22// Returns amount of reward collected.
23// Only callable by deposit owner.
24func (lp *launchpadV1) CollectRewardByDepositId(_ int, rlm realm, depositID string) int64 {
25 if !rlm.IsCurrent() {
26 panic(errors.New(errSpoofedRealm))
27 }
28
29 halt.AssertIsNotHaltedWithdraw()
30
31 previousRealm := rlm.Previous()
32
33 caller := previousRealm.Address()
34 lp.assertIsDepositOwner(depositID, caller)
35
36 deposit := lp.mustGetDeposit(depositID)
37 targetProjectTierID := deposit.ProjectTierID()
38 currentHeight := runtime.ChainHeight()
39 currentTime := time.Now().Unix()
40
41 rewardTokenPath, rewardAmount, err := lp.collectDepositReward(0, rlm, deposit, currentHeight, currentTime)
42 if err != nil {
43 panic(err)
44 }
45
46 // Transfer reward token to depositor
47 if rewardAmount > 0 {
48 common.SafeGRC20Transfer(cross(rlm), rewardTokenPath, deposit.Depositor(), rewardAmount)
49 }
50
51 chain.Emit(
52 "CollectRewardByDepositId",
53 "prevAddr", caller.String(),
54 "prevRealm", previousRealm.PkgPath(),
55 "depositId", depositID,
56 "targetProjectTierId", targetProjectTierID,
57 "amount", utils.FormatInt(rewardAmount),
58 )
59
60 return rewardAmount
61}
62
63// collectDepositReward calculates and collects the reward for a deposit.
64func (lp *launchpadV1) collectDepositReward(_ int, rlm realm, deposit *launchpad.Deposit, currentHeight, currentTime int64) (string, int64, error) {
65 if currentTime <= 0 {
66 return "", 0, makeErrorWithDetails(errInvalidTime, "currentTime must be positive")
67 }
68
69 // Get project and tier data
70 project, err := lp.getProject(deposit.ProjectID())
71 if err != nil {
72 return "", 0, err
73 }
74
75 projectTier, err := getProjectTier(project, deposit.Tier())
76 if err != nil {
77 return "", 0, err
78 }
79
80 // Get reward manager
81 rewardManager, err := lp.getProjectTierRewardManager(projectTier.ID())
82 if err != nil {
83 return "", 0, err
84 }
85
86 // Update reward state before collection
87 err = updateRewardPerDepositX128(rewardManager, getTierCurrentDepositAmount(projectTier), currentTime)
88 if err != nil {
89 return "", 0, err
90 }
91
92 // Collect reward
93 rewardAmount, err := collectReward(rewardManager, deposit.ID(), currentTime)
94 if err != nil {
95 return "", 0, err
96 }
97
98 // Update total collected amount for the tier
99 if rewardAmount > 0 {
100 projectTier.SetTotalCollectedAmount(gnsmath.SafeAddInt64(projectTier.TotalCollectedAmount(), rewardAmount))
101 project.SetTier(deposit.Tier(), projectTier)
102
103 projects := lp.store.GetProjects()
104 if err := lp.store.SetProjects(0, rlm, projects); err != nil {
105 return "", 0, err
106 }
107 }
108
109 emitUpdateLaunchpadRewardAccumulation(projectTier.ID(), rewardManager, getTierCurrentDepositAmount(projectTier))
110
111 return project.TokenPath(), rewardAmount, nil
112}