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