Overview
The FolioGovernor contract provides on-chain governance for Folio instances. It extends OpenZeppelin’s Governor framework with dynamic proposal thresholds based on token supply.Key Features
- Dynamic Proposal Threshold: Percentage-based threshold that scales with supply
- Timelock Integration: All proposals execute through a timelock
- Quorum Control: Configurable quorum as percentage of supply
- Vote Delegation: Users can delegate voting power
- Simple Counting: For/Against/Abstain voting
Architecture
FolioGovernor extends multiple OpenZeppelin governor modules:FolioGovernor.sol
Initialization
IVotes
Voting token (typically StakingVault or Folio with voting enabled)
TimelockControllerUpgradeable
Timelock contract for proposal execution
uint48
Delay in seconds before voting starts after proposal
uint32
Duration in seconds that voting remains open
uint256
Percentage of supply required to propose (e.g., 0.01e18 = 1%)
uint256
Percentage of supply required for quorum (e.g., 0.04e18 = 4%)
FolioGovernor.sol
Governance Parameters
Proposal Threshold
The number of tokens required to create a proposal is dynamically calculated:FolioGovernor.sol
The threshold is calculated as a percentage of the previous block’s supply, preventing manipulation through same-block minting.
Quorum
Quorum is calculated using the same percentage-based approach:FolioGovernor.sol
uint256
E.g., 0.04e18 for 4% quorum requirement
uint256
default:"1e18"
Fixed at 1e18 for 18-decimal precision
Proposal Lifecycle
1. Create Proposal
Example Proposal
2. Voting Delay
After creation, there’s a delay before voting begins:This delay allows users to acquire tokens and delegate voting power before the vote starts.
3. Active Voting
During the voting period, token holders can vote:Cast Vote
4. Queue in Timelock
Successful proposals must be queued:Queue Proposal
5. Execute After Timelock
Once the timelock delay passes:Execute Proposal
Proposal States
Proposal States
state
Proposal created, waiting for voting delay
state
Voting is open
state
Vote passed, ready to be queued
state
In timelock, waiting for execution delay
state
Successfully executed
Voting Power
Token-Based Voting
Voting power comes from the voting token (IVotes):Check Voting Power
Voting power is snapshotted at the proposal creation block to prevent double-voting.
Delegation
Users can delegate their voting power:Delegate Votes
Timelock Integration
Execution Delay
All proposals execute through a timelock:Timelock Flow
Cancellation Rights
Timelock guardians can cancel malicious proposals:Guardian Cancel
Admin Functions
Governor settings can be updated via governance:Set Voting Delay
FolioGovernor.sol
Set Voting Period
FolioGovernor.sol
Set Proposal Threshold
FolioGovernor.sol
Update Quorum
FolioGovernor.sol
View Functions
Get Proposal State
FolioGovernor.sol
Check Voting
FolioGovernor.sol
Get Votes
FolioGovernor.sol
Events
event
Emitted when a new proposal is createdParameters:
proposalId- Unique proposal identifierproposer- Address that created the proposaltargets- Target contract addressesvalues- ETH values for callssignatures- Function signaturescalldatas- Encoded function callsstartBlock- Voting start blockendBlock- Voting end blockdescription- Proposal description
event
Emitted when a vote is castParameters:
voter- Address that votedproposalId- Proposal IDsupport- Vote type (0=Against, 1=For, 2=Abstain)weight- Voting power usedreason- Vote reason (if provided)
event
Emitted when proposal is queued in timelockParameters:
proposalId- Proposal IDeta- Earliest execution time
event
Emitted when proposal is executedParameters:
proposalId- Proposal ID
Error Handling
error
Thrown when trying to set proposal threshold above 100%