On-chain grant programs represent a fundamental shift in how decentralized organizations allocate capital, moving from opaque, committee-based decisions to transparent, community-driven processes. By leveraging smart contracts on platforms like Ethereum, Optimism, or Arbitrum, projects can create a system where grant proposals, voting, and fund distribution are executed autonomously and immutably. This approach directly addresses trust issues in traditional grantmaking by providing a verifiable public record of all decisions and fund flows, aligning incentives between the treasury and the community of builders.
Launching a Community Grants Program with On-Chain Voting
Launching a Community Grants Program with On-Chain Voting
A technical walkthrough for DAOs and protocols to implement a transparent, decentralized grant funding system using smart contracts.
The core architecture of an on-chain grant program typically involves three key smart contract components: a proposal factory for submission, a voting module for decision-making, and a treasury vault for fund custody and disbursement. Popular frameworks like OpenZeppelin Governor or Aragon OSx provide modular, audited bases for these systems. For example, a proposal contract can store metadata (like an IPFS hash pointing to a detailed proposal) and executable calldata to transfer funds from the treasury to a recipient address upon a successful vote. This creates a seamless flow from idea to funded execution.
Implementing the voting mechanism requires careful design. Most systems use a token-weighted model, where voting power is proportional to a user's holdings of a governance token like UNI or AAVE. For a basic implementation, you can extend OpenZeppelin's Governor contract. The proposal lifecycle is managed on-chain: after a proposal is created, it enters a voting period where token holders cast their votes, followed by a timelock period for security, and finally execution. Here's a simplified snippet for a proposal's state logic:
solidityfunction state(uint256 proposalId) public view override returns (ProposalState) { // Check if proposal is defeated, succeeded, queued, etc. if (block.number <= proposalSnapshot(proposalId)) return ProposalState.Pending; if (block.number <= proposalDeadline(proposalId)) return ProposalState.Active; // ... determine if votes reached quorum & majority }
Security and parameterization are critical. You must configure several key variables: the proposal threshold (minimum tokens needed to submit), voting delay and period, quorum (minimum participation required), and voting basis (e.g., simple majority, quadratic voting). Setting a timelock executor, like OpenZeppelin's TimelockController, between the governor and the treasury adds a crucial security layer, allowing time to cancel malicious proposals before funds are moved. These parameters define the program's governance velocity and security posture and should be tested extensively on a testnet like Goerli or Sepolia before mainnet deployment.
To operationalize the program, you need a front-end interface for users to create and view proposals. This typically interacts with the smart contracts via a library like ethers.js or viem. The front-end fetches proposal data from the chain and from decentralized storage like IPFS or Arweave, where the full proposal details (specifications, budget breakdown, milestones) are stored. Successful execution is automated: once a proposal passes and the timelock expires, anyone can call the execute function on the governor contract to trigger the predefined fund transfer, completing the cycle from community vote to on-chain disbursement.
Prerequisites and Initial Setup
Before deploying a community grants program, you must establish the technical and governance infrastructure. This involves setting up a treasury, defining voting parameters, and preparing the smart contracts that will execute decisions.
The first prerequisite is a secure, multi-signature treasury wallet to hold the grant funds. For Ethereum-based projects, a Gnosis Safe is the industry standard, allowing a council of signers to approve transactions. You must decide on the initial funding amount and the token (e.g., USDC, ETH, your native token) to be used for disbursements. This treasury address will be the ultimate source of funds for all approved grants, so its security and transparency are paramount.
Next, you need to define the core governance parameters for your on-chain voting. This includes selecting a voting token (often the project's native ERC-20 token), setting a proposal threshold (the minimum token balance required to submit a grant application), and establishing voting periods. A typical structure includes a 3-7 day voting period followed by a 1-2 day timelock for execution. These parameters dictate the pace and accessibility of your grants process.
You must choose and deploy the smart contract infrastructure. For many projects, this involves a governor contract like OpenZeppelin's Governor, paired with a Treasury module or custom executor. The governor handles proposal creation, voting, and queueing, while the treasury contract holds the logic for releasing funds upon successful vote execution. Ensure these contracts are audited and their addresses are publicly verified on block explorers like Etherscan.
Finally, integrate a front-end interface for your community. While voting logic lives on-chain, users need an accessible way to create proposals, view active grants, and cast votes. You can use existing platforms like Tally or Snapshot (for gasless signaling), or build a custom interface that interacts directly with your governor contract. This setup completes the foundational stack, turning your smart contract parameters into a functional grants program.
Launching a Community Grants Program with On-Chain Voting
A step-by-step guide to designing and implementing a transparent, on-chain grants program for your DAO or protocol treasury.
A well-structured community grants program is a powerful tool for decentralized governance, allowing a treasury to fund ecosystem development, research, and marketing initiatives proposed by its users. The core mechanism involves an on-chain voting lifecycle where community members submit proposals, stakeholders vote using governance tokens, and funds are disbursed upon approval. This creates a transparent and accountable system, moving beyond opaque, multi-sig controlled grants. Key components include a proposal standard (like OpenZeppelin's Governor), a voting contract, and a mechanism for treasury stream payouts, which can be lump-sum or scheduled over time.
The proposal lifecycle typically follows four phases. First, a community member drafts a proposal detailing the project scope, budget, and deliverables, often using a template in a forum like Discourse. This undergoes a temperature check or informal discussion. If sentiment is positive, the proposal is formalized and submitted on-chain, initiating the voting period. During this period, token holders cast votes, with weight proportional to their stake. Finally, after a successful vote and any configured timelock delay for security, the proposal moves to the execution phase, where the treasury releases funds to the grant recipient's address.
For fund disbursement, consider moving beyond simple one-time transfers. Treasury streaming via smart contracts like Sablier or Superfluid provides superior accountability. Instead of sending 100,000 USDC upfront, the grant is streamed linearly over the project's milestone timeline (e.g., 12 months). This aligns incentives, as the recipient continuously earns the stream, and the DAO can cancel it if milestones are missed. Implementing this requires integrating a streaming module into your governance executor. The on-chain proposal would specify the recipient, total amount, token (e.g., USDC, ETH), and the stream duration.
Here is a simplified code snippet for a Governor proposal that would create a Sablier stream. The proposal's calldata calls a pre-authorized function in a treasury manager contract.
solidity// Example calldata for a grant proposal to create a 12-month Sablier stream bytes memory callData = abi.encodeWithSelector( TreasuryManager.createSablierLockupLinearStream.selector, recipientAddress, // Grant recipient 100000e6, // 100,000 USDC (6 decimals) block.timestamp + 1 days, // Stream starts in 1 day block.timestamp + 365 days // Stream ends in 1 year );
This data is packaged into a proposal via the Governor contract's propose function. Voters are effectively approving the execution of this specific transaction.
Successful programs require clear off-chain infrastructure. Establish public guidelines for grant tiers, eligibility, and reporting requirements. Use a dedicated forum category for discussions and a transparent rubric for evaluating proposals. After execution, mandate that recipients publish periodic progress reports. Tools like Snapshot for off-chain signaling, Tally for governance dashboards, and Safe for treasury management are commonly integrated. By combining robust smart contract mechanics with clear community processes, a grants program becomes a sustainable engine for growth, directly governed by the token holders who benefit from its success.
Governance Frameworks and Tools
A step-by-step guide to launching a transparent, on-chain grants program for your DAO or protocol. Covers tooling, voting mechanisms, and operational best practices.
Designing the Grant Framework
Define the scope, budget, and eligibility criteria for your program before deploying any smart contracts. Key decisions include:
- Grant Tiers: Small grants (<$10k), milestone-based medium grants ($10k-$50k), and large strategic grants ($50k+).
- Funding Source: Treasury allocation, protocol revenue streams, or a dedicated grants DAO.
- Evaluation Rubric: Clear, objective metrics for assessing proposals (e.g., impact, feasibility, team track record).
- Example: Uniswap Grants Program uses specialized sub-DAOs (UGP and UGP-Plus) with distinct budgets and focuses.
On-Chain Voting with Snapshot
Use Snapshot for gasless, off-chain signaling votes to gauge community sentiment on grant proposals. It's the standard for initial proposal discussion and temperature checks.
- How it works: Proposal creators upload metadata (title, description, choices) to IPFS. Token holders sign messages with their wallets to vote.
- Strategies: Customize voting power using token balances, delegation, or time-locked tokens (e.g., veCRV).
- Best Practice: Set a quorum (minimum participation) and vote duration (typically 3-7 days) to ensure legitimacy.
- Link: Snapshot Documentation
Automating Payouts with Safe & Zodiac
Execute approved grants automatically and securely using a Gnosis Safe combined with Zodiac modules. This removes manual, trust-based payouts.
- Reality Module: Uses the Reality.eth oracle to verify the outcome of a Snapshot vote and automatically triggers a transaction from the Safe.
- Delay Modifier: Adds a timelock (e.g., 24-48 hours) after a vote passes, allowing for a final review before funds are released.
- Process Flow: Snapshot vote passes → Reality.eth attests result → Delay period starts → Safe automatically executes payout to grantee's address. This creates a transparent, unstoppable funding pipeline.
Proposal Management with Tally
Tally provides a full-stack governance frontend for creating, managing, and tracking on-chain proposals, ideal for formal grant approvals.
- Governor Compatibility: Works with OpenZeppelin Governor contracts, the standard for on-chain execution.
- Workflow: Draft proposal → Snapshot temperature check → Deploy on-chain proposal via Tally → Token holders vote directly on-chain → Automatic execution if successful.
- Transparency: All proposals, votes, and execution transactions are immutably recorded on-chain and easily browsable in the Tally interface.
- Link: Tally Developer Docs
Optimistic Grants with OpenZeppelin Governor
Implement an optimistic approval model using a custom OpenZeppelin Governor contract to reduce governance overhead for small grants.
- Mechanism: A designated "Grants Committee" multisig can approve and disburse grants up to a predefined threshold (e.g., $25k).
- Challenge Period: The community has a set period (e.g., 3 days) to challenge a grant decision via a formal on-chain vote.
- Advantage: Speeds up small grant distribution while maintaining community veto power, balancing efficiency with sovereignty.
- Code Example: Extend the
Governorcontract with aproposeGrantfunction that includes the challenge window logic.
Metrics and Reporting with Dune & Subgraphs
Track the impact and financials of your grants program using on-chain analytics. Transparency is key for continued treasury funding.
- Dune Dashboards: Create public dashboards to track total funds disbursed, number of grantees, and treasury balance over time.
- The Graph Subgraph: Index grant proposal, vote, and payout events from your smart contracts for easy querying and integration into your frontend.
- Key Metrics: Grant Success Rate (% of funded projects delivering milestones), ROI Tracking (value generated vs. funds spent), and Community Participation (unique voters per grant round). Regular reporting builds trust and justifies the program's budget.
Governance Framework Comparison: OpenZeppelin Governor vs. Tally
A side-by-side analysis of the core technical frameworks for implementing on-chain governance in a grants program.
| Feature / Metric | OpenZeppelin Governor | Tally |
|---|---|---|
Core Architecture | Modular smart contract library | Integrated governance platform |
Deployment Model | Self-hosted, custom deployment | Managed service with UI |
Voting Token Standard | ERC-20, ERC-721, ERC-1155 | Primarily ERC-20 |
Gas Cost for Proposal Creation | $50-200 (varies by network) | $0 (sponsored by Tally) |
Time-lock Support | Native integration via OpenZeppelin | Requires custom integration |
Off-chain Voting (Snapshot) | Requires custom integration | Native integration and UI |
Vote Delegation | Built into Governor contracts | Built-in with delegation dashboard |
Real-time Analytics & UI | None (requires custom build) | Comprehensive dashboard provided |
Step 1: Define the Grant Proposal Standard
A well-structured proposal standard is the cornerstone of a transparent and efficient grants program. This step defines the data model for all submissions.
Before deploying any smart contracts, you must define the data structure for a grant proposal. This standard ensures all submissions contain the necessary information for voters to make informed decisions and for the treasury to execute payments. A common approach is to model proposals as structs within a Solidity smart contract, containing fields like id, proposer, title, description, requestedAmount, recipientAddress, and status. This on-chain record becomes the single source of truth for the proposal's lifecycle.
Consider what information is essential for your community. Beyond basics, you may want to include a milestones array to track deliverables, a category field (e.g., Development, Marketing, Research), or links to external documents like a technical specification or budget breakdown stored on IPFS or Arweave. The standard should balance completeness with simplicity to avoid discouraging applicants. Tools like OpenZeppelin's Governor contract use a similar pattern, where proposal metadata is often stored off-chain via a URI pointing to a JSON file that conforms to a schema.
Here is a simplified example of a proposal struct and a function to create one. This code defines the core data and an initial state.
soliditystruct GrantProposal { uint256 id; address proposer; address beneficiary; uint256 amount; string title; string descriptionHash; // IPFS hash of full description uint256 voteStart; uint256 voteEnd; bool executed; uint256 forVotes; uint256 againstVotes; } function createProposal( address _beneficiary, uint256 _amount, string memory _title, string memory _descriptionHash ) public returns (uint256) { proposalCount++; proposals[proposalCount] = GrantProposal({ id: proposalCount, proposer: msg.sender, beneficiary: _beneficiary, amount: _amount, title: _title, descriptionHash: _descriptionHash, voteStart: 0, // To be set when voting starts voteEnd: 0, executed: false, forVotes: 0, againstVotes: 0 }); return proposalCount; }
Your standard must also define the proposal lifecycle states. A typical flow is: Pending -> Active (voting period) -> Succeeded/Defeated -> Queued -> Executed. Each state transition is governed by the contract's logic, such as moving from Succeeded to Queued after a timelock delay for security. Clearly documenting this state machine is crucial for both developers building the interface and community members understanding the process.
Finally, align your technical standard with the submission form on your frontend application. The form should collect all data defined in the on-chain struct, hash large descriptions to IPFS, and call the appropriate contract function. Using a framework like Governor Bravo from Compound provides a battle-tested standard, but customizing your own allows for tailored fields like projectDuration or expectedImpact. The key is consistency; this standard will be used for storage, voting, and ultimately, the dispersal of funds.
Step 2: Deploy the Governance and Treasury Contracts
This step establishes the on-chain decision-making and fund management systems for your grants program. We'll deploy a Governor contract for voting and a Treasury contract to hold and distribute funds.
The governance contract is the engine of your program. Using a standard like OpenZeppelin Governor provides a battle-tested foundation for proposals and voting. You'll configure key parameters: the voting delay (time between proposal submission and voting start), voting period (duration votes are open, e.g., 3-7 days), and proposal threshold (minimum token balance required to submit a proposal). For a grants program, a lower threshold encourages participation, while a longer voting period allows for thorough community discussion.
The treasury contract acts as the program's bank. A multisig wallet controlled by elected council members is a common starting point for security. For more decentralized control, you can use a TimelockController contract. This introduces a mandatory delay between a governance vote passing and the funds being released, giving the community a final safety window to cancel malicious transactions. The treasury holds the grant pool funds (e.g., in ETH, USDC, or your project's native token) and will execute transfers based on passed proposals.
Deployment involves writing and running a script. Below is a simplified example using Hardhat and OpenZeppelin contracts, deploying a Governor with a 1-block voting delay, a 3-day (45818 blocks) voting period, and a Timelock-controlled treasury. The Token address refers to the ERC-20 voting token deployed in Step 1.
javascript// scripts/deploy-governance.js const { ethers } = require("hardhat"); async function main() { const [deployer] = await ethers.getSigners(); const tokenAddress = "0x..."; // Your ERC-20 token address // 1. Deploy Timelock const Timelock = await ethers.getContractFactory("TimelockController"); const timelock = await Timelock.deploy(2 * 60 * 60, [], []); // 2-hour delay // 2. Deploy Governor const Governor = await ethers.getContractFactory("GovernorContract"); const governor = await Governor.deploy( tokenAddress, timelock.address, 1, // Voting Delay (blocks) 45818, // Voting Period (~3 days in blocks) 0 // Proposal Threshold ); // 3. Setup roles: Grant the Governor the PROPOSER role on the Timelock const PROPOSER_ROLE = await timelock.PROPOSER_ROLE(); await timelock.grantRole(PROPOSER_ROLE, governor.address); console.log("Timelock deployed to:", timelock.address); console.log("Governor deployed to:", governor.address); }
After deployment, you must verify the contracts on a block explorer like Etherscan or Blockscout. This provides transparency, allowing anyone to read the contract code and verify its functionality. Next, fund the treasury by transferring the initial grant pool (e.g., 100,000 USDC) to the Timelock contract address. Finally, publish the contract addresses and a link to the verified source code in your project's documentation and forum, completing the public setup of your program's core infrastructure.
Step 3: Configure Voting Mechanics and Rounds
Define the core on-chain logic for how your community will evaluate and select grant proposals.
The voting mechanism is the engine of your grants program. You must decide on a voting strategy that determines vote weighting and eligibility. Common strategies include token-weighted voting (1 token = 1 vote), which is simple but can favor whales, and quadratic voting, which reduces whale influence by squaring the number of tokens used. For community-focused grants, one-person-one-vote (1p1v) using soulbound tokens or verified credentials can be more inclusive. Your choice will define the program's governance philosophy and must be encoded into your smart contracts.
Next, configure the voting round parameters. This includes setting the votingDelay (time between proposal submission and voting start), votingPeriod (duration votes are open, e.g., 7 days), and quorum (minimum participation threshold for a vote to be valid). For example, an OpenZeppelin Governor-based contract might initialize with votingDelay = 1 day, votingPeriod = 5 days, and quorum = 4% of total voting power. These settings balance efficiency with sufficient community deliberation.
You also need to establish proposal thresholds. This defines who can submit a proposal, often by requiring a minimum token balance or a deposit. A common pattern is to allow any token holder to propose, but require their proposal to gain a minimum number of sponsorship signatures from other delegates before it moves to a full vote. This prevents spam and ensures only serious proposals reach the community. Implement this logic in your contract's propose function.
Finally, decide on the vote counting method. The standard is simple majority, where >50% of votes cast decides the outcome. For significant treasury allocations, you may require a supermajority (e.g., 66% or 75%). Some programs also implement vote delegation, allowing token holders to delegate their voting power to experts or stewards. All these rules are enforced on-chain, creating a transparent and tamper-proof selection process for funding community projects.
Step 4: Integrate with a Frontend (Tally, Builder)
Deploy a user-friendly interface for your on-chain grants program using popular governance frontends.
With your smart contracts deployed and your governance token configured, the next step is to provide a user interface for your community. Frontends like Tally and Builder (formerly Boardroom) are specialized platforms that abstract away the complexity of directly interacting with governance contracts. They provide a unified dashboard for creating proposals, voting, delegating tokens, and tracking governance history. Integrating with these platforms is primarily a configuration task, as they are designed to work with standard governance frameworks like OpenZeppelin Governor and Compound's Governor Bravo.
To integrate with Tally, you first need to add your DAO to their directory. Visit the Tally DAO Directory and click "Add your DAO." You will need to provide your DAO's name, description, and the Ethereum mainnet address of your deployed Governor contract. Tally will automatically index your contract's events to display proposals, votes, and delegate information. Ensure your token contract implements the standard ERC20Votes or ERC20VotesComp interface for proper vote power tracking.
For Builder, the process is similar. Navigate to the Builder App and connect your wallet. Use the "Add Space" feature, inputting your Governor contract address and your governance token address. Builder supports multiple networks, so select the one where your contracts are live (e.g., Ethereum, Arbitrum, Optimism). The platform will fetch your DAO's details and populate a dedicated space where members can interact with your governance system. Both platforms offer custom branding options for a cohesive experience.
These frontends handle critical user flows. They enable token holders to delegate their voting power without writing transactions, create proposals using structured forms, vote on active proposals with clear options (For, Against, Abstain), and execute successful proposals once the voting period ends. They also display real-time quorum and vote thresholds, helping voters understand the proposal's status. This dramatically lowers the barrier to participation compared to manual contract interaction.
For advanced customization, you can fork the open-source frontend code of these platforms or use their APIs to build a custom interface. However, for most community grants programs, using the hosted platforms provides a secure, maintained, and immediately functional solution. Your final step is to announce the live frontend URL to your community, along with clear documentation on how to delegate tokens and participate in the inaugural grant funding round.
Frequently Asked Questions
Common technical questions and solutions for developers implementing on-chain grant programs. This FAQ covers smart contract mechanics, voting models, and operational best practices.
The three primary models are token-weighted voting, quadratic funding, and conviction voting.
- Token-weighted voting: Each voter's influence is proportional to their token holdings (e.g., 1 token = 1 vote). This is simple but can lead to whale dominance.
- Quadratic funding: Voting power is calculated as the square root of the amount committed, then summed and matched. This model, used by Gitcoin, favors projects with broad community support over a few large contributions.
- Conviction voting: Voters stake tokens on proposals over time, and voting power accumulates based on the duration of the stake. This is designed for continuous funding, as seen in Commons Stack and 1Hive gardens.
The choice depends on your goals: maximizing participation (quadratic), aligning with token ownership (weighted), or enabling continuous funding (conviction).
Resources and Further Reading
Key tools and references for designing, deploying, and operating a community grants program with on-chain proposal creation, voting, and fund disbursement.
Conclusion and Next Steps
Your community grants program is now live on-chain. This section summarizes the key components you've deployed and outlines pathways for future development and governance.
You have successfully implemented a foundational on-chain grants program. The core system includes a GrantFactory for proposal creation, a QuadraticVoting or ERC20Voting contract for community decision-making, and a Treasury with a TimelockController for secure, automated fund distribution. By using a modular architecture, you've separated the logic for proposal management, voting, and treasury operations, making the system easier to audit and upgrade. The use of a timelock ensures a mandatory review period between a vote passing and funds being released, a critical security measure for any DAO treasury.
The next phase involves operationalizing and evolving the program. Begin by establishing clear off-chain processes: a public grants charter, application templates, and community forums for discussion. Use tools like Snapshot for temperature checks before formal on-chain proposals. Monitor key metrics such as proposal throughput, voter participation rates, and the impact of funded projects. Consider integrating sybil-resistant identity providers like Gitcoin Passport or BrightID to enhance the integrity of your quadratic voting mechanism and prevent manipulation.
For technical enhancements, explore upgrading your voting contract to support vote delegation, allowing less active members to delegate their voting power to trusted stewards. Implement batching for treasury transactions to save on gas costs when distributing funds to multiple grantees. You could also add support for streaming payments via Sablier or Superfluid, releasing funds based on milestone completion rather than in a lump sum. Always ensure any contract upgrades follow your DAO's governance process, typically involving a separate proposal to upgrade the proxy contract's implementation.
Finally, remember that a grants program is a dynamic community tool. Regularly solicit feedback through governance forums and retrospective votes. Be prepared to iterate on the contract parameters—like proposal thresholds, voting periods, and grant sizes—based on what you learn. The goal is to create a flywheel where successful grants build community trust, which in turn increases participation and funds more ambitious projects. Your on-chain foundation provides the transparency and automation needed to scale this process sustainably.