Розробка кастомних пулів на Uniswap v4
Uniswap v4 — це не чергова версія з поліпшеним AMM. Це платформа для створення кастомних пулів. Ключова зміна: архітектура hooks дозволяє виконувати довільний код до і після будь-якої операції з пулом — ініціалізації, свапу, додавання/видалення ліквідності, донації. Це відкриває простір, якого не було в v2 та v3: динамічні комісії, on-chain order books, автоматичний rebalancing, MEV-захист прямо в пулі.
Ціна цієї гнучкості — складність. Хук-контракт працює в контексті PoolManager через механізм unlock callback із системою BalanceDelta обліку. Помилка в хуці може заблокувати весь пул або слити ліквідність.
Архітектура Uniswap v4: що змінилось принципово
Singleton PoolManager та BalanceDelta
У v2/v3 кожен пул — окремий контракт. У v4 всі пули живуть усередину одного PoolManager. Це скорочує газ на створення пулу з ~500k до ~150k, і робить мультихоп свапи значно дешевшими (немає трансфертів між контрактами).
Розрахунок токенів ведеться через BalanceDelta — не реальні переводи, а дельти, які накопичуються та розраховуються в кінці unlock callback. Поки PoolManager залочений (у межах одного unlock), токени фізично не переходять. Це відкриває flash accounting: зробити свап, використати отримані токени для чогось, повернути борг — все в одній транзакції без flash loan.
Система хуків: адреса як бітова маска
Хук-контракт реєструється при створенні пулу через PoolKey. Адреса хука кодує дозволені callback через провідні біти: певні біти адреси повинні бути встановлені для активації відповідних хуків. beforeSwap — біт 7, afterSwap — біт 6, beforeAddLiquidity — біт 5, і так далі.
Це означає, що адреса хук-контракту не може бути вибрана довільно — потрібно майнити vanity-адресу з потрібними бітами через CREATE2. Інструменти: v4-template від Uniswap, скрипти для mining адреси через Foundry.
Всього 14 можливих хуків:
| Хук | Опис |
|---|---|
beforeInitialize / afterInitialize |
До/після створення пулу |
beforeAddLiquidity / afterAddLiquidity |
До/після додавання ліквідності |
beforeRemoveLiquidity / afterRemoveLiquidity |
До/після видалення |
beforeSwap / afterSwap |
До/після свапу |
beforeDonate / afterDonate |
До/після донації в пул |
beforeSwapReturnDelta |
Модифікація виводу свапу |
afterSwapReturnDelta |
Взяти комісію після свапу |
afterAddLiquidityReturnDelta |
Змінити баланс LP |
afterRemoveLiquidityReturnDelta |
Змінити баланс при видаленні |
Найцікавіші кастомні механіки
Динамічні комісії через beforeSwap
У v3 fee tier фіксований при створенні пулу (0.05%, 0.3%, 1%). У v4 хук може повертати lpFeeOverride прямо з beforeSwap, змінюючи комісію для кожного свапу динамічно. Це дозволяє будувати:
Волатильність-залежні комісії: Chainlink price feed + sliding window волатильність → при високій волатильності fee 1%, при низькій 0.05%. LP отримують справедливе вознаграження за ризик impermanent loss.
TWAP-базовані комісії: якщо поточна ціна відхилилась від TWAP більш ніж на X%, збільшити fee — захист від oracle-driven арбітража, який збагачує арбітражників за рахунок LP.
Limit orders через tick-based хуки
З afterSwap хук знає, що свап відбувся і ціна змінилась. Якщо поточний tick перетнув заранее заданий рівень — можна виконати limit order: купити/продати ліквідність із маппінгу заявок. Це повноцінний on-chain limit order book без centralized sequencer.
Складність реалізації: газ на ітерацію по заявкам у хуці. При 50+ заявок на один tick свап стає дорогим. Рішення — lazy execution: заявки виконуються при наступному зверненню до тика, не блокуючи поточен свап.
TWAMM (Time-Weighted Average Market Maker)
Великі ордери розбиваються на маленькі віртуальні ордери, виконувані continuous по часу. Хук накопичує токени від TWAMM-ордерів, поступово виконує їх через пул, не створюючи слиппаж. Це вирішує проблему whale orders — $10M свап за один блок рухає ціну та створює sandwich можливості. TWAMM-хук розмазує його на 1000 блоків.
Математика: віртуальні ордери обчислюються через формулу експоненціального розподілу, яка дозволяє пересчитати стан для будь-якого моменту часу без пошагового обходу.
Типічні помилки при розробці хуків
Reentrancy через PoolManager. PoolManager має власний lock, але хук може викликати зовнішні контракти, які знов входять в пул. NoSuchPool, AlreadyUnlocked — частісні помилки при відладці. Правило: в хуках не робити зовнішніх вызовів, окрім read-only запитів.
Некоректний BalanceDelta. Хук повертає дельту токенів. Якщо вона неправильно розрахована — PoolManager ревертить з DeltaNotSettled. Поширений кейс: afterSwapReturnDelta пробує забрати більше, ніж є в дельті після свапу.
Mining адреси для production. CREATE2 mining займає від хвилин до годин залежно від кількості потрібних бітів. Для 14 хуків (всі активні) — потрібні 14 специфічних бітів, це ~16,384 спроби в середньому. На GPU — швидко, на CPU з Foundry — від 10 хвилин до години.
Стек та процес розробки
Розробка ведеться на базі офіційного v4-template репозиторію. Foundry — єдиний адекватний інструмент для тестування v4 хуків: PoolSwapTest, PoolModifyLiquidityTest хелпери з v4-periphery, fork-тесты на стані mainnet/testnet.
Проектування (2–3 дні): визначення механіки пулу, набору хуків, BalanceDelta логіки. На цьому етапі — формальна специфікація інваріантів: «пул ніколи не може мати негативний баланс», «fee не перевищує X% при будь-якій умові».
Розробка хук-контракту (3–5 днів): імплементація callback, mining адреси, допоміжні контракти (oracle, order book, rebalancer).
Тестування (3–5 днів): unit-тесты кожного хука в ізоляції, інтеграційні тесты через PoolSwapTest, fuzz-тесты критичних параметрів (розмір свапу, tick range, fee multiplier), fork-тесты на реальному стані.
Аудит та деплой (2–3 дні): Slither, ручний review з фокусом на reentrancy та BalanceDelta коректність, деплой через Foundry forge script з верифікацією.
Всього: 1–2 тижні для хука з однією механікою. Складні системи (TWAMM, full order book) — 4–6 тижнів. Вартість розраховується після опису механіки та вимог до throughput.







