Розробка агрегатора управління кількох DAO
Великі емітенти токенів, що беруть участь в кількох DAO одночасно, стикаються з операційним хаосом: Uniswap Governor, Compound Governor, Aave AIP, ENS Governor — кожний має інший інтерфейс, логіку пропозицій, дедлайни. Пропустити дедлайн голосування — звичайна справа. Агрегатор управління вирішує це: один дашборд для моніторингу, можливість делегування та правила авто-голосування.
Архітектура системи
Три шари агрегації
Індексна шар — індексує evento з усіх відстежуваних контрактів Governor. Кожен протокол має особливості (Governor Bravo vs OZ Governor відрізняються); потрібні адаптери.
State шар — об'єднана модель даних для пропозицій з різних джерел. Нормалізація: незважаючи на різні контракти, всі пропозиції мають структуру {id, protocol, status, deadline, description, calldata}.
Action шар — on-chain або off-chain механізм для виконання голосів. Найскладніший компонент.
Адаптери протоколів
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])
};
}
}
On-chain компонент: групове голосування
Контракт-агрегатор дозволяє голосувати в кількох DAO однією транзакцією:
contract GovernanceAggregator {
struct VoteInstruction {
address governor; // адреса контракту Governor
uint256 proposalId;
uint8 support; // 0=Проти, 1=За, 2=Утримаюсь
bytes reason; // опціональне обґрунтування
}
mapping(address => mapping(address => bool)) public authorizedDelegates;
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);
}
}
}
}
Правила авто-голосування
Ключова функція — автоматичне виконання голосів за правилами:
interface VotingRule {
protocol: string; // "uniswap" | "compound" | "*"
proposalType: string; // "parameter-change" | "treasury" | "*"
conditions: Condition[];
defaultVote: 0 | 1 | 2; // Проти/За/Утримаюсь
requireConfirmation: boolean;
}
// Приклад: завжди голосуйте Проти пропозицій казни > $1M
const rule: VotingRule = {
protocol: "*",
proposalType: "treasury",
conditions: [{
field: "requestedAmount",
operator: ">",
value: 1_000_000_000000 // $1M у USDC (6 decimals)
}],
defaultVote: 0, // Проти
requireConfirmation: false
};
Сповіщення та дедлайни
Без сповіщень про дедлайни агрегатор втрачає половину цінності:
Моніторинг: опитуйте активні пропозиції кожні N хвилин або підпишіться через WebSocket.
Сповіщення: email / Telegram / webhook на: нова пропозиція, наближення дедлайну (24h), пропозиція пройшла/не пройшла.
Розрахунок дедлайну: Governor зберігає proposalDeadline як номер блоку. Конвертуйте в timestamp: deadlineBlock * avgBlockTime + referenceTimestamp. Точність ±5 хвилин достатньо.
Стек розробки
Бекенд: Node.js + TypeScript + viem + BullMQ (черги задач) + PostgreSQL (зберігання стану пропозицій).
Індексація: The Graph subgraphs для основних протоколів + власні слухачі для інших.
Фронтенд: React + wagmi + Radix UI. Ключові екрани: дашборд активних пропозицій, управління правилами, історія голосів.
Смарт контракт: Solidity 0.8.x + Foundry. Контракт агрегатора мінімальний; логіка off-chain.
Графік
| Функція | Графік |
|---|---|
| Індексер (3–5 протоколів) | 2–3 тижні |
| Контракт групового голосування | 1 тиждень |
| Правила + автоматизація | 2–3 тижні |
| Дашборд фронтенду | 2–3 тижні |
| Сповіщення | 1 тиждень |
MVP з ручним груповим голосуванням і базовим дашбордом — 4–5 тижнів. Повний агрегатор з правилами — 2–3 місяці.







