Поради з розробки контрактів: досвід, отриманий з коду Uniswap
Нещодавно, під час написання посібника з розробки децентралізованих бірж, я звернувся до реалізації Uniswap V3 і дізнався багато цікавих моментів. Як новачок, який вперше намагається розробити контракти DeFi, ці поради, напевно, будуть дуже корисними для інших, хто хоче навчитися розробці контрактів.
Прогнозована адреса розгортання контракту
Зазвичай адреса, отримана в результаті розгортання контракту, здається випадковою і важко передбачуваною. Але в деяких випадках нам потрібно зробити висновки про адресу контракту на основі інформації про угоду, наприклад, щоб визначити права на угоду або отримати адресу пулу.
Uniswap використовує метод CREATE2 для створення контрактів, додаючи параметр salt, що робить адресу передбачуваною. Логіка генерації нової адреси така: hash("0xFF", адреса творця, salt, initcode). Цей метод робить адреси контрактів передбачуваними, що є дуже корисним.
Розумне використання функцій зворотного виклику
У Solidity контракти можуть викликати один одного. У певних ситуаціях A викликає метод B, а B у викликаному методі викликає A, така модель є дуже корисною.
У Uniswap обмінні транзакції реалізовано через механізм зворотного виклику. Метод swap в UniswapV3Pool викликає swapCallback, передаючи фактичну кількість токенів, яка потрібна. Викликаюча сторона повинна передати токени у зворотному виклику, що забезпечує завершення та безпеку методу swap без необхідності в складному веденні змінних.
Використання виключень для передачі інформації, реалізація оцінки交易 за допомогою try catch
У контракті Quoter Uniswap метод swap UniswapV3Pool обгорнутий у блок try catch. Це робиться для моделювання обміну, щоб оцінити необхідні токени для угоди, але під час оцінки фактичний обмін токенів не відбувається, тому виникає помилка.
Uniswap вибрасыває спеціальну помилку в колбек-функції, а потім перехоплює цю помилку та аналізує з неї необхідну інформацію. Цей підхід здається хитрим, але дуже практичний, оскільки не потрібно спеціально модифікувати метод swap для оцінки попиту, логіка стає більш чіткою.
Використання великих чисел для вирішення проблеми точності
У коді Uniswap є велика кількість обчислень, наприклад, для розрахунку кількості токенів, що обмінюються, на основі поточної ціни та ліквідності. Щоб уникнути втрати точності під час ділення, в процесі обчислення часто використовують операцію "<< FixedPoint96.RESOLUTION", тобто зсув вліво на 96 біт, що дорівнює множенню на 2^96.
Зліва переміщуючи, а потім ділячи, можна забезпечити точність за нормальної торгівлі без переповнень. Хоча теоретично все ще буде невелика втрата точності, це вже прийнятно.
Розрахунок прибутку за допомогою Share
Uniswap повинен зафіксувати дохід від комісій LP( для постачальника ліквідності ). Очевидно, що не можна реєструвати комісії для кожного LP з кожною угодою, це вимагатиме великих витрат на газ.
Рішення полягає в тому, щоб у структурі Position записувати feeGrowthInside0LastX128 та feeGrowthInside1LastX128, що вказують на те, яку комісію повинен отримати кожен одиничний ліквідності під час останнього вилучення комісії.
Достатньо зафіксувати загальну комісію та комісію, що розподіляється на одиницю ліквідності; під час виведення LP можна розрахувати доступну комісію, виходячи з утримуваної ліквідності. Це подібно до утримання акцій: під час виведення прибутків потрібно лише знати історичний прибуток на акцію та прибуток під час останнього виведення.
Не всю інформацію потрібно отримувати з ланцюга
Зберігання на блокчейні відносно дороге, не вся інформація повинна бути на блокчейні або отримуватися з блокчейну. Наприклад, багато інтерфейсів, які викликаються фронтендом Uniswap, є традиційними веб-інтерфейсами Web2.
Список торгових пулів, інформація тощо можуть зберігатися в звичайній базі даних, частина з них повинна періодично синхронізуватися з блокчейном, але не потрібно в режимі реального часу викликати дані з ланцюга або RPC-інтерфейси вузлів.
Багато постачальників RPC для блокчейну також пропонують розширені інтерфейси, які дозволяють швидше і дешевше отримувати певні дані. Ці інтерфейси зазвичай використовують кеш для підвищення продуктивності та ефективності.
Звичайно, ключові угоди все ще проводяться в мережі.
Навчіться розділяти контракти та використовувати вже існуючі стандартні контракти
Проект може містити кілька фактично розгорнутих контрактів. Навіть якщо розгорнуто лише один контракт, код також можна підтримувати шляхом розподілу на кілька контрактів через успадкування.
Наприклад, контракт NonfungiblePositionManager Uniswap успадкував кілька контрактів. Контракт ERC721Permit безпосередньо використовує реалізацію ERC721 від OpenZeppelin, що спрощує управління позиціями за допомогою NFT та підвищує ефективність розробки.
Підсумок
Розробка спрощеної версії децентралізованої біржі власноруч допоможе вам глибше зрозуміти реалізацію Uniswap і дізнатися більше про знання, які можна застосувати в реальних проектах. Теоретичне навчання, безумовно, важливе, але практичний досвід є ще більш цінним. Сподіваюся, ці невеликі поради будуть корисними для вашого шляху в розробці контрактів.
Ця сторінка може містити контент третіх осіб, який надається виключно в інформаційних цілях (не в якості запевнень/гарантій) і не повинен розглядатися як схвалення його поглядів компанією Gate, а також як фінансова або професійна консультація. Див. Застереження для отримання детальної інформації.
19 лайків
Нагородити
19
7
Поділіться
Прокоментувати
0/400
GasWaster
· 07-16 11:49
Всі, хто вивчає контракти, повинні дивитися
Переглянути оригіналвідповісти на0
MissedAirdropAgain
· 07-16 07:39
Вивчити контракт вже запізно...
Переглянути оригіналвідповісти на0
YieldWhisperer
· 07-14 20:20
бачив цей точний патерн на dyydx у 2020 році... якщо чесно, нічого нового
Переглянути оригіналвідповісти на0
MEVictim
· 07-14 20:18
Чи дійсно ці знання, про які ви запитуєте, корисні?
Розбір коду Uniswap: 7 порад із розробки смартконтрактів
Поради з розробки контрактів: досвід, отриманий з коду Uniswap
Нещодавно, під час написання посібника з розробки децентралізованих бірж, я звернувся до реалізації Uniswap V3 і дізнався багато цікавих моментів. Як новачок, який вперше намагається розробити контракти DeFi, ці поради, напевно, будуть дуже корисними для інших, хто хоче навчитися розробці контрактів.
Прогнозована адреса розгортання контракту
Зазвичай адреса, отримана в результаті розгортання контракту, здається випадковою і важко передбачуваною. Але в деяких випадках нам потрібно зробити висновки про адресу контракту на основі інформації про угоду, наприклад, щоб визначити права на угоду або отримати адресу пулу.
Uniswap використовує метод CREATE2 для створення контрактів, додаючи параметр salt, що робить адресу передбачуваною. Логіка генерації нової адреси така: hash("0xFF", адреса творця, salt, initcode). Цей метод робить адреси контрактів передбачуваними, що є дуже корисним.
Розумне використання функцій зворотного виклику
У Solidity контракти можуть викликати один одного. У певних ситуаціях A викликає метод B, а B у викликаному методі викликає A, така модель є дуже корисною.
У Uniswap обмінні транзакції реалізовано через механізм зворотного виклику. Метод swap в UniswapV3Pool викликає swapCallback, передаючи фактичну кількість токенів, яка потрібна. Викликаюча сторона повинна передати токени у зворотному виклику, що забезпечує завершення та безпеку методу swap без необхідності в складному веденні змінних.
Використання виключень для передачі інформації, реалізація оцінки交易 за допомогою try catch
У контракті Quoter Uniswap метод swap UniswapV3Pool обгорнутий у блок try catch. Це робиться для моделювання обміну, щоб оцінити необхідні токени для угоди, але під час оцінки фактичний обмін токенів не відбувається, тому виникає помилка.
Uniswap вибрасыває спеціальну помилку в колбек-функції, а потім перехоплює цю помилку та аналізує з неї необхідну інформацію. Цей підхід здається хитрим, але дуже практичний, оскільки не потрібно спеціально модифікувати метод swap для оцінки попиту, логіка стає більш чіткою.
Використання великих чисел для вирішення проблеми точності
У коді Uniswap є велика кількість обчислень, наприклад, для розрахунку кількості токенів, що обмінюються, на основі поточної ціни та ліквідності. Щоб уникнути втрати точності під час ділення, в процесі обчислення часто використовують операцію "<< FixedPoint96.RESOLUTION", тобто зсув вліво на 96 біт, що дорівнює множенню на 2^96.
Зліва переміщуючи, а потім ділячи, можна забезпечити точність за нормальної торгівлі без переповнень. Хоча теоретично все ще буде невелика втрата точності, це вже прийнятно.
Розрахунок прибутку за допомогою Share
Uniswap повинен зафіксувати дохід від комісій LP( для постачальника ліквідності ). Очевидно, що не можна реєструвати комісії для кожного LP з кожною угодою, це вимагатиме великих витрат на газ.
Рішення полягає в тому, щоб у структурі Position записувати feeGrowthInside0LastX128 та feeGrowthInside1LastX128, що вказують на те, яку комісію повинен отримати кожен одиничний ліквідності під час останнього вилучення комісії.
Достатньо зафіксувати загальну комісію та комісію, що розподіляється на одиницю ліквідності; під час виведення LP можна розрахувати доступну комісію, виходячи з утримуваної ліквідності. Це подібно до утримання акцій: під час виведення прибутків потрібно лише знати історичний прибуток на акцію та прибуток під час останнього виведення.
Не всю інформацію потрібно отримувати з ланцюга
Зберігання на блокчейні відносно дороге, не вся інформація повинна бути на блокчейні або отримуватися з блокчейну. Наприклад, багато інтерфейсів, які викликаються фронтендом Uniswap, є традиційними веб-інтерфейсами Web2.
Список торгових пулів, інформація тощо можуть зберігатися в звичайній базі даних, частина з них повинна періодично синхронізуватися з блокчейном, але не потрібно в режимі реального часу викликати дані з ланцюга або RPC-інтерфейси вузлів.
Багато постачальників RPC для блокчейну також пропонують розширені інтерфейси, які дозволяють швидше і дешевше отримувати певні дані. Ці інтерфейси зазвичай використовують кеш для підвищення продуктивності та ефективності.
Звичайно, ключові угоди все ще проводяться в мережі.
Навчіться розділяти контракти та використовувати вже існуючі стандартні контракти
Проект може містити кілька фактично розгорнутих контрактів. Навіть якщо розгорнуто лише один контракт, код також можна підтримувати шляхом розподілу на кілька контрактів через успадкування.
Наприклад, контракт NonfungiblePositionManager Uniswap успадкував кілька контрактів. Контракт ERC721Permit безпосередньо використовує реалізацію ERC721 від OpenZeppelin, що спрощує управління позиціями за допомогою NFT та підвищує ефективність розробки.
Підсумок
Розробка спрощеної версії децентралізованої біржі власноруч допоможе вам глибше зрозуміти реалізацію Uniswap і дізнатися більше про знання, які можна застосувати в реальних проектах. Теоретичне навчання, безумовно, важливе, але практичний досвід є ще більш цінним. Сподіваюся, ці невеликі поради будуть корисними для вашого шляху в розробці контрактів.