Разработка системы real-time детекции эксплойтов
Взлом Euler Finance в марте 2023 — $197M за несколько транзакций. Взлом BNB Bridge — $570M за одну транзакцию. В обоих случаях у протоколов было достаточно времени (несколько блоков, иногда несколько транзакций) чтобы заметить аномалию и остановить следующую транзакцию. Но автоматической системы детекции не было.
Real-time мониторинг смарт-контрактов — это система, которая анализирует каждую транзакцию до или во время её включения в блок, и может инициировать защитный response (pause контракта, whitelist enforcement, alert) быстрее чем атака завершится.
Существует три временных окна для детекции: mempool (транзакция отправлена, не включена — самое раннее, но только pending txs), block execution (транзакция включена в блок, но блок ещё не finalized — для chains с instant finality это не применимо), post-block (блок finalized — поздно для превентивного действия, только для alert и post-mortem).
Архитектура системы мониторинга
Mempool-уровень детекция
Самый ранний момент детекции — mempool. Транзакция отправлена атакующим, но ещё не включена в блок. Для классических атак (не MEV-bundle через private mempool) это даёт 1-12 секунд на Ethereum (время до следующего блока).
Private mempool limitation. Большинство MEV-атак на DeFi сегодня идут через private mempool (Flashbots, MEV Blocker, etc.) — транзакции напрямую к validator, не в public mempool. Mempool-мониторинг не видит такие транзакции до включения в блок. Это ограничение системы.
Тем не менее, многие protocol-level атаки (особенно multi-step: сначала borrow, потом dump, потом drain) проходят через public mempool хотя бы частично.
Блокирующий вызов через собственный node:
// Подписка на pending transactions через WebSocket
const provider = new ethers.WebSocketProvider(ALCHEMY_WS_URL);
provider.on("pending", async (txHash) => {
try {
const tx = await provider.getTransaction(txHash);
if (!tx || !tx.to) return;
// Проверяем только транзакции к нашим контрактам
if (!MONITORED_CONTRACTS.has(tx.to.toLowerCase())) return;
const risk = await analyzeTransaction(tx);
if (risk.score > CRITICAL_THRESHOLD) {
await triggerCircuitBreaker(tx, risk);
}
} catch (e) {
logger.error("Mempool analysis error", e);
}
});
Ethereum Mempool API (Blocknative, Bloxroute) предоставляют более надёжный доступ к mempool с фильтрацией по адресу. Стоит денег, но значительно надёжнее чем self-hosted нода.
Transaction simulation
Перед принятием решения о риске нужно понять что транзакция делает — не только её calldata. eth_call с текущим state позволяет симулировать исполнение без отправки в сеть:
async function simulateTransaction(tx: TransactionRequest): Promise<SimulationResult> {
// Tenderly API для детального trace с state changes
const simulation = await tenderly.simulate({
network_id: "1",
from: tx.from,
to: tx.to,
input: tx.data,
value: tx.value?.toString() ?? "0",
save: false,
});
return {
success: simulation.transaction.status,
gasUsed: simulation.transaction.gas_used,
stateChanges: simulation.transaction.transaction_info.state_diff,
events: simulation.transaction.transaction_info.logs,
balanceChanges: extractBalanceChanges(simulation),
};
}
Tenderly, Alchemy Simulate, Blocknative предоставляют simulation API. Key insight: симуляция показывает все state changes до исполнения. Если симуляция показывает что balanace протокола упадёт на >10% за одну транзакцию — это аномалия.
Invariant checking
После симуляции проверяем набор инвариантов протокола:
interface ProtocolInvariant {
name: string;
check: (stateBefore: ProtocolState, stateAfter: ProtocolState) => boolean;
severity: "critical" | "high" | "medium";
}
const INVARIANTS: ProtocolInvariant[] = [
{
name: "TVL_DROP_THRESHOLD",
check: (before, after) => {
const tvlChange = (after.tvl - before.tvl) / before.tvl;
return tvlChange > -0.10; // не более 10% падения за одну транзакцию
},
severity: "critical",
},
{
name: "PRICE_IMPACT_LIMIT",
check: (before, after) => {
if (!after.lastSwap) return true;
return Math.abs(after.lastSwap.priceImpact) < 0.20; // < 20%
},
severity: "high",
},
{
name: "BORROW_UTILIZATION",
check: (before, after) => {
return after.borrowUtilization < 0.95; // < 95%
},
severity: "high",
},
{
name: "FLASH_LOAN_IN_PROGRESS",
check: (before, after) => {
// Flash loan сам по себе не exploit, но в комбинации с другими признаками
return !after.hasActiveFlashLoan || after.flashLoanRepaid;
},
severity: "medium",
},
];
Circuit breaker integration
Обнаружить атаку недостаточно — нужно иметь механизм остановки. Варианты:
Pause Guardian. Специальный адрес (multisig или automated guardian contract) с правом вызвать pause() на протоколе. Мониторинг система может иметь privileged key для вызова pause. Риск: compromise этого ключа = DoS протокола. Митигация: pause guardian может только pauseне unpause (unpause требует Governor + Timelock).
On-chain circuit breaker. Контракт с логикой автоматической паузы при нарушении инвариантов:
contract CircuitBreaker {
uint256 public constant MAX_TVL_DROP_BPS = 1000; // 10%
uint256 public lastTVL;
bool public paused;
modifier checkCircuit() {
_;
uint256 currentTVL = getTVL();
if (lastTVL > 0) {
uint256 dropBps = (lastTVL - currentTVL) * 10000 / lastTVL;
if (dropBps > MAX_TVL_DROP_BPS) {
paused = true;
emit CircuitBreakerTriggered(lastTVL, currentTVL, dropBps);
}
}
lastTVL = currentTVL;
}
function deposit(uint256 amount) external checkCircuit {
require(!paused, "Circuit breaker active");
// ... deposit logic
}
}
On-chain circuit breaker не требует off-chain infrastructure, но добавляет gas overhead к каждой транзакции и увеличивает attack surface (можно ли манипулировать getTVL() чтобы искусственно triggerить circuit breaker?).
Defender Relayer (OpenZeppelin Defender). Defender позволяет настроить автоматические actions: при детекции аномального события — Relayer вызывает pause() от privileged address. Defender хранит приватный ключ в HSM, автоматизация настраивается через UI или code.
ML-детекция аномалий
Rule-based инварианты ловят известные паттерны. ML подходит для обнаружения неизвестных аномалий.
Feature engineering для on-chain транзакций
Признаки транзакции для классификации:
| Feature | Описание | Важность |
|---|---|---|
gas_used / gas_limit |
Высокое использование газа — сложная транзакция | Высокая |
value_transferred / pool_tvl |
Объём относительно ликвидности пула | Критическая |
call_depth |
Глубина вложенных вызовов | Высокая |
unique_contracts_touched |
Сколько контрактов вызвано | Высокая |
flash_loan_amount |
Флаг flash loan и объём | Высокая |
time_since_last_tx |
Аномально быстрые последовательные транзакции | Средняя |
sender_age |
Новый адрес — выше подозрительность | Средняя |
token_price_delta |
Изменение цены токена за транзакцию | Высокая |
Anomaly detection модели
Isolation Forest — хорошо работает для multivariate anomaly detection без labeled attack data. Обучается на нормальных транзакциях, флагирует выбросы.
LSTM Autoencoder — для sequence anomalies: серия транзакций, которая в целом аномальна. Важно для multi-step атак (несколько транзакций составляют атаку).
Gradient Boosting (XGBoost/LightGBM) — если есть labeled attack data (известные исторические взломы). Требует баланс классов (attacks редки), SMOTE для oversampling.
Training data: Forta Network, Dune Analytics, DeBank имеют исторические данные о транзакциях. Known exploit транзакции (Euler, Ronin, BNB Bridge) — negative класс. Нормальная торговля — positive класс.
Latency constraint. ML inference должна умещаться в ~200ms для mempool детекции. Простые модели (Isolation Forest, логистическая регрессия) — ок. LSTM на CPU — ~50-100ms для inference. Если нужно быстрее — GPU inference или квантизованные модели (ONNX runtime).
Интеграция с alert infrastructure
Alert routing
Детектированная аномалия должна попасть к правильному человеку быстро. Стек:
- PagerDuty / OpsGenie — для critical alerts (потенциальная атака). Звонок на телефон on-call дежурного в 3 ночи.
- Telegram / Discord bot — для high/medium alerts. Channel с мониторинг-бот.
- Grafana dashboard — real-time метрики: TVL, transaction volume, price impact, circuit breaker status.
async function routeAlert(alert: Alert) {
if (alert.severity === "critical") {
await pagerduty.triggerIncident({
title: `CRITICAL: ${alert.name} detected`,
body: formatAlertBody(alert),
severity: "critical",
});
// Автоматически инициировать pause если confidence > 0.9
if (alert.confidence > 0.9 && alert.autoActionEnabled) {
await pauseGuardian.pause(alert.transactionHash);
}
}
// Всегда отправлять в Discord для аудита
await discord.send(ALERTS_CHANNEL, formatDiscordAlert(alert));
// Метрики в Prometheus
metrics.increment("alerts_total", { severity: alert.severity, type: alert.name });
}
Forta Network интеграция
Forta — decentralized мониторинговая сеть. Разработчики деплоят detection bots (Node.js или Python) которые получают каждую транзакцию и генерируют alerts. Bot-runner nodes исполняют боты и публикуют alerts on-chain.
Преимущество: не нужна собственная инфраструктура нод. Недостаток: задержка (post-block), нет mempool мониторинга, latency зависит от Forta infrastructure.
Для кастомного протокола: Forta bot как дополнительный слой поверх собственного мониторинга — redundancy важна.
Производственная инфраструктура
Node infrastructure
Для mempool мониторинга нужен надёжный WebSocket подключение к Ethereum node. Self-hosted архивная нода (Geth, Reth) на bare metal даёт наименьшую latency, но требует 2+ TB SSD и maintenance. Managed: Alchemy, QuickNode — надёжны, но WebSocket может иметь throttling при высокой нагрузке.
Для production: dual-provider setup. Основной provider (например, Alchemy) + fallback (QuickNode). Автоматический переключение при degraded connection.
Scalability
При мониторинге 10+ протоколов на нескольких chains:
- Горизонтальное масштабирование: отдельный worker per chain
- Message queue (Kafka, RabbitMQ) между detector и action layers
- State management: Redis для кеширования protocol state (TVL, prices) — избегать повторных RPC запросов
| Компонент | Технология |
|---|---|
| Mempool monitoring | Node.js + ethers.js v6 + WS provider |
| Transaction simulation | Tenderly API / Alchemy Simulate |
| ML inference | Python FastAPI + ONNX runtime |
| Alert routing | PagerDuty + Telegram bot |
| Dashboard | Grafana + Prometheus |
| Pause automation | OpenZeppelin Defender |
| Redundancy | Forta Network bots |
Сроки разработки
MVP (rule-based детекция + alerts + manual pause): 4-6 недель.
Полная система (ML детекция + automated circuit breaker + Forta integration + dashboard): 3-5 месяцев.
Важно: система мониторинга сама требует security review. Compromise automated pause guardian может использоваться для DoS атаки на протокол — заблокировать protocol в критический момент. Defense: rate limiting на pause calls, multisig для unpause, transparency log всех automated actions.







