Поділитися порадами з розробки контрактів: навчання з вихідного коду Uniswap
Нещодавно, коли я писав посібник з розробки децентралізованої біржі, я звертався до реалізації коду Uniswap V3 і дізнався багато цінних моментів. Як розробник, який вперше намагається розробити Defi-контракти, ці поради будуть дуже корисні для новачків, які хочуть навчитися розробці контрактів.
Далі я поділюся деякими маленькими хитрощами, деякі з яких навіть можна назвати дивними трюками.
Прогнозовані адреси розгортання контрактів
Зазвичай адреса, отримана при розгортанні контракту, виглядає випадковою, оскільки пов'язана з nonce, тому передбачити адресу контракту важко. Але в деяких випадках нам потрібно мати можливість вивести адресу контракту на основі торгових пар та відповідної інформації. Це дуже корисно при визначенні прав доступу до транзакцій або отриманні адреси пулу.
Uniswap створює контракт, використовуючи CREATE2 з додаванням параметра salt, що робить адресу створеного контракту передбачуваною. Логіка генерації адреси: нова адреса = hash("0xFF", адреса творця, salt, initcode).
Розумне використання функцій зворотного виклику
У деяких випадках контракт A викликає методи контракту B, а B у викликаному методі викликає зворотний виклик A, цей спосіб дуже практичний.
Наприклад, під час торгівлі за допомогою методу swap контракту UniswapV3Pool, викликається зворотний виклик swapCallback, в якому передається обчислений токен, необхідний для цієї угоди. Викликальник повинен передати токени, необхідні для угоди, в UniswapV3Pool у зворотному виклику, а не ділити метод swap на дві частини для виклику. Це забезпечує безпеку методу swap, гарантує повне виконання всієї логіки без необхідності ведення складних записів змінних для забезпечення безпеки.
Використання виняткової передачі інформації, реалізація оцінки угоди за допомогою try catch
У контракті Quoter Uniswap метод swap UniswapV3Pool виконується в упаковці try catch. Це робиться для моделювання методу swap для оцінки необхідних токенів для транзакції. Оскільки під час оцінки фактично не відбувається обміну токенів, виникає помилка. Uniswap викидає спеціальну помилку в зворотному виклику транзакції, а потім захоплює цю помилку, щоб витягти необхідну інформацію з тексту помилки.
Цей метод здається хитрим, але дуже практичний. Не потрібно модифікувати метод swap для оцінки торгових потреб, логіка простіша.
Використання великих чисел для вирішення проблеми точності
У коді Uniswap є велика кількість обчислювальної логіки, наприклад, обчислення токенів за поточною ціною та ліквідністю. Щоб уникнути втрати точності під час ділення, в обчислювальному процесі часто використовують операцію "<< FixedPoint96.RESOLUTION", що означає зсув вліво на 96 біт, що еквівалентно множенню на 2^96. Після зсуву проводять ділення, що забезпечує точність в умовах нормальних угод без переповнення.
Розрахунок доходу за допомогою Share
У Uniswap потрібно зафіксувати дохід від комісії ліквідності для LP(. Очевидно, що не можна фіксувати комісії для кожного LP під час кожної угоди, це споживе велику кількість Gas.
Рішення Uniswap полягає в тому, щоб у структурі Position записувати feeGrowthInside0LastX128 та feeGrowthInside1LastX128, що відображає, яку частину комісії має отримати кожен ліквідний актив під час останнього виведення комісії. Достатньо зафіксувати загальну комісію та комісію, що підлягає розподілу між кожним ліквідним активом; при виведенні LP комісія, яку можна вивести, обчислюється відповідно до утримуваного ліквідного активу. Це схоже на володіння акціями компанії: під час виведення прибутку потрібно знати лише історичний прибуток на акцію компанії та прибуток на момент останнього виведення.
![Web3 новачок серія: маленькі поради з розробки контрактів, які я навчився з коду Uniswap])https://img-cdn.gateio.im/webp-social/moments-45e66af69435e6d4412ae506e77ab893.webp(
Необхідну інформацію не потрібно отримувати з ланцюга
Зберігання на блокчейні відносно дороге, і не всяка інформація повинна бути на ланцюзі або отримуватися з ланцюга. Багато інтерфейсів, які використовує фронтенд сайт Uniswap, є традиційними Web2 інтерфейсами.
Список торгових пулів, інформація про торгові пули тощо можуть зберігатися в звичайних базах даних, частина з них може потребувати періодичної синхронізації з блокчейном, але немає необхідності в реальному часі викликати RPC-інтерфейси ланцюга або вузлів для отримання відповідних даних.
Звичайно, ключові угоди повинні проводитися в ланцюзі.
Розумне розділення контрактів, використання існуючих стандартних контрактів
Проект може містити кілька реально розгорнутіх контрактів. Навіть якщо насправді розгорнуто лише один контракт, код може бути розділений на кілька контрактів для підтримки за допомогою успадкування.
Наприклад, контракт NonfungiblePositionManager Uniswap успадковує кілька контрактів. При перегляді реалізації контракту ERC721Permit виявляється, що він безпосередньо використовує контракт @openzeppelin/contracts/token/ERC721/ERC721.sol. Це зручно як для управління позицією через NFT, так і для підвищення ефективності розробки з використанням існуючих стандартних контрактів.
Підсумок
Практика є найкращим методом навчання. Спробуйте самостійно реалізувати спрощену версію децентралізованої біржі, щоб глибше зрозуміти реалізацію коду Uniswap та дізнатися більше про знання, які використовуються в реальних проектах.
![Web3 новачок серії: маленькі хитрощі розробки контрактів, які я навчився з коду Uniswap])https://img-cdn.gateio.im/webp-social/moments-f95ddc9d89809cf11dbe65b9bafda157.webp(
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.
5 лайків
Нагородити
5
5
Поділіться
Прокоментувати
0/400
IntrovertMetaverse
· 20год тому
Знову прийшлося укладати контракт
Переглянути оригіналвідповісти на0
SerumSurfer
· 20год тому
Цей v3 вихідний код використовується досить класно.
Переглянути оригіналвідповісти на0
FlyingLeek
· 20год тому
Схоже на добре, чекаю, коли обдурюватимуть людей, як лохів
Розкриття коду Uniswap: 7 основних порад з розробки контрактів для допомоги новачкам у Defi до місяця
Поділитися порадами з розробки контрактів: навчання з вихідного коду Uniswap
Нещодавно, коли я писав посібник з розробки децентралізованої біржі, я звертався до реалізації коду Uniswap V3 і дізнався багато цінних моментів. Як розробник, який вперше намагається розробити Defi-контракти, ці поради будуть дуже корисні для новачків, які хочуть навчитися розробці контрактів.
Далі я поділюся деякими маленькими хитрощами, деякі з яких навіть можна назвати дивними трюками.
Прогнозовані адреси розгортання контрактів
Зазвичай адреса, отримана при розгортанні контракту, виглядає випадковою, оскільки пов'язана з nonce, тому передбачити адресу контракту важко. Але в деяких випадках нам потрібно мати можливість вивести адресу контракту на основі торгових пар та відповідної інформації. Це дуже корисно при визначенні прав доступу до транзакцій або отриманні адреси пулу.
Uniswap створює контракт, використовуючи CREATE2 з додаванням параметра salt, що робить адресу створеного контракту передбачуваною. Логіка генерації адреси: нова адреса = hash("0xFF", адреса творця, salt, initcode).
Розумне використання функцій зворотного виклику
У деяких випадках контракт A викликає методи контракту B, а B у викликаному методі викликає зворотний виклик A, цей спосіб дуже практичний.
Наприклад, під час торгівлі за допомогою методу swap контракту UniswapV3Pool, викликається зворотний виклик swapCallback, в якому передається обчислений токен, необхідний для цієї угоди. Викликальник повинен передати токени, необхідні для угоди, в UniswapV3Pool у зворотному виклику, а не ділити метод swap на дві частини для виклику. Це забезпечує безпеку методу swap, гарантує повне виконання всієї логіки без необхідності ведення складних записів змінних для забезпечення безпеки.
Використання виняткової передачі інформації, реалізація оцінки угоди за допомогою try catch
У контракті Quoter Uniswap метод swap UniswapV3Pool виконується в упаковці try catch. Це робиться для моделювання методу swap для оцінки необхідних токенів для транзакції. Оскільки під час оцінки фактично не відбувається обміну токенів, виникає помилка. Uniswap викидає спеціальну помилку в зворотному виклику транзакції, а потім захоплює цю помилку, щоб витягти необхідну інформацію з тексту помилки.
Цей метод здається хитрим, але дуже практичний. Не потрібно модифікувати метод swap для оцінки торгових потреб, логіка простіша.
Використання великих чисел для вирішення проблеми точності
У коді Uniswap є велика кількість обчислювальної логіки, наприклад, обчислення токенів за поточною ціною та ліквідністю. Щоб уникнути втрати точності під час ділення, в обчислювальному процесі часто використовують операцію "<< FixedPoint96.RESOLUTION", що означає зсув вліво на 96 біт, що еквівалентно множенню на 2^96. Після зсуву проводять ділення, що забезпечує точність в умовах нормальних угод без переповнення.
Розрахунок доходу за допомогою Share
У Uniswap потрібно зафіксувати дохід від комісії ліквідності для LP(. Очевидно, що не можна фіксувати комісії для кожного LP під час кожної угоди, це споживе велику кількість Gas.
Рішення Uniswap полягає в тому, щоб у структурі Position записувати feeGrowthInside0LastX128 та feeGrowthInside1LastX128, що відображає, яку частину комісії має отримати кожен ліквідний актив під час останнього виведення комісії. Достатньо зафіксувати загальну комісію та комісію, що підлягає розподілу між кожним ліквідним активом; при виведенні LP комісія, яку можна вивести, обчислюється відповідно до утримуваного ліквідного активу. Це схоже на володіння акціями компанії: під час виведення прибутку потрібно знати лише історичний прибуток на акцію компанії та прибуток на момент останнього виведення.
![Web3 новачок серія: маленькі поради з розробки контрактів, які я навчився з коду Uniswap])https://img-cdn.gateio.im/webp-social/moments-45e66af69435e6d4412ae506e77ab893.webp(
Необхідну інформацію не потрібно отримувати з ланцюга
Зберігання на блокчейні відносно дороге, і не всяка інформація повинна бути на ланцюзі або отримуватися з ланцюга. Багато інтерфейсів, які використовує фронтенд сайт Uniswap, є традиційними Web2 інтерфейсами.
Список торгових пулів, інформація про торгові пули тощо можуть зберігатися в звичайних базах даних, частина з них може потребувати періодичної синхронізації з блокчейном, але немає необхідності в реальному часі викликати RPC-інтерфейси ланцюга або вузлів для отримання відповідних даних.
Звичайно, ключові угоди повинні проводитися в ланцюзі.
Розумне розділення контрактів, використання існуючих стандартних контрактів
Проект може містити кілька реально розгорнутіх контрактів. Навіть якщо насправді розгорнуто лише один контракт, код може бути розділений на кілька контрактів для підтримки за допомогою успадкування.
Наприклад, контракт NonfungiblePositionManager Uniswap успадковує кілька контрактів. При перегляді реалізації контракту ERC721Permit виявляється, що він безпосередньо використовує контракт @openzeppelin/contracts/token/ERC721/ERC721.sol. Це зручно як для управління позицією через NFT, так і для підвищення ефективності розробки з використанням існуючих стандартних контрактів.
Підсумок
Практика є найкращим методом навчання. Спробуйте самостійно реалізувати спрощену версію децентралізованої біржі, щоб глибше зрозуміти реалізацію коду Uniswap та дізнатися більше про знання, які використовуються в реальних проектах.
![Web3 новачок серії: маленькі хитрощі розробки контрактів, які я навчився з коду Uniswap])https://img-cdn.gateio.im/webp-social/moments-f95ddc9d89809cf11dbe65b9bafda157.webp(