这篇文章开始,我准备开始写一个 TON 合约开发的系列文章,主要是想讲讲 TON 链上的合约开发,读者最好是有一些 Solidity 的合约开发基础,这样读起来比较容易。希望在大家读完这个系列的文章之后,能对 TON 的合约开发有一个大体的了解,并能够自己上手开发项目。 ## TON 合约开发语言 目前 TON 上的合约开发语言主要有下面四个: + Fift,最底层的语言,类似汇编,一般不用学习。 + FunC,官方支持的语言,目前 TON 链上主流的钱包,DEX 等都是由 FunC 编写。类似于 C 语言,上手难度稍高。 + Tact,社区支持的语言,发展比较迅速,语法和文档都持续在更新。类似于 Solidity,上手容易,但目前还有一些功能可能还不太完善,例如不支持合约升级,Gas 较高等。 + Tolk,官方最新推出的语言,宣称要在未来全面替代 FunC,对比 FunC 来说稍微简单一些。并且未来官方文档的所有合约示例应该都要改写为 Tolk。 这几个语言中,目前热度比较高的是 Tact 和 FunC。Tolk 刚刚发布(2024.11),后期发展要看官方生态的动作。我们这个系列主要来讲 Tact 和 FunC。Tolk 后期如果发展迅速的话也会讲讲。 这几个语言的关系如下:  由于官方支持的 FunC 难度较高,因此社区便开发支持了 Tact 语言。但其实 Tact 也是最终会编译成 FunC,Fift。而 Tolk 可以理解为 FunC 的另一个变种,它的语法相对能简单一些。最终它们都会被编译成 Fift。 Tact 和 FunC 目前来看是取决于开发者取舍的两种语言: Tact 好学,开发起来简单,但是它还有一些功能仍在完善,如果需要实现某些特定功能,可能无法做到,并且合约消耗的 Gas 相对较高。 FunC 难学,并且在开发的时候需要考虑更多底层的问题,例如消息格式处理等,但它支持的功能也最全面,合约耗费的 Gas 也更少。 如果只是开发一些简单的合约,例如一些简单的 Token,NFT 等,Tact 就足够了。但是如果要深入 TON 的合约开发,FunC 还是有必要学习的。并且 TON 链上目前的主流钱包,DEX 等都是由 FunC 开发的。如果不懂 FunC,这些合约的代码也很难看懂,更不用说与它们进行乐高的集成了。 Tolk 目前还处在较初期,我们先暂不考虑。 ## TON 架构 TON 采用了 Masterchain - WorkChain 机制,有一条 Masterchain,最多支持创建 2^32 条 Workchain(目前只有一条)。 我们可以将其简单理解为波卡的 中继链 - 平行链,或者以太坊 L1 - L2 的关系。我们开发的合约一般都在 WorkChain(L2)上部署执行,而 Masterchain(L1) 主要负责区块链的底层操作例如出块等。 ## TON 合约机制 TON 链并不是常见的 EVM 架构,它是一个异步的区块链。 在 EVM 中,合约之间互相调用是一个很常见的场景,并且是原子化的,也就是说,不论一个交易中涉及到多少次合约之间的互相调用,只要有一步出错,那么整个交易都会回滚,和什么都没发生一样。并且不论多长的调用链,它们都是在一条交易中的,只要这条交易上链,那么这个调用链的执行都是在同一时刻就完成了。 但是在 TON 中,它不支持合约之间的相互调用。那合约之间怎么交互呢,需要靠消息发送机制。我们可以理解为,地球向太空中的卫星发送消息,假设有下面的场景:  在 A 时刻,地球上的人做完了一系列事情,然后向卫星发送消息。 卫星在 B 时刻接收消息,并进行一系列的处理,然后向地球回传消息。 地球在 C 时刻收到回传消息,并进行处理。 在 EVM 的场景下,我们完成这一系列操作,只需要直接调用别的合约即可。但是在 TON 中,由于我们只能采用消息发送机制,因此就只能和上面的地球卫星之间发送消息一样,合约之间也只能发送消息。而且这一系列操作也不是同一时刻就能完成的,A 时刻开始发送的消息,C 时刻才能完成。最难的是,和 EVM 的原子化不同,如果 B 时刻发生了错误,那么 A 时刻已经发生的动作是没法回滚的。如果 C 时刻发生了错误,那么 A 和 B 时刻已经发生的动作也是没法回滚的! 在这个限制下,一个在 EVM 上很简单的逻辑,在 TON 上可能就会变得很复杂。因此我们在开发 TON 合约的时候就需要更加小心,以避免更多的问题。 ## TON 钱包 在 EVM 中,地址分为 EOA 和合约地址。我们平时常用的 MetaMask 所创建的钱包地址就是 EOA,这个地址自身没有代码。但是在 TON 中,所有的钱包都是智能合约。既然是合约,那就是由代码组成的。这里又引入了另一个点,就是钱包合约的实现方式不同,那么它的功能可能就有一些差距。比如说我使用的是 A 公司开发的钱包,你使用的是 B 公司开发的钱包,那咱俩的钱包的合约代码就不同,可能就会有一些功能上的差距。 TON 上有一个很重要的概念是,合约地址是由(代码 + 初始化参数)决定的,即:  也就是说,如果合约代码一致,合约初始化参数一致,那么得到的就是固定的合约地址。 TON 上钱包是靠助记词生成的,那么由于上面的原因,即使是同一份助记词,如果使用的是不同的钱包,那么得到的合约地址也是不一样的。即:  由于钱包是合约,那么我们想要使用钱包,这个合约必须存在才可以。也就是说,这个合约必须要被部署才行。一般当我们使用一个钱包产品(例如 TonKeeper)时,它会为我们提供初始的助记词,并根据这套助记词和它们的合约生成出一个地址,我们需要首先向这个地址打入一定量的 Gas,然后对其进行部署。我们不需要手动进行部署,在第一笔任何操作之前,合约会自动进行部署。 ## TON 合约地址 在 EVM 中,一个地址在任何链上的显示形式都是固定的。例如 0xabc123 这个地址,在任何 EVM 兼容链上,都是这个形式的地址。但是在 TON 中,一个地址有多种表达形式。例如,TON 主网上的 USDT 地址是 > EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs 但是它一共有这么多种的表达形式([地址转换工具](https://ton.org/address/)):  主网和测试网的地址不相同,这里引入了一个 Bounce 的概念。 我们前面说到,合约之间需要靠发送消息来交互。如果一条消息在处理过程中发生了错误,这时消息发送方 A 已经更改了状态,TON 为此提供了一个 bounce 容错机制,使得消息可以回弹,如果 A 也同时设置的回弹消息的处理逻辑,那就可以将 A 的状态变更回之前的状态。 可能比较难理解,不着急,我们后面会随着合约开发的学习来慢慢消化。 ## 合约租金 我们前面说过,TON 上的所有地址都是合约。TON 有一个神奇的机制是,所有的合约都需要交租金。它的逻辑是,将合约类比成传统 Web2 的各种网站、APP,这些网站是需要为自己租用服务器付费的。那么 TON 上的合约也需要为自己在链上有一席之地来付费。比如,一个钱包中有 1 TON 余额,那么在 N 年后,可能就只剩 0.9 TON 的余额,消失的 0.1 TON 就是在 TON 链上缴纳的租金。如果一个合约长时间都没有余额,那么它就会被冻结,无法使用,因此我们在合约开发中也需要考虑到这点。 ## 总结 TON 的合约开发相较于 EVM 的合约,有很大的不同。如果一开始不习惯也很正常,这些概念需要随着学习来慢慢消化。后面的文章开始介绍 Tact 和 FunC 的开发,我们可以慢慢学习理解。 ## 关于我 欢迎[和我交流](https://linktr.ee/xyymeeth)
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.