Розробка кастомних хуків Uniswap v4 під ключ

Кастомні хуки Uniswap v4: архітектура та розробка Ми розробляємо кастомні хуки Uniswap v4 під ключ — від ідеї до деплою та аудиту. Uniswap v4 змінив архітектуру радикально: один singleton-контракт `PoolManager` управляє всіма пулами, а розширення логіки — через хуки. Це не просто callback-и. Хуки

Напрямки блокчейн-розробки

Часті запитання

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1450
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1308
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1003
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1269
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    717
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    1008

Кастомні хуки Uniswap v4: архітектура та розробка

Ми розробляємо кастомні хуки Uniswap v4 під ключ — від ідеї до деплою та аудиту. Uniswap v4 змінив архітектуру радикально: один singleton-контракт PoolManager управляє всіма пулами, а розширення логіки — через хуки. Це не просто callback-и. Хуки отримують контроль над критичними точками життєвого циклу пулу: до і після ініціалізації, до і після свапу, до і після додавання/видалення ліквідності. Правильно написаний хук дозволяє вбудувати limit orders, динамічне ціноутворення, fee rebate, MEV-capture — без форку протоколу. Неправильний — заблокує пул або стане вектором атаки. Зв'яжіться з нами, щоб оцінити ваше завдання — ми підготуємо пропозицію за 1 день.

Як правильно налаштувати прапори хука?

Прапори та permissions

Адреса хука кодує дозволи в бітах. Біти 0-7 визначають, які callback-и активні: BEFORE_SWAP_FLAG, AFTER_SWAP_FLAG, BEFORE_ADD_LIQUIDITY_FLAG тощо. Якщо хук оголошує getHookPermissions() з прапором afterSwap: true, але адреса деплою не містить відповідний біт — PoolManager ревертне при ініціалізації пулу.

Це означає: адреса контракту хука не довільна. Потрібен CREATE2-деплой з підбором salt до співпадіння потрібних бітів в адресі. Для складного хука з 4-5 прапорами підбір salt — окреме завдання, яке вирішують off-chain скриптом.

PoolKey та ізоляція пулів

Кожен пул в v4 ідентифікується PoolKey: {currency0, currency1, fee, tickSpacing, hooks}. Адреса хука — частина ідентифікатора пулу. Два пули з однаковими токенами та fee, але різними хуками — різні пули з різними liquidity positions. Це означає: ліквідність не можна «мігрувати» між хуками без повного виведення та введення.

transient storage та EIP-1153

V4 активно використовує EIP-1153 transient storage — сховище, яке очищується в кінці транзакції. Це дешевше за SSTORE/SLOAD і ідеально для тимчасового стану всередині транзакції (наприклад, прапор «свап вже йде»). Хуки можуть використовувати transient storage для reentrancy-захисту без постійного storage overhead.

Типові кейси хуків та їх складності

Dynamic fee hook

Найпопулярніший запит: fee, яка змінюється залежно від волатильності. Логіка afterSwap: рахуємо відхилення від TWAP, якщо >threshold — підвищуємо fee для наступного свапу через poolManager.updateDynamicLPFee().

Проблема: TWAP потрібно зберігати in-hook. Якщо використовуємо Uniswap v3 TWAP оракул як reference — це зовнішній виклик з afterSwap, що збільшує gas cost кожного свапу на 3-5k gas. Альтернатива: власний rolling TWAP в hook storage, оновлюваний в afterSwap. Дешевше, але потребує bootstrap періоду та обробки edge case при перших свапах.

Другий нюанс: updateDynamicLPFee можна викликати лише якщо пул ініціалізовано з FEE_DYNAMIC_FLAG. Цей прапор має бути встановлений в fee полі PoolKey при створенні пулу. Пропустити — контракт задеплоєно, пул створено, хук не працює. Переграти не можна.

Limit order hook

beforeSwap перевіряє, чи є pending limit orders в діапазоні поточного тіка. Якщо так — виконує їх як частину свапу. Реалізація: мапінг tick => orders[], обхід при перетині тіка.

Головний ризик: unbounded loop по orders на тіку. Якщо на одному тіку накопичилось 500 ордерів, один свап через цей тік витратить >1M gas і впреться в block gas limit. Захист: обмеження на кількість ордерів на тік + батчинг виконання через окрему keeper-функцію для накопичених ордерів.

MEV capture через afterSwap fee redistribution

Ідея: частина fee від свапу, який викликав значний рух ціни (підозра на MEV), перенаправляється в окремий пул компенсацій для LP. afterSwap рахує price impact, якщо вище порогу — надсилає додатковий платіж в vault.

Технічна складність: afterSwap отримує delta — зміну балансів. Потрібно розрахувати price impact на основі delta та початкового стану пулу. Початковий стан пулу потрібно зняти в beforeSwap та зберегти в transient storage — щоб в afterSwap можна було порівняти. Це класичний патерн для пар beforeX/afterX хуків.

Інструменти розробки

Foundry — єдиний нормальний вибір для v4 хуків. v4-core репозиторій написаний під Foundry, тести — теж. forge test --fork-url <mainnet> дозволяє тестувати хук проти реального стану PoolManager.

v4-template від Uniswap — стартова точка. Містить правильний setup HookMiner для CREATE2 деплою, базовий BaseHook з абстракціями, приклади тестів.

Slither з кастомними детекторами для v4 — перевіряємо коректність прапорів, відсутність storage collision з PoolManager slots.

Чому transient storage важливий для продуктивності?

Використання SSTORE в гарячому шляху додасть +20k gas на кожен свап. Transient storage (EIP-1153) обходиться в ~100 gas за операцію, що дає економію до 20% газового бюджету транзакції. Ми гарантуємо, що ваш хук буде спроектований з урахуванням цієї оптимізації — наш досвід включає більше 10 проектів на v4.

Часті помилки при розробці хуків

Помилка Наслідок Рішення
Неправильні біти в адресі Пул не ініціалізується CREATE2 + HookMiner до деплою
Зовнішній виклик в beforeSwap без reentrancy guard Можливий reentrancy через хук nonReentrant + transient storage lock
Unbounded loop в order book DoS через gas limit Обмеження ордерів на тік + keeper
Використання SSTORE в гарячому шляху +20k gas на кожен свап Transient storage (EIP-1153)
Мутація PoolKey в хуці Неможливо — PoolKey immutable Проектувати логіку без зміни key

Процес розробки

Специфікація (2-3 дні). Формалізуємо поведінку хука в кожній точці життєвого циклу. Які інваріанти мають дотримуватись? «Сума fee завжди ≥ base fee», «limit order ніколи не виконується за ціною гіршою за заявлену».

Розробка (5-7 днів). Foundry + v4-template. CREATE2 деплой скрипт з HookMiner. Property-based тести через Echidna на ключові інваріанти.

Fork-тестування (2-3 дні). Тести проти реального mainnet стану: ініціалізація пулу, серія свапів, граничні випадки (empty pool, single-sided liquidity, large price impact).

Аудит та газовий профіль. Slither + ручний review. Gas snapshot через forge snapshot — порівнюємо gas cost свапу з хуком та без. Допустимий overhead для більшості кейсів: <10k gas на свап.

Приклад батчингу ордерів Для обмеження unbounded loop ми реалізуємо функцію `batchExecuteOrders(uint24 tick, uint256 limit)`, яка обробляє не більше 20 ордерів за виклик. Keeper-сервіс запускається кожні N блоків.

Що входить в роботу

  • Специфікація та архітектура хука (PDF)
  • Вихідний код з тестами (Foundry)
  • CREATE2 деплой-скрипт з підбором salt
  • Газовий профіль (forge snapshot)
  • Звіт про автоматичний аудит (Slither + Mythril)
  • Посібник з експлуатації (Markdown)
  • 1 місяць підтримки після деплою

Орієнтири за термінами

Простий хук (dynamic fee або whitelist) — 1 тиждень включаючи тести. Хук середньої складності (limit orders, MEV capture) — 2-3 тижні. Комплексна система з кількома взаємодіючими хуками — від 4 тижнів.

Вартість розраховується індивідуально після обговорення необхідної механіки. Отримайте консультацію та попередню оцінку за 1 день — напишіть нам.

Цитата з офіційної документації: Uniswap v4 hooks provide a powerful way to customize pool behavior without forking the core protocol.