> 技术文档 > 【区块链安全 | 第三十二篇】内联汇编

【区块链安全 | 第三十二篇】内联汇编


文章目录

  • 内联汇编
    • 示例
    • 访问外部变量、函数和库
    • 需要避免的事项
    • Solidity 中的约定
      • 类型变量的值
      • 内存管理
      • 内存安全
    • 高级内存安全使用

【区块链安全 | 第三十二篇】内联汇编

内联汇编

在 Solidity 语句中,我们可以交错使用内联汇编,这种汇编语言接近以太坊虚拟机(EVM)底层语言。这为我们提供了更精细的控制,尤其在编写库或优化 gas 使用时非常有用。

Solidity 中使用的内联汇编语言是 Yul,它有独立的文档。在这一部分,我们主要讨论内联汇编代码如何与周围的 Solidity 代码交互。

内联汇编是一种低级别访问以太坊虚拟机的方式。它绕过了 Solidity 的一些重要安全特性和检查。因此,我们应仅在确实需要时使用内联汇编,并且在完全理解其影响的情况下使用它。

内联汇编代码块通过 assembly { … } 进行标记,花括号中的代码是 Yul 语言的代码。

不同的内联汇编块之间没有共享命名空间,也就是说,无法在不同的内联汇编块中调用 Yul 函数或访问 Yul 变量。

内联汇编代码可以访问局部 Solidity 变量。

示例

以下示例展示了一个库代码,用于访问另一个合约的代码并将其加载到 bytes 变量中。在“纯 Solidity”中,这也可以通过使用

.code 来实现。不过,重点在于,可重用的汇编库能够在不需要修改编译器的情况下增强 Solidity 语言的功能:

// SPDX-License-Identifier: GPL-3.0pragma solidity >=0.4.16 <0.9.0;library GetCode { function at(address addr) public view returns (bytes memory code) { assembly { // retrieve the size of the code, this needs assembly let size := extcodesize(addr) // allocate output byte array - this could also be done without assembly // by using code = new bytes(size) code := mload(0x40) // new \"memory end\" including padding mstore(0x40, add(code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) // store length in memory mstore(code, size) // actually retrieve the code, this needs assembly extcodecopy(addr, add(code, 0x20), 0, size) } }}

当 Solidity 优化器无法生成高效代码时,内联汇编就显得特别有用。如下例所示:

// SPDX-License-Identifier: GPL-3.0pragma solidity >=0.4.16 <0.9.0;library VectorSum { // This function is less efficient because the optimizer currently fails to // remove the bounds checks in array access. function sumSolidity(uint[] memory data) public pure returns (uint sum) { for

书法艺术字体在线生成