> ## 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](/cn/pages/ephemeral-rollups-ers/introduction/ephemeral-rollup)
速度转移资金的链上程序，例如 DEX、AMM、预测市场、托管合约或游戏。核心模式是：将一个归程序所有的
账户委托给 ER，并由你的程序以 PDA 身份签署 token 转账。

<Note>
  需要从客户端而非链上转移 token？请参阅
  [快速入门](/cn/pages/ephemeral-spl-token/quickstart)。
</Note>

### 两种托管模型

| 模型                 | 你委托的是……                            | 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。
  </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>}>
    通过 CPI 调用 Ephemeral SPL Token 程序，将 eATA 委托给 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。

```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>

你的程序拥有一个状态 PDA（例如 `Pool`），它是资金的 authority。ER 上的托管使用由该 PDA
拥有的 **ephemeral ATA（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>

通过 CPI 调用 Ephemeral SPL Token 程序来委托 eATA（`DelegateEphemeralAta`，
discriminator `4`）。

<Warning>
  不支持将归普通 PDA 所有的 ATA 直接委托给 ER；ER 上的 token 托管必须通过 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="非托管转账">
    如果你的程序不托管资金，而只是代表用户在两个已委托账户之间转移 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="/cn/pages/overview/additional-information/system-status" iconType="duotone">
    Subscribe to MagicBlock Server Status
  </Card>
</CardGroup>

***
