Эта страница переведена с помощью ИИ. За эталон принимается английская версия.Открыть английскую версию →
Эта страница — авторитетный справочник инструкций. Для кода, который фактически составляет эти инструкции, см.
products/cpmm/code-demos. Для значений кодов ошибок см. reference/error-codes.Обновление программы 2026-09 переписало CPMM на Anchor 1.0.2 / Solana 3.1.10, добавило админ-инструкцию CollectExcessLamports, удалило жёстко закодированный список разрешённых минтов Token-2022 и изменило, что CreateAmmConfig записывает в protocol_owner / fund_owner. Ни одна пользовательская инструкция не изменила свои счёты, аргументы или математику. См. запись в журнале изменений от 2026-09-09.Сводка инструкций
Битовая маска статуса:
status каждого пула — это u8, где бит 0 = депозит отключен, бит 1 = вывод отключен, бит 2 = своп отключен (PoolStatusBitIndex { Deposit, Withdraw, Swap } в программе). Очищенный бит означает, что операция разрешена; установленный бит означает, что она приостановлена. UpdatePoolStatus принимает сырой u8 и перезаписывает существующее значение.
Следующие разделы подробно рассматривают каждую инструкцию. Порядок счётов соответствует IDL CPMM; SDK и Rust-клиент в raydium-cp-swap/programs/cp-swap/src/instructions соответствуют этому порядку.
Initialize
Создать новый пул CPMM.
Аргументы
* pool_state подписывает только на пути со случайной парой ключей; путь с каноническим PDA работает без подписи pool_state.
Предусловия
- Минты отсортированы (
token_0_mint < token_1_mintпо порядку байтов). - Ни один минт не использует расширение вне списка разрешений CPMM (
TransferFeeConfig,MetadataPointer,TokenMetadata,InterestBearingConfig,ScaledUiAmount) — см.products/cpmm/accounts. Минт, для которого существует PDASupportMintAssociated(seed[b"support_mint", mint]), пропускает проверку расширения — но вы должны добавить этот PDA вremaining_accounts. Программа сканирует только переданные вами счёты и никогда не загружает PDA самостоятельно, поэтому полагаться на реестр без предоставления счёта всё равно не удаётся сNotSupportMint(6007). Порядок не имеет значения (сопоставление по ключу); передайте одну запись на минт, которому нужен обход. Этот реестр — единственный обход с тех пор, как обновление 2026-09 удалило жёстко закодированный список четырёх минтов. creatorимеет по крайней мереinit_amount_0иinit_amount_1в соответствующих ATA.amm_config.disable_create_pool == false.
pool_state.lp_supply = sqrt(init_amount_0 * init_amount_1)— полный квадратный корень. Создателю выдаётсяlp_supply − 100; 100 заблокированных базовых единиц учитываются вlp_supply, но никогда не выпускаются.- Таким образом,
lp_mint.supply == pool_state.lp_supply − 100на протяжении всей жизни пула. Вся математика LP-доли (депозит, вывод) делится наlp_supply, поэтому используйте это поле и не подставляйте предложение минта в цепи. ВозвращаетInitLpAmountTooLess, еслиsqrt(...) < 100. observation_stateинициализируется;observation_index = 0иpool_id = pool_state.key().- Лампорты
create_pool_feeпередаются от создателя получателю и синхронизируются как нативный SOL (это ATA wSOL). - Битовая маска статуса пула —
0(депозит / вывод / своп все включены). enable_creator_fee = falseиcreator_fee_on = BothToken.Initializeне поддерживает включение комиссии создателя — этот путь —InitializeWithPermission.open_timeувеличивается доblock_timestamp + 1, если вызывающий передал значение<= block_timestamp. Своп отклоняется доopen_time; депозиты и выводы работают немедленно.
reference/error-codes)
InvalidInput— минты не отсортированы или идентичны.NotSupportMint— заблокировано расширение Token-2022.ExceededSlippage— редко; еслиinit_amount_0/1приводят к нулевому LP из-за несовпадения десятичных знаков.
Deposit
Добавить ликвидность в оба токена пропорционально пулу.
Аргументы
Математика
vault_amount_without_fee, т.е. сырой баланс минус накопленные счётчики протокола, фонда и создателя), а не сырой баланс хранилища; и крышка проскальзывания проверяется против того, что плательщик фактически передаёт, после добавления комиссии передачи Token-2022, а не против валового движения хранилища.
Нет изменения пропорциональности k — обе суммы и lp_supply масштабируются на один и тот же коэффициент.
Постусловия
lp_supply += lp_token_amount.vault_0 += needed_token_0(за вычетом любой комиссии передачи Token-2022 на входе).vault_1 += needed_token_1(за вычетом любой комиссии передачи Token-2022 на входе).
ExceededSlippage, ZeroTradingTokens, InvalidStatus, если депозит приостановлен.
Withdraw
Сжечь LP-токены и получить оба базовых токена пропорционально.
Аргументы
Первые 13 счётов идентичны
Deposit, и lp_mint записываемый, потому что LP-токены сжигаются. Withdraw дополнительно принимает 14-й счёт, memo_program (ограничение address = memo::ID) — Deposit не принимает. Withdraw с 13 счётами не проходит десериализацию Anchor, поэтому LP не может выйти.
Математика
lp_supply -= lp_token_amount.- Хранилища отправляют
out_token_0/out_token_1(валовой; пользователь получает за вычетом любой комиссии передачи Token-2022).
SwapBaseInput
Своп с точным входом.
Аргументы
Порядок вход → выход определяется направлением пользователя, а не каноническим
token_0 / token_1 пула. Программа определяет, какое хранилище какое, сопоставляя минты.
Математика — см. products/cpmm/math.
Предусловия
open_time <= now.pool_statusразрешает своп.- Ни один минт не приостановлен или заморожен для этого органа власти.
amount_in > 0.
ExceededSlippage—amount_out < minimum_amount_out.ZeroTradingTokens— сделка округляется до нуля.NotApproved— пул приостановлен для своп черезUpdatePoolStatus.InvalidInput— минты не совпадают ни с одним из минтов хранилища пула.
SwapBaseOutput
Своп с точным выходом.
Аргументы
SwapBaseInput.
Математика — обратная кривая с потолком, см. products/cpmm/math.
Распространённые ошибки — ExceededSlippage (gross_in > max_amount_in), ZeroTradingTokens, InvalidInput, NotApproved.
CollectProtocolFee
Собрать накопленные комиссии протокола из хранилищ на целевой адрес протокола.
Аргументы — нет.
Счёты
Эффект
InvalidOwner (6001), если подписывающий ни amm_config.protocol_owner, ни админ программы. (На этом пути нет NotApproved.)
CollectFundFee
Та же форма, что CollectProtocolFee, но подписана amm_config.fund_owner — или, опять же, админом программы — и обнуляет счётчики fund_fees_*. Та же InvalidOwner при неправильном подписывающем.
CollectCreatorFee
Подписана pool_state.pool_creator. Она рассчитывает накопленную комиссию создателя и передаёт часть создателя на токен-счёты создателя.
Аргументы — нет.
Счёты
Эффект
CollectProtocolFee. Оба счётчика уже исключены из представления кривой о хранилище, поэтому цена пула не движется. Полный вывод в products/cpmm/fees.
Распространённые ошибки — NoFeeCollect, когда оба счётчика создателя равны нулю (проверяется перед разделением), InvalidInput (6003), если разрешённый share_rate превышает 1_000_000, MathOverflow (6011), если бронирование доли переполнит protocol_fees_token_*, и ошибка Anchor ConstraintSeeds, если creator_fee_share не является каноническим PDA.
CollectCreatorFeePermissionless
Кто угодно может запустить сбор комиссии создателя. Инструкция всегда отправляет часть создателя на канонические связанные токен-счёты, принадлежащие pool_state.pool_creator; вызывающий не может выбрать другого создателя или целевой адрес. Если какой-либо ATA отсутствует, плательщик финансирует его создание.
Оригинальный CollectCreatorFee остаётся вызываемым, поэтому создатель, который хочет подписать для своего собственного сбора, всё ещё может.
Аргументы — нет.
Счёты
Эффект — идентичен
CollectCreatorFee выше: доля разрешается из creator_fee_share или amm_config, часть протокола учитывается в protocol_fees_token_{0,1}, часть создателя передаётся на ATA создателя, оба счётчика создателя обнуляются и recent_epoch обновляется. Возвращает NoFeeCollect, когда оба счётчика равны нулю.
UpdatePoolStatus
Приостановить или возобновить отдельные операции на пуле. Поле status — это битовая маска:
Аргументы
Ключ админа — это публичный ключ, скомпилированный в программу (
crate::admin::ID), а не орган власти обновления BPF — изменение его требует обновления программы. См. reference/program-addresses для значения и security/admin-and-multisig для того, кто его держит.
CreateAmmConfig
Создать новый уровень комиссий.
Аргументы
Предусловия
- Нет существующего
AmmConfigс тем жеindex. protocol_fee_rate + fund_fee_rate <= FEE_RATE_DENOMINATOR_VALUE.
Изменено в 2026-09: владельцы комиссий нового конфига больше не берутся из подписывающего.
create_amm_config теперь записывает жёстко закодированный protocol_fee_owner::ID программы в protocol_owner и fund_fee_owner::ID в fund_owner, вместо копирования ключа подписывающего админа в оба. Адреса находятся в reference/program-addresses.Последствия: комиссии на вновь созданном AmmConfig попадают в выделенные кошельки комиссий, а не в кошелёк админа. Админ остаётся принятым подписывающим для сбора — CollectProtocolFee / CollectFundFee принимают amm_config.protocol_owner / fund_owner или crate::admin::ID — поэтому ничего не нужно ротировать для сбора; что изменилось, это только то, куда по умолчанию идут доходы. Существующие счёты AmmConfig не переписываются — всё, что на них хранится, всё ещё управляет, поэтому всегда читайте protocol_owner / fund_owner со счёта вместо предположения любого значения. Параметры UpdateAmmConfig 3 и 4 всё ещё их ротируют.UpdateAmmConfig
Изменить ставки комиссий или владение на существующем AmmConfig. Принимает param: u8 (какое поле обновить) и value: u64. Полная таблица диспетчеризации:
param = 0→trade_fee_rate(утверждаетtrade_fee_rate + creator_fee_rate < 1_000_000)param = 1→protocol_fee_rate(утверждает≤ 1_000_000и+ fund_fee_rate ≤ 1_000_000)param = 2→fund_fee_rate(утверждает≤ 1_000_000и+ protocol_fee_rate ≤ 1_000_000)param = 3→protocol_owner. Новый ключ не вvalue: добавьте его какremaining_accounts[0](только для чтения в порядке). Он не должен быть ключом по умолчанию, и пропуск счёта паникует наunwrap().param = 4→fund_owner. Тот же механизм, что3.param = 5→create_pool_feeparam = 6→disable_create_pool(любое ненулевоеvalueотключает)param = 7→creator_fee_rate(утверждаетcreator_fee_rate + trade_fee_rate < 1_000_000)param = 8→creator_fee_share_rate(утверждает≤ 1_000_000). Добавлено 2026-09-19. Доля протокола по умолчанию комиссии создателя на этом уровне; см.products/cpmm/fees. Это не связано сprotocol_fee_rate, который разделяет комиссию торговли.
param возвращает InvalidInput.
Изменения подписаны админом и влияют на каждый пул, привязанный к этому AmmConfig при следующем своп. Нет миграции; пулы просто читают новые значения.
CreateCreatorFeeShare
Установить пользовательскую долю протокола комиссии создателя для одной пары (creator, amm_config), переопределяя AmmConfig.creator_fee_share_rate для каждого пула, который этот создатель владеет на этом уровне комиссий. Добавлено в обновление creator-fee-share 2026-09-19.
Аргументы
Предусловия
share_rate <= 1_000_000, иначеInvalidInput(6003).- PDA не должен уже существовать — Anchor
initне проходит при втором вызове для одной пары. Чтобы изменить ставку, закройте счёт и создайте его снова.
creator_fee_shareхранитbump,creator,amm_configиshare_rate.- Каждый последующий
CollectCreatorFee/CollectCreatorFeePermissionlessна пуле, созданномcreatorподamm_config, разрешает долю из этого счёта вместо конфига.
Создатель пула не является стороной этой инструкции и не подписывает её. Ставка читается во время сбора, поэтому переопределение, созданное после того, как комиссии уже накопились, применяется к этому накопленному балансу тоже.
CloseCreatorFeeShare
Удалить переопределение. Пара возвращается к AmmConfig.creator_fee_share_rate.
Аргументы — нет.
Счёты
Постусловия
- Счёт закрыт и его лампорты идут на
owner. - Сборы для этой пары разрешают долю из
amm_config.creator_fee_share_rateснова — что0, если админ не установилUpdateAmmConfigparam8.
CollectExcessLamports
Админ-сбор лампортов, сидящих выше минимума для освобождения от аренды на счётах, контролируемых CPMM. Добавлено в обновление 2026-09, чтобы протокол мог вернуть избыточное финансирование, которое SIMD-0437 rent reduction оставляет на счётах, созданных до каждого шага.
Движется только избыток. Балансы токенов, данные счёта, владельцы, состояние пула и кривая не трогаются, и инструкция — это no-op для счёта, уже находящегося на минимуме — поэтому безопасно переиспользовать после каждого развёртывания шага.
Аргументы — нет.
Счёты
Исправление порядка, 2026-09-19. Программа теперь делает два прохода по
remaining_accounts — каждый CPI токен-программы сначала, затем прямые дебеты CPMM-управляемых PDA. Чередование их прерывалось с UnbalancedInstruction рантайма (“сумма балансов счётов до и после инструкции не совпадают”) всякий раз, когда PDA дебетовался перед CPI, потому что ожидающие изменения лампортов вызывающего только сбрасываются в счёта, которые CPI фактически несёт. Вызывающие не должны группировать или сортировать список сами.owner исходного счёта:
Потому что он принимает неограниченный список
remaining_accounts, размер транзакции — это реальный лимит — то же ограничение, что и сбор со стороны кошелька, описанный в solana-fundamentals/rent-and-reclaimable-rent.
Распространённые ошибки — InvalidOwner (6001, неправильный подписывающий), LamportsCalculateError (6015, wSOL round-trip не нетировал до нуля) и InsufficientFunds из пути, управляемого программой, когда счёт держит меньше, чем его собственный минимум аренды.
Нет SDK-построителя. @raydium-io/raydium-sdk-v2 не поставляет построитель для этой инструкции, и ни raydium-sdk-V2-demo репо — это админ-путь. Кодируйте вручную, как сбор со стороны кошелька в solana-fundamentals/rent-and-reclaimable-rent делает для инструкции токен-программы.
Матрица изменения состояния
Куда дальше
products/cpmm/code-demos— запускаемые примеры TypeScript для вышеперечисленного.reference/error-codes— полная таблица ошибок Anchor.products/cpmm/fees— модель накопления комиссий, которую инструкцииCollect*Feeосушают.

