06.控制流


文档摘要

title: 06. 控制流 tags: huff control flow jumpi jumpdest bytecode WTF Huff极简入门: 06. 控制流 我最近在重新学Huff,巩固一下细节,也写一个“Huff极简入门”,供小白们使用(编程大佬可以另找教程),每周更新1-3讲。 推特:@0xAAScience 社区:Discord|微信群|官网 wtf.academy 所有代码和教程开源在github: github.com/AmazingAng/WTF-Huff 这一讲,我们将介绍Huff中的控制流,包括跳转标签和 指令。 控制流 EVM底层主要是使用跳转指令 , ,和 进行代码的流程控制。如果你对它们不了解,建议阅读WTF EVM Opcodes教程第9讲。

title: 06. 控制流 tags: - huff - control flow - jumpi - jumpdest - bytecode

WTF Huff极简入门: 06. 控制流

我最近在重新学Huff,巩固一下细节,也写一个“Huff极简入门”,供小白们使用(编程大佬可以另找教程),每周更新1-3讲。

推特:@0xAA_Science

社区:Discord微信群官网 wtf.academy

所有代码和教程开源在github: github.com/AmazingAng/WTF-Huff

这一讲,我们将介绍Huff中的控制流,包括跳转标签和JUMPDEST指令。

控制流

EVM底层主要是使用跳转指令JUMPJUMPI,和JUMPDEST进行代码的流程控制。如果你对它们不了解,建议阅读WTF EVM Opcodes教程第9讲

为了方便开发者使用跳转指令,Huff提供了跳转标签,可以在宏或函数哪定义,由冒号后跟一个单词表示。注意,虽然看起来标签是由于缩进而作为代码块的作用域,但它们实际上只是字节码中的跳转目的地。如果标签下面存在操作,除非程序计数器被更改或执行由revertreturnstopselfdestruct操作码中断,否则它们将被执行。

#define macro MAIN() = takes (0) returns (0) { // 从 calldata 读取值 0x00 calldataload // [calldata @ 0x00] 0x00 eq jump_one jumpi // 如果到达此点,则revert 0x00 0x00 revert // 跳转标签1 jump_one: jump_two jump // 如果到达此点,则revert 0x00 0x00 revert // 跳转标签2 jump_two: 0x00 0x00 return }

在合约中,Main宏先会读取调用的calldata,如果为0,则先跳转到jump_one,接着跳转到jump_two;如果不为0,则不会跳转,继续运行到revert回滚交易。

分析合约字节码

我们可以使用huffc命令获取上面合约的runtime code:

huffc src/06_ControlFlow.huff -r

打印出的bytecode为:

5f355f1461000b575f5ffd5b610013565f5ffd5b5f5ff3

转换成格式化的表格:

pc op opcode stack
[00] 5f PUSH0 0x00
[01] 35 CALLDATALOAD calldata
[02] 5f PUSH0 0x00 calldata
[03] 14 EQ suc
[04] 61 000b PUSH2 0x000b 0x000b suc
[07] 57 JUMPI
[08] 5f PUSH0 0x00
[09] 5f PUSH0 0x00 0x00
[0a] fd REVERT
[0b] 5b JUMPDEST
[0c] 61 0013 PUSH2 0x0013 0x0013
[0e] 56 JUMP
[10] 5f PUSH0 0x00
[11] 5f PUSH0 0x00 0x00
[12] fd REVERT
[13] 5b JUMPDEST
[14] 5f PUSH0 0x00
[15] 5f PUSH0 0x00 0x00
[16] f3 RETURN

我们可以看到,这段字节码的功能:

  1. CALLDATALOADcalldata中读取值
  2. EQ对比数据是否为0。若calldata0suc = 1,程序计数器(PC)通过JUMPI跳转到0x0b位置,也就时跳转标签jump_one标记的地方。若calldata不为0,则会继续运行,直到在0xfdREVERT指令回滚交易。
  3. 0x0b继续运行,程序会遇到JUMP指令,PC跳转到0x13位置,也就是跳转标签jump_two标记的地方。
  4. 0x13继续运行,见到RETURN,返回数据并结束交易。

可以看到Huff的编译器在这里并没有做到最优,因为合约中JUMPDEST的位置可以用1字节表示,但它却用了2字节,0x000b0x0013,浪费了gas。

总结

这一讲,我们介绍了Huff中的控制流。Huff提供了跳转标签,方便开发者使用JUMPJUMPI进行流程控制。


作者与出处
原作者: WTFAcademy
来源:WTFAcademy
整理: 灏天文库整理
由灏天文库结构化整理,提供目录导航、全文检索与在线阅读,便于系统化学习
发布者: 作者: WTFAcademy 转发
评论区 (0)
U