Розробка системи JIT (Just-In-Time) ліквідності
JIT-ліквідність — це MEV стратегія, яку Uniswap Labs називає «добропорядною MEV» на відміну від сендвіч-атак. Механіка: у тому ж блоці, що й великий своп, провайдер додає концентровану ліквідність навколо поточної ціни, заробляє на комісіях з цього свопу, і в тому ж блоці виводить ліквідність. Три on-chain операції та комісія за своп в одній транзакції.
У листопаді 2022-го адреса 0x0a59... заробила $250k за один місяць виключно на JIT. При цьому інші LP у тих же пулах втрачали частину своїх комісій. JIT-бот буквально «вставляється» перед великою угодою і перехоплює значну частину комісій.
Чому JIT працює: математика Uniswap v3
Концентрована ліквідність і доля комісії
У Uniswap v3 комісія від свопу розподіляється пропорційно ліквідності в активному діапазоні tick. Якщо в момент свопу JIT-позиція додала $1M ліквідності в діапазон tick [P-0.1%, P+0.1%], а всі інші LP мають $500k у цьому діапазоні — JIT отримує 1M/1.5M = 66.7% від комісії цього свопу.
Стратегія є вигідною коли:
- Своп достатньо великий (інакше комісія не покриває газ на 3 операції)
- Діапазон tick достатньо вузький (більша доля, менший impermanent loss під час утримання)
- Позиція утримується один блок (нульовий ризик impermanent loss)
Мінімальний розмір свопу для беззбитковості при 0.3% fee tier на Ethereum mainnet (газ ~30 gwei):
-
addLiquidity+removeLiquidity+collect≈ 350k gas ≈ $25 при ETH=$2000 - Потрібно зібрати >$25 комісій → своп має бути >$8300
На L2 (Arbitrum): той же розрахунок дає мінімальний своп ~$500. Значно більше можливостей.
Проблема затримки: блок вже виків
JIT потребує бачити своп у мемпулі до його включення в блок. Приватний мемпул через Flashbots MEV-Share або публічний мемпул через websocket. Між виявленням транзакції й включенням вашого бандла — секунди мають значення.
Оптимальна інфраструктура:
- Власна нода з MEV-Geth або reth з mempool websocket
- Підключення до Flashbots MEV-Share для перегляду підказок щодо очікуючих свопів
- Отримання бандла через
eth_sendBundle— атомарне включення всіх трьох транзакцій в один блок
Без отримання бандла JIT не працює: якщо addLiquidity і своп потраплять в різні блоки — стратегія безглуздої та збиткова.
Архітектура JIT-системи
Off-chain компоненти
Сканер мемпулу: WebSocket підписка на ноду, фільтрація свопів Uniswap v3 за exactInputSingle/exactInput selector. Декодування calldata для визначення пулу, розміру, slippage.
Калькулятор прибутковості: для кожного кандидата розраховує:
- Очікувана комісія =
swapAmount * feeTier - Доля комісії =
depositAmount / (poolLiquidity + depositAmount) - Газова вартість бандла =
(addLiq + removeLiq + collect) * gasPrice - Чистий прибуток = (комісія * доля) - газ
Якщо чистий прибуток > поріг ($10–50) — бандл відправляється.
Конструктор бандла: формує три транзакції для Flashbots бандла:
-
tx1:mintпозиції в потрібному діапазоні tick -
tx2: оригінальний своп (backrun) -
tx3:burn+collectпозиції
Смарт-контракт для JIT операцій
Контракт обертає операції з ліквідністю та мінімізує газ:
function executeJIT(
address pool,
int24 tickLower,
int24 tickUpper,
uint128 liquidity,
bytes calldata swapData // оригінальний calldata свопу
) external onlyOperator {
// tx1: add liquidity
INonfungiblePositionManager(NPM).mint(MintParams({...}));
// tx2: forward swap (у бандлі через Flashbots — окрема tx)
// tx3: remove liquidity + collect
INonfungiblePositionManager(NPM).decreaseLiquidity(...);
INonfungiblePositionManager(NPM).collect(...);
}
Важливо: контракт повинен мати достатній баланс обох токенів пулу для додавання ліквідності. Управління балансами є критичним операційним аспектом: при дисбалансі токенів частину ліквідності не можна додати в потрібному діапазоні.
Вибір діапазону tick
Вузький діапазон максимізує частку комісії, але підвищує ризик: якщо своп переміщує ціну за межі діапазону — JIT-позиція стає неактивною і перестає збирати комісії. Для свопу без істотного впливу на ціну (< 0.5%) достатньо діапазону ±0.3% від поточної ціни. Для великих свопів з впливом на ціну 1–2% розширити діапазон до ±2%.
Розрахунок діапазону tick за впливом на ціну:
// tickLower = log(1 - priceImpact) / log(1.0001)
// tickUpper = log(1 + priceImpact) / log(1.0001)
// Плюс буфер 20-30 ticks для надійності
Ризики та обмеження
Ризик рівернення бандла. Якщо оригінальний своп рівернеться (наприклад, слагрізна захист трейдера) — весь бандл рівернеться. Газ на addLiquidity при цьому втрачається. Пом'якшення: включати лише свопи з м'яким слагпрізним допуском (>1%).
Конкуренція з іншими JIT-ботами. На високоліквідних парах (ETH/USDC, ETH/USDT) десятки ботів конкурують за одні й ті ж свопи. Газова війна через priority fee може знищити прибуток. Більш прибутковою є стратегія на середньокапітальних парах, де конкуренція нижча.
Uniswap v4 та JIT. З приходом гуків пули можуть запровадити beforeAddLiquidity гук з мінімальним часом утримання — прямий контрзахід проти JIT. Кілька пулів уже тестують такі механізми.
Процес і терміни
Розробка off-chain компонентів (4–5 днів): сканер мемпулу, калькулятор прибутковості, конструктор бандла з інтеграцією Flashbots.
Розробка on-chain контракту (2–3 дні): JIT виконавець, контроль доступу, оптимізація газу.
Інфраструктура (2–3 дні): нода (reth/geth), інтеграція MEV-Share, моніторинг.
Тестування (2–3 дні): симуляції на mainnet fork, back-testing історичних свопів для оцінки прибутковості.
Всього: 1–2 тижні. Вартість розраховується після уточнення цільових пулів та мереж.







