Search Apps Documentation Source Content File Folder Download Copy Actions Download

launchpad_deposit.gno

5.05 Kb ยท 195 lines
  1package v1
  2
  3import (
  4	"chain"
  5	"chain/runtime"
  6	"time"
  7
  8	"gno.land/r/gnoswap/access"
  9	"gno.land/r/gnoswap/common"
 10	"gno.land/r/gnoswap/gns"
 11	gov_staker "gno.land/r/gnoswap/gov/staker"
 12	"gno.land/r/gnoswap/gov/xgns"
 13	"gno.land/r/gnoswap/halt"
 14	"gno.land/r/gnoswap/launchpad"
 15	"gno.land/r/gnoswap/referral"
 16)
 17
 18// DepositGns deposits GNS tokens to a launchpad project tier.
 19//
 20// Parameters:
 21//   - targetProjectTierID: format "{projectId}:{tierType}"
 22//   - depositAmount: amount of GNS to deposit
 23//   - referrer: referral address (optional)
 24//
 25// Returns deposit ID.
 26func (lp *launchpadV1) DepositGns(targetProjectTierID string, depositAmount int64, referrer string) string {
 27	halt.AssertIsNotHaltedLaunchpad()
 28
 29	previousRealm := runtime.PreviousRealm()
 30	access.AssertIsUser(previousRealm)
 31
 32	assertIsValidAmount(depositAmount)
 33
 34	projectID, tierDuration := parseProjectTierID(targetProjectTierID)
 35	caller := previousRealm.Address()
 36
 37	project, err := lp.getProject(projectID)
 38	if err != nil {
 39		panic(err.Error())
 40	}
 41
 42	deposit, rewardState, isFirstDeposit, distributeAmountPerSecondX128, err := lp.depositGns(
 43		project,
 44		tierDuration,
 45		depositAmount,
 46		caller,
 47	)
 48	if err != nil {
 49		panic(err.Error())
 50	}
 51
 52	actualReferrer, success := registerReferral(referrer, caller)
 53	if !success {
 54		actualReferrer = referral.GetReferral(runtime.PreviousRealm().Address().String())
 55	}
 56
 57	if isFirstDeposit {
 58		chain.Emit(
 59			"FirstDepositForProjectTier",
 60			"prevAddr", previousRealm.Address().String(),
 61			"prevRealm", previousRealm.PkgPath(),
 62			"targetProjectTierId", targetProjectTierID,
 63			"amount", formatInt(depositAmount),
 64			"depositId", deposit.ID(),
 65			"claimableTime", formatInt(rewardState.ClaimableTime()),
 66			"tierAmountPerSecondX128", distributeAmountPerSecondX128,
 67		)
 68	}
 69
 70	chain.Emit(
 71		"DepositGns",
 72		"prevAddr", previousRealm.Address().String(),
 73		"prevRealm", previousRealm.PkgPath(),
 74		"targetProjectTierId", targetProjectTierID,
 75		"amount", formatInt(depositAmount),
 76		"depositId", deposit.ID(),
 77		"claimableTime", formatInt(rewardState.ClaimableTime()),
 78		"referrer", actualReferrer,
 79	)
 80
 81	launchpadAddress := runtime.CurrentRealm().Address()
 82
 83	// stake governance token to the project
 84	err = lp.stakeGovernance(project.Recipient(), depositAmount, launchpadAddress, caller)
 85	if err != nil {
 86		panic(err.Error())
 87	}
 88
 89	return deposit.ID()
 90}
 91
 92// depositGns deposits GNS to a project tier.
 93func (lp *launchpadV1) depositGns(
 94	project *launchpad.Project,
 95	tierDuration int64,
 96	depositAmount int64,
 97	callerAddress address,
 98) (*launchpad.Deposit, *launchpad.RewardState, bool, string, error) {
 99	balanceOfFn := func(tokenPath string, caller address) int64 {
100		if tokenPath == GOV_XGNS_PATH {
101			return xgns.BalanceOf(caller)
102		}
103
104		return common.BalanceOf(tokenPath, caller)
105	}
106
107	err := checkProjectConditions(project, callerAddress, balanceOfFn)
108	if err != nil {
109		return nil, nil, false, "", err
110	}
111
112	projectTier, err := getProjectTier(project, tierDuration)
113	if err != nil {
114		return nil, nil, false, "", err
115	}
116
117	currentTime := time.Now().Unix()
118	currentHeight := runtime.ChainHeight()
119
120	if !projectTier.IsActivated(currentTime) {
121		return nil, nil, false, "", makeErrorWithDetails(errInactiveProject, project.ID())
122	}
123
124	depositID := lp.nextDepositID()
125	deposit := launchpad.NewDeposit(
126		depositID,
127		project.ID(),
128		tierDuration,
129		callerAddress,
130		depositAmount,
131		currentHeight,
132		currentTime,
133		projectTier.EndTime(),
134	)
135
136	// Get state and store deposit
137	deposits := lp.store.GetDeposits()
138	deposits.Set(depositID, deposit)
139
140	rewardManager, err := lp.getProjectTierRewardManager(projectTier.ID())
141	if err != nil {
142		return nil, nil, false, "", err
143	}
144
145	isFirstDeposit := !isRewardManagerInitialized(rewardManager)
146
147	// update rewards before adding deposit to reward manager
148	err = updateRewardPerDepositX128(rewardManager, getTierCurrentDepositAmount(projectTier), currentHeight, currentTime)
149	if err != nil {
150		return nil, nil, false, "", err
151	}
152
153	// add reward state to reward manager
154	rewardState := addRewardStateByDeposit(rewardManager, deposit)
155
156	// update tier data after adding reward state to reward manager
157	depositToTier(projectTier, deposit)
158	project.SetTier(tierDuration, projectTier)
159
160	// Save the modified state back
161	if err := lp.store.SetDeposits(deposits); err != nil {
162		return nil, nil, false, "", err
163	}
164
165	return deposit,
166		rewardState,
167		isFirstDeposit,
168		rewardManager.DistributeAmountPerSecondX128().ToString(),
169		nil
170}
171
172// registerReferral registers a referral for a caller.
173func registerReferral(referrer string, callerAddress address) (string, bool) {
174	success := referral.TryRegister(cross, callerAddress, referrer)
175	actualReferrer := referrer
176	if !success {
177		actualReferrer = referral.GetReferral(callerAddress.String())
178	}
179
180	return actualReferrer, success
181}
182
183// stakeGovernance stakes governance token to the project.
184func (lp *launchpadV1) stakeGovernance(recipient address, depositAmount int64, launchpadAddress address, callerAddress address) error {
185	gov_staker.SetAmountByProjectWallet(cross, recipient, depositAmount, true)
186
187	gns.TransferFrom(
188		cross,
189		callerAddress,
190		launchpadAddress,
191		depositAmount,
192	)
193
194	return nil
195}