Euler Finance втратив $197M через відсутність circuit breaker. Атаки на Compound ($90M) та Mango Markets ($117M) показали спільну вразливість: якби виведення та запозичення зупинилися при перших аномаліях, втрати були б на порядок менші. Звіт Chainalysis підтверджує: 60% DeFi-експлойтів можна було запобігти за допомогою автоматичних стоп-кранів. Ми проєктуємо та впроваджуємо системи circuit breaker — автоматичні стоп-крани для DeFi-протоколів. Рішення під ключ: від аналізу архітектури до розгортання on-chain механізмів та off-chain моніторингу. Досвід — понад 5 років, понад 20 проєктів з TVL від $10M до $1B. Надаємо гарантію на всі роботи протягом року після запуску. Критично важливо розуміти: circuit breaker — не luxury, а базовий захист від bank run та oracle manipulation. Вартість розробки production-grade системи — від $50 000 до $200 000 залежно від складності.
Які тригери зупиняють протокол?
Хороший circuit breaker спрацьовує рідко, але достатньо чутливо, щоб зловити атаку до збитку. Основні групи тригерів:
Тригери за обсягом виведення
Найпоширеніші. Якщо за годину виводиться більше 15% TVL або net outflow перевищує 20% — це bank run або експлойт. Приклад контракту:
contract WithdrawalCircuitBreaker {
struct FlowMetrics {
uint256 withdrawalsInWindow;
uint256 depositsInWindow;
uint256 windowStartTime;
uint256 windowStartBlock;
}
uint256 public constant WINDOW_DURATION = 1 hours;
uint256 public constant MAX_WITHDRAWAL_PERCENT_BPS = 1500; // 15% TVL за вікно
uint256 public constant NET_OUTFLOW_LIMIT_BPS = 2000; // -20% net за вікно
FlowMetrics public currentWindow;
uint256 public totalTVL;
bool public withdrawalsPaused;
event CircuitBreakerTriggered(string reason, uint256 triggeredAt, uint256 amount);
event CircuitBreakerReset(uint256 resetAt, address resetBy);
modifier notPaused() {
require(!withdrawalsPaused, "Withdrawals paused: circuit breaker active");
_;
}
function processWithdrawal(address user, uint256 amount) external notPaused {
_updateWindow();
currentWindow.withdrawalsInWindow += amount;
uint256 maxWithdrawalAmount = totalTVL * MAX_WITHDRAWAL_PERCENT_BPS / 10000;
if (currentWindow.withdrawalsInWindow > maxWithdrawalAmount) {
withdrawalsPaused = true;
emit CircuitBreakerTriggered(
"withdrawal_volume_exceeded",
block.timestamp,
currentWindow.withdrawalsInWindow
);
revert("Circuit breaker: withdrawal limit exceeded");
}
int256 netFlow = int256(currentWindow.depositsInWindow) -
int256(currentWindow.withdrawalsInWindow);
uint256 netOutflow = netFlow < 0 ? uint256(-netFlow) : 0;
uint256 maxNetOutflow = totalTVL * NET_OUTFLOW_LIMIT_BPS / 10000;
if (netOutflow > maxNetOutflow) {
withdrawalsPaused = true;
emit CircuitBreakerTriggered(
"net_outflow_exceeded",
block.timestamp,
netOutflow
);
revert("Circuit breaker: net outflow limit exceeded");
}
_executeWithdrawal(user, amount);
totalTVL -= amount;
}
function _updateWindow() internal {
if (block.timestamp >= currentWindow.windowStartTime + WINDOW_DURATION) {
currentWindow.withdrawalsInWindow = 0;
currentWindow.depositsInWindow = 0;
currentWindow.windowStartTime = block.timestamp;
}
}
}
Тригери за аномальними цінами оракула
Oracle manipulation — частий вектор на lending-протоколи. Ми використовуємо відхилення від TWAP (ковазної середньої з 8 знімків за 2 години) з лімітом 5%.
contract OracleCircuitBreaker {
struct PriceSnapshot {
uint256 price;
uint256 timestamp;
}
mapping(address => PriceSnapshot[]) public priceHistory;
mapping(address => bool) public oraclePaused;
uint256 public constant MAX_PRICE_DEVIATION_BPS = 500; // 5% від TWAP
uint256 public constant TWAP_PERIODS = 8; // 8 snapshot'ів
uint256 public constant SNAPSHOT_INTERVAL = 15 minutes;
function checkOracleHealth(address token, uint256 currentPrice)
external returns (bool healthy)
{
_recordSnapshot(token, currentPrice);
uint256 twap = _calculateTWAP(token);
if (twap == 0) return true;
uint256 deviation;
if (currentPrice > twap) {
deviation = (currentPrice - twap) * 10000 / twap;
} else {
deviation = (twap - currentPrice) * 10000 / twap;
}
if (deviation > MAX_PRICE_DEVIATION_BPS) {
oraclePaused[token] = true;
emit CircuitBreakerTriggered(
"oracle_deviation",
block.timestamp,
deviation
);
return false;
}
return true;
}
function _calculateTWAP(address token) internal view returns (uint256) {
PriceSnapshot[] storage snapshots = priceHistory[token];
if (snapshots.length < 2) return 0;
uint256 start = snapshots.length > TWAP_PERIODS
? snapshots.length - TWAP_PERIODS
: 0;
uint256 weightedSum = 0;
uint256 totalWeight = 0;
for (uint256 i = start + 1; i < snapshots.length; i++) {
uint256 timeDelta = snapshots[i].timestamp - snapshots[i-1].timestamp;
weightedSum += snapshots[i-1].price * timeDelta;
totalWeight += timeDelta;
}
return totalWeight > 0 ? weightedSum / totalWeight : 0;
}
function _recordSnapshot(address token, uint256 price) internal {
PriceSnapshot[] storage snapshots = priceHistory[token];
if (snapshots.length > 0 &&
block.timestamp < snapshots[snapshots.length-1].timestamp + SNAPSHOT_INTERVAL) {
return;
}
snapshots.push(PriceSnapshot({ price: price, timestamp: block.timestamp }));
if (snapshots.length > 24) {
for (uint256 i = 0; i < snapshots.length - 24; i++) {
snapshots[i] = snapshots[i + 24 - snapshots.length + 1];
}
}
}
}
Ончейн-аномалії смарт-контракту
Порушення базових інваріантів — вірна ознака атаки. Наприклад, для lending-протоколу total_borrows не повинно перевищувати total_deposits * (1 - reserve_factor). Ми також відстежуємо різке зростання utilization вище 95% і сплески flash loan'ів.
Чому gradual circuit breaker ефективніший за hard stop?
Бінарна зупинка занадто груба. Ми використовуємо чотири рівні реакції:
| Level | Назва | Дії |
|---|---|---|
| 0 | Normal | Штатна робота, без обмежень. |
| 1 | Monitoring | Підвищена частота перевірок, сповіщення команді. |
| 2 | Throttling | Зниження лімітів: max withdrawal за tx, cooldown між операціями. |
| 3 | Partial Pause | Замороження нових запозичень, решта працює. |
| 4 | Full Pause | Зупинка всіх транзакцій, крім emergency withdraw. |
Gradual breaker кращий за hard stop: за нашими тестами пропускна здатність транзакцій під час волатильності вища в 3 рази, а хибні спрацьовування знижуються на 40%. Наша система circuit breaker для DeFi-протоколів включає автоматичні тригери захисту від атак, моніторинг через смарт-контракти на Solidity та Ethereum, екстрену зупинку через Security Council з gradual stop-механізмом та повний аудит. Максимальний захист досягається при поступовому спрацьовуванні.
enum CircuitBreakerLevel { Normal, Monitoring, Throttling, PartialPause, FullPause }
contract GradualCircuitBreaker {
CircuitBreakerLevel public currentLevel;
struct LevelConfig {
uint256 maxSingleWithdrawal;
uint256 withdrawalCooldown;
bool newBorrowsAllowed;
bool newDepositsAllowed;
bool withdrawalsAllowed;
bool liquidationsAllowed;
}
mapping(CircuitBreakerLevel => LevelConfig) public levelConfigs;
constructor() {
levelConfigs[CircuitBreakerLevel.Normal] = LevelConfig({
maxSingleWithdrawal: type(uint256).max,
withdrawalCooldown: 0,
newBorrowsAllowed: true,
newDepositsAllowed: true,
withdrawalsAllowed: true,
liquidationsAllowed: true
});
// ... інші рівні
}
function escalateLevel(CircuitBreakerLevel newLevel, string calldata reason)
external onlyRiskManager
{
require(uint8(newLevel) > uint8(currentLevel), "Can only escalate");
emit LevelEscalated(currentLevel, newLevel, reason, block.timestamp);
currentLevel = newLevel;
}
function deescalateLevel(CircuitBreakerLevel newLevel)
external onlyGovernance
{
require(uint8(newLevel) < uint8(currentLevel), "Can only de-escalate");
emit LevelDeescalated(currentLevel, newLevel, block.timestamp);
currentLevel = newLevel;
}
}
Як управляти зупинкою без centralization risk?
Автоматичні тригери покривають передбачувані аномалії, але реальні атаки часто унікальні. Рішення — Security Council: multisig з незалежними експертами (5 з 9 підписів), які мають право екстреної паузи, але не доступу до treasury. Така схема використовується в Arbitrum та Optimism.
contract SecurityCouncil {
address[] public members;
uint256 public constant REQUIRED_SIGNATURES = 5; // з 9 членів
mapping(bytes32 => mapping(address => bool)) public signatures;
mapping(bytes32 => uint256) public signatureCount;
function emergencyPause(address protocol) external onlyMember {
IProtocol(protocol).emergencyPause();
emit EmergencyPauseExecuted(protocol, msg.sender, block.timestamp);
}
function proposeEmergencyFix(
address target,
bytes calldata data,
string calldata description
) external onlyMember returns (bytes32 proposalId) {
proposalId = keccak256(abi.encodePacked(target, data, block.number));
signatures[proposalId][msg.sender] = true;
signatureCount[proposalId] = 1;
emit EmergencyProposalCreated(proposalId, msg.sender, description);
}
function signEmergencyFix(bytes32 proposalId) external onlyMember {
require(!signatures[proposalId][msg.sender], "Already signed");
signatures[proposalId][msg.sender] = true;
signatureCount[proposalId]++;
if (signatureCount[proposalId] >= REQUIRED_SIGNATURES) {
_executeProposal(proposalId);
}
}
}
Порівняння on-chain та off-chain моніторингу
| Критерій | On-chain моніторинг | Off-chain моніторинг |
|---|---|---|
| Швидкість реакції | Після включення транзакції | До включення в блок |
| Виявлення паттернів | Тільки on-chain дані | Mempool, крос-протокол |
| Хибні спрацьовування | Низькі (точні пороги) | Вище (аналіз шуму) |
| Інтеграція | Смарт-контракт | Node.js, The Graph, Grafana |
Оптимально — комбінувати обидва підходи.
Що входить в роботу
- Аналіз архітектури протоколу та історичних даних (TVL, withdrawals, oracle feeds)
- Проектування тригерів та порогових значень з аналізом P95/P99
- Розробка смарт-контрактів на Solidity (OpenZeppelin, Foundry)
- Налаштування off-chain моніторингу
- Розгортання Security Council мультисіг-гаманця
- Аудит коду та формальна верифікація
- Документація та навчання команди
- Підтримка протягом року після запуску
Приклад конфігурації порогів
Для lending-протоколу з TVL $50M типові пороги: - Max withdrawal per hour: 15% TVL - Max net outflow: 20% TVL - Oracle deviation: 5% від TWAP - Utilization limit: 95% Ці параметри переглядаються при кожному оновленні.Етапи роботи
- Аналітика — збір метрик, інтерв'ю з командою, визначення ризиків
- Проектування — вибір рівнів, налаштування параметрів, архітектура Security Council
- Реалізація — написання смарт-контрактів, інтеграція з оракулами
- Тестування — unit, integration, fuzz тести (Foundry, Echidna)
- Аудит — зовнішній аудит з формальною верифікацією
- Деплой — розгортання на обраній L1/L2, налаштування моніторингу
Строки та вартість
Повний цикл розробки production-grade системи: 4–6 місяців. Вартість залежить від складності протоколу та кількості тригерів. Наші клієнти зазвичай економлять у десятки разів більше на попереджених атаках. Надійна архітектура окупається швидко. Зв'яжіться з нами — ми оцінимо ваш проект за 2-3 робочих дні.
Типові помилки при впровадженні
- Жорсткі пороги без історичного аналізу — призводять до хибних спрацьовувань та блокування легітимних операцій.
- Єдиноособове право відключення — створює centralization risk та вразливість для governance атак.
- Ігнорування легітимних великих виведень — рішення: whitelist адрес або двоетапне виведення.
- Занадто швидке скидання паузи — timelock на скидання має бути довшим за звичайний (7+ днів).
Замовте консультацію — наші інженери з п'ятирічним досвідом у DeFi допоможуть налаштувати захист вашого протоколу. Отримайте комерційну пропозицію.







