Разработка системы split-routing для оптимизации цены
Ордер на 500K USDC через один DEX — это гарантированный проскальз на 3-8% в зависимости от глубины пула. На Uniswap v3 с концентрированной ликвидностью ситуация лучше, но на неликвидных парах price impact всё равно съедает значимую часть сделки. Split-routing — это не маркетинг, это математика: оптимальное разбиение ордера между несколькими источниками ликвидности снижает суммарный price impact за счёт работы на разных участках кривых.
Почему наивное разбиение не работает
Интуитивный подход — split 50/50 между Uniswap и Curve — даёт субоптимальный результат. Оптимальное распределение нелинейно и зависит от текущего состояния пулов, глубины ликвидности в конкретных тиках (для Uniswap v3), и наклона bonding curve (для Curve StableSwap). Проблема усугубляется тем, что состояние пулов меняется между вычислением маршрута и исполнением транзакции.
Front-running через MEV и staleness маршрута
Системы split-routing атакуют на двух уровнях. Первый — классический sandwich attack: MEV-бот видит крупный swap в mempool, вставляет buy перед ним и sell после, используя flashbots bundle или private mempool. Второй уровень тоньше: маршрут вычисляется off-chain по состоянию пулов на блок N, а исполняется на блок N+2. За два блока ликвидность в активном тике Uniswap v3 могла сдвинуться, и оптимальный маршрут стал субоптимальным.
На практике это означает, что алгоритм маршрутизации должен закладывать tolerance на изменение состояния и пересчитывать при расхождении с ожидаемым выходом. 1inch реализует это через «partial fill» с minReturn, мы реализуем аналогичный механизм в on-chain executor.
Проблема атомарности многошагового маршрута
Split через несколько транзакций — не split, это последовательные свапы. Для атомарного исполнения нужен контракт-агрегатор, который в одном вызове выполняет все части маршрута через multicall или собственную логику роутинга. Если промежуточный шаг ревертируется — весь бандл откатывается. Это требует careful handling газа: каждый дополнительный hop стоит 30-80k gas в зависимости от протокола.
Как мы строим split-routing
Алгоритм оптимизации маршрута
Ядро системы — off-chain оптимизатор, который решает задачу минимизации суммарного price impact. Для каждого DEX мы получаем кривую «объём → цена исполнения»:
-
Uniswap v2/v3, PancakeSwap: через
quoterконтракт или симуляцию черезeth_callс fork состояния - Curve: аналитическая формула StableSwap/Cryptoswap
-
Balancer: формула WeightedPool или StablePool через
querySwap - DODO: PMM (Proactive Market Maker) — нелинейная кривая с параметрами из оракула
Оптимизатор делит ордер на N частей и итерирует по распределению, минимизируя суммарный выход. Используем gradient descent с численным дифференцированием — аналитические производные для Uniswap v3 с тиками нетривиальны из-за дискретности. Алгоритм сходится за 50-200 итераций, что укладывается в < 100ms на типичном сервере.
On-chain executor
Контракт-агрегатор получает от off-chain оптимизатора encoded маршрут: массив (address pool, bytes calldata swapData, uint256 portion). Executor итерирует по массиву, вызывая каждый пул с рассчитанной долей входного токена. На выходе проверяет actualOutput >= minOutput через require, иначе revert.
struct SwapStep {
address pool;
address tokenIn;
address tokenOut;
uint256 amountIn;
bytes data; // ABI-encoded call to pool
}
Для Uniswap v3 data содержит encoded exactInputSingle с параметрами. Для Curve — exchange с i, j, dx. Единый интерфейс через адаптеры под каждый протокол.
Защита от MEV
Интеграция с Flashbots Protect RPC как опция для крупных ордеров — транзакция идёт напрямую к builder, минуя публичный mempool. Для EVM-совместимых L2 (Arbitrum, Optimism) MEV-риск ниже за счёт centralized sequencer, но на Base и zkSync уже появляются MEV-боты.
Слипейдж tolerance настраивается динамически: для пар с высокой волатильностью (алты) — 0.5-1%, для стейблов на Curve — 0.05-0.1%.
Процесс работы
Анализ ликвидности (3-5 дней). Профилируем пулы на целевых чейнах: глубина ликвидности, типичные объёмы, распределение по тикам для v3. Определяем список DEX для интеграции.
Разработка оптимизатора (1-2 недели). Off-chain сервис на TypeScript/Python. Тестируем на исторических данных через The Graph — насколько оптимальный маршрут превосходит прямой свап по выходной цене.
Smart contract executor (1 неделя). Разработка и тесты в Foundry с fork-тестами на mainnet. Проверяем все граничные случаи: нулевой выход, revert в промежуточном пуле, reentrancy через callback.
Интеграция и деплой. API для front-end, документация по параметрам, деплой на testnet → mainnet через Gnosis Safe мультисиг.
Ориентиры по срокам
Базовая система с 3-5 DEX на одном чейне — 3-4 недели. Мультичейн агрегатор с кросс-L2 маршрутизацией через bridge — от 2 месяцев. Сроки зависят от количества интегрируемых протоколов и требований к обновлению маршрутов в реальном времени.
Типичные грабли при разработке
Stale quotes в production. Алгоритм вычисляет маршрут по состоянию блока N, транзакция майнится на N+3. Пул успел сдвинуться. Решение — on-chain verification минимального выхода и достаточно консервативный slippage tolerance.
Газ на multicall превышает экономию от лучшей цены. На Ethereum mainnet при высоком газе (> 50 gwei) разбиение на 5 хопов добавляет 200-400k gas. Для мелких ордеров это дороже, чем price impact от прямого свапа. Оптимизатор должен учитывать стоимость газа как часть целевой функции.
Curve pool imbalance после крупного свапа. После исполнения нашей части маршрута через Curve пул может оказаться сильно несбалансирован, и следующий хоп получает худшую цену, чем предполагал оптимизатор. Для последовательных хопов внутри одной транзакции это критично — нужна симуляция состояния after каждого шага.







