Аудит безпеки DeFi-протоколу
DeFi-аудит — це не формальність перед запуском. Це структурований процес виявлення вразливостей у коді, який керуватиме реальними грошима без можливості екстреного патчу. За останні три роки через експлойти в DeFi витекло понад $5 мільярдів. Більшість зломів — не екзотичні атаки нульового дня, а класичні вразливості: reentrancy, integer overflow, некоректна валідація стану, маніпуляція ціною через flash loan.
Хороший аудит знаходить ці проблеми до того, як їх знаходять зловмисники.
Що включає професійний DeFi-аудит
Ручний перегляд коду
Автоматичні інструменти (Slither, Mythril) знаходять ~30-40% типових вразливостей. Решта — ручний аналіз. Аудитор читає код як атакуючий: які інваріанти мають дотримуватися? Що станеться, якщо кожен буде порушений? Як можна змусити контракт порушити власні інваріанти?
Конкретні вектори, що перевіряються вручну:
Reentrancy. Включаючи cross-function reentrancy (атака через іншу функцію того ж контракту) та cross-contract reentrancy (контракт A реентрує контракт B через callback). Приклад: у Curve у 2023 році вразливість reentrancy у компіляторі Vyper дозволила атакувати кілька пулів, загальні втрати $62M.
// Вразливий паттерн
function withdraw(uint256 amount) external {
balances[msg.sender] -= amount;
(bool success,) = msg.sender.call{value: amount}(""); // вразливість якщо msg.sender — контракт
require(success);
}
// Правильно: CEI паттерн (Checks-Effects-Interactions)
function withdraw(uint256 amount) external nonReentrant {
require(balances[msg.sender] >= amount, "Insufficient");
balances[msg.sender] -= amount; // Effect спочатку
(bool success,) = msg.sender.call{value: amount}(""); // Interaction останньою
require(success, "Transfer failed");
}
Маніпуляція Oracle. Протоколи, що використовують spot price з AMM пулу як oracle, вразливі до flash loan атак: зловмисник у одній транзакції (1) бере flash loan, (2) маніпулює ціною в пулі, (3) експлуатує протокол за спотвореною ціною, (4) повертає кредит. Mango Markets ($114M), Euler Finance ($197M) — маніпуляція oracle у числі векторів.
Перевірка: використовує ли протокол TWAP (time-weighted average price) з Uniswap v3, Chainlink чи власний VWAP? Одноблокові маніпуляції через flash loan можливі тільки проти spot price.
Контроль доступу. Хто може викликати привільовані функції? Правильно ли налаштовані ролі? Чи є функції без onlyOwner/onlyRole, які мають бути захищені? Номінальний паттерн: перевіряємо кожну external та public функцію на предмет того, чи має вона бути обмежена.
Формальна верифікація
Для критичних математичних інваріантів — формальна верифікація через Certora Prover або Halmos (symbolic execution на Foundry). Приклад інваріанта lending протоколу: «сумарна задолженість всіх позичальників ніколи не перевищує сумарні депозити плюс накопичені відсотки».
Certora Prover працює з CVL (Certora Verification Language) — декларативна мова для опису властивостей:
rule totalDebtNeverExceedsDeposits {
uint256 totalDebt = getTotalDebt();
uint256 totalDeposits = getTotalDeposits();
uint256 accruedInterest = getAccruedInterest();
assert totalDebt <= totalDeposits + accruedInterest;
}
Якщо правило порушується — Prover генерує контрприклад: конкретну послідовність викликів, що призводить до порушення. Це не просто тест — це математичне доведення для всіх можливих вхідних даних.
Економічний аналіз атак
Технічна коректність коду — необхідна, але недостатня умова. Економічно грамотний атакуючий може експлуатувати protocol mechanics без жодної технічної вразливості.
Атаки через price impact. Якщо протокол використовує on-chain pricing з недостатнім slippage protection — великі угоди можуть рухати ціну невигідно для протоколу.
Каскади ліквідацій. У lending протоколах: різкого падіння ціни застави → велика кількість позицій під ліквідацію → liquidators не встигають → протокол накопичує bad debt. Аналізуємо: достатня ли ліквідаційна маржа? Як поводиться протокол при 50% падінні ціни застави за один блок?
MEV та sandwich атаки. Якщо frontend дозволяє занадто високий slippage tolerance — транзакції користувачів вразливі до sandwich атак. Аудит перевіряє не тільки контракти, але й рекомендації для frontend.
Ризики, специфічні для токенів. Токени з transfer fee (дефляційні), rebase токени (AMPL, stETH), токени з функцією blacklist (USDC, USDT) — всі порушують стандартні очікування ERC-20. Протокол, що не враховує ці особливості, отримує помилки обліку.
Інструменти статичного аналізу
Slither
Slither (Trail of Bits) — найбільш потужний статичний аналізатор для Solidity. 90+ детекторів для відомих паттернів вразливостей. Запускається локально або в CI:
slither . --checklist --markdown-root https://github.com/project/repo/
Генерує звіт з класифікацією за severity: High, Medium, Low, Informational, Optimization. Більшість High findings — false positives або вже відомі паттерни, але їх потрібно верифікувати вручну.
Корисні детектори: reentrancy-eth, arbitrary-send-eth, controlled-delegatecall, msg-value-loop, tautology.
Mythril
Mythril (ConsenSys Diligence) — symbolic execution. Намагається знайти шляхи виконання, при яких assert порушується. Повільніший за Slither, глибше аналізує можливі execution paths.
Echidna (fuzzing)
Echidna (Trail of Bits) — property-based fuzzer для Solidity. Ви визначаєте інваріанти як функції з echidna_ префіксом, Echidna генерує випадкові послідовності транзакцій намагаючись порушити їх:
contract TestLendingPool is LendingPool {
// Інваріант: totalBorrowed ніколи не перевищує totalDeposited
function echidna_debt_invariant() public view returns (bool) {
return totalBorrowed() <= totalDeposited();
}
// Інваріант: баланс користувача не йде в мінус
function echidna_no_negative_balance() public view returns (bool) {
return balanceOf(msg.sender) >= 0; // uint256, завжди true — але перевіряємо overflow
}
}
Echidna особливо ефективна для виявлення edge cases у математиці: переповнення uint256, ділення на нуль, втрати precision при округленні.
Foundry invariant тести
Foundry має вбудований invariant fuzzing через invariant_ префікс. Інтегрується в існуючий тестовий набір:
function invariant_totalSharesMatchTotalAssets() public {
assertApproxEqRel(
vault.totalAssets(),
vault.totalShares() * vault.sharePrice() / 1e18,
1e15 // 0.1% допуск для округлення
);
}
Класифікація вразливостей
| Severity | Критерій | Приклади |
|---|---|---|
| Critical | Пряма втрата/крадіж коштів | Reentrancy drain, bypass контролю доступу |
| High | Значна шкода за певних умов | Flash loan price manip, помилка ліквідації |
| Medium | Обмежена шкода або складні умови | Integer rounding помилки, DoS через gas |
| Low | Мінорні проблеми або best practice | Відсутність событий, надлишкові перевірки |
| Informational | Немає впливу, але поліпшує код | Стиль коду, gas оптимізація, коментарі |
Critical та High findings мають бути виправлені до деплою. Medium — виправлені або явно задокументовані з обґрунтуванням accepted risk.
Процес та графік
Pre-audit (1 тиждень). Команда надає: фінальний код (заморожений), документацію архітектури, специфікацію інваріантів, відомі обмеження. Аудитор готує threat model та scope.
Фаза аудиту 1 (2-3 тижні). Кожен аудитор працює незалежно. Ручний review + автоматичні інструменти. Без спілкування між аудиторами — запобігання bias.
Фаза аудиту 2 (1 тиждень). Аудитори обмінюються findings, спільний аналіз спірних випадків, симуляція economic attacks.
Чорновик звіту (3-5 днів). Звіт з класифікованими findings, proof of concept для критичних вразливостей, рекомендації по виправленню.
Усунення проблем (1-3 тижні). Команда виправляє findings. Аудитори верифікують виправлення — окремий review pass.
Фінальний звіт. Публічний або приватний звіт зі статусами resolved/acknowledged/won't-fix.
Вибір аудитора
Топові компанії: Trail of Bits, OpenZeppelin, ChainSecurity, Halborn, Certik (для більших проектів), Spearbit. Незалежні дослідники через Code4rena або Sherlock — хороший спосіб отримати додаткові очі після основного аудиту.
Червоні прапори при виборі аудитора: немає публічних звітів у портфоліо, термін аудиту менше 1 тижня на >1000 строк коду, не проводять economic analysis.
Вартість аудиту (орієнтир): простий ERC-20 + staking — $10-30K, середній DeFi протокол (1000-3000 LOC) — $40-100K, складний lending/perp DEX — $100-300K+. Дорого? Порівняйте з $50-200M, втраченими у середньостатистичному DeFi exploit.







