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

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Разработка weighted pool (Balancer-стиль)
Сложная
~1-2 недели
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1221
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1163
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    855
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1060
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    828

Разработка 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 для смены весов
Фронтенд 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 недель, плюс обязательный внешний аудит.