21
21
latestProposalByProposer = make(map[std.Address]uint64) // proposer -> proposalId
22
22
)
23
23
24
+ const (
25
+ GOV_SPLIT = "*GOV*"
26
+ EXE_SPLIT = "*EXE*"
27
+ )
28
+
24
29
// ProposeText creates a new text proposal with the given data
25
30
// It checks if the proposer is eligible to create a proposal and if they don't have an active proposal.
26
31
// Returns the proposal ID
@@ -187,7 +192,7 @@ func ProposeParameterChange(
187
192
}
188
193
189
194
// check if numToExecute is a valid number
190
- splitGov := strings.Split(executions, "*GOV*" )
195
+ splitGov := strings.Split(executions, GOV_SPLIT )
191
196
if uint64(len(splitGov)) != numToExecute {
192
197
panic(addDetailToError(
193
198
errInvalidInput,
@@ -197,7 +202,7 @@ func ProposeParameterChange(
197
202
198
203
// check if each execution is valid
199
204
for _, gov := range splitGov {
200
- splitExe := strings.Split(gov, "*EXE*" )
205
+ splitExe := strings.Split(gov, EXE_SPLIT )
201
206
if len(splitExe) != 3 {
202
207
panic(addDetailToError(
203
208
errInvalidInput,
@@ -259,63 +264,104 @@ func ProposeParameterChange(
259
264
260
265
func updateProposalsState() {
261
266
now := uint64(time.Now().Unix())
267
+
262
268
for id, proposal := range proposals {
263
- config := GetConfigVersion(proposal.ConfigVersion)
264
-
265
- // check if proposal is in a state that needs to be updated
266
- // - created
267
- // - not canceled
268
- // - not executed
269
-
270
- // proposal is in voting period
271
- if proposal.ExecutionState.Created &&
272
- !proposal.ExecutionState.Canceled &&
273
- !proposal.ExecutionState.Executed {
274
-
275
- if proposal.ExecutionState.Upcoming && // was upcoming
276
- now >= (proposal.ExecutionState.CreatedAt+config.VotingStartDelay) && // voting started
277
- now <= (proposal.ExecutionState.CreatedAt+config.VotingStartDelay+config.VotingPeriod) { // voting not ended
278
- proposal.ExecutionState.Upcoming = false
279
- proposal.ExecutionState.Active = true
280
- }
281
- }
269
+ updater := newProposalStateUpdater(&proposal, now)
282
270
283
- // proposal voting ended, check if passed or rejected
284
- if now > (proposal.ExecutionState.CreatedAt+config.VotingStartDelay+config.VotingPeriod) &&
285
- (proposal.ExecutionState.Passed == false && proposal.ExecutionState.Rejected == false && proposal.ExecutionState.Canceled == false) {
286
- yeaUint := proposal.Yea.Uint64()
287
- nayUint := proposal.Nay.Uint64()
288
- quorumUint := proposal.QuorumAmount
289
-
290
- if yeaUint >= quorumUint && yeaUint > nayUint {
291
- proposal.ExecutionState.Passed = true
292
- proposal.ExecutionState.PassedAt = now
293
- } else {
294
- proposal.ExecutionState.Rejected = true
295
- proposal.ExecutionState.RejectedAt = now
296
- }
297
- proposal.ExecutionState.Upcoming = false
298
- proposal.ExecutionState.Active = false
299
- }
271
+ updater.updateVotingState()
272
+ updater.updateVotingResult()
273
+ updater.updateExecutionState()
300
274
301
- // TODO (@notJoon): refactor this.
302
- // (non text) proposal passed but not executed until executing window ends
303
- if proposal.ProposalType != Text && // isn't text type ≈ can be executed
304
- proposal.ExecutionState.Passed && // passed
305
- !proposal.ExecutionState.Executed && // not executed
306
- !proposal.ExecutionState.Expired { // not expired
307
-
308
- votingEnd := proposal.ExecutionState.CreatedAt + config.VotingStartDelay + config.VotingPeriod
309
- windowStart := votingEnd + config.ExecutionDelay
310
- windowEnd := windowStart + config.ExecutionWindow
311
-
312
- if now >= windowEnd { // execution window ended
313
- proposal.ExecutionState.Expired = true
314
- proposal.ExecutionState.ExpiredAt = now
315
- }
316
- }
275
+ proposals[id] = *updater.proposal
276
+ }
277
+ }
278
+
279
+ type proposalStateUpdater struct {
280
+ proposal *ProposalInfo
281
+ config Config
282
+ now uint64
283
+ }
284
+
285
+ func newProposalStateUpdater(proposal *ProposalInfo, now uint64) *proposalStateUpdater {
286
+ return &proposalStateUpdater{
287
+ proposal: proposal,
288
+ config: GetConfigVersion(proposal.ConfigVersion),
289
+ now: now,
290
+ }
291
+ }
292
+
293
+ func (u *proposalStateUpdater) shouldUpdate() bool {
294
+ return u.proposal.ExecutionState.Created &&
295
+ !u.proposal.ExecutionState.Canceled &&
296
+ !u.proposal.ExecutionState.Executed
297
+ }
298
+
299
+ func (u *proposalStateUpdater) getVotingTimes() (start, end uint64) {
300
+ start = u.proposal.ExecutionState.CreatedAt + u.config.VotingStartDelay
301
+ end = start + u.config.VotingPeriod
302
+ return
303
+ }
304
+
305
+ func (u *proposalStateUpdater) getExecutionTimes() (start, end uint64) {
306
+ _, votingEnd := u.getVotingTimes()
307
+ start = votingEnd + u.config.ExecutionDelay
308
+ end = start + u.config.ExecutionWindow
309
+ return
310
+ }
311
+
312
+ func (u *proposalStateUpdater) updateVotingState() {
313
+ if !u.shouldUpdate() {
314
+ return
315
+ }
316
+
317
+ votingStart, votingEnd := u.getVotingTimes()
318
+ isVotingPeriod := u.now >= votingStart && u.now <= votingEnd
319
+
320
+ if u.proposal.ExecutionState.Upcoming && isVotingPeriod {
321
+ u.proposal.ExecutionState.Upcoming = false
322
+ u.proposal.ExecutionState.Active = true
323
+ }
324
+ }
325
+
326
+ func (u *proposalStateUpdater) updateVotingResult() {
327
+ _, votingEnd := u.getVotingTimes()
328
+
329
+ hasNoResult := !u.proposal.ExecutionState.Passed &&
330
+ !u.proposal.ExecutionState.Rejected &&
331
+ !u.proposal.ExecutionState.Canceled
332
+
333
+ if u.now <= votingEnd || !hasNoResult {
334
+ return
335
+ }
336
+
337
+ yeaUint := u.proposal.Yea.Uint64()
338
+ nayUint := u.proposal.Nay.Uint64()
339
+
340
+ if yeaUint >= u.proposal.QuorumAmount && yeaUint > nayUint {
341
+ u.proposal.ExecutionState.Passed = true
342
+ u.proposal.ExecutionState.PassedAt = u.now
343
+ } else {
344
+ u.proposal.ExecutionState.Rejected = true
345
+ u.proposal.ExecutionState.RejectedAt = u.now
346
+ }
347
+
348
+ u.proposal.ExecutionState.Upcoming = false
349
+ u.proposal.ExecutionState.Active = false
350
+ }
351
+
352
+ func (u *proposalStateUpdater) updateExecutionState() {
353
+ if u.proposal.ProposalType == Text ||
354
+ !u.proposal.ExecutionState.Passed ||
355
+ u.proposal.ExecutionState.Executed ||
356
+ u.proposal.ExecutionState.Expired {
357
+ return
358
+ }
359
+
360
+ _, executionEnd := u.getExecutionTimes()
317
361
318
- proposals[id] = proposal
362
+ if u.now >= executionEnd {
363
+ u.proposal.ExecutionState.Expired = true
364
+ u.proposal.ExecutionState.ExpiredAt = u.now
319
365
}
320
366
}
321
367
0 commit comments