Предисловие

Благодаря быстрому развитию децентрализованных финансов (DeFi) Uniswap, как ведущая децентрализованная биржа, оказалась в авангарде инноваций. В этой статье будет представлен углубленный анализ основного механизма протокола Uniswap v3 и подробное объяснение его функционального дизайна, включая ключевые функции, такие как централизованная ликвидность, множественные ставки, обмен токенами и мгновенные кредиты, а также предоставятся соответствующие точки аудита для аудиторы. (Примечание. Изображения в этой статье можно просмотреть в высоком разрешении по адресу https://www.figma.com/board/QyIpAUR93MxZ4XZZf2QjDk/uniswap-v3.)

Краткий анализ архитектуры

Протокол Uniswap v3 в основном состоит из четырех модулей:

  • PositionManager: основной интерфейс для пользователей для выполнения операций с ликвидностью, с помощью которого пользователи могут создавать пулы токенов, предоставлять/удалять ликвидность и использовать ERC721 в качестве учетных данных для поставщиков ликвидности (LP).

  • SwapRouter: доступ пользователей к обмену токенов. Пользователи могут выполнять операции обмена токенов через этот модуль.

  • Пул: отвечает за реализацию транзакций токенов, управление ликвидностью, сбор комиссий за транзакции и функции управления данными Oracle. Среди них механизм Tick делит диапазон цен на несколько тонких шкал.

  • Фабрика: используется для создания контрактов пула и управления ими.

Процесс сортировки

Создать пара токенов

Пользователи могут сделать это с помощью функции createAndInitializePoolIfNecessary. Пользователю необходимо передать token0, token1, комиссию за обработку (комиссию) и начальную цену () пары токенов. В первую очередь система проверит наличие токенов через функцию GetPool. Если она не была создана, вызывается CreatePool и используется инструкция Create2 для развертывания конфронтации транзакций. Наконец, функция инициализации используется для завершения инициализации цены, комиссии за обработку, тика, оракула и других связанных параметров.

Обеспечить ликвидность

Пользователи могут создавать новые позиции ликвидности и генерировать соответствующие NFT с помощью функции монетного двора или добавлять ликвидность к существующим позициям ликвидности NFT с помощью функции увеличения ликвидности. Сначала система проверит, выполнена ли транзакция в указанном диапазоне времени, а затем вызовет функцию addLiquidity для завершения конкретной операции. В этой функции сначала рассчитываются адрес и ликвидность пула, а затем вызывается updatePosition для обновления позиции пользователя, изменения нижнего, верхнего тика и общей накопленной комиссии за обработку. Впоследствии система добавляет ликвидность черезmodifyPosition, проверяет, соответствует ли тик условиям верхней и нижней границы, возвращает рассчитанное количество token0 и token1 (int256) и отправляет его в пул. Наконец, система обновляет соответствующую информацию о позиции на основе идентификатора токена пользователя.

Удалить ликвидность

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

менять

Пользователи могут указать количество токенов, подлежащих выплате, и минимальное количество токенов, которые, как ожидается, будут получены с помощью функции точного ввода, или указать максимальное количество токенов, подлежащих выплате, и установить количество токенов, которые, как ожидается, будут получены, с помощью функции точного вывода. Система сначала анализирует путь (путь), а затем последовательно вызывает функцию «exactInputInternal» или «exactOutputInternal» для завершения каждого шага операции подкачки.

В функции обмена система сначала блокирует разблокированное состояние, чтобы другие транзакции не мешали обновлению переменных состояния. После входа в цикл система находит цену следующей транзакции через тик и вызывает функцию CompeSwapStep для расчета обмена на каждом этапе, пока tokenIn или tokenOut не достигнет ожидания пользователя. В то же время система обновит соответствующие значения комиссий, ликвидности, тиков и цен. Если тик изменится, данные Oracle также необходимо обновить. После завершения этих операций система выплачивает пользователю tokenOut, а пользователь выплачивает tokenIn через функцию обратного вызова uniswapV3SwapCallback. Этот механизм можно рассматривать как флэш-своп. Впоследствии система проверит соответствие баланса контракта и разблокирует состояние разблокировки после подтверждения.

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

вспышка

Пользователи могут выполнять операции флэш-кредитования с помощью флэш-функций. Сначала система рассчитает комиссию за заимствование, а затем отправит токен, необходимый пользователю, на указанный адрес кредитования. Далее система вызывает обратно функцию uniswapV3FlashCallback, реализованную пользователем, и пользователь завершает операцию погашения в этой функции. Система проверит изменение баланса контракта после обратного вызова, чтобы убедиться, что оно соответствует сумме кредита пользователя, и обновит соответствующую комиссию за обработку. В дополнение к флэш-функциям пользователи также могут реализовать аналогичные функции флэш-кредитования посредством операций свопа, то есть заимствования и последующего погашения токенов в процессе транзакции.

Аудиторские точки

1. Проверьте, вызывается ли returnETH после операции свопа.

В функции точного ввода пользователю необходимо указать количество токенов для оплаты и минимальное количество токенов, которое ожидается получить. Перед вызовом uniswapV3SwapCallback система пересчитает суммы 0 и 1, чтобы гарантировать, что пользователь может точно отправить токен. Однако при обмене с помощью ETH пользователям необходимо отправить ETH вместе с транзакцией. Даже если весь ETH не будет использован во время транзакции, функция не вернет излишки автоматически. Функция strictInput возвращает только sumOut, поэтому трейдеры не могут напрямую узнать, сколько ETH на самом деле было израсходовано этой биржей.

Кроме того, любой может вызвать функцию returnETH, чтобы вывести из контракта неиспользованный ETH. Поэтому рекомендуется проверить, вызывается ли returnETH после операции обмена, чтобы пользователи не оставляли неиспользуемые ETH в протоколе, или использовать функцию MultiCall для выполнения нескольких вызовов функций за одну операцию.

2. Проверьте, реализован ли TWAP для получения цены оракула.

При использовании Uniswap в качестве источника цен может возникнуть риск манипулирования ценами, если внешний протокол напрямую обращается к Slot0 для получения sqrtPriceX96. Злоумышленники могут манипулировать состоянием пула ликвидности посредством свопов и других методов для получения выгодных цен при выполнении транзакций.

Чтобы снизить этот риск, разработчикам рекомендуется дополнительно внедрить средневзвешенную по времени цену (TWAP) для получения цен, поскольку TWAP может эффективно уменьшить влияние резких колебаний цен в краткосрочной перспективе, что затрудняет манипулирование ценами.

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

Когда другие протоколы используют Uniswap v3 для операций подкачки, разработчикам рекомендуется установить защиту от проскальзывания на основе бизнес-сценариев и позволить пользователям самостоятельно настраивать параметры для предотвращения сэндвич-атак. В этой функции свопа четвертый параметр sqrtPriceLimitX96 используется для указания минимальной или максимальной цены, по которой пользователь готов выполнить своп. Этот параметр может эффективно предотвращать резкие колебания цен в процессе транзакции, тем самым уменьшая потери пользователей из-за чрезмерного проскальзывания.

4. Рекомендуется внедрить механизм белого списка пула ликвидности.

В Uniswap v3 одна и та же пара токенов ERC20 может существовать в нескольких пулах ликвидности (Пулах) одновременно на основе разных комиссий. Как правило, несколько пулов ликвидности содержат большую часть ликвидности, в то время как другие пулы могут иметь очень небольшой общий заблокированный объем (TVL) или даже еще не созданы. Эти пулы с более низким TVL с большей вероятностью станут объектами манипулирования ценами.

Поэтому, когда стороны проекта решают использовать данные пула ликвидности, им следует избегать простого использования LP в качестве источника данных. Для обеспечения достоверности данных рекомендуется ввести механизм «белых списков» для отсеивания пулов с достаточной ликвидностью и сложностью манипулирования. Этот механизм значительно снижает риск, обеспечивая безопасность и точность справочных данных о ценах, предотвращая при этом потенциальные потери от манипулирования пулами со слишком низким TVL.

5. Проверьте, используется ли флажок в TickMath.sol, FullMath.sol и Position.sol.

Такие модули, как TickMath, FullMath и Position, используются в Uniswap v3 для выполнения сложных математических вычислений, основанных на механизме обработки переполнения в Solidity. В более ранних версиях Solidity (<0.8.0) поведение целочисленного переполнения и опустошения по умолчанию не вызывало исключений, поэтому код мог работать нормально на основе этого предположения. Однако, начиная с версии Solidity 0.8.0, переполнение и опустошение автоматически выдают исключения, что влияет на выполнение существующего кода. Чтобы гарантировать правильную работу этих модулей в Solidity 0.8.0 и выше, разработчикам необходимо вручную отключить проверку переполнения, используя непроверенные блоки кода в определенных функциях. Это восстанавливает поведение предыдущих версий и обеспечивает эффективное выполнение операций, чувствительных к переполнению.

Официальная поддержка и корректировки сделаны для Solidity 0.8.0 и выше. Подробности см. в этом обновлении (https://github.com/Uniswap/v3-core/commit/6562c52e8f75f0c10f9deaf44861847585fc8129). Это изменение гарантирует, что TickMath, FullMath и другие связанные модули будут продолжать корректно работать в новых версиях компилятора.

6. Проверьте, совпадают ли методы кодирования и декодирования пути.

В функциях Exactinput и ExactoutPut Uniswap V3 пользователям необходимо ввести параметр PATH. Этот путь должен быть закодирован и декодирован в фиксированном формате, то есть tokena-Fee-Tokenb для операций обмена токенов. Эта структура пути явно определяет два токена, участвующих в каждом переходе транзакции, и уровень комиссии между ними. Если внешний протокол выбирает другой метод декодирования пути при использовании функции обмена токенами Uniswap V3, это может привести к несоответствию формату пути, ожидаемому Uniswap. В этом случае протокол может оказаться не в состоянии правильно определить путь и, следовательно, не сможет успешно выполнить намеченную операцию обмена токенами.

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

7. Проверьте, влияет ли порядок токенов на логику проекта.

В UNISWAP token0 — это токены с более низким порядком для базовых токенов (базовый токен), а token1 — это токены с последовательностями более высокого порядка для токенов котировок. Uniswap сортирует адреса двух токенов лексикографически, чтобы гарантировать, что порядок пар токенов всегда согласован в пуле.

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

Подвести итог

Вышеуказанные основные элементы проверки основаны на текущей версии Uniswap v3 и используются аудиторами для проверки проектов, взаимодействующих с Uniswap v3. Реализация различных проектов имеет свои особенности, поэтому аудиторам необходимо иметь глубокое понимание соглашения и проводить строгие проверки, исходя из реальной ситуации. Для проектов, находящихся в разработке, команда безопасности SlowMist рекомендует разработчикам тщательно учитывать эти проверки в процессе разработки, чтобы обеспечить безопасность и надежность протокола.

Автор |

Редактор | Лиз