Розроблення Solver для Intent-Based протоколів
Intent-based архітектура — це зсув від «користувач вказує точний маршрут транзакції» до «користувач описує потрібний результат». Замість swapExactInputSingle(WETH, USDC, 500, 1e18, minOut, deadline) користувач підписує intent: «хочу отримати щонайменше 3000 USDC за 1 WETH до завтрашнього ранку». Як саме це виконається — задача solver-а.
CoW Protocol, UniswapX, 1inch Fusion, ERC-7683 (cross-chain intents) — усі ці системи потребують кастомних solver-ів для конкурентного виконання ордерів.
Що робить solver і чому це нетривіально
Solver — це off-chain агент, який:
- Отримує intent користувача (підписаний EIP-712 ордер)
- Знаходить оптимальний спосіб його виконання
- Складає on-chain транзакцію (або bundle) для settlement
- Конкурує з іншими solver-ами за право виконати ордер
Конкуренція — ключове слово. У CoW Protocol solver-и змаганяються в batch auction: кожні ~30 секунд система приймає рішення від кількох solver-ів і вибирає того, хто забезпечив користувачу найбільший surplus (різницю між очікуваним і реальним результатом).
Програвші solver-и не отримують нічого за обчислення. Це створює інтенсивний стимул до оптимізації швидкості та якості рішення.
UniswapX: архітектура та механізм виконання
UniswapX використовує Dutch auction: filler (solver) може виконати ордер у будь-який момент до закінчення терміну. Початкова ціна сприятлива користувачу, поступово зміщується на користь solver-а. Перший solver, який виконує ордер при прийнятному співвідношенні — перемагає.
Структура ордера UniswapX (ExclusiveFillerOrder):
interface ExclusiveFillerOrder {
info: {
reactor: Address // UniswapX Reactor контракт
swapper: Address // Користувач
nonce: bigint
deadline: bigint
additionalValidationContract: Address
additionalValidationData: Hex
}
exclusiveFiller: Address // Пріоритетний filler (якщо є)
exclusivityOverrideBps: number
input: {
token: Address
amount: bigint
}
outputs: Array<{
token: Address
startAmount: bigint // Початок Dutch auction (сприятливо користувачу)
endAmount: bigint // Кінець auction (сприятливо solver-у)
recipient: Address
}>
}
Solver отримує input.amount від користувача, повинен повернути мінімум currentOutput (значення між startAmount і endAmount залежно від timestamp).
Reactor контракт і settlement
UniswapX Reactor — це on-chain контракт, який верифікує підпис користувача, перевіряє currentOutput за часом і управляє transfer-ами. Solver викликає execute(order, signature, fillData).
Ключовий момент: solver отримує input токени на початку виконання і повинен повернути output токени до кінця тієї ж транзакції. Між отриманням і поверненням solver може використовувати будь-які on-chain протоколи — це й є простір для оптимізації.
Пошук оптимального маршруту виконання
Завдання solver-а — максимізувати surplus при заданих input/output. Surplus = actualOutput - minRequiredOutput. Кращий surplus → більша вероятність перемогти в auction у batch-системах.
Маршрутизація через кілька DEX
Базовий підхід — пошук кращої ціни через агрегатор:
async function findOptimalRoute(
tokenIn: Address,
tokenOut: Address,
amountIn: bigint
): Promise<RouteResult> {
const [uniV3Quote, aerodromeQuote, curveQuote, oneInchQuote] = await Promise.all([
quoteUniswapV3(tokenIn, tokenOut, amountIn),
quoteAerodrome(tokenIn, tokenOut, amountIn),
quoteCurve(tokenIn, tokenOut, amountIn),
quote1inch(tokenIn, tokenOut, amountIn)
])
const routes = [uniV3Quote, aerodromeQuote, curveQuote, oneInchQuote]
.filter(r => r.success)
.sort((a, b) => Number(b.amountOut - a.amountOut))
return routes[0]
}
Це паралельний запит — latency визначається найповільнішим джерелом, а не сумою. Для production встановіть timeout для кожного джерела на 500ms, обираючи найкраще серед тих, що відповідали.
Split routing
Якщо одного DEX недостатньо для виконання без великого slippage — розділяємо на частини:
// 60% через Uniswap V3, 40% через Curve
const splits = [
{ dex: 'uniswap_v3', fraction: 0.6, amountIn: amountIn * 6n / 10n },
{ dex: 'curve', fraction: 0.4, amountIn: amountIn * 4n / 10n }
]
Split routing ефективний для великих ордерів, де єдиний маршрут дає значний price impact.
Приватна ліквідність (RFQ)
Крім on-chain DEX, solver може мати доступ до приватних market maker-ів через RFQ (Request for Quote). Market maker відповідає підписаною котировкою — якщо вона краща за on-chain маршрут, solver її використовує.
CoW Protocol підтримує це через GPv2 interaction: solver включає підписану котировку від market maker-а як частину settlement.
CoW Protocol solver: механіка batch auction
У CoW Protocol batch auction відбувається так:
- Orderbook: користувачі підписують ордера (CoW Swap UI або безпосередньо), ордера потрапляють у публічний orderbook API
-
Auction call: кожні ~30 секунд CoW Protocol викликає
/solveна зареєстрованих solver-ах - Solver computation: solver отримує список ордерів у batch, знаходить оптимальний набір виконань (включаючи CoW — матчування протилежних ордерів без DEX)
- Submission: solver відправляє рішення з calldata для on-chain settlement
- Winner selection: вибирається solver з найбільшим суммарним surplus для batch
- On-chain settlement: winning solver виконує транзакцію через GPv2Settlement контракт
CoW (Coincidence of Wants) — особлива функція: якщо в batch є ордер на продаж ETH за USDC і ордер на продаж USDC за ETH — solver може матчувати їх напрямку. Без DEX fee, без price impact. Обидві сторони отримують кращу ціну.
Реєстрація solver-а в CoW Protocol
Solver повинен бути авторизований CoW DAO. Для участі в production аукціонах потрібен внесений bond (DAO governance голосування). Для тестування — staging середовище без bond.
Інфраструктура solver-а
Вимоги до продуктивності критичні: CoW auction window — 30 секунд, з яких частина йде на отримання ордерів і відправлення рішення. Реальний час на computation — 10–15 секунд.
Мови: Rust або Go для production solver-а (Python/Node.js прийнятні для простих стратегій). Rust з tokio async runtime дозволяє паралельний RPC до десятків джерел за 100–200ms.
Кеш стану пулів: зберігання актуальних резервів/sqrtPrice топ-100 пулів у пам'яті, оновлення через WebSocket subscriptions на Sync/Swap eventi. Це дозволяє розраховувати маршрути без RPC викликів — latency в мікросекундах замість мілісекунд.
Симулятор: in-process EVM симулятор (revm) для перевірки маршруту без on-chain виклику. Критично для CoW batching, де потрібно симулювати N ордерів одночасно.
Стек розроблення
Solver off-chain: Rust + alloy (новий ethereum crate, заміна ethers-rs). Паралельна маршрутизація через tokio tasks.
Settlement контракт (при необхідності кастомного): Solidity 0.8.24 + Foundry fork-тесты проти реальних UniswapX/CoW контрактів.
Моніторинг: Prometheus метрики (win rate, avg surplus, latency за джерелами), Grafana дашборд, Telegram алерти при win rate < 5%.
Процес роботи
Аналітика (2–3 дні). Вибір протоколу (UniswapX, CoW, 1inch Fusion, ERC-7683), аналіз конкурентного середовища solver-ів, оцінка ROI.
MVP solver (1 тиждень). Базовий routing через 2–3 DEX, settlement інтеграція, реєстрація в staging.
Оптимізація (1 тиждень). Split routing, RFQ інтеграції, кеш стану пулів, latency оптимізація.
Production деплой. Реєстрація в mainnet (для CoW — governance), моніторинг win rate.
Орієнтири за часом
Базовий UniswapX filler з простим routing — 1 тиждень. Повноцінний CoW Protocol solver з CoW matching, split routing та RFQ — 3–4 тижні.







