Proposals
Any proposal to Meticulous' Governor 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 Meticulous protocol.
Submission
Anyone can submit a proposal to the Governor contract by calling propose()
. However, the proposer must
have a minimum amount of voting power to submit a proposal, which is determined by calling the getProposalThresholdVotes()
function:
function getProposalThresholdVotes() public view returns (uint256) {
return (MET.totalSupply() * proposalThreshold) / 100_000;
}
The proposer's MET balance is checked within the propose()
, queue()
, and execute()
functions. If, at any time, the proposer's MET balance falls below the proposal threshold, the proposal reverts. This approach ensures that proposers (or their delegators) maintain skin in the game, preventing them from benefiting from malicious proposals.
The current proposalThreshold is set to 0.4% of the total MET 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.
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 feasibility and impact.
The current votingDelay is set to 3 days
Proposal Activation
Anyone can activate a proposal by calling activate()
. Calling activate records 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 (MET.totalSupply() * highRiskQuorum) / 100_000;
}
Otherwise, quorum is calculated using the getQuorumVotes()
function:
function getQuorumVotes() public view returns (uint256) {
return (MET.totalSupply() * quorumPct) / 100_000;
}
The proposal will use this quorumVotes
for the remainder of proposal lifecycle.
The current quorumPct is set to 10% of MET supply
The current votingPeriod is set to 7 days from the time the proposal is activated.
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 MET 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 MET 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 MET balance
is below proposalThreshold
.