Поділ досвідом з розробки контрактів: уроки, отримані з Uniswap
Нещодавно, під час розробки проекту децентралізованої біржі, я звернувся до реалізації коду відомої DEX і дізнався багато корисних моментів. Як новачок, який тільки почав займатися розробкою Defi-контрактів, ці техніки стали для мене великим натхненням, і я впевнений, що вони також будуть корисні іншим, хто хоче навчитися розробці смарт-контрактів.
Прогнозована адреса контракту
Зазвичай адреса, отримана в результаті розгортання контракту, виглядає випадковою, оскільки вона пов'язана з nonce. Але в певних випадках нам потрібно вивести адресу контракту за допомогою інформації про транзакцію, наприклад, щоб визначити права на транзакцію або отримати адресу ліквідного пулу.
Це можна реалізувати, використовуючи метод CREATE2 для створення контракту. Конкретний спосіб полягає в додаванні параметра salt під час створення контракту:
солідність
pool = address(new UniswapV3Pool{salt: keccak256(abi.encode(token0, token1, fee))}());
Адреса контракту, що генерується таким чином, є передбачуваною і відповідає наступній логіці:
Новий адрест = hash("0xFF", адреса творця, сіль, initcode)
Розумне використання функцій зворотного виклику
У деяких сценаріях взаємні виклики між контрактами можуть бути корисними. Наприклад, метод A викликає B, а B під час виклику методу викликає A.
У певному DEX, при виклику методу swap для торгівлі, він викликає swapCallback, передаючи розраховану кількість токенів, необхідних для цієї торгівлі. Викликаюча сторона повинна в callback перенести потрібні токени в торговий пул, а не розділяти метод swap. Це забезпечує повне виконання методу swap без необхідності у складних записах змінних для забезпечення безпеки.
Використання виключень для передачі інформації
При оцінці угод нам потрібно змоделювати метод swap, але фактична заміна токенів не буде виконана, тому виникне помилка. Один DEX реалізує оцінку, викидаючи спеціальну помилку в функції зворотного виклику угоди, а потім ловить цю помилку та витягує необхідну інформацію.
Цей метод виглядає хитромудрим, але дуже практичний. Не потрібно переробляти метод обміну для оцінки попиту, логіка простіша.
Використання великих чисел для вирішення проблеми точності
У кодах, що стосуються обчислень, слід уникати втрати точності під час операцій ділення. Один DEX часто використовує "<< FixedPoint96.RESOLUTION" операцію, що еквівалентно множенню на 2^96. Після зсуву вліво, потім виконуючи ділення, можна забезпечити точність без переповнення.
Хоча теоретично все ще можуть бути втрати точності, зазвичай це лише мінімальні втрати одиниці, які можна прийняти.
Розрахунок прибутку за допомогою Share
Для розрахунку доходу від комісії для постачальника ліквідності (LP) не можна фіксувати кожну угоду, це витрачатиме багато Gas. Один DEX використовує спосіб запису загальної комісії та розподілу комісії для кожної ліквідності.
При виведенні комісії за LP, сума, яку можна вивести, розраховується на основі наявної ліквідності. Це схоже на володіння акціями компанії, при виведенні прибутку потрібно лише знати історичний прибуток на акцію та прибуток під час останнього виведення.
Розумний вибір способу отримання інформації
Зберігання на ланцюзі відносно дороге, не вся інформація повинна бути на ланцюзі або отримуватися з ланцюга. Наприклад, списки торгових пулів, інформація тощо можуть зберігатися в звичайних базах даних, з регулярною синхронізацією з ланцюга.
Деякі постачальники RPC для блокчейн пропонують розширені інтерфейси, які дозволяють швидше отримувати дані. Але ключові транзакції все ще потрібно виконувати в мережі.
Розподіл контрактів та повторне використання стандартних контрактів
Проект може містити кілька контрактів, навіть якщо фактично розгортається один контракт, його можна розділити на кілька контрактів для обслуговування шляхом успадкування.
Контракт управління позиціями NFT певної DEX успадкував кілька контрактів:
солідність
контракт NonfungiblePositionManager є
INonfungiblePositionManager,
Мультидзвінок,
ПериферіяНезмінний Стан,
PoolInitializer,
УправлінняЛіквідністю,
Переферійна валідація,
Самостійний дозвіл,
Дозвіл ERC721
{...}
Водночас, він також використовує стандартний контракт ERC721 від OpenZeppelin, що полегшує управління позиціями та підвищує ефективність розробки.
Підсумок
Розробка спрощеної версії децентралізованої біржі дозволить вам глибше зрозуміти реалізацію коду зрілих проектів, отримати більше практичних знань. Сподіваюся, ці маленькі поради надихнуть вас, бажаю успіху в розробці!
Ця сторінка може містити контент третіх осіб, який надається виключно в інформаційних цілях (не в якості запевнень/гарантій) і не повинен розглядатися як схвалення його поглядів компанією Gate, а також як фінансова або професійна консультація. Див. Застереження для отримання детальної інформації.
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.
У певному DEX, при виклику методу swap для торгівлі, він викликає swapCallback, передаючи розраховану кількість токенів, необхідних для цієї торгівлі. Викликаюча сторона повинна в callback перенести потрібні токени в торговий пул, а не розділяти метод swap. Це забезпечує повне виконання методу swap без необхідності у складних записах змінних для забезпечення безпеки.
Використання виключень для передачі інформації
При оцінці угод нам потрібно змоделювати метод swap, але фактична заміна токенів не буде виконана, тому виникне помилка. Один DEX реалізує оцінку, викидаючи спеціальну помилку в функції зворотного виклику угоди, а потім ловить цю помилку та витягує необхідну інформацію.
Цей метод виглядає хитромудрим, але дуже практичний. Не потрібно переробляти метод обміну для оцінки попиту, логіка простіша.
Використання великих чисел для вирішення проблеми точності
У кодах, що стосуються обчислень, слід уникати втрати точності під час операцій ділення. Один DEX часто використовує "<< FixedPoint96.RESOLUTION" операцію, що еквівалентно множенню на 2^96. Після зсуву вліво, потім виконуючи ділення, можна забезпечити точність без переповнення.
солідність uint256 чисельник1 = uint256(liquidity) << FixedPoint96.RESOLUTION; чисельник uint256 = sqrtRatioBX96 - sqrtRatioAX96; кількість0 = чисельник1 * чисельник2 / (sqrtRatioBX96 * sqrtRatioAX96);
Хоча теоретично все ще можуть бути втрати точності, зазвичай це лише мінімальні втрати одиниці, які можна прийняти.
Розрахунок прибутку за допомогою Share
Для розрахунку доходу від комісії для постачальника ліквідності (LP) не можна фіксувати кожну угоду, це витрачатиме багато Gas. Один DEX використовує спосіб запису загальної комісії та розподілу комісії для кожної ліквідності.
При виведенні комісії за LP, сума, яку можна вивести, розраховується на основі наявної ліквідності. Це схоже на володіння акціями компанії, при виведенні прибутку потрібно лише знати історичний прибуток на акцію та прибуток під час останнього виведення.
Розумний вибір способу отримання інформації
Зберігання на ланцюзі відносно дороге, не вся інформація повинна бути на ланцюзі або отримуватися з ланцюга. Наприклад, списки торгових пулів, інформація тощо можуть зберігатися в звичайних базах даних, з регулярною синхронізацією з ланцюга.
Деякі постачальники RPC для блокчейн пропонують розширені інтерфейси, які дозволяють швидше отримувати дані. Але ключові транзакції все ще потрібно виконувати в мережі.
Розподіл контрактів та повторне використання стандартних контрактів
Проект може містити кілька контрактів, навіть якщо фактично розгортається один контракт, його можна розділити на кілька контрактів для обслуговування шляхом успадкування.
Контракт управління позиціями NFT певної DEX успадкував кілька контрактів:
солідність контракт NonfungiblePositionManager є INonfungiblePositionManager, Мультидзвінок, ПериферіяНезмінний Стан, PoolInitializer, УправлінняЛіквідністю, Переферійна валідація, Самостійний дозвіл, Дозвіл ERC721 {...}
Водночас, він також використовує стандартний контракт ERC721 від OpenZeppelin, що полегшує управління позиціями та підвищує ефективність розробки.
Підсумок
Розробка спрощеної версії децентралізованої біржі дозволить вам глибше зрозуміти реалізацію коду зрілих проектів, отримати більше практичних знань. Сподіваюся, ці маленькі поради надихнуть вас, бажаю успіху в розробці!