Skip to content

Decentralized governance system with proposal lifecycle, three-way voting, checkpoint-based delegation and timelock execution delay

Notifications You must be signed in to change notification settings

Kazopl/governance-dao-governor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

18 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

DAO Governance System

A production-grade, Bravo-style governance system built with Foundry. Implements decentralized proposal creation, voting, timelock execution, and token-based voting power delegation.

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                           GOVERNANCE SYSTEM                                 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                             β”‚
β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                          β”‚
β”‚    β”‚  Governance     │◄───────►│    Governor     β”‚                          β”‚
β”‚    β”‚  Token (GOV)    β”‚         β”‚   (Bravo-style) β”‚                          β”‚
β”‚    β”‚                 β”‚         β”‚                 β”‚                          β”‚
β”‚    β”‚ β€’ ERC-20        β”‚         β”‚ β€’ Proposals     β”‚                          β”‚
β”‚    β”‚ β€’ Delegation    β”‚         β”‚ β€’ Voting        β”‚                          β”‚
β”‚    β”‚ β€’ Checkpoints   β”‚         β”‚ β€’ Quorum        β”‚                          β”‚
β”‚    β”‚ β€’ Permit        β”‚         β”‚ β€’ Thresholds    β”‚                          β”‚
β”‚    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                          β”‚
β”‚                                         β”‚                                   β”‚
β”‚                                         β”‚ queue/execute                     β”‚
β”‚                                         β–Ό                                   β”‚
β”‚                                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                          β”‚
β”‚                                β”‚    Timelock     β”‚                          β”‚
β”‚                                β”‚   Controller    β”‚                          β”‚
β”‚                                β”‚                 β”‚                          β”‚
β”‚                                β”‚ β€’ Min Delay     β”‚                          β”‚
β”‚                                β”‚ β€’ Batch Ops     β”‚                          β”‚
β”‚                                β”‚ β€’ Role-Based    β”‚                          β”‚
β”‚                                β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜                          β”‚
β”‚                                         β”‚                                   β”‚
β”‚                                         β”‚ execute                           β”‚
β”‚                                         β–Ό                                   β”‚
β”‚                                β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                          β”‚
β”‚                                β”‚  Target         β”‚                          β”‚
β”‚                                β”‚  Contracts      β”‚                          β”‚
β”‚                                β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                          β”‚
β”‚                                                                             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Proposal Lifecycle

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ PENDING  │───►│  ACTIVE  │───►│SUCCEEDED │───►│  QUEUED  │───►│ EXECUTED β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
     β”‚               β”‚               β”‚
     β”‚               β”‚               └──────────────┐
     β”‚               β”‚                              β”‚
     β–Ό               β–Ό                              β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ CANCELED β”‚    β”‚ DEFEATED β”‚                  β”‚ EXPIRED  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Timeline:
β”œβ”€ Voting Delay ─┼─────── Voting Period ───────┼── Timelock Delay ───
     (1 day)              (1 week)                   (2 days)

Features

Governance Token

  • ERC-20 with voting delegation
  • Checkpoint-based historical voting power
  • EIP-2612 permit for gasless approvals
  • Capped supply (100M tokens max)

Governor (Bravo-style)

  • Proposal creation with threshold requirement
  • Three-way voting: For, Against, Abstain
  • Configurable voting delay and period
  • Quorum requirements
  • EIP-712 vote signatures

Timelock Controller

  • Configurable execution delay
  • Batch operation support
  • Operation predecessor dependencies
  • Role-based access control

Configuration

Parameter Value Description
Voting Delay 7,200 blocks (~1 day) Time before voting starts
Voting Period 50,400 blocks (~1 week) Duration of voting
Proposal Threshold 100,000 GOV (1%) Minimum tokens to propose
Quorum 4% Minimum participation
Timelock Delay 2 days Execution delay

Roles

Proposer

  • Can create proposals (requires threshold tokens)
  • Can cancel own proposals (while pending)

Voter

  • Delegates voting power (to self or others)
  • Casts votes on active proposals
  • Weight based on historical balance at snapshot

Executor

  • Governor contract (through timelock)
  • Executes successful proposals after delay

Guardian (Optional)

  • Can cancel malicious proposals
  • Emergency veto power

Installation

git clone https://github.com/Kazopl/governance-dao-governor.git
cd governance-dao-governor
forge install

Build

forge build

Test

# Run all tests
forge test

# Run with verbosity
forge test -vvv

# Run specific test file
forge test --match-path test/unit/Governor.t.sol

# Run fuzz tests
forge test --match-path test/fuzz/

# Run invariant tests
forge test --match-path test/invariant/

Deployment

Configure Environment

cp .env.example .env
# Edit .env with your values:
# PRIVATE_KEY=your_private_key
# SEPOLIA_RPC_URL=your_rpc_url
# ETHERSCAN_API_KEY=your_api_key

Deploy to Sepolia

forge script script/DeployGovernance.s.sol:DeployGovernance \
    --rpc-url $SEPOLIA_RPC_URL \
    --broadcast \
    --verify

Usage Examples

Create a Proposal

address[] memory targets = new address[](1);
targets[0] = targetContract;

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

bytes[] memory calldatas = new bytes[](1);
calldatas[0] = abi.encodeWithSignature("setValue(uint256)", 42);

uint256 proposalId = governor.propose(
    targets,
    values,
    calldatas,
    "Set value to 42"
);

Cast a Vote

// Vote For (1), Against (0), or Abstain (2)
governor.castVoteWithReason(proposalId, 1, "I support this proposal");

Queue and Execute

// After voting period ends and proposal succeeded
governor.queue(targets, values, calldatas, descriptionHash);

// After timelock delay
governor.execute(targets, values, calldatas, descriptionHash);

Delegate Voting Power

// Delegate to self
token.delegate(msg.sender);

// Delegate to another address
token.delegate(delegatee);

Security Considerations

Flash Loan Governance Attacks

Risk: Attacker borrows tokens, votes, returns tokens in same block.

Mitigations:

  1. Snapshot-based voting (votes counted at proposal creation block)
  2. Voting delay prevents same-block voting
  3. Historical balance checks via checkpoints

Proposal Spam

Risk: Attacker creates many proposals to clog governance.

Mitigations:

  1. Proposal threshold (1% of supply)
  2. Active proposals limit (not implemented, but recommended)
  3. Economic cost of holding tokens

Timelock Bypass

Risk: Malicious proposals that modify timelock itself.

Mitigations:

  1. Timelock can only be updated through itself
  2. Admin role carefully managed
  3. Consider renouncing admin after setup

Voting Power Manipulation

Risk: Moving tokens between accounts to vote multiple times.

Mitigations:

  1. Snapshot at proposal creation
  2. Delegation tracking per account
  3. Cannot vote after delegating away

Threat Model

Threat Impact Likelihood Mitigation
Flash loan voting High Low Checkpoints + delay
Proposal spam Medium Medium Threshold requirement
Malicious execution High Low Timelock delay
Admin key compromise Critical Low Renounce admin
Quorum manipulation Medium Low Dynamic quorum

Gas Optimization

  • Efficient checkpoint storage using packed structs
  • Batch operations in timelock
  • Minimal storage writes during voting
  • Unchecked blocks where safe

Project Structure

governance-dao-governor/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ GovernanceToken.sol     # ERC-20 with voting
β”‚   β”œβ”€β”€ Governor.sol            # Bravo-style governor
β”‚   β”œβ”€β”€ Timelock.sol            # Execution delay controller
β”‚   β”œβ”€β”€ interfaces/
β”‚   β”‚   β”œβ”€β”€ IGovernanceToken.sol
β”‚   β”‚   β”œβ”€β”€ IGovernor.sol
β”‚   β”‚   └── ITimelock.sol
β”‚   └── mocks/
β”‚       └── MockTarget.sol
β”œβ”€β”€ test/
β”‚   β”œβ”€β”€ BaseTest.sol
β”‚   β”œβ”€β”€ unit/
β”‚   β”‚   β”œβ”€β”€ GovernanceToken.t.sol
β”‚   β”‚   β”œβ”€β”€ Governor.t.sol
β”‚   β”‚   └── Timelock.t.sol
β”‚   β”œβ”€β”€ fuzz/
β”‚   β”‚   └── GovernanceFuzz.t.sol
β”‚   └── invariant/
β”‚       └── GovernanceInvariant.t.sol
β”œβ”€β”€ script/
β”‚   β”œβ”€β”€ DeployGovernance.s.sol
β”‚   └── Interactions.s.sol
β”œβ”€β”€ foundry.toml
└── README.md

References

License

MIT

About

Decentralized governance system with proposal lifecycle, three-way voting, checkpoint-based delegation and timelock execution delay

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published