A production-grade, Bravo-style governance system built with Foundry. Implements decentralized proposal creation, voting, timelock execution, and token-based voting power delegation.
┌─────────────────────────────────────────────────────────────────────────────┐
│ 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 │ │
│ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ PENDING │───►│ ACTIVE │───►│SUCCEEDED │───►│ QUEUED │───►│ EXECUTED │
└──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘
│ │ │
│ │ └──────────────┐
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ CANCELED │ │ DEFEATED │ │ EXPIRED │
└──────────┘ └──────────┘ └──────────┘
Timeline:
├─ Voting Delay ─┼─────── Voting Period ───────┼── Timelock Delay ──┤
(1 day) (1 week) (2 days)
- ERC-20 with voting delegation
- Checkpoint-based historical voting power
- EIP-2612 permit for gasless approvals
- Capped supply (100M tokens max)
- Proposal creation with threshold requirement
- Three-way voting: For, Against, Abstain
- Configurable voting delay and period
- Quorum requirements
- EIP-712 vote signatures
- Configurable execution delay
- Batch operation support
- Operation predecessor dependencies
- Role-based access control
| 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 |
- Can create proposals (requires threshold tokens)
- Can cancel own proposals (while pending)
- Delegates voting power (to self or others)
- Casts votes on active proposals
- Weight based on historical balance at snapshot
- Governor contract (through timelock)
- Executes successful proposals after delay
- Can cancel malicious proposals
- Emergency veto power
git clone https://github.com/Kazopl/governance-dao-governor.git
cd governance-dao-governor
forge installforge build# 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/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_keyforge script script/DeployGovernance.s.sol:DeployGovernance \
--rpc-url $SEPOLIA_RPC_URL \
--broadcast \
--verifyaddress[] 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"
);// Vote For (1), Against (0), or Abstain (2)
governor.castVoteWithReason(proposalId, 1, "I support this proposal");// After voting period ends and proposal succeeded
governor.queue(targets, values, calldatas, descriptionHash);
// After timelock delay
governor.execute(targets, values, calldatas, descriptionHash);// Delegate to self
token.delegate(msg.sender);
// Delegate to another address
token.delegate(delegatee);Risk: Attacker borrows tokens, votes, returns tokens in same block.
Mitigations:
- Snapshot-based voting (votes counted at proposal creation block)
- Voting delay prevents same-block voting
- Historical balance checks via checkpoints
Risk: Attacker creates many proposals to clog governance.
Mitigations:
- Proposal threshold (1% of supply)
- Active proposals limit (not implemented, but recommended)
- Economic cost of holding tokens
Risk: Malicious proposals that modify timelock itself.
Mitigations:
- Timelock can only be updated through itself
- Admin role carefully managed
- Consider renouncing admin after setup
Risk: Moving tokens between accounts to vote multiple times.
Mitigations:
- Snapshot at proposal creation
- Delegation tracking per account
- Cannot vote after delegating away
| 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 |
- Efficient checkpoint storage using packed structs
- Batch operations in timelock
- Minimal storage writes during voting
- Unchecked blocks where safe
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
MIT