Розробка concentrated liquidity pools

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1306 послуг
Розробка concentrated liquidity pools
Складний
від 2 тижнів до 3 місяців
Часті запитання

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

Етапи блокчейн-розробки

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

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

Розробка пулів зосередженої ліквідності

Команда запускає DEX і хоче не просто скопіювати Uniswap V2 з його x·y=k, а зробити щось конкурентоспроможне. Перехід на concentrated liquidity — правильне рішення, але реалізація значно складніша: тики, діапазони, віртуальні резерви, piecewise-криві. Одна помилка в математиці — і LP втрачають гроші непомітно для себе, а арбітражники стригають протокол.

Чому x·y=k більше не працює для серйозних AMM

Класична constant product формула ефективно використовує 5% до 20% ліквідності при реалістичних цінових діапазонах. Інші 80% капіталу LP «сплять» на хвостах, які ніколи не торгуються. Uniswap V3 вирішив це через концентрацію: LP вибирає діапазон [tickLower, tickUpper], і його ліквідність працює тільки всередині нього — але працює в багато разів інтенсивніше.

Архітектурно це означає перехід від однієї глобальної кривої до piecewise-лінійної апроксимації. Кожен тик — границя діапазону, в якому діє локальна формула. Перетин тика перераховує активну ліквідність.

Математика, яка ламається при неправильній реалізації

Tick math і Q64.96 fixed-point арифметика

Uniswap V3 зберігає ціни як sqrtPriceX96 — корінь з ціни в форматі Q64.96. Не випадково: множення двох Q64.96 чисел дає Q128.192, що умістилося в uint256. Будь-яке відхилення від цієї схеми — overflow або втрата точності.

Функція TickMath.getSqrtRatioAtTick(int24 tick) — критично важлива: вона переводить номер тика в sqrtPrice через таблицю прекомпільованих констант з бітовими зсувами. Самостійна реалізація без точного відтворення цих констант дає накопичувальну помилку, видиму при граничних значеннях тиків (MIN_TICK = -887272, MAX_TICK = 887272).

Практичний кейс: при тестуванні на Foundry fuzz-тестами з int24 параметрами ми спіймали розбіжність в 1 wei на крайніх тиках — здавалось, нічого. Але на функції спалювання ліквідності це давало underflow в uint256 і revert. На mainnet це блокувало б виведення ліквідності.

Fee accumulation через глобальні аккумулятори

Механізм збору комісій у концентрованих пулах працює через глобальні аккумулятори feeGrowthGlobal0X128 і feeGrowthGlobal1X128, плюс per-tick значення feeGrowthOutside. Формула розрахунку fees всередину діапазону:

feeGrowthInside = feeGrowthGlobal - feeGrowthBelow(tickLower) - feeGrowthAbove(tickUpper)

Де feeGrowthBelow і feeGrowthAbove залежать від того, знаходиться ли поточний тик вище або нижче границі. Помилка в умові currentTick >= tickLower vs currentTick > tickLower дає неверний розрахунок fees на граничних тиках. Це тиха помилка — LP отримують чуть менше або чуть більше комісій, протокол накопичує борг або профіцит.

Reentrancy через callback в swap

Swap-функція в concentrated liquidity AMM використовує callback-паттерн: пул контракт спочатку відпускає токени, потім викликає uniswapV3SwapCallback у msg.sender, в якому очікує отримати вхідні токени. Це відкриває reentrancy-вектор: в момент callback стан пула вже змінений (ціна зсунута), але транзакція ще не завершена.

OpenZeppelin ReentrancyGuard не допомагає прямо — callback викликається самим пулом в рамках тієї ж транзакції. Захист: lock-флаг в storage пула, який встановлюється на початку swap і знімається в кінці. Uniswap V3 використовує unlocked флаг в slot0 саме для цього.

Як ми будуємо concentrated liquidity pools

Архітектурні рішення

Розробляємо на базі Uniswap V3 Core як референцу, але не форкаємо прямо — ліцензія BSL 1.1 до 2023 року мала обмеження на комерційне використання (тепер закінчилась, але аудитори все ще запитують). Використовуємо Uniswap V4's hooks архітектуру для розширень, якщо потрібна кастомна fee-логіка.

Стек: Foundry для всієї розробки та тестування, Hardhat для deploy-скриптів з hardhat-deploy. Математичні бібліотеки — портуємо з @uniswap/v3-core/contracts/libraries: FullMath, TickMath, SqrtPriceMath, LiquidityMath. Тести включають property-based fuzzing з invariant-тестами в Foundry:

  • Інваріант 1: сума всієї ліквідності в активних діапазонах завжди >= virtualReserves
  • Інваріант 2: після будь-якого swap з нульовим slippage sqrtPrice не виходить за границі вказаного діапазону
  • Інваріант 3: collected fees не перевищують accumulated feeGrowth * liquidity

Tick bitmap оптимізація

Пошук наступного ініціалізованого тика при cross-tick операціях — гарячий шлях. Uniswap V3 використовує bitmap: 256 тиків упаковані в один uint256. Пошук наступного set bit через BitMath.mostSignificantBit — O(1) замість O(n) по всім тикам.

Реалізація bitmap для tickSpacing > 1 вимагає маппінгу з tickIndex в bitPosition: compressed = tick / tickSpacing, wordPos = compressed >> 8, bitPos = uint8(compressed). Помилка в зсувах дає неверний пошук тика і пропуск cross-tick логіки при swaps через кілька діапазонів.

Тестування на реальних даних

Fork-тесты на Ethereum mainnet через vm.createFork дозволяють відтворити реальні стани пулів USDC/ETH 0.05% fee tier з реальним розподілом ліквідності. Прогоняємо історичні swaps з Uniswap V3 subgraph через The Graph і порівнюємо результати з референсною реалізацією. Розбіжність > 1 wei на будь-якому swap — сигнал до розслідування.

Компонент Інструмент Покриття
TickMath Foundry fuzz, порівняння з V3 core 100% граничних тиків
Fee accumulation Property-based invariant tests 50k ітерацій
Swap через кілька тиків Fork-тести на mainnet даних 1000+ історичних swaps
Liquidity mint/burn Статичний аналіз Slither + ручний review Всі публічні функції

Періферія та інтеграції

Сам пул — це тільки ядро. Для повноцінного продукту потрібен NonfungiblePositionManager (або аналог) для управління LP-позиціями як NFT (ERC-721), SwapRouter для агрегації маршрутів, і quoter-контракт для off-chain симуляції swaps без gas.

Інтеграція з Chainlink Price Feeds як sanity check: якщо ціна в пулі відхиляється від oracle більш ніж на X%, circuit breaker приостанавлює swaps. Це захист від oracle manipulation через flash loans — вектор, який використовувався в атаках на протоколи, що будувалися поверх AMM-цін.

Frontend будуємо на Uniswap SDK v3 + wagmi + viem. SDK абстрагує tick math і route finding, але для кастомних пулів його потрібно розширювати — підключати власні pool factories і переозначати computePoolAddress.

Етапи роботи

Аналітика (3-5 днів). Визначаємо параметри: fee tiers (0.01% / 0.05% / 0.3% / 1%), tickSpacing, потрібні ли кастомні hooks (V4-стиль), мультичейн деплой (Ethereum + Arbitrum + Optimism типово). Перевіряємо, потрібна ли апгрейдовність пула або immutable з admin-функціями тільки в періферії.

Проектування (5-7 днів). Storage layout, інтерфейси, математичні бібліотеки. Формальна верифікація інваріантів на папері до написання коду.

Розробка (4-8 тижнів). Core pool → математичні бібліотеки → position manager → router → quoter. Порядок важливий: кожен шар тестується незалежно.

Аудит. Concentrated liquidity — один з найскладніших класів DeFi-контрактів. Зовнішній аудит обов'язків для будь-якого об'єму TVL. Внутрішній аудит через Slither + Echidna закриває low/medium перед відправкою.

Деплой. Foundry forge script + Gnosis Safe мультисиг. Деплой на Sepolia/Arbitrum Goerli, нагрузочні тесты, потім mainnet.

Орієнтири по термінам

MVP з одним fee tier і базовою періферією — 6-8 тижнів. Повноцінний multi-tier DEX з custom hooks і агрегатором маршрутів — 2-3 місяці. Без урахування часу зовнішнього аудиту (зазвичай 3-6 тижнів для протоколу такої складності).

Вартість рахується індивідуально після технічного брифінгу.