Советы по разработке контрактов: опыт, полученный из Uniswap
Недавно, разрабатывая проект децентрализованной биржи, я обратился к коду реализации известного DEX и узнал много полезных знаний. Как новичок в разработке Defi-контрактов, эти приемы были для меня вдохновляющими, и я уверен, что они также помогут другим, кто хочет изучить разработку смарт-контрактов.
Предсказуемый адрес контракта
Обычно адрес, полученный при развертывании контракта, кажется случайным, поскольку он связан с nonce. Но в некоторых случаях нам нужно вывести адрес контракта через информацию о сделках, например, чтобы определить права на транзакцию или получить адрес пула ликвидности.
Это можно реализовать, создав контракт с использованием метода CREATE2. Конкретный способ заключается в добавлении параметра salt при создании контракта:
солидность
pool = address(new UniswapV3Pool{salt: keccak256(abi.encode(token0, token1, fee))}());
Сгенерированный таким образом адрес контракта предсказуем, следуя следующей логике:
Новый адрес = hash("0xFF", адрес создателя, соль, initcode)
Разумное использование функций обратного вызова
В некоторых сценариях взаимные вызовы между контрактами могут быть полезными. Например, метод A вызывает B, а B в вызываемом методе вызывает A.
При вызове метода swap в某DEX, он будет вызывать swapCallback, передавая рассчитанный на этот раз необходимый токен для сделки. Вызывающая сторона должна в коллбэке перевести необходимый токен в пул ликвидности, а не разбивать метод swap на части. Это гарантирует полное выполнение метода swap без необходимости сложной записи переменных для обеспечения безопасности.
Использование аномалий для передачи информации
При оценке сделки нам необходимо смоделировать метод свопа, но мы не будем фактически обменивать токены, поэтому возникнет ошибка. Некоторые DEX реализуют оценку, выбрасывая специальную ошибку в функции обратного вызова сделки, а затем перехватывая эту ошибку и извлекая необходимую информацию.
Этот метод кажется хитрым, но он очень практичен. Не нужно модифицировать метод свопа для оценки спроса, логика проще.
Использование больших чисел для решения проблем с точностью
В коде, связанном с вычислениями, необходимо избегать потери точности при операциях деления. Некоторые DEX часто используют операцию "<< FixedPoint96.RESOLUTION", что эквивалентно умножению на 2^96. После сдвига влево, выполнение деления может гарантировать точность без переполнения.
Хотя теоретически все еще может быть потеря точности, но обычно это лишь минимальная потеря единиц, что приемлемо.
Расчет доходов с использованием метода Share
Для расчета доходов от комиссий поставщиков ликвидности (LP) нельзя записывать каждую сделку, так как это потребует большого количества газа. Один DEX использует метод записи общей комиссии и распределения комиссии для каждой ликвидности.
При выводе комиссии за LP, сумма, которую можно вывести, рассчитывается на основе удерживаемой ликвидности. Это похоже на владение акциями компании, при выводе дохода нужно знать историческую доходность на акцию и доходность при последнем выводе.
Рациональный выбор способа получения информации
Хранение на блокчейне относительно дорого, не вся информация должна быть записана в блокчейне или получена из него. Например, списки пулов транзакций, информация и т.д. могут храниться в обычной базе данных и периодически синхронизироваться с блокчейном.
Некоторые поставщики RPC для блокчейна предлагают расширенные интерфейсы, которые позволяют быстрее получать данные. Однако ключевые транзакции все равно должны выполняться в сети.
Разделение контрактов и повторное использование стандартных контрактов
Проект может содержать несколько контрактов, даже если фактически развернут только один контракт, его можно разделить на несколько контрактов для поддержки через наследование.
Контракт управления местоположением NFT на одном DEX унаследовал несколько контрактов:
солидность
контракт NonfungiblePositionManager является
INonfungiblePositionManager,
Мультиколл,
PeripheryImmutableState,
Инициализатор пула,
Управление ликвидностью,
Периферийная валидация,
SelfPermit,
ERC721Разрешение
{...}
Кроме того, он также использует стандартный контракт ERC721 от OpenZeppelin, что упрощает управление позициями и повышает эффективность разработки.
Резюме
Создайте простую версию децентрализованной биржи, чтобы глубже понять реализацию кода зрелых проектов и узнать больше практических моментов. Надеюсь, эти небольшие советы вдохновят вас, желаю удачи в разработке!
На этой странице может содержаться сторонний контент, который предоставляется исключительно в информационных целях (не в качестве заявлений/гарантий) и не должен рассматриваться как поддержка взглядов компании Gate или как финансовый или профессиональный совет. Подробности смотрите в разделе «Отказ от ответственности» .
9 Лайков
Награда
9
6
Поделиться
комментарий
0/400
NFTArchaeologis
· 14ч назад
Слепое копирование также является способом обучения
Посмотреть ОригиналОтветить0
OnlyOnMainnet
· 08-05 15:56
Не забудьте про практическое использование Тестовая сеть.
7 практических советов по разработке контрактов на основных DEX
Советы по разработке контрактов: опыт, полученный из Uniswap
Недавно, разрабатывая проект децентрализованной биржи, я обратился к коду реализации известного DEX и узнал много полезных знаний. Как новичок в разработке Defi-контрактов, эти приемы были для меня вдохновляющими, и я уверен, что они также помогут другим, кто хочет изучить разработку смарт-контрактов.
Предсказуемый адрес контракта
Обычно адрес, полученный при развертывании контракта, кажется случайным, поскольку он связан с nonce. Но в некоторых случаях нам нужно вывести адрес контракта через информацию о сделках, например, чтобы определить права на транзакцию или получить адрес пула ликвидности.
Это можно реализовать, создав контракт с использованием метода CREATE2. Конкретный способ заключается в добавлении параметра salt при создании контракта:
солидность pool = address(new UniswapV3Pool{salt: keccak256(abi.encode(token0, token1, fee))}());
Сгенерированный таким образом адрес контракта предсказуем, следуя следующей логике:
Новый адрес = hash("0xFF", адрес создателя, соль, initcode)
Разумное использование функций обратного вызова
В некоторых сценариях взаимные вызовы между контрактами могут быть полезными. Например, метод A вызывает B, а B в вызываемом методе вызывает A.
При вызове метода swap в某DEX, он будет вызывать swapCallback, передавая рассчитанный на этот раз необходимый токен для сделки. Вызывающая сторона должна в коллбэке перевести необходимый токен в пул ликвидности, а не разбивать метод swap на части. Это гарантирует полное выполнение метода swap без необходимости сложной записи переменных для обеспечения безопасности.
Использование аномалий для передачи информации
При оценке сделки нам необходимо смоделировать метод свопа, но мы не будем фактически обменивать токены, поэтому возникнет ошибка. Некоторые DEX реализуют оценку, выбрасывая специальную ошибку в функции обратного вызова сделки, а затем перехватывая эту ошибку и извлекая необходимую информацию.
Этот метод кажется хитрым, но он очень практичен. Не нужно модифицировать метод свопа для оценки спроса, логика проще.
Использование больших чисел для решения проблем с точностью
В коде, связанном с вычислениями, необходимо избегать потери точности при операциях деления. Некоторые DEX часто используют операцию "<< FixedPoint96.RESOLUTION", что эквивалентно умножению на 2^96. После сдвига влево, выполнение деления может гарантировать точность без переполнения.
солидность uint256 numerator1 = uint256(liquidity) << FixedPoint96.RESOLUTION; uint256 числитель2 = sqrtRatioBX96 - sqrtRatioAX96; amount0 = числитель1 * числитель2 / (sqrtRatioBX96 * sqrtRatioAX96);
Хотя теоретически все еще может быть потеря точности, но обычно это лишь минимальная потеря единиц, что приемлемо.
Расчет доходов с использованием метода Share
Для расчета доходов от комиссий поставщиков ликвидности (LP) нельзя записывать каждую сделку, так как это потребует большого количества газа. Один DEX использует метод записи общей комиссии и распределения комиссии для каждой ликвидности.
При выводе комиссии за LP, сумма, которую можно вывести, рассчитывается на основе удерживаемой ликвидности. Это похоже на владение акциями компании, при выводе дохода нужно знать историческую доходность на акцию и доходность при последнем выводе.
Рациональный выбор способа получения информации
Хранение на блокчейне относительно дорого, не вся информация должна быть записана в блокчейне или получена из него. Например, списки пулов транзакций, информация и т.д. могут храниться в обычной базе данных и периодически синхронизироваться с блокчейном.
Некоторые поставщики RPC для блокчейна предлагают расширенные интерфейсы, которые позволяют быстрее получать данные. Однако ключевые транзакции все равно должны выполняться в сети.
Разделение контрактов и повторное использование стандартных контрактов
Проект может содержать несколько контрактов, даже если фактически развернут только один контракт, его можно разделить на несколько контрактов для поддержки через наследование.
Контракт управления местоположением NFT на одном DEX унаследовал несколько контрактов:
солидность контракт NonfungiblePositionManager является INonfungiblePositionManager, Мультиколл, PeripheryImmutableState, Инициализатор пула, Управление ликвидностью, Периферийная валидация, SelfPermit, ERC721Разрешение {...}
Кроме того, он также использует стандартный контракт ERC721 от OpenZeppelin, что упрощает управление позициями и повышает эффективность разработки.
Резюме
Создайте простую версию децентрализованной биржи, чтобы глубже понять реализацию кода зрелых проектов и узнать больше практических моментов. Надеюсь, эти небольшие советы вдохновят вас, желаю удачи в разработке!