Маленькі хитрощі розробки контрактів, які можна навчитися з коду Uniswap
Нещодавно, коли я писав посібник з розробки децентралізованих бірж, я звернувся до коду реалізації Uniswap V3 і дізнався багато цінних моментів. Як розробник, який раніше лише розробляв прості NFT контракти, цей досвід у розробці Defi контрактів дав мені багато нових знань. Впевнений, що ці маленькі поради будуть дуже корисні новачкам, які хочуть навчитися розробці контрактів.
Давайте розглянемо ці корисні розробницькі поради, деякі з яких навіть можна вважати хитрощами.
Прогнозована адреса розгортання контракту
Зазвичай адреса, отримана при розгортанні контракту, виглядає випадковою, оскільки вона пов'язана з nonce, тому передбачити адресу контракту важко. Але в деяких випадках нам потрібно зробити висновки про адресу контракту за допомогою торгових пар та відповідної інформації, наприклад, для визначення прав на торгівлю або отримання адреси пулу тощо.
Uniswap створює контракти за допомогою CREATE2, додаючи параметр salt, що робить адресу створеного контракту передбачуваною. Логіка генерації адреси: нова адреса = hash("0xFF", адреса творця, salt, initcode).
Використання зворотних функцій
У Solidity контракти можуть викликати один одного. У деяких сценаріях корисно, коли A викликає метод B, а B у викликаному методі викликає A.
У Uniswap, коли викликається метод swap контракту UniswapV3Pool для торгівлі, він викликає swapCallback, в якому передається розрахований токен, необхідний для цієї угоди. Виклик повинен перевести токени, необхідні для угоди, в UniswapV3Pool під час зворотного виклику, а не розділяти метод swap на дві частини, щоб викликати його. Це забезпечує безпеку методу swap, гарантує повне виконання всієї логіки без необхідності ускладненого ведення записів змінних для забезпечення безпеки.
Використання виключень для передачі інформації, реалізація оцінки угоди за допомогою try catch
У деяких контрактах Uniswap метод swap UniswapV3Pool обгорнутий у try catch. Це робиться для імітації методу swap для оцінки необхідних токенів для торгівлі. Оскільки під час оцінки фактичний обмін токенів не відбувається, виникає помилка. Uniswap генерує спеціальну помилку в функції зворотного виклику транзакції, а потім перехоплює цю помилку, щоб витягти необхідну інформацію з повідомлення про помилку.
Цей метод здається трохи хитрим, але дуже практичний. Не потрібно модифікувати метод swap для оцінки торгового попиту, логіка також простіша.
Використання великих чисел для вирішення проблеми точності
У коді Uniswap є велика кількість обчислювальної логіки, наприклад, для розрахунку обміну токенів на основі поточної ціни та ліквідності. Щоб уникнути втрати точності внаслідок операцій ділення, у процесі обчислень часто використовують << FixedPoint96.RESOLUTION, тобто зсув вліво на 96 біт, що дорівнює множенню на 2^96. Після зсуву виконується операція ділення, що гарантує точність за умов, що нормальні угоди не переповнюються.
Хоча теоретично все ще може бути втрата точності, зазвичай це лише втрата найменшої одиниці, що є прийнятною.
Розрахунок прибутку за допомогою Share
У Uniswap потрібно фіксувати дохід від комісій LP (постачальників ліквідності). Очевидно, що не можна фіксувати кожному LP їхні комісії під час кожної угоди, оскільки це споживатиме велику кількість Gas.
Рішення 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 для торгівлі, він викликає swapCallback, в якому передається розрахований токен, необхідний для цієї угоди. Виклик повинен перевести токени, необхідні для угоди, в UniswapV3Pool під час зворотного виклику, а не розділяти метод swap на дві частини, щоб викликати його. Це забезпечує безпеку методу swap, гарантує повне виконання всієї логіки без необхідності ускладненого ведення записів змінних для забезпечення безпеки.
Використання виключень для передачі інформації, реалізація оцінки угоди за допомогою try catch
У деяких контрактах Uniswap метод swap UniswapV3Pool обгорнутий у try catch. Це робиться для імітації методу swap для оцінки необхідних токенів для торгівлі. Оскільки під час оцінки фактичний обмін токенів не відбувається, виникає помилка. Uniswap генерує спеціальну помилку в функції зворотного виклику транзакції, а потім перехоплює цю помилку, щоб витягти необхідну інформацію з повідомлення про помилку.
Цей метод здається трохи хитрим, але дуже практичний. Не потрібно модифікувати метод swap для оцінки торгового попиту, логіка також простіша.
Використання великих чисел для вирішення проблеми точності
У коді Uniswap є велика кількість обчислювальної логіки, наприклад, для розрахунку обміну токенів на основі поточної ціни та ліквідності. Щоб уникнути втрати точності внаслідок операцій ділення, у процесі обчислень часто використовують << FixedPoint96.RESOLUTION, тобто зсув вліво на 96 біт, що дорівнює множенню на 2^96. Після зсуву виконується операція ділення, що гарантує точність за умов, що нормальні угоди не переповнюються.
Хоча теоретично все ще може бути втрата точності, зазвичай це лише втрата найменшої одиниці, що є прийнятною.
Розрахунок прибутку за допомогою Share
У Uniswap потрібно фіксувати дохід від комісій LP (постачальників ліквідності). Очевидно, що не можна фіксувати кожному LP їхні комісії під час кожної угоди, оскільки це споживатиме велику кількість Gas.
Рішення Uniswap полягає в визначенні feeGrowthInside0LastX128 та feeGrowthInside1LastX128 у структурі Position, які фіксують комісійні збори, що належать кожній ліквідності, під час останнього вилучення комісії для кожної позиції.
Коротко кажучи, потрібно просто зафіксувати загальний комісійний збір і комісійний збір, який слід розподілити між кожною ліквідністю. Коли LP виводить комісійний збір, він розраховується на основі ліквідності, що тримається. Це схоже на те, як тримати акції компанії, під час виведення дивідендів потрібно лише знати історичний дохід на акцію компанії та прибуток під час останнього виведення.
Не всю інформацію потрібно отримувати з блокчейну
Зберігання в ланцюзі відносно дороге, і не вся інформація повинна бути в ланцюзі або отримуватися з ланцюга. Наприклад, багато інтерфейсів, які викликає фронтенд веб-сайту Uniswap, є традиційними веб-інтерфейсами Web2.
Список торгових пулів, інформація про торгові пули тощо можуть зберігатися в звичайній базі даних, деякі можуть потребувати періодичної синхронізації з блокчейном, але немає необхідності в реальному часі викликати RPC-інтерфейси, надані ланцюгом або вузлом для отримання відповідних даних.
Звичайно, ключові угоди повинні проводитися в ланцюгу.
Навчіться розподілу контрактів, використовуючи вже існуючі стандартні контракти
Проект може містити кілька фактично розгорнутого контракту. Навіть якщо фактично розгорнуто лише один контракт, ми можемо розділити контракт на кілька контрактів за допомогою успадкування для його підтримки.
Наприклад, деякі контракти в Uniswap успадковують кілька контрактів. При реалізації безпосередньо використовувався контракт @openzeppelin/contracts/token/ERC721/ERC721.sol, що дозволяє зручно керувати позиціями через NFT, а також використовувати вже існуючі стандартні контракти для підвищення ефективності розробки.
Підсумок
Самостійна розробка поглиблює розуміння більше, ніж читання статей. Спроба реалізувати спрощену версію децентралізованої біржі дозволить вам глибше зрозуміти реалізацію коду Uniswap, а також навчитися більше практичних знань з реальних проектів.