Kind Realm (renderable)
Name v1
Namespace gnoswap / launchpad
Exported functions 1
Module gno.land/r/gnoswap/launchpad/v1
gno 0.9 launchpad_withdraw.gno gno
⧉
1 package launchpad 2 3 import ( 4 "chain" 5 "chain/runtime" 6 "errors" 7 "time" 8 NewLaunchpadV1 (launchpadStore interface {GetDepositCounter func() *gno.land/r/gnoswap/launchpad.Counter; GetDeposits func() *gno.land/p/nt/bptree/v0.BPTree; GetProjectRecipients func() *gno.land/p/nt/bptree/v0.BPTree; GetProjectTierRewardManagers func() *gno.land/p/nt/bptree/v0.BPTree; GetProjects func() *gno.land/p/nt/bptree/v0.BPTree; GetTotalGNSStakedAmount func() int64; HasDepositCounterStoreKey func() bool; HasDepositsKey func() bool; HasProjectRecipientsKey func() bool; HasProjectTierRewardManagersKey func() bool; HasProjectsKey func() bool; HasTotalGNSStakedAmountKey func() bool; NextDepositID func() string; SetDepositCounter func(int, .uverse.realm, *gno.land/r/gnoswap/launchpad.Counter) .uverse.error; SetDeposits func(int, .uverse.realm, *gno.land/p/nt/bptree/v0.BPTree) .uverse.error; SetProjectRecipients func(int, .uverse.realm, *gno.land/p/nt/bptree/v0.BPTree) .uverse.error; SetProjectTierRewardManagers func(int, .uverse.realm, *gno.land/p/nt/bptree/v0.BPTree) .uverse.error; SetProjects func(int, .uverse.realm, *gno.land/p/nt/bptree/v0.BPTree) .uverse.error; SetTotalGNSStakedAmount func(int, .uverse.realm, int64) .uverse.error}) interface {CollectDepositGns func(int, .uverse.realm, string) (int64, .uverse.error); CollectEmissionReward func(int, .uverse.realm); CollectProtocolFee func(int, .uverse.realm); CollectProtocolFeeReward func(int, .uverse.realm, string); CollectRewardByDepositId func(int, .uverse.realm, string) int64; CreateProject func(int, .uverse.realm, string, string, .uverse.address, int64, string, string, int64, int64, int64, int64) string; DepositGns func(int, .uverse.realm, string, int64, string) string; GetCurrentDepositId func() int64; GetDeposit func(string) (gno.land/r/gnoswap/launchpad.Deposit, .uverse.error); GetDepositAmount func(string) (int64, .uverse.error); GetDepositCount func() int; GetDepositCreatedAt func(string) (int64, .uverse.error); GetDepositCreatedHeight func(string) (int64, .uverse.error); GetDepositEndTime func(string) (int64, .uverse.error); GetDepositProjectID func(string) (string, .uverse.error); GetDepositProjectTierID func(string) (string, .uverse.error); GetDepositTier func(string) (int64, .uverse.error); GetDepositWithdrawnHeight func(string) (int64, .uverse.error); GetDepositWithdrawnTime func(string) (int64, .uverse.error); GetProjectActiveStatus func(string) (bool, .uverse.error); GetProjectCondition func(string, string) (*gno.land/r/gnoswap/launchpad.ProjectCondition, .uverse.error); GetProjectCreatedAt func(string) (int64, .uverse.error); GetProjectCreatedHeight func(string) (int64, .uverse.error); GetProjectDepositAmount func(string) (int64, .uverse.error); GetProjectName func(string) (string, .uverse.error); GetProjectRecipient func(string) (.uverse.address, .uverse.error); GetProjectTier func(string, int64) (*gno.land/r/gnoswap/launchpad.ProjectTier, .uverse.error); GetProjectTierDistributeAmountPerSecondX128 func(string, int64) (*gno.land/p/gnoswap/uint256/v1.Uint, .uverse.error); GetProjectTierEndTime func(string, int64) (int64, .uverse.error); GetProjectTierRewardAccumulatedDistributeAmount func(string) (int64, .uverse.error); GetProjectTierRewardAccumulatedRewardPerDepositX128 func(string) (*gno.land/p/gnoswap/uint256/v1.Uint, .uverse.error); GetProjectTierRewardAccumulatedTime func(string) (int64, .uverse.error); GetProjectTierRewardClaimableDuration func(string) (int64, .uverse.error); GetProjectTierRewardDistributeAmountPerSecondX128 func(string) (*gno.land/p/gnoswap/uint256/v1.Uint, .uverse.error); GetProjectTierRewardDistributeEndTime func(string) (int64, .uverse.error); GetProjectTierRewardDistributeStartTime func(string) (int64, .uverse.error); GetProjectTierRewardManager func(string) (*gno.land/r/gnoswap/launchpad.RewardManager, .uverse.error); GetProjectTierRewardManagerCount func() int; GetProjectTierRewardTotalClaimedAmount func(string) (int64, .uverse.error); GetProjectTierRewardTotalDistributeAmount func(string) (int64, .uverse.error); GetProjectTierRewards func(string, int64) *gno.land/p/nt/bptree/rotree/v0.ReadOnlyTree; GetProjectTierStartTime func(string, int64) (int64, .uverse.error); GetProjectTierTotalCollectedAmount func(string, int64) (int64, .uverse.error); GetProjectTierTotalDepositAmount func(string, int64) (int64, .uverse.error); GetProjectTierTotalDepositCount func(string, int64) (int64, .uverse.error); GetProjectTierTotalDistributeAmount func(string, int64) (int64, .uverse.error); GetProjectTierTotalWithdrawAmount func(string, int64) (int64, .uverse.error); GetProjectTierTotalWithdrawCount func(string, int64) (int64, .uverse.error); GetProjectTiersRatios func(string) (map[int64]int64, .uverse.error); GetProjectTokenPath func(string) (string, .uverse.error); GetProjects func() *gno.land/p/nt/bptree/rotree/v0.ReadOnlyTree; GetRewardState func(string, string) (*gno.land/r/gnoswap/launchpad.RewardState, .uverse.error); GetTotalGNSStakedAmount func() int64; Render func(string) string; TransferLeftFromProjectByAdmin func(int, .uverse.realm, string, .uverse.address) int64}
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
This realm does not provide renderable output (vm/qrender → NoRenderDeclError).
View on gnoweb ↗ vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.
9 gnsmath "gno.land/p/gnoswap/gnsmath/v1"
10 "gno.land/p/gnoswap/utils/v1"
11 ufmt "gno.land/p/nt/ufmt/v0"
12
13 "gno.land/r/gnoswap/common"
14 "gno.land/r/gnoswap/emission"
15 "gno.land/r/gnoswap/halt/v1"
16 "gno.land/r/gnoswap/launchpad"
17
18 gov_staker "gno.land/r/gnoswap/gov/staker"
19 )
20
21 // CollectDepositGns withdraws the original GNS deposit after the lock period
22 // ends. Before returning the principal, it settles any claimable project-token
23 // reward for the deposit.
24 //
25 // Parameters:
26 // - _: Noncrossing implementation-call discriminator; pass 0.
27 // - rlm: Current realm context forwarded by the launchpad proxy; invalid contexts return an error.
28 // - depositID: ID of the deposit to withdraw.
29 //
30 // Returns:
31 // - amount: original GNS deposit amount returned to the depositor, in base units.
32 // - err: non-nil for a spoofed-realm call; other withdrawal failures panic before returning.
33 //
34 // Only callable by deposit owner when the current time is strictly after the
35 // selected tier's end time.
36 func (lp *launchpadV1) CollectDepositGns(_ int , rlm realm, depositID string ) ( int64 , error ) {
37 if !rlm.IsCurrent() {
38 return 0 , errors.New(errSpoofedRealm)
39 }
40
41 halt.AssertIsNotHaltedWithdraw()
42
43 previousRealm := rlm.Previous()
44
45 caller := previousRealm.Address()
46 lp.assertIsDepositOwner(depositID, caller)
47
48 emission.MintAndDistributeGns(cross(rlm))
49
50 deposit := lp.mustGetDeposit(depositID)
51 targetProjectTierID := deposit.ProjectTierID()
52 currentHeight := runtime.ChainHeight()
53 currentTime := time.Now().Unix()
54
55 // Collect reward before withdrawal
56 rewardTokenPath, rewardAmount, err := lp.collectDepositReward( 0 , rlm, deposit, currentHeight, currentTime)
57 if err != nil {
58 panic(err)
59 }
60
61 beforeTotalGNSStakedAmount := lp.store.GetTotalGNSStakedAmount()
62
63 recipient, withdrawalAmount, err := lp.withdrawDeposit( 0 , rlm, deposit, runtime.ChainHeight(), currentTime)
64 if err != nil {
65 panic(err.Error())
66 }
67
68 afterTotalGNSStakedAmount := gnsmath.SafeSubInt64(beforeTotalGNSStakedAmount, withdrawalAmount)
69 if err := lp.store.SetTotalGNSStakedAmount( 0 , rlm, afterTotalGNSStakedAmount); err != nil {
70 panic(err.Error())
71 }
72
73 // Cross-realm governance update before token transfers
74 unStakeGovernance( 0 , rlm, recipient, withdrawalAmount)
75
76 // Transfer reward token to depositor
77 if rewardAmount > 0 {
78 common.SafeGRC20Transfer( 0 , rlm, rewardTokenPath, deposit.Depositor(), rewardAmount)
79
80 chain.Emit(
81 "CollectRewardByDepositId" ,
82 "prevAddr" , caller.String(),
83 "prevRealm" , previousRealm.PkgPath(),
84 "depositId" , depositID,
85 "targetProjectTierId" , targetProjectTierID,
86 "amount" , utils.FormatInt(rewardAmount),
87 )
88 }
89
90 // Transfer the original GNS deposit back to the depositor
91 common.SafeGRC20Transfer( 0 , rlm, GNS_TOKEN_KEY, deposit.Depositor(), withdrawalAmount)
92
93 chain.Emit(
94 "CollectDepositGns" ,
95 "prevAddr" , caller.String(),
96 "prevRealm" , previousRealm.PkgPath(),
97 "depositId" , depositID,
98 "targetProjectTierId" , targetProjectTierID,
99 "amount" , utils.FormatInt(withdrawalAmount),
100 "totalGNSStakedAmount" , utils.FormatInt(afterTotalGNSStakedAmount),
101 "recipient" , recipient.String(),
102 )
103
104 return withdrawalAmount, nil
105 }
106
107 // withdrawDeposit withdraws a deposit and updates the reward manager.
108 func (lp *launchpadV1) withdrawDeposit(_ int , rlm realm, deposit launchpad.Deposit, currentHeight, currentTime int64 ) (address, int64 , error ) {
109 // Input validation
110 if currentTime <= 0 {
111 return "" , 0 , makeErrorWithDetails(errInvalidTime, "currentTime must be positive" )
112 }
113
114 // State validation
115 if deposit.IsWithdrawn() {
116 return "" , 0 , makeErrorWithDetails(errAlreadyCollected, ufmt.Sprintf( "(%s)" , deposit.ID()))
117 }
118
119 if !deposit.IsEnded(currentTime) {
120 return "" , 0 , makeErrorWithDetails(errNotYetEndedProject, ufmt.Sprintf( "(%s)" , deposit.ID()))
121 }
122
123 // Get project and tier information
124 project, err := lp.getProject(deposit.ProjectID())
125 if err != nil {
126 return "" , 0 , err
127 }
128
129 projectTier, err := getProjectTier(project, deposit.Tier())
130 if err != nil {
131 return "" , 0 , err
132 }
133
134 // Get reward manager and update rewards before withdrawal
135 rewardManager, err := lp.getProjectTierRewardManager(projectTier.ID())
136 if err != nil {
137 return "" , 0 , err
138 }
139
140 // Update rewards with current deposit amount
141 err = updateRewardPerDepositX128(rewardManager, getTierCurrentDepositAmount(projectTier), currentTime)
142 if err != nil {
143 return "" , 0 , err
144 }
145
146 // Process withdrawal from project tier
147 withdrawToTier(projectTier, deposit)
148 project.SetTier(deposit.Tier(), projectTier)
149
150 // Finalize withdrawal
151 deposit, withdrawalAmount := withdrawDeposit(deposit, currentHeight, currentTime)
152
153 // Remove the reward state and its reserved active claim after withdrawal.
154 if err := removeRewardState(rewardManager, deposit.ID()); err != nil {
155 return "" , 0 , err
156 }
157
158 // Persist the updated value; the caller's deposit value is unchanged.
159 deposits := lp.store.GetDeposits()
160 deposits.Set(deposit.ID(), deposit)
161
162 // Save the modified state back
163 if err := lp.store.SetDeposits( 0 , rlm, deposits); err != nil {
164 return "" , 0 , err
165 }
166
167 emitUpdateLaunchpadRewardAccumulation(projectTier.ID(), rewardManager, getTierCurrentDepositAmount(projectTier))
168
169 return project.Recipient(), withdrawalAmount, nil
170 }
171
172 // unStakeGovernance removes the staked amount from governance system
173 func unStakeGovernance(_ int , rlm realm, recipient address, withdrawalAmount int64 ) {
174 gov_staker.SetAmountByProjectWallet(cross(rlm), recipient, withdrawalAmount, false )
175 }
176