Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
LABS
Guides

Setting Up an On-Chain Voting Framework with Off-Chain Deliberation

A technical guide for implementing a two-phase governance system: off-chain discussion and signaling followed by binding on-chain execution.
Chainscore © 2026
introduction
INTRODUCTION

Setting Up an On-Chain Voting Framework with Off-Chain Deliberation

This guide explains how to build a hybrid governance system that combines the security of on-chain execution with the flexibility of off-chain discussion.

On-chain voting frameworks like OpenZeppelin Governor provide a secure, transparent mechanism for executing decisions, but they often lack the space for nuanced discussion. Off-chain deliberation platforms such as Snapshot or Discourse allow communities to debate proposals freely before committing them to the blockchain. This hybrid model separates the signal-gathering phase from the binding execution phase, creating a more resilient and informed governance process. It is the standard approach for major DAOs like Uniswap and Compound.

The core architecture involves three key components: a deliberation forum for discussion, a signaling tool (often using token-weighted votes) to gauge sentiment, and an on-chain governance contract to execute passed proposals. The on-chain contract is typically built using a standard like EIP-712 for structured data signing or a full Governor implementation with a TimelockController for security. This separation mitigates risks like gas wars during debates and allows for proposal refinement before incurring on-chain costs.

Setting up the off-chain layer usually begins with configuring a Snapshot space. This involves connecting a wallet, setting voting strategies (e.g., token-weighted, quadratic), and defining space admins. Proposals are created off-chain with a title, description, and choices. Voting occurs via cryptographically signed messages, which are free and do not require gas. This process creates a clear, tamper-proof record of community sentiment that can be referenced when submitting the final, executable proposal on-chain.

The on-chain system requires deploying smart contracts. A common setup uses OpenZeppelin's Governor contracts. You would deploy a Governor contract (e.g., GovernorCompatibilityBravo), a TimelockController for delayed execution, and the governance token itself. The Governor is configured with parameters like votingDelay, votingPeriod, and quorum. The Timelock becomes the executor, meaning passed proposals are queued in the Timelock before execution, giving users time to react to malicious proposals.

The final step is bridging the two systems. After a Snapshot vote passes, a community member (a Proposer) must formally submit the transaction data to the on-chain Governor contract. This involves calling the propose function with the target addresses, values, and calldata for execution. This proposal then goes through the Governor's on-chain voting period, allowing token holders to vote again—this time with gas—to finally queue it in the Timelock. This dual-vote system ensures off-chain consensus is ratified by on-chain economic stake.

This framework balances agility with security. Off-chain tools enable rapid iteration and inclusive discussion, while the on-chain layer guarantees immutable execution and protects the protocol's treasury. Developers must carefully align voting power and quorum rules between both layers to prevent governance attacks. The result is a robust system suitable for managing upgrades, treasury allocations, and parameter changes in a decentralized organization.

prerequisites
SETUP REQUIREMENTS

Prerequisites

Before building an on-chain voting system with off-chain deliberation, you need to establish the foundational technical environment and understand the core architectural components.

The first prerequisite is a development environment for writing and testing smart contracts. You will need Node.js (v18 or later) and a package manager like npm or yarn. A blockchain development framework is essential; we recommend Hardhat or Foundry for their robust testing suites and local network capabilities. Install your chosen framework and create a new project. You will also need a code editor like VS Code with Solidity support.

Next, you must understand the two core parts of the system. The on-chain component is a smart contract deployed to a blockchain like Ethereum, Arbitrum, or Optimism. It handles the immutable record of proposals, voting power (often via token balances), and the final execution of passed votes. The off-chain component is a backend service or indexer that hosts discussion forums, aggregates sentiment, and can generate cryptographic proofs (like Merkle roots) of off-chain activity to be submitted on-chain.

You will need a basic understanding of Solidity for the voting contract, focusing on state variables, access control (using OpenZeppelin's libraries), and secure voting logic. Familiarity with a backend language like JavaScript/TypeScript (with Node.js and Express) or Python (with FastAPI) is required for the off-chain server. Knowledge of IPFS (InterPlanetary File System) is beneficial for storing proposal details and discussion threads in a decentralized manner, using libraries like ipfs-http-client.

For wallet integration and user interaction, you must be comfortable with Ethers.js v6 or viem libraries. These are used to connect the frontend to both the blockchain and the user's wallet (e.g., MetaMask). You should also set up a .env file to manage sensitive configuration like private keys for deployment and RPC URLs for connecting to networks like Sepolia or a local Hardhat node.

Finally, plan your data flow. The off-chain server typically needs to listen for on-chain events (new proposals) using an RPC provider or The Graph. It should have a database (PostgreSQL or a lightweight option like SQLite) to store discussion data and user profiles. Ensure you have a plan for generating and verifying any proofs that bridge off-chain deliberation to on-chain voting, which may involve cryptographic libraries such as merkletreejs.

system-architecture
SYSTEM ARCHITECTURE OVERVIEW

Setting Up an On-Chain Voting Framework with Off-Chain Deliberation

This guide explains the hybrid architecture for decentralized governance, combining the finality of on-chain execution with the flexibility of off-chain discussion.

A hybrid on-chain/off-chain voting system separates the deliberation phase from the execution phase. Off-chain platforms like Discourse forums or Snapshot spaces are used for proposal discussion, amendment, and temperature checks. This allows for fluid, gas-free conversation and community signaling without committing irreversible transactions to the blockchain. The final, ratified proposal and its execution are then handled on-chain via a smart contract, ensuring transparency and immutability.

The core on-chain component is a governance smart contract, typically following standards like OpenZeppelin's Governor. This contract manages the proposal lifecycle: - Proposal Submission: A hashed version of the proposal metadata and calldata is stored. - Voting: Token holders cast votes with their governance tokens. - Execution: If the vote passes, the authorized transactions are executed. The off-chain platform must cryptographically link to this on-chain proposal ID for verifiable provenance.

Secure communication between off-chain and on-chain layers is critical. The standard pattern uses EIP-712 typed structured data signing. When a proposal is finalized off-chain, its content (target addresses, calldata, description hash) is assembled. An authorized proposer signs this structured data. The hash of this data becomes the on-chain proposal's unique identifier, preventing tampering and creating a verifiable audit trail from forum post to blockchain state change.

For voting strategies, consider moving beyond simple token-weighted voting. Integrate modules for: - Time-weighted voting (like ERC-20Votes with checkpoints) to prevent snapshot manipulation. - Delegation to experts via contracts like GovernorVotes. - Cross-chain voting using message bridges for multi-chain DAOs. The contract's voting delay and period must be configured to allow sufficient time for off-chain discussion to conclude and for voters to react to final arguments.

A complete architecture includes upgradeability and emergency safeguards. Use a transparent proxy pattern (e.g., UUPS) for the governance contract to allow for protocol improvements. Implement a timelock controller (like OpenZeppelin's TimelockController) between the governor and other protocol contracts. This introduces a mandatory delay between a vote's passage and its execution, providing a final window for the community to review and potentially cancel malicious or erroneous transactions.

To implement, start with a verified base contract like Governor from OpenZeppelin Contracts v5.0.0. Use GovernorSettings to configure parameters, GovernorVotes for token-weighted voting, and GovernorTimelockControl for execution delays. The off-chain frontend should generate EIP-712 signatures compatible with the contract's propose function. Tools like Tally or Boardroom can provide user-friendly interfaces for interacting with the deployed governance system.

key-concepts
ON-CHAIN VOTING FRAMEWORKS

Key Governance Concepts

A modular guide to building governance systems that combine on-chain execution with off-chain coordination, used by leading DAOs.

06

Designing Quorum & Voting Parameters

Setting the right governance parameters is critical for security and participation. Key considerations:

  • Quorum: The minimum voting power required for a proposal to pass. A high quorum (e.g., 4% of supply) prevents low-turnout attacks but can cause stagnation.
  • Voting Delay/Period: Time between proposal submission and voting start, and voting duration. 1-3 days for delay and 3-7 days for voting is common.
  • Proposal Threshold: The minimum token balance required to submit a proposal.

Analyze historical turnout in similar DAOs to set initial values, then adjust via governance.

step-1-off-chain-phase
FRAMEWORK DESIGN

Step 1: Designing the Off-Chain Deliberation Phase

The off-chain deliberation phase is a critical component of a hybrid governance model, where complex discussion and consensus-building happen efficiently before a proposal is finalized for an on-chain vote.

The primary goal of the off-chain phase is to refine ideas, gather community sentiment, and build consensus without incurring on-chain gas costs or forcing premature decisions. This is typically facilitated through platforms like Discourse forums, Snapshot signaling votes, or dedicated governance portals such as those used by Compound or Uniswap. Here, participants can debate proposal details, economic impacts, and technical feasibility. A well-structured forum will have clear categories for different proposal types (e.g., Treasury, Protocol Parameters, Grants) and require a minimum template for submissions to ensure all necessary information is provided upfront.

Establishing clear entry criteria for moving from discussion to an on-chain vote is essential. Common requirements include reaching a predefined threshold of forum engagement (e.g., 50 unique commenters), a minimum discussion period (e.g., 5-7 days), and a successful non-binding temperature check or signaling vote on Snapshot. This Snapshot vote uses token-weighted polling to gauge sentiment without executing a transaction on the mainnet. These gates prevent spam and ensure only well-vetted proposals with demonstrated community support proceed, conserving on-chain resources and voter attention.

The output of this phase is a fully specified, auditable proposal ready for the on-chain contract. This final draft should be immutable (e.g., posted to IPFS with a content hash like QmXoy...) and include all execution details: the target smart contract address, the exact calldata for the function call, and a comprehensive rationale. Tools like the OpenZeppelin Defender platform can help draft and simulate this calldata safely. By resolving debates and technical questions off-chain, the subsequent on-chain vote becomes a simpler, more secure binary decision to execute a specific, pre-audited transaction.

step-2-on-chain-contract
CORE INFRASTRUCTURE

Step 2: Building the On-Chain Voting Contract

This guide details the implementation of a secure, gas-efficient on-chain voting contract that records final decisions while integrating with off-chain deliberation platforms like Snapshot.

The on-chain contract is the single source of truth for governance outcomes. Its primary responsibilities are to define a proposal's lifecycle, enforce voting rules, and immutably record the result. A minimal, secure design is critical to minimize gas costs and attack surface. We'll build a contract using Solidity and the OpenZeppelin governance libraries, which provide battle-tested components for access control and state management. The contract will not handle complex discussion or vote aggregation off-chain; it will only accept and execute a finalized result.

Start by inheriting from OpenZeppelin's Governor contract. This base contract provides the standard interface (IGovernor) and core logic for proposal state (Pending, Active, Defeated, Succeeded, etc.). You must configure key parameters in the constructor: votingDelay (blocks between proposal submission and vote start), votingPeriod (blocks votes are active), and a quorum threshold. For gas efficiency with off-chain voting, set votingDelay to 1 and votingPeriod to a minimal value (e.g., 5 blocks), as the actual voting window occurs off-chain.

The core integration point is the propose function. Instead of allowing on-chain proposal creation, modify it to only accept proposals from a trusted Relayer address (controlled by your off-chain system). This relayer will call propose with the hashed proposal data (descriptionHash) after the off-chain vote concludes. Use OpenZeppelin's GovernorProposalThreshold to set the proposal threshold to zero, as eligibility is determined off-chain. The contract stores the proposal ID and its associated hash, creating an on-chain anchor.

To execute a successful vote, implement the execute function. It must verify the proposal is in the Succeeded state, then execute the encoded calldata against the target address. Crucially, add a validation step that checks the passed descriptionHash matches the one stored during propose. This prevents execution of a proposal whose details were altered after the off-chain vote. All state changes and token transfers occur within this function, secured by the Governor's timelock and access control mechanisms.

For security, employ a timelock contract (like TimelockController) as the executor. Configure the Governor to queue proposals to the timelock, which introduces a mandatory delay before execution. This gives token holders a final safety period to react if a malicious proposal somehow passes. Use OpenZeppelin's GovernorTimelockControl module for integration. Additionally, consider implementing emergency cancellation functions guarded by a multisig, allowing trusted entities to halt malicious proposals that bypass off-chain safeguards.

Finally, deploy and verify your contract on your target EVM chain (e.g., Ethereum, Arbitrum, Polygon). Use tools like Hardhat or Foundry for testing. Write comprehensive tests that simulate the full flow: off-chain proposal creation via the relayer, state transitions, and successful execution via the timelock. The contract's address and ABI will be the essential integration point for your off-chain voting interface, completing the hybrid governance loop.

step-3-integration-bridge
ON-CHAIN EXECUTION

Step 3: Creating the Integration Bridge

This step connects off-chain deliberation to on-chain execution, finalizing the voting process by securely committing results to the blockchain.

The integration bridge is a smart contract that receives the final proposal result—typically a Merkle root—from your off-chain service. Its primary function is to verify the integrity of the result using a cryptographic proof before allowing any state changes. For example, a contract using Snapshot's off-chain voting would verify a Merkle proof against the stored root to confirm a voter's choice and tally it. This design ensures the on-chain contract is the single source of truth for proposal outcomes and fund distribution, while the heavy computation of voting and tallying occurs off-chain.

Implementing the bridge requires defining a clear permission model. Common patterns include using a multi-signature wallet, a decentralized autonomous organization (DAO) with a proposal module, or a designated relayer address controlled by your backend service. The chosen entity is authorized to call the finalizeProposal(bytes32 merkleRoot) function. It's critical to include a timelock or finalization delay in this function to allow for a challenge period, where anyone can submit a fraud proof if they detect a discrepancy between the off-chain tally and the submitted root.

For developers, a basic bridge contract skeleton in Solidity includes a mapping to store proposal roots and a finalization function. You must also implement the logic for vote execution, which could be transferring tokens, updating parameters, or interacting with other DeFi protocols. Always audit this contract thoroughly, as it controls the ultimate execution of community decisions. Consider using established libraries like OpenZeppelin for access control and reviewing reference implementations from projects like Compound Governor Bravo or OpenZeppelin's Governor for standard patterns.

After deployment, the final workflow is: 1) The off-chain voting concludes and generates a final Merkle root. 2) An authorized relayer submits this root to the bridge contract. 3) After the challenge period expires, the executeProposal function becomes callable. 4) Individual voters or a batched executor can then submit their votes with Merkle proofs to trigger the on-chain action, such as releasing funds from a treasury. This two-step commit-and-execute pattern balances security with efficiency.

FRAMEWORK PHASES

Off-Chain vs. On-Chain Phase Comparison

A breakdown of the core characteristics, trade-offs, and typical tools for the deliberation and execution phases of a hybrid governance system.

FeatureOff-Chain DeliberationOn-Chain Execution

Primary Goal

Discussion, proposal formation, and consensus building

Binding settlement and state change on the blockchain

Data Location

Centralized servers, IPFS, or private databases

Immutable public blockchain ledger

Participation Cost

Typically $0 (gasless)

Requires gas fees for transactions

Finality & Immutability

Malleable; discussions can be edited or deleted

Immutable and cryptographically final

Throughput & Speed

High (handled by web servers)

Limited by blockchain block time and gas limits

Common Tooling

Discourse, Snapshot, Commonwealth

Compound Governor, OpenZeppelin Governor, Aragon OSx

Security Model

Trust in platform operator and data availability

Trust in blockchain consensus and smart contract code

Voter Identity

Flexible (web2 logins, token-gated forums)

Cryptographic (wallet addresses holding governance tokens)

step-4-proposal-lifecycle
ARCHITECTURE

Step 4: Defining the Full Proposal Lifecycle

This step integrates on-chain execution with off-chain discussion to create a complete governance system. We'll build a lifecycle from proposal creation to execution, using Snapshot for signaling and an on-chain registry for finalization.

A robust governance lifecycle separates the deliberation phase from the execution phase. This hybrid model, popularized by platforms like Compound and Uniswap, allows for extensive community debate off-chain (e.g., on forums or Snapshot) before committing irreversible transactions on-chain. The core components are a Snapshot space for off-chain voting and a proposal registry smart contract that stores approved proposals and their execution status. This separation enhances security by preventing spam and allows for more flexible discussion without gas costs for voters.

The lifecycle follows a defined state machine. A proposal begins in a Pending state after creation. It moves to Active for a Snapshot vote. If the vote passes quorum and threshold, it becomes Queued for a timelock period—a critical security feature that allows users to react to malicious proposals. Finally, it reaches Executed or Canceled. Your smart contract must enforce these transitions. For example, only a proposal in the Queued state that has passed its timelock delay can be executed.

Implementing this requires structuring your contract's data and functions. You will need a Proposal struct storing the id, snapshotId, target address, calldata, status, and timestamps. Key functions include createProposal(bytes32 snapshotId, address target, bytes calldata) to register a passed Snapshot vote, and executeProposal(uint proposalId) to execute the stored calldata on the target contract after the delay. Always verify the proposal's status and the msg.sender's authority (e.g., a multisig or the ProposalCreator role) at each step.

Integrating with Snapshot involves listening to their GraphQL API or using their EIP-712 signing utilities. Your createProposal function should validate that the provided snapshotId corresponds to a concluded vote that met your predefined criteria (e.g., a majority for 'Yes'). You can use a library like @snapshot-labs/snapshot.js in your frontend or an off-chain validator to fetch and verify vote results before allowing the on-chain proposal creation, ensuring the two systems are synchronized.

Security considerations are paramount. The timelock delay is your primary defense, giving the community time to exit protocols or prepare a response if a malicious proposal is queued. Ensure your execution function uses call or delegatecall carefully and includes reentrancy guards. Consider adding a guardian or pause mechanism for emergencies. All state transitions should be protected by access controls, typically using a system like OpenZeppelin's AccessControl to define roles such as PROPOSAL_CREATOR and EXECUTOR.

Finally, test the complete flow end-to-end. Use a forked mainnet environment with tools like Foundry or Hardhat to simulate creating a Snapshot vote, verifying it on-chain, queueing the proposal, waiting the timelock, and executing a transaction on a mock contract. This verifies that your lifecycle logic is sound and that the off-chain and on-chain states remain consistent, resulting in a trustworthy governance framework ready for production.

security-considerations
ON-CHAIN VOTING FRAMEWORK

Security and Trust Considerations

Implementing a secure on-chain voting system requires careful design to protect against manipulation, ensure voter privacy, and maintain the integrity of the deliberation process.

04

Vote Privacy and Coercion Resistance

On-chain votes are typically public, which can lead to voter coercion. To enhance privacy:

  • Zero-Knowledge Proofs (ZKPs): Use zk-SNARKs (via circom or SnarkJS) to prove a valid vote was cast without revealing the choice until a reveal phase.
  • Minimal Anti-Collusion Infrastructure (MACI): A system, pioneered by clr.fund, that uses ZKPs and a central coordinator to provide coercion resistance and collusion prevention in quadratic voting.
  • Private Voting Rollups: Consider using a privacy-focused L2 like Aztec Network, where vote logic is executed in a private environment.
06

Monitoring and Crisis Response

Continuous monitoring and clear emergency procedures are necessary for live governance systems.

  • Vote Sniping Detection: Monitor for last-block vote swings using block explorers or custom scripts, which can indicate manipulation.
  • Emergency Brakes (Pause Guards): Implement a decentralized pause mechanism, often called a "Security Council" or "Guardian," that can halt execution in case of a discovered exploit. This role should itself be governed by a separate, slower multi-sig.
  • Post-Mortem Analysis: Use event logging and tools like Tenderly to replay transactions and analyze any anomalous voting behavior after a proposal concludes.
ON-CHAIN VOTING & OFF-CHAIN DELIBERATION

Frequently Asked Questions

Common technical questions and solutions for developers implementing hybrid governance systems that combine on-chain execution with off-chain discussion.

A hybrid voting framework separates the deliberation phase from the execution phase. Off-chain platforms like Discourse, Commonwealth, or Snapshot (in signaling mode) host discussions, proposal drafts, and temperature checks. The final, ratified proposal—including its calldata and target addresses—is then submitted to an on-chain governance contract (e.g., OpenZeppelin's Governor) for a binding vote and execution. This architecture reduces gas costs for participants, allows for richer debate, and uses the blockchain as a secure settlement layer for final decisions. The critical link is a trusted proposal relay or a hash-based commitment that ensures the on-chain proposal matches the off-chain consensus.

How to Build a Hybrid On-Chain/Off-Chain Governance System | ChainScore Guides