title: 02. 存储 tags: huff storage FREESTORAGEPOINTER bytecode WTF Huff极简入门: 02. 存储 我最近在重新学Huff,巩固一下细节,也写一个“Huff极简入门”,供小白们使用(编程大佬可以另找教程),每周更新1-3讲。 推特:@0xAAScience 社区:Discord|微信群|官网 wtf.academy 所有代码和教程开源在github: github.com/AmazingAng/WTF-Huff 这一讲,我们将介绍Huff中的存储,特别是 关键字。 Huff中的存储 EVM中的存储(storage)是一种持久化存储空间,存在其中的数据在交易之间可以保持。它是EVM状态的一部分,支持以256 bit为单位的读写。
title: 02. 存储 tags: - huff - storage - FREE_STORAGE_POINTER - bytecode
我最近在重新学Huff,巩固一下细节,也写一个“Huff极简入门”,供小白们使用(编程大佬可以另找教程),每周更新1-3讲。
所有代码和教程开源在github: github.com/AmazingAng/WTF-Huff
这一讲,我们将介绍Huff中的存储,特别是FREE_STORAGE_POINTER关键字。
EVM中的存储(storage)是一种持久化存储空间,存在其中的数据在交易之间可以保持。它是EVM状态的一部分,支持以256 bit为单位的读写。

Huff中的存储并不复杂,可以通过FREE_STORAGE_POINTER()关键字来跟踪合约中未使用的存储槽(free storage)。下面,我们声明了2个存储槽STORAGE_SLOT0和STORAGE_SLOT1:
#define constant STORAGE_SLOT0 = FREE_STORAGE_POINTER() #define constant STORAGE_SLOT1 = FREE_STORAGE_POINTER()
EVM的存储使用键值对存储数据,存储槽是其中的键。在Huff中,编译器将在编译时从0开始分配自由存储槽。在上面的例子中,会将0分配给STORAGE_SLOT0,将1分配给STORAGE_SLOT1。
我们可以通过将存储槽括在方括号中来在代码中引用该槽 - 就像这样[STORAGE_SLOT0]。在下面的代码中,我们在MAIN()宏中将0x69存入STORAGE_SLOT0,然后将0x420存入STORAGE_SLOT1。
#define macro MAIN() = takes(0) returns(0) { 0x69 // [0x69] [STORAGE_SLOT0] // [value_slot0_pointer, 0x69] sstore // [] 0x420 // [0x420] [STORAGE_SLOT1] // [value_slot1_pointer, 0x420] sstore // [] }
我们可以使用huffc命令获取上面合约的runtime code:
huffc src/02_Storage.huff -r
打印出的bytecode为:
60695f55610420600155
直接看字节码可能有些令人头大,我们将它转换成下面的表格:
| pc | op | opcode | stack |
|---|---|---|---|
| [00] | 60 69 | PUSH1 0x69 | 0x69 |
| [02] | 5f | PUSH0 | 0 0x69 |
| [03] | 55 | SSTORE | |
| [04] | 61 0420 | PUSH2 0x420 | 0x0420 |
| [07] | 60 01 | PUSH1 0x01 | 0x01 |
| [09] | 55 | SSTORE |
可以看到,字节码用了两次SSTORE,分别将0x69和0x420存入存储槽0和1。
这一讲,我们介绍了如何在Huff中使用存储,特别是FREE_STORAGE_POINTER()关键字,它可以跟踪合约中未使用的存储槽,并在编译时分配它们。