Розробка weighted pool (Balancer-стиль)

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

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

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

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

  • 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
    1121
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    589
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    858

Розробка weighted pool (Balancer-стиль)

Balancer V2 переосмислив AMM: замість жорсткого співвідношення 50/50 з'явилися пулы з довільними вагами активів — 80/20, 60/20/20, 33/33/34. Це відкрило новий клас завдань: on-chain управління портфелем з автоматичною ребалансировкою через арбітраж. Але реалізувати weighted pool з нуля — означає зіткнутися з математикою інваріантів, проблемою точності при великих експонентах та уразливостями маніпуляції ціною.

Математика weighted pool та де вона ломається

Інваріант Balancer та обчислення з фіксованою точкою

Weighted pool тримається на інварианті:

V = ∏(Bᵢ / Wᵢ)^Wᵢ

де Bᵢ — баланс токена i, Wᵢ — його нормалізований вага. При своп-операції система вирішує це рівняння відносно вихідного балансу. Проблема — x^y при нецілих експонентах вимагає LogExpMath, бібліотеки з фіксованою точкою для обчислення натурального логарифму та експоненти в 18-decimal Solidity.

Balancer використовує LogExpMath.sol з межами: x повинен бути у діапазоні [0.000001e18, 2^255], експонента — не перевищувати 130e18. Вихід за межі — revert. Це не просто технічна деталь: при додаванні ліквідності з екстремальними співвідношеннями (наприклад, 99% одного активу в пул 80/20) обчислення можуть упиратися в межі бібліотеки. addLiquidity ревертується при легітимних операціях.

Spot price та маніпуляція через flash loan

Spot price у weighted pool визначається як:

SP = (Bᵢ / Wᵢ) / (Bⱼ / Wⱼ)

Це миттєва ціна до застосування swap fee. Якщо протокол використовує getSpotPrice() як оракул — він уразливий до flash loan маніпуляції. Атакуючий бере величезний займ, робить своп, який зміщує spot price в 10 разів, викликає уразливу функцію, повертає займ. Все в одній транзакції.

Рішення — не використовувати spot price як ціновий оракул. Для on-chain цін потрібен Chainlink або TWAP від Uniswap V3 (IUniswapV3Pool.observe()). Всередину пулу spot price використовується тільки для розрахунку свапів — це коректно, тому що сам своп змінює балансов та зміщує ціну назад через swap fee.

Проблема джойна з неравними вагами та impermanent loss

На відміну від Uniswap V2, weighted pool дозволяє входити з довільним набором токенів або одним токеном. Single-asset join проходить через внутрішній віртуальний своп, який облагається swap fee. Це потрібно явно пояснювати користувачам: вхід через single-asset join з великою сумою — це як свап на половину суми. При вагах 80/20 ETH/USDC та вході тільки через USDC користувач неявно купує ETH.

Impermanent loss у weighted pool менший, ніж у 50/50 пулі, при тих же рухах ціни. Для пулу 80/20 при росту активу A в 5 разів IL складає близько 4.4% проти 25.5% у 50/50. Це математично доказуємо, ми додаємо в документацію графіки IL для конкретних ваг.

Як ми будуємо weighted pool

Архітектура на базі Balancer V2 Vault

Balancer V2 розділив зберігання токенів та логіку пулу. Всі токени зберігаються в одному контракті Vault, пулы — це тільки логіка обчислень. Це дає:

  • Flash loans з будь-якого токена в Vault без окремого контракту
  • Batch swaps через кілька пулів в одній транзакції
  • Єдину точку авторизації через IAuthorizer

При розробці кастомного weighted pool ми реалізуємо інтерфейс IBasePool та реєструємо пул у Vault. Ключові методи: onSwap(), onJoinPool(), onExitPool(). Логіка інварианту живе у WeightedMath.sol — ми використовуємо перевірену реалізацію Balancer, не пишемо свою математику.

Управляємі ваги (Managed Pool)

Для on-chain індексних фондів потрібна можливість менять ваги без flash loan-уразливості. Balancer вирішує це через gradual weight update: ваги лінійно інтерполюються між стартовими та кінцевими значеннями по блокам.

function _getNormalizedWeight(IERC20 token) internal view returns (uint256) {
    uint256 pctProgress = _calculateWeightChangeProgress();
    return _interpolateWeight(_startWeight[token], _endWeight[token], pctProgress);
}

Різке зміщення ваг дозволяє арбітражникам витягувати цінність за рахунок LP. Градуальне зміщення дає арбітражникам можливість торгувати по ринкових цінах, що мінімізує втрати.

Тестування на форці mainnet

Перед деплоєм гоним fork-тести через Foundry проти реального Balancer Vault на Ethereum:

forge test --fork-url $MAINNET_RPC --match-contract WeightedPoolTest -vvv

Перевіряємо: своп туда-обратно не втрачає більше swap fee + 1 wei (інваріант не порушується), single-asset join/exit коректно рахує BPT (Balancer Pool Tokens), граничні кейси LogExpMath не викликають revert при реальних об'ємах.

Стек та інтеграції

Компонент Технологія
Математика LogExpMath.sol, FixedPoint.sol (Balancer)
Тестування Foundry fork-tests, Echidna property tests
Ціннові оракули Chainlink Data Feeds, Uniswap V3 TWAP
Управління Gnosis Safe + Timelock для зміни ваг
Frontend wagmi v2, viem, Balancer SDK
Індексація The Graph (subgraph для подій пулу)

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

Аналіза (2-3 дні). Визначаємо склад пулу, ваги, swap fee, потрібна ли управляємість ваг. Рассчитуємо очікувані об'єми та IL для LP.

Проектування (3-5 днів). Вибір між форком Balancer V2 та кастомною реалізацією на базі інтерфейсів. Для більшості завдань — форк з мінімальними змінами, не винаходимо свою математику.

Розробка (1-2 тижні). Контракти пулу + адміністративні функції + інтеграція з Vault. Fuzz-тести інварианту через Echidna: властивість V_after >= V_before після будь-якої операції (крім свапів, де V змінюється коректно).

Аудит та деплой. Slither + ручний аудит математики. Деплой через forge script з верифікацією. Для пулів з TVL >$500K — зовнішній аудит обов'язковий.

Орієнтири за строками

Weighted pool на базі форку Balancer V2 з кастомними вагами — від 2 до 4 тижнів. Managed Pool з градуальним змінене ваг та governance — від 4 до 6 тижнів. Повністю кастомна математика з новим інвариантом — від 6 тижнів, плюс обов'язковий зовнішній аудит.