Розробка системи proposals DAO

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

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

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

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

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

Інтеграція з OpenZeppelin Governor

OpenZeppelin Governor — це модульний фреймворк для on-chain управління, що реалізує стандарт, сумісний з Compound Governor Bravo. Більшість DeFi протоколів з on-chain управління побудовані на цій базі або сумісні з нею: Uniswap, Compound, Gitcoin, ENS використовують контракти, сумісні з Governor. Тому інтеграція з Governor — це не просто додавання управління до вашого протоколу, це досягнення сумісності з більш широкою екосистемою інструментів: Tally, Boardroom, Snapshot (для off-chain сигналізації).

Архітектура Governor

Governor — це не один контракт, а набір модулів через множинне спадкування Solidity.

contract MyGovernor is
    Governor,
    GovernorSettings,         // voting delay, voting period, proposal threshold
    GovernorCountingSimple,   // For, Against, Abstain підрахунок
    GovernorVotes,            // інтеграція з токеном ERC-20Votes
    GovernorVotesQuorumFraction, // кворум як % від загального пропозиції
    GovernorTimelockControl  // виконання через Timelock
{
    constructor(IVotes _token, TimelockController _timelock)
        Governor("MyProtocol Governor")
        GovernorSettings(
            1 days,   // voting delay: як довго чекати після створення пропозиції
            1 weeks,  // voting period: як довго триває голосування
            10_000e18 // proposal threshold: мінімум токенів для створення пропозиції
        )
        GovernorVotes(_token)
        GovernorVotesQuorumFraction(4) // 4% від циркуляцією = кворум
        GovernorTimelockControl(_timelock)
    {}
}

Кожен модуль вирішує окрему задачу. Якщо потрібна користувацька логіка підрахунку голосів (наприклад, квадратичне голосування), замініть GovernorCountingSimple своєю реалізацією.

Життєвий цикл пропозиції

Пропозиція проходить через суворо визначені стани:

Очікування → Активна → Успішна/Поражена/Скасована → В черзі → Виконана

Створення → [voting delay] → Голосування → [voting period] → Підрахунок →
[timelock delay] → Виконання

votingDelay захищає від атак flash loan. Якщо голосування починається одразу після створення, зловмисник може купити великі токени в одному блоці, проголосувати й продати. З затримкою голосування в 1-2 дні це неможливо: токени повинні утримуватися до блоку снапшоту.

GovernorVotes фіксує голосувальну силу кожної адреси на блоці початку голосування через механізм чекпоїнту ERC-20Votes. Зміни баланса після цього блоку не впливають на вагу голосу.

Інтеграція Timelock

TimelockController — окремий контракт, який є власником ваших контрактів протоколу. Governor відправляє транзакції в чергу Timelock; після затримки (зазвичай 48–72 години) виконання стає можливим.

// Деплой TimelockController
TimelockController timelock = new TimelockController(
    2 days,           // minDelay
    proposers,        // тільки Governor може ставити в чергу
    executors,        // будь-хто може виконати (або конкретна адреса)
    admin             // після налаштування admin = address(0), видалити права admin
);

// Governor отримує PROPOSER_ROLE
timelock.grantRole(timelock.PROPOSER_ROLE(), address(governor));
// Executor — відкритий (address(0)) або конкретна адреса
timelock.grantRole(timelock.EXECUTOR_ROLE(), address(0));
// Відкликати admin (важливо!)
timelock.revokeRole(timelock.DEFAULT_ADMIN_ROLE(), deployer);

Чому відкликання admin важливо: якщо deployer зберігає DEFAULT_ADMIN_ROLE, він може будь-коли обійти управління й безпосередньо надати собі PROPOSER_ROLE. Останній крок — revokeRole admin від deployer.

Propose, Vote, Execute

Створення пропозиції

Пропозиція — це один або більше викликів функцій, виконаних, якщо голосування пройде.

// Приклад: пропозиція на змінення параметра комісії протоколу
address[] memory targets = new address[](1);
targets[0] = address(protocolContract);

uint256[] memory values = new uint256[](1); // Значення ETH, зазвичай 0
values[0] = 0;

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

string memory description = "Пропозиція #1: встановити комісію протоколу на 0.3%";

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

proposalId обчислюється як keccak256(abi.encode(targets, values, calldatas, keccak256(bytes(description)))). Це має значення: опис є частиною id, тому зміна її створює іншу пропозицію.

Голосування

// 0 = Проти, 1 = За, 2 = Утримаюсь
governor.castVote(proposalId, 1);

// З обгрунтуванням (on-chain, дорогий газ)
governor.castVoteWithReason(proposalId, 1, "Підвищує конкурентоспроможність протоколу");

// Підпис EIP-712 для безгазового голосування через relayer
governor.castVoteBySig(proposalId, 1, v, r, s);

castVoteBySig критичний для UX. Більшість емітентів не будуть платити $5–20 за on-chain голос. Безгазове голосування: користувач підписує голос off-chain, relayer (або сам протокол) відправляє транзакцію й платить газ.

Виконання

// Після успішного голосування та затримки timelock
governor.execute(targets, values, calldatas, keccak256(bytes(description)));

Налаштування: що ви можете змінити

Джерело голосувальної сили. За замовчуванням — токен ERC-20Votes. Можна замінити на: ERC-721Votes (управління NFT), користувацьке зважування (заблоковані токени важать більше), модель veToken (стиль Curve).

Кворум. GovernorVotesQuorumFraction підраховує кворум від загального пропозиції. Проблема: якщо велика частина токенів не делегована, кворум ніколи не досягається. Рішення — підраховуйте від делегованої пропозиції, не загальної. Вимагає перевизначення функції quorum().

Поріг пропозиції. Високий поріг (наприклад, 1% пропозиції) захищає від спам-пропозицій, але виключає малих емітентів. Альтернатива: поріг делегування — будь-який емітент може створити пропозицію, якщо збирає достатньо делегатів.

Tally та екосистема інструментів

Tally — это web3 дашборд управління, який працює з будь-яким контрактом, сумісним з Governor, з коробки. Після розгортання Governor на Tally він з'являється автоматично через їхній індексер. Це має значення: не потрібно будувати користувацький UI голосування з нуля.

Snapshot для off-chain сигналізації використовує підписи EIP-712 без газу. Інтеграція Governor + Snapshot: результати Snapshot служать сигналом перед on-chain пропозицією, або через модуль Snapshot у стилі Governor дозволяють binding голосування з on-chain виконанням. ENS використовує цей паттерн.

Часті помилки інтеграції

Забуття transferOwnership до Timelock. Governor + Timelock марні, якщо ваші контракти протоколу все ще належать гаманцю deployer. Повинні явно передати власність.

Неправильний кворум. 4% від загального при 30% циркуляційній ставці означає 13% від циркуляції — важко досягти. Тестуйте проти реальних даних розподілу токенів.

Відсутність ERC-20Votes у токені. Стандартний ERC-20 не підтримує чекпоїнти. Або токен спадкує ERC20Votes, або використовуйте обгортку (як wToken). Модифікуйте існуючий токен через ERC20VotesWrapper.

Графік інтеграції: стандартна інтеграція Governor з існуючим токеном — 1–2 тижні розробки плюс 1 тиждень тестування. Користувацька механіка голосування — 3–4 тижні додаткових.