DAOForm
Governance-as-Code for DAOs. Define governance in YAML, manage proposals in code, resolve votes with configurable quorum and threshold rules.
Quick Start
pip install daoform
# Initialize governance config
daoform init --name "MyDAO"
# Validate config
daoform validate
# Create a proposal
daoform propose --id PROP-1 --title "Fund development" --author alice.ethGovernance Model
# dao.yaml — your DAO's constitution
name: MyDAO
description: Community-governed protocol
quorum: 0.1 # 10% participation required
threshold: 0.5 # 50% approval to pass
voting_period_days: 7 # Proposals open for 7 days
timelock_days: 2 # 2-day delay before execution
token_address: null # Governance token (optional)Proposal lifecycle: DRAFT → ACTIVE → PASSED/REJECTED → EXECUTED
Quorum: Minimum total voting weight required. If not met, proposal is rejected regardless of vote split.
Threshold: Percentage of FOR votes (excluding abstain) needed to pass. 0.5 = simple majority.
Weight: Each vote has a weight representing voting power (e.g., token balance).
Python SDK
from daoform.engine import GovernanceEngine
from daoform.models import DAOConfig, Proposal, ProposalStatus, Vote, VoteChoice
config = DAOConfig(name="MyDAO", quorum=0.1, threshold=0.5)
engine = GovernanceEngine(config)
# Create and activate proposal
p = engine.create_proposal(
Proposal(id="PROP-1", title="Fund core dev", author="alice.eth")
)
p.status = ProposalStatus.ACTIVE
# Cast votes
engine.cast_vote(Vote(proposal_id="PROP-1", voter="alice.eth", choice=VoteChoice.FOR, weight=10))
engine.cast_vote(Vote(proposal_id="PROP-1", voter="bob.eth", choice=VoteChoice.AGAINST, weight=3))
# Tally
tally = engine.tally("PROP-1")
# {'for': 10.0, 'against': 3.0, 'abstain': 0.0, 'total': 13.0}
# Resolve
status = engine.resolve("PROP-1") # PASSED (76.9% > 50%)Persistence
Proposals and votes are stored as YAML files in .daoform/:
from daoform.store import Store
store = Store(".daoform")
# Save
store.save_proposal(proposal)
store.save_vote(vote)
# Load
proposal = store.load_proposal("PROP-1")
votes = store.load_votes("PROP-1")
all_proposals = store.list_proposals()The Store class is designed to be swappable — implement the same interface with PostgreSQL, SQLite, or on-chain storage for production.
CLI Reference
| Command | Description |
|---|---|
daoform init --name MyDAO | Create dao.yaml governance config |
daoform validate --config-file dao.yaml | Validate config |
daoform propose --id PROP-1 --title "..." --author alice | Create proposal |