TON(The Open Network)以其创新特性和强大的智能合约性能,不断拓宽区块链技术的边界。基于早期的区块链平台(如以太坊等)的经验与教训,TON为开发者提供了一个更加高效且灵活的开发环境。其中推动这一进步的关键要素之一便是Tact编程语言。
Tact是专为TON链设计的一种全新编程语言,以高效与简洁为核心目标。它易于学习和使用,并与智能合约完美契合。Tact是一种静态类型语言,拥有简单的语法和强大的类型系统。
尽管如此,开发者在使用FunC时遇到的许多问题,在Tact开发中仍然存在。以下将结合审计实践案例,分析Tact开发中的一些常见错误。
数据结构
可选地址
Tact语言简化了声明、解码和编码的数据结构。然而,开发者仍需保持谨慎。我们来看一个例子:
这是根据TEP-74标准用于转移jetton的内部传输(InternalTransfer)消息声明。请注意response_destination的声明,它是一个地址(Address)类型。在Tact中,要求地址必须是非零地址。然而,jetton标准的参考实现允许零地址(addr_none),它由两个零位表示。这意味着用户或其他合约可能会尝试发送带有零响应地址的jetton,而该操作会意外失败。
此外,如果用户发送给其钱包的Transfer消息允许设置response_destination,而从发送方钱包到接收方钱包的InternalTransfer消息却不支持该参数,那么jetton将会“飞出”,意味着jetton无法到达目标地址,最终导致丢失。稍后,我们将讨论一种例外情况,即如何正确处理被退回的消息。息会被妥善处理。
在这种情况下,允许零地址的更好结构声明应为Address?,但在Tact中,将可选地址传递到下一条消息目前较为繁琐。
数据序列化
在Tact中,开发者可以指定字段的序列化方式。
本例中,totalAmount将序列化为coins,而releasedAmount将序列化为int257(默认为Int)。releasedAmount可以是负值,并且将占用257位。在大多数情况下,省略序列化类型不会带来问题;然而,如果数据涉及到通信,这就变得至关重要。
以下是我们审计的项目中的一个例子: