A SubDAO's voting mechanism is the core of its decentralized governance, enabling token holders to collectively make decisions. The process typically involves three key smart contracts: a Governor contract that manages proposals and voting, a Voting Token (often an ERC-20 or ERC-721) that defines voting power, and a Timelock Controller that introduces a delay between a vote's approval and its execution for security. This architecture, popularized by OpenZeppelin's Governor contracts, separates the voting logic from the execution of on-chain actions, allowing for modular and upgradeable governance systems.
How to Implement a SubDAO Voting Mechanism and Proposal Process
How to Implement a SubDAO Voting Mechanism and Proposal Process
A practical guide to building a secure and functional voting system for a SubDAO, covering smart contract design, proposal lifecycle, and integration patterns.
The proposal lifecycle begins with proposal submission. A proposer, who must hold a minimum voting power threshold, calls the propose function on the Governor contract. This function takes an array of target addresses, values, and calldata representing the actions to execute if the proposal passes. The contract calculates a unique proposalId and enters a pending state. During the voting period, token holders can cast their votes using functions like castVote. Voting power is typically calculated via a snapshot mechanism at the start of the voting period to prevent manipulation.
Implementing the vote tally requires choosing a voting strategy. Common standards include simple token-weighted voting (1 token = 1 vote) and delegated voting, where users can delegate their voting power to another address. For more complex governance, consider quadratic voting or conviction voting models. After the voting period ends, the proposal moves to the execution phase. If the vote meets quorum and passes the required vote threshold (e.g., a simple majority or supermajority), the approved transactions are queued in the Timelock and can be executed after the delay expires, providing a final safety check.
Here is a simplified example of a proposal submission using Solidity and OpenZeppelin's Governor contract framework:
solidity// Assume `governor` is an instance of a Governor contract address[] memory targets = new address[](1); uint256[] memory values = new uint256[](1); bytes[] memory calldatas = new bytes[](1); // Proposal to transfer 100 tokens from the treasury targets[0] = address(tokenTreasury); values[0] = 0; calldatas[0] = abi.encodeWithSignature("transfer(address,uint256)", recipient, 100e18); // Submit the proposal governor.propose(targets, values, calldatas, "Transfer 100 tokens to grants pool");
Integrating this system requires a front-end interface for users to view active proposals, delegate votes, and cast their ballots. Tools like Tally or Snapshot (for gasless off-chain voting) provide ready-made interfaces, but you can also build a custom UI that interacts with your Governor contract's ABI. Key front-end tasks include fetching proposal state via the contract's view functions (state(), proposalVotes()), connecting user wallets, and signing transactions for castVote or execute. Always ensure your implementation includes clear documentation for members on proposal creation rules, voting periods, and execution steps.
Security best practices are critical. Always use a Timelock for executing sensitive treasury transactions. Set appropriate proposal thresholds and quorum requirements to prevent spam and ensure meaningful participation. Consider implementing veto powers or a security council for emergency actions via a separate, multi-sig controlled contract. Regularly audit your governance contracts, especially any custom voting logic. By following these patterns, you can create a robust SubDAO governance system that is transparent, secure, and truly decentralized.
Prerequisites and Technical Requirements
Before implementing a SubDAO voting system, you need to establish the foundational technical and conceptual requirements. This guide outlines the essential knowledge, tools, and smart contract frameworks required to build a secure and functional on-chain governance process.
A SubDAO voting mechanism is a specialized governance module that allows a subset of a larger DAO to manage specific tasks or treasury funds. The core technical requirement is a smart contract development environment. You will need proficiency with a language like Solidity (for EVM chains) or Rust (for Solana), and a framework such as Hardhat, Foundry, or Anchor. Familiarity with OpenZeppelin's governance contracts is highly recommended, as they provide battle-tested, modular components for voting, timelocks, and execution.
Your development stack must include a testnet environment and wallet for deployment and interaction. For EVM chains, use Sepolia or Goerli testnets with MetaMask. For Solana, use Devnet with Phantom. You will also need access to blockchain data, requiring an RPC provider like Alchemy, Infura, or QuickNode. These services are essential for querying proposal states, voter balances, and transaction execution during development and testing.
The proposal process logic must be defined upfront. Key parameters to codify include: the voting token (ERC-20 or SPL), proposal threshold (minimum tokens to submit), voting period (e.g., 3-7 days), quorum (minimum participation for validity), and vote counting method (e.g., simple majority, quadratic voting). These rules are immutable once deployed, so careful design is critical. Use a timelock contract to introduce a delay between a proposal's approval and its execution, providing a safety mechanism for the parent DAO.
For on-chain voting, you must integrate with a token contract to check voting power. This typically involves calling the balanceOf or getPastVotes (for snapshot-based voting) function. Off-chain components are also common; you may need to run a snapshot server to capture voter balances at a specific block number or build a frontend using libraries like wagmi, ethers.js, or @solana/web3.js. The frontend will connect user wallets, display active proposals, and facilitate voting transaction signing.
Security auditing is a non-negotiable prerequisite. Governance contracts control treasury funds and critical protocol parameters. Before any mainnet deployment, your code should undergo a formal audit by a reputable firm. Additionally, implement comprehensive tests covering all voting scenarios: proposal creation, voting for/against, reaching quorum, execution, and failure cases. Tools like Foundry's forge test or Hardhat's waffle/chai are used for this. Finally, consider gas optimization, as complex voting logic can become expensive for users.
How to Implement a SubDAO Voting Mechanism and Proposal Process
A step-by-step guide to building a secure and functional voting system for SubDAOs using smart contracts and governance frameworks.
A SubDAO's voting mechanism is the core of its decentralized governance, enabling token holders to make collective decisions. The process typically involves three key smart contracts: a proposal factory for creation, a voting vault for staking and vote weighting, and a timelock controller for secure execution. Unlike simple token-weighted voting, advanced SubDAOs often implement features like quadratic voting to reduce whale dominance, conviction voting for gauging long-term support, or multisig execution for high-security actions. The choice of mechanism directly impacts the SubDAO's agility, security, and resistance to governance attacks.
The proposal lifecycle begins when a member with sufficient voting power submits a structured proposal. This is usually done by calling a function like createProposal() on the governance contract, which stores the proposal's metadata and executable calldata. Proposals should include a clear title, description, on-chain actions (e.g., target, value, data), and a voting period. Using a standard like EIP-712 for typed structured data signing can improve user experience and security. Proposals are typically stored on-chain in a state of Pending before moving to Active for voting.
During the voting period, members cast votes by signing a message or submitting a transaction, with their voting power calculated from tokens staked in the voting vault. A common implementation uses the OpenZeppelin Governor contract with a custom token logic module. For example, a vote function might look like: function castVote(uint256 proposalId, uint8 support) public returns (uint256). Votes are usually tallied as For, Against, or Abstain. Implementing snapshot voting (off-chain signing) can reduce gas costs for voters, but requires a trusted oracle to post results on-chain for execution.
Once voting ends, the proposal must be queued and executed. If the proposal meets quorum (minimum participation) and passes the vote threshold, it is queued in a Timelock contract. The Timelock introduces a mandatory delay, providing a safety window for the community to react to malicious proposals. After the delay, anyone can call the execute function to run the proposal's encoded transactions. This multi-step process—propose, vote, queue, timelock, execute—is crucial for security. Audit this flow thoroughly, as bugs in proposal execution can lead to fund loss or protocol takeover.
To implement this, you can fork and customize established frameworks. The Compound Governor Bravo system is a widely audited blueprint. Alternatively, OpenZeppelin's Governor contracts offer modular components for voting, timelocks, and vote counting. For a SubDAO on Aragon OSx, you would use its DAO and Plugin architecture to install a voting plugin. Always write comprehensive tests for edge cases: proposal creation rights, vote snapshot accuracy, quorum logic, and timelock cancellation. A well-tested SubDAO voting mechanism balances decentralization, security, and practical usability for its members.
Voting Platform Comparison: Snapshot vs. On-Chain
Key technical and operational differences between off-chain and on-chain voting solutions for DAO governance.
| Feature | Snapshot (Off-Chain) | On-Chain Voting |
|---|---|---|
Voting Cost for User | $0 (Gasless) | ~$5-50+ (Gas Fee Varies) |
Finality & Execution | Requires separate execution | Vote result is execution |
Vote Weighting | Flexible (ERC-20, ERC-721, ERC-1155) | Native token or governance token only |
Sybil Resistance | Relies on snapshot strategy (e.g., token hold) | Native to blockchain (1 token = 1 vote) |
Vote Delay to Execution | Minutes to days (manual execution) | Immediate upon vote conclusion |
Maximum Voter Scalability | Theoretically unlimited | Limited by block gas limits |
Typical Use Case | Signal votes, temperature checks | Direct treasury transfers, parameter changes |
Smart Contract Integration | Read-only via strategies | Full, executable logic via proposals |
Step 1: Design the Proposal Lifecycle
A well-defined proposal lifecycle is the core of any functional SubDAO. This step maps the journey from idea to execution, establishing clear rules for governance participation.
The proposal lifecycle defines the stages a governance motion must pass through, from creation to final resolution. A typical lifecycle includes: Drafting, Voting, Timelock, and Execution. Each stage serves a specific purpose: the draft phase allows for community feedback, the voting phase measures consensus, the timelock provides a security delay for review, and the execution phase enacts the approved changes. Structuring this process in your smart contract is the first technical requirement.
Start by defining the proposal state machine in your governance contract. Common states are Pending, Active, Succeeded, Queued, and Executed. Transitions between these states are triggered by specific actions, such as a successful vote or the expiration of a timelock. For example, a proposal moves from Active to Succeeded when the voting period ends and the for votes exceed both a quorum threshold and a majority requirement. This logic enforces your DAO's rules programmatically.
Key parameters must be set during contract deployment or via governance itself. These include the voting delay (time between proposal submission and voting start), voting period (duration of the active vote), and timelock delay (mandatory waiting period after a vote passes before execution). For a treasury SubDAO, a 24-hour timelock is a common security measure, allowing time to review a malicious transaction before it's executed on-chain.
The proposal lifecycle must also define proposal eligibility. Who can submit a proposal? Often, a minimum token balance or delegated voting power is required, such as holding 0.1% of the governance token supply. This prevents spam. The lifecycle should also specify which contracts or functions the SubDAO can govern, typically defined by a TimelockController address that holds the treasury funds and executes approved transactions.
Here is a simplified skeleton of a proposal state transition in a Solidity contract:
solidityenum ProposalState { Pending, Active, Succeeded, Queued, Executed } function state(uint256 proposalId) public view returns (ProposalState) { Proposal storage p = proposals[proposalId]; if (block.number <= p.startBlock) return ProposalState.Pending; if (block.number <= p.endBlock) return ProposalState.Active; if (p.forVotes <= p.againstVotes || p.forVotes < quorumVotes) return ProposalState.Defeated; if (p.eta == 0) return ProposalState.Succeeded; if (block.timestamp >= p.eta) return ProposalState.Queued; return ProposalState.Executed; }
This function determines the current state based on block numbers, vote totals, and execution timestamps.
Finally, document this lifecycle clearly for members. A transparent process—knowing exactly how long a vote lasts, when a timelock expires, and how to challenge a proposal—builds trust and participation. The designed lifecycle becomes the immutable rulebook for your SubDAO's decision-making, balancing efficiency with necessary security checks.
Step 2: Implement Voting Logic and Strategies
This section details the implementation of a SubDAO's core governance engine, covering smart contract logic for proposals, voting strategies, and result execution.
The foundation of your SubDAO is its voting mechanism, defined within a smart contract. A standard implementation involves three primary states for a proposal: Pending, Active, and Executed. The contract must manage a proposal's lifecycle, including its creation, a defined voting period, tallying of votes, and final execution. Key data structures include a Proposal struct storing the proposal ID, creator, description, target contract address, calldata for execution, vote counts, and timestamps. The contract exposes functions like createProposal, castVote, and executeProposal to interact with this lifecycle.
Voting power is not simply one-address-one-vote. You must implement a voting strategy that determines how voting weight is calculated. Common strategies include token-weighted voting (e.g., 1 ERC-20 token = 1 vote), NFT-based voting (e.g., 1 NFT = 1 vote), or a hybrid model. This logic is often separated into a standalone VotingStrategy contract for modularity. For example, a token-weighted strategy would query the voter's balance of a specific governance token at a predetermined block snapshot to prevent manipulation. The main voting contract calls the strategy contract's getVotingPower function for each voter.
To cast a vote, a user calls castVote(proposalId, support). The contract must check that the proposal is in the Active state, that the voting period hasn't ended, and that the voter hasn't already voted. It then queries the voting strategy for the user's power and records the vote, typically incrementing forVotes or againstVotes. Implementing vote delegation adds complexity, requiring a mapping that allows users to delegate their voting power to another address, which then votes on their behalf.
After the voting period ends, any account can call executeProposal(proposalId) if the proposal succeeded. The execution logic must verify that the proposal reached a quorum (a minimum threshold of total voting power participation) and that the forVotes exceed the againstVotes (or meet a custom passing threshold). Only then should it use a low-level call to execute the stored calldata on the target contract. It's critical to implement security checks here, such as ensuring the target is a whitelisted contract to prevent arbitrary code execution.
For advanced governance, consider implementing time-locks and multisig guardians. A timelock contract can queue a successful proposal for a delay before execution, giving the community a final review period. A multisig of trusted entities can be granted a veto or emergency cancel power in a separate guardian role, providing a circuit breaker for malicious or flawed proposals. These features enhance security but increase system complexity.
Finally, integrate this contract with a front-end using a library like wagmi or ethers.js. The UI should fetch active proposals, display voting power, and facilitate transaction signing. Always audit your voting contracts thoroughly and consider using established, audited bases like OpenZeppelin's Governor contracts as a starting point to reduce risk and development time.
Step 3: Integrate with Snapshot for Off-Chain Signaling
This step details how to configure a Snapshot space for your SubDAO to manage gas-free, off-chain voting on governance proposals before they are executed on-chain.
Snapshot is the leading off-chain voting platform, enabling communities to create and vote on proposals without paying gas fees. For a SubDAO, it serves as the primary signaling layer where members can debate, amend, and gauge sentiment for initiatives. The core workflow involves creating a dedicated Snapshot space for your SubDAO, configuring voting strategies that read from your membership token (e.g., an ERC-20 or ERC-721), and setting up proposal types and voting parameters. This off-chain process is crucial for building consensus before committing irreversible, on-chain transactions.
To begin, navigate to snapshot.org and connect the wallet of your SubDAO's admin or multisig. Create a new space, which will act as your SubDAO's governance hub. The most critical configuration is the Voting Strategy. You will define how voting power is calculated, typically by linking to your membership token contract. For example, a common strategy is the erc20-balance-of strategy, which assigns one vote per token held at a specific block number. You can also use erc721 strategies for NFT-based DAOs or create custom strategies that combine multiple tokens or consider delegation.
Next, define your Voting System and Proposal Validation. Snapshot supports several systems: Single Choice Voting for straightforward yes/no decisions, Approval Voting where voters can select multiple options, and Ranked Choice Voting for complex prioritization. You must also set validation criteria, such as a minimum proposal submission threshold (e.g., member must hold 100 tokens) and a proposal duration (e.g., 5 days). These settings enforce that only engaged, legitimate members can initiate and shape proposals, maintaining the integrity of the governance process.
With the space configured, members can submit proposals. A well-structured proposal should include a clear title, a detailed description using markdown, the specific choices for voting (e.g., "For," "Against," "Abstain"), and a discussion period before the voting starts. The Snapshot interface allows linking to external discussion forums like Discord or Discourse threads. Once a proposal is live, members cast their votes by signing a message with their wallet—a gas-free operation. The results are transparently tallied on Snapshot's interface.
The final, crucial step is bridging the off-chain signal to on-chain execution. A successful Snapshot vote is a signal, not an action. Your SubDAO needs a trusted entity—often a multisig wallet or a designated executor contract—to validate the proposal's passage on Snapshot and then execute the corresponding transaction on-chain. This can be a manual process for smaller DAOs or automated using tools like Snapshot's Zodiac module for Gnosis Safe, which allows approved transactions to be executed automatically upon a successful vote.
Implement a SubDAO Voting Mechanism and Proposal Process
This guide details the implementation of a SubDAO's core governance module, enabling token-weighted voting and a structured lifecycle for on-chain proposals.
A SubDAO's voting mechanism is typically implemented as a smart contract that manages proposal creation, voting, and execution. The core data structures include a Proposal struct to store the proposal's metadata—such as id, creator, description, startBlock, endBlock, forVotes, againstVotes, and an executed flag. Voting power is usually calculated based on a snapshot of the governance token balance at the proposal's creation block, preventing manipulation via token transfers during the voting period. This is often implemented using OpenZeppelin's Governor contracts as a foundation, which provide battle-tested logic for these core functions.
The proposal lifecycle follows a specific sequence. First, a member with sufficient proposal threshold submits a transaction calling propose(), which includes the target contract addresses, calldata for the actions to execute, and a description. This creates a new proposal and emits an event. The proposal then enters a voting delay period, followed by an active voting period (e.g., 3-7 days). During this time, token holders cast their votes using castVote(), with options like For, Against, or Abstain. Votes are weighted by the voter's token balance at the proposal snapshot block.
After the voting period ends, the proposal can be queued for execution if it meets quorum and passes the vote threshold (e.g., a simple majority of For votes). The quorum is a minimum percentage of the total token supply that must participate for the vote to be valid. Once queued, a timelock period often ensues, providing a final safety window for the community to react before changes are applied. Finally, anyone can call execute() to run the proposal's encoded actions on the target contracts, marking the proposal as executed.
Key security considerations must be addressed. Use a timelock controller (like OpenZeppelin's TimelockController) to delay execution of successful proposals, preventing malicious or rushed upgrades. Implement access controls to restrict proposal creation and execution functions. Ensure the voting math is protected against overflow/underflow attacks. It's also critical to thoroughly test the integration between the Governor contract, the timelock, and the target contracts that will receive the executed calls.
For a practical example, a proposal to upgrade a protocol's fee parameter might encode a call to Treasury.setFeePercentage(250) for a 2.5% fee. The SubDAO contract would store this calldata. After a successful vote, the execute function would send this call via the timelock, which would wait 48 hours before finally calling the Treasury contract. This multi-step process ensures transparent, deliberate, and secure on-chain governance execution for the SubDAO.
Step 5: Create a Governance Frontend Dashboard
Build a React-based interface for your SubDAO's governance, connecting to on-chain voting contracts and displaying live proposal data.
A governance frontend is the user-facing application where SubDAO members discover, discuss, and vote on proposals. The core architecture involves a React or Next.js application that interacts with your smart contracts via a library like wagmi or ethers.js. The frontend's primary responsibilities are to fetch proposal data from the blockchain, manage user wallet connections, and submit signed transactions for actions like creating proposals, casting votes, and executing passed proposals. You'll need to connect to an RPC provider for the network your contracts are deployed on, such as Alchemy or Infura.
The dashboard should clearly display the lifecycle of a proposal. Key UI components include a list of active proposals showing their title, description, current vote tally (For/Against/Abstain), and time remaining. Each proposal should link to a detail page with the full description and voting interface. Use a library like react-query or SWR to efficiently cache and poll for on-chain state updates, ensuring the UI reflects the latest vote counts and proposal statuses without requiring a page refresh.
To implement voting, you must call the vote function on your governance contract. The frontend needs to handle the transaction flow: prompting the user to sign, showing a pending state, and confirming success or failure. For gasless voting, integrate a relayer service like Gelato or OpenZeppelin Defender. Display the user's voting power, typically derived from their token balance or NFT holdings, and disable the vote button if they have insufficient power or have already voted. Always verify proposal state (e.g., Active, Succeeded, Executed) on-chain before enabling actions.
Enhance the user experience with off-chain components. Integrate a discussion forum for each proposal using a tool like Discourse or Snapshot's discussion forum, linking from the proposal detail page. For complex proposal creation, build a multi-step form that validates inputs (e.g., ensuring calldata is correctly formatted for the target contract) before submission. Implement filtering and sorting for the proposals list (by status, by date) and provide clear visual indicators for proposals that are executable or have passed quorum.
Finally, ensure security and accessibility. Use TypeScript for type safety with your contract ABIs. All contract interactions should be validated on the client side to prevent errors. The site should be responsive and follow Web3 UX best practices, such as clear wallet connection prompts and transaction status modals. For production, host the static site on Vercel, Fleek, or IPFS and consider using a domain service like ENS for a decentralized frontend entry point.
Essential Tools and Resources
Practical tools and frameworks for implementing a SubDAO voting mechanism and proposal process. Each resource focuses on a concrete part of the governance stack, from onchain execution to offchain signaling.
Frequently Asked Questions on SubDAO Governance
Common technical questions and solutions for implementing SubDAO voting and proposal systems on-chain.
A SubDAO voting mechanism is a specialized governance module that delegates specific decision-making authority from a main DAO to a smaller, focused group. The key technical differences lie in scope and execution.
Main DAO Governance typically controls core protocol parameters, treasury allocations, and major upgrades. Voting often uses the native token (e.g., $GOV) and requires broad, high-quorum participation.
SubDAO Governance handles delegated, operational decisions like grant approvals, content moderation, or managing a specific treasury pool. It uses a separate, often lighter-weight voting token (e.g., a non-transferable sGOV or NFT-based membership) and lower quorum thresholds. On-chain, this is implemented via a separate Governor contract (like OpenZeppelin's) that is authorized by the main DAO's TimelockController to execute specific function calls on target contracts.
Conclusion and Next Steps
You have now built the core components of a SubDAO voting and proposal system. This guide covered the essential smart contract logic, frontend integration, and security considerations.
Implementing a robust SubDAO system requires careful consideration of governance parameters. Key decisions include setting the proposal threshold, voting delay and period, and the quorum requirement. For example, a common starting point is a 1% token threshold to create a proposal, a 2-day voting delay, a 7-day voting period, and a 4% quorum. These values should be calibrated based on your token distribution and desired level of decentralization. Tools like Tally or Snapshot can provide benchmarks from live DAOs.
The next step is to enhance your system's functionality and security. Consider implementing timelocks for executed proposals, which add a mandatory delay before transactions are executed, providing a safety net. Integrate with Sybil-resistant identity systems like Gitcoin Passport or BrightID to mitigate vote manipulation. Furthermore, explore gasless voting via meta-transactions or dedicated relayers to reduce voter participation costs, a significant barrier in on-chain systems.
To test your implementation thoroughly, write comprehensive unit and integration tests using Hardhat or Foundry. Simulate governance attacks, such as proposal spam or flash loan voting power manipulation. Once tested, consider a phased launch: begin with a multisig-controlled timelock executor for the DAO treasury, gradually increasing the proposal power and treasury control as the community demonstrates responsible governance. Document the entire process and parameter choices transparently for your community.