Советы по разработке контрактов: опыт, полученный из кода Uniswap
Недавно, когда я писал руководство по децентрализованной бирже, я ссылался на реализацию Uniswap V3 и узнал много интересных моментов. Как новичку, только начинающему работать с Defi смарт-контрактами, эти техники были для меня очень вдохновляющими, и я верю, что они также будут полезны другим, кто хочет научиться разработке смарт-контрактов.
Предсказуемый адрес контракта
Обычно адреса развернутых контрактов выглядят случайными, поскольку они связаны с nonce. Но в некоторых случаях нам нужно вывести адрес контракта через информацию о торговых парах, например, чтобы определить разрешения на транзакции или получить адрес пула.
Uniswap создал контракт, используя CREATE2, добавив параметр salt. Таким образом, адрес контракта, который генерируется, предсказуем и следует логике "новый адрес = hash('0xFF', адрес создателя, salt, initcode)".
Умелое использование колбек-функций
В Solidity контракты могут вызывать друг друга. Иногда контракт A вызывает метод контракта B, а затем B вызывает метод A, что бывает полезно в некоторых сценариях.
Например, в процессе торговли Uniswap, когда вызывается метод swap контракта UniswapV3Pool, он вызывает swapCallback, передавая фактическое количество необходимых токенов. Вызывающая сторона должна передать необходимые токены в колбэке, что обеспечивает целостность и безопасность всей торговой логики.
Передача информации с помощью исключений, реализация оценки сделки с помощью try catch
В контракте Quoter Uniswap используется конструкция try catch для выполнения метода swap в UniswapV3Pool. Это сделано для имитации необходимого токена для оценки сделки, но при оценке токены не будут фактически обмениваться, поэтому возникнет ошибка.
Uniswap выбрасывает специальную ошибку в функции обратного вызова транзакции, а затем перехватывает эту ошибку и анализирует информацию. Хотя этот метод может показаться хитрым, он очень практичен, так как не требует специальной модификации метода swap для оценки спроса.
Проблема точности обработки больших чисел
В коде Uniswap задействовано множество вычислений, например, для расчета количества токенов для обмена на основе текущей цены и ликвидности. Чтобы избежать потери точности при делении, в процессе вычислений часто используется операция "<< FixedPoint96.RESOLUTION", что эквивалентно умножению на 2^96.
Этот метод гарантирует, что нормальная торговля не будет превышена (обычно вычисляется с помощью uint256), а также обеспечивает точность. Хотя теоретически все еще может быть минимальная потеря точности, это уже приемлемо.
Расчет дохода с помощью Share
В Uniswap необходимо учитывать комиссионные доходы поставщиков ликвидности (LP). Чтобы избежать записи комиссионных для каждого LP при каждой сделке (что требует больших затрат на газ), Uniswap использует умный метод.
В структуре Position определены feeGrowthInside0LastX128 и feeGrowthInside1LastX128, которые фиксируют, какую комиссию на каждую единицу ликвидности должен был получить каждый позиционер при последнем выводе комиссии. Таким образом, нужно лишь зафиксировать общую комиссию и долю каждой единицы ликвидности, а LP при выводе рассчитывает доступную к выводу комиссию в зависимости от удерживаемой ликвидности.
Баланс получения информации на блокчейне и вне его
Хранение на блокчейне относительно дорого, и не вся информация должна быть размещена в блокчейне или извлекаться из него. Например, многие интерфейсы, используемые фронтендом Uniswap, являются традиционными интерфейсами Web2.
Список пулов ликвидности, информация о пулах ликвидности и т.д. могут храниться в обычной базе данных, с периодической синхронизацией с блокчейном. Нет необходимости в реальном времени вызывать RPC интерфейсы цепи или узлов для получения соответствующих данных.
Некоторые поставщики блокчейн RPC предлагают расширенные интерфейсы, которые позволяют быстрее и дешевле получать данные. Эти интерфейсы обычно повышают производительность и эффективность за счет кэширования.
Разделение контрактов и использование стандартных контрактов
Проект может включать несколько фактически развернутых контрактов. Даже если развернут только один контракт, код можно поддерживать, разделив его на несколько контрактов через наследование.
Например, контракт NonfungiblePositionManager Uniswap наследует несколько контрактов. Контракт ERC721Permit напрямую использует стандартный контракт ERC721 от OpenZeppelin, что упрощает управление позициями с помощью NFT и повышает эффективность разработки.
Заключение
Практика – лучший способ обучения. Попробовав реализовать упрощенную версию децентрализованной биржи, можно глубже понять реализацию кода Uniswap и узнать больше о знаниях, применяемых в реальных проектах. Надеюсь, этот опыт поможет тем, кто стремится к разработке проектов в области Web3 и DeFi.
На этой странице может содержаться сторонний контент, который предоставляется исключительно в информационных целях (не в качестве заявлений/гарантий) и не должен рассматриваться как поддержка взглядов компании Gate или как финансовый или профессиональный совет. Подробности смотрите в разделе «Отказ от ответственности» .
7 Лайков
Награда
7
6
Поделиться
комментарий
0/400
StableNomad
· 17ч назад
статистически говоря, uniswap все еще имеет самый чистый код...просто говорю
Посмотреть ОригиналОтветить0
StablecoinAnxiety
· 17ч назад
Адрес可预测这个太关键了!
Посмотреть ОригиналОтветить0
PumpStrategist
· 17ч назад
Цыц, DEX тоже играет с Машиной Oracle, возможности для больших вложений снова увеличились.
Посмотреть ОригиналОтветить0
ZkProofPudding
· 17ч назад
про договоры играются отлично
Посмотреть ОригиналОтветить0
ILCollector
· 17ч назад
Не учись у Uni, мошенничество — это их специализация.
7 основных советов по разработке контрактов Uniswap: от предсказуемых адресов до баланса в блокчейне и вне блокчейна
Советы по разработке контрактов: опыт, полученный из кода Uniswap
Недавно, когда я писал руководство по децентрализованной бирже, я ссылался на реализацию Uniswap V3 и узнал много интересных моментов. Как новичку, только начинающему работать с Defi смарт-контрактами, эти техники были для меня очень вдохновляющими, и я верю, что они также будут полезны другим, кто хочет научиться разработке смарт-контрактов.
Предсказуемый адрес контракта
Обычно адреса развернутых контрактов выглядят случайными, поскольку они связаны с nonce. Но в некоторых случаях нам нужно вывести адрес контракта через информацию о торговых парах, например, чтобы определить разрешения на транзакции или получить адрес пула.
Uniswap создал контракт, используя CREATE2, добавив параметр salt. Таким образом, адрес контракта, который генерируется, предсказуем и следует логике "новый адрес = hash('0xFF', адрес создателя, salt, initcode)".
Умелое использование колбек-функций
В Solidity контракты могут вызывать друг друга. Иногда контракт A вызывает метод контракта B, а затем B вызывает метод A, что бывает полезно в некоторых сценариях.
Например, в процессе торговли Uniswap, когда вызывается метод swap контракта UniswapV3Pool, он вызывает swapCallback, передавая фактическое количество необходимых токенов. Вызывающая сторона должна передать необходимые токены в колбэке, что обеспечивает целостность и безопасность всей торговой логики.
Передача информации с помощью исключений, реализация оценки сделки с помощью try catch
В контракте Quoter Uniswap используется конструкция try catch для выполнения метода swap в UniswapV3Pool. Это сделано для имитации необходимого токена для оценки сделки, но при оценке токены не будут фактически обмениваться, поэтому возникнет ошибка.
Uniswap выбрасывает специальную ошибку в функции обратного вызова транзакции, а затем перехватывает эту ошибку и анализирует информацию. Хотя этот метод может показаться хитрым, он очень практичен, так как не требует специальной модификации метода swap для оценки спроса.
Проблема точности обработки больших чисел
В коде Uniswap задействовано множество вычислений, например, для расчета количества токенов для обмена на основе текущей цены и ликвидности. Чтобы избежать потери точности при делении, в процессе вычислений часто используется операция "<< FixedPoint96.RESOLUTION", что эквивалентно умножению на 2^96.
Этот метод гарантирует, что нормальная торговля не будет превышена (обычно вычисляется с помощью uint256), а также обеспечивает точность. Хотя теоретически все еще может быть минимальная потеря точности, это уже приемлемо.
Расчет дохода с помощью Share
В Uniswap необходимо учитывать комиссионные доходы поставщиков ликвидности (LP). Чтобы избежать записи комиссионных для каждого LP при каждой сделке (что требует больших затрат на газ), Uniswap использует умный метод.
В структуре Position определены feeGrowthInside0LastX128 и feeGrowthInside1LastX128, которые фиксируют, какую комиссию на каждую единицу ликвидности должен был получить каждый позиционер при последнем выводе комиссии. Таким образом, нужно лишь зафиксировать общую комиссию и долю каждой единицы ликвидности, а LP при выводе рассчитывает доступную к выводу комиссию в зависимости от удерживаемой ликвидности.
Баланс получения информации на блокчейне и вне его
Хранение на блокчейне относительно дорого, и не вся информация должна быть размещена в блокчейне или извлекаться из него. Например, многие интерфейсы, используемые фронтендом Uniswap, являются традиционными интерфейсами Web2.
Список пулов ликвидности, информация о пулах ликвидности и т.д. могут храниться в обычной базе данных, с периодической синхронизацией с блокчейном. Нет необходимости в реальном времени вызывать RPC интерфейсы цепи или узлов для получения соответствующих данных.
Некоторые поставщики блокчейн RPC предлагают расширенные интерфейсы, которые позволяют быстрее и дешевле получать данные. Эти интерфейсы обычно повышают производительность и эффективность за счет кэширования.
Разделение контрактов и использование стандартных контрактов
Проект может включать несколько фактически развернутых контрактов. Даже если развернут только один контракт, код можно поддерживать, разделив его на несколько контрактов через наследование.
Например, контракт NonfungiblePositionManager Uniswap наследует несколько контрактов. Контракт ERC721Permit напрямую использует стандартный контракт ERC721 от OpenZeppelin, что упрощает управление позициями с помощью NFT и повышает эффективность разработки.
Заключение
Практика – лучший способ обучения. Попробовав реализовать упрощенную версию децентрализованной биржи, можно глубже понять реализацию кода Uniswap и узнать больше о знаниях, применяемых в реальных проектах. Надеюсь, этот опыт поможет тем, кто стремится к разработке проектов в области Web3 и DeFi.