Разработка системы защиты от MEV
Мы проектируем и внедряем защиту транзакций от MEV-атак для DeFi-протоколов и dApp на Ethereum, Polygon, Arbitrum и других EVM-сетях. Сэндвич-атаки, фронтраннинг и арбитраж MEV — ежедневная угроза, из-за которой пользователи теряют миллионы долларов. Даже одна сэндвич-атака на крупный своп может нанести ущерб в $10 000 или более. Наше комплексное решение включает приватный мемпул, commit-reveal схемы, TWAP оракулы и интеграцию с Flashbots и MEV Blocker. Гарантируем защиту от 90% сэндвич-векторов без изменения архитектуры вашего протокола. Более подробно о концепции MEV можно прочитать на Wikipedia.
Опираемся на многолетний опыт в Web3 и 15+ успешных проектов по защите от MEV. Свяжитесь с нами для аудита вашей транзакционной безопасности.
Как работает сэндвич-атака
Атакующий мониторит публичный mempool, видит крупный swap (например, 50 ETH в USDC через Uniswap). До транзакции жертвы он вставляет свою — купить ETH, поднимая цену. После — продаёт ETH по поднятой цене. Жертва получает USDC по худшей цене, атакующий извлекает разницу. Такая атака возможна из-за публичности mempool и достаточного slippage tolerance у жертвы. Защита начинается с сокрытия транзакции от посторонних глаз.
Блок N:
tx[0]: Attacker buys ETH (frontrun) — газ выше чем у жертвы
tx[1]: Victim swaps 50 ETH → USDC (по завышенной цене)
tx[2]: Attacker sells ETH (backrun) — газ ниже чем у жертвы
Как защитить транзакцию от MEV
Применяем комбинацию методов — от быстрой настройки приватного RPC до глубокой архитектурной защиты.
Приватный RPC и MEV-блокировщики
Самый простой способ: отправлять транзакции через приватный mempool. Flashbots Protect RPC — бесплатный endpoint. Транзакции идут напрямую в bundle builders, минуя публичный mempool. Как отмечается в документации Flashbots, приватный мемпул блокирует до 90% сэндвич-атак. Не подходит для быстрого арбитража, но отлично для обычных swap-ов.
MEV Blocker (от CoW Protocol и Gnosis) отправляет транзакции нескольким builders одновременно, первый включивший получает эксклюзивный доступ к backrun (без frontrun). Прибыль от backrun возвращается пользователю как kickback. MEV Blocker в 3 раза эффективнее блокирует sandwich по сравнению с обычным Flashbots. Настройка MEV Blocker позволяет сэкономить до 5 ETH на крупном свопе.
Интеграция в dApp: добавить альтернативный RPC endpoint в wallet connection:
const mevProtectedProvider = new ethers.JsonRpcProvider(
'https://rpc.mevblocker.io',
{ chainId: 1, name: 'mainnet' }
)
const config = createConfig({
chains: [mainnet],
transports: {
[mainnet.id]: http('https://rpc.mevblocker.io'),
},
})
Commit-Reveal схема
Для протоколов с конфиденциальными параметрами (аукционы, лотереи). Двухфазный процесс:
Commit: пользователь отправляет hash(action + secret) — скрытое намерение. Reveal: после deadline все участники раскрывают секреты, действия исполняются.
contract CommitRevealAuction {
mapping(address => bytes32) public commitments;
mapping(address => bool) public revealed;
uint256 public commitDeadline;
uint256 public revealDeadline;
function commit(bytes32 commitment) external {
require(block.timestamp < commitDeadline, "Commit phase over");
commitments[msg.sender] = commitment;
}
function reveal(uint256 bidAmount, bytes32 secret) external {
require(block.timestamp >= commitDeadline, "Still in commit phase");
require(block.timestamp < revealDeadline, "Reveal phase over");
require(!revealed[msg.sender], "Already revealed");
bytes32 expectedCommitment = keccak256(abi.encodePacked(bidAmount, secret, msg.sender));
require(commitments[msg.sender] == expectedCommitment, "Invalid reveal");
revealed[msg.sender] = true;
_processBid(msg.sender, bidAmount);
}
}
Уязвимость: если reveal транзакции видны в mempool — атакующий может frontrun последний reveal. Защита: encrypted reveal через threshold encryption (SUAVE, Shutter Network).
Slippage controls on-chain
Жёсткие on-chain ограничения slippage не защищают от sandwich (атака подстраивается под tolerance), но ограничивают ущерб. Uniswap v3 sqrtPriceLimitX96 — hard limit на цену. Если цена выходит за лимит — swap останавливается.
function swap(
address tokenIn,
address tokenOut,
uint256 amountIn,
uint256 minAmountOut
) external returns (uint256 amountOut) {
amountOut = _executeSwap(tokenIn, tokenOut, amountIn);
require(amountOut >= minAmountOut, "Slippage exceeded");
return amountOut;
}
minAmountOut должен рассчитываться с учётом реального slippage (0.1-1%). Рекомендуем максимальный slippage 0.5% — снижает эффективность sandwich атак на 60%.
TWAP для on-chain pricing
Протоколы, использующие AMM spot price для расчётов — уязвимы к flash loan манипуляции. TWAP (time-weighted average price) из Uniswap v3 устойчив к одноблочным манипуляциям.
function getTWAP(address pool, uint32 twapInterval) internal view returns (uint256 price) {
uint32[] memory secondsAgos = new uint32[](2);
secondsAgos[0] = twapInterval; // например, 1800 секунд
secondsAgos[1] = 0;
(int56[] memory tickCumulatives,) = IUniswapV3Pool(pool).observe(secondsAgos);
int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];
int24 timeWeightedAverageTick = int24(tickCumulativesDelta / int32(twapInterval));
price = TickMath.getSqrtRatioAtTick(timeWeightedAverageTick);
}
30-минутный TWAP делает манипуляцию экономически нецелесообразной.
Будущее: EIP-7702
EIP-7702 (активен в Pectra upgrade) позволяет EOA временно делегировать выполнение контракту. Это открывает путь к transaction bundles на уровне кошелька — несколько транзакций атомарно, что делает sandwich невозможным. Для новых протоколов, ориентированных на Pectra-совместимые кошельки — перспективная архитектура.
Сравнение приватных RPC
| Провайдер |
Защита от sandwich |
Kickback |
Доп. газ |
| Flashbots Protect |
Высокая |
Нет |
Минимальный |
| MEV Blocker |
Высокая |
Да (до 90% backrun) |
Минимальный |
| BloxRoute |
Средняя |
Нет |
Средний |
| Eden Network |
Средняя |
Нет |
Средний |
Почему не стоит полагаться только на приватный RPC?
Приватные RPC защищают от фронтраннинга, но не от других форм MEV (арбитраж, ликвидации). Если ваша механика чувствительна к порядку транзакций (например, аукцион с привязкой к времени), commit-reveal обязателен. Для price oracles — TWAP. Комбинация методов даёт максимальную защиту.
Пошаговая настройка защиты
- Аудит текущих транзакций — выявляем уязвимые места.
- Выбор приватного RPC — MEV Blocker для большинства DeFi, Flashbots для быстрых операций.
- Интеграция RPC во фронтенд — через wagmi или ethers.js.
- Настройка slippage — 0.5% для стейблкоинов, 1% для волатильных активов.
- Для протоколов: внедрение commit-reveal или TWAP.
- Тестирование — прогон через Tenderly симуляции сэндвич-атак.
- Документация и обучение команды.
Сравнение методов защиты
| Метод |
Защита от sandwich |
Сложность |
Влияние на UX |
| Private RPC |
Высокая |
Минимальная |
Минимальное |
| Commit-Reveal |
Высокая |
Высокая |
Высокое (2 tx) |
| Slippage controls |
Частичная |
Низкая |
Нет |
| TWAP oracle |
Flash loan protection |
Средняя |
Нет |
| MEV Blocker |
Высокая + rebate |
Минимальная |
Минимальное |
Практическая рекомендация: для dApp — интегрировать MEV Blocker как default транспорт + жёсткие параметры slippage (max 0.5% для стейблкоинов, max 1% для волатильных активов). Это закрывает 90% sandwich векторов.
Для выбора оптимальной комбинации методов защиты вашего протокола обратитесь к нашим специалистам. Проведем аудит и предложим решение под ваш бюджет.
Что входит в работу
- Аудит безопасности транзакций вашего протокола
- Настройка приватного RPC (Flashbots/MEV Blocker)
- Внедрение commit-reveal схем (Solidity + frontend)
- Интеграция TWAP оракулов (Uniswap v3)
- Тестирование на Tenderly с симуляцией атак
- Документация и доступы
- Обучение команды
Получите консультацию по защите вашего протокола. Оцениваем проект за 1-2 дня. Свяжитесь с нами.
Пример экономии при использовании MEV Blocker
Пользователь совершил swap на 100 ETH. Без защиты потерял бы от sandwich 2-3% (2-3 ETH). С MEV Blocker потери составили 0.2 ETH — экономия более 90%.
Аудит смарт-контрактов: как находят то, что не видит компилятор
Когда протокол теряет $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 при повторном обращении.