Розробка протоколу стабільного обміну

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1306 послуг
Розробка протоколу стабільного обміну
Складний
від 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

Розробка протоколу стабільного обміну

Curve Finance утримує $3-5 млрд TVL не тому що перший DEX, а тому що вирішив конкретну математичну проблему: Uniswap V2 з кривою x*y=k дає 1% slippage вже при 0.1% обміну пула. Для активів, які повинні коштувати одинаково (USDC/USDT, stETH/ETH, WBTC/renBTC), це неприйнятно. Stable swap інваріант концентрує ліквідність біля паритету і зменшує slippage в рази.

Якщо ваш проект працює з pegged активами — LST (liquid staking tokens), stablecoins, wrapped assets — вам потрібна саме ця математика.

Математика stable swap: навіщо це не просто "AMM для стейблкоинів"

Інваріант StableSwap Curve

Curve використовує гібридний інваріант, комбінуючи constant sum (x+y=k, нульовий slippage) та constant product (x*y=k, нескінченна ліквідність). Формула для двох активів:

A * n^n * sum(x_i) + D = A * D * n^n + D^(n+1) / (n^n * prod(x_i))

де A — коефіцієнт посилення, D — інваріант, n — кількість активів.

Коефіцієнт посилення — ключовий параметр. При A=0 система поводиться як Uniswap (constant product). При A→∞ — як constant sum. Curve використовує A=100-2000 залежно від пула. Для пар USDC/USDT — високий A (100-200), тому що активи рідко відхиляються від паритету. Для stETH/ETH спочатку — нижче, тому що stETH торгувався з дисконтом і високий A привів би до дисбалансу пула.

Важливо: A можна змінювати. Але зміна A повинна бути поступовою — Curve реалізує ramp_A/stop_ramp_A з мінімальним timelock 7 днів та обмеженням не більше 10x за раз. Різка зміна A при дисбалансованому пулі — по суті зміна цін активів, еквівалентна маніпуляції.

Рішення D через ітерації Ньютона

Рівняння інварианту не має аналітичного рішення для D — використовується метод Ньютона-Рафсона. Типова реалізація сходиться за 4-8 ітерацій при нормальних балансах. Проблема: при сильно дисбалансованому пулі або екстремальних значеннях ітерації можуть не сходитися.

У Solidity це виглядає як цикл з обмеженням на 255 ітерацій та перевіркою |D_new - D_prev| <= 1. Якщо не збіглося — revert. Рідкий випадок, але без нього контракт може зависнути в infinite loop при атаці зі спеціально підібраними параметрами.

Точність вичислень та PRECISION_MUL

Різні stablecoins мають різні decimals: USDC — 6, DAI — 18, USDT — 6. Всередині контракту всі балан нормалізуються до 18 decimals через PRECISION_MUL = [1e12, 1e12, 1] (для пула USDC/USDT/DAI). Забути цю нормалізацію — означає отримати арифметичну уразливість, яка дозволяє витягнути несправедливу частку активів через remove_liquidity_one_coin.

Реальний випадок: саме помилка в нормалізації decimals стала одним з векторів у кількох форках Curve, де атакуючий міг витягнути більше токенів з 18 decimals, ніж вніс токенів з 6 decimals.

Що будуємо: компоненти протоколу

Базовий пул (2-3 активи)

Контракт зберігає балан, реалізує exchange(), add_liquidity(), remove_liquidity(), remove_liquidity_one_coin(). LP-токен — ERC-20 з mintом при додаванні ліквідності. Комісія (зазвичай 0.04%) ділиться між LP та протоколом.

get_dy() (view функція розрахунку выходу) повинна реплікувати логіку exchange() з точністю до 1 wei. Якщо розбіжність існує — арбітражники використовуватимуть це.

Архітектура meta-pool

Curve використовує meta-pools для пар типу newStable/3CRV. Новий стейблкоин пулюється не з трьома активами напряму, а з LP-токеном базового 3pool. Це:

  • Зменшує фрагментацію ліквідності
  • Дає доступ до всієї ліквідності 3pool через одну торгову пару

Реалізація складніша: exchange_underlying() повинна розпакувати вкладений LP-токен в базові активи. Математика залишається тією ж, але з'являються додаткові виклики до базового пула.

Rate providers для non-pegged активів (Curve V2 / Balancer-style)

stETH/ETH не торгується рівно 1:1 — stETH накопичує yield. Потрібен rate provider: контракт, який повертає поточний обменний курс. Пул використовує rate при розрахунку інварианту, що дозволяє торгувати без slippage навіть коли активи не 1:1.

Критично важлива точка: якщо rate provider маніпулюєм (наприклад, використовує spot price з пула) — вся математика пула стає експлуатуємою. Rate provider повинен використовувати зовнішній trusted oracle або накопиченою rate (як stETH/ETH з контракту Lido), не залежний від поточних угод.

Стек та інструменти

Solidity 0.8.x для основних контрактів. Для високоточної математики використовуємо mulDiv з OpenZeppelin Math — уникаємо переповнення при проміжних обчисленнях типу a * b / c, де a * b може перевищити uint256.

Foundry для тестування: fork-тесты на Ethereum mainnet дозволяють відтворити реальні балан пулів Curve та порівняти вихід нашого контракту з оригіналом. Розбіжність >1 wei на однакових вхідних даних — червоний прапор.

Vyper (як Curve) проти Solidity: оригінальний Curve написаний на Vyper. Ми пишемо Solidity для кращої сумісності toolchain (Foundry, Slither, Hardhat-екосистема). Математика — ідентична при правильній реалізації.

Компонент Інструмент Причина
Контракти Solidity 0.8.x Сумісність toolchain
Математика OpenZeppelin Math.mulDiv Overflow-safe
Тесты Foundry + fork mainnet Порівняння з оригіналом Curve
Статичний аналіз Slither + Aderyn Виявлення арифметичних проблем
Fuzzing Echidna Інварианти D-константи

Ризики при форку Curve

Форкнути Curve — спокусливо, код відкритий. Але:

Vyper→Solidity трансляція містить пастки. У Vyper функції @view не можуть змінювати стан на рівні компілятора. У Solidity це контролює тільки модифікатор view, не завжди правильно застосований при трансляції.

Reentrancy в read-only контексті: атака read-only reentrancy на Curve (2023) дозволила маніпулювати ціною LP-токена через виклик під час remove_liquidity. Протоколи, що використовували ціну LP-токена Curve як oracle, були вразливі. Якщо ваш пул планується як oracle для інших протоколів — реалізуйте reentrancy lock на всіх state-changing функціях та окремий view-safe price feed.

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

Специфікація (1 тиждень). Визначаємо: кількість активів, потрібні rate providers, архітектура (базовий пул vs meta-pool), модель комісій, параметри governance (хто змінює A та комісії).

Розробка математичного ядра (1-2 тижні). Інваріант, метод Ньютона для D, get_y() для розрахунку виходу. Покриття тестами: порівняння з Python reference implementation Curve.

Контракти пула та LP-токена (1-2 тижні). exchange, add/remove liquidity, admin функції з timelock.

Інтеграційні тесты (1 тиждень). Fork-тесты, fuzzing інваріантів, stress testing екстремальних сценаріїв дисбалансу.

Аудит. Для пулів з реальними середствами — обов'язковий зовнішній аудит. Математика stable swap нетривіальна та містить неочевидні edge cases.

Сроки: 2-3 місяці від специфікації до готовності до аудиту. Залежить від складності архітектури (базовий пул vs meta-pool з rate providers). Вартість — після фіналізації вимог.