分享百科

Yul

该视频的核心内容是展示如何使用 YUL (YORL) 编写几乎全部的智能合约,并演示了如何通过 Solidity 接口与 YUL 合约进行交互。 视频的关键论据和信息包括: * **YUL 合约结构:** 合约主要由内联汇编代码组成,没有明确定义的 Solidity 函数或接口。 * **函数选择器:** 通过提取调用数据的头四个字节(函数选择器)并使用位移操作,实现类似 switch 语句的函数分发机制。 * **YUL 中的返回值:** YUL 使用内存来存储返回值,并通过 `return` 语句将值返回给调用合约。`leave` 关键字用于在 YUL 函数之间跳转并最终返回。 * **调用数据处理:** 使用 `calldataload` 指令加载调用数据,并根据函数选择器和参数执行不同的逻辑。 * **接口合约:** 为了方便测试,视频创建了一个 Solidity 接口合约,该合约调用 YUL 合约的 fallback 函数,从而实现与 YUL 合约的交互。 * **演示示例:** 视频演示了两个函数:`get123` 返回硬编码值 123,`get999` 接受一个参数,如果参数等于 999 则返回 999,否则返回 888。
52
0
0
2025-04-16 09:34
该视频的核心内容是展示如何使用 Yul (YOR) 语言从智能合约向钱包发送以太币,并对比了使用 Solidity 和 Yul 实现相同功能的 gas 消耗。 **关键论据/信息:** * **功能对比:** 视频展示了 Solidity 和 Yul 两种语言实现从合约向指定地址转移以太币的功能。Solidity 版本使用了 `payable` 地址类型和 `call` 函数,而 Yul 版本则直接使用了 `call` 操作码。 * **Gas 消耗:** 视频重点强调了使用 Yul 语言编写的合约在执行时 gas 消耗更低。通过实际部署和调用合约,视频展示了 Yul 版本的 gas 消耗比 Solidity 版本低约 273 gas。 * **Yul 代码解释:** 视频详细解释了 Yul 代码中 `call` 操作码的各个参数,包括 gas 限制、目标地址、发送的 value (使用 `self-balance` 获取合约余额)、以及用于传递和接收数据的内存区域。`self-balance` 被指出是比 `balance address` 更经济的获取合约余额的方式。 * **代码逻辑:** 两种语言实现的合约都包含一个 `withdraw` 函数,该函数将合约的所有余额转移到预先设定的 owner 地址。合约构造函数被设置为 `payable`,以便在部署时接收以太币。合约会检查交易是否成功,如果交易失败则回滚。
47
0
0
2025-04-16 09:33
该视频主要讲解了在YUL中如何处理日志(logging),特别是如何手动生成和发出事件(events),以及如何区分索引(indexed)和非索引(non-indexed)数据。 **核心内容/主要观点:** * YUL需要手动处理事件的生成和发出,包括生成事件签名的哈希值(keccak256)。 * YUL使用`log`系列操作码(opcode)来发出事件,`log3`用于有三个topic的情况,`log2`用于有两个topic的情况。 * 索引数据存储在交易收据(transaction receipt)的topics中,而非索引数据存储在data中。 **关键论据/关键信息:** * **Solidity vs. YUL:** Solidity会自动处理事件签名哈希的生成,而YUL需要手动生成。 * **事件签名哈希:** 事件签名哈希是事件接口(interface)的keccak256哈希值,用于唯一标识事件类型。 * **`log`操作码:** `log`操作码的参数包括: * `P` 和 `S`: 指向内存中非索引数据的指针和大小。 * `T1`, `T2`, `T3`...: 事件的topics,第一个topic通常是事件签名哈希,后续topics是索引数据。 * **索引 vs. 非索引数据:** 索引数据可以被快速搜索,而非索引数据不能。非索引数据需要先存储在内存中,然后通过`log`操作码指定内存地址和大小。 * **交易收据分析:** 通过分析交易收据的topics和data字段,可以区分事件中的索引和非索引数据。
121
0
0
2025-04-16 09:31
该视频主要讲解了如何在Yul语言中使用`return`、`revert`和`keccak256`这三个关键操作。 **核心内容:** * **Yul中`return`、`revert`和`keccak256`的使用方法:** 视频通过具体的代码示例,展示了如何在Yul中进行数据返回、交易回滚以及哈希计算。 **关键论据/信息:** * **Return:** * Yul中的`return`操作允许返回内存中的数据。 * 返回的数据长度需要与函数接口定义的类型匹配,否则可能导致客户端解码错误。如果返回的数据字节数少于ABI定义的,客户端会报错。如果返回的数据字节数多于ABI定义的,客户端会截取前32个字节,但建议避免这种情况。 * Yul处理的是32字节的字,最终会根据函数接口转换成对应的类型。 * **Revert:** * `revert`用于终止交易并回滚状态。 * 视频展示了Solidity和Yul两种方式实现`revert`,Yul的实现更底层,需要手动检查条件并调用`revert`操作码。 * `revert`通常不返回数据,主要用于错误处理。 * **Keccak256:** * `keccak256`用于计算数据的哈希值。 * Solidity中需要先使用`abi.encode`将数据编码到内存中,再传递给`keccak256`函数。 * Yul中需要手动将数据写入内存,然后调用`keccak256`函数,并指定数据在内存中的起始位置和长度。 * 视频演示了如何在Yul中手动管理内存指针,将多个32字节的数据块写入连续的内存区域,然后计算整个区域的哈希值。 * Yul中的`keccak256`函数返回的哈希值可以存储在内存的“scratch space”中,以便后续返回。 * **内存管理:** 视频强调了Yul中内存管理的重要性,包括使用free memory pointer,以及确保数据在内存中的正确布局。 * **Yul文档和Remix:** 视频推荐使用Yul官方文档和Remix IDE进行学习和测试。
57
0
0
2025-04-16 09:31
该视频主要讲解了Yul语言中ABI编码对内存分配的影响,重点对比了`abi.encode`和`abi.encodePacked`两种编码方式在内存使用上的差异。 **核心内容/主要观点:** * Yul中的ABI编码会影响内存的使用和分配。 * `abi.encode` 会将数据填充到32字节的字长,即使数据本身小于32字节,也会进行填充,导致占用更多内存。 * `abi.encodePacked` 会尝试将数据打包到尽可能小的空间,避免填充,从而节省内存。 **关键论据/关键信息:** * Yul使用自由内存指针(Free Memory Pointer)来管理内存分配,该指针的初始位置为0x80,存储在地址0x40。 * `abi.encode` 会在实际数据之前添加一个32字节的字,用于指示后续数据的长度。 * 视频通过具体的例子展示了`abi.encode`和`abi.encodePacked`在编码相同数据时,自由内存指针的移动距离不同,从而验证了`abi.encodePacked`更节省内存的结论。 * 视频通过调试工具展示了内存中的数据布局,清晰地展示了填充和打包的区别。
128
0
0
2025-04-16 09:28
该视频的核心内容是讲解Solidity如何管理内存中的空闲内存指针(free memory pointer),以及如何使用Yul语言访问和操作它。视频强调了在使用Yul直接操作内存时,需要手动更新空闲内存指针,否则可能导致意想不到的后果。 **关键论据/信息:** 1. **空闲内存指针的位置:** Solidity将空闲内存指针存储在内存地址`0x40`处。初始值通常为`0x80`。 2. **Solidity的自动管理:** 当使用Solidity代码(例如,将数据复制到内存)时,Solidity编译器会自动更新空闲内存指针。 3. **Yul的手动管理:** 当使用Yul语言直接访问和修改内存时(例如,使用`mload`和`mstore`),Solidity不会自动更新空闲内存指针。 4. **`msize`操作码:** `msize`操作码返回函数调用期间访问的最远内存位置。它与空闲内存指针不同,空闲内存指针是Solidity用于分配新内存的指针。 5. **潜在风险:** 如果使用Yul写入内存但不更新空闲内存指针,可能会覆盖Solidity管理的数据,导致程序出错。 6. **示例代码:** 视频通过示例代码演示了如何使用Yul读取和写入内存,以及如何使用`msize`操作码。示例还展示了如何使用Hardhat控制台日志输出空闲内存指针的值。
204
0
0
2025-04-16 09:28
该视频主要讲解了在Yul(Solidity的底层语言)中如何管理和使用内存,重点介绍了 `mstore` 和 `mstore8` 这两个关键的内存操作指令。 **关键论据/信息:** * **内存使用的必要性:** 智能合约需要内存来返回值、设置参数、获取外部调用值、回退特定字符串、记录日志、部署新合约以及使用 `keccak256` 函数。 * **内存组织:** Solidity中的内存以32字节为增量进行组织,没有垃圾回收机制。 * **关键指令:** 内存管理的关键指令包括 `mload`、`mstore`、`mstore8` 和 `mSize`。 * **`mstore` 的工作方式:** `mstore` 指令将32字节的数据写入指定的内存地址。视频演示了如何使用 `mstore` 将一个32字节的全1值(0xFF...FF)写入内存的特定位置,以及如何通过偏移量改变写入的位置。 * **`mstore8` 的工作方式:** `mstore8` 指令仅修改单个字节。视频演示了 `mstore8` 如何只修改内存地址的第一个字节,以及 `mstore` 如何覆盖 `mstore8` 的结果,因为它操作的是整个32字节的字。 * **内存指针:** 视频提到了空闲内存指针(free memory pointer),并指出后续会深入探讨。
122
0
0
2025-04-16 09:27
该视频主要讲解了如何使用 Yul (YOR) 在 Solidity 合约中处理和读取 mappings (映射) 的数据。 **核心内容/主要观点:** * Yul 可以用来读取 Solidity 合约中 mappings 的数据,包括简单映射、嵌套映射以及地址到动态数组的映射。 * 读取 mapping 数据的关键在于计算出数据存储的位置 (data location),这通常涉及到将 mapping 的 slot (存储位置) 与 key (键) 进行 Keccak-256 哈希运算。 **关键论据/关键信息:** * **简单映射:** 通过 `keccak256(key, slot)` 计算数据位置,然后使用 `sload` 读取数据。 * **嵌套映射:** 按照从左到右的顺序,依次将 key 与 slot 进行 Keccak-256 哈希运算。例如,对于 `mapping(uint256 => mapping(uint256 => uint256))`,先计算 `keccak256(key1, slot)`,再计算 `keccak256(key2, 上一步的结果)`,得到最终的数据位置。 * **地址到动态数组的映射:** * 首先,`keccak256(key, slot)` 得到的是动态数组的长度,而不是数组本身的数据位置。 * 要获取数组中的元素,需要再次进行 Keccak-256 哈希运算,计算 `keccak256(keccak256(key, slot))`,得到数组的起始数据位置。 * 然后,通过将索引 (index) 添加到起始数据位置,即可使用 `sload` 读取数组中特定索引的元素。
53
0
0
2025-04-16 09:26
该视频主要讲解了YUL(YORL)语言中如何处理和存储数组,特别是固定大小数组、动态数组以及较小数据类型(uint8)的动态数组。 **核心内容/主要观点:** YUL处理不同类型的数组的方式不同,理解这些差异对于优化智能合约的存储和gas消耗至关重要。 **关键论据/关键信息:** * **固定大小数组:** 元素按顺序存储在连续的存储槽中,每个元素占用一个完整的32字节的存储槽(slot)。访问元素时,通过数组的起始存储槽加上索引偏移量来定位。 * **动态数组:** 数组的长度存储在数组变量对应的存储槽中。数组的实际数据存储在一个通过对数组变量的存储槽进行keccak256哈希运算得到的新的存储位置开始的连续区域中。这样做是为了避免与合约中其他变量的数据发生冲突。 * **uint8动态数组:** 由于uint8类型小于32字节,YUL会将多个uint8元素紧密地打包到一个存储槽中,以节省存储空间。一个存储槽可以容纳32个uint8元素。
49
0
0
2025-04-16 09:26
该视频深入探讨了如何在 Solidity 智能合约开发中使用 Yul 语言来管理存储槽。 **核心内容/主要观点:** * Yul 允许开发者直接访问和操作智能合约的存储槽,提供了比 Solidity 更底层的控制能力。 * 视频演示了如何使用 Yul 读取和写入存储槽,以及如何处理存储槽中的数据打包(packing)问题。 **关键论据/关键信息:** * **存储槽的概念:** Solidity 中的存储变量会被分配到智能合约内部的索引槽中。 * **.slot 属性:** Yul 中,变量名后加 `.slot` 可以获取该变量在存储中的槽位索引。 * **sload 函数:** Yul 中的 `sload(slot_index)` 函数可以读取指定槽位索引中的数据。 * **sstore 函数:** Yul 中的 `sstore(slot_index, value)` 函数可以将指定值写入指定槽位索引。视频强调了直接使用 `sstore` 的风险,因为它可能导致合约漏洞。 * **数据打包(Packing):** Solidity 会将小于 256 位的变量打包到同一个存储槽中以节省 Gas。 * **偏移量(Offset):** 当变量被打包到同一个存储槽中时,每个变量都有一个偏移量,表示该变量在槽中的起始位置。可以通过 `.offset` 属性获取变量的偏移量。 * **位移(Shifting)和掩码(Masking):** 当需要从打包的存储槽中读取特定变量时,需要使用位移和掩码技术。 * **位移(shr):** 使用 `shr(bits, value)` 函数将数据向右移动指定的位数。 * **掩码(Bitwise AND):** 使用位与运算符 `&` 和掩码来提取所需的数据。 * 视频通过具体的代码示例,展示了如何使用 Yul 读取和写入存储槽,以及如何处理数据打包的情况。
44
0
0
2025-04-16 09:24
该视频主要介绍了Solidity中的汇编语言YUL,以及学习和使用YUL的好处和基本概念。 **核心内容/主要观点:** * YUL是Solidity代码和编译后的字节码之间的中间语言,理解YUL有助于更深入地理解Solidity的工作原理,并能更好地调试和解决Solidity代码中的问题。 * YUL可以提高代码的gas效率,并且Solidity的新特性通常会先在YUL中实现。 **关键论据/关键信息:** * **YUL的优势:** * 更深入地理解Solidity:帮助理解Solidity的底层行为和编译器错误的原因。 * 提前使用新特性:Solidity升级后,新特性通常先在YUL中可用。 * 提高Gas效率:用YUL编写的合约或函数通常更节省Gas。 * **YUL的局限性:** * 底层语言:缺乏Solidity中的许多语法糖和辅助功能。 * 数据类型单一:只有一种数据类型,即256位的字(uint256)。 * 缺乏高级特性:没有存储变量、内存管理、数组、函数参数传递等。 * **YUL的基本概念:** * 数据类型:所有数据都表示为256位的字。 * 变量赋值:使用`:=`进行赋值。 * 作用域:YUL代码块可以访问Solidity中定义的变量。 * 字符串处理:由于YUL处理的是指针,字符串需要使用`bytes32`类型,并且长度不能超过32字节。可以使用`ABI encode`将`bytes32`转换回`string`。 * 布尔值:布尔值在YUL中用32位字的最后一位表示,1为真,0为假。 * 逻辑运算:使用`iszero`进行零值判断,实现逻辑非。 * 控制流:支持`if`语句和`for`循环,但没有`else`语句。 * 函数调用:可以使用算术函数(ADD, DIV, MOD)、比较函数(LT, GT, EQ)等。 * **YUL中的真值和假值:** * 真值:任何非零值都被认为是真。 * 假值:只有零值被认为是假。 * **避免使用`not`进行逻辑非:** * `not`会翻转所有位,而不是简单地返回真或假。应该使用`iszero`来判断是否为零。
517
0
0
2025-04-16 09:23
登链社区