@overnight-contracts/blp-rebalancer v0.0.1
RebalancerAave
Взят по адресу: https://etherscan.io/address/0x1ed9c8bd3dccb85f704a5287444b552f9d5e1a26#code
Используется для примера построения своего ребалансера.
RebalancerPlus
Осуществляет ребалансировку основного токена в линейном (LinearPool) пуле по аналогии с RebalancerAave. В пуле планируется работать с парой USDC-USD+, где USDC будет основным (mainToken), а USD+ врапированным статик токеном StaticUsdPlus (wrapped). UsdPlus и StaticUsdPlus конвертируются через deposit/redeem на контракте StaticUsdPlus.
Для получения flash займов используется пул UniswapV3 USDC-USDT:
- на Polygon используем пул: https://info.uniswap.org/#/polygon/pools/0x3f5228d0e7d75467366be7de2c31d0d098ba2c23 - 0.05%
- на Etherium такой же пул: https://info.uniswap.org/#/pools/0x5777d92f208679db4b9778590fa3cab3ac9e2168 - 0.01%
UniswapV3 pool USDC-USDT на polygonscan: https://polygonscan.com//address/0x3f5228d0e7d75467366be7de2c31d0d098ba2c23
Balancer Vault на polygonscan: https://polygonscan.com/address/0xba12222222228d8ba445958a75a0704d566bf2c8
Принцип работы
Параметрами вызова метода rebalance являются:
- id балансируемого пула с Balancer
- желаемый объем основного токена, к которому надо привести текущее значение
- флаг использования flash займов
Если желаемый объем не указан, то вместо него будет использовано ближайшая граница коридора допустимого значения основного токена.
Если не указано использовать флеш займ, то будет произведена попытка произвести своп с использованием средств вызвавшего контракт пользователя, поэтому необходимо будет разрешить (approve) движение средств, на необходимый объем для соответствующего токена. Объем для аппрува необходимо будет узнать через вызов approveAmountRequirement.
Основного токена меньше желаемого объема
Для случая когда основного токена меньше желаемого объема, то необходимо сделать обмен (swap) на этом пуле основного токена на врапировнный (USDC -> USD+). При этом указываемый для обмена объем соответствует объему основного токена и нет необходимости в доп расчетах.
Для определения объема займа дополнительно ничего делать не нужно, т.к. займ будет в USDC и объем для свопа и займа совпадают.
Основного токена больше желаемого объема
В обратном случае необходимо произвести обмен врапированного токена на основной (USD+ -> USDC). На волте можно указать для операции свопа, что мы знаем объем выводимого токена, поэтому для формирования запроса больше ничего не требуется.
Но для подсчета объема для займа необходимо получить необходимый объем врапированного токена, который
надо будет передать во время обмена в пул. Этот объем вычисляется так же, как это будет происходить
внутри пула в момент обмена, поэтому из линейного пула берется функция из линейного
пула (getWrappedInForMainOut).
Дальше этот объем врапированного токена для обмена пересчитывается в объем USDC,
который потребуется для займа - для этого используется staticToDynamicAmount функция из врапированного
токена (StaticUsdPlus)
Flash
Для движения средств в обоих случаях требуется обернуть какое-то количество USDC, которые берутся из пула юнисвопа USDC-USDT по механизму flash-loans. Для этого на предыдущем этапе был подсчитан объем USDC, который будет взят в займы. Принцип работы флешей подразумевает, что контракт должен реализовать функцию-колбек (uniswapV3FlashCallback), которую вызовет пул после перечисления средств на контракт ребалансера. По окончанию работы этой функции на адрес пула (он вызывает, msg.sender) необходимо перечислить взятые ранее взаймы средства и доплатить процент. Процент определяется на пуле и соответствует проценту при свопах.
Запрос на флеш должен содержать в себе объем займа и данные, которые будут переданы в функцию колбека.
uniswapV3FlashCallback
На момент вызова этой функции текущий контракт получает заказанный объем основного токена (USDC) и далее производит следующие действия:
- проверка, что вызов был из нужного пула, а не стороннего пользователя или контракта
- проверка, что действительно был получен займ
- выполнение обмена (вызов doSwap)
- оценка необходимости в доп ликвидности и запрос ее
- передача средств займа с процентами в пул
Дополнительная ликвидность может потребоваться для оплаты процентов, например из-за некорректно указанных комиссий. В таком случае будет произведена попытка запросить у вызвавшего метод rebalance необходимого для покрытия объема USDC. В случае невозможности произойдет откат.
Если после обмена останется прибыль в виде неизрасходованных USDC,
doSwap
Осуществляет сами обмены.
USD+ -> USDC
Если осуществляется обмен USD+ -> USDC для увеличения объема USDC, то перед обменом производится перевод
заемных средств (USDC) в StaticUsdPlus в два этапа:
1. На Exchange
через метод buy
обмениваются Usdc на UsdPlus
2. Полученные UsdPlus переводятся в StaticUsdPlus в StaticUsdPlus.deposit
После чего осуществляется обмен (swap) на волте балансера. Комиссия 0.04% на эксчендже на buy, которая будет компенсирована на пейауте, можно считать, что эти выплаты пойду уже на пул, но при вычислениях это образует нехватку.
USDC -> USD+
Если осуществляется обмен USDC -> USD+ для уменьшения объема USDC, то сначала производится обмен на волте.
После обмена полученные StaticUsdPlus токены обмениваются на USDC в два этапа:
1. StaticUsdPlus переводятся в UsdPlus в StaticUsdPlus.redeem
2. Полученные UsdPlus на Exchange
через метод redeem
обмениваются на Usdc
Комиссия 0.04% на эксчендже на redeem, невозвратные.
estimateDeficitRequirement
При работе с флеш займом возможна ситуация, когда недостаточно средств для выплаты комиссии, поэтому данный метод дает оценку дефицита, который должен быть покрыт вызывающим ребансировку. Вызывающий должен иметь необходимый объем основного токена и выдать разрешение (approve) на перевод от имени контракта этого объема.
approveAmountRequirement
Высчитывает объем основного токена, который будет запрошен у вызывающего ребалансировку, если не будет использоваться флеш займ. На этот объем необходимо выдать approve на контракт ребалансера.
Запуск тестов в IDEA
Для запуска тестов mocha из-под IDEA необходимо указать в Node options
:
-r ts-node/register
И в Environment variables
:
TS_NODE_FILES=true
1 year ago