FunC 开发手册
创建 FunC 开发手册的核心原因是将所有 FunC 开发者的经验汇集在一个地方,以便未来的开发者们使用!
与 FunC 文档相比,本文更侧重于 FunC 开发者在智能合约开发过程中每天都要解决的任务。
基础知识
如何编写 if 语句
假设我们想检查某个事件是否相关。为此,我们使用标志变量。记住在 FunC 中 true 是 -1 而 false 是 0。
int flag = 0; ;; false
if (flag) {
;; do something
}
else {
;; reject the transaction
}
💡 注意
我们不需要使用
==操作符,因为0的值是false,所以任何其他值都将是true。
💡 有用的链接
如何编写 repeat 循环
以指数运算为例
int number = 2;
int multiplier = number;
int degree = 5;
repeat(degree - 1) {
number *= multiplier;
}
💡 有用的链接
如何编写 while 循环
当我们不知道要执行特定操作多少次时,while 循环很有用。例如,取一个 cell,我们知道它可以存储最多四个对其他 cell 的引用。
cell inner_cell = begin_cell() ;; create a new empty builder
.store_uint(123, 16) ;; store uint with value 123 and length 16 bits
.end_cell(); ;; convert builder to a cell
cell message = begin_cell()
.store_ref(inner_cell) ;; store cell as reference
.store_ref(inner_cell)
.end_cell();
slice msg = message.begin_parse(); ;; convert cell to slice
while (msg.slice_refs_empty?() != -1) { ;; we should remind that -1 is true
cell inner_cell = msg~load_ref(); ;; load cell from slice msg
;; do something
}
💡 有用的链接
如何编写 do until 循环
当我们需要循环至少运行一次时,我们使用 do until。
int flag = 0;
do {
;; do something even flag is false (0)
} until (flag == -1); ;; -1 is true
💡 有用的链接
如何确定 slice 是否为空
在处理 slice 之前,需要检查它是否有数据以便正确处理。我们可以使用 slice_empty?() 来做到这一点,但我们必须考虑到,如果有至少一个 bit 的数据或一个 ref,它将返回 -1(true)。
;; creating empty slice
slice empty_slice = "";
;; `slice_empty?()` returns `true`, because slice doesn't have any `bits` and `refs`
empty_slice.slice_empty?();
;; creating slice which contains bits only
slice slice_with_bits_only = "Hello, world!";
;; `slice_empty?()` returns `false`, because slice have any `bits`
slice_with_bits_only.slice_empty?();
;; creating slice which contains refs only
slice slice_with_refs_only = begin_cell()
.store_ref(null())
.end_cell()
.begin_parse();
;; `slice_empty?()` returns `false`, because slice have any `refs`
slice_with_refs_only.slice_empty?();
;; creating slice which contains bits and refs
slice slice_with_bits_and_refs = begin_cell()
.store_slice("Hello, world!")
.store_ref(null())
.end_cell()
.begin_parse();
;; `slice_empty?()` returns `false`, because slice have any `bits` and `refs`
slice_with_bits_and_refs.slice_empty?();
💡 有用的链接
如何确定 slice 是否为空(不含任何 bits,但可能包含 refs)
如果我们只需要检查 bits,不关心 slice 中是否有任何 refs,那么我们应该使用 slice_data_empty?()。
;; creating empty slice
slice empty_slice = "";
;; `slice_data_empty?()` returns `true`, because slice doesn't have any `bits`
empty_slice.slice_data_empty?();
;; creating slice which contains bits only
slice slice_with_bits_only = "Hello, world!";
;; `slice_data_empty?()` returns `false`, because slice have any `bits`
slice_with_bits_only.slice_data_empty?();
;; creating slice which contains refs only
slice slice_with_refs_only = begin_cell()
.store_ref(null())
.end_cell()
.begin_parse();
;; `slice_data_empty?()` returns `true`, because slice doesn't have any `bits`
slice_with_refs_only.slice_data_empty?();
;; creating slice which contains bits and refs
slice slice_with_bits_and_refs = begin_cell()
.store_slice("Hello, world!")
.store_ref(null())
.end_cell()
.begin_parse();
;; `slice_data_empty?()` returns `false`, because slice have any `bits`
slice_with_bits_and_refs.slice_data_empty?();
💡 有用的链接
如何确定 slice 是否为空(没有任何 refs,但可能有 bits)
如果我们只对 refs 感兴趣,我们应该使用 slice_refs_empty?() 来检查它们 的存在。
;; creating empty slice
slice empty_slice = "";
;; `slice_refs_empty?()` returns `true`, because slice doesn't have any `refs`
empty_slice.slice_refs_empty?();
;; creating slice which contains bits only
slice slice_with_bits_only = "Hello, world!";
;; `slice_refs_empty?()` returns `true`, because slice doesn't have any `refs`
slice_with_bits_only.slice_refs_empty?();
;; creating slice which contains refs only
slice slice_with_refs_only = begin_cell()
.store_ref(null())
.end_cell()
.begin_parse();
;; `slice_refs_empty?()` returns `false`, because slice have any `refs`
slice_with_refs_only.slice_refs_empty?();
;; creating slice which contains bits and refs
slice slice_with_bits_and_refs = begin_cell()
.store_slice("Hello, world!")
.store_ref(null())
.end_cell()
.begin_parse();
;; `slice_refs_empty?()` returns `false`, because slice have any `refs`
slice_with_bits_and_refs.slice_refs_empty?();
💡 有用的链接
如何确定 cell 是否为空
要检查 cell 中是否有任何数据,我们应首先将其转换为 slice。如果我们只对 bits 感兴趣,应使用 slice_data_empty?();如果只对 refs 感兴趣,则使用 slice_refs_empty?()。如果我们想检查是否有任何数据,无论是 bit 还是 ref,我们需要使用 slice_empty?()。
cell cell_with_bits_and_refs = begin_cell()
.store_uint(1337, 16)
.store_ref(null())
.end_cell();
;; Change `cell` type to slice with `begin_parse()`
slice cs = cell_with_bits_and_refs.begin_parse();
;; determine if slice is empty
if (cs.slice_empty?()) {
;; cell is empty
}
else {
;; cell is not empty
}
💡 有用的链接
如何确定 dict 是否为空
有一个 dict_empty?() 方法可以检查 dict 中是否有数据。这个方法相当于 cell_null?(),因为通常一个空的 cell 就是一个空字典。
cell d = new_dict();
d~udict_set(256, 0, "hello");
d~udict_set(256, 1, "world");
if (d.dict_empty?()) { ;; Determine if dict is empty
;; dict is empty
}
else {
;; dict is not empty
}
💡 有用的链接
文档中的“new_dict()” 创建空字典
[文档中的“dict_set()”](/develop/
如何确定 tuple 是否为空
在处理 tuple 时,重要的是始终知道里面是否有任何值可供提取。如果我们试图从一个空的 "元组 "中提取值,就会出现错误:不是有效大小的元组",并显示 "退出代码 7"。
;; Declare tlen function because it's not presented in stdlib
(int) tlen (tuple t) asm "TLEN";
() main () {
tuple t = empty_tuple();
t~tpush(13);
t~tpush(37);
if (t.tlen() == 0) {
;; tuple is empty
}
else {
;; tuple is not empty
}
}
💡 Noted
我们正在声明 tlen 汇编函数。你可以在 此处 和 list of all assembler commands 阅读更多内容。
💡 注意
我们声明了 tlen 汇编函数。你可以在这里阅读更多,并查看所有汇编指令列表。
文档中的"tpush()"