Безопасная проверка пула ликвидности перед стейкингом активов
DeFi-сегмент ежегодно теряет миллиарды долларов на эксплойтах и rug pull. Стейкинг в пул ликвидности без предварительной проверки контракта — это операция с отрицательным матожиданием.

1. Постановка задачи: что именно проверяем
Пул ликвидности (LP) — смарт-контракт, который хранит резервы двух или более токенов и выдаёт поставщику LP-токен, подтверждающий долю в пуле. Риски стейкинга делятся на четыре класса с разными механизмами.
| Класс риска | Механизм потери | Диапазон потерь |
|---|---|---|
| Rug pull | Владелец выводит ликвидность через `removeLiquidity`, `setRouter` или `withdraw` | 100% депозита |
| Honeypot | Купить токен можно, продать нельзя (sell tax = 100% или blacklist) | 100% депозита |
| Эксплойт кода | Уязвимость в контракте (reentrancy, oracle manipulation, flash loan attack) | 10–100% TVL |
| Имперманентная потеря | Расхождение цен активов в паре | 5–50% депозита |
Три первых класса — детерминированные. Их можно проверить до открытия позиции, без депозита. Четвёртый — рыночный, зависит от волатильности пары и хеджируется отдельно.
2. Предварительная фильтрация: TVL, возраст, аудит
Перед чтением кода отсеивается большинство проектов по трём метрикам, доступным через агрегаторы и обозреватели.
2.1. Total Value Locked
Источники: DeFiLlama, DefiPulse, обозреватель пары. Минимальный порог для пары на EVM-цепях — $500 тыс. на основной паре. Ниже этого уровня — недостаточная ликвидность для безопасного выхода и повышенный риск манипуляции ордербуком. Дополнительно проверяется удержание TVL в течение минимум 14 дней: резкий рост за сутки при отсутствии органического трафика — признак накачки TVL перед rug pull.
2.2. Возраст контракта
Дата деплоя берётся из обозревателя (Etherscan, BscScan, Arbiscan, Polygonscan). Возраст менее 30 дней — повышенный риск. Менее 7 дней — отказ. Характерный срок жизни honeypot-контрактов и rug pull-пулов — несколько недель: времени на привлечение средств и вывод обычно не хватает на длинный горизонт.
2.3. Аудит
Проверяется наличие отчёта от аудиторов с устоявшейся репутацией: Certik, Hacken, OpenZeppelin, PeckShield, SlowMist, Trail of Bits, Consensys Diligence, Quantstamp. Наличие PDF с findings не равно безопасности. Смотрятся три параметра:
- Дата аудита: старше года — перепроверить текущий код. Разработчики могли деплоить новую версию после проверки.
- Количество нерешённых критических issues: > 0 — отказ.
- Репутация аудитора: проверяется через собственный портфель проектов аудитора. Аудитор с десятками проектов надёжнее ноунейма с первым контрактом.
Аудит подтверждает, что код делает то, что заявлено в спецификации. Аудит не подтверждает, что код безопасен для конкретного депозита.
3. Чтение контракта в обозревателе
После прохождения фильтра открывается исходник контракта пула. Цель — найти функции, контролирующие активы, и определить, кому они доступны.
3.1. Verified Source
В обозревателе ищется вкладка «Contract» → «Code». Статус «Verified» обязателен. Без verified source — отказ, дальнейшие шаги не выполняются. Верификация гарантирует совпадение байткода на блокчейне с опубликованным Solidity-кодом.
3.2. Список критических функций
В исходнике ищутся следующие сигнатуры и классифицируются по доступу.
- `setFee(uint256 _fee)` — изменение комиссии. Допустимо при верхнем ограничении: `require(_fee <= 3000)` (30% в basis points). Без ограничения — rug pull через установку 100% sell fee.
- `withdraw(address _token, uint256 _amount)` или `emergencyWithdraw` — вывод произвольного токена из контракта. Доступна владельцу — rug pull через одну транзакцию. Отказ.
- `pause()` и `unpause()` — стоп-механизм. Допустимо только при вызове через timelock с задержкой > 24 часов. Без timelock — owner ставит паузу и выводит активы.
- `migrate(address newRouter)` или `setRouter(address _router)` — смена роутера. Доступ owner без timelock — подмена роутера на собственный контракт с последующим опустошением. Допустимо только с timelock > 48 часов.
- `setMaxTxAmount` и `setMaxWallet` — лимиты на размер транзакции и кошелька. Доступ owner без timelock — риск honeypot: после депозита крупных игроков owner устанавливает лимит = 1 wei, блокируя вывод.
- `setBlacklist` и `mapping(address => bool) isBlacklisted` — чёрный список. Доступ owner без timelock — выборочная заморозка средств.
Каждая найденная функция заносится в таблицу решений:
| Функция | Доступ | Ограничение | Вердикт |
|---|---|---|---|
| `setFee` | owner | `require(_fee <= 3000)` | Допустимо |
| `withdraw` | owner | нет | Отказ |
| `pause` | owner | timelock 48ч | Допустимо |
| `migrate` | owner | timelock 48ч | Допустимо |
| `setRouter` | owner | нет | Отказ |
| `setBlacklist` | owner | нет | Отказ |
3.3. Ownership
Проверяется функция `owner()`. Два допустимых варианта:
1. `owner() == address(0)` — `renounceOwnership` выполнен. Предпочтительный сценарий: разработчик больше не может менять параметры.
2. `owner()` возвращает адрес мультисиг-кошелька Gnosis Safe с порогом подписи > 2/3 и публичными адресами подписантов.
Любой EOA (внешний кошелёк) в роли owner — отказ. Ключ может быть скомпрометирован, держатель — выведен из проекта.
4. Проверка ликвидности и лока
Даже при renounced ownership rug pull возможен через вывод ликвидности из пары, если LP-токены остались у разработчика. Проверяется блокировка.
4.1. LP-токен пары
В обозревателе находится адрес пары (для Uniswap V2-форка — через `factory.getPair(tokenA, tokenB)`, для V3 — через `NonfungiblePositionManager`). Читаются `getReserves()` и `totalSupply()` LP-токенов. Доля LP-токенов у одного адреса должна быть < 50%. Концентрация > 80% у одного кошелька — rug pull через одну транзакцию вывода.
4.2. Lock-контракт
В истории пары ищется транзакция, в которой LP-токены переведены на адрес известного локера: Unicrypt Network, Team Finance, Mudra Locker, PinkLock. Лок верифицируется через API локера или через обозреватель: lock-контракт должен иметь метод `getLock` с параметрами `unlockDate` и `amount`. Блокировка менее 6 месяцев — повышенный риск. Менее 30 дней — отказ.
4.3. Burn LP
Альтернатива локу — отправка LP-токенов на `0x000000000000000000000000000000000000dead`. Проверяется в истории пары: крупная транзакция `Transfer` на dead-адрес от разработчика означает сожжённую ликвидность. Ручной вывод невозможен.
5. Honeypot-симуляция
Симуляция продажи токена до депозита. Используются специализированные сервисы и ручная проверка исходника.
5.1. Sell tax
Проверяется через honeypot.is, tokensniffer.com, dextools.io. Допустимый диапазон:
- Buy tax: 0–5%
- Sell tax: 0–5%
- Transfer tax: 0%
Sell tax > 10% — отказ. Sell tax = 100% — honeypot, отказ. Асимметрия buy/sell > 5% (например, buy 0%, sell 8%) — отказ.
5.2. Blacklist и whitelist
В исходнике проверяется `mapping(address => bool) isBlacklisted` и функция `setBlacklist(address, bool)`. Доступ owner без timelock — отказ. Режим whitelist-only для продаж — отказ (схема pump-and-dump для ограниченного круга адресов).
5.3. Симуляция транзакции
Перед подписанием `approve` + `deposit` выполняется форк-симуляция в Tenderly. Подставляются реальные параметры (адрес кошелька, сумма) и проверяются:
- `deposit` не revert'ится
- Gas estimate < 500k
- Возвращаемое значение соответствует ожидаемому количеству LP-токенов
Revert в симуляции — отказ вне зависимости от текста ошибки.
6. Протокол принятия решения
Собранные данные сводятся в финальную матрицу.
| № | Проверка | Результат | Действие при «нет» |
|---|---|---|---|
| 1 | TVL > $500k | да/нет | Отказ |
| 2 | Возраст контракта > 30 дней | да/нет | Отказ |
| 3 | Аудит без unresolved critical | да/нет | Отказ |
| 4 | Verified source | да/нет | Отказ |
| 5 | Owner renounced или multisig | да/нет | Отказ |
| 6 | Нет owner-функций `withdraw`/`setRouter` без timelock | да/нет | Отказ |
| 7 | LP lock > 6 мес. или burn | да/нет | Отказ |
| 8 | Sell tax < 5% | да/нет | Отказ |
| 9 | Симуляция deposit проходит | да/нет | Отказ |
6.1. Размер позиции
При прохождении всех девяти проверок — максимум 2% портфеля на один LP. При одной-двух оговорках (например, timelock 24 часа вместо 48, или TVL $400k) — 0.5% портфеля. При трёх и более оговорках — 0. Депозит свыше 2% на один LP — отказ вне зависимости от результатов проверок: диверсификация обязательна.
6.2. Мониторинг после депозита
Стейкинг не заканчивается на `deposit`. Контракт может быть обновлён через proxy, owner может быть восстановлен, аудитор может обнаружить критическую уязвимость постфактум. Обязательные действия:
- Подписка на GitHub-репозиторий проекта: уведомления о новых коммитах.
- Мониторинг обозревателя: уведомления о крупных транзакциях с участием owner-адреса.
- Проверка каждые 14 дней: TVL, holder distribution, статус lock, изменение owner.
Бинарный протокол: на каждом шаге — да или нет. Ответ «вероятно» равен ответу «нет».
Для отслеживания смежной повестки — от новостной ленты до практических гидов — работает агрегатор на burcusaral.com.
Итог
Безопасный стейкинг в пул ликвидности — это не доверие к бренду протокола и не оценка доходности, а последовательность из девяти бинарных проверок. TVL выше порога, возраст контракта больше месяца, аудит без нерешённых критических issues, верифицированный исходник, renounced owner или мультисиг, отсутствие критических owner-функций без timelock, LP залочен на полгода или сожжён, sell tax ниже 5%, симуляция deposit проходит. Каждый пункт — либо «да», либо «нет». Ответ «вероятно» приравнивается к «нет». Депозит сверх установленного лимита позиции — отказ вне зависимости от результатов проверки. Вердикт: безопасно — только при девяти «да» подряд и размере позиции ≤ 2% портфеля. Любая другая комбинация — небезопасно.