Decentralized protocol governance via GNS staking and voting.
Overview
Governance system enables GNS holders to stake for xGNS voting power, create proposals, and vote on protocol changes. For more details, check out docs.
Configuration
The governance.Config type defines the core governance parameters. All values can be modified through governance proposals. This type can be found in the config.gno file.
Field
Description
Default
VotingStartDelay
Delay before voting starts after proposal creation
1 day
VotingPeriod
Duration for collecting votes
7 days
VotingWeightSmoothingDuration
Period for averaging voting weight (prevents flash loans)
1 day
Quorum
Percentage of active xGNS required for proposal passage
50%
ProposalCreationThreshold
Minimum xGNS amount required to create a proposal
1,000 xGNS
ExecutionDelay
Waiting period after voting ends before execution
1 day
ExecutionWindow
Time window during which an approved proposal can be executed
Weight = 24hr average delegation (prevents flash loans)
Execution
A proposal is considered valid and executable when:
The voting period has ended
Total votes meet the quorum threshold (50% of xGNS total supply)
YES votes strictly exceed NO votes (ties do not pass)
The execution delay period (configured via ExecutionDelay default: 24 hours) has passed after voting ends
Within the execution window period (configured via ExecutionWindow default: 30 days)
ExecutionDelay and ExecutionWindow are configured through the governance.Config type.
Anyone can trigger execution once conditions are met
Technical Details
Vote Weight Calculation
1// 24-hour average prevents manipulation2snapshot1=getDelegationAt(proposalTime-24hr)3snapshot2=getDelegationAt(proposalTime)4voteWeight=(snapshot1+snapshot2)/2
Quorum Calculation
1activeXGNS=totalXGNS-launchpadXGNS2quorumAmount=activeXGNS*quorumPercent/100// quorumPercent defaults to 50
The quorum threshold is calculated based on the Quorum percentage (default: 50%) of the active xGNS supply at the time of proposal creation. A proposal passes only when total votes reach quorum and the accumulated YES votes strictly exceed the accumulated NO votes.
NewProposalCommunityPoolSpendData creates proposal data for a community pool spend proposal. Automatically generates the execution message for the token transfer.
Parameters:
tokenPath: path of the token to transfer
to: recipient address for the transfer
amount: amount of tokens to transfer
communityPoolPackagePath: package path of the community pool contract
Returns:
*ProposalData: proposal data configured for community pool spending
NewProposalExecutionData creates proposal data for a parameter change proposal. Each message in executions should be formatted as <pkgPath>*EXE*<function>*EXE*<params>, separated by *GOV* when there are multiple messages.
Parameters:
numToExecute: number of parameter changes to execute
executions: raw encoded execution string with parameter changes
Returns:
*ProposalData: proposal data configured for parameter changes
NewProposalScheduleStatus creates a new schedule status with calculated timestamps. This constructor takes the governance timing parameters and calculates all important timestamps for the proposal's lifecycle.
Parameters:
votingStartDelay: delay before voting starts (seconds)
votingPeriod: duration of voting period (seconds)
executionDelay: delay before execution can start (seconds)
executionWindow: window during which execution is allowed (seconds)
createdAt: timestamp when proposal was created
Returns:
*ProposalScheduleStatus: new schedule status with calculated times
NewProposalStatus creates a new proposal status with the specified configuration. This initializes all status components with the governance configuration and timing.
Parameters:
config: governance configuration to use
maxVotingWeight: maximum voting weight for this proposal
executable: whether this proposal type can be executed
createParameterHandlers initializes and configures all supported parameter handlers. This function defines all the parameter changes that can be executed through governance proposals. It covers configuration changes for various system components including pools, staking, fees, etc.
Returns:
*ParameterRegistry: fully configured registry with all supported handlers
1typeParameterHandlerinterface{2// Execute processes the parameters and applies the changes to the system.3// The `_ int, cur realm` discriminator pair forwards the governance proxy's4// realm value into the handler so any cross-realm calls inside the closure5// run under the proxy's identity (the only address with caller-allowlist6// permission against the targeted /r/ realms).7Execute(_int,rlmrealm,params[]string)error8}
ParameterHandler interface defines the contract for parameter execution handlers. Each handler is responsible for executing specific parameter changes in the system.
1typeParameterHandlerOptionsstruct{2pkgPathstring// Package path of the target contract3functionstring// Function name to be called4paramCountint// Expected number of parameters5handlerFuncfunc(_int,rlmrealm,_[]string)error// Function that executes the parameter change6paramValidators[]paramValidator// Optional per-parameter validators for proposal-time checks7}
ParameterHandlerOptions contains the configuration and execution logic for a parameter handler. This struct encapsulates all information needed to identify and execute a parameter change.
NOTE: handlerFunc uses `rlm realm` (rather than `cur realm`) as the realm parameter name. The v2 preprocessor reserves the `cur` name for the first realm-type parameter of top-level crossing function declarations and `t.Run` closures only; using it as the realm-parameter name on a multi-parameter struct-field function value trips a parser check ("only the first realm type argument of a crossing function may have name `cur`"). Naming it `rlm` keeps the lowering identical without the syntax constraint.
Execute validates parameter count and executes the handler function. This method ensures the correct number of parameters are provided before execution.
Parameters:
cur: governance proxy realm threaded in by the caller; forwarded to the wrapped closure so its cross-realm calls run under the proxy.
params: slice of string parameters to pass to the handler
Returns:
error: execution error if parameter count mismatch or handler execution fails
ParameterRegistry manages the collection of parameter handlers for governance execution. This registry allows proposals to execute parameter changes across different system contracts.
handler retrieves a parameter handler by package path and function name. This method is used during proposal execution to find the appropriate handler.
Parameters:
pkgPath: package path of the target contract
function: function name to be called
Returns:
ParameterHandler: the matching parameter handler
error: error if handler not found or casting fails
ParameterChangesInfos parses the execution messages and returns structured parameter change information. Each message is expected to be in format: pkgPath*EXE*function*EXE*params
Returns:
[]ParameterChangeInfo: slice of parsed parameter change information
error: validation error if any execution message is malformed
IsActive determines if the proposal is currently active (can be voted on or executed). A proposal is considered active if it's not rejected, expired, executed, or canceled.
IsPassedExecutableAt checks if the current time has passed the execution start time. When true, approved proposals can be executed (after execution delay).
IsPassedExpiredAt checks if the current time has passed the execution expiration time. When true, the proposal can no longer be executed and has expired.
StatusType determines the current status of the proposal based on timing, voting, and actions. This is the main status calculation method that considers all factors.
Parameters:
current: current timestamp to evaluate status at
Returns:
ProposalStatusType: current status of the proposal
IsPassed determines if the proposal has passed the voting requirements. A proposal passes when quorum is reached and "yes" votes strictly exceed "no" votes.