Aave. Flash loans в децентрализованных протоколах кредитования

от автора

Flash loan — это тип кредитования, который не требует залога для обеспечения займа. По‑другому, быстрый заем. Основное условие такого займа — долг должен быть погашен заемщиком в рамках одной транзакции. Это означает, что заемщик, берет активы в займы, а к концу транзакции обязан вернуть долг обратно. Если этого не произойдет, то транзакция будет отменена.

Off top! Транзакция в блокчейне обладает свойством атомарности. Поэтому она либо выполняется полностью, либо не выполняется вовсе. Если в конце транзакции долг не возвращается, то транзакция отменяется и никакие изменения не вступают в силу.

Где‑то в промежутке между займом и возвратом долга заемщик должен успеть провести необходимые операции с заемными активами. Он может использовать их на свое усмотрение.

На данный момент flash loans являются популярными в ряде современных децентрализованных протоколов кредитования. Они обладают следующими уникальными характеристиками:

  • Смарт‑контракт. В работе быстрого займа используется смарт‑контракт. Именно он позволяет следить за соблюдением условий кредитования.

  • Отсутствие залога. Вместо залога, заемщик должен вернуть средства в рамках одной транзакции.

  • Скорость. Так как заем и возврат происходят в рамках одной транзакции, скорость операций очень высокая.

  • Нулевой риск. Если к концу транзакции, заем не будет погашен. Транзакция будет отменена. Заемщик не потеряет средств, так как залог протоколу он не оставлял.

История появления flash loans

Впервые концепция flash loans упоминалась протоколом Marble в 2018 году. Marble называли себя «smart contract bank» в сети Ethereum. Продукт позиционировался, как децентрализованный кредитный протокол с открытым исходным кодом. Инновацией проекта считалась возможность смарт‑контракта выполнять любой произвольный код после займа. Важным условием такого займа был возврат средств на смарт‑контракт в рамках одной транзакции. Подробнее в статье Max Wolff “Introducing Marble”.

По-настоящему все изменилось, когда Aave запустило свой протокол на базе пулов ликвидности в январе 2020 года. Для flash loans началась новая веха в истории. Потому что при помощи протокола Aave сторонние разработчики получили возможность разрабатывать целые DeFi приложения на базе flash loans. При этом размер быстрого займа мог достигать миллионов долларов, а комиссия за его выдачу всего 0,09% от суммы займы.

Разработчики приложений воистину оценили огромный потенциал flash loans практически сразу, как Aave появилась в релизе. Однако по-настоящему, быстрые займы стали востребованы спустя несколько месяцев, благодаря росту числа пользователей DeFi приложений и последовавшим ростом комиссий в сети Ethereum. Обычные операции с DeFi-протоколами стали обходиться слишком дорого. Но использование стратегий на основе flash loans позволяло значительно снизить затраты на газ и найти новые возможности для извлечения прибыли.

Принцип работы flash loan

На данный момент мы знаем, что в протоколе кредитования участвуют два основных субъекта:

  • Кредитор

  • Заемщик

Для взаимодействия с кредитором при помощи инструмента flash loan заемщику необходимо разработать смарт-контракт. Этот смарт контракт должен уметь выполнять три действия:

  1. Занимать средства у кредитора. В нашем случае кредитором для заемщика выступают протоколы кредитования, которые предоставляют функционал flash loan. Например, Aave.

  2. Совершать операции с заемными средствами. Например, продажа или покупка активов на бирже.

  3. Возвращать заемные средства кредитору с процентами за использование займа.

Все это происходит в рамках одной транзакции и представлено на схеме ниже.

Для чего можно использовать flash loans?

Flash loans имеют широкий спектр применения. Они используются во многих ситуациях от извлечения дополнительных объемов в торговли до ликвидации собственных позиций. Ниже предлагаю разобрать самые популярные варианты использования.

Арбитражная торговля

Арбитраж — стратегия заработка с использованием разных цен на один и тот же актив на одной или разных биржах с целью получения прибыли.

В упрощенном виде, арбитраж можно представить схемой ниже.

Flash loans позволяют использовать заемные средства для арбитража с нулевым риском. Риск отсутствует, потому что кредитный протокол самостоятельно отменит транзакцию в случае нехватки средств для погашения долга. Поэтому, если заемщик прогорит на межбиржевых операциях, неправильно рассчитает свои затраты на газ или произойдет проскальзывание цены, он не рискует ни своими средствами, ни средствами кредитного протокола. Но если заемщик правильно просчитает профит при арбитраже, быстрый заем поможет увеличить профит в несколько раз.

Помимо отсутствия риска, flash loans обладают высокой скоростью исполнения. Скорость положительно влияет на арбитражную торговлю. Делать одну транзакцию вместо обычных двух (транзакция на покупку и транзакция на продажу) выгоднее. Это предохраняет от проскальзывания цены и позволяет попасть в арбитражное окно (момент, когда нам выгодно проводить арбитражную торговлю).

Также огромный плюс заключается в возможности привлечь дополнительные активы протоколов кредитования. Нет необходимости обладать стартовым капиталом, всегда можно взять flash loans без залога.

Например, алгоритм может выглядеть следующим.

Понять схему выше можно следующим образом:

  1. Взять актив в быстрый заем у кредитного протокола.

  2. На заемные средства купить актив на бирже, где он дешевле.

  3. Продать актив на той бирже, где он дороже.

  4. Вернуть долг + проценты кредитному протоколу. Профит оставить себе.

Именно арбитражная торговля является одним из самых популярных способов использования flash loans. К тому же такой арбитраж помогает поддерживать межбиржевой курс любого актива. То есть, если на одной бирже курс падает, то всегда найдется арбитражер, который своими манипуляциями выровняет курс. Flash loans в этом случае помогают арбитражерам заниматься выравниванием рынка.

Самоликвидация займов (self-liquidating loans)

Обычный заем требует блокировки залоговых средств. Если стоимость залога упадет относительно заемных средств и перестанет обеспечивать заем, то ликвидатор может ликвидировать заем частично или полностью.

Flash loans являются единственным инструментом, который может помочь провести самостоятельную ликвидацию без штрафа. Я не говорю о частичном погашение долга или увеличение суммы залога. Это конечно тоже поможет избежать ликвидации, но сейчас нам интересны flash loans.

Как это работает? Заемщик может спасти свой заем следующим образом.

Понять схему выше можно следующим образом:

  1. Взять быстрый заем.

  2. Погасить долг заемными средствами. Тем самым освободить залог.

  3. Часть залога отправить на погашение flash loan с соответствующими комиссиями.

В результате использования flash loans, пользователь может избежать штрафа за ликвидацию кредита.

Замена залога (swap collateral)

Обычно замена обеспечения займа может потребоваться только в случае падения цены залогового актива. При падение стоимости залога, заем будет неумолимо приближаться к ликвидации. В таком случае от ликвидации можно спастись не только самостоятельно ликвидировав заем (как в прошлом примере). Куда разумнее заменить залог на другой актив, который будет менее волатилен.

Замена обеспечения без использования flash loans потребует полного закрытия кредита. Это будет происходить в несколько этапов. Придется сделать несколько транзакций, что в свою очередь увеличит транзакционные сборы.

Рефинансирование займов

Ставки по займам в различных протоколах кредитования постоянно меняются. Это происходит из-за изменений рыночных условий и объема ликвидности. Flash loans оказались удобным инструментом для перемещения займа с одного протокола на другой с более низкими процентными ставками. При этом всегда есть возможность поменять актив в залоге для обеспечения.

Процесс рефинансирования выглядит следующим образом.

Понять схему выше можно следующим образом:

  1. Взять flash loan.

  2. Погасить долг заемными средствами. Тем самым освободить залог.

  3. Внести залог в другой протокол с более низкими ставками.

  4. Взять заем в новом протоколе.

  5. Часть займа отправить на погашение flash loan с соответствующими комиссиями.

Flash loans в Uniswap

Отдельно стоит отметить, что свою версию flash loans предложил обменник Uniswap. Называется эта опция «flash swaps». Она была запущена во второй версии протокола в мае 2021 года.

На самом деле, со второй версии протокола любые обмены в Uniswap являются flash swaps. Протокол может отменить любую транзакцию на обмен, если выяснится, что он не дополучил достаточно токенов взамен. К тому же любой вызов метода swap() на uniswap принимает параметр data типа bytes. Этот параметр отвечает за выполнение пользовательских операций при получение средств.

function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data);

Если data.length равно 0, это значит, что контракт сначала получает токен для обмена и затем выдает токены в замен.

Если data.length больше 0, то контракт сначала отправляет токены, затем вызывает то, что закодировано в data. Это позволяет выполнять произвольную логику в середине обмена. И если в конце транзакции контракт не получит свою долю токена, транзакция будет отменена.

Flash loan в Aave v2

Во второй версии протокола для использования быстрого займа необходимо вызвать метод flashLoan() на контракте LendingPool.sol.

Особенно стоит отметить, что быстрые займы в протоколе Aave предназначены только для разработчиков. Потому что для их реализации необходимо уметь разрабатывать смарт-контракты и понимать основные принципы блокчейн технологии.

function flashLoan(     address receiverAddress,     address[] calldata assets,     uint256[] calldata amounts,     uint256[] modes,     address onBehalfOf,     bytes calldata params,     uint16 referralCode )

Функция flashLoan принимает следующие аргументы:

  1. receiverAddress. Адрес контракта, который получит активы от протокола. Должен реализовывать интерфейс IFlashLoanReceiver. Этот контракт будет выполнять дополнительные операции пользователя с заемными средствами.

  2. assets. Массив адресов резервов для займа. Адреса токенов, которые будут принимать участие в быстром займе.

  3. amounts. Массив чисел. Обозначает количество занимаемых активов.

  4. modes. Массив чисел. Обозначает режим управления долгом для каждого вида актива. Применяется в случае, если заем не будет погашен до окончания транзакции. Принимает следующие значения:

    • 0 — означает, что долг должен быть обязательно возвращен, иначе будет revert транзакции.

    • 1 — будет взят обычный заем с стабильной процентной ставкой (stable Interest Rate)

    • 2 — будет взят обычный заем с переменной процентной ставкой (variable Interest Rate)

  5. onBehalfOf. Это адрес, который должен владеть достаточно залогом, чтобы был взят обычный заtм. Используется в случае, если параметр mode равен 1 или 2.

  6. params. Закодированные в байтах параметры, которые будут использоваться receiverAddress контрактом.

  7. referralCode. Код реферальной программы Aave.

Как работает функция flashLoan под капотом? Ответом на этот вопрос служит схема ниже, которая показывает, что происходит после вызова функции flashLoan().

Согласно схеме:

  1. Для того чтобы воспользоваться быстрым займом необходимо реализовать контракт User contract. Этот контракт реализует интерфейс IFlashLoanReceiver и должен вызвать функцию flashLoan() на контракте LendingPool. Внутрь функции необходимо передать полный список аргументов согласно списку из документации, который разобран выше.

  2. Внутри контракта LendingPool, в первую очередь, будет проверена валидность переданных аргументов. Необходимо, чтобы длина массива assets равнялась длине массива amounts. Валидация вынесена в отдельный контракт, который называется ValidationLogic.

  3. После проверки LendingPool переведет запрашиваемые средства на адрес контракта пользователя.

  4. После перевода средств LendingPool вызовет метод executeOperation() на контракте пользователя.

  5. Контракт пользователя выполняет все, что у него реализовано в методе executeOperation(). Например, это может арбитражная торговля. Покупка и продажа токенов.

  6. После выполнения executeOperation()LendingPool попытается вернуть заемные средства плюс проценты по займу обратно.

Возврат средств может происходить несколькими способами на усмотрение заемщика. Этим управляет аргумент modes. Это массив чисел. Каждое из значений обозначает режим взимания долга с заемщика. Весь процесс возврата заемных средств протоколу представлен на схеме ниже.

Расшифровать эту схему можно следующим образом.

Если mode для соответствующего актива установлен в значение 0. Протокол постарается вернуть средства в конце транзакции. Он буквально посчитает сумму (заем + проценты), которые необходимо вернуть и постарается сделать transferFrom() на адрес контракта LendingPool. Перед этим он обновит информацию о резервах токенов на контракте. Если для трансфера будет недостаточно средств, то транзакция будет отменена (revert).

Если mode для соответствующего актива установлен в значение 1 или 2. Это значит, что пользователь решил покрыть быстрый заем другим способом — перевести быстрый заем в обычный. Протокол автоматически проверит наличие необходимого залога на адресе, который был указан в параметре onBehalfOf и выполнит заем средств для погашения долга в быстром займе.

Example

Я подготовил целый контракт Liquidator.sol для демонстрации работы с flashLoan(). Этот контракт позволяет ликвидировать позицию заемщика с использованием быстрого займа в рамках одной транзакции. Вознаграждение от процесса ликвидации будет отправляться на кошелек пользователя.

Смарт-контракт Liquidator.sol
// SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.19;  import {IERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; import {SafeERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";  import "./interfaces/IFlashLoanReceiver.sol"; import "./interfaces/ILendingPool.sol"; import "./interfaces/ILendingAdapter.sol"; import "./interfaces/IUniswapV2Router02.sol";  /**  * @title Контракт ликвидатор займа  * @notice Ликвидирует позицию указанного пользователя с использование flashLoan() без использования собственных средств.  * Необходима только оплата за газ  */ contract Liquidator is IFlashLoanReceiver {     using SafeERC20 for IERC20;      ILendingPool lendingPool;     ILendingAdapter lendingAdapter;     IUniswapV2Router02 router;      IERC20 tokenA; // collateral token     IERC20 tokenB; // debt token      constructor(address _lendingPool, address _lendingAdapter, address _router) {         lendingPool = ILendingPool(_lendingPool);         lendingAdapter = ILendingAdapter(_lendingAdapter);         router = IUniswapV2Router02(_router);          tokenA = lendingAdapter.tokenA();         tokenB = lendingAdapter.tokenB();     }      /**      * Ликвидирует позицию заемщика с использованием flashLoan()      * @param borrower Адрес заемщика      * @param repayAmount Сумма для ликвидации долга заемщика      */     function liquidate(address borrower, uint256 repayAmount) external {         address[] memory assets = new address[](1);         assets[0] = address(tokenB);          uint256[] memory amounts = new uint256[](1);         amounts[0] = repayAmount;          // 0 = no debt, 1 = stable, 2 = variable         uint256[] memory modes = new uint256[](1);         modes[0] = 0;          bytes memory params = abi.encode(borrower, msg.sender);          /// Берем быстрый займ и ожидаем что протокол вызовет функцию executeOperation() на нашем контракте         /// в котором мы получим в заем активы и используем для ликвидации позиции заемщика         lendingPool.flashLoan(             address(this),             assets,             amounts,             modes,             address(this),             params,             0         );     }      /**      * Функция callback вызываемая протоколом Aave в рамках работы flashLoan()      * @param amounts Массив сумм для каждого актива      * @param premiums Комиссия с каждого актива, которую необходимо вернуть вместе с заемными активами в конце транзакции      * @param params Упакованные данные, которые переданы вызывающим flashLoan()      */     function executeOperation(         address[] calldata /** assets - Список активов полученных для займа**/,         uint256[] calldata amounts,         uint256[] calldata premiums,         address /** initiator - Адрес вызывающего транзакцию flashLoan()**/ ,         bytes calldata params     ) external returns (bool) {         (address borrower, address recipient) = abi.decode(params, (address, address));         uint256 repayAmount = amounts[0];          /// Даем Approve для LendingPool контракта на взятый в займы tokenB         uint amountOwing = amounts[0] + premiums[0];         tokenB.safeApprove(address(lendingPool), amountOwing);          /// Ликвидируем заем, выплачиваем долг в виде tokenB, получаем за это tokenA         tokenB.safeApprove(address(lendingAdapter), repayAmount);         lendingAdapter.liquidate(borrower, repayAmount);          /// Обмениваем tokenA на tokenB. Нам необходима сумма, которую мы вернем в конце транзакции в рамках flashLoan()         address[] memory path = new address[](2);         path[0] = address(tokenA);         path[1] = address(tokenB);          tokenA.safeApprove(address(router), tokenA.balanceOf(address(this)));         router.swapTokensForExactTokens(             amountOwing,             tokenA.balanceOf(address(this)),             path,             address(this),             block.timestamp         );          /// Отправляем остаток tokenA на собственный адрес. Для нас это profit         tokenA.safeTransfer(recipient, tokenA.balanceOf(address(this)));          return true;     } }

Важно! Полный код в проекте тут. Будь внимательным, если захочется скомпилировать проект и запустить тесты необходимо установить переменную окружения. Смотри readme.

Flash loans приложения

Что же может сделать пользователь, который не умеет писать смарт-контракты? На данный момент существует множество приложений, которые построили веб-интерфейсы для работы с flash loans. Все эти интерфейсы основаны на базе децентрализованных протоколов кредитования.

CollateralSwap

Это веб-сервис с максимально простым интерфейсом. Единственное ограничение заключается в том, что пока он может работать только с протоколом MakerDAO.

Сервис выполняет две задачи:

  1. Быстрая замена залогового обеспечения без необходимости погашения займа;

  2. Самоликвидация займа без штрафа.

В обоих случаях комиссия CollateralSwap берет комиссионные сборы за использование сервиса.

DeFi Saver

Это полноценное децентрализованное приложение, которое позволяет создавать собственные стратегии управления активами и займами на базе flash loans. Приложение поддерживает работу с протоколами MakerDao, Aave, Compound, dYdX и другие. Defi saver наиболее известен благодаря инструменту управления кредитным плечом. Пользователи могут управлять этим инструментом, увеличивая или выплачивая долг всего за одну транзакцию.

Приложение обладает большим набором функциональных возможностей:

  • Поддержка множества кошельков. MetaMask, Ledger, Trezor, Argent, TrustWallet.

  • Yield farming. Вклады активов под годовой процент.

  • Exchange. Обмен одних токенов на другие.

  • Smart Savings. Инструмент, который позволяет быстро перемещать активы между протоколами.

  • Smart Wallet. Это кошелек для смарт-контрактов без ограничений на сложные транзакции.

  • DeFi Recipe Creator. Инструмент создания сложной цепочки последовательных транзакций, которые включают в себя несколько действий. Например, пользователь может создать следующую стратегию «Занять 5000 USDT у Aave v2, продать USDT за UNI на Uniswap».

  • DeFi Saver Automation. Это автоматизированная система управления займами с обеспечением.

Furucombo

Это приложение позволяет максимально просто создать собственные DeFi-стратегии при помощи простого интерфейса. Такие стратегии называются «комбо». Внутри «комбо» можно выстраивать любые стратегии путем перетаскивания различных действий. Каждая транзакция в «комбо» отображается в виде куба. Пользователь может настраивать параметры кубов и их порядок. Затем сервис объединяет все кубы в одну транзакцию и отправляет на исполнение. Flash loans от Aave являются базовой основой для большинства шаблонных «комбо», доступных в этом приложении.

Это отличный инструмент для людей, которые хотят выполнять действия между разными протоколами при помощи flash loans.

Какую опасность в себе несут flash Loans?

Кажется, что flash loans полностью безрисковый инструмент. Если что-то пошло не так, то flash loans не выполнится, транзакция будет отменена. Ведь для займа не требуется залог и совсем нет риска собственными активами.

В чем же может заключаться опасность? Опасность заключается в том, что быстрые займы могут быть превращены в «оружие». Есть две основные причины, по которым быстрые займы привлекательны для злоумышленников:

  1. Многие атаки требуют большого стартового капитала. Например манипуляции с ценовыми оракулами.

  2. Flash loans безрисковые. Это значит, что они сводят к минимуму опасность для злоумышленника. Злоумышленник не будет рисковать своим собственным капиталом для воплощения злонамеренных действий.

Поэтому flash loans чрезвычайно опасны для децентрализованных приложений. Ниже разберем несколько примеров уже состоявшихся атак, которые в свое время потрясли сообщество.

  1. Приложения, которые используют DAO, как механизм голосования в принятие управленческих решений могут быть подвержены атакам. Злоумышленник может взять заем и использовать его для участия в голосование. Ярким примером подобной атаки является протоколов DeFi Beanstalk, который подвергся атаке в апреле 2022 года. Злоумышленник использовал flash loans для того, чтобы принять свое собственное предложение на вывод активов. Ущерб составил приблизительно 77 миллионов долларов.

  2. Flash loans могут использоваться для манипулирования ценами в DEX. Подобная атака произошла в феврале 2020 года с участием торговой платформы dYdX. Злоумышленник взял в заем миллионы ETH, обменял их на BTC на одной площадке, открыл короткую позицию против BTC на другой площадке. После этого продал BTC, чтобы обрушить стоимость, закрыл короткую позицию с прибылью. После чего он спокойно погасил заем и остался с прибылью в 360 000 долларов.

  3. Одной из самых популярных атак с использованием flash loans является взлом при помощи протокола bZx. Злоумышленник занимал средства у протокола и тут же обменивал их на стейблкоин (sUSD). Поскольку стейблкоин управляется смарт‑контрактом, злоумышленник манипулировал его ценой, разместив крупный ордер на покупку sUSD, что подняло цену стейблкоина до 2 долларов, удвоив его привязанную стоимость. Затем злоумышленник взял более крупный кредит в более дорогом sUSD, погасил свои займы и забрал прибыль с собой.

  4. Приложение CREAM Finance несколько раз подвергалась атакам в 2021 году. Это один из самых крупнейших взломов, который привлек 130 миллионов долларов. Злоумышленники украли токены ликвидности CREAM на сумму в миллионы долларов за неизвестный период времени. Как и в случае с большинством взломов, злоумышленник использовал несколько контрактов на flash loans и манипулировал ценовыми оракулами.

  5. В мае 2021 года злоумышленник взломал платформу PancakeBunny. Ему удалось украсть около 3 миллионов долларов. Сначала он взял огромный заем в BNB на PancakeSwap. Затем провел несколько манипуляции с торговыми парами BUNNY/BNB и USDT/BNB. Продавал и покупал. После этого у него в руках оказалось огромное количество токенов BUNNY, которые он тут же сбросил, вернул BNB, погасив долг и исчез вместе с прибылью. Все эти испытания привели к шокирующему падению цены на PancakeBunny со 146 до 6,17 долларов.

Конечно разработчики децентрализованных приложений пытаются противодействовать flash атакам. Эксперты по безопасности изучают различные взломы протоколов. Все это породило два решения, которые должны помочь успешнее противостоять взломам.

  • Децентрализованные ценовые оракулы. Так как большинство атак строится на манипулирование ценой активов, то необходимо этому противодействовать. Например атаки с манипулированием цены будет проводить сложнее, если протокол будет ориентироваться не на один DEX, а на децентрализованный оракул, который агрегирует цены с нескольких DEX или из нескольких независимых источников.

  • Внедрение платформ безопасности. Сюда можно отнести аудит смарт‑контрактов, использование проверенных решений при реализации контрактов от библиотеки OpenZeppelin. Роль этой библиотеки заключается в защите смарт‑контрактов и приложений в целом.

Вывод

Flash loans являются отличным дополнение к экосистеме DeFi. Несмотря на то что в настоящее время этот инструмент часто используется в злонамеренных целях, он открывает огромный потенциал в создании децентрализованных приложений.

Flash loans — это продвинутая техника заимствования активов без необходимости вносить залог. Обычно займы используются для арбитражной торговли, которая уравновешивает стоимость активов между различными децентрализованными биржами. Чуть реже используются для замены токена в залоге, так называемый collateral swap и ликвидации займа без штрафа. Flash loans уникальны для технологии блокчейна и одновременно являются одной из самых больших угроз, о которых должны знать разработчики. Но при этом остаются мощным инструментом, который используется для стабилизации экономики в DeFi.


ссылка на оригинал статьи https://habr.com/ru/articles/829406/