> ## Documentation Index
> Fetch the complete documentation index at: https://docs.magicblock.gg/llms.txt
> Use this file to discover all available pages before exploring further.

# スマートコントラクト統合

> Ephemeral Rollup 上で独自の Solana プログラムから SPL token をカストディ・移動します。PDA 署名送金、委任、コミット/委任解除に対応します。

***

### クイックアクセス

<CardGroup cols={3}>
  <Card title="binary-prediction" icon="github" href="https://github.com/magicblock-labs/magicblock-engine-examples/tree/main/binary-prediction" iconType="duotone">
    eATA カストディをエンドツーエンドで実装
  </Card>

  <Card title="rewards-delegated-vrf" icon="github" href="https://github.com/magicblock-labs/magicblock-engine-examples/tree/main/rewards-delegated-vrf" iconType="duotone">
    Base-layer のコミット後支払い
  </Card>

  <Card title="spl-tokens" icon="github" href="https://github.com/magicblock-labs/magicblock-engine-examples/tree/main/spl-tokens" iconType="duotone">
    ノンカストディ送金
  </Card>
</CardGroup>

このガイドは、ユーザー資金を保持し、[Ephemeral Rollup](/jp/pages/ephemeral-rollups-ers/introduction/ephemeral-rollup)
の速度で移動する DEX、AMM、予測市場、エスクロー、ゲームなどのオンチェーンプログラム向けです。
基本パターンは、プログラム所有アカウントを ER に委任し、プログラムが PDA として token
送金に署名することです。

<Note>
  オンチェーンではなくクライアントから token を移動する場合は、
  [クイックスタート](/jp/pages/ephemeral-spl-token/quickstart)を参照してください。
</Note>

### 2 つのカストディモデル

| モデル                   | 委任対象                                   | Token の移動                                 | 用途                             |
| --------------------- | -------------------------------------- | ----------------------------------------- | ------------------------------ |
| **eATA カストディ**        | プログラム所有の **ephemeral ATA（eATA）**       | **ER 上**、PDA 署名                           | rollup 内で決済または支払いを行う場合（例：市場約定） |
| **状態 PDA + コミット後支払い** | **状態 PDA** のみ。実際の ATA は base layer に残す | **base layer 上**、post-commit action として実行 | 資金を L1 に残し、コミット時に決済する場合        |

以下の手順では **eATA カストディ**を扱い、post-commit のバリエーションは高度なスニペットで説明します。

***

## ステップ別ガイド

プログラムに eATA の authority を付与して委任し、ER 上で PDA 署名により資金を移動してから
Solana に決済します：

<Steps>
  <Step title={<a href="#1-er-aware-program">プログラムを ER 対応にする</a>}>
    `#[ephemeral]` 属性を追加し、SDK helper を import します。
  </Step>

  <Step title={<a href="#2-create-eata">カストディ PDA と eATA を作成</a>}>
    カストディ PDA から Ephemeral SPL Token プログラム配下の eATA を所有します。
  </Step>

  <Step title={<a href="#3-delegate-eata">eATA を委任</a>}>
    Ephemeral SPL Token プログラムに CPI して ER へ委任します。
  </Step>

  <Step title={<a href="#4-pda-signed-transfer">PDA 署名で token を移動</a>}>
    rollup 内でカストディ PDA として送金に署名します。
  </Step>

  <Step title={<a href="#5-commit-undelegate">コミットして委任解除</a>}>
    アカウントを base layer に戻します。
  </Step>
</Steps>

***

## カストディの例

以下のソフトウェアパッケージが必要になる場合があります。ほかのバージョンでも互換性がある可能性があります。

| ソフトウェア     | バージョン   | インストールガイド                                                       |
| ---------- | ------- | --------------------------------------------------------------- |
| **Solana** | 3.1.9   | [Solana をインストール](https://docs.anza.xyz/cli/install)             |
| **Rust**   | 1.89.0  | [Rust をインストール](https://www.rust-lang.org/tools/install)         |
| **Anchor** | 1.0.2   | [Anchor をインストール](https://www.anchor-lang.com/docs/installation) |
| **Node**   | 24.10.0 | [Node をインストール](https://nodejs.org/en/download/current)          |

### コードスニペット

<h4 id="1-er-aware-program">
  1. ER 対応プログラム
</h4>

`#[program]` を `#[ephemeral]` で囲み、必要な SDK helper を import します。

```rust theme={null}
use ephemeral_rollups_sdk::anchor::{commit, delegate, ephemeral};
use ephemeral_rollups_sdk::cpi::DelegateConfig;
use ephemeral_rollups_sdk::ephem::MagicIntentBundleBuilder;

#[ephemeral]
#[program]
pub mod your_program {
    use super::*;
    // ...
}
```

[⬆️ トップに戻る](#code-snippets)

<h4 id="2-create-eata">
  2. eATA を作成
</h4>

プログラムは資金の authority となる状態 PDA（例：`Pool`）を所有します。ER 上のカストディでは、
その PDA が所有する \*\*ephemeral ATA（eATA）\*\*を使います。eATA は Ephemeral SPL Token
プログラム（`SPLxh1LVZzEkX99H6rqYizhytLWPZVV296zyYDPagv2`）配下で `[owner, mint]` から導出されます。

```rust theme={null}
// The eATA is owned by your custody PDA (e.g. a Pool), derived under the
// Ephemeral SPL Token program from [owner, mint].
let (eata, _bump) = Pubkey::find_program_address(
    &[owner.as_ref(), mint.as_ref()],
    &EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
);

// At initialize, create the eATA (InitializeEphemeralAta) and the per-mint
// global vault that backs every eATA (InitializeGlobalVault), then fund it.
```

[⬆️ トップに戻る](#code-snippets)

<h4 id="3-delegate-eata">
  3. eATA を委任
</h4>

Ephemeral SPL Token プログラムへの CPI（`DelegateEphemeralAta`、discriminator `4`）で
eATA を委任します。

<Warning>
  通常の PDA 所有 ATA を ER に直接委任することはできません。ER 上の token custody は
  eATA を介します。token account ではなくプログラムの*状態*を委任する場合は、SDK の
  `#[delegate]` マクロを使用してください。
</Warning>

```rust theme={null}
// Delegate the eATA with a CPI to the Ephemeral SPL Token program.
// An optional trailing validator pubkey routes to a specific validator.
let mut data = vec![4]; // DelegateEphemeralAta
if let Some(validator) = validator {
    data.extend_from_slice(validator.as_ref());
}

let instruction = Instruction {
    program_id: EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
    accounts: vec![
        AccountMeta::new(payer.key(), true),
        AccountMeta::new(ephemeral_ata.key(), false),
        AccountMeta::new_readonly(EPHEMERAL_SPL_TOKEN_PROGRAM_ID, false),
        AccountMeta::new(buffer.key(), false),
        AccountMeta::new(record.key(), false),
        AccountMeta::new(metadata.key(), false),
        AccountMeta::new_readonly(delegation_program.key(), false),
        AccountMeta::new_readonly(system_program.key(), false),
    ],
    data,
};
invoke(&instruction, &account_infos)?;
```

[⬆️ トップに戻る](#code-snippets)

<h4 id="4-pda-signed-transfer">
  4. PDA 署名送金
</h4>

eATA を委任したら、`CpiContext::new_with_signer` を介してカストディ PDA が署名する
SPL Token CPI で rollup 内の token を移動します。signer seed は `[POOL_SEED, bump]` です。
プログラム自体が支払いを承認するため、ユーザー署名は不要です。

```rust theme={null}
use anchor_spl::token::{self, Transfer as SplTransfer};

// The custody PDA signs the transfer — no user signature required.
let bump_seed = [pool_bump];
let signer_seeds: &[&[&[u8]]] = &[&[POOL_SEED, &bump_seed]];

let cpi_accounts = SplTransfer {
    from,
    to,
    authority: pool, // the Pool PDA
};
let cpi_ctx = CpiContext::new_with_signer(token_program.to_account_info(), cpi_accounts, signer_seeds);
token::transfer(cpi_ctx, amount)?;
```

[⬆️ トップに戻る](#code-snippets)

<h4 id="5-commit-undelegate">
  5. コミットして委任解除
</h4>

`MagicIntentBundleBuilder` で ER 状態をコミットし、アカウントを base layer に戻します。

```rust theme={null}
// The #[commit] attribute on the accounts context supplies
// magic_context and magic_program.
MagicIntentBundleBuilder::new(
    ctx.accounts.payer.to_account_info(),
    ctx.accounts.magic_context.to_account_info(),
    ctx.accounts.magic_program.to_account_info(),
)
.commit_and_undelegate(&[ctx.accounts.pool.to_account_info()])
.build_and_invoke()?;
```

[⬆️ トップに戻る](#code-snippets)

***

### 高度なコードスニペット

<Tabs>
  <Tab title="ノンカストディ送金">
    プログラムが資金をカストディせず、ユーザーに代わって 2 つの委任済みアカウント間で
    token を移動する場合、PDA signer は不要です。authority はユーザーの `Signer` で、
    通常の `CpiContext::new` を使用します。

    ```rust theme={null}
    // No PDA signer — the authority is the user's Signer.
    let cpi_accounts = SplTransfer {
        from: ctx.accounts.from.to_account_info(),
        to: ctx.accounts.to.to_account_info(),
        authority: ctx.accounts.payer.to_account_info(),
    };
    token::transfer(CpiContext::new(ctx.accounts.token_program.to_account_info(), cpi_accounts), amount)?;
    ```

    [⬆️ トップに戻る](#advanced-code-snippets)
  </Tab>

  <Tab title="Base-layer のコミット後支払い">
    実際の token account を base layer に残してプログラム状態だけを委任するには、支払いを
    post-commit action としてスケジュールします。コミット直後に base layer 上で PDA 署名により
    実行されます。`transfer_checked`（Token-2022 対応）を使用し、action を添付してコミットします。

    ```rust theme={null}
    // Keep real token accounts on base, delegate only program state, and pay out
    // PDA-signed on the base layer right after the commit. Use the PDA AccountInfo
    // as the payer and pass its seeds to build_and_invoke_signed.
    MagicIntentBundleBuilder::new(
        payer_pda.to_account_info(),
        magic_context.to_account_info(),
        magic_program.to_account_info(),
    )
        .magic_fee_vault(magic_fee_vault.to_account_info())
        .commit(&[state_pda.to_account_info()])
        .add_post_commit_actions([action])
        .build_and_invoke_signed(&[payer_seeds])?;
    ```

    [⬆️ トップに戻る](#advanced-code-snippets)
  </Tab>
</Tabs>

***

## Solana エクスプローラー

Solana 上のトランザクションとアカウントの情報を確認できます。

<CardGroup cols={2}>
  <Card title="Solana エクスプローラー" icon="search" href="https://explorer.solana.com/" iconType="duotone">
    公式 Solana エクスプローラー
  </Card>

  <Card title="Solscan" icon="searchengin" href="https://solscan.io/" iconType="duotone">
    Solana ブロックチェーンを探索する
  </Card>
</CardGroup>

## Solana RPC プロバイダー

既存の RPC プロバイダーを通じてトランザクションやリクエストを送信します。

<CardGroup cols={2}>
  <Card title="Solana" icon="star" href="https://solana.com/docs/references/clusters#on-a-high-level" iconType="duotone">
    Free Public Nodes
  </Card>

  <Card title="Helius" icon="sun" href="https://www.helius.dev/solana-rpc-nodes" iconType="duotone">
    Free Shared Nodes
  </Card>

  <Card title="Triton" icon="crystal-ball" href="https://triton.one/solana" iconType="duotone">
    Dedicated High-Performance Nodes
  </Card>
</CardGroup>

## Solana バリデータダッシュボード

Solana バリデータインフラのリアルタイム更新を確認できます。

<CardGroup cols={2}>
  <Card title="Solana Beach" icon="wave" href="https://solanabeach.io/" iconType="duotone">
    Get Validator Insights
  </Card>

  <Card title="Validators App" icon="cloud-binary" href="https://www.validators.app/" iconType="duotone">
    Discover Validator Metrics
  </Card>
</CardGroup>

## サーバーステータス

Solana と MagicBlock のサーバーステータスを確認しましょう。

<CardGroup cols={2}>
  <Card title="Solana Status" icon="server" href="https://status.solana.com/" iconType="duotone">
    Subscribe to Solana Server Updates
  </Card>

  <Card title="MagicBlock Status" icon="heart-pulse" href="/jp/pages/overview/additional-information/system-status" iconType="duotone">
    Subscribe to MagicBlock Server Status
  </Card>
</CardGroup>

***
