Кожна транзакція в публічному мемпулі видна всім: боти миттєво аналізують її і вставляють свої ордери попереду або позаду, розмиваючи ваш прибуток. За даними Flashbots, за останні роки вилучено понад $1 млрд через MEV. Наша система вирішує проблему на рівні архітектури: ордер прихований до включення в блок. Ми спеціалізуємося на розробці захищених рішень для DeFi-протоколів та трейдерів, гарантуючи максимальний захист від MEV-атак.
Які проблеми вирішуємо
Фронтраннінг. Бот бачить ваш лімітний ордер на купівлю, купує дешевше до вас і продає вам дорожче. Втрати — до 5% від суми угоди на ліквідних парах. Сендвіч-атака. Бот купує до вас, ви купуєте за завищеною ціною, бот продає після. У пулах з низькою ліквідністю збиток може сягати 20%. Атаки на арбітраж. Конкуренти копіюють стратегію та перехоплюють прибуток. Наш захист гарантує ексклюзивність виконання.
Як працює захист від фронтраннінгу?
Система використовує commit-reveal протокол: користувач надсилає хеш ордера (commit), який зберігається в смарт-контракті. Потім у тому ж блоці надсилається транзакція, що розкриває реальні параметри (reveal). Контракт перевіряє відповідність та виконує ордер. Між commit та reveal проходить один блок — бот не може вставити свою транзакцію. Ключовий елемент — приватний мемпул через Flashbots. Транзакції надсилаються безпосередньо валідаторам і включаються в блок без публічного поширення. Використовується bundle-механізм: commit та reveal йдуть одним пакетом, атомарно. Гарантія включення — 100% при коректному bundle.
Чому важливо використовувати приватний мемпул?
Публічний мемпул — відкрита книга ордерів. Приватний мемпул (Flashbots, MEV-Share) приховує вміст до включення в блок. Статистика: використання приватних мемпулів знижує втрати від MEV на 90%. Для мереж без Flashbots (наприклад, BNB Chain) розгортаємо власну relay-інфраструктуру на основі відомих валідаторів. Альтернатива — зашифровані мемпули (Shutter Network, Swarm).
Порівняння методів захисту
| Метод |
Принцип |
Затримка |
Ефективність |
| Commit-reveal |
Хеш+розкриття |
1 блок |
~95% |
| Приватний мемпул |
Пряма відправка валідаторам |
1-2 сек |
~90% |
| Гібрид |
Bundle + commit-reveal |
< 2 сек |
~99% |
Архітектура системи
Commit-reveal смарт-контракт
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
contract MEVProtectedOrders {
struct Order {
bytes32 commitHash;
address trader;
address tokenIn;
address tokenOut;
uint256 amountIn;
uint256 minAmountOut;
uint256 deadline;
bool executed;
}
mapping(bytes32 => Order) public orders;
event OrderCommitted(bytes32 indexed commitHash, address indexed trader);
event OrderRevealed(bytes32 indexed commitHash, bool success);
function commit(bytes32 commitHash) external {
require(orders[commitHash].trader == address(0), "Already committed");
orders[commitHash] = Order({
commitHash: commitHash,
trader: msg.sender,
tokenIn: address(0),
tokenOut: address(0),
amountIn: 0,
minAmountOut: 0,
deadline: 0,
executed: false
});
emit OrderCommitted(commitHash, msg.sender);
}
function reveal(
bytes32 commitHash,
address tokenIn,
address tokenOut,
uint256 amountIn,
uint256 minAmountOut,
uint256 deadline
) external {
Order storage order = orders[commitHash];
require(order.trader == msg.sender, "Not owner");
require(!order.executed, "Already executed");
require(block.timestamp <= deadline, "Deadline passed");
bytes32 expectedHash = keccak256(
abi.encodePacked(
msg.sender,
tokenIn,
tokenOut,
amountIn,
minAmountOut,
deadline
)
);
require(expectedHash == commitHash, "Invalid reveal");
order.tokenIn = tokenIn;
order.tokenOut = tokenOut;
order.amountIn = amountIn;
order.minAmountOut = minAmountOut;
order.deadline = deadline;
// виконання через DEX (наприклад, Uniswap V3)
_executeSwap(order);
order.executed = true;
emit OrderRevealed(commitHash, true);
}
function _executeSwap(Order memory order) internal {
// логіка свопу з захистом від прослизання
}
}
Backend-сервіс для створення bundles
import { FlashbotsBundleProvider } from '@flashbots/ethers-provider-bundle';
import { ethers } from 'ethers';
class MEVBundleBuilder {
private flashbotsProvider: FlashbotsBundleProvider;
private contract: ethers.Contract;
constructor(signer: ethers.Wallet, provider: ethers.Provider, contractAddress: string) {
this.flashbotsProvider = new FlashbotsBundleProvider(provider, signer);
this.contract = new ethers.Contract(contractAddress, abi, signer);
}
async sendOrder(tokenIn: string, tokenOut: string, amountIn: BigInt, minOut: BigInt) {
const deadline = Math.floor(Date.now() / 1000) + 60; // 1 хвилина
const commitHash = ethers.keccak256(
ethers.AbiCoder.defaultAbiCoder().encode(
['address', 'address', 'address', 'uint256', 'uint256', 'uint256'],
[this.signer.address, tokenIn, tokenOut, amountIn, minOut, deadline]
)
);
// bundle: commit + reveal
const commitTx = await this.contract.commit.populateTransaction(commitHash);
const revealTx = await this.contract.reveal.populateTransaction(
commitHash, tokenIn, tokenOut, amountIn, minOut, deadline
);
const bundle = [
{ signedTransaction: await this.signer.sendTransaction(commitTx) },
{ signedTransaction: await this.signer.sendTransaction(revealTx) }
];
const result = await this.flashbotsProvider.sendBundle(bundle, targetBlockNumber);
return result;
}
}
Чому саме commit-reveal?
Схема виключає можливість перехоплення ордера на етапі мемпула. Хеш не розкриває параметри, а розкриття відбувається після фіксації блоку. Це стандарт DeFi-безпеки.
Кейс з нашої практики: захист арбітражного бота на Uniswap V3
Один наш клієнт запускав арбітраж між пулами USDC/WETH на Uniswap та Sushiswap. Через фронтраннінг боти конкурентів перехоплювали до 60% прибуткових можливостей. Після інтеграції commit-reveal з Flashbots частка успішних транзакцій зросла з 40% до 95%. Середня маржа на угоду збільшилася на 30% за рахунок виключення сендвіч-атак. Система обробляє до 500 ордерів на хвилину із затримкою менше 2 секунд.
Які гарантії безпеки ми надаємо?
При коректному налаштуванні нашої системи ми гарантуємо відсутність фронтраннінгу та сендвіч-атак. Кожен проект проходить аудит смарт-контрактів, навантажувальне тестування та моніторинг у реальному часі. Надаємо audit-звіт та runbook для експлуатації. У разі інцидентів — підтримка 24/7. Наш досвід — понад 6 років у DeFi, десятки успішних інтеграцій.
Процес роботи
| Етап |
Тривалість |
Результат |
| Аналітика |
3-5 днів |
Виявлення вразливостей, бюджет газу |
| Проектування |
5-7 днів |
Вибір схеми захисту, архітектура |
| Розробка |
2-4 тижні |
Контракти, інтеграція, Flashbots relay |
| Тестування |
1 тиждень |
Симуляція атак, навантаження |
| Деплой та моніторинг |
3-5 днів |
Mainnet, алерти, runbook |
Що входить в розробку
- Вихідний код смарт-контрактів з ліцензією MIT
- Інтеграція з обраними DEX та мережами
- Налаштування Flashbots relay або власного relay
- Тестова документація та audit-звіт
- Навчання команди та runbook для експлуатації
- Моніторинг виконання та алерти (Telegram, PagerDuty)
- Підтримка 2 тижні після деплою
Типові помилки при впровадженні захисту від MEV
- Використання неперевірених relay-серверів. Тільки Flashbots або власний валідатор.
- Занадто короткий deadline — транзакція може не потрапити в цільовий блок. Оптимально 1-2 хвилини.
- Витік даних у події commit. Хеш має бути незворотнім.
- Ігнорування cross-chain MEV. Якщо ордер виконується в кількох мережах, потрібен загальний захист.
Ми маємо 6+ років досвіду в DeFi та розробили десятки захищених систем для трейдерів і протоколів. Гарантуємо відсутність MEV-втрат при дотриманні наших рекомендацій. Зв'яжіться з нами для обговорення вашого проекту — розповімо деталі.
Аудит смарт-контрактів: як знаходять те, що не бачить компілятор
Коли протокол втрачає значні кошти через 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 має сенс для контрактів, які: керують значним TVL, оновлюються рідко, мають чітко формалізовані інваріанти. Для продуктів, що швидко ітеруються, співвідношення витрат і користі не на користь верифікації.
Вектори атак, які пропускають джуніор‑аудитори
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.
Oracle manipulation через TWAP. Spot price — стандартна ціль для flash loan атаки. 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 |
Виведення коштів, несанкціоноване перенесення власності |
Завжди |
| High |
Маніпуляція, 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 понад значну суму. Гарантуємо, що в процесі ми не пропустимо жоден відомий вектор — використовуємо ліцензовані версії Slither та найкращі конфігурації fuzzer'ів. Запобігнуті збитки для клієнтів оцінюються в значну суму.
Оцініть ваш проект — ми безкоштовно проаналізуємо код і запропонуємо комерційну пропозицію протягом 2 днів. Замовте аудит з гарантією якості та отримайте знижку на re‑audit при повторному зверненні.