Kind Realm (renderable)
Name v1
Namespace gnoswap / gov / governance
Exported functions n/a — Gnoland RPC unavailable (functions): rpc abci_query: HTTP 500
Module gno.land/r/gnoswap/gov/governance/v1
gno 0.9 governance_execute.gno gno
⧉
1 package governance 2 3 import ( 4 "chain" 5 "chain/runtime" 6 "errors" 7 "time" 8 Gnoland RPC unavailable (functions): rpc abci_query: HTTP 500
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 ufmt "gno.land/p/nt/ufmt/v0"
10 "gno.land/r/gnoswap/access/v1"
11
12 "gno.land/p/gnoswap/utils/v1"
13
14 "gno.land/r/gnoswap/common"
15 "gno.land/r/gnoswap/emission"
16 "gno.land/r/gnoswap/halt/v1"
17
18 "gno.land/r/gnoswap/gov/governance"
19 )
20
21 // Execute executes an approved proposal.
22 //
23 // Processes and implements governance decisions after successful voting.
24 // Enforces the configured execution delay and execution window.
25 // Anyone can trigger execution to ensure decentralization.
26 //
27 // Parameters:
28 // - _: Internal call discriminator; pass 0.
29 // - rlm: Propagated realm context; must be current for authorized governance state updates and is crossed into execution-dependent calls.
30 // - proposalID: ID of the proposal to execute
31 //
32 // Requirements:
33 // - Proposal must have passed (quorum and strict yes-over-no majority)
34 // - Quorum must be reached using the proposal's stored amount, derived from
35 // the total xGNS supply and configured quorum percentage at creation
36 // - Execution delay must have elapsed (1 day by default)
37 // - Must be within the execution window (30 days by default)
38 // - Proposal not already executed or cancelled
39 //
40 // Effects:
41 // - Executes proposal actions (parameter changes, treasury transfers)
42 // - Marks proposal as executed
43 // - Emits execution event
44 //
45 // Returns:
46 // - proposalID: ID of the executed proposal
47 //
48 // Callable by anyone once the proposal is executable.
49 func (gv *governanceV1) Execute(_ int , rlm realm, proposalID int64 ) int64 {
50 access.AssertIsRlmCurrent( 0 , rlm)
51
52 // Check if execution is allowed (system not halted for execution).
53 // Halt recovery proposals remain executable while governance is halted.
54 assertIsNotHaltedGovernanceForProposal(gv, proposalID)
55
56 // Get caller information and current blockchain state
57 prev := rlm.Previous()
58 caller := prev.Address()
59 currentHeight := runtime.ChainHeight()
60 currentAt := time.Now().Unix()
61
62 // Mint and distribute GNS tokens as part of the execution process
63 emission.MintAndDistributeGns(cross(rlm))
64
65 // Attempt to execute the proposal with current context
66 proposal, err := gv.executeProposal(
67 0 , rlm,
68 proposalID,
69 currentAt,
70 currentHeight,
71 caller,
72 )
73 if err != nil {
74 panic(err)
75 }
76 if err := gv.removeActiveProposal( 0 , rlm, proposal); err != nil {
77 panic(err)
78 }
79
80 // Emit execution event for tracking and auditing
81 chain.Emit(
82 "Execute" ,
83 "prevAddr" , prev.Address().String(),
84 "prevRealm" , prev.PkgPath(),
85 "proposalId" , utils.FormatInt(proposalID),
86 )
87
88 return proposal.ID()
89 }
90
91 // executeProposal handles core logic of proposal execution.
92 func (gv *governanceV1) executeProposal(
93 _ int , rlm realm,
94 proposalID int64 ,
95 executedAt int64 ,
96 executedHeight int64 ,
97 executedBy address,
98 ) (*governance.Proposal, error ) {
99 // Retrieve the proposal from storage
100 proposal, ok := gv.getProposal(proposalID)
101 if !ok {
102 return nil , errors.New(errDataNotFound)
103 }
104
105 // Text proposals cannot be executed (they are informational only)
106 if proposal.IsTextType() {
107 return nil , errors.New(errTextProposalNotExecutable)
108 }
109
110 proposalResolver := NewProposalResolver(proposal)
111
112 // Verify proposal is in executable state (timing and voting requirements met)
113 if !proposalResolver.IsExecutable(executedAt) {
114 return nil , errors.New(errProposalNotExecutable)
115 }
116
117 // Mark proposal as executed in its status
118 err := proposalResolver.execute(executedAt, executedHeight, executedBy)
119 if err != nil {
120 return nil , err
121 }
122
123 // Execute proposal based on its type
124 switch proposal.Type() {
125 case governance.CommunityPoolSpend:
126 // Execute community pool spending (token transfers)
127 err = executeCommunityPoolSpend( 0 , rlm, proposal, globalParameterRegistry, executedAt, executedHeight, executedBy)
128 if err != nil {
129 return nil , err
130 }
131 case governance.ParameterChange:
132 // Execute parameter changes (governance configuration updates)
133 err = executeParameterChange( 0 , rlm, proposal, globalParameterRegistry, executedAt, executedHeight, executedBy)
134 if err != nil {
135 return nil , err
136 }
137 }
138
139 return proposal, nil
140 }
141
142 // Cancel cancels a proposal in upcoming status.
143 //
144 // Allows proposers to withdraw their proposals before voting begins.
145 // Prevents accidental or malicious proposals from reaching vote.
146 // Safety mechanism for proposal errors or changed circumstances.
147 //
148 // Parameters:
149 // - _: Internal call discriminator; pass 0.
150 // - rlm: Propagated realm context; must be current for authorized governance state updates and is crossed into reward-distribution calls.
151 // - proposalID: ID of the proposal to cancel
152 //
153 // Requirements:
154 // - Must be called by original proposer
155 // - Proposal must be in "upcoming" status
156 // - Voting must not have started yet
157 // - Proposal not already cancelled or executed
158 //
159 // Effects:
160 // - Sets proposal status to "cancelled"
161 // - Prevents future voting or execution
162 // - Emits cancellation event
163 // - Frees up proposer's proposal slot
164 //
165 // Returns:
166 // - proposalID: ID of the cancelled proposal
167 //
168 // Only callable by original proposer before voting begins.
169 func (gv *governanceV1) Cancel(_ int , rlm realm, proposalID int64 ) int64 {
170 access.AssertIsRlmCurrent( 0 , rlm)
171
172 halt.AssertIsNotHaltedGovernance()
173
174 prev := rlm.Previous()
175 caller := prev.Address()
176 assertCallerIsProposer(gv, proposalID, caller)
177
178 // Get current blockchain state and caller information
179 currentHeight := runtime.ChainHeight()
180 currentAt := time.Now().Unix()
181
182 // Mint and distribute GNS tokens as part of the process
183 emission.MintAndDistributeGns(cross(rlm))
184
185 // Attempt to cancel the proposal
186 proposal, err := gv.cancel(proposalID, currentAt, currentHeight, caller)
187 if err != nil {
188 panic(err)
189 }
190 if err := gv.removeActiveProposal( 0 , rlm, proposal); err != nil {
191 panic(err)
192 }
193
194 // Emit cancellation event for tracking
195 chain.Emit(
196 "Cancel" ,
197 "prevAddr" , prev.Address().String(),
198 "prevRealm" , prev.PkgPath(),
199 "proposalId" , utils.FormatInt(proposalID),
200 )
201
202 return proposal.ID()
203 }
204
205 // RemoveInactiveProposalFromIndex removes one inactive proposal from the
206 // snapshot index without deleting its proposal or voting history.
207 // Parameters:
208 // - _: Internal call discriminator; pass 0.
209 // - rlm: Propagated realm context used for the authorized snapshot-index update.
210 // - proposalID: Identifier of the inactive proposal to remove from the snapshot index.
211 func (gv *governanceV1) RemoveInactiveProposalFromIndex(_ int , rlm realm, proposalID int64 ) {
212 access.AssertIsRlmCurrent( 0 , rlm)
213
214 halt.AssertIsNotHaltedGovernance()
215
216 proposal, exists := gv.getProposal(proposalID)
217 if !exists {
218 panic(makeErrorWithDetails(errProposalNotFound, ufmt.Sprintf( "proposalID: %d" , proposalID)))
219 }
220 if NewProposalResolver(proposal).IsActive(time.Now().Unix()) {
221 panic(makeErrorWithDetails(errInvalidInput, ufmt.Sprintf( "proposal %d is still active" , proposalID)))
222 }
223 if err := gv.removeActiveProposal( 0 , rlm, proposal); err != nil {
224 panic(err)
225 }
226
227 prev := rlm.Previous()
228 chain.Emit(
229 "RemoveInactiveProposalFromIndex" ,
230 "prevAddr" , prev.Address().String(),
231 "prevRealm" , prev.PkgPath(),
232 "proposalId" , utils.FormatInt(proposalID),
233 )
234 }
235
236 // cancel handles core logic of proposal cancellation.
237 // Validates proposal state and updates status to canceled.
238 func (gv *governanceV1) cancel(
239 proposalID, canceledAt, canceledHeight int64 ,
240 canceledBy address,
241 ) (proposal *governance.Proposal, err error ) {
242 // Retrieve the proposal from storage
243 proposal, ok := gv.getProposal(proposalID)
244 if !ok {
245 return nil , errors.New(errDataNotFound)
246 }
247
248 proposalResolver := NewProposalResolver(proposal)
249
250 // Attempt to cancel the proposal (this validates cancellation conditions)
251 err = proposalResolver.cancel(canceledAt, canceledHeight, canceledBy)
252 if err != nil {
253 return nil , err
254 }
255
256 return proposal, nil
257 }
258
259 // executeCommunityPoolSpend executes community pool spending proposals.
260 // Handles token transfers from community pool to specified recipients.
261 func executeCommunityPoolSpend(
262 _ int , rlm realm,
263 proposal *governance.Proposal,
264 parameterRegistry *ParameterRegistry,
265 executedAt int64 ,
266 executedHeight int64 ,
267 executedBy address,
268 ) error {
269 // Verify token registration for community pool spending
270 if proposal.IsCommunityPoolSpendType() {
271 common.MustRegistered(proposal.Data().CommunityPoolSpend().TokenPath())
272 }
273
274 // Execute all parameter changes defined in the proposal
275 dataResolver := NewProposalDataResolver(proposal.Data())
276 parameterChangesInfos, err := dataResolver.ParameterChangesInfos()
277 if err != nil {
278 return err
279 }
280 for _, parameterChangeInfo := range parameterChangesInfos {
281 // Get the appropriate handler for this parameter change
282 key := makeHandlerKey(parameterChangeInfo.PkgPath(), parameterChangeInfo.Function())
283 handler, err := parameterRegistry.Handler(key)
284 if err != nil {
285 return err
286 }
287
288 // Execute the parameter change with provided parameters
289 err = handler.Execute( 0 , rlm, parameterChangeInfo.Params())
290 if err != nil {
291 return err
292 }
293 }
294
295 return nil
296 }
297
298 // executeParameterChange executes parameter change proposals.
299 // Handles governance configuration updates and system parameter modifications.
300 func executeParameterChange(
301 _ int , rlm realm,
302 proposal *governance.Proposal,
303 parameterRegistry *ParameterRegistry,
304 executedAt int64 ,
305 executedHeight int64 ,
306 executedBy address,
307 ) error {
308 // Execute all parameter changes defined in the proposal
309 dataResolver := NewProposalDataResolver(proposal.Data())
310 parameterChangesInfos, err := dataResolver.ParameterChangesInfos()
311 if err != nil {
312 return err
313 }
314 for _, parameterChangeInfo := range parameterChangesInfos {
315 // Get the appropriate handler for this parameter change
316 key := makeHandlerKey(parameterChangeInfo.PkgPath(), parameterChangeInfo.Function())
317 handler, err := parameterRegistry.Handler(key)
318 if err != nil {
319 return err
320 }
321
322 // Execute the parameter change with provided parameters
323 err = handler.Execute( 0 , rlm, parameterChangeInfo.Params())
324 if err != nil {
325 return err
326 }
327 }
328
329 return nil
330 }
331