Skip to content

发送消息

TON 区块链是基于消息的——要与其他合约通信或部署新合约,你需要发送消息。

在 Tact 中,消息通常使用内置的 Struct SendParameters 组成,其中包括:

字段类型描述
bounceBool当设置为 true(默认)时,如果接收合约不存在或无法处理消息,消息会退回给发送者。
toAddressTON 区块链中接收者的内部 Address
valueInt你希望随消息发送的 Toncoins 数量。该值用于支付接收方的 gas 费用。
modeInt一个 8 位的值,用于配置如何发送消息,默认为 $0$。参见:消息 mode
bodyCell?可选 的消息体,作为 Cell
codeCell?可选 的合约初始代码(编译后的字节码)
dataCell?可选 的合约初始数据(合约的 init() 函数的参数)

字段 codedata 被称为 初始化包,用于部署新合约。

发送简单回复

最简单的消息是回复传入消息,返回消息的所有多余值:

solidity
receive() {
    self.reply("Hello, World!".asComment()); // asComment 将字符串转换为带有注释的 Cell
}

发送消息

如果你需要更高级的逻辑,可以直接使用 send() 函数和 SendParameters Struct

事实上,上一示例中的 .reply() 可以通过以下对 send() 函数的调用来实现:

solidity
receive() {
    send(SendParameters{
        // 默认情况下,bounce 设置为 true
        to: sender(), // 将消息发送回发送者
        value: 0, // 不向消息添加 Toncoins...
        mode: SendRemainingValue | SendIgnoreErrors, // ...除了由于 SendRemainingValue 从发送者接收的 Toncoins
        body: "Hello, World".asComment(), // asComment 将字符串转换为带有注释的 Cell
    });
}

另一个示例向指定的 Address 发送一条 value 为 $1$ TON 的消息,消息体为带有 String "Hello, World!" 的注释:

solidity
let recipient: Address = ...;
let value: Int = ton("1");
send(SendParameters{
    // 默认情况下,bounce 设置为 true
    to: recipient,
    value: value,
    mode: SendIgnoreErrors, // 无论发生任何错误都将发送消息
    body: "Hello, World!".asComment(),
});

可选标志 SendIgnoreErrors 意味着即使在消息发送过程中发生错误,后续消息仍将继续发送。发送阶段的任何错误都不会导致交易回滚。

发送类型化消息

要发送二进制类型化消息,可以使用以下代码:

solidity
let recipient: Address = ...;
let value: Int = ton("1");
send(SendParameters{
    // 默认情况下,bounce 设置为 true
    to: recipient,
    value: value,
    mode: SendIgnoreErrors, // 发生错误时也不中止
    body: SomeMessage{arg1: 123, arg2: 1234}.toCell(),
});

部署合约

要部署合约,你需要使用 initOf 计算其地址和初始状态,然后将它们发送到初始化消息中:

solidity
let init: StateInit = initOf SecondContract(arg1, arg2);
let address: Address = contractAddress(init);
let value: Int = ton("1");
send(SendParameters{
    // 默认情况下,bounce 设置为 true
    to: address,
    value: value,
    mode: SendIgnoreErrors, // 发生错误时也不中止
    code: init.code,
    data: init.data,
    body: "Hello, World!".asComment(), // 非必需,可以省略
});