Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

proposal_status.gno

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