以太坊虚拟机(EVM)内存存取,理解智能合约的高速数据通道
在以太坊区块链的世界中,智能合约是自动执行的协议,而以太坊虚拟机(EVM)则是这些智能合约的运行环境,EVM的设计精巧且复杂,其中内存(Memory)作为一种关键且高效的存储资源,扮演着智能合约执行过程中“高速数据通道”的角色,理解EVM内存的存取机制,对于智能合约开发者优化性能、控制成本以及编写安全高效的代码至关重要。
EVM内存:是什么与为什么?

与持久化存储在区块链上的状态存储(State Storage,由存储槽位组成)不同,EVM内存是一种临时性、易失性的数据存储区域,它存在于智能合约执行期间,一旦合约执行结束,内存中的数据就会被清空,不会写入区块链,这种设计决定了内存的特性和用途:
- 临时性:生命周期仅限于当前交易中合约的执行过程。
- 易失性:断电或执行结束后数据丢失,类似于计算机的RAM。
- 高效性:相比于状态存储,内存的读写操作要快得多,成本也低得多,状态存储的修改会永久记录在链上,需要消耗大量的Gas,而内存操作仅消耗相对较少的Gas。
EVM内存的组织与结构
EVM内存被组织成一个线性的字节数组(byte array),从地址0开始连续排列,内存的分配是“按需增长”的,初始大小为0,当合约需要访问超出当前内存大小的地址时,内存会进行扩展,内存扩展的代价相对较高,因为需要将新的内存页初始化为零,智能合约开发者通常会尽量减少内存扩展的次数,例如通过预先分配足够的内存空间。
内存的最小可寻址单位是字节(byte),EVM提供了一些操作码来以更高效的方式访问内存中的数据,例如按32字节(256位,一个字词word)进行读写。
EVM内存存取操作码
EVM提供了一系列操作码来对内存进行读写操作:
-
MLOAD (Memory Load):从内存中加载数据。

- 格式:
MLOAD offset - 功能:从内存
offset地址开始,读取32字节(256位)的数据压入栈顶。 - 示例:如果内存地址0x20处存储了32字节数据,执行
MLOAD 0x20会将这32字节数据加载到栈中。
- 格式:
-
MSTORE (Memory Store):将数据存储到内存中。
- 格式:
MSTORE offset value - 功能:将栈顶的32字节数据
value存储到内存offset地址开始的32字节空间中。 - 示例:执行
PUSH1 0x10 PUSH1 0x00 MSTORE会将值0x10存储在内存地址0x00处(仅存储一个字节,其余31字节会被填充为0,因为PUSH1只推送1字节,实际MSTORE会扩展到32字节)。
- 格式:
-
MSTORE8 (Memory Store 8 bits):存储单字节数据到内存。
- 格式:
MSTORE8 offset value - 功能:将栈顶数据的最低有效字节(LSB)存储到内存
offset地址处。 - 示例:执行
PUSH1 0xAB PUSH1 0x00 MSTORE8会将字节0xAB存储在内存地址0x00。
- 格式:
-
MSIZE (Memory Size):获取当前内存大小。
- 格式:
MSIZE - 功能:将当前内存的大小(以字节为单位)压入栈顶,内存大小总是32字节的倍数。
- 格式:
-
MCOPY (Memory Copy):内存拷贝操作(由柏林硬分叉引入)。
- 格式:
MCOPY dest src size - 功能:从内存
src地址开始,拷贝size字节数据到内存dest地址,这是一个非常高效的操作,避免了多次MLOAD和MSTORE的开销。
- 格式:
内存存取的应用场景
EVM内存在智能合约的执行中无处不在,主要用于:
-
变量存储与计算:在合约执行过程中,大量的中间计算结果、局部变量、函数参数等都会存储在内存中,以便快速访问和修改,在复杂的数学运算或数据处理算法中,内存用于暂存中间值。

-
数据编码与解码:与外部交互(如调用其他合约、接收ABI编码的数据)时,通常需要处理ABI编码的数据,内存用于存储这些编码的数据,并进行解码操作。
abi.decode()函数内部就大量依赖内存操作。 -
哈希计算:如SHA3(Keccak-256)哈希计算,通常需要将待哈希的数据先加载到内存中,然后对内存区域进行哈希。
SHA3操作码可以直接对内存区域进行哈希。 -
日志记录:虽然日志数据最终存储在区块链的收据中,但在构造日志主题和数据时,这些数据会先在内存中进行组装。
-
合约交互:在调用其他合约时,输入参数通常会先编码并存储在内存中,然后传递给被调用合约。
内存管理与Gas成本
虽然内存读写本身比状态存储便宜,但内存的扩展是有Gas成本的,EVM采用一种“分层”的Gas计算模型来惩罚内存的过度扩展:
- 基础Gas:每次MLOAD、MSTORE、MSTORE8操作消耗固定的基础Gas。
- 内存扩展Gas:当内存需要扩展时(即访问的内存地址超出当前内存大小),会支付内存扩展Gas,扩展的成本与内存大小的增长呈平方关系(具体计算公式较为复杂,但核心思想是扩展越大,单位成本越高),这意味着频繁或大量地扩展内存会显著增加交易成本。
优秀的智能合约开发者会:
- 预分配内存:如果预计需要较大内存,可以使用
PUSH <size> DUP1 MSTORE或更高效的PUSH <size> MSIZE DUP2 SUB DUP3 MSTORE等模式来预分配内存,避免多次扩展。 - 复用内存:尽可能在已分配的内存区域进行操作,减少不必要的扩展。
- 及时清理:虽然内存会自动清理,但在复杂合约中,合理规划内存使用顺序,避免长期占用大块内存,有助于提高整体执行效率。
内存与存储(Storage)及栈(Stack)的区别
为了更好地理解EVM内存,有必要将其与另外两个关键数据区——存储(Storage)和栈(Stack)进行区分:
- 内存(Memory):临时字节数组,按需扩展,读写较快,成本中等,生命周期为交易执行期间。
- 存储(Storage):持久化键值对存储,每个合约一个,存储在区块链上,读写慢,成本高,生命周期永久。
- 栈(Stack):临时数据结构,用于操作数计算和指令执行,最大深度1024,操作极快,成本极低(无额外Gas,仅包含在基础Gas中),生命周期为指令执行期间。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。



