Розробка управління казною DAO
Казна DAO — це не просто мультисиг гаманець з грошима. Це система управління активами, яка повинна пережити зміну команди, витримати медвежий ринок й залишитися стійкою до атак управління. MakerDAO втратила 35% вартості казни в 2022 році не через хаки — через погану розподіл нативного токена. Правильна архітектура казни починається з диверсифікації й закінчується автоматизацією виконання.
Архітектура системи казни
Сучасна казна DAO будується на кількох рівнях з різними рівнями доступу:
Рівень 1: Основна казна (Gnosis Safe + Governor)
Основне сховище активів, керованих через on-chain управління. Будь-яка видатки вимагають повного циклу управління: пропозиція → голосування → timelock → виконання. TimelockController обов'язковий посередник.
Управління Governor ──propose──► TimelockController ──execute──► Gnosis Safe
▲ (48h затримка) │
│ ▼
Емітенти токенів Активи казни
Gnosis Safe тут — остаточне сховище, не інструмент управління. Це важливо: Safe не повинен бути підписантом керованим для основних коштів.
Рівень 2: Операційний бюджет (Sub-DAO Safe)
Окремий Gnosis Safe для операційних видатків з лімітом (наприклад, $50k/місяць). Керується основною командою з 3/5 мультисигом. Фінансується з Core Treasury через звичайну пропозицію управління щоквартально.
Рівень 3: Потокові платежі (Superfluid / Sablier)
Зарплати й гранти через потокові токени — контрибьютори отримують безперервний потік токенів, який можна зупинити в будь-який момент. Немає необхідності в ручних платежах.
Смарт-контракти казни
Контролер казни
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/governance/TimelockController.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
contract DAOTreasury is AccessControl {
using SafeERC20 for IERC20;
bytes32 public constant GOVERNOR_ROLE = keccak256("GOVERNOR_ROLE");
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
// Лімити для операційних видатків без управління
mapping(address => uint256) public monthlySpendLimit;
mapping(address => mapping(uint256 => uint256)) public monthlySpent; // токен -> місяць -> сума
event FundsDisbursed(address indexed token, address indexed recipient, uint256 amount, string reason);
event AllocationUpdated(address indexed token, uint256 amount, string strategy);
constructor(address _governor, address _operator) {
_grantRole(DEFAULT_ADMIN_ROLE, _governor);
_grantRole(GOVERNOR_ROLE, _governor);
_grantRole(OPERATOR_ROLE, _operator);
}
// Виділення через управління (без лімітів)
function disburse(
address token,
address recipient,
uint256 amount,
string calldata reason
) external onlyRole(GOVERNOR_ROLE) {
IERC20(token).safeTransfer(recipient, amount);
emit FundsDisbursed(token, recipient, amount, reason);
}
// Операційні видатки з місячними лімітами
function operationalDisburse(
address token,
address recipient,
uint256 amount
) external onlyRole(OPERATOR_ROLE) {
uint256 currentMonth = block.timestamp / 30 days;
uint256 spent = monthlySpent[token][currentMonth];
require(
spent + amount <= monthlySpendLimit[token],
"Monthly limit exceeded"
);
monthlySpent[token][currentMonth] = spent + amount;
IERC20(token).safeTransfer(recipient, amount);
emit FundsDisbursed(token, recipient, amount, "operational");
}
function setMonthlyLimit(address token, uint256 limit)
external
onlyRole(GOVERNOR_ROLE)
{
monthlySpendLimit[token] = limit;
}
// Прийом ETH
receive() external payable {}
}
Потокові платежі через Sablier V2
Sablier V2 LockupLinear — стандарт для потокових платежів у DAO:
import { ISablierV2LockupLinear } from "@sablier/v2-core/interfaces/ISablierV2LockupLinear.sol";
import { LockupLinear, Broker } from "@sablier/v2-core/types/DataTypes.sol";
contract TreasuryStreaming {
ISablierV2LockupLinear public immutable sablier;
IERC20 public immutable daoToken;
// Створити потік зарплати для контрибьютора
function createContributorStream(
address contributor,
uint128 totalAmount,
uint40 startTime,
uint40 endTime,
uint40 cliffDuration,
bool cancelable
) external returns (uint256 streamId) {
daoToken.approve(address(sablier), totalAmount);
LockupLinear.CreateWithDurations memory params = LockupLinear.CreateWithDurations({
sender: address(this),
recipient: contributor,
totalAmount: totalAmount,
asset: daoToken,
cancelable: cancelable, // true для випробування
transferable: false, // неможна передати права
durations: LockupLinear.Durations({
cliff: cliffDuration, // наприклад, 3 місяці
total: endTime - startTime
}),
broker: Broker(address(0), ud60x18(0))
});
streamId = sablier.createWithDurations(params);
}
// Скасувати потік (при припиненні контрибьютора)
function cancelStream(uint256 streamId) external {
sablier.cancel(streamId);
// Невиплачені кошти автоматично повертаються в казну
}
}
Диверсифікація активів
Утримання 80%+ казни в нативному токені — стандартна помилка новачків. На медвежому ринку така казна втрачає 80-95% покупівельної спроможності й DAO не може фінансувати розробку.
Рекомендована структура для протоколу з казною $5M+
| Актив | Частка | Обґрунтування |
|---|---|---|
| Стейблкойни (USDC, DAI) | 40-50% | Операції, доріжка запасу |
| ETH | 20-30% | Рідкий резерв, yield через стейкінг |
| Нативний токен | 20-30% | Управління, стимули |
| Диверсифіковані DeFi (wBTC, тощо) | 0-10% | Опційно |
Yield на стейблкойн частини
Неактивні стейблкойни в казні — це втрачена прибуток. Популярні стратегії:
Aave/Compound: простий лендинг, 3-8% APY на USDC. Мінімальний ризик, миттєве вилучення.
Maker DSR (DAI Savings Rate): офіційна прибуток DAI від MakerDAO.
Yearn Finance: автоматизоване управління стратегіями yield. Вимагає довіри до Yearn vaults.
Пропозиція управління для кожної зміни yield стратегії — правильний підхід для прозорості.
Моніторинг та аналітика
On-chain метрики казни
// Скрипт щоденного снапшоту казни
interface TreasurySnapshot {
timestamp: number;
assets: {
token: string;
balance: bigint;
usdValue: number;
}[];
totalUsdValue: number;
runwayMonths: number; // при поточному темпі витрат
}
async function getTreasurySnapshot(
provider: ethers.Provider,
treasuryAddress: string,
tokenList: string[]
): Promise<TreasurySnapshot> {
const assets = await Promise.all(
tokenList.map(async (token) => {
const contract = new ethers.Contract(token, ERC20_ABI, provider);
const balance = await contract.balanceOf(treasuryAddress);
const price = await getTokenPrice(token); // CoinGecko API
return {
token,
balance,
usdValue: Number(ethers.formatEther(balance)) * price
};
})
);
const totalUsdValue = assets.reduce((sum, a) => sum + a.usdValue, 0);
const monthlyBurn = await getMonthlyBurnRate(); // з історичних транзакцій
return {
timestamp: Date.now(),
assets,
totalUsdValue,
runwayMonths: totalUsdValue / monthlyBurn
};
}
KPI дашборд
| Метрика | Ціль | Сигнал тривоги |
|---|---|---|
| Доріжка запасу | > 24 місяці | < 12 місяців |
| Коефіцієнт стейблів | > 40% | < 25% |
| Місячні витрати | Відомі й узгоджені | +20% перевищення |
| Yield APY | > 4% на стейбли | < 2% |
| Концентрація токенів | < 40% в нативному | > 60% |
Захист від атак управління
Поріг пропозиції: створення пропозиції видатків повинно вимагати значного залику (1%+ пропозиції). Інакше невеликий зловмисник може спробувати шкідливу пропозицію.
Timelock: обов'язкова затримка перед фінансовими операціями. Мінімум 48 годин; для великих сум — 7 днів. Дає спільноті час помітити й реагувати.
Лімити видатків: навіть через управління — не дозволяйте вилучати більше X% казни за пропозицію. Вимагайте розбиття великих видатків на частини.
Механізм вето: деякі DAO (Compound, Uniswap) мають Security Council — малий мультисиг з правами вето на рішення управління протягом періоду timelock. Використовується тільки для явно шкідливих пропозицій.
// Механізм Guardian / veto
contract TreasuryGuardian {
address public immutable securityCouncil; // 4/7 мультисиг
TimelockController public immutable timelock;
// Скасувати шкідливу пропозицію під час періоду timelock
function vetoOperation(bytes32 operationId) external {
require(msg.sender == securityCouncil, "Not security council");
timelock.cancel(operationId);
emit OperationVetoed(operationId);
}
}
Казна — це доріжка запасу DAO. Добре керована казна дозволяє протоколу пережити медвежий ринок й продовжити розробку незалежно від ціни нативного токена.







