读者好,这是 TON 生态系统之旅的第二部分。在这一部分中,我们将继续研究 FunC 的不同方面。
目前的状况
在上一部分中,我们熟悉了 TON 网络中的智能合约。我们弄清楚了为什么需要消息,为什么需要 c4 寄存器,并且还讨论了测试。现在让我们来谈谈允许您创建复杂智能合约的事情。
OP和费用
当我们继续探索 TON 生态系统时,我们将了解到有一些建议智能合约进行交互的规则。
TON 中的智能合约通过发送所谓的内部消息来相互交互。为了方便智能合约之间的交互,制定了建议。这些建议的关键是将query_id
和添加op
到消息的开头:
op
标识要执行的操作,或要调用的智能合约的方法。query_id
在所有查询响应内部消息中使用,以指示响应与查询相关(如果我们想要发送响应)。
它看起来是这样的:
() recv_internal (int balance, int msg_value, cell in_msg_full, slice in_msg_body) {
int op = in_msg_body~load_int(32);
int query_id = in_msg_body~load_uint(64);
if (op == 1) {
;;
} else {
if (op == 2) {
;;
} else {
;; there might be an exception here
}
}
}
您在 TON 中旅行的时间越长,您对与环境交互的了解就越多。你团队的客户经理说他知道如何让你的智能合约更加高效。
TON 网络有自己的货币 - Toncoin。多亏了 Toncoin 加密货币,才有了计算市场。这样的市场为参与者验证和满足交易请求并向网络提供计算资源提供了经济激励。任何广播交易请求的参与者都必须以 Toncoin 支付费用。智能合约也使用 Toncoin,因此您需要考虑在费用方面优化智能合约。
在 TON 中,交易费用包括:
storage_fees
- 区块链中“位置”的费用。
in_fwd_fees
- 导入消息的费用(这是我们处理外部消息时的情况)。
computation_fees
- 执行TVM指令的费用。
action_fees
- 与处理一系列操作(例如,发送消息)相关的费用。
out_fwd_fees
- 导入外发消息的费用。
inline
降低费用的一种简单技术是对调用一次或两次的函数使用关键字,以便在编译时将它们简单地替换到函数调用站点中。
例如,如果您需要加载数据,例如仅加载一次:
(slice, slice) load_data () inline {
var ds = get_data().begin_parse();
return (ds~load_msg_addr(), ds~load_msg_addr());
}
更多关于op
.
测试操作
作为一名经验丰富的 TON 旅行者,您知道一切都必须经过测试......
为了测试 op 的工作,我们需要了解合约执行了哪些操作。注册 c5 将帮助我们解决这个问题。
c5 - 包含输出操作。该值是一个单元格。
来自智能合约的传出消息被写入寄存器 c5。因此,在测试中,我们将在地址之间发送消息并解析 c5 寄存器以确保一切正确。
寄存器 c5 减法示例:
(int, cell) extract_single_message(cell actions) impure inline method_id {
;; ---------------- Parse actions list
;; prev:^(OutList n)
;; #0ec3c86d
;; mode:(## 8)
;; out_msg:^(MessageRelaxed Any)
;; = OutList (n + 1);
slice cs = actions.begin_parse();
throw_unless(1010, cs.slice_refs() == 2);
cell prev_actions = cs~load_ref();
throw_unless(1011, prev_actions.cell_empty?());
int action_type = cs~load_uint(32);
throw_unless(1013, action_type == 0x0ec3c86d);
int msg_mode = cs~load_uint(8);
throw_unless(1015, msg_mode == 64);
cell msg = cs~load_ref();
throw_unless(1017, cs.slice_empty?());
return (msg_mode, msg);
}
关于测试的课程op
。
哈希映射
随着智能合约复杂性的增加,出现了如何存储和处理数据的问题,例如,相对于时间而言。这个机会是由哈希图或它们也称为字典提供的。
Hashmap是一种用树表示的数据结构。Hashmap - 将键映射到任意类型的值,以便可以快速查找和修改。更多详细信息请参见第 3.3 条。在 FunC 中,哈希图由 cell 表示。
为了方便使用哈希图,FunС 标准库提供了许多函数。例如,如果要向 hashmap 添加数据,可以使用dict_set
,它将 dict 字典中与键索引键 n 位深度关联的值设置为切片并返回结果字典。
dic~udict_set(256, key, in_msg_body);
要使用哈希图,我们需要循环:
循环通常用于处理哈希图。FunC 有三个循环:repeat
, until
, while
。
最方便的哈希图循环是until
,因为许多使用哈希图的函数都会返回一个标志,通过该标志可以方便地检查循环终止条件。
测试哈希图
当我们测试使用某种时间逻辑的合约时,需要使用c7寄存器。因此,在智能合约的测试中,我们需要编写一个帮助函数来处理时间。
c7 — 包含临时数据的根。它是一个元组。
辅助函数将允许我们将需要的任何时间放入寄存器中。辅助函数如下所示:
tuple get_c7_now(int now) inline method_id {
return unsafe_tuple([unsafe_tuple([
0x076ef1ea, ;; magic
0, ;; actions
0, ;; msgs_sent
now, ;; unixtime
1, ;; block_lt
1, ;; trans_lt
239, ;; randseed
unsafe_tuple([1000000000, null()]), ;; balance_remaining
null(), ;; myself
get_config() ;; global_config
])]);
}
由于智能合约具有存储值和接收的逻辑,因此我们必须测试从之前的测试中接收到的数据,这不能使用标准 FunC 库来完成,但是在 toncli 中这一刻是经过深思熟虑的:在 toncli 的描述中测试时,有get_prev_c4
/get_prev_c5
函数允许您从之前的测试中获取c4
/c5
单元格。
为了方便我们使用堆栈中的元组,标准库具有以下函数:
- first - 返回元组的第一个元素。
- Second - 返回元组的第二个元素。
进一步的路径
恭喜,我们在旅程中取得了重大进展。
在下一部分中,我们将讨论 TON 中的代币标准和 NFT。
本站所提供的所有资讯均仅供读者参考。这些资讯不代表任何投资建议、提供、邀请或推荐。读者在使用这些资讯时,应当考虑自己的个人需求、投资目标和财务状况。所有投资都伴随着一定的风险,在做出任何投资决策之前请多加留意。