Search Apps Documentation Source Content File Folder Download Copy Actions Download

proposal_status.gno

7.36 Kb ยท 241 lines
  1package v1
  2
  3import (
  4	"gno.land/r/gnoswap/gov/governance"
  5)
  6
  7type ProposalStatusResolver struct {
  8	*governance.ProposalStatus
  9	scheduleResolver     *ProposalScheduleStatusResolver
 10	actionStatusResolver *ProposalActionStatusResolver
 11	voteStatusResolver   *ProposalVoteStatusResolver
 12}
 13
 14func NewProposalStatusResolver(status *governance.ProposalStatus) *ProposalStatusResolver {
 15	return &ProposalStatusResolver{
 16		ProposalStatus:       status,
 17		scheduleResolver:     NewProposalScheduleStatusResolver(status.Schedule()),
 18		actionStatusResolver: NewProposalActionStatusResolver(status.ActionStatus()),
 19		voteStatusResolver:   NewProposalVoteStatusResolver(status.VoteStatus()),
 20	}
 21}
 22
 23// TotalVoteWeight returns the total weight of all votes cast.
 24//
 25// Returns:
 26//   - int64: total vote weight
 27func (p *ProposalStatusResolver) TotalVoteWeight() int64 {
 28	return p.voteStatusResolver.TotalVoteWeight()
 29}
 30
 31// StatusType determines the current status of the proposal based on timing, voting, and actions.
 32// This is the main status calculation method that considers all factors.
 33//
 34// Parameters:
 35//   - current: current timestamp to evaluate status at
 36//
 37// Returns:
 38//   - ProposalStatusType: current status of the proposal
 39func (p *ProposalStatusResolver) StatusType(current int64) governance.ProposalStatusType {
 40	actionStatus := p.ActionStatus()
 41
 42	// Check action-based statuses first (these override time-based statuses)
 43	if actionStatus.IsExecuted() {
 44		return governance.StatusExecuted
 45	}
 46
 47	if actionStatus.Canceled() {
 48		return governance.StatusCanceled
 49	}
 50
 51	// Check time-based statuses
 52	if !p.scheduleResolver.IsPassedActiveAt(current) {
 53		return governance.StatusUpcoming
 54	}
 55
 56	if !p.scheduleResolver.IsPassedVotingEndedAt(current) {
 57		return governance.StatusActive
 58	}
 59
 60	// Check voting outcome after voting period ends
 61	if p.voteStatusResolver.IsRejected() {
 62		return governance.StatusRejected
 63	}
 64
 65	// For passed proposals, check execution status
 66	if !p.ActionStatus().IsExecutable() || !p.scheduleResolver.IsPassedExecutableAt(current) {
 67		return governance.StatusPassed
 68	}
 69
 70	if !p.scheduleResolver.IsPassedExpiredAt(current) {
 71		return governance.StatusExecutable
 72	}
 73
 74	return governance.StatusExpired
 75}
 76
 77// IsUpcoming checks if the proposal is in upcoming status.
 78//
 79// Parameters:
 80//   - current: timestamp to check status at
 81//
 82// Returns:
 83//   - bool: true if proposal is upcoming
 84func (p *ProposalStatusResolver) IsUpcoming(current int64) bool {
 85	return p.StatusType(current) == governance.StatusUpcoming
 86}
 87
 88// IsActive checks if the proposal is in active voting status.
 89//
 90// Parameters:
 91//   - current: timestamp to check status at
 92//
 93// Returns:
 94//   - bool: true if proposal is active (voting period)
 95func (p *ProposalStatusResolver) IsActive(current int64) bool {
 96	return p.StatusType(current) == governance.StatusActive
 97}
 98
 99// IsPassed checks if the proposal has passed voting.
100//
101// Parameters:
102//   - current: timestamp to check status at
103//
104// Returns:
105//   - bool: true if proposal has passed
106func (p *ProposalStatusResolver) IsPassed(current int64) bool {
107	return p.StatusType(current) == governance.StatusPassed
108}
109
110// IsRejected checks if the proposal has been rejected by voting.
111//
112// Parameters:
113//   - current: timestamp to check status at
114//
115// Returns:
116//   - bool: true if proposal was rejected
117func (p *ProposalStatusResolver) IsRejected(current int64) bool {
118	return p.StatusType(current) == governance.StatusRejected
119}
120
121// IsExecutable checks if the proposal is in executable status.
122//
123// Parameters:
124//   - current: timestamp to check status at
125//
126// Returns:
127//   - bool: true if proposal can be executed
128func (p *ProposalStatusResolver) IsExecutable(current int64) bool {
129	return p.StatusType(current) == governance.StatusExecutable
130}
131
132// IsExpired checks if the proposal execution window has expired.
133//
134// Parameters:
135//   - current: timestamp to check status at
136//
137// Returns:
138//   - bool: true if proposal has expired
139func (p *ProposalStatusResolver) IsExpired(current int64) bool {
140	return p.StatusType(current) == governance.StatusExpired
141}
142
143// IsExecuted checks if the proposal has been executed.
144//
145// Parameters:
146//   - current: timestamp to check status at
147//
148// Returns:
149//   - bool: true if proposal has been executed
150func (p *ProposalStatusResolver) IsExecuted(current int64) bool {
151	return p.StatusType(current) == governance.StatusExecuted
152}
153
154// IsCanceled checks if the proposal has been canceled.
155//
156// Parameters:
157//   - current: timestamp to check status at
158//
159// Returns:
160//   - bool: true if proposal has been canceled
161func (p *ProposalStatusResolver) IsCanceled(current int64) bool {
162	return p.StatusType(current) == governance.StatusCanceled
163}
164
165// cancel marks the proposal as canceled with the provided details.
166// This delegates to the action status for actual cancellation logic.
167//
168// Parameters:
169//   - canceledAt: timestamp when proposal was canceled
170//   - canceledHeight: block height when proposal was canceled
171//   - canceledBy: address that canceled the proposal
172//
173// Returns:
174//   - error: cancellation error if operation fails
175func (p *ProposalStatusResolver) cancel(canceledAt int64, canceledHeight int64, canceledBy address) error {
176	return p.actionStatusResolver.cancel(canceledAt, canceledHeight, canceledBy)
177}
178
179// execute marks the proposal as executed with the provided details.
180// This delegates to the action status for actual execution logic.
181//
182// Parameters:
183//   - executedAt: timestamp when proposal was executed
184//   - executedHeight: block height when proposal was executed
185//   - executedBy: address that executed the proposal
186//
187// Returns:
188//   - error: execution error if operation fails
189func (p *ProposalStatusResolver) execute(executedAt int64, executedHeight int64, executedBy address) error {
190	return p.actionStatusResolver.Execute(executedAt, executedHeight, executedBy)
191}
192
193// vote records a vote on the proposal and updates vote tallies.
194// This delegates to the vote status for actual vote recording.
195//
196// Parameters:
197//   - votedYes: true for "yes" vote, false for "no" vote
198//   - weight: voting weight to apply
199//
200// Returns:
201//   - error: voting error if operation fails
202func (p *ProposalStatusResolver) vote(votedYes bool, weight int64) error {
203	if votedYes {
204		return p.voteStatusResolver.AddYesVoteWeight(weight)
205	}
206
207	return p.voteStatusResolver.AddNoVoteWeight(weight)
208}
209
210// NewProposalStatus creates a new proposal status with the specified configuration.
211// This initializes all status components with the governance configuration and timing.
212//
213// Parameters:
214//   - config: governance configuration to use
215//   - maxVotingWeight: maximum voting weight for this proposal
216//   - executable: whether this proposal type can be executed
217//   - createdAt: timestamp when proposal was created
218//
219// Returns:
220//   - *ProposalStatus: new proposal status instance
221func NewProposalStatus(
222	config governance.Config,
223	maxVotingWeight int64,
224	executable bool,
225	createdAt int64,
226) *governance.ProposalStatus {
227	schedule := NewProposalScheduleStatus(
228		config.VotingStartDelay,
229		config.VotingPeriod,
230		config.ExecutionDelay,
231		config.ExecutionWindow,
232		createdAt,
233	)
234	actionStatus := governance.NewProposalActionStatus(executable)
235
236	// Calculate the quorum amount based on the max voting weight and quorum percentage
237	quorumAmount := safeMulDiv(maxVotingWeight, config.Quorum, 100)
238	voteStatus := governance.NewProposalVoteStatus(maxVotingWeight, quorumAmount)
239
240	return governance.NewProposalStatusBy(schedule, actionStatus, voteStatus)
241}