You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Solana Rust如何获取当前CPI函数调用返回值 移植Solidity的方案是否正确

Solana CPI调用获取返回值的解决方案

你提到的拆分两次交易、靠全局账户存储返回值的方案是不正确的,存在竞态风险,且完全没有必要,目前有更安全高效的实现方式:

  • 方案1:传入调用方可控的临时账户接收返回值(链上逻辑需要使用返回值时首选)
    Solana的CPI调用支持传入自定义账户,你可以在调用deposit/withdraw方法时,额外传入一个由你当前程序控制、专门用于接收本次调用返回值的临时账户(可以是一次性的PDA,也可以是调用时创建的临时账户)。被调用的Strategy程序执行完核心逻辑后,直接把sharesAdded/sharesRemoved写入这个临时账户即可。
    整个读写过程都在同一个原子交易中完成,不会出现并发修改的问题,你在当前交易的后续逻辑中可以直接读取这个账户里的返回值,不需要拆分两次交易。
    对应Anchor实现的示例:

    // 被调用的Strategy程序的接口定义
    pub fn deposit(ctx: Context<Deposit>, sender: Pubkey, want_amt: u64) -> Result<()> {
        // 核心存款逻辑计算份额
        let shares_added = xxxx;
        // 写入返回值到调用方传入的临时账户
        ctx.accounts.return_data_account.shares = shares_added;
        Ok(())
    }
    
    #[derive(Accounts)]
    pub struct Deposit<'info> {
        // 其他原有业务账户...
        pub return_data_account: Account<'info, ReturnData>,
    }
    

    你作为调用方在发起CPI时传入该账户即可,执行完CPI直接读取这个账户的shares字段就能拿到返回值。

  • 方案2:使用链上事件(仅链下客户端需要获取返回值时使用)
    如果你不需要在链上逻辑中使用该返回值,仅需要链下客户端拿到结果,只需要让被调用的Strategy程序在执行完deposit/withdraw后emit对应的事件即可,客户端在交易确认后解析交易日志里的事件内容就能拿到sharesAdded/sharesRemoved,不需要额外的调用。

你之前设想的方案之所以不推荐,是因为如果把返回值存在被调用程序的公共存储账户中,多个用户同时调用时返回值会被互相覆盖,且两次交易之间的间隔无法保证数据一致性,完全没有必要采用。

内容的提问来源于stack exchange,提问作者Russo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 22:09:04