什么是 Yul?
Yul 是一种中间编程语言,可以在智能合约内部用它写一种形式的汇编语言。虽然我们通常看到 Yul 用在智能合约内部,但你也可以完全用 Yul 编写一个智能合约。
理解 Yul 可以提升你的智能合约水平,让你了解 solidity 底层发生了什么,这反过来能帮你为用户节省 gas 费用。
我们可以通过以下语法在智能合约中识别出 Yul。
在本文接下来的部分,我们将通过示例讨论使用 Yul 的基础知识,建议你在 Remix 中跟着一起操作。
Yul 中的变量赋值、运算与求值
首先要讲的是简单的运算。Yul 有 +、-、、/、%、、<、> 和 =。
注意 >= 和 <= 不在 Yul 可用运算符列表中,因为 Yul 没有这些运算符。此外,求值结果不是 true 或 false,而是分别等于 1 或 0。好了,让我们开始学习一些 Yul 吧!
在继续之前,我们先来快速看一个例子。
Yul 中的 for 循环与 if 语句
为了学习 for 循环和 if 语句,我们来写一个函数,统计一串数字中有多少个偶数。
if 语句的语法与 Solidity 类似,但条件不需要放在括号里。
对于 for 循环,注意在声明 i 和递增 i 时我们使用了括号,但在判断条件时没有使用。此外,我们用 continue 跳过了循环的某一次迭代。在 Yul 中我们也可以使用 break 语句。
Yul 中存储的工作原理
一个智能合约有 2²⁵⁶ 个存储槽(slot)。声明变量时,我们从槽 0 开始并依次递增。每个槽长 256 位(32 字节);这也是 uint256 和 bytes32 名称的由来。所有变量都会被转换为十六进制。如果使用的是像 uint128 这样的变量,我们不会用整个槽来存储它,而是在左侧用 0 补齐。
想了解更多关于 Yul 存储的工作原理,请阅读我们另一篇涵盖以下内容的文章:
- 数组
- 动态数组
- 映射(Mappings)
- 嵌套映射
如何在 Yul 中读写打包(packed)变量
打包变量指的是对变量进行排序,使它们的存储总量小于 32 字节,从而能够一起放入同一个槽中!打包变量可以节省 gas,是智能合约优化的一项重要技巧。
例如,0x000000000000000000000000000002 和 0x000000000000000000000000000001 可以完美地放入同一个槽,因为它们各占 16 字节(半个槽)。
想了解更多如何在 Yul 中读写打包存储变量,请阅读我们的深度解析文章!
Yul 中内存是如何工作的?
内存的行为与存储不同,它不是持久化的(也就是说,函数执行完毕后,所有变量都会被清空)。Yul 中内存的一些用途包括:
- 为外部调用返回值
- 为外部调用设置函数值
- 从外部调用中获取值
- 使用错误字符串进行 revert
- 记录日志消息
想了解更多关于 Yul 内存的工作原理,请阅读我们另一篇深入探讨该主题的文章!
Yul 中合约调用是如何工作的?
一旦你理解了 Yul 的语法、存储以及内存的工作原理,接下来就该学习如何调用合约了。我们 Yul 系列的最后一篇文章讲解了在 Yul 中如何调用合约,具体包括:
call()- 调用地址 a 处的合约,出错时返回 0,成功时返回 1staticcall()- 与 call(g, a, 0, in, insize, out, outsize) 相同,但不允许状态修改delegatecall()- 与 callcode 相同,但同时保留 caller 和 callvalue
关于合约调用定义的更多信息,可参阅 Yul 语言文档。
相关概览

构建区块链应用
Alchemy 将最强大的 Web3 开发者产品和工具与资源、社区及专业支持结合在一起。


