EVM存储结构在EVM中实际上有六个位置可以存储数据:stack,memory,calldata,storage,code(在一个特定的地址),log(触发事件)实际上深入研究的是前四个:stack,memory,calldata,storage
在 EVM 中实际上有六个位置可以存储数据:stack,memory,calldata,storage,code(在一个特定的地址),log(触发事件)
实际上深入研究的是前四个:stack,memory,calldata,storage
在以太坊的堆栈中,每一次 push 或 pop 的堆栈内容是一个 32 bytes 的内容。
以太坊中的 Memory 和上面的 Stack 类似,也是基于 32 bytes 的大小。**但是,它不需要任何的 PUSH,POP 操作 **,我们可以写入两个特定的内存字,并准确地选择要写入的位。Memory 实际上有一个很特殊的布局

calldata 也可以存储任意字节,但是不同的是,calldata 只能在这个区域读取,不能编写任何内容来调用数据。因此从calldata 中读取和访问东西要便宜很多。
所以对于一些需要经常读取,但是不需要进行修改的数据,我们可以放在 calldata 中读取它,而不是将他放在 Memory 中。如果有一个函数的参数,不需要修改 Meomry 的参数,我们就可以把他定义为 calldata。
Storage 是上述这些存储数据类型中最昂贵的。但是,它是这些存储类型中唯一一个永久的。所有其他的存储结构,stack,memory,calldata 在函数调用完成后都会被清除。他们是在事务处理期间存储数据的临时场所。从某种意义上来讲,我们可以把 Storage 想象成区块链的数据库。它的工作方式与 Memory 类似,我们有 32 bytes 的数据存储在 Storage 中,但是 Storage 具有 slot(插槽),也没有像 Memory 中类似于空闲内存指针的预留空白区域。
区块链的状态,大致可以按照下图的样式理解:

EVM 这些不同的领域构成了 Ethereum。什么把他们聚集在一起,使得这些东西相互影响?真正可行的是 Opcodes(操作码)的想法。在以太坊黄皮书,或者EVM Code 中给出了所有的操作码,我们可以在其中看到这些 Opcode 是如何操作 EVM 的。在 Huff 入门文章中,也有相关的详细的通过 Huff 操作 Opcode 的过程。
在 Ethereum 黄皮书和 EVM Code 中我们可以看到,这些操作码实际上对应的都是十六进制值
在一个合约中,一般有多个函数,当外部调用该合约的函数时,在 EVM 层次上,实际上是将 calldata 中的 selector 与合约中的 selector 挨个对比(EQ opcode),然后 PUSH 要跳转到的位置,在调用 JUMPI 来判断是否进行调用。也就是说,越早的成功匹配 selector,也就能更加节省调用合约所花费的 gas 费用。
那么 selector 的是按照什么顺序排列的?
在合约编译成字节码时,函数选择器 selector 的排布是按照 selector 的 16 进制字面量大小顺序排序的,字面量越小,越靠前也就是说,在高层次上来看,调用selector 更小的函数,会比调用 selector 大的函数更节省 gas。
在我的合约中实现了四个函数:
// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity ^0.8.20;
contract Test {
uint256 number;
// 0x0b3f62f5
function first(uint256 a) external {
number = a;
}
// 0xfc563658
function getNumber(uint256 a) external view returns (uint256) {
return number * a;
}
// 0x60362514
function doubleNumber() external {
number *= 2;
}
// 0xd6980dfd
function number3() external {
number *= 3;
}
}
示例合约的布局与相应函数对应的 selector 如上,但是实际得到的字节码是如下的,selector 的排列顺序是按照 selector 的大小来的
[36] PUSH0
[37] CALLDATALOAD
[38] PUSH1 e0
[3a] SHR
[3b] DUP1
[3c] PUSH4 0b3f62f5
[41] EQ
[42] PUSH2 004e
[45] JUMPI
[46] DUP1
[47] PUSH4 60362514
[4c] EQ
[4d] PUSH2 006a
[50] JUMPI
[51] DUP1
[52] PUSH4 d6980dfd
[57] EQ
[58] PUSH2 0074
[5b] JUMPI
[5c] DUP1
[5d] PUSH4 fc563658
[62] EQ
[63] PUSH2 007e
[66] JUMPI
[67] JUMPDEST
[68] PUSH0
[69] DUP1
[6a] REVERT
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!
作者暂未设置收款二维码