Небольшие советы по разработке контрактов, которые я узнал из кода Uniswap
Недавно, когда я писал руководство по разработке децентрализованных бирж, я обратился к коду реализации Uniswap V3 и узнал много ценных моментов. Будучи разработчиком, который ранее разрабатывал только простые NFT контракты, этот опыт разработки Defi контрактов принес мне много новых знаний. Уверен, что эти маленькие советы будут очень полезны новичкам, желающим изучить разработку контрактов.
Давайте теперь вместе рассмотрим эти полезные советы по разработке, некоторые из которых можно даже назвать хитростями.
Предсказуемый адрес развертывания контракта
Обычно адрес, получаемый при развертывании контракта, выглядит как случайный, так как он связан с nonce, поэтому адрес контракта трудно предсказать. Однако в некоторых случаях нам нужно сделать вывод о адресе контракта на основе пары транзакций и связанной информации, например, для определения прав на транзакцию или получения адреса пула.
Uniswap создает контракт с помощью метода CREATE2, добавляя параметр salt, что делает адрес созданного контракта предсказуемым. Логика генерации адреса такова: новый адрес = hash("0xFF", адрес создателя, salt, initcode).
Умелое использование колбэк-функций
В Solidity контракты могут вызывать друг друга. В некоторых сценариях полезно, чтобы A вызывал метод B, а B вызывал A в своем методе.
В Uniswap, при вызове метода swap контракта UniswapV3Pool для выполнения сделки, будет вызван callback swapCallback, который передаст рассчитанный необходимый для сделки токен. Вызывающая сторона должна передать необходимый токен в UniswapV3Pool в callback, а не разбивать метод swap на две части, чтобы вызыватель вызывал их самостоятельно. Это обеспечивает безопасность метода swap, гарантируя, что вся логика будет выполнена полностью, без необходимости в сложной записи переменных для обеспечения безопасности.
Используйте исключения для передачи информации, реализуйте оценку сделки с помощью try catch
В некоторых контрактах Uniswap метод swap UniswapV3Pool обернут в try catch. Это сделано для того, чтобы смоделировать метод swap с целью оценки необходимых токенов для сделки. Поскольку при оценке фактический обмен токенов не происходит, возникает ошибка. Uniswap генерирует специальную ошибку в функции обратного вызова транзакции, а затем перехватывает эту ошибку, извлекая необходимую информацию из сообщения об ошибке.
Этот метод кажется немного хитрым, но очень практичен. Не нужно модифицировать метод swap для оценки торговых потребностей, логика также проще.
Решение проблем с точностью с помощью больших чисел
В коде Uniswap содержится множество вычислительной логики, такой как расчет токенов для обмена на основе текущей цены и ликвидности. Чтобы избежать потерь точности при делении, в процессе вычислений часто используется операция << FixedPoint96.RESOLUTION, то есть сдвиг влево на 96 бит, что эквивалентно умножению на 2^96. После сдвига выполняется операция деления, что гарантирует точность при нормальных сделках без переполнения.
Хотя теоретически все равно будет потеря точности, обычно это просто потеря минимальной единицы, что приемлемо.
Расчет доходности с помощью Share
В Uniswap необходимо учитывать доходы от комиссий для LP (поставщиков ликвидности). Очевидно, что нецелесообразно фиксировать комиссии для каждого LP при каждой сделке, так как это потребует значительных затрат газа.
Решение Uniswap заключается в определении feeGrowthInside0LastX128 и feeGrowthInside1LastX128 в структуре Position, которые фиксируют размер комиссии, причитающейся каждой ликвидности, при последнем извлечении комиссии для каждой позиции.
Короче говоря, нужно просто записать общую комиссию и комиссию, которую должен получить каждый поставщик ликвидности. Когда LP извлекает комиссию, она рассчитывается на основе ликвидности, которой он владеет. Это похоже на владение акциями компании: чтобы получить дивиденды, нужно знать историческую прибыль на акцию и доходы на момент последнего извлечения.
Не вся информация должна быть получена из цепочки
Хранение на блокчейне относительно дорого, и не вся информация должна быть записана в блокчейн или извлечена из него. Например, многие интерфейсы, используемые фронтенд-сайтом Uniswap, являются традиционными Web2 интерфейсами.
Список торговых пулов, информация о торговых пулах и т. д. могут храниться в обычной базе данных, некоторые из них могут потребовать периодической синхронизации с блокчейном, но для получения соответствующих данных не требуется в реальном времени вызывать RPC-интерфейсы, предоставляемые цепочкой или узлом.
Конечно, ключевые сделки должны проводиться в цепочке.
Научитесь разделять контракты, используя существующие стандартные контракты
Проект может содержать несколько фактически развернутых контрактов. Даже если фактически развернут только один контракт, мы можем разделить контракт на несколько контрактов с помощью наследования для удобства поддержки.
Например, некоторые контракты в Uniswap наследуют несколько контрактов. При реализации непосредственно используется контракт @openzeppelin/contracts/token/ERC721/ERC721.sol, что позволяет удобно управлять позициями через NFT и использовать существующие стандартные контракты для повышения эффективности разработки.
Резюме
Самостоятельная разработка углубляет понимание больше, чем чтение статей. Попытка реализовать упрощенную версию децентрализованной биржи поможет вам глубже понять реализацию кода Uniswap и узнать больше о практических аспектах проектов.
This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
7 Лайков
Награда
7
4
Поделиться
комментарий
0/400
ForumLurker
· 2ч назад
про можете ли вы подробнее рассказать об этой части навыков
Посмотреть ОригиналОтветить0
BearMarketGardener
· 23ч назад
Маленький новичок, начни с приготовления эликсиров.
Посмотреть ОригиналОтветить0
MissedAirdropAgain
· 23ч назад
Снова будет открытие? Только что закончил с NFT, еще недостаточно.
Посмотреть ОригиналОтветить0
Web3Educator
· 23ч назад
ок, студенты, позвольте мне быстро это объяснить...
Анализ кода Uniswap V3: 7 практических советов по разработке контрактов
Небольшие советы по разработке контрактов, которые я узнал из кода Uniswap
Недавно, когда я писал руководство по разработке децентрализованных бирж, я обратился к коду реализации Uniswap V3 и узнал много ценных моментов. Будучи разработчиком, который ранее разрабатывал только простые NFT контракты, этот опыт разработки Defi контрактов принес мне много новых знаний. Уверен, что эти маленькие советы будут очень полезны новичкам, желающим изучить разработку контрактов.
Давайте теперь вместе рассмотрим эти полезные советы по разработке, некоторые из которых можно даже назвать хитростями.
Предсказуемый адрес развертывания контракта
Обычно адрес, получаемый при развертывании контракта, выглядит как случайный, так как он связан с nonce, поэтому адрес контракта трудно предсказать. Однако в некоторых случаях нам нужно сделать вывод о адресе контракта на основе пары транзакций и связанной информации, например, для определения прав на транзакцию или получения адреса пула.
Uniswap создает контракт с помощью метода CREATE2, добавляя параметр salt, что делает адрес созданного контракта предсказуемым. Логика генерации адреса такова: новый адрес = hash("0xFF", адрес создателя, salt, initcode).
Умелое использование колбэк-функций
В Solidity контракты могут вызывать друг друга. В некоторых сценариях полезно, чтобы A вызывал метод B, а B вызывал A в своем методе.
В Uniswap, при вызове метода swap контракта UniswapV3Pool для выполнения сделки, будет вызван callback swapCallback, который передаст рассчитанный необходимый для сделки токен. Вызывающая сторона должна передать необходимый токен в UniswapV3Pool в callback, а не разбивать метод swap на две части, чтобы вызыватель вызывал их самостоятельно. Это обеспечивает безопасность метода swap, гарантируя, что вся логика будет выполнена полностью, без необходимости в сложной записи переменных для обеспечения безопасности.
Используйте исключения для передачи информации, реализуйте оценку сделки с помощью try catch
В некоторых контрактах Uniswap метод swap UniswapV3Pool обернут в try catch. Это сделано для того, чтобы смоделировать метод swap с целью оценки необходимых токенов для сделки. Поскольку при оценке фактический обмен токенов не происходит, возникает ошибка. Uniswap генерирует специальную ошибку в функции обратного вызова транзакции, а затем перехватывает эту ошибку, извлекая необходимую информацию из сообщения об ошибке.
Этот метод кажется немного хитрым, но очень практичен. Не нужно модифицировать метод swap для оценки торговых потребностей, логика также проще.
Решение проблем с точностью с помощью больших чисел
В коде Uniswap содержится множество вычислительной логики, такой как расчет токенов для обмена на основе текущей цены и ликвидности. Чтобы избежать потерь точности при делении, в процессе вычислений часто используется операция << FixedPoint96.RESOLUTION, то есть сдвиг влево на 96 бит, что эквивалентно умножению на 2^96. После сдвига выполняется операция деления, что гарантирует точность при нормальных сделках без переполнения.
Хотя теоретически все равно будет потеря точности, обычно это просто потеря минимальной единицы, что приемлемо.
Расчет доходности с помощью Share
В Uniswap необходимо учитывать доходы от комиссий для LP (поставщиков ликвидности). Очевидно, что нецелесообразно фиксировать комиссии для каждого LP при каждой сделке, так как это потребует значительных затрат газа.
Решение Uniswap заключается в определении feeGrowthInside0LastX128 и feeGrowthInside1LastX128 в структуре Position, которые фиксируют размер комиссии, причитающейся каждой ликвидности, при последнем извлечении комиссии для каждой позиции.
Короче говоря, нужно просто записать общую комиссию и комиссию, которую должен получить каждый поставщик ликвидности. Когда LP извлекает комиссию, она рассчитывается на основе ликвидности, которой он владеет. Это похоже на владение акциями компании: чтобы получить дивиденды, нужно знать историческую прибыль на акцию и доходы на момент последнего извлечения.
Не вся информация должна быть получена из цепочки
Хранение на блокчейне относительно дорого, и не вся информация должна быть записана в блокчейн или извлечена из него. Например, многие интерфейсы, используемые фронтенд-сайтом Uniswap, являются традиционными Web2 интерфейсами.
Список торговых пулов, информация о торговых пулах и т. д. могут храниться в обычной базе данных, некоторые из них могут потребовать периодической синхронизации с блокчейном, но для получения соответствующих данных не требуется в реальном времени вызывать RPC-интерфейсы, предоставляемые цепочкой или узлом.
Конечно, ключевые сделки должны проводиться в цепочке.
Научитесь разделять контракты, используя существующие стандартные контракты
Проект может содержать несколько фактически развернутых контрактов. Даже если фактически развернут только один контракт, мы можем разделить контракт на несколько контрактов с помощью наследования для удобства поддержки.
Например, некоторые контракты в Uniswap наследуют несколько контрактов. При реализации непосредственно используется контракт @openzeppelin/contracts/token/ERC721/ERC721.sol, что позволяет удобно управлять позициями через NFT и использовать существующие стандартные контракты для повышения эффективности разработки.
Резюме
Самостоятельная разработка углубляет понимание больше, чем чтение статей. Попытка реализовать упрощенную версию децентрализованной биржи поможет вам глубже понять реализацию кода Uniswap и узнать больше о практических аспектах проектов.