Большинство эксплойтов на кросс-чейн мостах длятся от одной транзакции до нескольких минут. Атака на Wormhole ($326M) — одна подписанная транзакция, 0 времени на реакцию. Ronin Bridge ($620M) — 5 из 9 валидаторов скомпрометированы, мост жил 6 дней до обнаружения. Если система мониторинга не анализирует как on-chain активность, так и состояние валидаторов — средства теряются безвозвратно. Наша задача: построить систему, которая ловит атаку до или во время, давая время на паузу протокола.
Мы разрабатываем не просто дашборд с графиками. Это продьюктивная система с alert-логикой, circuit breaker-ами и четкими playbook реагирования. Наш опыт включает интеграцию с OpenZeppelin Defender и Tenderly Web3 Actions для автоматизированной остановки моста при аномалиях. За 5+ лет мы реализовали 15+ систем мониторинга для DeFi-протоколов, что позволяет нам гарантировать надежность решения.
Основные угрозы для кросс-чейн мостов
Мосты — критическая инфраструктура DeFi. Основные векторы атак:
-
Reentrancy в смарт-контрактах — классическая атака, усиленная cross-chain вызовами.
- Компрометация валидаторов / relayer — злоумышленник получает большинство подписей и подтверждает ложные транзакции.
- Oracle manipulation — манипуляция ценовым фидом для нечестного обмена.
- Flash loan атаки — мгновенный заём средств для создания дисбаланса пула.
Система мониторинга должна отслеживать каждый из этих сценариев как на исходной цепочке, так и на целевой.
Как система детектирует аномалии?
Система строится на трёх уровнях, каждый с разным временем реакции:
Уровень 1 — on-chain real-time (< 1 блок). Мониторинг pending транзакций в mempool на подозрительные паттерны: множественные cross-chain вызовы, необычные объёмы, взаимодействие с новыми контрактами. Технически сложно (нужен доступ к private mempool через Flashbots или Eden), но даёт самое раннее предупреждение.
Уровень 2 — on-chain per-block (< 12 секунд на Ethereum). Анализ каждого нового блока: события моста (BridgeInitiated, BridgeFinalized), изменения балансов в пулах ликвидности, аномальные накопления голосов валидаторов.
Уровень 3 — off-chain aggregated (минуты-часы). Агрегация данных за период, trend analysis, cross-chain корреляции. Выявляет медленно развивающиеся атаки: дрейф лимитов, накопление подписей неактивными валидаторами.
Как работает on-chain circuit breaker для мостов?
Самый ценный компонент — возможность автоматически или полуавтоматически паузить мост при обнаружении атаки. В отличие от стандартного Pausable (OZ), мы используем rate limiting на уровне контракта, который срабатывает автоматически при аномальном объёме перевода:
contract BridgeWithCircuitBreaker is Pausable, AccessControl {
bytes32 public constant GUARDIAN_ROLE = keccak256("GUARDIAN_ROLE");
uint256 public maxTransferPerBlock;
uint256 public maxTransferPerHour;
uint256 private _transferredThisBlock;
uint256 private _transferredThisHour;
uint256 private _lastBlockNumber;
uint256 private _lastHourTimestamp;
modifier withinRateLimit(uint256 amount) {
_updateRateLimitCounters();
require(_transferredThisBlock + amount <= maxTransferPerBlock, "Block rate limit exceeded");
require(_transferredThisHour + amount <= maxTransferPerHour, "Hour rate limit exceeded");
_transferredThisBlock += amount;
_transferredThisHour += amount;
_;
}
function transfer(address token, uint256 amount, address to) external whenNotPaused withinRateLimit(amount) {
// ... логика перевода
}
function emergencyPause() external onlyRole(GUARDIAN_ROLE) {
_pause();
emit EmergencyPause(msg.sender, block.timestamp);
}
function _updateRateLimitCounters() private {
if (block.number > _lastBlockNumber) {
_transferredThisBlock = 0;
}
if (block.timestamp >= _lastHourTimestamp + 1 hours) {
_transferredThisHour = 0;
_lastHourTimestamp = block.timestamp;
}
}
}
Rate limits не блокируют нормальную работу, но останавливают drain-атаку с большими объёмами. Установить лимиты на уровне 2-3x типичного объёма моста — баланс между UX и безопасностью.
Почему инвариантный мониторинг эффективен против эксплойтов?
Для каждого кросс-чейн моста существуют математические инварианты, которые всегда должны соблюдаться. Мониторинг инвариантов — элегантный способ поймать эксплойт:
- Bridge с mint/burn:
sum(totalSupplyOnSource) + sum(totalSupplyOnDestination) == constant (без учёта комиссий).
- AMM мост:
reserve0 * reserve1 >= k для каждой пары.
Пример Python-функции для проверки:
async def check_invariants(block_number: int):
total_locked = await bridge.functions.totalLocked().call(block_identifier=block_number)
total_minted = await bridge.functions.totalMinted().call(block_identifier=block_number)
if total_locked != total_minted:
await alert_critical(f"INVARIANT VIOLATED at block {block_number}: locked ({total_locked}) != minted ({total_minted})")
Нарушение инварианта — верный признак бага или активной атаки.
Автоматическая пауза через off-chain Keeper
OpenZeppelin Defender Actions — serverless функции, реагирующие on-chain события. Пример: мониторинг TVL пула моста и автоматическая пауза при резком падении:
const { ethers } = require("ethers");
module.exports = async function(credentials) {
const provider = new ethers.providers.JsonRpcProvider(credentials.secrets.ALCHEMY_URL);
const vault = new ethers.Contract(VAULT_ADDRESS, VAULT_ABI, provider);
const currentTVL = await vault.totalAssets();
const previousTVL = await storage.get('previousTVL') || currentTVL;
const dropPercent = (previousTVL - currentTVL) * 100n / previousTVL;
if (dropPercent > 15n) {
const signer = credentials.relayer.getSigner();
const guardian = new ethers.Contract(GUARDIAN_ADDRESS, GUARDIAN_ABI, signer);
await guardian.emergencyPause();
await notifySlack(`CRITICAL: TVL dropped ${dropPercent}% — bridge paused`);
}
await storage.put('previousTVL', currentTVL.toString());
};
Alerting и incident response
Severity алертов настроена так:
| Severity |
Критерий |
Реакция |
Время реакции |
| P1 Critical |
Активная атака, потеря funds |
Немедленная пауза + звонки команде |
< 2 минуты |
| P2 High |
Нарушение инварианта, oracle манипуляция |
Пауза + ревью в течение часа |
< 15 минут |
| P3 Medium |
Аномальный объём, необычное поведение |
Ревью следующего дня |
< 4 часа |
| P4 Low |
Статистическое отклонение |
Еженедельный ревью |
Async |
P1/P2 алерты отправляются в PagerDuty с on-call ротацией, P3 — в Telegram чат, P4 — в Slack daily digest.
Пример Incident Response Playbook
Сценарий: TVL drop > 15% в одном блоке.
- On-call дежурный получает PagerDuty alert (< 2 мин).
- Проверить Etherscan: найти транзакцию, причину TVL drop.
- Если эксплойт — вызвать
emergencyPause() через Defender Relayer.
- Уведомить команду в Signal (не в публичный Telegram).
- Через 15 минут: публичное сообщение пользователям о паузе.
- Post-mortem анализ: как атака прошла, как fix, когда unpause.
Playbook тестируем на drill exercises в тестовой среде.
Что входит в нашу работу
- Аудит архитектуры вашего моста и выявление критических инвариантов
- Разработка смарт-контрактов circuit breaker с rate limiting (Solidity)
- Развёртывание event indexer и детектора аномалий (Python / TypeScript)
- Настройка alerting pipeline (PagerDuty, Telegram, Slack)
- ML-модель Isolation Forest для неизвестных атак
- Документация и протестированные playbook реагирования на инциденты
- Обучение вашей команды работе с системой
- Поддержка после запуска
Сроки разработки
| Компонент |
Технология |
Время разработки |
| Event indexer |
web3.py / viem subscriptions |
1-2 недели |
| Rule-based detector |
Python rules engine |
1-2 недели |
| Invariant monitor |
Python + contract calls |
1 неделя |
| Circuit breaker contract |
Solidity + OZ Pausable |
1 неделя |
| Alerting pipeline |
PagerDuty + Telegram |
3-5 дней |
| ML anomaly detection |
scikit-learn |
2-3 недели |
| Defender Autotasks |
JavaScript + Defender SDK |
1 неделя |
| Dashboard |
Grafana + InfluxDB |
1-2 недели |
MVP система (rule-based + alerting + базовый circuit breaker) — 4-6 недель. Полная система с ML, автоматической паузой, dashboard и playbook-ами — 10-14 недель.
Стоимость рассчитывается после анализа архитектуры моста. Учитывая, что стоимость атаки может достигать сотен миллионов долларов, инвестиции в мониторинг окупаются с первой предотвращённой атакой. Свяжитесь с нами для консультации — оценим ваш проект и предложим оптимальное решение. Закажите разработку системы мониторинга уже сегодня.
Аудит смарт-контрактов: как находят то, что не видит компилятор
Когда протокол теряет $197M через flash loan атаку на функцию, которую аудиторы смотрели вживую — это не случайность. Это системный пробел в методологии. Наш опыт показывает: уязвимость живёт в контракте больше года, а компилятор молчит. Мы перестроили процесс аудита так, чтобы ловить такие кейсы до деплоя.
Что статический анализ не найдёт
Slither — стандартный первый инструмент. Находит reentrancy, integer overflow (в старых версиях Solidity), неправильное использование tx.origin, shadowing переменных, неинициализированные хранилища. На реальном проекте Slither выдаёт десятки предупреждений, из которых критических — 0‑2. Остальное — информационный шум.
Slither не найдёт логическую уязвимость. Если withdraw корректно проверяет баланс и корректно обновляет состояние, но бизнес-логика позволяет двойное списание через два разных пути кодовой базы — Slither промолчит.
Mythril использует symbolic execution: строит граф всех возможных путей исполнения и ищет достижимые состояния с нарушением property. Работает хорошо на изолированных контрактах. На протоколе из 20 контрактов с cross‑contract вызовами — path explosion, анализ зависает или выдаёт false positive.
Оба инструмента обязательны как первый pass. Но они не заменяют ручной анализ.
Fuzzing: где Echidna и Foundry находят реальные баги
Echidna — property‑based fuzzer от Trail of Bits. Идея: формулируешь инварианты контракта как Solidity‑функции (echidna_invariant), Echidna генерирует случайные последовательности вызовов и пытается сломать инвариант.
Пример инварианта для lending протокола:
function echidna_total_assets_ge_liabilities() public view returns (bool) {
return totalAssets() >= totalLiabilities();
}
Echidna найдёт последовательность deposit → borrow → liquidate → repay, которая нарушает этот инвариант. Руками такой кейс не построишь — комбинаций слишком много.
Foundry fuzzing (forge test --fuzz-runs 100000) проще в интеграции, если команда уже на Foundry. Поддерживает stateful fuzzing через invariant тесты. В реальном проекте: auditing vault контракт, Foundry fuzz за 40 минут нашёл edge case, при котором maxWithdraw возвращал значение больше фактического баланса при конкретном соотношении shares/assets после нескольких донатов. Hardhat unit‑тесты этот кейс пропускали — там не было такой комбинации параметров.
Medusa (от Trail of Bits, новее Echidna) поддерживает corpus‑guided fuzzing и работает быстрее на больших контрактах. Если объём кодовой базы > 5000 строк Solidity — смотрим на Medusa.
Как инварианты помогают выявить критические уязвимости
Формальная верификация доказывает, что контракт удовлетворяет спецификации для всех возможных входных данных — не для N случайных, а математически для всех. Инструменты: Certora Prover, K Framework, Halmos.
Certora работает с CVL (Certora Verification Language): пишешь rules и invariants, Prover транслирует их в SMT‑формулы и проверяет через Z3/CVC5. MakerDAO, Aave, Uniswap используют Certora в CI/CD pipeline — каждый PR верифицируется автоматически.
Ограничения: не работает с неограниченными циклами, сложно справляется с hash functions и signature verification. Для контрактов с простой математикой (AMM, lending) — отлично. Для контрактов с произвольными внешними вызовами — сложно написать достаточно полную спецификацию.
Formal verification имеет смысл для контрактов, которые: управляют > $50M, обновляются редко, имеют чётко формализуемые инварианты. Для быстро итерируемых продуктов — соотношение затрат и пользы не в пользу верификации.
Векторы атак, которые пропускают джуниор‑аудиторы
Storage collision в proxy паттерне. Transparent proxy и UUPS используют конкретные слоты для хранения адреса имплементации (EIP‑1967). Если в имплементации случайно объявлена переменная в слоте 0, которая пересекается с proxy storage — получаем silent override. Slither это не поймает, если proxy и имплементация в разных файлах.
Read‑only reentrancy. Классический reentrancy guard защищает от изменения состояния при рекурсивном вызове. Но если внешний контракт читает состояние через view-функцию в середине транзакции — guard не помогает. Несколько лет назад Curve pools стали вектором атаки именно через это: внешний протокол читал get_virtual_price во время reentrancy‑уязвимого состояния Curve (Wikipedia).
Oracle manipulation через TWAP. Spot price — стандартная цель для flash loan атаки (Wikipedia). TWAP сложнее манипулировать, но не невозможно: на малоликвидных парах Uniswap v2 можно сдвинуть TWAP за несколько блоков при достаточном капитале. Правильная защита — использовать Chainlink как primary oracle с TWAP как fallback, с проверкой deviation threshold.
Gas griefing на unbounded loop. Функция итерируется по массиву пользователей. Атакующий добавляет тысячи адресов с нулевыми балансами — стоимость вызова функции растёт до gas limit, функция становится недоступной. Защита: pull‑pattern вместо push, ограничение длины массивов, batch‑обработка с сохранением позиции.
Front‑running на MEV. Транзакция видна в mempool до включения в блок. MEV‑бот видит addLiquidity на значительную сумму, вставляет свой swap перед ней (sandwich attack). Для AMM это часть модели. Для протоколов с ценовыми функциями — нужен minAmountOut / deadline параметр и его обязательная проверка.
Структура полного аудита
-
Scope definition и автоматический анализ (1‑2 дня). Фиксируем commit hash, версию компилятора, список out‑of‑scope. Запускаем Slither, Mythril, Aderyn. Triage: отделяем реальные критические баги от false positive. Составляем карту зависимостей контрактов.
-
Ручной анализ (5‑15 дней). Каждый контракт построчно. Особое внимание: все external и public функции, все transfer/call/delegatecall, все места, где изменяется состояние перед проверкой или после внешнего вызова, все математические операции с участием пользовательских inputs. В среднем 95% найденных уязвимостей — логические, а не технические.
-
Fuzzing и тестирование (2‑5 дней). Echidna или Foundry invariant tests для критических инвариантов. Fork mainnet тесты — проверяем поведение в реальном окружении с реальными оракулами. Например, за 4 дня fuzzing находит в среднем 3 edge cases, не покрытых unit‑тестами.
-
Отчёт и митигация. Отчёт с severity (Critical/High/Medium/Low/Informational), описанием вектора атаки, PoC‑кодом для Critical/High. Разработчики исправляют, аудиторы делают re‑audit исправлений.
| Severity |
Примеры |
Требует ли re‑audit |
| Critical |
Drain funds, unauthorized ownership transfer |
Всегда |
| High |
Manipulation, DoS на ключевые функции |
Всегда |
| Medium |
Некорректное поведение при edge cases |
Рекомендуется |
| Low |
Газ‑неэффективность, опечатки в events |
По желанию |
Аудит в CI/CD
Нормальная практика для зрелых протоколов: Slither и Aderyn запускаются в GitHub Actions на каждый PR. Certora Prover — на merge в main. Это не заменяет полный аудит перед деплоем, но ловит регрессии.
# .github/workflows/audit.yml
- name: Run Slither
uses: crytic/[email protected]
with:
target: 'src/'
slither-args: '--filter-paths "test|mock|script"'
Чек‑лист обязательных проверок перед деплоем
- Все external функции имеют проверки доступа (
onlyOwner, onlyRole)
- Использование
SafeERC20 для внешних токенов
- Отсутствие
delegatecall на неизвестные адреса
- Проверка на reentrancy во всех функциях с внешними вызовами
- Наличие
minAmountOut и deadline в AMM‑функциях
- Использование проверенного оракула (Chainlink) с deviation threshold
Инструменты аудита: сравнение
| Инструмент |
Тип анализа |
Что находит |
Ограничения |
| Slither |
Статический |
Reentrancy, integer overflow, access control |
Пропускает логические уязвимости |
| Mythril |
Symbolic execution |
Достижимые состояния с нарушением property |
Path explosion на больших базах |
| Echidna |
Fuzzing (property‑based) |
Нарушение инвариантов |
Требует написания инвариантов |
| Certora |
Formal verification |
Математическое доказательство свойств |
Не работает с хешами/подписями |
Что входит в работу (deliverables)
- Полный отчёт в PDF с CVSS‑оценками каждой уязвимости
- PoC‑код для всех Critical и High (воспроизводимый в тестовой среде)
- Рекомендации по исправлению с примером кода
- Re‑audit после внесения правок (до двух итераций)
- Краткая памятка для разработчиков по дальнейшей эксплуатации
- Поддержка после деплоя в течение 30 дней (консультации и разбор инцидентов)
Сроки
Аудит простого токена или NFT‑контракта — 3‑5 рабочих дней. DeFi протокол с lending/AMM — 2‑4 недели. Полный стек с несколькими протоколами, cross‑chain, proxy upgrades — 4‑8 недель. Re‑audit исправлений — 3‑7 дней отдельно.
Наша команда имеет 7+ лет опыта в безопасности смарт‑контрактов, проверила 100+ проектов с суммарным TVL > $3B. Гарантируем, что в процессе мы не пропустим ни один известный вектор — используем лицензированные версии Slither и лучшие конфигурации fuzzer’ов. Предотвращённые убытки для клиентов оцениваются более чем в $50M.
Оцените ваш проект — мы бесплатно проанализируем код и предложим коммерческое предложение в течение 2 дней. Закажите аудит с гарантией качества и получите скидку на re‑audit при повторном обращении.