Proposal Lifecycle
Any proposal to Olympus' Governor Bravo follows this lifecycle:
- Proposal is submitted by calling
propose()
. Proposal review period begins. - Proposal is activated for voting by calling
activate()
. Proposal voting period begins. - Proposal is queued by calling
queue()
. Proposal is transfered to Timelock, and grace period begins. - Proposal is executed by calling
execute()
, upgrading Olympus protocol.
Proposal Submission
To submit a new proposal to On-chain Governance (OCG), submitters interact directly with Governor Bravo contract by calling propose() function. However, the following requirements must be met before submitting a proposal:
- Minimum voting power - proposer must hold, and maintain, at least proposalThreshold of the total gOHM supply at time of proposal submission.
- Code review - proposals must be added, tested and simulated in olympus-v3 repository. This process ensures that the proposal is secure and achieves the intended outcomes without putting the protocol at risk.
To learn more about how to submit proposals, visit Proposal Submission Framework page.
The current proposalThreshold is set to 0.017% of the total gOHM supply
Proposal Review
Calling propose()
sets the start block of the proposal votingDelay
number of days after current block. This delay is designed to give tokenholders time to review the proposal and its implications.
OCG's trustless nature is one of its greatest strengths, but it also presents a challenge: the inability to mandate specific frameworks or best practices at the smart contract level. As a result, tokenholders plays a central role in evaluating the proposed on-chain actions for intent. Tokenholders responsibilities include, but are not limited to:
- Verify proposal actions align with the protocol's goals,
- Intent: Ensure the proposal intent is clear, transparent and not malicious,
- Consensus: Ensure the proposal on-chain actions matches the consensus reached in the forums.
- Security Assurance: This phase is critical for safeguarding the protocol against malicious proposals.
- Community Engagement: Active community participation is vital in evaluating the proposal's feasibility and impact.
To address this challenge, Olympus uses forge-proposal-simulator, an open-source framework designed to structure proposals effectively and streamline the proposal verification process. On a high-level, this framework allows anyone to execute proposals in a forked environment and develop integration tests to examine the new system's behavior in a controlled sandbox.
Due to the importance of this framework in ensuring transparency and security, Emergency MS will veto any proposals not adopting it. This stance is based on the belief that omitting the framework could indicate an attempt to pass a harmful proposal by obfuscating its review process.
The current votingDelay is set to 3 days
Proposal Activation
Anyone can activate a proposal by calling activate()
. Calling activate records quorumVotes
on the proposal. If the proposal targets a high-risk module, the quorum is calculated using the getHighRiskQuorumVotes()
function:
function getHighRiskQuorumVotes() public view returns (uint256) {
return (gohm.totalSupply() * highRiskQuorum) / 100_000;
}
Otherwise, quorum is calculated using the getQuorumVotes()
function:
function getQuorumVotes() public view returns (uint256) {
return (gohm.totalSupply() * quorumPct) / 100_000;
}
The proposal will use this quorumVotes
for the remainder of proposal lifecycle.
The current quorumPct is set to 20% of gOHM supply
Also, if the proposal is not activated within the activationGracePeriod
days after proposal review, it will expire and can no longer be activated.
The current activationGracePeriod is set to 1 day
Proposal Voting
Olympus' implementation of Governor Bravo employs a pessimistic vote casting mechanism. This mechanism operates under the assumption that all governance proposals could potentially be malicious. Therefore, it consistently computes the most unfavorable voting supply at different timestamps for each participant. This mechanism is designed to prevent voters from altering their exposure level to the gOHM and influence the outcome of the vote. By doing so, it attempts to safeguard the voting process against strategies that manipulate voting power.
function castVoteInternal(
address voter,
uint256 proposalId,
uint8 support
) internal returns (uint256) {
// Checks...
// Get the user's votes at the start of the proposal and at the time of voting. Take the minimum.
uint256 originalVotes = gohm.getPriorVotes(voter, proposal.startBlock);
uint256 currentVotes = gohm.getPriorVotes(voter, block.number);
uint256 votes = currentVotes > originalVotes ? originalVotes : currentVotes;
// Effects...
}
Consider the following examples:
- Alice has 0 gOHM at time of
proposal.startBlock
and 100 gOHM when she votes.castVote()
will return 0 gOHM. - Jim has 100 gOHM at time of
proposal.startBlock
and 0 gOHM when he votes.castVote()
will return 0 gOHM. - Bob has 100 gOHM at time of
proposal.startBlock
and 100 gOHM when he votes.castVote()
will return 100 gOHM. - Robert has 50 gOHM at time of
proposal.startBlock
and 100 gOHM when he votes.castVote()
will return 50 gOHM.
At the end of the voting period, the contract checks proposal's state by checking two things:
- Quorum: Number of FOR votes at least
proposal.quorumVotes
(the proposal quorum set duringactivate()
) - Net votes: Percentage of FOR votes at least
approvalThresholdPct
(the majority approval threshold)
function getVoteOutcome(uint256 proposalId) public view returns (bool) {
Proposal storage proposal = proposals[proposalId];
if (proposal.forVotes == 0 && proposal.againstVotes == 0) {
return false;
} else if (
(proposal.forVotes * 100_000) / (proposal.forVotes + proposal.againstVotes) <
approvalThresholdPct ||
proposal.forVotes < proposal.quorumVotes
) {
return false;
}
return true;
}
If either quorum or net votes is not met, the proposal is automatically defeated.
The current votingPeriod is set to 7 days from the time the proposal is activated.
The current quorumPct is set to 20% of gOHM supply
The current approvalThresholdPct is set to 60%
Proposal Queuing
Anyone can activate a proposal by calling queue()
. Queueing a proposal prepares the proposal for execution by the Timelock contract in delay
days. The proposer's gOHM balance is again checked during queue()
. If the balance falls below proposalThreshold
, the proposal will fail.
The current delay is set to 1 day
Proposal Execution
Any can execute a proposal by calling execute()
. Executing a proposal triggers the Timelock contract to execute the proposal's actions. The proposer's gOHM balance is again checked during execute()
. If the balance falls below proposalThreshold
, the proposal will fail.
Also, if the proposal is not activated within the GRACE_PERIOD
days after proposal is queued, it will expire and can no longer be executed.
The current GRACE_PERIOD is set to 1 day
Canceling Proposal
The proposal can be canceled at any time (before execution) by the proposer. A proposer can be canceled by anyone only if the proposer's gOHM balance
is below proposalThreshold
.
Vetoing Proposal
The proposal can be vetoed any time (before execution) by the Veto Guardian. Once a proposal is vetoed, it fails forever.
The current Veto Guardian is set to Emergency MS
Emergency State
In the event that gOHM supply collapsed below MIN_GOHM_SUPPLY, Governor Bravo contract enters an emergency state. No
proposal can be submitted, activated, queued, or executed. The only action that can be taken is emergencyPropose()
which
can only be called by Veto Guardian. This function is used to propose a new proposal to address the emergency situation.
The current MIN_GOHM_SUPPLY is set to 1000 gOHM