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

如何在TON区块链的FunC中调用其他合约函数获取数据?

在FunC中调用其他TON智能合约获取数据的实现方法

TON智能合约之间的交互是异步的,无法在当前合约的recv_internal流程里直接同步获取其他合约的数据。你需要先向目标合约发送调用消息,等待对方将结果通过回调消息返回后,再在自己的合约里处理回调数据推进流程。以下是具体实现步骤和代码示例:

1. 构造并发送调用目标合约的消息

明确目标合约的地址、调用的函数名和参数,打包成消息体发送给对方。替换你代码中的TODO部分:

() recv_internal(int msg_value, cell in_msg_full, slice in_msg_body) impure {
    if (in_msg_body.slice_empty?()) { ;; 忽略空消息
        return ();
    }

    slice cs = in_msg_full.begin_parse();
    int flags = cs~load_uint(4);

    if (flags & 1) { ;; 忽略所有 bounced 消息
        return ();
    }
    slice sender_address = cs~load_msg_addr();

    ;; --------------------------
    ;; 调用其他合约的核心代码
    ;; --------------------------
    ;; 1. 定义目标合约地址(替换成实际地址)
    slice target_contract = parse_std_addr("EQ..."); 

    ;; 2. 构造调用消息体:指定要调用的函数名和参数
    cell call_body = begin_cell()
        .store_uint(0x18, 6) ;; 内部消息的opcode
        .store_slice("get_data") ;; 要调用的目标合约函数名
        .store_uint(123, 32) ;; 传递给目标函数的参数(示例:32位整数)
        .end_cell();

    ;; 3. 发送内部消息,附带足够的gas(这里用0.01TON作为手续费,可调整)
    send_raw_message(
        begin_cell()
            .store_uint(0, 2) ;; 消息类型:内部消息
            .store_slice(target_contract) ;; 目标地址
            .store_coins(10000000) ;; 附带的TON(0.01TON)
            .store_uint(0, 1+4+4+64+32) ;; 消息标志、过期时间等默认值
            .store_slice(call_body.begin_parse())
            .end_cell(),
        64 ;; 发送模式:忽略错误,不要求回执
    );
}

2. 处理目标合约的回调消息

目标合约处理完调用后,需要主动发送回调消息回来。在recv_internal中添加逻辑,识别回调消息并解析数据:

() recv_internal(int msg_value, cell in_msg_full, slice in_msg_body) impure {
    if (in_msg_body.slice_empty?()) {
        return ();
    }

    slice cs = in_msg_full.begin_parse();
    int flags = cs~load_uint(4);
    if (flags & 1) {
        return ();
    }
    slice sender_address = cs~load_msg_addr();

    ;; 解析消息体,判断是否是目标合约的回调
    slice body = in_msg_body;
    int op = body~load_uint(6);
    if (op == 0x18) { ;; 匹配内部消息opcode
        slice func_name = body~load_string();
        if (func_name == "callback_data") { ;; 匹配回调函数名
            ;; 解析目标合约返回的数据(示例:32位整数)
            int returned_data = body~load_uint(32);

            ;; --------------------------
            ;; 这里用返回的数据推进后续流程
            ;; 比如更新合约状态、触发其他逻辑等
            ;; --------------------------
            ;; 示例:打印日志(测试用,主网可移除)
            print("Received data from target contract: ", returned_data);
            return;
        }
    }

    ;; 原有的调用目标合约逻辑(保留)
    slice target_contract = parse_std_addr("EQ..."); 
    cell call_body = begin_cell()
        .store_uint(0x18, 6)
        .store_slice("get_data")
        .store_uint(123, 32)
        .end_cell();

    send_raw_message(
        begin_cell()
            .store_uint(0, 2)
            .store_slice(target_contract)
            .store_coins(10000000)
            .store_uint(0, 1+4+4+64+32)
            .store_slice(call_body.begin_parse())
            .end_cell(),
        64
    );
}

关键注意事项

  • Gas费用:发送消息时必须附带足够的TON作为手续费,否则消息会执行失败。
  • 回调验证:要验证回调消息的发送者确实是目标合约,防止恶意伪造消息干扰合约逻辑。
  • 异步特性:合约间调用是异步的,不能依赖立即获取结果,必须提前设计好回调处理流程。
  • 只读方法查询:如果只是查询目标合约的只读数据(不修改状态),可以在链下通过get_method接口查询,不需要合约间发送消息。

内容的提问来源于stack exchange,提问作者Tho Bui Ngoc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 21:13:16