Введение
В этой статье мы рассмотрим протокол кредитования — Curve LlamaLend. Это уникальный проект, основанный на стейблкоине CrvUSD и использующий автоматизированного маркет-мейкера (AMM) в своей основе. У CrvUSD есть несколько интересных особенностей, таких как математическая модель для управления стабильностью курса и механизмы стабилизации, которые работают с ценовыми диапазонами. Эти диапазоны чем-то напоминают «тики» из Uniswap V3, но функционируют иначе. Ещё одна необычная деталь — так называемые «мягкие ликвидации». Они работают совершенно не так, как стандартные ликвидации в других протоколах.
Разработка Curve LlamaLend ведётся в основном на языке программирования Vyper, что делает его ещё более интересным для технических специалистов.
Протокол Curve LlamaLend представляет собой набор рынков кредитования, где CrvUSD используется как основной стейблкоин:
Небольшое отступление: в своём Telegram-канале я делюсь ещё большим количеством полезного контента о децентрализованных финансах и деривативах: t.me/kirrya_achieves
Но а теперь, давайте разберёмся, как это работает!
Высокоуровневый дизайн
Протокол кредитования Curve использует ту же механику и код, что и CrvUSD. Это логично, поскольку большинство алгоритмических стейблкоинов применяют позиции долга/обеспечения, схожие с механизмами кредитования. Основное различие заключается в том, что в CrvUSD создаются новые стейблкоины, а в кредитовании они берутся из пула ликвидности:
«Сердцем» обоих механизмов является LLAMMA — AMM с уникальным дизайном. Поскольку мы говорим о кредитовании, невозможно не упомянуть LLAMMA, так как она добавляет уникальные свойства всему протоколу.
Ликвидность в LLAMMA организована в «диапазонах», аналогичных «тикам» в Uniswap V3, где каждый диапазон отвечает за свой ценовой диапазон. Работа AMM Curve в рамках одного диапазона схожа с Uniswap V3. Свопы также последовательно «пересекают» диапазоны, оставляя слева от текущего диапазона только заемные активы, а справа — только обеспеченные активы:
Однако в стейблкоин-протоколах и кредитных протоколах всегда используется внешний оракул для определения цены обеспеченного актива. В таких протоколах AMM работает не только как DEX, но и как механизм стабилизации, который способен перемещать позиции пользователей ближе к «здоровому» состоянию. Уникальная идея CrvUSD и кредитования заключается в создании AMM, который стимулирует маркет-мейкеров постоянно обменивать обеспеченные активы на заемные токены и наоборот, чтобы улучшать позиции пользователей.
На графике из whitepaper мы видим:
-
Внешнюю цену оракула 0,
-
Ценовой диапазон «текущего диапазона» (белая зона),
-
Цена AMM внутри AMM.
Когда своп перемещается в следующий диапазон (выходя за пределы белой зоны), цена AMM увеличивается или уменьшается более резко, чем линейно (зеленая и желтая зоны). Такие операции «заглядывают вперед» на рынок, устанавливая цены покупки/продажи ниже/выше рыночных. Это стимулирует торговых ботов проводить более крупные свопы и быстрее двигаться к рыночной цене.
Эта нелинейная смена цен за пределами текущего диапазона достигается путем изменения всей(!) ценовой сетки для диапазонов. Это существенно отличается от Uniswap V3, где интервалы между «тиками» фиксированы. В Curve цены, «привязанные» к диапазонам выше и ниже текущего, изменяются нелинейно, что создает дополнительные стимулы для маркет-мейкеров обмениваться в «правильном» направлении.
Обеспеченные активы пользователей распределяются по диапазонам, а свопы в LLAMMA одновременно конвертируют обеспеченный актив в заемный токен и наоборот. Если операция происходит в «правильном» направлении, то она покупает активы, чья цена упала, повышая их стоимость (когда цена обеспечения падает, а пользователи становятся «нездоровыми»), и продает активы в обратном случае.
Этот механизм позволяет AMM Curve поддерживать кредитные механики, создавая стимулы для автоматической ликвидации и «мягких ликвидаций». Таким образом, ликвидации в CrvUSD (если цены не демонстрируют резких изменений) на самом деле не являются ликвидациями. Это непрерывный обмен обеспеченного актива на долговой актив и наоборот, перемещающий позиции пользователей в «здоровое» состояние с помощью торговых ботов. В случае резкого изменения цен Curve также поддерживает традиционные «жесткие ликвидации», аналогичные другим протоколам, где долг пользователя погашается за счет его обеспечения.
Мягкие ликвидации делают позиции пользователей нестабильными, так как их обеспеченные активы могут разделяться на две части: одна часть остаётся в обеспеченном активе (например, WETH), а другая — в стейблкоине (например, CrvUSD). Соотношение между этими активами изменяется в зависимости от цены обеспечения.
Этот дизайн очень интересен, но при экстремальных изменениях цен может возникнуть ситуация, когда всё обеспечение пользователя конвертируется в стейблкоины. В таком случае «здоровье» позиции становится странным: например, CrvUSD может оказаться и обеспечением, и долгом одновременно, что добавляет сложности.
Теперь давайте посмотрим, как устроен сам протокол.
Основная структура Curve LLamaLend
В основе работы Curve LlamaLend лежит комбинация трёх ключевых контрактов: Vault, AMM (LLAMMA) и Controller. Эти контракты совместно создают рынок кредитования для двух токенов: один из них используется как заемный актив, а другой — в качестве обеспечения. Существует два варианта развертывания этой комбинации: OneWayFactory и TwoWayFactory.
-
OneWayFactory
Этот вариант создает рынок кредитования для пары CrvUSD + токен-обеспечение. Например, CrvUSD выступает в роли заемного актива, а другой токен, такой как WETH, используется в качестве обеспечения. -
TwoWayFactory
Этот вариант более сложный и создает два взаимосвязанных кредитных рынка с «зеркальными» ролями токенов. Один рынок ориентирован на «лонг», а другой — на «шорт». Например:-
На первом рынке CrvUSD используется как заемный токен, а WETH — как обеспечение.
-
На втором рынке роли меняются: WETH становится заемным токеном, а CrvUSD используется в качестве обеспечения.
-
Этот подход обеспечивает большую гибкость для пользователей, позволяя им как занимать стейблкоины под активы, так и использовать стейблкоины для получения ликвидных активов в долг.
Factory (Фабрика)
Первым шагом является инициализация фабрики, где задаются адреса для контрактов AMM, Controller и Vault, а также адреса оракулов, параметры денежной политики и другие настройки. После инициализации фабрика может развертывать новые рынки кредитования (в настоящее время только с CrvUSD в качестве стейблкоина).
Основные функции фабрики:
-
Создание хранилища (Vault):
Фабрика предоставляет методы для создания хранилища, где пользователи делят контракт хранения. Для определения цены можно использовать:-
Уже существующий пул AMM (например, обычный пул Curve), который выступает в роли ценового оракула.
-
-
Параметр A (коэффициент усиления):
Для каждого нового рынка кредитования необходимо задать параметр A, который аналогичен tickSpacing в тиках Uniswap V3. Этот параметр определяет, как AMM будет реагировать на изменения цен (описан в статье здесь).
После настройки параметров фабрика создаёт хранилище (Vault) и связанные с ним контракты AMM и Controller. Это обеспечивает полное взаимодействие всех элементов системы. В случае TwoWayLendingFactory создаются два хранилища, каждое из которых представляет свой рынок кредитования.
-
Ключевая особенность: Оба рынка используют один и тот же ценовой оракул.
-
Если для каждого рынка использовать разные ценовые оракулы, это может сделать систему уязвимой к манипуляциям с ценами. Даже небольшие изменения цен могут привести к усиленным арбитражным возможностям между хранилищами.
LLAMMA (Ключевая часть AMM)
LLAMMA (Liquidity Lending AMM) — это основной механизм кредитования, реализованный в контракте AMM.vy. Он связывает рыночные цены с внутренними ценами AMM, обеспечивая уникальную механику распределения ликвидности и управления ценовыми диапазонами.
Самая важная функция в LLAMM — _p_oracle_up(), которая вычисляет p_base * ((A - 1) / A) ** n — верхнюю цену для n-го диапазона (страшная математика в коде — это реализация exp). Эта функция управляет ценовыми диапазонами для каждого ценового диапазона и при изменении «сдвигает» распределение ценовых диапазонов по всем диапазонам. Все остальные «растущие» и «падающие» цены (опорные и AMM) для каждой группы рассчитываются на основе этой функции.
Основная рабочая функция в LLAMMA — _exchange(), которая, как и в Uniswap, имеет две ветви для расчёта целевых параметров обмена на основе необходимого «входящего» или «исходящего» количества токенов. Основной цикл «прохождения» по диапазонам с обновлением резервов каждого пересекаемого диапазона находится здесь. После этого active_band AMM меняется.
Далее в LLAMMA идёт функция deposit_range(), которая принимает залог от пользователя и помещает его в диапазон диапазонов (от n1 до n2). Мы разделяем весь залог на равные части (y_per_band) и для каждого диапазона добавляем доли пользователю и обновляем общее количество долей диапазона.
Возможно, вы помните, что при обеспечении ликвидности в Uniswap V3 не использовалась операция «для каждого тика». Здесь мы не можем избежать таких операций «для каждого диапазона» из-за «плавающей» сетки цен диапазонов и мягкой ликвидации. Нам нужно точное количество долей для каждого пользователя в каждом диапазоне, независимо от того, полностью ли этот диапазон состоит из залогового токена или стейблкоина. В противном случае для обеспечения ликвидности в диапазоне тиков можно использовать что-то похожее на Uniswap V3.
Функция вывода средств() работает аналогично функции ввода, перебирая диапазоны, удаляя ликвидность и доли.
Controller
Контроллер в системе Curve Lending реализован в контракте Controller.vy. Он отвечает за управление долгами пользователей, сохраняя их в loan mapping, а также за обработку заемных активов, предоставленных кредиторами. Когда пользователь вносит средства через функцию deposit()
, заемные токены передаются в Controller, который затем переводит их пользователю, формируя займ.
Создание займа (_create_loan())
-
Для создания займа используется функция
_create_loan()
, где параметр определяет количество диапазонов (bands), в которые равными частями распределяется обеспечение. -
При формировании долга определяется начальный диапазон , начиная с которого обеспечение распределяется по последующим диапазонам.
-
После сохранения данных о займе Controller вызывает
AMM.deposit_range()
, чтобы передать обеспечение напрямую в LLAMMA.
Этот процесс обеспечивает тесную связь между обеспечением и AMM, позволяя автоматически использовать его в механизмах стабилизации и управления ликвидностью.
Vault
В протоколе Curve Lending контракт Vault выполняет роль ERC-4626-хранилища (в Vyper нет готовой реализации стандарта ERC-4626) и выпускает доли хранилища (vault shares) для конечных пользователей. Все функции ERC-4626 реализованы в контракте, причем ключевыми являются _convert_to_assets
и _convert_to_shares
, которые отвечают за конвертацию активов и долей. Также используется механизм DEAD_SHARES для защиты хранилища от инфляционных атак.
Хотя Vault теоретически мог бы быть интегрирован в Controller, он был добавлен как отдельный модуль, поскольку механизм кредитования появился уже после разработки CrvUSD. Сейчас Vault отвечает за управление долями кредиторов и заемщиков, обеспечивая их взаимодействие с остальными компонентами системы.
Oracles (Оракулы)
В экосистеме Curve используются различные оракулы. Хотя возможно подключение к Chainlink или другим внешним оракулам, наиболее логичным решением является использование собственных пулов Curve, обладающих значительной ликвидностью.
Например, для кредитного AMM WETH/CrvUSD применяется контракт CryptoFromPool.vy, который берёт цену из пула crvUSD-WETH-CRV.
Важной частью дизайна оракулов в CrvUSD является ограничение скорости изменения цен с помощью функции limit_p_o()
. Резкие изменения цены оракула могут влиять на здоровье позиций пользователей и вызывать потери в AMM.
Также изменения цен, выдаваемых оракулом, влияют на динамическую комиссию для свопов (функция get_dynamic_fee()
). Это снижает риски значительных потерь AMM в условиях резких ценовых колебаний и атак типа «сэндвич».
Risk Management (Управление рисками)
Первый аспект управления рисками — это «здоровье» позиции пользователя. Основная функция — health. Значение должно быть положительным.
Первая часть расчёта аналогична другим протоколам: это соотношение обеспечения к долгу. Однако дополнительно учитывается разница цен выше самого высокого диапазона обеспечения пользователя, которая влияет на стоимость обеспечения и, соответственно, на «здоровье» позиции. Эта часть логики активируется с помощью флага full, который включён почти во всех случаях, кроме функции repay()
. В этой функции используется «чистый» расчёт соотношения здоровья для предотвращения манипуляций ценой в AMM во время ликвидаций.
APY для кредитования и заимствования (основанный на ставках заимствования) в CrvUSD не фиксированный и определяется денежной политикой. В системе реализованы несколько вариантов таких политик, включая SemilogMonetaryPolicy и SecondaryMonetaryPolicy. Например, пул кредитования CRV/CrvUSD использует SemilogMonetaryPolicy.vy.
Эта политика рассчитывает ставку, используемую в AMM, на основе коэффициента использования рынка (total_debt/total_collateral
). Администратор фабрики может изменять денежную политику, чтобы адаптировать протокол к рыночным условиям.
Additional Implementation Details
Проекты Curve содержат множество интересных деталей реализации.
Vault и Controller отслеживают балансы токенов напрямую. Некоторые протоколы, такие как Euler V2, вместо этого поддерживают собственные копии балансов. Оба подхода работают: подход с копией баланса более устойчив к атакам "пожертвования", но дороже и сложнее. Использование balanceOf() проще и дешевле, но более уязвимо для таких атак.
Пользовательские тики, содержащие информацию о долях в каждом тике, хранятся в виде 128-битных значений. Чтение пользовательских тиков реализовано здесь, а пользовательские позиции хранятся в виде сопоставления адрес => структура UserTicks, где userTicks содержит диапазон тиков (в виде переменной 2x128 = 256) и массив с долями в каждом тике в этом диапазоне.
Функция users_to_liquidate()
в Controller возвращает список пользователей, которых можно ликвидировать. В других протоколах боты отслеживают такие позиции самостоятельно. Эта функция может помочь ботам, но ее значение ограничено, так как боты в основном ориентируются на потенциальные ликвидации, предвосхищая изменения цен.
LLAMMA также поддерживает стимуляцию ликвидности через контракты майнинга, например, вызывая self.liquidity_mining_callback
в функциях вроде deposit_range()
.
Для оптимизации LLAMMA использует заранее рассчитанные значения квадратного корня и логарифма для выражений с параметром A, что снижает вычислительные затраты в контрактах.
Заключение
Curve LlamaLend — это инновационный проект, объединяющий передовые механизмы AMM и кредитования для решения ключевых проблем DeFi, таких как управление ликвидациями. В основе системы лежит LLAMMA, которая обеспечивает защиту пользователей от жёстких ликвидаций, автоматически оптимизируя их позиции в стабильных рыночных условиях. Благодаря этому рынки Curve практически избегают проблем с «плохими долгами», а объём жёстких ликвидаций остаётся минимальным даже в нестабильных пулах.
Хотя изначально система ориентирована на использование CrvUSD, её можно адаптировать и под другие стейблкоины. Вероятно, в будущем мы увидим новые рынки, использующие механизм стабилизации LLAMMA. Это делает кредитование Curve особенно интересным для разработчиков и аналитиков в сфере DeFi.
Мы продолжим анализировать важные протоколы кредитования в следующих статьях. Следите за обновлениями!
Автор: kirrya