contracts/DAOFactory.sol
The DAOFactory is the central deployment contract for CreateDAO v2. It deploys complete DAO governance systems using the EIP-1167 minimal proxy (Clones) pattern for gas efficiency.
Overview
The factory contains implementation contracts for DAOToken and DAOGovernor, deployed once in the constructor. When creating a new DAO, it clones these implementations and deploys a fresh TimelockController, configuring all three contracts to work together as a complete governance system.Key Concepts
EIP-1167 Minimal Proxies (Clones)
Instead of deploying full contract bytecode for each DAO, the factory uses OpenZeppelin’sClones library to create minimal proxy contracts (only 45 bytes each!) that delegate all calls to shared implementation contracts.
Benefits:
- Massive Gas Savings: Each proxy is only 45 bytes vs ~15KB+ for full contracts
- Factory Size: Keeps factory under the 24KB contract size limit
- Immutable: Proxies are not upgradeable - they permanently point to their implementation
- Identical Behavior: Function identically to full contracts
Deterministic Deployment (CREATE2)
The factory itself is deployed using Arachnid’s deterministic CREATE2 deployer, which means:- Same address across chains when using the same salt
- Predictable addresses before deployment
- Easy multi-chain deployment
Architecture
Key Functions
createDAO
daoName: Name of the DAO (used for Governor)tokenName: Name of the governance token (e.g., “My DAO Token”)tokenSymbol: Token symbol (e.g., “MYD”)totalSupply: Total token supply in wei (e.g.,1000000 * 10^18for 1M tokens)votingDelay: Delay before voting starts (seconds, e.g.,86400= 1 day)votingPeriod: Duration of voting period (seconds, e.g.,604800= 1 week)
token: Address of the DAOToken proxytimelock: Address of the TimelockController (treasury)governor: Address of the DAOGovernor proxy
-
Clone DAOToken (EIP-1167)
- Creates minimal proxy pointing to
tokenImplementation - Initializes with name, symbol, and total supply
- Mints all tokens to the factory temporarily
- Creates minimal proxy pointing to
-
Deploy TimelockController
- Creates full contract (not a proxy)
- Sets 1-day minimum delay
- Executors:
address(0)(anyone can execute after delay) - Admin: factory (temporarily, revoked later)
-
Clone DAOGovernor (EIP-1167)
- Creates minimal proxy pointing to
governorImplementation - Initializes with name, token address, and timelock address
- Sets initial manager to
msg.sender(DAO creator) - Configures voting delay, voting period, quorum (1%), and proposal threshold (1%)
- Creates minimal proxy pointing to
-
Configure Roles
- Grants
PROPOSER_ROLEto Governor (only Governor can propose timelock actions) - Grants
CANCELLER_ROLEto Governor - Revokes
ADMIN_ROLEfrom factory (Governor becomes sole admin via timelock)
- Grants
-
Distribute Tokens
- Transfers 1% to
msg.sender(creator) - auto-delegated - Transfers 99% to timelock (treasury)
- Transfers 1% to
-
Record & Emit
- Stores DAO info in
daosarray - Emits
DAOCreatedevent
- Stores DAO info in
View Functions
getDAOCount
getDAOByIndex
DAOInfo struct containing:
name: DAO nametoken: Token addressgovernor: Governor addresstimelock: Timelock addresscreator: Address that created the DAOcreatedAt: Timestamp of creation
getImplementations
Events
DAOCreated
Token Distribution
When a DAO is created, tokens are distributed as follows:| Recipient | Percentage | Purpose |
|---|---|---|
Creator (msg.sender) | 1% | Bootstrap governance - enables meeting quorum and creating initial proposals |
| Treasury (TimelockController) | 99% | Secure storage - distributed through governance proposals |
- OpenZeppelin’s
GovernorVotesQuorumFractionrequires minimum 1% quorum - Creator needs exactly 1% to meet quorum and pass initial proposals
- After initial setup, creator can propose token distribution to other members
Auto-Delegation
DAOToken implements auto-delegation, which means:- When an address receives tokens for the first time, they automatically delegate to themselves
- Voting power is immediately active - no manual
delegate()call needed - This applies to the creator and all future token recipients
Manager Role
The DAOGovernor contract includes a specialmanager address:
- Initial Value: Set to the DAO creator (
msg.sender) - Purpose: On-chain authorization for off-chain operations
- How to Change: Only through governance proposals (timelock-protected)
- Use Case: Integration with DAO management platforms like OpenBook
Gas Optimization
The Clones pattern provides significant gas savings:| Component | Traditional Deployment | With Clones | Savings |
|---|---|---|---|
| DAOToken | ~2.5M gas | ~150K gas | 94% |
| DAOGovernor | ~4M gas | ~200K gas | 95% |
| Total DAO | ~8M gas | ~2.5M gas | 69% |
Example Usage
Security Considerations
- Immutable Proxies: The clones are not upgradeable. Once deployed, they always point to the same implementation.
-
Implementation Protection: Implementation contracts call
_disableInitializers()in their constructor, preventing anyone from initializing them directly. - Role Configuration: The factory carefully configures timelock roles and revokes its own admin access, ensuring only the Governor can control the timelock.
- Deterministic Addresses: Using CREATE2 for factory deployment enables verification of factory authenticity across chains.