Skip to main content
Эта страница переведена с помощью ИИ. За эталон принимается английская версия.Открыть английскую версию →
Program ID и PDA seeds для CPMM перечислены в reference/program-addresses. На этой странице основное внимание уделяется назначению каждого аккаунта и инвариантам, которые он поддерживает, а не жёстко закодированным адресам.

Шесть аккаунтов пула CPMM

Каждый пул CPMM полностью описывается шестью адресами, производными от программы (PDA), под программой CPMM, плюс один общий аккаунт AmmConfig, на который он ссылается. Имея два mint’а, вы можете детерминированно вывести всё остальное без обращения к сети. И общая конфигурация:

Вывод пула из двух mint’ов

Всегда сортируйте mint’ы перед выводом PDA пула. Seed хеширует два mint’а в порядке байтов, а не в порядке пользователя. Два пула с (A, B) и (B, A) столкнулись бы в цепи — сортировка — это то, как программа делает отображение каноническим.
ID пула не всегда является каноническим PDA. Initialize принимает произвольную пару ключей подписанта как pool_state в дополнение к PDA выше. Если переданный аккаунт не совпадает с каноническим PDA, программа требует, чтобы он был подписантом — то есть создатель передаёт свежую пару ключей, которую они подписывают. Это защита от фронт-ранинга: любая третья сторона, пытающаяся захватить канонический PDA, может быть обойдена законным создателем, использующим вместо этого случайную пару ключей. Нижестоящие PDA (lpMint, vault0, vault1, observation) по-прежнему выводятся из poolState.key(), поэтому они остаются уникальными для любого использованного адреса. При индексировании пулов всегда обнаруживайте ID пула из состояния в цепи (например, аккаунты PoolState под программой CPMM), а не путём вывода канонического PDA — последний пропустит пулы со случайными парами ключей.

Макеты аккаунтов

Полные определения на Rust находятся в исходном коде raydium-cp-swap. Поля ниже — это те, которые вы будете читать при интеграции.

PoolState

Что на самом деле нужно читать:
  • lp_supply — внутреннее отражение пула от общего предложения LP mint. Используйте его для математики LP-доли; значение должно совпадать с предложением mint в цепи, но чтение его из PoolState избегает дополнительной выборки аккаунта.
  • protocol_fees_token{0,1}, fund_fees_token{0,1}накопленные комиссии, которые ещё не были собраны. Они не влияют на цену swap; они остаются в хранилищах до вызова CollectProtocolFee / CollectFundFee.
  • status — битовая маска, контролирующая, разрешены ли Swap, Deposit, Withdraw. Обновляется администратором через UpdatePoolStatus. SDK проверяет это перед построением транзакции; если вы CPI’ите напрямую, проверьте это сами.
  • token0_program / token1_program — программа токена для CPI в каждое хранилище. Одна может быть классическим SPL Token, а другая Token-2022; они независимы.
  • open_time — временная метка Unix. Swap’ы до этого времени не удаются. Депозиты разрешены до open_time, чтобы пул мог быть заполнен.
  • creator_fee_on / enable_creator_fee — вместе контролируют, активна ли опциональная комиссия создателя для этого пула и с какой стороны swap она собирается. enable_creator_fee == false полностью обнуляет путь комиссии создателя. Когда включено, creator_fee_on выбирает: 0 = взять комиссию с любого токена, который является входом swap (BothToken); 1 = взять комиссию только из token_0 (пропустить на swap’ах token_1 → token_0); 2 = взять комиссию только из token_1. Устанавливается при создании пула через InitializeWithPermission; не может измениться позже.
  • creator_fees_token_{0,1} — накопленные комиссии создателя, собираемые через CollectCreatorFee или CollectCreatorFeePermissionless. Оба пути обнуляют полные счётчики; путь без разрешения фиксирует получателей на канонические ATA pool_creator.

AmmConfig

Три вещи, на которые нужно обратить внимание:
  1. trade_fee_rate и creator_fee_rate — это доли объёма, обе обозначены в единицах 1/1_000_000. 2500 означает 0.25% от объёма торговли. protocol_fee_rate и fund_fee_rate — это доли торговой комиссии (не объёма), с тем же знаменателем 1/1_000_000. Комиссия создателя не является долей торговой комиссии — это её собственная независимая ставка. Полная арифметика находится в products/cpmm/fees.
  2. index — это u16, поэтому seed hash использует 2 байта big-endian. Ошибка на один в порядке байтов — частая ошибка интеграции.
  3. AmmConfig неизменяем на уровне пула. Пул указывает на один AmmConfig при создании и никогда не переключается. Изменения комиссий распространяются, потому что пул читает конфиг при каждом swap — но пул не может быть перемещён между уровнями комиссий.
Примечание о комиссиях создателя: сама ставка (creator_fee_rate) находится на AmmConfig и общая для уровня комиссии. Взимает ли конкретный пул её на самом деле (enable_creator_fee) и с какой стороны swap она приземляется (creator_fee_on) находятся на PoolState. Комиссия создателя независима от торговой комиссии — это её собственная ставка, накопленная на её собственные счётчики (creator_fees_token_{0,1}), и никогда не уменьшает доли LP / протокола / фонда торговой комиссии. Сбор осуществляется через CollectCreatorFee или ограниченный по назначению CollectCreatorFeePermissionless. Полная механика в products/cpmm/fees.

Permission

Небольшой аккаунт контроля доступа, используемый InitializeWithPermission. Программа CPMM поддерживает путь создания пула с разрешением, чтобы другие программы (например, LaunchLab при переводе токена на CPMM) могли доказать, что они имеют право создать пул для данного AmmConfig.
Permission PDA создаётся через CreatePermissionPda либо администратором CPMM, либо выделенным создателем PDA разрешений. Начиная с обновления 2026-09, ClosePermissionPda принимает тех же двух подписантов; раньше это было только для администратора. Конечные пользователи не взаимодействуют с этим аккаунтом напрямую — это сантехника для кросс-программных потоков. См. security/admin-and-multisig для границы ролей и reference/program-addresses для канонических адресов.

Хранилища и Token-2022

vault0 и vault1 принадлежат PDA authority CPMM, и их владелец token-программы (token_program) — это либо SPL Token, либо Token-2022, определяется при создании пула программой mint. Пул прозрачно обрабатывает оба случая — вы передаёте правильный ID token-программы для каждой стороны в аккаунты инструкции Swap / Deposit / Withdraw. CPMM применяет строгий список разрешённых расширений при создании пула (is_supported_mint в utils/token.rs). Mint Token-2022 может быть использован в пуле CPMM только если каждое расширение, которое он несёт, находится в этом списке:
  • TransferFeeConfig. Применяется mint при каждом переводе. Пул находится на принимающей стороне для депозитов SwapBaseInput и на отправляющей стороне для снятий. Программа вычисляет чистое количество, попадающее в хранилище, и устанавливает кривую соответственно. См. algorithms/token-2022-transfer-fees.
  • MetadataPointer и TokenMetadata. Стандартные метаданные на mint. Никакого влияния на математику swap.
  • InterestBearingConfig. UI-количество mint начисляет проценты. Хранилище хранит сырые количества; кривая работает только с сырыми количествами. UI, которые показывают APR, должны вызывать помощники Token-2022 для отображения UI-количества.
  • ScaledUiAmount. Расширение масштабирования UI-отображения. Такая же обработка, как InterestBearingConfig — кривая использует сырые количества.
Любое другое расширение — PermanentDelegate, TransferHook, DefaultAccountState, NonTransferable, ConfidentialTransfer, Group/GroupMember, MintCloseAuthority и т. д. — вызывает отклонение Initialize с NotSupportMint. Единственное исключение — реестр для каждого mint: если PDA SupportMintAssociated существует с seed [b"support_mint", mint], mint допускается независимо от его набора расширений. Этот PDA создаётся и удаляется администратором (или выделенным органом поддержки mint) через CreateSupportMintAssociated / CloseSupportMintAssociated, поэтому подключение конкретного mint больше не требует обновления программы.
Изменено в 2026-09. CPMM ранее также содержал жёстко закодированный четырёхадресный MINT_WHITELIST, который обходил проверку расширений. Этот массив был удалён; реестр PDA теперь является единственным обходом. Любой mint, который полагался на жёстко закодированный список, нуждается в PDA SupportMintAssociated перед созданием нового пула для него — существующие пулы не затронуты, потому что проверка выполняется только при создании пула.
Список проверенных расширений находится в исходном коде CP-Swap в programs/cp-swap/src/utils/token.rs и может измениться при будущих обновлениях программы. См. reference/token-2022-support для матрицы кросс-программ.

Observation

Аккаунт observation — это кольцевой буфер записей ObservationState, каждая хранит block_timestamp и кумулятивную цену. При каждом swap программа добавляет новое наблюдение, если прошло достаточно времени с момента последнего. TWAP вычисляются путём чтения двух наблюдений и деления Δcumulative / Δtime.
Кольцевой буфер рассчитан на 100 наблюдений. Каждое наблюдение занимает 40 байт, поэтому сам массив занимает 4000 байт; полный PDA ObservationState составляет около 4100 байт после окружающих полей и дискриминатора. Два правила для потребителей:
  • Не используйте одно наблюдение как цену. Это кумулятив, а не спот-цена. Используйте два из них для вычисления TWAP.
  • Выбирайте наблюдения, разделённые как минимум одним блоком. Swap’ы в одном блоке могут не создать новое наблюдение; чтение подряд может вернуть одну и ту же запись.
Больше математики в products/clmm/accounts.

Жизненный цикл аккаунта

Пулы CPMM и их PDA никогда не закрываются. Даже при нулевой ликвидности poolState остаётся. Это намеренно: повторное заполнение того же пула позже сохраняет его исторический буфер наблюдений и его вывод PDA остаётся стабильным.

Что читать где

  • Списки аккаунтов инструкций (какие из вышеперечисленных являются writable/signer для каждой инструкции): products/cpmm/instructions.
  • Семантика начисления комиссий: products/cpmm/fees.
  • Математика swap / правило обновления наблюдений: products/cpmm/math.
  • Канонические seeds / program IDs: reference/program-addresses.
Источники: