DAO Proposals System Development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
DAO Proposals System Development
Complex
~1-2 weeks
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1214
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

OpenZeppelin Governor Integration

OpenZeppelin Governor is a modular framework for on-chain governance, implementing a standard compatible with Compound Governor Bravo. Most DeFi protocols with on-chain governance are built on this foundation or compatible with it: Uniswap, Compound, Gitcoin, ENS use Governor-compatible contracts. Therefore, integrating with Governor isn't just adding governance to your protocol — it's achieving compatibility with the broader ecosystem of tools: Tally, Boardroom, Snapshot (for off-chain signaling).

Governor Architecture

Governor isn't a single contract but a set of modules via Solidity multiple inheritance.

contract MyGovernor is
    Governor,
    GovernorSettings,         // voting delay, voting period, proposal threshold
    GovernorCountingSimple,   // For, Against, Abstain counting
    GovernorVotes,            // ERC-20Votes token integration
    GovernorVotesQuorumFraction, // quorum as % of total supply
    GovernorTimelockControl  // execution via Timelock
{
    constructor(IVotes _token, TimelockController _timelock)
        Governor("MyProtocol Governor")
        GovernorSettings(
            1 days,   // voting delay: how long to wait after proposal creation
            1 weeks,  // voting period: how long voting lasts
            10_000e18 // proposal threshold: minimum tokens to create proposal
        )
        GovernorVotes(_token)
        GovernorVotesQuorumFraction(4) // 4% of circulating supply = quorum
        GovernorTimelockControl(_timelock)
    {}
}

Each module solves a separate task. If custom vote counting logic is needed (e.g., quadratic voting), replace GovernorCountingSimple with your implementation.

Proposal Lifecycle

A proposal goes through strictly defined states:

Pending → Active → Succeeded/Defeated/Canceled → Queued → Executed

Creation → [voting delay] → Voting → [voting period] → Counting →
[timelock delay] → Execution

votingDelay protects against flash loan attacks. If voting starts immediately after creation, an attacker can buy large tokens in the same block, vote, and sell. With a 1-2 day voting delay, this is impossible: tokens must be held until the snapshot block.

GovernorVotes fixes voting power for each address at voting start block via ERC-20Votes checkpoint mechanism. Balance changes after this block don't affect vote weight.

Timelock Integration

TimelockController is a separate contract that owns your protocol contracts. Governor sends transactions to Timelock queue; after delay (typically 48–72 hours) execution becomes possible.

// Deploy TimelockController
TimelockController timelock = new TimelockController(
    2 days,           // minDelay
    proposers,        // only Governor can queue
    executors,        // anyone can execute (or specific address)
    admin             // after setup admin = address(0), remove admin rights
);

// Governor gets PROPOSER_ROLE
timelock.grantRole(timelock.PROPOSER_ROLE(), address(governor));
// Executor — open (address(0)) or specific address
timelock.grantRole(timelock.EXECUTOR_ROLE(), address(0));
// Revoke admin (important!)
timelock.revokeRole(timelock.DEFAULT_ADMIN_ROLE(), deployer);

Why revoking admin is important: if deployer keeps DEFAULT_ADMIN_ROLE, they can anytime bypass governance and directly grant themselves PROPOSER_ROLE. Final step — revokeRole admin from deployer.

Propose, Vote, Execute

Creating a Proposal

A proposal is one or more function calls executed if voting passes.

// Example: proposal to change protocol fee parameter
address[] memory targets = new address[](1);
targets[0] = address(protocolContract);

uint256[] memory values = new uint256[](1); // ETH value, usually 0
values[0] = 0;

bytes[] memory calldatas = new bytes[](1);
calldatas[0] = abi.encodeWithSignature("setFee(uint256)", 30); // 0.3%

string memory description = "Proposal #1: Set protocol fee to 0.3%";

uint256 proposalId = governor.propose(targets, values, calldatas, description);

proposalId is computed as keccak256(abi.encode(targets, values, calldatas, keccak256(bytes(description)))). This matters: description is part of the id, so changing it creates a different proposal.

Voting

// 0 = Against, 1 = For, 2 = Abstain
governor.castVote(proposalId, 1);

// With reasoning (on-chain, expensive gas)
governor.castVoteWithReason(proposalId, 1, "Increases protocol competitiveness");

// EIP-712 signature for gasless voting via relayer
governor.castVoteBySig(proposalId, 1, v, r, s);

castVoteBySig is critical for UX. Most holders won't pay $5–20 for an on-chain vote. Gasless voting: user signs vote off-chain, relayer (or protocol itself) sends transaction and pays gas.

Execution

// After successful voting and timelock delay
governor.execute(targets, values, calldatas, keccak256(bytes(description)));

Customization: What You Can Change

Voting power source. By default — ERC-20Votes token. Can replace with: ERC-721Votes (NFT governance), custom weighting (locked tokens weigh more), veToken model (Curve style).

Quorum. GovernorVotesQuorumFraction counts quorum from total supply. Problem: if large token portion isn't delegated, quorum never reaches. Solution — count from delegated supply, not total. Requires overriding quorum() function.

Proposal threshold. High threshold (e.g., 1% supply) protects from spam proposals but excludes small holders. Alternative: delegation threshold — any holder can create proposal if collecting enough delegators.

Tally and Tool Ecosystem

Tally is a web3 governance dashboard working with any Governor-compatible contract out of the box. After deploying Governor on Tally it appears automatically via their indexer. This matters: no need to build custom voting UI from scratch.

Snapshot for off-chain signaling uses EIP-712 signatures without gas. Governor + Snapshot integration: Snapshot results serve as signal before on-chain proposal, or through Governor-style Snapshot module enable binding voting with on-chain execution. ENS uses this pattern.

Common Integration Mistakes

Forgetting to transferOwnership to Timelock. Governor + Timelock are useless if your protocol contracts still belong to the deployer wallet. Must explicitly transfer ownership.

Wrong quorum. 4% of total supply with 30% circulation rate means 13% of circulating — hard to achieve. Test against real token distribution data.

Missing ERC-20Votes in token. Standard ERC-20 doesn't support checkpoints. Either token inherits ERC20Votes or use wrapper (like wToken). Retrofit existing token through ERC20VotesWrapper.

Integration timeline: standard Governor integration with existing token — 1–2 weeks development plus 1 week testing. Custom voting mechanics — 3–4 weeks additional.