Крупный держатель токенов, участвующий в Uniswap, Compound, Aave и других DAO, ежедневно сталкивается с разными интерфейсами Governor, разной логикой пропозалов и сроками. Пропустить deadline — обычное дело. Наш агрегатор даёт единый дашборд, мониторинг, делегирование и автоматическое исполнение голосований. Опыт команды — 5+ лет, реализовано более 20 смарт-контрактов. Свяжитесь с нами — получите консультацию по архитектуре под ваш стек.
Архитектура системы
Агрегатор состоит из трёх слоёв: Indexing layer — индексирует события из Governor-контрактов через адаптеры (каждый протокол имеет свою специфику — Governor Bravo vs OZ Governor различаются). State layer — единая модель данных: пропозалы нормализованы в {id, protocol, status, deadline, description, calldata}. Action layer — on-chain или off-chain механизм исполнения голосований.
Как работают адаптеры протоколов?
Каждый Governor-совместимый контракт имеет немного разный ABI. OZ Governor v4/v5 отличается от Compound Governor Bravo, который отличается от Compound Governor Alpha. Для каждого пишется адаптер, реализующий единый интерфейс:
interface GovernorAdapter { getProposals(fromBlock: number): Promise<Proposal[]>; getProposalState(proposalId: bigint): Promise<ProposalState>; castVote(proposalId: bigint, support: number): Promise<TransactionRequest>; getVotingPower(voter: string, blockNumber: number): Promise<bigint>; } class OZGovernorAdapter implements GovernorAdapter { constructor(private contract: Contract) {} async getProposals(fromBlock: number) { const filter = this.contract.filters.ProposalCreated(); const events = await this.contract.queryFilter(filter, fromBlock); return events.map(e => this.normalizeProposal(e)); } async castVote(proposalId: bigint, support: number) { return { to: this.contract.target, data: this.contract.interface.encodeFunctionData('castVote', [proposalId, support]) }; } } class CompoundBravoAdapter implements GovernorAdapter { async castVote(proposalId: bigint, support: number) { return { to: this.contract.target, data: this.contract.interface.encodeFunctionData('castVote', [proposalId, support]) }; } } На момент разработки стоит проверить готовые адаптеры в библиотеках wagmi/viem или субграфах The Graph.
On-chain компонент: мультивызов голосований
Контракт-агрегатор позволяет голосовать в нескольких DAO одной транзакцией на основе паттерна Multicall. Код контракта минимален и проходит аудит.
contract GovernanceAggregator { struct VoteInstruction { address governor; uint256 proposalId; uint8 support; bytes reason; } mapping(address => mapping(address => bool)) public authorizedDelegates; modifier onlyAuthorized(address voter) { require( msg.sender == voter || authorizedDelegates[voter][msg.sender], "Not authorized" ); _; } function batchVote( address voter, VoteInstruction[] calldata instructions ) external onlyAuthorized(voter) { for (uint i = 0; i < instructions.length; i++) { VoteInstruction calldata inst = instructions[i]; try IGovernor(inst.governor).castVoteWithReason( inst.proposalId, inst.support, string(inst.reason) ) { emit VoteCast(voter, inst.governor, inst.proposalId, inst.support); } catch Error(string memory reason) { emit VoteFailed(voter, inst.governor, inst.proposalId, reason); } } } } Важный нюанс: каждый Governor проверяет msg.sender как voter. Агрегатор голосует от своего имени — это работает только если voting power делегирована на адрес агрегатора. Альтернативный подход — агрегатор как smart wallet с DELEGATECALL, но это усложняет безопасность.
Делегирование и пропорциональное голосование
Для ERC-20Votes токенов пользователь делегирует voting power на адрес агрегатора. Проблема: если 60% хотят For, а 40% — Against, агрегатор должен голосовать пропорционально. Решение — fractional voting: агрегатор голосует своим весом пропорционально предпочтениям. Compound Governor Bravo поддерживает castVoteWithWeightBySig, OZ Governor v5 добавил GovernorCountingFractional.
Правила автоматического голосования
Ключевая фича — автоматическое исполнение голосований по заданным правилам. Пример: всегда голосовать Against для treasury пропозалов > $1M. Off-chain сервис анализирует новые пропозалы, извлекает параметры из calldata и применяет правила. Если условия не сработали — голосование по умолчанию.
interface VotingRule { protocol: string; proposalType: string; conditions: Condition[]; defaultVote: 0 | 1 | 2; requireConfirmation: boolean; } Парсинг calldata пропозалов
Из calldata нужно извлечь смысл. Например, пропозал Compound на изменение collateral factor:
const KNOWN_SIGNATURES = { '0x3c3e4f7a': { name: 'setCollateralFactor', protocol: 'compound' }, '0x5b85a600': { name: '_setReserveFactor', protocol: 'compound' }, }; function parseProposalCalldata(calldata: string): ProposalAction { const selector = calldata.slice(0, 10); const known = KNOWN_SIGNATURES[selector]; if (!known) return { type: 'unknown', selector }; const iface = new ethers.Interface([`function ${known.name}(...)`]); const decoded = iface.decodeFunctionData(known.name, calldata); return { type: known.name, protocol: known.protocol, params: decoded }; } Это трудоёмкая работа для каждого протокола.
Уведомления и дедлайны
Система уведомлений: polling активных пропозалов каждые N минут или подписка через WebSocket (eth_subscribe logs). Уведомления по email / Telegram / webhook при создании пропозала, приближении дедлайна (за 24 часа), исполнении. Дедлайн расчёт: deadlineBlock * avgBlockTime + referenceTimestamp, точность ±5 минут.
Стек разработки
Backend: Node.js + TypeScript + viem + BullMQ + PostgreSQL. Indexing: The Graph субграфы + собственный listener. Frontend: React + wagmi + Radix UI. Smart contract: Solidity 0.8.x + Foundry.
Что входит в работу
| Компонент | Описание |
|---|---|
| Анализ протоколов | Определение поддерживаемых DAO и их Governor-контрактов |
| Разработка адаптеров | Создание нормализаторов для каждого протокола |
| Смарт-контракт агрегатора | Реализация batch vote с try/catch |
| Backend для индексации и правил | Мониторинг, парсинг, автоматическое голосование |
| Frontend дашборд | Просмотр пропозалов и управление правилами |
| Уведомления | Telegram/Email оповещения |
| Аудит безопасности | Проверка контракта и backend |
| Документация | API, правила, архитектура |
Сравнение с ручным голосованием
Агрегатор сокращает время мониторинга в 3 раза. Вместо 5–10 минут на проверку всех активных пропозалов — 1 минута на дашборде. Автоматические правила исключают человеческий фактор. Стоимость разработки MVP — от $20k–40k в зависимости от числа протоколов. Полный продукт с автоматикой — от $45k–65k. Закажите консультацию — оценим ваш проект за 1 день.
Почему наш подход надёжнее?
Каждый контракт проходит проверку на reentrancy, overflow, использует формальную верификацию с Echidna (fuzzing). Опыт команды — 5+ лет в блокчейн-разработке. Агрегатор не хранит средства пользователей, все транзакции подписываются авторизованным делегатом.
Ориентировочные сроки
| Функция | Срок |
|---|---|
| Базовый indexer (3–5 протоколов) | 2–3 недели |
| On-chain batch vote контракт | 1 неделя |
| Правила и автоматизация | 2–3 недели |
| Frontend дашборд | 2–3 недели |
| Уведомления | 1 неделя |
MVP с ручным batch voting — 4–5 недель. Полный агрегатор — 2–3 месяца. Свяжитесь с нами — мы рассчитаем стоимость и сроки под ваши протоколы.







