Documentation Index
Fetch the complete documentation index at: https://docs.raydium.io/llms.txt
Use this file to discover all available pages before exploring further.
Эта страница переведена с помощью ИИ. За эталон принимается английская версия.Открыть английскую версию →
Инвариант
CPMM поддерживает классический инвариант константного произведения на двух своих хранилищах: гдеx — это баланс vault0 после всех комиссий передачи Token-2022 при получении, и аналогично для y. Каждый свап должен оставить k' ≥ k после учёта торговых комиссий, зачисленных LP (протокол, фонд и комиссии создателя не учитываются при расчёте k — они находятся в хранилище, но исключаются из представления кривой, см. Комиссии на кривой ниже). Таким образом, k монотонно растёт с течением времени по мере начисления комиссий LP.
Цена LP-доли определяется резервами пула, а не k:
Сжигание ΔLP LP-токенов возвращает ровно ΔLP × x / lpSupply token0 и ΔLP × y / lpSupply token1. При депозите или выводе ни кривая, ни k не движутся — цена меняется только при свопах.
Модель комиссий на пути свопа
CPMM применяет две независимо установленные комиссии на каждом свопе:- Торговая комиссия берётся на входе с коэффициентом
AmmConfig.trade_fee_rate. Затем она разделяется на доли LP, протокола и фонда (доля LP остаётся в хранилище и увеличиваетk; доли протокола и фонда извлекаются из учёта хранилища). - Комиссия создателя (активна только когда
enable_creator_fee == true) берётся с коэффициентомAmmConfig.creator_fee_rate. Она берётся на входе или выходе в зависимости отPoolState.creator_fee_onи направления свопа (см./ru/products/cpmm/fees#с-какой-стороны-торговли-берутся-комиссии). Это отдельная корзина — никогда не доля торговой комиссии.
FEE_RATE_DENOMINATOR = 1_000_000trade_fee_rate— изAmmConfig, например2500= 0,25% от соответствующего объёмаcreator_fee_rate— изAmmConfig, например1000= 0,10% от соответствующего объёмаprotocol_fee_rate,fund_fee_rate— в единицах1/FEE_RATE_DENOMINATORторговой комиссии, а не объёма
protocol_fee + fund_fee + creator_fee хранится в хранилищах, но отслеживается отдельно в состоянии пула (protocol_fees_token*, fund_fees_token*, creator_fees_token*). Когда проверка инварианта константного произведения проверяет k' ≥ k, она использует балансы хранилища минус все три накопленные, но неизвлечённые комиссии — таким образом LP захватывают только lp_fee.
См. /ru/products/cpmm/fees для инструкций по сбору и выполненных численных примеров.
SwapBaseInput (вход точен)
“Пользователь дает нам ровноamount_in входного токена и получает как минимум minimum_amount_out выходного токена.”
Пока игнорируем Token-2022:
Δx_net = amount_in_after_trade_fee.
Затем программа обновляет учет хранилища так, чтобы часть trade_fee, полагающаяся протоколу/фонду/создателю, находилась в корзинах “накопленных” комиссий (не включаются в следующее x кривой), тогда как доля LP присоединяется к x для следующего свопа.
Token-2022 на входе
Если входной токен имеет расширение transfer-fee, монета вычитает свою комиссию при передаче от пользователя → хранилище. Поэтому хранилище фактически получаетamount_in − transfer_fee_in(amount_in). Программа CPMM поэтому вычисляет:
amount_in_after_trade_fee. Это важно, потому что цена кривой вычисляется исходя из чистой суммы, поступившей в хранилище, а не из объявленной суммы пользователя.
Token-2022 на выходе
Если выходной токен имеет комиссию передачи, пул отправляетamount_out из своего хранилища пользователю. Монета затем снимает свою комиссию в пути, поэтому пользователь получает amount_out − transfer_fee_out(amount_out). Программа вычисляет amount_out из кривой как обычно, но задача интегратора — преобразовать число “отправка из хранилища” пула в число “получение пользователем” при показе котировок.
Проверка скольжения
После вычисленияamount_out:
minimum_amount_out, так чтобы константа скольжения была номинирована в том, что пользователь фактически получит, а не в том, что отправит хранилище.
SwapBaseOutput (выход точен)
“Пользователь получит ровноamount_out выходного токена и готов заплатить до maximum_amount_in входного токена.”
Инвертируя кривую для Δx_net:
Потолок важен — он гарантирует k' ≥ k после целочисленного усечения. Затем:
gross_needed.
Проверка скольжения
Выполненный пример
Состояние пула, игнорируя Token-2022:x = 1_000_000_000_000(1 000 000,000000 token0, 6 знаков)y = 2_000_000_000_000(2 000 000,000000 token1, 6 знаков)AmmConfig:trade_fee_rate = 2500,protocol_fee_rate = 120_000,fund_fee_rate = 40_000,creator_fee_rate = 0
SwapBaseInput с amount_in = 1_000_000_000 (1 000,000000 token0). Комиссия создателя отключена (enable_creator_fee = false).
enable_creator_fee = true с creator_fee_rate = 1000 (0,10%) на входе, программа взимала бы total_input_fee = ceil(1_000_000_000 * 3500 / 1_000_000) = 3_500_000, затем разделила бы это как creator_fee = 1_000_000 и trade_fee = 2_500_000. Арифметика протокол/фонд/LP на trade_fee не изменяется по сравнению с примером выше — комиссия создателя — это отдельная корзина, накопленная в creator_fees_token0 и исключённая из curve_x вместе с корзинами протокола и фонда.
Если входной токен имеет комиссию передачи Token-2022 в размере 1%, хранилище получает 990_000_000 токенов вместо 1_000_000_000, и все последующие вычисления используют эту чистую сумму.
Правило обновления наблюдений
При каждом свопе программа оценивает, нужно ли добавить новое наблюдение в кольцевой буфер:- Кумулятивная цена, не спотовая цена. Одно наблюдение — это не цена. Чтобы получить TWAP за период от
t0доt1, прочитайте наблюдения, ближайшие к каждому концу, и вычислите(cumulative(t1) − cumulative(t0)) / (t1 − t0). - Образцы ограничены по частоте. Последовательные свопы в одном слоте могут делить одно наблюдение. Чтение наблюдения сразу после свопа может поэтому выглядеть устаревшим на один слот — это нормально.
/ru/products/clmm/accounts.
Комиссии на кривой
Это тонкая часть, стоящая того, чтобы её выделить. Арифметика кривой работает с чистыми балансами хранилища — то есть с опубликованным балансом SPL минус накопленные комиссии протокола, фонда и создателя (все три — независимые корзины — см./ru/products/cpmm/fees). Конкретная картина:
- Не котируйте из сырых балансов. Сначала вычтите поля накопленных комиссий, или вызовите
SwapBaseInputкак имитацию и возьмите его результат. CollectProtocolFeeперемещает токены из хранилища. После сбораraw_vault_balanceпадает, ноcurve_balanceостаётся неизменным; цена пула не движется. Это намеренно.
Точность и переполнение
- Вся арифметика кривой использует промежуточные значения
u128для предотвращения переполнения приx * y. - Деление округляется к нулю, за исключением
SwapBaseOutput’sΔx_net, который округляется вверх, и вычисления комиссии, которое округляется вверх наtrade_feeи вниз на подразделения. Эти направления округления выбраны так, чтобы инвариант никогда не уменьшался из-за целочисленного усечения. - Пулы с экстремальными соотношениями хранилищ (миллиарды : 1) могут попадать в полы точности при малых торговлях; программа возвращает
ZeroTradingTokensв этом случае. См./ru/reference/error-codes.
Куда дальше
/ru/products/cpmm/fees— полная семантика уровней комиссий и сбора./ru/products/cpmm/instructions— инструкции, которые вызывают эту математику./ru/algorithms/constant-product— вывод и граничные случаиx · y = k, общие для AMM v4 и CPMM.
raydium-io/raydium-cp-swap— математика свопа вstates/curve.rs- Отчёты аудитов Raydium, на которые указано в
/ru/security/audits


