> ## 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アカウント

> CPMMプールが参照するすべてのPDAと共有アカウント：PoolState、AmmConfig、authority、LPミント、トークンボルト、およびobservationリングバッファ。

<Info>
  **このページは AI による自動翻訳です。すべての内容は英語版を正とします。**

  [英語版を表示 →](/products/cpmm/accounts)
</Info>

<Info>
  CPMMのプログラムIDとPDAシードは [`reference/program-addresses`](/ja/reference/program-addresses) に正規に記載されています。このページは**各アカウントの役割と維持する不変量**に焦点を当てており、ハードコードされたアドレスについては扱いません。
</Info>

## CPMMプールの6つのアカウント

すべてのCPMMプールは、CPMMプログラム傘下の6つのプログラム派生アドレス（PDA）と、その1つが参照する共有`AmmConfig`アカウントで完全に記述されます。2つのミントがあれば、ネットワークに接触することなく、すべてを決定論的に導き出せます。

| アカウント         | シード                                                                      | 所有者                    | 目的                                                                                                                                                                                                           |
| ------------- | ------------------------------------------------------------------------ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `authority`   | `"vault_and_lp_mint_auth_seed"`                                          | CPMM                   | すべてのボルト移動とすべてのLPミント/バーン操作の署名者。**すべての**CPMMプール間で共有。                                                                                                                                                           |
| `poolState`   | `"pool"`、`ammConfig`、`token0Mint`、`token1Mint` **または** 任意の署名者提供のランダムキーペア | CPMM                   | プールの状態構造体 — ミントペア、ボルト残高、LP供給量、フィーの蓄積、observationポインタ。CPMM `Initialize` 命令は、4つのシードから導き出された正規PDA **または** 作成者が署名した任意のキーペアのいずれかを受け入れます。ランダムキーペアパスは、敵がメモプールを監視して正規PDAを正当な作成者より先に占有しようとするフロントランニング攻撃を回避するために存在します。 |
| `lpMint`      | `"pool_lp_mint"`、`poolState`                                             | SPL Token              | プールのLPトークン。供給量 = 発行済みLP総額。ミント権限 = CPMMのauthority PDA。                                                                                                                                                        |
| `vault0`      | `"pool_vault"`、`poolState`、`token0Mint`                                  | SPL Token / Token-2022 | プールのtoken0残高を保有。authorityPDAが所有。                                                                                                                                                                             |
| `vault1`      | `"pool_vault"`、`poolState`、`token1Mint`                                  | SPL Token / Token-2022 | プールのtoken1残高を保有。authorityPDAが所有。                                                                                                                                                                             |
| `observation` | `"observation"`、`poolState`                                              | CPMM                   | TWAPに使用される価格サンプルのリングバッファ。すべてのスワップで書き込み。                                                                                                                                                                      |

共有設定：

| アカウント       | シード                         | 所有者  | 目的                                                                                     |
| ----------- | --------------------------- | ---- | -------------------------------------------------------------------------------------- |
| `ammConfig` | `"amm_config"`、`index: u16` | CPMM | トレード/プロトコル/ファンド/クリエイターのフィーレートと管理者キーを保有。「フィーティア」ごと1つ。PoolStateは作成時に1つにバインドされ、その後変更できない。 |

## 2つのミントだけからプールを導き出す

```ts theme={null}
import { PublicKey } from "@solana/web3.js";
import BN from "bn.js";

const CPMM_PROGRAM_ID = new PublicKey(
  "CPMMoo8L3F4NbTegBCKVNunggL7H1ZpdTHKxQB5qKP1C"
); // mainnet — see reference/program-addresses

function u16ToBytes(n: number): Buffer {
  const b = Buffer.alloc(2);
  b.writeUInt16BE(n);
  return b;
}

// token0 < token1 by byte order. Getting this wrong yields a valid PDA
// that points at a nonexistent pool.
function sortMints(a: PublicKey, b: PublicKey): [PublicKey, PublicKey] {
  return Buffer.compare(a.toBuffer(), b.toBuffer()) < 0 ? [a, b] : [b, a];
}

export function deriveCpmmAccounts(
  mintA: PublicKey,
  mintB: PublicKey,
  ammConfigIndex = 0,
) {
  const [token0Mint, token1Mint] = sortMints(mintA, mintB);

  const [ammConfig] = PublicKey.findProgramAddressSync(
    [Buffer.from("amm_config"), u16ToBytes(ammConfigIndex)],
    CPMM_PROGRAM_ID,
  );
  const [authority] = PublicKey.findProgramAddressSync(
    [Buffer.from("vault_and_lp_mint_auth_seed")],
    CPMM_PROGRAM_ID,
  );
  const [poolState] = PublicKey.findProgramAddressSync(
    [
      Buffer.from("pool"),
      ammConfig.toBuffer(),
      token0Mint.toBuffer(),
      token1Mint.toBuffer(),
    ],
    CPMM_PROGRAM_ID,
  );
  const [lpMint] = PublicKey.findProgramAddressSync(
    [Buffer.from("pool_lp_mint"), poolState.toBuffer()],
    CPMM_PROGRAM_ID,
  );
  const [vault0] = PublicKey.findProgramAddressSync(
    [Buffer.from("pool_vault"), poolState.toBuffer(), token0Mint.toBuffer()],
    CPMM_PROGRAM_ID,
  );
  const [vault1] = PublicKey.findProgramAddressSync(
    [Buffer.from("pool_vault"), poolState.toBuffer(), token1Mint.toBuffer()],
    CPMM_PROGRAM_ID,
  );
  const [observation] = PublicKey.findProgramAddressSync(
    [Buffer.from("observation"), poolState.toBuffer()],
    CPMM_PROGRAM_ID,
  );

  return {
    ammConfig,
    authority,
    poolState,
    lpMint,
    token0Mint,
    token1Mint,
    vault0,
    vault1,
    observation,
  };
}
```

<Tip>
  **プールPDAを導き出す前に必ずミントをソートしてください。** シードはユーザー順ではなく、バイト順で2つのミントをハッシュします。`(A, B)` と `(B, A)` を持つ2つのプールはオンチェーンで衝突し、ソートはプログラムがマッピングを正規にする方法です。
</Tip>

<Note>
  **プールIDは必ずしも正規PDAではありません。** `Initialize` は、上記のPDAに加えて、任意の署名者キーペアを `pool_state` として受け入れます。渡されたアカウントが正規PDAと一致しない場合、プログラムは署名者である必要があります。つまり、作成者は署名する新しいキーペアを渡します。これはフロントラン対策です：正規PDAをつかもうとしているサードパーティは、正当な作成者がランダムキーペアを代わりに使用することで回避できます。下流のPDA（`lpMint`、`vault0`、`vault1`、`observation`）はまだ `poolState.key()` から導き出されるため、使用されたアドレスに関わらず一意のままです。プールにインデックスを付けるときは、正規PDAを導き出すことではなく、オンチェーン状態からプールIDを常に検出してください（例：CPMMプログラム傘下の `PoolState` アカウント）。後者はランダムキーペアプールを見逃します。
</Note>

## アカウントレイアウト

完全なRust定義は [`raydium-cp-swap`](https://github.com/raydium-io/raydium-cp-swap) ソースに存在します。以下のフィールドは、統合時に読み取るフィールドです。

### `PoolState`

```rust theme={null}
// programs/cp-swap/src/states/pool.rs
pub struct PoolState {
    pub amm_config: Pubkey,               // binds this pool to an AmmConfig
    pub pool_creator: Pubkey,             // who ran initialize
    pub token_0_vault: Pubkey,            // == vault0 PDA
    pub token_1_vault: Pubkey,            // == vault1 PDA

    pub lp_mint: Pubkey,
    pub token_0_mint: Pubkey,
    pub token_1_mint: Pubkey,

    pub token_0_program: Pubkey,          // SPL Token or Token-2022 program
    pub token_1_program: Pubkey,

    pub observation_key: Pubkey,          // == observation PDA
    pub auth_bump: u8,
    pub status: u8,                       // bitmask: deposit | withdraw | swap
    pub lp_mint_decimals: u8,
    pub mint_0_decimals: u8,
    pub mint_1_decimals: u8,

    pub lp_supply: u64,                   // mirrors lp_mint supply
    pub protocol_fees_token_0: u64,
    pub protocol_fees_token_1: u64,
    pub fund_fees_token_0: u64,
    pub fund_fees_token_1: u64,

    pub open_time: u64,                   // unix; swaps rejected before this
    pub recent_epoch: u64,

    // Creator-fee state (added after the original layout):
    pub creator_fee_on: u8,               // 0=BothToken, 1=OnlyToken0, 2=OnlyToken1
    pub enable_creator_fee: bool,
    pub padding1: [u8; 6],
    pub creator_fees_token_0: u64,
    pub creator_fees_token_1: u64,

    pub padding: [u64; 28],
}
```

実際に読み取るもの：

* **`lp_supply`** — プールのLPミント供給量の内部ミラー。LP シェア計算に使用します。値はミントのオンチェーン供給量と一致するはずですが、`PoolState` から読み取ることで、追加のアカウント取得を回避できます。
* **`protocol_fees_token{0,1}`**、**`fund_fees_token{0,1}`** — *蓄積された*未実行フィー。これらはスワップ価格に影響しません。`CollectProtocolFee` / `CollectFundFee` が呼び出されるまでボルトに残ります。
* **`status`** — `Swap`、`Deposit`、`Withdraw` が許可されているかどうかを制御するビットマスク。`UpdatePoolStatus` 経由で管理者が更新。SDKはトランザクション構築前にこれをチェックします。直接CPIを実行している場合は、自分でチェックしてください。
* **`token0_program` / `token1_program`** — 各ボルトのためにCPIを実行するトークンプログラム。1つはSPL Tokenで、もう1つはToken-2022の場合があります。これらは独立しています。
* **`open_time`** — Unixタイムスタンプ。この時刻前のスワップは失敗します。デポジットは `open_time` 前に許可されるため、プールをシードできます。
* **`creator_fee_on` / `enable_creator_fee`** — クリエイターフィーがこのプール用にアクティブなかどうか、およびスワップのどちら側から集められるかを制御します。`enable_creator_fee == false` はクリエイターフィーパスを完全にゼロにします。有効な場合、`creator_fee_on` は以下を選択します：`0` = スワップ入力であるトークンからのフィー取得（`BothToken`）；`1` = `token_0` のみからのフィー取得（`token_1 → token_0` スワップをスキップ）；`2` = `token_1` のみからのフィー取得。プール作成時に `InitializeWithPermission` で設定；その後変更不可。
* **`creator_fees_token_{0,1}`** — 蓄積されたクリエイターフィー。`CollectCreatorFee` で実行。

### `AmmConfig`

```rust theme={null}
pub struct AmmConfig {
    pub bump: u8,
    pub disable_create_pool: bool,
    pub index: u16,                       // matches the seed
    pub trade_fee_rate: u64,              // e.g., 2500 = 0.25%
    pub protocol_fee_rate: u64,           // fraction of trade fee to protocol
    pub fund_fee_rate: u64,               // fraction of trade fee to fund
    pub create_pool_fee: u64,             // paid once at init (in SOL or token)
    pub protocol_owner: Pubkey,           // can call CollectProtocolFee
    pub fund_owner: Pubkey,               // can call CollectFundFee
    pub creator_fee_rate: u64,            // optional pool-creator fee rate (1/1_000_000 of volume)
    pub padding: [u64; 15],
}
```

3つの注意点：

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`](/ja/products/cpmm/fees) にあります。
2. **`index` は `u16`** であるため、シードハッシュは2バイトのビッグエンディアンを使用します。バイト順の1ずれは一般的な統合バグです。
3. **`AmmConfig` はプールレベルで不変です。** プールは作成時に1つの `AmmConfig` を指してから、切り替わることはありません。フィー変更は、プールがスワップのたびに設定を読み取るため伝播しますが、プールはフィーティア間で移動できません。

クリエイターフィーについての注記：**レート自体** （`creator_fee_rate`）は `AmmConfig` に存在し、フィーティア間で共有されます。特定のプールが実際にそれを請求するかどうか（`enable_creator_fee`）、およびスワップのどちら側に着地するか（`creator_fee_on`）は `PoolState` に存在します。クリエイターフィーはトレード フィーの**独立した**もので、独立したレート、独立したカウンター（`creator_fees_token_{0,1}`）を備えており、LP/プロトコル/ファンドのトレード フィーシェアを削減することはありません。実行は `CollectCreatorFee` を通じて行われます。完全なメカニクスについては [`products/cpmm/fees`](/ja/products/cpmm/fees) を参照してください。

### `Permission`

`InitializeWithPermission` で使用される小さなアクセス制御アカウント。CPMMプログラムは、他のプログラム（例えば、トークンをCPMMに卒業させるときのLaunchLab）が与えられた `AmmConfig` に対してプールを作成できることを証明するための、許可されたプール作成パスをサポートしています。

```rust theme={null}
pub struct Permission {
    pub authority: Pubkey,    // who is allowed to call InitializeWithPermission
    pub padding: [u64; 8],
}
```

PermissionPDAはCPMM管理者が `CreatePermissionPda` を通じて作成され、`ClosePermissionPda` を通じて取り消されます。エンドユーザーはこのアカウントと直接やり取りしません。これはクロスプログラムフロー用の配管です。

### ボルトとToken-2022

`vault0` と `vault1` はCPMMのauthority PDAが所有し、それらのトークンプログラム所有者（`token_program`）はSPL TokenまたはToken-2022で、プール作成時にミントのプログラムによって決定されます。プールは2つのケースを透過的に処理し、`Swap` / `Deposit` / `Withdraw` 命令アカウントで各側の正しいトークンプログラムIDを渡します。

CPMMはプール作成時に厳密な**拡張許可リスト**を強制します（`utils/token.rs` の `is_supported_mint`）。Token-2022ミントはCPMMプールで使用でき、それが**すべての**拡張機能がこのリストに含まれている場合に限ります：

* **`TransferFeeConfig`。** ミントが転送のたびに適用。プールは `SwapBaseInput` デポジット側の受信側で、引き出し側の送信側です。プログラムはボルトに着地する**ネット**金額を計算し、曲線をそれに応じて設定します。[`algorithms/token-2022-transfer-fees`](/ja/algorithms/token-2022-transfer-fees) を参照してください。
* **`MetadataPointer`** および **`TokenMetadata`。** ミント上の標準メタデータ。スワップ計算への影響なし。
* **`InterestBearingConfig`。** ミントのUI金額は利息が蓄積。ボルトは生の金額を格納し、曲線は生の金額のみで動作します。APRを表示するUI は、Token-2022ヘルパーを呼び出してUI金額をレンダリングする必要があります。
* **`ScaledUiAmount`。** UI表示スケーリング拡張機能。`InterestBearingConfig` と同じ扱い — 曲線は生の金額を使用します。

他の拡張機能 — `PermanentDelegate`、`TransferHook`、`DefaultAccountState`、`NonTransferable`、`ConfidentialTransfer`、`Group`/`GroupMember`、`MintCloseAuthority` など — は `Initialize` が `NotSupportMint` で拒否されます。例外は、プログラムのハードコードされた小さな**ミントホワイトリスト**（いくつかの特定のpubkeys）で、拡張チェックをバイパスします。これはケースバイケースで特定のミントをオンボードするために使用されます。

ベットされた拡張リストとミントホワイトリストは、CP-Swapソースの `programs/cp-swap/src/utils/token.rs` に存在し、将来のプログラムアップグレードで変更される可能性があります。

### Observation

observationアカウントは `ObservationState` エントリのリングバッファで、各エントリは `block_timestamp` と**累積価格**を格納します。スワップのたびに、最後のスワップ以降に十分な時間が経過している場合、プログラムは新しいobservationを追加します。TWAPは2つのobservationを読み、`Δcumulative / Δtime` を計算することで計算されます。

```rust theme={null}
// OBSERVATION_NUM is hardcoded in the program to 100.
pub const OBSERVATION_NUM: usize = 100;

pub struct Observation {
    pub block_timestamp:              u64,
    pub cumulative_token_0_price_x32: u128,   // Q32.32, top 64 bits left for overflow
    pub cumulative_token_1_price_x32: u128,
}

pub struct ObservationState {
    pub initialized:           bool,
    pub observation_index:     u16,                            // circular index
    pub pool_id:               Pubkey,
    pub observations:          [Observation; OBSERVATION_NUM], // 100 entries
    pub last_update_timestamp: u64,                            // timestamp of the most recent append
    pub padding:               [u64; 3],
}
```

リングバッファは**100 observations** サイズです。各observationは40バイトなので、配列のみで4,000バイトです。周囲のフィールドとdiscriminatorの後、完全な `ObservationState` PDAは約4,100バイトです。

2つのコンシューマー規則：

* **単一observationを価格として使用しないでください。** それは*累積*であって、スポット価格ではありません。TWAPを計算するため、2つを使用してください。
* **少なくとも1ブロック離れたobservationを選択してください。** 同じブロック内のスワップは新しいobservationを生成しない場合があります。連続読み取りは同じレコードを返すことがあります。

その他の計算は [`products/clmm/accounts`](/ja/products/clmm/accounts) にあります。

## アカウントライフサイクル

| イベント                 | 作成されたアカウント                                           | 削除されたアカウント |
| -------------------- | ---------------------------------------------------- | ---------- |
| `Initialize`         | `poolState`、`lpMint`、`vault0`、`vault1`、`observation` | —          |
| `Deposit`            | — (ユーザーLP ATAが作成される可能性あり)                            | —          |
| `Withdraw`           | —                                                    | —          |
| `Swap`               | — (ユーザー宛先ATAが作成される可能性あり)                             | —          |
| `CollectProtocolFee` | —                                                    | —          |
| `CollectFundFee`     | —                                                    | —          |
| `UpdatePoolStatus`   | —                                                    | —          |

CPMMプールとそのPDAは**決してクローズされません**。流動性がゼロの場合でも、`poolState` は残ります。これは意図的です：後で同じプールを再シードすることは、その履歴observationバッファを保持し、そのPDA導出の安定性を保ちます。

## どこで何を読むか

* **命令アカウント一覧**（上記のうち各命令に対して書き込み可能/署名者であるもの）：[`products/cpmm/instructions`](/ja/products/cpmm/instructions)。
* **フィー蓄積セマンティクス**：[`products/cpmm/fees`](/ja/products/cpmm/fees)。
* **スワップ計算 / observation更新規則**：[`products/cpmm/math`](/ja/products/cpmm/math)。
* **正規シード / プログラムID**：[`reference/program-addresses`](/ja/reference/program-addresses)。

ソース：

* [`raydium-io/raydium-cp-swap` — PoolState、AmmConfig、ObservationState](https://github.com/raydium-io/raydium-cp-swap)
