Skip to main content

proposal_lifecycle

danger

DAOlympus governance has not been deployed yet. The following docs are provided for informational purposes only and are subject to change.

Proposal Lifecycle

Any proposal to DAOlympus' Governor Bravo follows this lifecycle:

  1. Proposal is submitted by calling propose(). Proposal review period begins.
  2. Proposal is activated for voting by calling activate(). Proposal voting period begins.
  3. Proposal is queued by calling queue(). Proposal is transfered to Timelock, and grace period begins.
  4. Proposal is executed by calling execute(), upgrading DAOlympus protocol.

proposal-timeline-diagram

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:

  1. Minimum voting power - proposer must hold, and maintain, at least proposalThreshold of the total gDAOHM supply at time of proposal submission.
  2. 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.

info

The current proposalThreshold is set to 0.017% of the total gDAOHM 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:

  1. Verify proposal actions align with the protocol's goals,
  2. Intent: Ensure the proposal intent is clear, transparent and not malicious,
  3. Consensus: Ensure the proposal on-chain actions matches the consensus reached in the forums.
  4. Security Assurance: This phase is critical for safeguarding the protocol against malicious proposals.
  5. Community Engagement: Active community participation is vital in evaluating the proposal's feasibility and impact.

To address this challenge, DAOlympus 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.

info

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.

info

The current quorumPct is set to 20% of gDAOHM supply

Also, if the proposal is not activated within the activationGracePeriod days after proposal review, it will expire and can no longer be activated.

info

The current activationGracePeriod is set to 1 day

Proposal Voting

DAOlympus' 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 gDAOHM 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 gDAOHM at time of proposal.startBlock and 100 gDAOHM when she votes. castVote() will return 0 gDAOHM.
  • Jim has 100 gDAOHM at time of proposal.startBlock and 0 gDAOHM when he votes. castVote() will return 0 gDAOHM.
  • Bob has 100 gDAOHM at time of proposal.startBlock and 100 gDAOHM when he votes. castVote() will return 100 gDAOHM.
  • Robert has 50 gDAOHM at time of proposal.startBlock and 100 gDAOHM when he votes. castVote() will return 50 gDAOHM.

At the end of the voting period, the contract checks proposal's state by checking two things:

  1. Quorum: Number of FOR votes at least proposal.quorumVotes (the proposal quorum set during activate())
  2. 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.

info

The current votingPeriod is set to 7 days from the time the proposal is activated.

info

The current quorumPct is set to 20% of gDAOHM supply

info

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 gDAOHM balance is again checked during queue(). If the balance falls below proposalThreshold, the proposal will fail.

info

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 gDAOHM 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.

info

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 gDAOHM 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.

info

The current Veto Guardian is set to Emergency MS

Emergency State

In the event that gDAOHM supply collapsed below MIN_GDAOHM_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.

info

The current MIN_GDAOHM_SUPPLY is set to 1000 gDAOHM