Skip to content

Commit

Permalink
update 15 import
Browse files Browse the repository at this point in the history
  • Loading branch information
AmazingAng committed Sep 30, 2023
1 parent 9ff5698 commit 54a0056
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@

**第14讲:映射**[Code](https://github.com/WTFAcademy/WTF-Huff/blob/main/src/14_Mapping.huff) | [文章](https://github.com/WTFAcademy/WTF-Huff/blob/main/tutorials/14_Mapping/readme.md)

**第15讲:引入**[Code](https://github.com/WTFAcademy/WTF-Huff/blob/main/src/15_Import.huff) | [文章](https://github.com/WTFAcademy/WTF-Huff/blob/main/tutorials/15_Import/readme.md)

## 运行模版项目

### 配置环境
Expand Down
21 changes: 21 additions & 0 deletions src/15_Import.huff
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "./15_Imported.huff"

/* 方法 */
#define macro SET_VALUE() = takes (0) returns (0) {
0x04 calldataload // [value]
[VALUE_LOCATION] // [ptr, value]
sstore // []
stop // []
}

#define macro GET_VALUE() = takes (0) returns (0) {
// 从存储中加载值
[VALUE_LOCATION] // [ptr]
sload // [value]

// 将值存入内存
0x00 mstore

// 返回值
0x20 0x00 return
}
21 changes: 21 additions & 0 deletions src/15_Imported.huff
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* 接口 */
#define function setValue(uint256) nonpayable returns ()
#define function getValue() view returns (uint256)

/* 存储槽位 */
#define constant VALUE_LOCATION = FREE_STORAGE_POINTER()

// 合约的主入口,判断调用的是哪个函数
#define macro MAIN() = takes (0) returns (0) {
// 通过selector判断要调用哪个函数
0x00 calldataload 0xE0 shr
dup1 __FUNC_SIG(setValue) eq set jumpi
dup1 __FUNC_SIG(getValue) eq get jumpi
// 如果没有匹配的函数,就revert
0x00 0x00 revert

set:
SET_VALUE()
get:
GET_VALUE()
}
132 changes: 132 additions & 0 deletions tutorials/15_Import/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
---
title: 15. 引用
tags:
- huff
- interface
- mapping
- bytecode
---

# WTF Huff极简入门: 15. 引用

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

推特:[@0xAA_Science](https://twitter.com/0xAA_Science)

社区:[Discord](https://discord.gg/5akcruXrsk)[微信群](https://docs.google.com/forms/d/e/1FAIpQLSe4KGT8Sh6sJ7hedQRuIYirOoZK_85miz3dw7vA1-YjodgJ-A/viewform?usp=sf_link)[官网 wtf.academy](https://wtf.academy)

所有代码和教程开源在github: [github.com/AmazingAng/WTF-Huff](https://github.com/AmazingAng/WTF-Huff)

-----

这一讲,我们介绍如何在Huff合约中引入其他合约,复用代码。

## 引入

Huff支持在合约中使用`#include`关键字引入其他合约,方便复用代码。下面我们介绍引入的规则。

### 1. 引入合约的顺序

当一个Huff合约(例如`C.huff`)引入了其他合约时,这些被引入的合约将按照它们被引入的顺序插入到当前的合约上方。

例如,如果你有一个`C.huff`合约,它首先引入了`A.huff`,然后引入了`B.huff`,那么这与直接在一个合约中按顺序有`A``B``C`是一样的。

这意味着合约内容的逻辑结构将是这样的:
```
内容来自A.huff
----------
内容来自B.huff
----------
内容来自C.huff
```

### 2. 函数或常量的覆盖

如果在引入的合约序列中,某个函数或常量被后续的合约覆盖,那么最后覆盖的版本会生效。

例如,如果`A.huff`有一个函数`MAIN()``B.huff`也有一个函数`MAIN()`,并且`C.huff`再次有一个函数`MAIN()`,那么最终生效的将是`C.huff`中的`MAIN()`函数。这与`A.huff``B.huff`中没有`MAIN()`函数的结果是相同的。

### 3. 如何在Huff中引入合约

在Huff中,你可以使用`#include`指令来引入其他Huff合约。格式如下:
```c
#include "合约路径/合约名.huff"
```
例如,要引入当前文件夹下名为`ContractName.huff`的合约,你可以这样写:
```c
#include "./ContractName.huff"
```

## 示例

我们可以将WTF Huff第7讲中的[07_Interface.huff](https://github.com/WTFAcademy/WTF-Huff/blob/main/src/07_Interface.huff)合约分成两个合约,然后用引入的方式将两部分并在一起。

第一部分`15_Imported.huff`包含接口、存储槽,和Main宏:

```c
/* 接口 */
#define function setValue(uint256) nonpayable returns ()
#define function getValue() view returns (uint256)

/* 存储槽位 */
#define constant VALUE_LOCATION = FREE_STORAGE_POINTER()

// 合约的主入口,判断调用的是哪个函数
#define macro MAIN() = takes (0) returns (0) {
// 通过selector判断要调用哪个函数
0x00 calldataload 0xE0 shr
dup1 __FUNC_SIG(setValue) eq set jumpi
dup1 __FUNC_SIG(getValue) eq get jumpi
// 如果没有匹配的函数,就revert
0x00 0x00 revert

set:
SET_VALUE()
get:
GET_VALUE()
}
```

第二部分包含`SET_VALUE()``GET_VALUE`两个方法,并且引入了第一部分:

```c
#include "./15_Imported.huff"

/* 方法 */
#define macro SET_VALUE() = takes (0) returns (0) {
0x04 calldataload // [value]
[VALUE_LOCATION] // [ptr, value]
sstore // []
stop // []
}

#define macro GET_VALUE() = takes (0) returns (0) {
// 从存储中加载值
[VALUE_LOCATION] // [ptr]
sload // [value]

// 将值存入内存
0x00 mstore

// 返回值
0x20 0x00 return
}
```

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

```shell
huffc src/15_Import.huff -r
```

打印出的bytecode为:

```
5f3560e01c8063552410771461001e5780632096525514610025575f5ffd5b6004355f55005b5f545f5260205ff3
```

这与第7讲的合约字节码一致,说明我们成功引入了第一部分的合约。

## 总结

理解Huff的引入规则是非常重要的,因为它决定了代码的结构以及哪些函数/常量会在合约中生效。在编写或分析Huff合约时,我们需要考虑到这些规则。

0 comments on commit 54a0056

Please sign in to comment.