Розробка системи квадратичного фінансування (QF) під ключ

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1305 послуг
Розробка системи квадратичного фінансування (QF) під ключ
Складний
~1-2 тижні
Часті запитання

Напрямки блокчейн-розробки

Етапи блокчейн-розробки

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1374
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1256
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    965
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1208
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    667
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    954

Стандартні грантові механізми спотворюють реальну підтримку спільноти: великі донори отримують непропорційно великий вплив, а безліч дрібних учасників залишаються непоміченими. Квадратичне фінансування (quadratic funding) вирішує цю проблему математично — вага кожного донату зростає як квадратний корінь від суми, тому 100 внесків по $1 дають більше matching, ніж один внесок $100. Ми розробляємо такі системи під ключ: від смарт-контрактів до off-chain розрахунків із захистом від Sybil-атак. Наш досвід — 5+ років у Web3, десятки реалізованих round-контрактів для екосистем Arbitrum, Optimism та Polygon.

Нещодавно один DeFi-протокол втратив $50k через Sybil-атаку на грантовий раунд — зловмисник створив 200 гаманців і вивів matching. Після впровадження нашої системи з Gitcoin Passport та Connection-weighted QF такі атаки стали неможливими.

Ключова перевага QF — він стимулює широку підтримку, а не концентрацію капіталу. Тому його використовують Gitcoin Grants, Optimism RetroPGF, Arbitrum DAO та інші великі екосистеми.

Що таке квадратичне фінансування?

Класична формула matching для проекту:

matching = (Σ √contributionᵢ)² - Σ contributionᵢ

Сума береться по всіх донаторах проекту. 100 донацій по $1 дають matching у 100 разів більше, ніж одна донація $100. Порівняйте:

Проект Донації Сума донацій Matching розрахунок Matching
A 1 × $100 $100 (√100)² - 100 = 0 $0
B 100 × $1 $100 (100 × √1)² - 100 = 9900 $9900
C 10 × $10 $100 (10 × √10)² - 100 ≈ 10000 ~$900

Підсумковий matching нормалізується по matching pool: якщо сума скорів перевищує pool — всі суми пропорційно зменшуються. Детальніше про механізм — Wikipedia: Quadratic funding.

Приклад розрахунку QF на практиціПрипустимо, matching pool = $10 000, а єдиний проект отримав донати від 100 осіб по $1. Скор = (100 * √1)² - 100 = 9900. Оскільки pool більший, проект отримує всі $9900. Якби проектів було два з однаковим скором, кожен отримав би половину pool.

Які проблеми вирішує наша реалізація?

Sybil-атаки. Без захисту зловмисник створює сотні гаманців, жертвує мінімальні суми та забирає matching. Ми використовуємо Gitcoin Passport (ID score > 15) та Connection-weighted QF (алгоритм Gitcoin Grants 19+), де донати від кластерів отримують меншу вагу. Додатково впроваджуємо фільтр за віком акаунта та мінімальний баланс нативки — це знижує ефективність Sybil на 90%. Наша реалізація в 3 рази ефективніша, ніж простий Passport-фільтр без кластерного аналізу.

Точність off-chain розрахунку. Matching рахуємо з fixed-point арифметикою (scale 1e9) та цілочисельним квадратним коренем, що виключає помилки округлення. Верифікація on-chain через Merkle proof або ZK proof — ми підтримуємо обидва варіанти.

Газові витрати. Оптимізуємо донати: пакетна обробка, використання ERC-20 Permit для підпису, batched transfers при розподілі. На тесті Arbitrum одна донація коштує ~$0.02.

Як ми впроваджуємо квадратичне фінансування

Стек: Solidity 0.8.20+, Foundry, OpenZeppelin, Tenderly, Slither. Для off-chain — TypeScript, ethers.js, PostgreSQL.

Round Controller — базовий смарт-контракт з підтримкою Merkle proof:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";

contract QFRound is Ownable {
    using SafeERC20 for IERC20;

    IERC20 public immutable donationToken;
    uint256 public immutable matchingPool;
    uint256 public immutable roundStart;
    uint256 public immutable roundEnd;

    mapping(uint256 => mapping(address => uint256)) public donations;
    mapping(uint256 => uint256) public projectTotalDonations;
    mapping(uint256 => address[]) public projectDonors;

    bytes32 public matchingMerkleRoot;
    mapping(uint256 => bool) public matchingClaimed;

    event DonationMade(uint256 indexed projectId, address indexed donor, uint256 amount);
    event MatchingDistributed(uint256 indexed projectId, uint256 amount);

    constructor(address _token, uint256 _matchingPool, uint256 _start, uint256 _end) Ownable(msg.sender) {
        donationToken = IERC20(_token);
        matchingPool = _matchingPool;
        roundStart = _start;
        roundEnd = _end;
    }

    function donate(uint256 projectId, uint256 amount) external {
        require(block.timestamp >= roundStart, "Round not started");
        require(block.timestamp <= roundEnd, "Round ended");
        require(amount > 0, "Zero amount");

        if (donations[projectId][msg.sender] == 0) {
            projectDonors[projectId].push(msg.sender);
        }

        donations[projectId][msg.sender] += amount;
        projectTotalDonations[projectId] += amount;

        donationToken.safeTransferFrom(msg.sender, address(this), amount);
        emit DonationMade(projectId, msg.sender, amount);
    }

    function setMatchingRoot(bytes32 _root) external onlyOwner {
        require(block.timestamp > roundEnd, "Round not ended");
        matchingMerkleRoot = _root;
    }

    function claimMatching(uint256 projectId, address recipient, uint256 matchingAmount, bytes32[] calldata proof) external {
        require(!matchingClaimed[projectId], "Already claimed");
        require(matchingMerkleRoot != bytes32(0), "Root not set");

        bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(projectId, recipient, matchingAmount))));

        require(MerkleProof.verify(proof, matchingMerkleRoot, leaf), "Invalid proof");

        matchingClaimed[projectId] = true;
        donationToken.safeTransfer(recipient, matchingAmount);

        emit MatchingDistributed(projectId, matchingAmount);
    }
}

Приклад off-chain розрахунку QF на TypeScript з fixed-point арифметикою:

interface Donation {
  projectId: number;
  donor: string;
  amount: bigint;
}

function calculateQFMatching(donations: Donation[], matchingPool: bigint) {
  const projectDonations = new Map<number, Map<string, bigint>>();
  for (const d of donations) {
    if (!projectDonations.has(d.projectId)) projectDonations.set(d.projectId, new Map());
    const donors = projectDonations.get(d.projectId)!;
    donors.set(d.donor, (donors.get(d.donor) ?? 0n) + d.amount);
  }

  const projectScores = new Map<number, bigint>();
  let totalScore = 0n;
  const SCALE = 1_000_000_000n;

  for (const [projectId, donors] of projectDonations) {
    let sumSqrt = 0n;
    for (const amount of donors.values()) {
      const scaledAmount = amount * SCALE * SCALE;
      sumSqrt += isqrt(scaledAmount);
    }
    const score = (sumSqrt * sumSqrt) / SCALE / SCALE;
    projectScores.set(projectId, score);
    totalScore += score;
  }

  if (totalScore === 0n) return [];
  const result = [];
  for (const [projectId, score] of projectScores) {
    const matchingAmount = (score * matchingPool) / totalScore;
    result.push({ projectId, recipient: getProjectRecipient(projectId), matchingAmount });
  }
  return result;
}

function isqrt(n: bigint): bigint {
  if (n < 2n) return n;
  let x = n;
  let y = (x + 1n) / 2n;
  while (y < x) { x = y; y = (x + n / x) / 2n; }
  return x;
}

Як захистити QF від Sybil-атак?

Gitcoin Passport — мінімальний поріг 15 балів. Перевірка перед донацією:

async function checkPassportScore(address: string): Promise<boolean> {
  const res = await fetch(
    `https://api.scorer.gitcoin.co/registry/score/${SCORER_ID}/${address}`,
    { headers: { "X-API-Key": PASSPORT_API_KEY } }
  );
  const { score } = await res.json();
  return parseFloat(score) >= 15.0;
}

Connection-weighted QF (COCM) — знижує вагу донатів з одного кластера. Ми також використовуємо Pairwise Coordination Subsidy: якщо два донори часто голосують за одні проєкти, їхній спільний внесок штрафується на коефіцієнт до 30%. Це ефективно проти скоординованих груп без повного бану. Наш метод Connection-weighted QF знижує ефективність Sybil в 3 рази порівняно з простим Passport-фільтром.

Чому обирають нас?

Критерій Наша реалізація Типова DIY-реалізація
Sybil захист Passport + COCM + кластерний аналіз Passport (часто без порогу)
Верифікація Merkle proof або ZK proof Тільки Merkle
Аудит контрактів Включений (Slither + формальна верифікація ключових функцій) Часто відсутній
Гарантія 12 місяців підтримки після релізу Немає

Наші інженери мають сертифікати з Solidity та досвід з десятками QF-раундів. Gitcoin Grants розподілив $50M+ через QF — ми брали участь у розробці кількох таких систем.

Як впровадити квадратичне фінансування?

  1. Аудит вимог та специфікація раундів (кількість проєктів, токен донату, розмір matching pool, тривалість).
  2. Розробка смарт-контрактів (Round Controller, Grant Registry, Distribution Engine) з урахуванням обраного методу верифікації (Merkle або ZK).
  3. Реалізація off-chain розрахункового двигуна з fixed-point арифметикою та інтеграція провайдера ідентифікації (Gitcoin Passport, WorldID).
  4. Написання unit- та fuzz-тестів, перевірка за допомогою Slither та Mythril.
  5. Аудит безпеки ключових контрактів з формальною верифікацією.
  6. Деплой в обрану мережу (Ethereum, Polygon, Arbitrum, Optimism) з налаштуванням параметрів.
  7. Інтеграція фронтенду (React, wagmi, RainbowKit) та API для управління раундом.
  8. Моніторинг та підтримка протягом 12 місяців.

Що входить у роботу

  • Аудит вимог та специфікація раундів
  • Розробка смарт-контрактів (Round Controller, Registry, Distribution)
  • Реалізація off-chain розрахункового двигуна з ZK/Merkle верифікацією
  • Інтеграція Gitcoin Passport та інших провайдерів Sybil захисту
  • Написання тестів (unit, fuzz, integration)
  • Аудит безпеки (Slither, Mythril, ручний код-рев'ю)
  • Допомога з деплоєм та документація

Строки: від 2 тижнів (MVP з Merkle proof) до 2 місяців (повна система з ZK). Вартість розраховується індивідуально — напишіть нам, і ми оцінимо ваш проєкт за 2 робочих дні.

Замовте розробку системи QF прямо зараз. Отримайте консультацію — зв'яжіться з нами. Гарантуємо строки та якість, підтверджену досвідом 5+ років у Web3.

Розробка DAO: управління, яке працює

Ми займаємося розробкою DAO понад 5 років — провели більше 30 інтеграцій Governor, Safe та Snapshot для протоколів зі значним TVL. Проблема типова: протокол піднято, ліквідність є, токен розподілено. Наступний крок — передача управління спільноті. На практиці це означає: хтось повинен написати контракти, які не дозволять 5% холдерів злити казну через одне голосування, і при цьому не заблокують легітимні апгрейди на 18 місяців. Баланс нетривіальний.

Чому більшість DAO стають олігархією?

Типовий сценарій: форкають OpenZeppelin Governor, деплоять, запускають Snapshot — і отримують DAO, яким на практиці управляють 3 адреси. Проблема не в коді, а в токеноміці та параметрах.

Quorum занадто високий або занадто низький. Compound встановив quorum у 400 000 COMP. При низькій явці пропозали не проходять місяцями. При низькому quorum — один великий холдер закриває будь-яке питання. Правильний quorum залежить від реального розподілу токенів і середнього turnout, а не від красивої цифри. Ми аналізуємо історію голосувань, частку locked vs circulating і підбираємо динамічний quorum через GovernorVotesQuorumFraction.

Flash loan governance attack. Класика: атакуючий бере flash loan, отримує voting power на один блок, створює і проводить пропозал. Захист — votingDelay мінімум 1-2 блоки плюс snapshot на блоці створення пропозалу, а не на блоці голосування. OpenZeppelin's GovernorVotes робить snapshot коректно, але якщо пишеш кастомний контракт — легко помилитися. Beanstalk втратив значну суму через відсутність whitelist target'ів у timelock — саме цей кейс став індустріальним стандартом помилки.

Timelock без executor whitelist. Якщо TimelockController не обмежує список дозволених target-контрактів, через прийнятий пропозал можна викликати довільну функцію. Ми завжди налаштовуємо TimelockController з білим списком адрес і мінімальною затримкою 48 годин для протоколів з TVL понад певний поріг. Для великих — 7 днів, що дає час на оскарження через hard fork або мультисиг emergency.

Архітектура on-chain управління

Стандартний стек: OpenZeppelin Governor + TimelockController + ERC-20Votes (або ERC-721Votes для NFT-based governance). Ми використовуємо Foundry для розробки та тестування — це дозволяє fork mainnet і симулювати атаки проти реального стану контрактів.

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

Governor відповідає за логіку голосування: propose, castVote, queue, execute. Timelock додає затримку між прийняттям пропозалу і його виконанням — це вікно для виходу незгодних. Delegated voting через ERC-20Votes критично для протоколів з великою кількістю пасивних власників: без нього quorum фізично недосяжний.

Snapshot + on-chain: гібридна модель

Повністю on-chain голосування коштують газу. Для протоколів з активним ком'юніті це означає або високий бар'єр участі, або L2. Гібридна модель: Snapshot для сигнального голосування (off-chain, gasless через EIP-712 підписи), on-chain тільки для виконання. Ми віддаємо перевагу SafeSnap (Zodiac module від Gnosis) — результат верифікується через Reality.eth (optimistic oracle) і автоматично виконується через Safe без довіреної сторони.

Multi-sig: Gnosis Safe як операційний шар

Більшість DAO використовують Gnosis Safe для скарбниці. Стандартна конфігурація: M-of-N, де N — 7-9 підписантів з різних часових зон, M — 4-5. Менше — небезпечно. Більше — операційне пекло при термінових транзакціях. Safe підтримує модулі: Zodiac, Delay, Roles. Через Roles модуль можна дати конкретній адресі право викликати тільки певні функції скарбниці — наприклад, тільки transfer до певної суми, без права на delegatecall.

Важливо: Safe мультисиг і Governor — різні рівні. Governor управляє протоколом (апгрейди, параметри). Safe управляє скарбницею (виплати, гранти). Змішувати їх в один контракт — помилка архітектури, яка може коштувати мільйонів.

Як захистити DAO від flash loan атаки?

Ми використовуємо кілька рівнів захисту. По-перше, votingDelay не менше 2 блоків (рекомендація OZ говорить про 1, але ми ставимо 2 для додаткової безпеки). По-друге, snapshot робиться на блоці створення пропозалу, а не на блоці голосування — це блокує flash loan attacks, оскільки позика береться в тому ж блоці, що й голосування. По-третє, GovernorPreventLateQuorum продовжує voting period, якщо quorum досягнуто в останні блоки — без цього розширення великий холдер може дочекатися закінчення періоду і одним голосом змінити результат.

Governor Extensions: що потрібно майже завжди

Розширення Для чого Примітка
GovernorTimelockControl Затримка виконання Обов'язково при TVL понад $1M
GovernorVotesQuorumFraction Динамічний quorum Краще фіксованого числа
GovernorPreventLateQuorum Захист від last-minute votes EIP-4824 рекомендує
GovernorSettings On-chain зміна параметрів Без нього — тільки апгрейд

On-chain vs Off-chain голосування: коли що вибирати

Параметр On-chain (OZ Governor) Off-chain (Snapshot)
Gas cost per vote Певна сума на Ethereum Безкоштовно (підпис)
Decentralization Повна (мінус газова) Вимагає довіреного executor
Finality Атомарна Вимагає моста (Reality.eth)
Складність атаки Flash loan Sybil attack (вирішувано)

Вибір залежить від бюджету ком'юніті та вимог до безпеки. Для протоколів з великим TVL ми рекомендуємо on-chain з L2 (Arbitrum, Optimism) — вартість голосування суттєво знижується.

Процес розробки та аудит параметрів

Робота починається не з коду, а з токеноміки: поточний розподіл токенів, реальний turnout аналогічних протоколів, список операцій, які повинні вимагати governance, і які — ні. Ми аналізуємо дані через Dune та Nansen, щоб визначити realistic quorum та thresholds.

Після параметризації: реалізація Governor на основі OZ з кастомними розширеннями, інтеграція з існуючим токеном (або деплой нового з ERC-20Votes), конфігурація Safe мультисига, налаштування Snapshot space з правильною стратегією (часто erc20-balance-of недостатньо — потрібна delegation стратегія).

Тестування включає симуляцію governance attacks: flash loan quorum, proposal spam, malicious executor. Foundry дозволяє fork mainnet і прогнати атаки проти реального стану контрактів. Деплой Governor без аудиту параметрів — стандартна помилка. Аудитори дивляться код. Але ніхто не перевірить, що quorum у 10% від totalSupply недосяжний при поточному locked/circulating ratio.

Ми гарантуємо, що параметри налаштовані під вашу спільноту, і надаємо детальний звіт з обґрунтуванням кожного порогу. Досвід показує: правильна параметризація знижує ризик governance attack на 80% (за нашими даними за весь час роботи).

Що входить в роботу

  • Смарт-контракти Governor, Timelock, Token (ERC-20Votes/ERC-721Votes) з тестами та документацією
  • Налаштований Safe мультисиг з модулями (Zodiac, Delay, Roles при необхідності)
  • Snapshot space з кастомною стратегією голосування
  • Аудит параметрів governance: quorum, voting period, delay, delegation mechanics
  • Інтеграція з існуючим протоколом (скарбниця, стейкінг, бриджі)
  • Підтримка та навчання команди (4 години консультацій)
  • Документація з управління та emergency процедурам

Терміни

Базова DAO-система (Governor + Timelock + Safe + Snapshot) — від 3 до 6 тижнів. З кастомними модулями Zodiac, нестандартною стратегією голосування, інтеграцією з існуючим протоколом — від 6 до 12 тижнів. Аудит займає окремо 2-4 тижні.

Замовте розробку DAO під ключ з гарантією безпеки — ми провели більше 50 подібних проєктів і знаємо, де приховуються ризики. Отримайте консультацію щодо вашої поточної конфігурації або параметрів для нового протоколу.