Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/reserve-protocol/reserve-index-dtf/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Reserve Folio uses a multi-role governance system designed to balance security, flexibility, and decentralization. The system supports timelocked execution while enabling responsive rebalancing.

Governance Architecture

Core Components

FolioGovernor

Time-based governor contract that controls Folio parameters through timelock delays.

TimelockController

Enforces delays on governance actions, giving users time to exit before changes take effect.

StakingVault

Holds staked tokens and issues voting power. The central voting token for all governance types.

GovernanceDeployer

Factory contract for deploying complete governance systems.

Governance Structure

Most Folios use a dual-governor system:
This separation allows slow, high-security decisions (changing fees, assets) to have longer delays while fast decisions (rebalancing) can respond more quickly.

FolioGovernor Contract

The canonical governor implementation for Reserve Folios.

Key Features

  • Dynamic Proposal Threshold: Based on percentage of total supply
  • Quorum Requirements: Configurable quorum fraction
  • Timelock Integration: All actions go through timelock
  • Voting Power: Derived from staked tokens

Initialization

function initialize(
    IVotes _token,                          // Voting token (StakingVault)
    TimelockControllerUpgradeable _timelock, // Timelock for execution
    uint48 _votingDelay,                    // {s} Delay before voting starts
    uint32 _votingPeriod,                   // {s} Duration of voting
    uint256 _proposalThreshold,             // e.g. 0.01e18 for 1%
    uint256 _quorumFraction                 // e.g. 0.01e18 for 1%
) external initializer
// Slow Governor (for admin actions)
slowGovernor.initialize(
    stakingVault,
    slowTimelock,
    2 days,      // 2 day voting delay
    7 days,      // 7 day voting period  
    0.01e18,     // 1% proposal threshold
    0.04e18      // 4% quorum
);

// Fast Governor (for rebalancing)
fastGovernor.initialize(
    stakingVault,
    fastTimelock,
    6 hours,     // 6 hour voting delay
    2 days,      // 2 day voting period
    0.01e18,     // 1% proposal threshold
    0.04e18      // 4% quorum
);

Proposal Threshold Calculation

The proposal threshold is dynamic based on token supply:
function proposalThreshold() public view returns (uint256) {
    uint256 threshold = super.proposalThreshold(); // D18{1} (percentage)
    uint256 pastSupply = Math.max(1, token().getPastTotalSupply(clock() - 1));
    
    // CEIL to ensure thresholds near 0% don't round to 0 tokens
    return (threshold * pastSupply + (1e18 - 1)) / 1e18;
}
If threshold is set to 1% and there are 1M voting tokens, proposers need 10,000 tokens.

Timelock Configuration

Timelocks enforce delays between proposal passing and execution.

Typical Timelock Delays

Governor TypeTypical DelayPurpose
Community Governor3-7 daysStakingVault parameter changes
Slow Folio Governor7-14 daysAsset changes, fee changes, core parameters
Fast Folio Governor1-3 daysStarting/ending rebalances
Timelock delays must be long enough for users to exit if they disagree with a proposal, but short enough to respond to market conditions.

Timelock Roles

OpenZeppelin TimelockController uses a role-based system:
  • PROPOSER_ROLE: Can queue operations (usually the Governor)
  • EXECUTOR_ROLE: Can execute operations (often set to address(0) for permissionless execution)
  • CANCELLER_ROLE: Can cancel operations (usually the Governor or admin)
  • ADMIN_ROLE: Can grant/revoke roles

StakingVault

The central voting token for all governance types.

Key Features

  • Staking: Users stake Folio shares to receive voting power
  • Multi-Reward: Can earn rewards in multiple tokens simultaneously
  • Unstaking Delay: Configurable delay to prevent governance attacks
  • Vote Delegation: Users can delegate voting power

Governance Rights

Only the StakingVault owner (usually Community Governor’s timelock) can:
  • Add/remove reward tokens
  • Set reward half-life parameters
  • Set unstaking delay
// Approve Folio shares
folio.approve(address(stakingVault), 1000e18);

// Stake to receive voting power
stakingVault.stake(1000e18);

// Delegate voting power (optional)
stakingVault.delegate(delegateAddress);

Creating Proposals

Proposals follow the standard OpenZeppelin Governor flow.
1

Prepare Proposal

Define the actions (targets, values, calldatas) and description.
2

Submit Proposal

Call propose() on the governor (requires meeting proposal threshold).
3

Voting Delay

Wait for voting delay to pass before voting begins.
4

Voting Period

Users vote For, Against, or Abstain during the voting period.
5

Queue in Timelock

If proposal passes, anyone can queue it in the timelock.
6

Timelock Delay

Wait for timelock delay to pass.
7

Execute

Anyone can execute the proposal after the delay.
// Prepare proposal parameters
address[] memory targets = new address[](1);
targets[0] = address(folio);

uint256[] memory values = new uint256[](1);
values[0] = 0;

bytes[] memory calldatas = new bytes[](1);
calldatas[0] = abi.encodeWithSelector(
    folio.setTVLFee.selector,
    0.002e18  // 0.2% annual fee
);

string memory description = "Reduce TVL fee to 0.2% annually";

// Submit proposal
slowGovernor.propose(
    targets,
    values,
    calldatas,
    description
);

Voting on Proposals

Token holders (stakers) vote on proposals:
// Vote on a proposal
// support: 0 = Against, 1 = For, 2 = Abstain
governor.castVote(proposalId, 1);

// Vote with reason
governor.castVoteWithReason(
    proposalId,
    1,
    "I support this proposal because..."
);

// Vote by signature (for meta-transactions)
governor.castVoteBySig(
    proposalId,
    support,
    v, r, s
);

Emergency Actions

Governance should prepare for emergency scenarios.

Deprecating a Folio

If a Folio is compromised or needs to be sunset:
// Callable only by DEFAULT_ADMIN_ROLE
folio.deprecateFolio();
Deprecated Folios cannot:
  • Be minted
  • Have auctions approved, opened, or bid on
But users CAN still redeem their shares.

Closing Dangerous Rebalances

If prices move outside approved ranges:
// AUCTION_LAUNCHER or REBALANCE_MANAGER should act quickly
folio.endRebalance();

Removing Compromised Assets

If a basket token becomes malicious:
// DEFAULT_ADMIN_ROLE can remove tokens
folio.removeFromBasket(token);
Users will have limited time to redeem before the token becomes inaccessible. Only remove tokens if they’re compromised.

Governance Best Practices

Slow Governor:
  • Use longer delays (7-14 days) for critical changes
  • Assets, fees, role changes, deprecation
Fast Governor:
  • Use shorter delays (1-3 days) for market-responsive actions
  • Starting/ending rebalances
Community Governor:
  • Medium delays (3-7 days) for staking parameters
  • Reward tokens, unstaking delays
  • 1-2% for active, engaged communities
  • 0.1-0.5% for larger, more distributed holdings
  • Monitor and adjust based on participation
  • Balance spam prevention with accessibility
  • 4-10% typical range
  • Higher for more contentious decisions
  • Lower for routine operations
  • Should be achievable but meaningful
  • Keep DEFAULT_ADMIN_ROLE on longest timelock
  • Use separate REBALANCE_MANAGER on faster timelock
  • AUCTION_LAUNCHER can be EOA/multisig for responsiveness
  • Monitor AUCTION_LAUNCHER behavior and revoke if malicious
  • Discuss proposals before submission
  • Provide clear rationale in descriptions
  • Give community time to analyze
  • Use off-chain voting for temperature checks
  • Document all governance decisions

Governance Security

Preventing Governance Attacks

1

Unstaking Delays

Set appropriate unstaking delays to prevent flash loan governance attacks:
stakingVault.setUnstakingDelay(3 days);
2

Proposal Thresholds

Ensure threshold is high enough to prevent spam but low enough for legitimate proposals.
3

Quorum Requirements

Set quorum high enough that proposals can’t pass with minimal participation.
4

Timelock Delays

Give users sufficient time to exit if they disagree with a proposal.

Monitoring and Response

Governance should actively monitor:
  • Unusual voting patterns
  • Large stake accumulations
  • Malicious proposals
  • AUCTION_LAUNCHER behavior during rebalances
  • Price movements during auctions
If AUCTION_LAUNCHER behaves maliciously, governance should immediately revoke the role and potentially end any ongoing rebalance.

Build docs developers (and LLMs) love