Skip to main content
이 페이지는 AI 자동 번역입니다. 모든 내용은 영문판을 기준으로 합니다.영문판 보기 →
CPMM의 프로그램 ID와 PDA 시드는 reference/program-addresses에 정식으로 나열되어 있습니다. 이 페이지는 각 계정의 용도와 유지되는 불변성에 중점을 두며, 하드코딩된 주소는 다루지 않습니다.

CPMM 풀의 6개 계정

모든 CPMM 풀은 CPMM 프로그램 아래의 6개 프로그램 파생 주소(PDA)와 이를 참조하는 1개의 공유 AmmConfig 계정으로 완전히 설명됩니다. 두 개의 mint만 있으면 네트워크에 접근하지 않고도 모든 것을 결정론적으로 파생할 수 있습니다. 그리고 공유 설정: 그리고 생성자당 선택적 계정:

두 개의 mint만으로 풀 파생하기

풀 PDA를 파생하기 전에 항상 mint를 정렬하세요. 시드는 사용자 순서가 아닌 바이트 순서로 두 mint를 해시합니다. (A, B)와 (B, A)를 가진 두 풀은 온체인에서 충돌할 것입니다 — 정렬은 프로그램이 매핑을 정식으로 만드는 방법입니다.
풀 ID가 항상 정식 PDA는 아닙니다. Initialize는 위의 PDA 외에도 pool_state로 임의의 서명자 keypair를 허용합니다. 전달된 계정이 정식 PDA와 일치하지 않으면 프로그램은 이를 서명자로 요구합니다 — 즉, 생성자가 자신이 서명한 새로운 keypair를 전달합니다. 이것이 프론트런 방어입니다: 정식 PDA를 차지하려고 경쟁하는 제3자는 정당한 생성자가 대신 임의의 keypair를 사용하여 우회할 수 있습니다. 다운스트림 PDA(lpMint, vault0, vault1, observation)는 여전히 poolState.key()에서 파생되므로 사용된 주소에 관계없이 고유합니다. 풀을 인덱싱할 때 정식 PDA를 파생하여 풀 ID를 발견하지 말고 온체인 상태에서 발견하세요 (예: CPMM 프로그램 아래의 PoolState 계정) — 후자는 임의 keypair 풀을 놓칠 것입니다.

계정 레이아웃

전체 Rust 정의는 raydium-cp-swap 소스에 있습니다. 아래 필드는 통합에서 읽을 필드입니다.

PoolState

실제로 읽을 내용:
  • lp_supply — 풀의 내부 LP 총액입니다. LP mint의 공급량과 같지 않습니다: 정확히 100 기본 단위 더 높습니다. 100개의 잠금 단위가 여기서 계산되지만 절대 mint되지 않기 때문입니다. 모든 LP 공유 수학(예치, 인출)은 lp_supply로 나누므로 이 필드를 사용하고 mint의 온체인 공급량을 대체하지 마세요.
  • protocol_fees_token{0,1}, fund_fees_token{0,1} — 아직 수집되지 않은 누적된 수수료입니다. 이들은 스왑 가격에 영향을 주지 않습니다; CollectProtocolFee / CollectFundFee가 호출될 때까지 vault에 있습니다. protocol_fees_token{0,1}은 생성자 수수료가 수집될 때 생성자 수수료의 프로토콜 공유도 받으므로 스왑 외부에서 증가합니다 — products/cpmm/fees를 참조하세요.
  • status — Swap, Deposit, Withdraw이 허용되는지 제어하는 비트마스크입니다. UpdatePoolStatus를 통해 관리자가 업데이트합니다. SDK는 트랜잭션을 구축하기 전에 이를 확인합니다; CPI를 직접 수행하는 경우 직접 확인하세요.
  • token0_program / token1_program — 각 vault에 대해 CPI할 토큰 프로그램입니다. 하나는 클래식 SPL Token이고 다른 하나는 Token-2022일 수 있습니다; 이들은 독립적입니다.
  • open_time — Unix 타임스탬프입니다. 이 시간 이전의 스왑은 실패합니다. 예치는 open_time 이전에 허용되므로 풀을 시드할 수 있습니다.
  • creator_fee_on / enable_creator_fee — 함께 선택적 생성자 수수료가 이 풀에 대해 활성화되는지 여부와 스왑의 어느 쪽에서 수집되는지를 제어합니다. enable_creator_fee == false는 생성자 수수료 경로를 완전히 0으로 만듭니다. 활성화되면 creator_fee_on은 다음을 선택합니다: 0 = 스왑 입력이 무엇이든 그 토큰에서 수수료를 가져옵니다 (BothToken); 1 = token_0에서만 수수료를 가져옵니다 (token_1 → token_0 스왑에서 건너뜀); 2 = token_1에서만 수수료를 가져옵니다. InitializeWithPermission을 통해 풀 생성 시 설정됩니다; 나중에 변경할 수 없습니다.
  • creator_fees_token_{0,1} — 누적된 생성자 수수료이며, CollectCreatorFee 또는 CollectCreatorFeePermissionless로 수집됩니다. 두 경로 모두 전체 카운터를 0으로 만들지만, 2026-09-19 생성자 수수료 공유 업그레이드 이후로는 잔액의 일부만 풀을 떠납니다: 프로토콜의 공유는 protocol_fees_token_{0,1}에 추가되고 나머지는 생성자에게 전송됩니다. 권한 없는 경로는 수신자를 pool_creator의 정식 ATA로 고정합니다. PoolState 자체는 변경되지 않았습니다 — 공유 금액에 대한 별도의 카운터가 없습니다.

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**이므로 시드 해시는 2바이트 빅엔디안을 사용합니다. 바이트 순서의 오프바이원은 일반적인 통합 버그입니다.
  3. AmmConfig는 풀 수준에서 불변입니다. 풀은 생성 시 하나의 AmmConfig를 가리키고 절대 전환하지 않습니다. 수수료 변경은 풀이 각 스왑에서 설정을 읽기 때문에 전파됩니다 — 하지만 풀은 수수료 계층 간에 이동할 수 없습니다.
생성자 수수료에 대한 참고: 비율 자체 (creator_fee_rate)는 AmmConfig에 있고 수수료 계층 전체에서 공유됩니다. 특정 풀이 실제로 이를 청구하는지 여부 (enable_creator_fee)와 스왑의 어느 쪽에 착지하는지 (creator_fee_on)는 PoolState에 있습니다. 생성자 수수료는 거래 수수료와 독립적입니다 — 이는 자체 비율이며, 자체 카운터 (creator_fees_token_{0,1})에 누적되며, LP / 프로토콜 / 펀드 거래 수수료 공유를 절대 줄이지 않습니다. 수집은 CollectCreatorFee 또는 대상 제약 CollectCreatorFeePermissionless를 통해 이루어지며, 두 경로 모두 나가는 길에 누적 잔액의 공유를 프로토콜에 전달합니다 — creator_fee_share_rate에서, 또는 해당 (creator, amm_config) 쌍에 대해 CreatorFeeShare PDA가 존재할 때 그 비율에서입니다. 전체 메커니즘은 products/cpmm/fees를 참조하세요.

Permission

InitializeWithPermission에서 사용되는 작은 접근 제어 계정입니다. CPMM 프로그램은 다른 프로그램 (예: LaunchLab이 토큰을 CPMM으로 졸업할 때)이 주어진 AmmConfig에 대해 풀을 생성할 자격이 있음을 증명할 수 있도록 권한이 있는 풀 생성 경로를 지원합니다.
Permission PDA는 CPMM 관리자 또는 전용 permission-PDA 생성자 권한에 의해 CreatePermissionPda를 통해 생성됩니다. 2026-09 업그레이드 이후 ClosePermissionPda는 동일한 두 서명자를 허용합니다; 이전에는 관리자 전용이었습니다. 최종 사용자는 이 계정과 직접 상호작용하지 않습니다 — 이는 크로스 프로그램 흐름을 위한 배관입니다. 역할 경계는 security/admin-and-multisig를 참조하고 정식 주소는 reference/program-addresses를 참조하세요.

CreatorFeeShare

한 (풀 생성자, AmmConfig) 쌍에 대해 프로토콜의 생성자 수수료 공유를 재정의하는 선택적 계정입니다. 2026-09-19 생성자 수수료 공유 업그레이드에서 추가되었습니다.
동작 방식:
  • 선택사항이지만 계정은 명령어에서 절대 선택사항이 아닙니다. CollectCreatorFee와 CollectCreatorFeePermissionless 모두 위의 시드 제약으로 creator_fee_share를 선언하고 모든 호출에서 이를 가져옵니다. 그러면 프로그램은 계정이 비어 있거나 외부 소유인지 확인합니다; 그렇다면 AmmConfig.creator_fee_share_rate로 폴백합니다. 따라서 클라이언트는 계정이 존재하는지 여부에 관계없이 항상 주소를 파생하고 전달해야 합니다.
  • share_rate는 생성 시 FEE_RATE_DENOMINATOR_VALUE (1_000_000)로 제한되며, 분할이 실행될 때 다시 제한됩니다. 1_000_000은 전체 생성자 수수료를 프로토콜로 라우팅합니다; 0은 아무것도 라우팅하지 않습니다.
  • 관리자 또는 전용 권한에 의해 생성 및 종료됩니다 CreateCreatorFeeShare / CloseCreatorFeeShare를 통해. 이를 종료하면 임차료가 서명자에게 반환되고 쌍이 설정 기본값으로 폴백됩니다; 풀 생성자는 두 경로 모두에서 서명자가 아닙니다.
  • 풀이 아닌 생성자로 키가 지정됩니다. 하나의 계정이 해당 생성자가 해당 AmmConfig에서 가진 모든 풀을 관리합니다. 두 수수료 계층에 풀이 있는 생성자는 두 계정이 필요하여 둘 다 적용됩니다.
이를 구동하는 분할 산술은 products/cpmm/fees에 있습니다.

Vault 및 Token-2022

vault0과 vault1은 CPMM authority PDA가 소유하며, 이들의 토큰 프로그램 소유자 (token_program)는 SPL Token 또는 Token-2022이며, 풀 생성 시 mint의 프로그램에 의해 결정됩니다. 풀은 두 경우를 투명하게 처리합니다 — Swap / Deposit / Withdraw 명령어 계정에서 각 쪽에 대해 올바른 토큰 프로그램 ID를 전달합니다. CPMM은 풀 생성 시 엄격한 확장 허용 목록을 적용합니다 (utils/token.rs의 is_supported_mint). Token-2022 mint는 모든 확장이 이 목록에 있는 경우에만 CPMM 풀에서 사용할 수 있습니다:
  • TransferFeeConfig. 모든 전송에서 mint에 의해 적용됩니다. 풀은 SwapBaseInput 예치의 수신 쪽이고 인출의 송신 쪽입니다. 프로그램은 vault에 착지하는 순 금액을 계산하고 곡선을 그에 따라 설정합니다. algorithms/token-2022-transfer-fees를 참조하세요.
  • MetadataPointer 및 TokenMetadata. 표준 온민트 메타데이터입니다. 스왑 수학에 영향을 주지 않습니다.
  • InterestBearingConfig. mint의 UI 금액이 이자를 누적합니다. vault는 원시 금액을 저장합니다; 곡선은 원시 금액에서만 작동합니다. APR을 표시하는 UI는 Token-2022 헬퍼를 호출하여 UI 금액을 렌더링해야 합니다.
  • ScaledUiAmount. UI 표시 스케일링 확장입니다. InterestBearingConfig와 동일한 처리 — 곡선은 원시 금액을 사용합니다.
다른 확장 — PermanentDelegate, TransferHook, DefaultAccountState, NonTransferable, ConfidentialTransfer, Group/GroupMember, MintCloseAuthority 등 — 은 Initialize를 NotSupportMint로 거부하게 합니다. 한 가지 예외는 민트별 레지스트리입니다: 시드 [b"support_mint", mint]에 SupportMintAssociated PDA가 존재하면 확장 세트에 관계없이 mint가 허용됩니다. 해당 PDA는 관리자 (또는 전용 support-mint 권한)에 의해 CreateSupportMintAssociated / CloseSupportMintAssociated를 통해 생성 및 제거되므로 특정 mint를 온보딩하는 것은 더 이상 프로그램 업그레이드가 필요하지 않습니다.
2026-09에서 변경됨. CPMM은 이전에 확장 확인을 단락시킨 하드코딩된 4주소 MINT_WHITELIST도 수행했습니다. 해당 배열은 제거되었습니다; 레지스트리 PDA는 이제 유일한 우회입니다. 하드코딩된 목록에 의존하던 모든 mint는 새 풀을 생성하기 전에 SupportMintAssociated PDA가 필요합니다 — 기존 풀은 영향을 받지 않습니다. 확인은 풀 생성 시에만 실행되기 때문입니다.
검증된 확장 목록은 CP-Swap 소스의 programs/cp-swap/src/utils/token.rs 아래에 있으며 향후 프로그램 업그레이드로 변경될 수 있습니다. 크로스 프로그램 매트릭스는 reference/token-2022-support를 참조하세요.

Observation

observation 계정은 ObservationState 항목의 ring buffer이며, 각각 block_timestamp와 누적 가격을 저장합니다. 모든 스왑에서 프로그램은 마지막 이후 충분한 시간이 경과했으면 새로운 observation을 추가합니다. TWAP는 두 observation을 읽고 Δcumulative / Δtime을 나누어 계산됩니다.
ring buffer는 100개의 observation을 위해 크기가 지정됩니다. 각 observation은 40바이트 (8 + 16 + 16)이므로 배열 자체는 4,000바이트입니다; ObservationState::LEN은 정확히 4,075바이트 (8 + 1 + 2 + 32 + 4,000 + 8 × 4)입니다. 두 가지 소비자 규칙:
  • 단일 observation을 가격으로 사용하지 마세요. 이는 현물 가격이 아닌 누적입니다. TWAP를 계산하려면 두 개를 사용하세요.
  • 최소 한 블록 떨어진 observation을 선택하세요. 동일 블록 내의 스왑은 새로운 observation을 생성하지 않을 수 있습니다; 연속으로 읽으면 동일한 레코드를 반환할 수 있습니다.
더 많은 수학은 products/clmm/accounts에 있습니다.

계정 생명주기

CPMM 풀과 그 PDA는 절대 종료되지 않습니다. Permission, SupportMintAssociated 및 CreatorFeeShare는 예외입니다 — 이들은 풀 상태가 아닌 독립형 관리자 관리 레코드이며 각각 명시적 종료 명령어가 있습니다. 유동성이 0이어도 poolState는 유지됩니다. 이는 의도적입니다: 나중에 동일한 풀을 다시 시드하면 역사적 observation buffer가 보존되고 PDA 파생이 안정적으로 유지됩니다.

어디서 무엇을 읽을지

소스: