Разработка бота ликвидаций для lending-протоколов
В Aave V3 позиция уходит в ликвидацию, когда health factor падает ниже 1.0. В этот момент любой может вызвать liquidationCall() и получить liquidation bonus — от 5% до 15% от размера залога в зависимости от актива. На крупных протоколах за одну транзакцию ликвидатор может заработать десятки тысяч долларов. За право быть первым конкурируют сотни ботов с co-located серверами и оптимизированным газом.
Разрыв между медленным ботом и быстрым — не в алгоритме, а в инфраструктуре и деталях реализации.
Где конкурируют ликвидационные боты
Обнаружение позиций: polling vs event subscription
Наивный подход — каждые N секунд запрашивать список позиций через getUserAccountData. При тысячах активных позиций это неработоспособно: слишком много RPC-запросов, слишком высокая latency.
Правильный подход — комбинация двух каналов:
Event subscription через WebSocket. Слушаем Borrow, Deposit, Repay события протокола. При каждом событии обновляем локальный state конкретного пользователя. Не нужно переопрашивать всё — только изменившиеся позиции.
Price feed subscription. Слушаем Chainlink AnswerUpdated события для всех активов протокола. Когда цена актива меняется — пересчитываем health factor для всех позиций, использующих этот актив как collateral или debt. Именно обновление цены оракула обычно триггерит ликвидации, а не действия пользователя.
Комбинация двух каналов даёт актуальный список кандидатов на ликвидацию с задержкой в одну-две секунды после изменения состояния on-chain.
Flash loan для ликвидации без капитала
Классическая ликвидация требует держать запас каждого debt-токена. При десятках активов в протоколе — дорого и неэффективно. Стандартное решение: flash loan из Aave или Balancer для получения debt-токена, вызов liquidationCall(), обмен полученного collateral на исходный токен через Uniswap V3 или Curve, возврат flash loan. Весь цикл — одна транзакция.
Критичный момент — profitable path. После flash loan fee (0.09% в Aave V3) и swap slippage/fee ликвидация должна оставаться прибыльной. Бот должен симулировать полную транзакцию через eth_call перед отправкой — иначе gas на реверт транзакции тоже потеря.
MEV и private mempool
Публичный mempool — смерть для ликвидационного бота. Profitable транзакция будет sandwich-атакована или front-run MEV-ботом в ту же секунду. Решение — Flashbots Bundles (Ethereum) или приватные RPC-эндпоинты (Alchemy Private, BloxRoute). Транзакция идёт напрямую к валидатору, минуя публичный mempool.
На L2 (Arbitrum, Optimism, Base) ситуация иная: sequencer централизован, MEV менее агрессивен, но latency к sequencer-ноде важна не меньше.
Архитектура бота
| Компонент | Реализация | Роль |
|---|---|---|
| State manager | In-memory + Redis | Позиции пользователей, health factors |
| Event listener | ethers.js WebSocket | Обновления позиций и цен |
| Profitability calculator | Onchain simulation | eth_call до отправки |
| Executor | Flashbots / private RPC | Отправка без front-run |
| Flash loan handler | Solidity контракт | Атомарная ликвидация |
Liquidation контракт деплоится отдельно. Бот вызывает его execute() функцию, передавая параметры: адрес заёмщика, debt token, collateral token, сумму. Контракт выполняет flash loan → ликвидация → swap → возврат. Прибыль остаётся на контракте, бот периодически выводит.
Поддержка нескольких протоколов
Aave V3, Compound V3 (Comet), Venus на BSC, Radiant — каждый имеет свой интерфейс liquidationCall и свою логику health factor. Используем adapter-паттерн: общий интерфейс ILiquidator с реализациями под каждый протокол. Добавить новый протокол = написать новый adapter без изменения core логики.
Тестирование и деплой
Fork-тесты на mainnet — обязательны. Foundry vm.createFork + vm.warp позволяют воспроизвести историческую ликвидацию: берём блок, в котором позиция была ликвидирована, запускаем бота — он должен её обнаружить и выполнить. Это лучший способ проверить правильность расчётов health factor.
Нагрузочный тест: 10 000 позиций в state manager, симуляция обновления цены всех Chainlink feeds — бот должен обработать очередь за < 500ms.
Деплой: сервер в том же регионе, где хостятся Alchemy/Infura ноды (обычно us-east-1). PM2 или systemd для uptime. Мониторинг через Grafana: latency от события до транзакции, profit per liquidation, failed attempts.
Ориентиры по срокам
Базовый бот для одного протокола (Aave) на одном чейне — 1-1.5 недели. Мультипротокольный с flash loan executor и Flashbots интеграцией — 2-3 недели. Поддержка нескольких чейнов с единым state manager — ещё неделя на чейн.







