Разработка системи реагування на інциденти у блокчейні
Hack у DeFi — це не взлом у традиційному сенсі. Немає брутфорсу, немає фішингу. Атака займає одну транзакцію (іноді кілька), гроші йдуть необоротно за секунди. До моменту коли команда дізнається про інцидент — збиток вже нанесений. Єдиний спосіб мінімізувати втрати — детектувати атаку у реальному часі (в ідеалі до виконання) та мати заздалегідь підготовлені механізми зупинки.
Ronin Bridge (березень 2022, $625M) не помітив взлом 6 днів. Euler Finance (березень 2023, $197M) відреагував швидко, договорився про повернення за 2 тижні — атипічний happy ending. Різниця у підході до incident response.
Архітектура системи реагування
Система складається з трьох рівнів:
Детекція (мониторинг) — on-chain та off-chain мониторинг аномалій у реальному часі.
Реакція (circuit breaker) — набір on-chain механізмів для невідкладної зупинки критичних функцій.
Комунікація та восстановлення — процеси уведомлення, оцінки збитку, координації відповіді.
Circuit Breaker контракти
Pause механізм
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
contract ProtocolCore is Pausable, AccessControl {
bytes32 public constant GUARDIAN_ROLE = keccak256("GUARDIAN_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
// Emergency pause: окремі функції, не весь протокол
mapping(bytes4 => bool) public functionPaused;
event FunctionPaused(bytes4 indexed selector, address indexed by);
event FunctionUnpaused(bytes4 indexed selector);
event EmergencyWithdrawTriggered(address indexed asset, uint256 amount);
modifier notFunctionPaused() {
require(!functionPaused[msg.sig], "Function paused");
_;
}
// Глобальна зупинка — тільки через timelock (крім Guardian)
function pause() external {
require(
hasRole(PAUSER_ROLE, msg.sender) || hasRole(GUARDIAN_ROLE, msg.sender),
"Not authorized"
);
_pause();
}
// Возобновлення — тільки через timelock governance
function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) {
_unpause();
}
// Точкова пауза конкретної функції
function pauseFunction(bytes4 selector) external onlyRole(GUARDIAN_ROLE) {
functionPaused[selector] = true;
emit FunctionPaused(selector, msg.sender);
}
// Критична: вивести кошти у safe wallet при компрометації
function emergencyWithdraw(
address asset,
address safeDestination
) external onlyRole(GUARDIAN_ROLE) whenPaused {
require(safeDestination != address(0), "Invalid destination");
uint256 balance = IERC20(asset).balanceOf(address(this));
if (balance > 0) {
IERC20(asset).safeTransfer(safeDestination, balance);
emit EmergencyWithdrawTriggered(asset, balance);
}
}
}
Rate limiter
Не всі DeFi взломи відбуваються однією транзакцією. Часто атака — серія транзакцій. Rate limiter сповільнює відток коштів:
contract RateLimiter {
struct RateLimit {
uint256 maxAmount; // максимум за період
uint256 periodDuration; // довжина періоду в секундах
uint256 currentAmount; // витрачено в поточному періоді
uint256 periodStart; // початок поточного періоду
}
mapping(address => RateLimit) public limits; // per-asset limits
event RateLimitExceeded(address indexed asset, uint256 requested, uint256 available);
function _checkAndUpdateRateLimit(address asset, uint256 amount) internal {
RateLimit storage limit = limits[asset];
if (limit.maxAmount == 0) return; // лімітпом не встановлено
// Скидання періоду якщо істік
if (block.timestamp >= limit.periodStart + limit.periodDuration) {
limit.currentAmount = 0;
limit.periodStart = block.timestamp;
}
uint256 available = limit.maxAmount - limit.currentAmount;
if (amount > available) {
emit RateLimitExceeded(asset, amount, available);
revert("Rate limit exceeded");
}
limit.currentAmount += amount;
}
}
Мониторингова система
Мониторинг on-chain подій
Перший рівень детекції — прослуховування до подій контракту. Аномальні события для мониторингу:
interface MonitoringRule {
eventSignature: string;
condition: (event: Log) => boolean;
severity: 'low' | 'medium' | 'high' | 'critical';
action: 'alert' | 'auto-pause' | 'notify-guardian';
}
const rules: MonitoringRule[] = [
{
eventSignature: 'Withdrawal(address,uint256)',
condition: (e) => BigInt(e.data) > LARGE_WITHDRAWAL_THRESHOLD,
severity: 'high',
action: 'alert',
},
{
eventSignature: 'OwnershipTransferred(address,address)',
condition: () => true, // будь-який transfer ownership — critical
severity: 'critical',
action: 'notify-guardian',
},
];
Invariant мониторинг
Найнадійніший детектор — безперервна перевірка фінансових інваріантів:
interface ProtocolInvariant {
name: string;
check: (state: ProtocolState) => boolean;
description: string;
}
const invariants: ProtocolInvariant[] = [
{
name: 'total_supply_consistency',
check: (s) => s.totalShares * s.pricePerShare <= s.totalAssets * 1.001,
description: 'Вартість total shares не перевищує total assets',
},
{
name: 'no_sudden_tvl_drop',
check: (s) => s.currentTVL >= s.previousTVL * 0.8,
description: 'TVL не впав більше ніж на 20% за один блок',
},
];
Runbook та процеси
T+0 (перший алерт):
- Guardian on-call отримує Telegram/PagerDuty алерт
- Оцінка: false positive або реальна атака? 2-3 хвилини максимум
- Якщо сумнів — pause невідкладно, розбираємось потім
T+5 хвилин:
- Pause виконаний (або рішення не паузити)
- Уведомлення core team
- Початок on-chain розслідування (Tenderly transaction trace)
T+30 хвилин:
- Публічне уведомлення через Twitter/Discord: "We are investigating an issue"
- Оцінка збитку
- Координація з іншими протоколами (якщо cross-protocol атака)
T+24-48 годин:
- Публічний post-mortem
- План восстановлення
- Координація з біржами (заморозка адрес атакуючого)
Безпека Guardian ключа
Guardian ключ, який може паузити протокол — сам по собі вразливість. Якщо компрометований — атакуючий паузит протокол і вимагає гроші за розблокування.
Рекомендації:
- Guardian — Gnosis Safe 2/3 або 3/5, не EOA
- Hardware wallet для підписання (Ledger/Trezor)
- Географічно розподілені keyholders
- Регулярні drill-тренування (щокварталу)
- Мониторинг самого Guardian мультисига
Сроки розробки: 2-2,5 місяці. On-chain розробка (1-2 тижні), мониторингова система (2-3 тижні), runbook та тестування (2-3 тижні), інтеграція інфраструктури (1 тиждень).







