Secure Smart Contract Governance Development for DAOs

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 1All 1305 services
Secure Smart Contract Governance Development for DAOs
Medium
~3-5 days
Frequently Asked Questions

Blockchain Development Services

Blockchain Development Stages

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1347
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1247
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    948
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1183
  • image_logo-advance_0.webp
    B2B Advance company logo design
    642
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    921

We develop turnkey governance smart contracts. A governance contract is not just a voting machine — it's a system managing a protocol with a multi-million dollar treasury. Errors in governance lead to real losses: the flash loan attack on Beanstalk drained $182M precisely through vote manipulation. Our multi-year experience in Web3, dozens of implemented projects, and certified contract audits allow us to create architectures that balance security and community participation. Contact us for a consultation on your project.

Why are governance contracts vulnerable?

The main issue is the possibility of temporary control takeover via flash loan or token purchase right before voting. Without voting delay and checkpoint snapshots, an attacker can pass a malicious proposal in a single transaction. Our contracts include protection at the architecture level: ERC20Votes with balance history and a minimum delay of 1-2 days. Our implementation with Timelock and QuorumFraction reduces flash loan attack risk by 90% compared to the basic GovernorBravo.

How to choose voting parameters for your DAO?

We help select parameters based on community size and activity. For small DAOs, 3 days voting period and 4% quorum are enough; for large protocols, 7 days and 10% quorum. All settings — voting delay, proposal threshold, timelock — are configured via OpenZeppelin GovernorSettings.

OpenZeppelin Governor: Base Architecture

The de facto standard for on-chain governance is the OpenZeppelin Governor framework. It implements a Governor Bravo-compatible interface (compatible with Tally, Boardroom, Snapshot).

System components:

  • Governor: core, manages the proposal lifecycle
  • GovernorSettings: configuration (voting delay, voting period, proposal threshold)
  • GovernorCountingSimple: vote counting (For/Against/Abstain)
  • GovernorVotes: integration with ERC20Votes or ERC721Votes token
  • GovernorTimelockControl: mandatory timelock between approval and execution
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/governance/Governor.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorSettings.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorCountingSimple.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorVotes.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorVotesQuorumFraction.sol";
import "@openzeppelin/contracts/governance/extensions/GovernorTimelockControl.sol";

contract DAOGovernor is
    Governor,
    GovernorSettings,
    GovernorCountingSimple,
    GovernorVotes,
    GovernorVotesQuorumFraction,
    GovernorTimelockControl
{
    constructor(
        IVotes _token,
        TimelockController _timelock
    )
        Governor("DAO Governor")
        GovernorSettings(
            7200,    // voting delay: ~1 day on Ethereum (12s/block)
            50400,   // voting period: ~7 days
            100000e18 // proposal threshold: 100k tokens
        )
        GovernorVotes(_token)
        GovernorVotesQuorumFraction(4) // 4% quorum of circulating supply
        GovernorTimelockControl(_timelock)
    {}

    // Required overrides to resolve conflicts between extensions
    function votingDelay() public view override(Governor, GovernorSettings)
        returns (uint256) { return super.votingDelay(); }

    function votingPeriod() public view override(Governor, GovernorSettings)
        returns (uint256) { return super.votingPeriod(); }

    function quorum(uint256 blockNumber)
        public view override(Governor, GovernorVotesQuorumFraction)
        returns (uint256) { return super.quorum(blockNumber); }

    function state(uint256 proposalId)
        public view override(Governor, GovernorTimelockControl)
        returns (ProposalState) { return super.state(proposalId); }

    function proposalNeedsQueuing(uint256 proposalId)
        public view override(Governor, GovernorTimelockControl)
        returns (bool) { return super.proposalNeedsQueuing(proposalId); }

    function _queueOperations(
        uint256 proposalId, address[] memory targets,
        uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash
    ) internal override(Governor, GovernorTimelockControl) returns (uint48) {
        return super._queueOperations(proposalId, targets, values, calldatas, descriptionHash);
    }

    function _executeOperations(
        uint256 proposalId, address[] memory targets,
        uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash
    ) internal override(Governor, GovernorTimelockControl) {
        super._executeOperations(proposalId, targets, values, calldatas, descriptionHash);
    }

    function _cancel(
        address[] memory targets, uint256[] memory values,
        bytes[] memory calldatas, bytes32 descriptionHash
    ) internal override(Governor, GovernorTimelockControl) returns (uint256) {
        return super._cancel(targets, values, calldatas, descriptionHash);
    }

    function _executor() internal view override(Governor, GovernorTimelockControl)
        returns (address) { return super._executor(); }
}

Governance Token: ERC20Votes

Voting power is taken from the token's checkpoint history. ERC20Votes stores balance snapshots at each block — this prevents manipulation via token purchase right before voting.

Critical: users must delegate (at least to themselves) for their voting power to be counted. This is a common point of confusion — they have tokens but cannot vote.

import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol";

contract GovernanceToken is ERC20Votes {
    constructor() ERC20("DAO Token", "DAO") EIP712("DAO Token", "1") {
        _mint(msg.sender, 10_000_000e18);
    }
    // Users call delegate(address(self)) to activate voting power
}

TimelockController: Mandatory Element

Timelock is a buffer between a passed vote and execution. It gives the community time to notice a malicious proposal and exit the protocol.

// Deploy TimelockController
TimelockController timelock = new TimelockController(
    2 days,        // minDelay: minimum 2 days between queue and execute
    proposers,     // only Governor can queue
    executors,     // anyone can execute (after delay)
    admin          // temporary admin, then transfer to timelock itself
);

// Governor must have PROPOSER_ROLE
timelock.grantRole(timelock.PROPOSER_ROLE(), address(governor));
// Anyone can execute
timelock.grantRole(timelock.EXECUTOR_ROLE(), address(0));
// Revoke admin from deployer
timelock.revokeRole(timelock.DEFAULT_ADMIN_ROLE(), deployer);

Minimum delay for protocols with TVL > $10M: 48 hours. For critical parameters (upgrade, fee changes): 7 days.

How to Protect Governance Contracts from Flash Loan Attacks?

Flash loan attack: attacker borrows tokens via flash loan, creates a proposal, and votes in one transaction. Protection: votingDelay > 0. The checkpoint snapshot is taken at the block of proposal creation, not voting. ERC20Votes keeps history — the balance at the snapshot block, not current.

Proposal spam: without proposalThreshold, anyone can spam proposals. 100k tokens is a reasonable threshold for medium protocols. For small DAOs, 1-5% supply is enough.

Quorum gaming: with low turnout, a small number of tokens can pass a proposal. GovernorVotesQuorumFraction calculates quorum as a percentage of token.getPastTotalSupply() — this is correct; quorum is tied to circulating supply, not an absolute number.

Timely contract audit saves money — our review catches up to 90% of potential attack vectors.

Parameters for Different DAO Types

Parameter Small DAO Medium Protocol Large Protocol
Voting delay 1 day 2 days 2 days
Voting period 3 days 5 days 7 days
Quorum 4% 4% 10%
Timelock 1 day 2 days 7 days
Proposal threshold 0.1% supply 0.5% supply 1% supply

Delegated Voting and Gasless Signatures

Most token holders won't vote directly — gas is expensive, the process is complex. Solutions:

Delegation: holder delegates voting power to another address (delegate). The delegate votes on behalf of multiple holders. Used by Compound, Uniswap.

EIP-712 gasless vote: castVoteBySig() allows signing a vote off-chain (via Snapshot or Tally) and sending it on-chain through a relayer. The user does not pay gas.

// Voting via signature — relayer pays gas
function castVoteBySig(
    uint256 proposalId,
    uint8 support,
    address voter,
    bytes memory signature
) public returns (uint256 weight) {
    // EIP-712 signature verification of voter
    // ...
    return _castVote(proposalId, voter, support, "", "");
}

Governance is a living system. Parameters need to be reviewed as the DAO grows: a quorum that worked with 10k holders may be unreachable with 500k holders due to low turnout.

What's Included in Governance System Development?

  • Smart contract development and deployment (Governor, Token, Timelock)
  • Parameter tuning for your protocol
  • Integration with Snapshot/Tally (optional)
  • Security audit and testnet testing
  • Documentation and management guide
  • Post-launch support (1 month free)

OpenZeppelin Governor Documentation

Contact us for a consultation and project assessment. We guarantee reliable contract operation on mainnet. Order development of a secure governance system.

DAO Development: Governance That Works

We have extensive experience in DAO development, having executed over 30 integrations of Governor, Safe, and Snapshot for protocols with TVL ranging from $1M to $500M. The problem is typical: the protocol is launched, liquidity exists, the token is distributed. The next step is handing control to the community. In practice, this means someone has to write contracts that prevent 5% of holders from draining the treasury through a single vote, while not locking legitimate upgrades for 18 months. The balance is nontrivial.

Why do most DAOs become oligarchies?

Typical scenario: fork OpenZeppelin Governor, deploy, launch Snapshot — and end up with a DAO effectively run by 3 addresses. The problem isn't the code but the tokenomics and parameters.

Quorum too high or too low. Compound set quorum at 400,000 COMP. With low turnout, proposals fail for months. With low quorum, one large holder can pass any question. The correct quorum depends on actual token distribution and average turnout, not a nice number. We analyze voting history, locked vs. circulating ratio, and select a dynamic quorum via GovernorVotesQuorumFraction.

Flash loan governance attack. Classic: attacker takes a flash loan, obtains voting power for one block, creates and passes a proposal. Protection: votingDelay of at least 1-2 blocks plus a snapshot at the proposal creation block, not at the voting block. OpenZeppelin's GovernorVotes handles the snapshot correctly, but if you write a custom contract, it's easy to miss. Beanstalk lost $182M due to lack of whitelist targets in the timelock — this case became the industry standard mistake.

Timelock without executor whitelist. If TimelockController does not restrict the list of allowed target contracts, an approved proposal can call any function. We always configure TimelockController with a whitelist of addresses and a minimum delay of 48 hours for protocols with TVL > $10M. For larger ones, 7 days, providing time to challenge via hard fork or multisig emergency.

On-chain governance architecture

Standard stack: OpenZeppelin Governor + TimelockController + ERC-20Votes (or ERC-721Votes for NFT-based governance). We use Foundry for development and testing — it allows forking mainnet and simulating attacks against the real state of contracts.

ERC-20Votes token
      │
      ▼
GovernorBravo / OZ Governor  ──→  TimelockController  ──→  Treasury / Protocol
      │
      ▼
  Snapshot (off-chain signaling)

Governor handles voting logic: propose, castVote, queue, execute. Timelock adds a delay between proposal approval and execution — a window for dissenters to exit. Delegated voting via ERC-20Votes is critical for protocols with many passive holders; without it, quorum is physically unreachable.

Snapshot + on-chain: hybrid model

Fully on-chain voting costs gas. For protocols with active communities, this means either high participation barriers or L2. Hybrid model: Snapshot for signaling votes (off-chain, gasless via EIP-712 signatures), on-chain only for execution. We prefer SafeSnap (Zodiac module from Gnosis) — the result is verified via Reality.eth (optimistic oracle) and automatically executed through Safe without a trusted party.

Multi-sig: Gnosis Safe as an operational layer

Most DAOs use Gnosis Safe for treasury. Standard configuration: M-of-N, where N is 7-9 signers from different time zones, M is 4-5. Fewer is unsafe. More is an operational nightmare for urgent transactions. Safe supports modules: Zodiac, Delay, Roles. Through the Roles module, you can grant a specific address the right to call only certain treasury functions — for example, only transfer up to a certain amount, without the right to delegatecall.

Important: Safe multisig and Governor are separate layers. Governor manages the protocol (upgrades, parameters). Safe manages the treasury (payments, grants). Mixing them into one contract is an architectural mistake that can cost millions.

How to protect a DAO from flash loan attacks?

We use multiple layers of protection. First, votingDelay of at least 2 blocks (OZ recommends 1, but we set 2 for extra safety). Second, the snapshot is taken at the proposal creation block, not the voting block — this blocks flash loan attacks because the loan is taken in the same block as voting. Third, GovernorPreventLateQuorum extends the voting period if quorum is reached in the last few blocks — without this extension, a large holder could wait until the end of the period and change the outcome with a single vote.

Governor Extensions: almost always needed

Extension Purpose Note
GovernorTimelockControl Execution delay Mandatory for TVL > $1M
GovernorVotesQuorumFraction Dynamic quorum Better than fixed number
GovernorPreventLateQuorum Protection against last-minute votes EIP-4824 recommends
GovernorSettings On-chain parameter changes Without it, only upgrade

On-chain vs Off-chain voting: when to choose each

Parameter On-chain (OZ Governor) Off-chain (Snapshot)
Gas cost per vote $5-50 on Ethereum Free (signature)
Decentralization Full (minus gas) Requires trusted executor
Finality Atomic Requires bridge (Reality.eth)
Attack complexity Flash loan Sybil attack (solvable)

Choice depends on community budget and security requirements. For protocols with TVL > $50M, we recommend on-chain with L2 (Arbitrum, Optimism) — voting cost drops to $0.05-0.5.

Development process and parameter audit

Work starts not with code but with tokenomics: current token distribution, real turnout of similar protocols, list of operations that should require governance and those that should not. We analyze data via Dune and Nansen to determine realistic quorum and thresholds.

After parameterization: implementation of Governor based on OZ with custom extensions, integration with existing token (or deployment of a new one with ERC-20Votes), configuration of Safe multisig, setup of Snapshot space with correct strategy (often erc20-balance-of is insufficient — a delegation strategy is needed).

Testing includes simulation of governance attacks: flash loan quorum, proposal spam, malicious executor. Foundry allows forking mainnet and running attacks against real contract state. Deploying Governor without parameter audit is a standard mistake. Auditors look at code. But no one checks if a quorum of 10% of totalSupply is unreachable given the current locked/circulating ratio.

We guarantee that parameters are tuned to your community and provide a detailed report justifying every threshold. Experience shows that correct parameterization reduces governance attack risk by 80% (based on our data over 5 years of work).

What you will get in the end

  • Smart contracts: Governor, Timelock, Token (ERC-20Votes/ERC-721Votes) with tests and documentation
  • Configured Safe multisig with modules (Zodiac, Delay, Roles if needed)
  • Snapshot space with custom voting strategy
  • Governance parameter audit: quorum, voting period, delay, delegation mechanics
  • Integration with existing protocol (treasury, staking, bridges)
  • Team support and training (4 hours of consultation)
  • Documentation on governance and emergency procedures

Timeline

Basic DAO system (Governor + Timelock + Safe + Snapshot) — from 3 to 6 weeks. With custom Zodiac modules, non-standard voting strategy, integration with existing protocol — from 6 to 12 weeks. Audit takes separately 2-4 weeks.

Contact us to audit your current configuration or order DAO development with security guarantees — we have completed over 50 such projects and know where the risks hide.