Anchor 中的跨程序调用

  • 0xE
  • 发布于 2025-04-03 10:59
  • 阅读 1015

本文将详细讲解如何在 Anchor 框架中实现 CPI,重点展示调用另一个 Anchor 程序的过程,并以 Alice 调用 Bob 的示例说明。

跨程序调用(CPI)是指在 Solana 中一个程序调用另一个程序的公共函数。本文将详细讲解如何在 Anchor 框架中实现 CPI,重点展示调用另一个 Anchor 程序的过程,并以 Alice 调用 Bob 的示例说明。注意,本教程适用于 Anchor 程序,不适用于纯 Rust 开发的程序。


CPI 基础回顾

CPI 的典型示例是向系统程序转账 SOL:

pub fn send_sol(ctx: Context<SendSol>, amount: u64) -> Result<()> {
    let cpi_context = CpiContext::new(
        ctx.accounts.system_program.to_account_info(),
        system_program::Transfer {
            from: ctx.accounts.signer.to_account_info(),
            to: ctx.accounts.recipient.to_account_info(),
        }
    );

    let res = system_program::transfer(cpi_context, amount);

    if res.is_ok() {
        return Ok(());
    } else {
        return err!(Errors::TransferFailed);
    }
}

CpiContext 表示跨程序调用,调用其他程序的逻辑与之类似。


Bob 程序

首先创建 Bob 程序:

anchor init bob

将以下代码写入 bob/lib.rs:

use anchor_lang::prelude::*;
use std::mem::size_of;

declare_id!("BN2aLyQ8UJozgebuDVdwhY47VZA2RbS3HDRDz5zyYQqw");

#[program]
pub mod bob {
    use super::*;

    pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
        msg!("Data Account Initialized: {}", ctx.accounts.bob_data_account.key());
        Ok(())
    }

    pub fn add_and_store(ctx: Context<BobAddOp>, a: u64, b: u64) -> Result<()> {
        let result = a + b;
        ctx.accounts.bob_data_account.result = result;
        Ok(())
    }
}

#[account]
pub struct BobData {
    pub result: u64,
}

#[derive(Accounts)]
pub struct BobAddOp<'info> {
    #[account(mut)]
    pub bob_data_account: Account<'info, BobData>,
}

#[derive(Accounts)]
pub struct Initialize<'info> {
    #[account(init, payer = signer, space = size_of::<BobData>() + 8)]
    pub bob_data_account: Account<'info, BobData>,
    #[account(mut)]
    pub signer: Signer<'info>,
    pub system_program: Program<'info, System>,
}

Bob 提供两个函数:initialize 初始化存储账户,add_and_store 将两个 u64 相加并存储。


Alice 程序

在 bob 项目中创建 Alice 程序:

anchor new alice

编辑 programs/alice/Cargo.toml,添加依赖:

[dependencies]
bob = { path = "../bob", features = ["cpi"] }

此依赖使 Alice 能访问 Bob 的函数和结构体,类似 Solidity 中的接口导入。

Alice 的完整代码如下:


use anchor_lang::prelude::*;
use bob::cpi::accounts::BobAddOp;
use bob::program::Bob;
use bob::BobData;

declare_id!("GaKz6s9cpFBNMTM56TE3uQLMJ3YefZp4VFiUnCkQT8fU");

#[program]
pub mod alice {
    use super::*;

    pub fn ask_bob_to_add(ctx: Context<AliceOp>, a: u64, b: u64) -> Result<()> {
        let cpi_ctx = CpiContext::new(
            ctx.accounts.bob_program.to_account_info(),
            BobAddOp {
                bob_data_account: ctx.accounts.bob_data_account.to_account_info(),
            }
        );

        let res = bob::cpi::add_and_store(cpi_ctx, a, b);

        if res.is_ok() {
            return Ok(());
        } else {
            return err!(Errors::CPIToBobFailed);
        }
    }
}

#[error_code]
pub enum Errors {
    #[msg("cpi to bob failed")]
    CPIToBobFail...

剩余50%的内容订阅专栏后可查看

点赞 1
收藏 1
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
0xE
0xE
0x59f6...a17e
17年进入币圈,Web3 开发者。刨根问底探链上真相,品味坎坷悟 Web3 人生。