以太坊和Solidity的细节:EVM 内存

本文深入探讨了以太坊虚拟机(EVM)中内存的工作原理,包括其定义、Solidity 中的保留空间、内存布局(如值类型和引用类型的存储方式)以及 gas 成本。此外,文章还提供了关于如何在 Solidity 中有效管理内存的最佳实践,例如避免不必要的内存使用和尊重 Solidity 的内存管理方式。

以太坊和Solidity的细节:EVM内存

内存是solidity智能合约拥有的四个数据位置之一(其他是:storage、calldata和stack)。 简单来说,它是智能合约运行时与之关联的“堆”。 值不会持久化,一旦交易完成,内存内容就会被删除。

内存定义

当调用智能合约时,EVM会为其“实例化”一个内存空间。 该内存是字节寻址的(与字寻址的存储相反),长度为2**256字节,换句话说,内存是一个超长的字节数组。

Solidity 使用内存做很多事情,例如:

  • 向外部调用返回值。
  • 为外部调用设置参数。
  • 从外部调用获取值。
  • 使用错误字符串恢复(Revert)。
  • 记录消息。
  • 创建其他智能合约。
  • 使用 keccak256 函数

Solidity 保留空间

Solidity 以非常特定的方式使用前 4 个内存字(每个字 32 字节 -> 总共前 128 字节):

  • 字 0 和 1(字节 0x00 到字节 0x3F)用作“暂存空间”,用于写入值的临时空间(例如由 sha3 操作码使用)。
  • 字 3(字节 0x40 到字节 0x5F)用作“空闲内存指针”,其中包含内存中上次访问的字节的地址(通过访问,我们指的是写入)。 内存永远不会被清理(没有像其他编程语言那样的垃圾收集器),这意味着空闲内存指针只会增加而永远不会减少。 当合约执行时,空闲内存指针的第一个值始终为 0x80
  • 字 4 (字节 0x60 到字节 0x7F) 始终为空

重要的是要注意,如果开发人员将 YUL(例如以_汇编块_的形式)添加到其智能合约函数中,他/她可以以他/她喜欢的任何方式使用内存数组,这意味着如果合约还运行一些 solidity 生成的代码,则可能存在对内存内容产生混淆/误解的风险……

内存布局

变量可以以不同的方式存储在内存中,具体取决于其数据类型。

值类型

值类型存储在内存中,就像在存储中一样,唯一的区别是变量不能被打包(不与其他变量合并在一起),每个变量占用 32 字节。

引用类型

结构体(Structures) 的管理方式与值类型相同,结构体中的每个变量占用 32 个字节,不执行打包。

固定大小数组的工作方式非常相似,只是第一个字(32 字节)指示数组长度,这样编译器就可以知道数组使用了多少个插槽。

目前,映射(mappings)动态大小数组 无法存储在内存中。

另一方面,bytesstrings 可以存储在内存中,我们可以将它们也视为引用类型(因为它们基本上是字节的动态大小数组)。

Solidity 处理内存中的 bytes/string 的方式就像它处理固定大小的数组一样,但是当 bytes/string 被“调整大小”(添加/删除新的字节/字符)时,Solidity 会在内存中完全重新创建它(而不删除它的前一个副本,记住,内存中没有任何东西会被清除)。

Gas 成本

内存 gas 费用取决于已用内存量,换句话说,取决于上次访问的内存位置(访问以写入或读取值并不重要),这是一个递增的数字,因为内存永远不会被清除……

访问内存位置的操作码有:RETURN、REVERT、MLOAD、MSTORE、MSTORE8。 这些操作码中的每一个都具有固定 gas 费用(MLOAD 为 3 gas,...)加上一个可变的 gas 费用,如果它们访问以前未访问过的内存位置,则可以添加该费用。

这里需要注意的重要一点是,对于使用的前 724 字节内存,这个“可变 gas 费用”呈线性增长,之后,增长变为指数级,这意味着即使内存应该有 2**256 字节长,有些内存位置也无法到达,仅仅是因为交易会耗尽 gas……

最佳实践

  • 尊重 solidity 管理内存的方式:如果你只编写 solidity 代码,则不必关心 solidity 使用内存的方式,但是,如果你开始在 solidity 函数中嵌入一些 YUL,请小心不要弄乱内存(注意预留空间,始终更新空闲内存指针等...)。
  • 除非绝对必要,否则不要使用内存:内存比存储便宜,但比 calldata 更贵。 如果你正在编写一个接收引用类型参数(结构体、数组)的外部函数,请尽量使用 calldata 位置,只有在需要更改参数值时才应使用内存。
  • 原文链接: medium.com/coinmonks/sol...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 1
收藏 1
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
alberto.molina.arribere
alberto.molina.arribere
江湖只有他的大名,没有他的介绍。