Liquidity Request (Pending Withdrawal)
Что такое Liquidity Request
При выводе Alien токенов из TVM в EVM контракт MultiVault должен отправить получателю реальные токены из своего баланса. Если баланс недостаточен — вывод не может завершиться мгновенно. В этом случае создаётся Liquidity Request (LR) — отложенный вывод (Pending Withdrawal) со статусом NotRequired, который ожидает поступления ликвидности.
Зачем нужен механизм LR?
- Защита от блокировки средств — без LR транзакция бы просто откатилась, и пользователь не смог бы получить токены. LR фиксирует право на вывод и позволяет завершить его позже
- Экономический стимул для LP — пользователь устанавливает bounty (награду), что привлекает провайдеров ликвидности для быстрого закрытия LR
- Гибкость для получателя — если ликвидность не появляется, пользователь может отменить LR и вернуть токены в TVM
Как это работает
- Пользователь инициирует вывод Alien токена из TVM → EVM
- При вызове
saveWithdrawAlien()MultiVault обнаруживает, что баланс меньше суммы вывода - Создаётся Pending Withdrawal со статусом
NotRequired— одобрение governance не требуется - Получатель устанавливает bounty — награду за заполнение LR
- Провайдер ликвидности (LP) вносит токены через
deposit(), закрывает LR и забирает bounty - Получатель получает свои токены (за вычетом bounty)
Важно
Liquidity Request существует только на стороне EVM сети и только для Alien токенов. Native токены при выводе минтятся, поэтому нехватка ликвидности для них невозможна.
Схема создания Liquidity Request
Технически LR — тот же Pending Withdrawal, что создаётся при превышении лимитов, но со статусом NotRequired вместо Required.
Пример сценария
Пользователь выводит 50,000 USDT из TVM → EVM
1. Контракт проверяет баланс MultiVault: 10,000 USDT
2. 50,000 > 10,000 — ликвидности недостаточно
3. Создаётся LR с approveStatus = NotRequired
4. LP заполняет LR через Fill и забирает bounty
5. Пользователь получает свои 50,000 USDT (минус bounty)Структура данных
Что хранится в каждом LR
| Поле | Что означает |
|---|---|
token | Какой токен выводится |
amount | Сколько (уже за вычетом комиссии) |
bounty | Награда для LP за fill (устанавливает пользователь) |
timestamp | Когда был создан запрос в TVM |
approveStatus | Текущий статус (NotRequired для LR) |
chainId | В какую сеть выводить |
callback | Данные для вызова после вывода |
Доступные действия
LR создаётся со статусом NotRequired — одобрение governance не требуется, можно действовать сразу:
| Действие | Кто может | Описание |
|---|---|---|
| Fill | Любой (обычно LP) | LP вносит токены, получатель получает сумму минус bounty |
| Force Withdraw | Любой | Прямой вывод при появлении ликвидности на MultiVault |
| Cancel | Владелец LR | Отмена и возврат токенов в TVM |
| Bounty | Владелец LR | Установка/изменение награды для LP |
TIP
Если Pending Withdrawal создан из-за превышения лимитов (статус Required), действия отличаются — см. Лимиты.
Идентификация LR
Каждый LR идентифицируется парой recipient (адрес получателя) + id (порядковый номер).
События для отслеживания
| Event | Когда эмитится | Параметры |
|---|---|---|
PendingWithdrawalCreated | При создании LR | recipient, id, token, amount, payloadId |
PendingWithdrawalFill | При fill через deposit | recipient, id |
PendingWithdrawalForce | При force withdraw | recipient, id |
PendingWithdrawalCancel | При отмене | recipient, id, amount |
PendingWithdrawalUpdateBounty | При изменении bounty | recipient, id, bounty |
TIP
События Approve/Reject и автовывода описаны в разделе Лимиты.
Механизм Fill (LP)
Провайдер ликвидности (LP) может "заполнить" чужой LR, внеся свои токены. Получатель получает деньги, а LP забирает bounty.
LP вносит 1000 USDT через deposit()
│
▼
Пользователь с LR получает 990 USDT (установил bounty = 10)
│
▼
LP получает в TVM: 1000 + 10 - fee = ~1008 USDTПроцесс:
- LP вызывает
deposit()с токенами и списком LR для закрытия - Для каждого LR:
- Проверяется что токен совпадает
- Проверяется что достаточно средств
- Получатель получает
amount - bounty - LP накапливает bounty
- LP получает в TVM:
depositAmount + totalBounty - fee
Bounty — вознаграждение для LP
Пользователь сам устанавливает bounty — это стимул для LP заполнить именно его LR:
- Чем выше bounty, тем привлекательнее LR для LP
- Bounty не может быть больше суммы вывода
- Можно изменить bounty в любой момент (пока LR активен)
Как установить bounty:
setPendingWithdrawalBounty(id, bounty)Cancel — отмена LR
Получатель может отменить Liquidity Request и вернуть токены в TVM.
cancelPendingWithdrawal(id, amount, tvmRecipient, ...)Ограничения:
- Только для Alien токенов (из EVM)
- Только владелец LR
- Статус должен быть
NotRequiredилиApproved
Force Withdraw — прямой вывод
Если LR имеет статус NotRequired или Approved и на MultiVault появилась ликвидность, любой адрес может протолкнуть вывод напрямую. Получатель получает полную сумму — bounty не вычитается.
forceWithdraw(pendingWithdrawalIds[])Коды ошибок
| Ошибка | Причина |
|---|---|
"Pending: amount is zero" | LR уже заполнен или отменён |
"Pending: native token" | Bounty нельзя установить для Native токенов |
"Pending: bounty too large" | Bounty больше суммы вывода |
"Pending: wrong amount" | Неверная сумма для cancel |
"Pending: wrong token" | Токен LR не совпадает с токеном депозита |
"Pending: deposit insufficient" | Недостаточно средств для fill |