Building a DAO: Governance on the Blockchain
A Decentralized Autonomous Organization (DAO) replaces traditional corporate governance with smart contracts. Token holders vote on proposals, and the code executes the outcome. No board of directors, no manual processes — just transparent, on-chain decision-making.
The Governance Stack
A typical DAO has three components:
-
Governance Token: An ERC-20 token that grants voting power
-
Governor Contract: Manages proposals, voting, and execution
-
Timelock: Delays execution so members can react to passed proposals
OpenZeppelin provides battle-tested implementations:
import "@openzeppelin/contracts/governance/Governor.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";
contract MyDAO is Governor, GovernorVotes, GovernorTimelockControl {
constructor(
IVotes _token,
TimelockController _timelock
)
Governor("MyDAO")
GovernorVotes(_token)
GovernorTimelockControl(_timelock)
{}
function votingDelay() public pure override returns (uint256) {
return 1 days;
}
function votingPeriod() public pure override returns (uint256) {
return 7 days;
}
function quorum(uint256) public pure override returns (uint256) {
return 100_000e18; // 100,000 tokens
}
}
The Proposal Lifecycle
-
Propose: Any token holder (above a threshold) submits a proposal — a set of on-chain actions (transfer funds, update parameters, upgrade contracts)
-
Voting delay: A buffer period so members can delegate votes and prepare
-
Active voting: Token holders cast votes — For, Against, or Abstain
-
Quorum check: Did enough tokens participate?
-
Timelock: If passed, the proposal enters a delay before execution
-
Execute: Anyone can trigger the execution after the timelock expires
// Proposing from a frontend (using ethers.js)
const targets = [treasuryAddress];
const values = [0];
const calldatas = [
treasury.interface.encodeFunctionData("transfer", [
recipientAddress,
ethers.parseEther("1000"),
]),
];
const description = "Transfer 1000 tokens to the dev team";
const tx = await governor.propose(targets, values, calldatas, description);
Voting Strategies
Token-weighted: 1 token = 1 vote. Simple but plutocratic — whales dominate.
Quadratic voting: Voting power = √(tokens). Reduces whale influence but is vulnerable to Sybil attacks (splitting tokens across wallets).
Conviction voting: Votes accumulate over time. The longer you signal support, the more weight it carries. Good for continuous funding decisions.
Delegation: Token holders delegate voting power to representatives. Most governance tokens support on-chain delegation via ERC-20Votes.
Common DAO Pitfalls
-
Voter apathy: Most token holders don't vote. Set reasonable quorum thresholds.
-
Governance attacks: Flash loans to borrow tokens, vote, and repay in one transaction. Mitigate with snapshot-based voting (vote power = balance at proposal creation block).
-
Proposal spam: Require a minimum token balance to submit proposals.
-
Execution risk: Complex proposals can have unintended consequences. The timelock gives time for review, but someone needs to actually review.
Real-World Examples
-
Uniswap: Governs the DEX protocol, controls the fee switch and treasury
-
Aave: Manages risk parameters, asset listings, and protocol upgrades
-
ENS: Governs the Ethereum Name Service, allocates treasury funds
DAOs are still experimental. The legal status is murky, voter turnout is low, and the tooling is maturing. But for open-source projects and crypto-native organizations, on-chain governance offers a level of transparency and automation that traditional structures can't match.