EVM详解之Storage

EVM详解之Storage
文章旨在记录过去所学知识,若文章内容存在不当,欢迎指出。若对文章内容感兴趣,也欢迎评论区留言讨论!文章部分图片来自他人博客!

一、Storage的结构

EVM中的主要数据存储结构包括Storage、Memeory、Stack、Calldata。本章主要介绍Storage数据结构。Storage可以视作一个非常大的字典,里面存储着非常多的键值对,每一个键值对我们都将他称为一个存储槽。 智能合约的状态变量就存储在存储槽中。每一个存储槽的长度都为32字节,存储槽的位置从0开始,只有当需要新的存储槽时,EVM才会重新开辟一个存储槽,storage结构如下图所示:
在这里插入图片描述
注意:虽然存储槽的位置从0开始,但是并不是每一个存储槽的"键"都是数字,还有可能是一串哈希值(Mapping类型的状态变量)。

二、Storage的特点

EVM存储主要有以下几个特点:
1.不同于memory和calldata,可以直接通过偏移量(offset)访问其中的数据,要想访问Storage中的数据,就必须使用数据对应的"键"
2.我们在合约内,函数外定义的变量都默认为storage类型状态变量
3.如果你部署一个合约上链或者调用链上某个合约中的方法(改变了合约中的状态变量),都会导致整个以太坊上的世界状态发生改变,所以storage存储状态变量是非常昂贵的,所以EVM为了节省资源,使得storage中的每一个存储槽都可以存储多个数据。(可以≠一定会存储)

在solidity中,我们在定义变量的时候,常常会指定该变量的长度:
在这里插入图片描述
例如这段合约中,状态变量total被规定为长度uint256(32字节),stateA,stateB被规定为uint128(16字节),地址类型owner自然是32字节,json被规定为uint64(8字节)。在第一部分我们说过,每一个storage存储槽都是32字节,刚才我们又说了storage中的每一个存储槽都可以存储多个数据。那就是说如果变量是32字节那么storage就会给他分配一个单独的存储槽,如果变量小于32字节,storage会尽可能的将这些变量存储在用一个存储槽。
对于上述的合约,看看他的storage存储情况:
在这里插入图片描述
可以看到数据长度为32字节的total,owner都会存储到了一个单独的存储槽,长度只有16字节的stateA,stateB被存储到了同一个存储槽,这时候你是不是在想如果长度只有8字节的4个变量会怎样呢?对,他们四个会被存储到同一个存储槽中(且和你声明状态变量的代码位置无关)。
对上面的例子观察仔细地话,你会发现状态变量json在storage中没有存在,这是为什么呢?这就是我们要说的storage的第四个特点。

4.storage类型变量是在使用时才会编译的,所以我们可以定义任意多的storage变量,但事实上并不会给编译的合约增加任何code
我们说过存储状态变量是及其昂贵的,这不仅仅只体现在storage将多个长度较小的数据存放在同一个存储槽,同样体现在第四个特点上。观察上述我们的例子合约,合约中并没有对json变量进行赋值,在这样的情况下,storage是不会存储该变量的,该变量也不会体现在合约的字节码中。

三、Storage的工作方式

在介绍Storage的工作方式之前,先介绍一下storage中的键值对的键是怎样工作的。
在storage中,除了mapping类型的状态变量其他类型变量的键都是从0开始依次递增,mapping类型的状态变量值对应的键都是哈希值,至于这些哈希值是怎样计算而来的,是对mapping类型变量的键和值的组合进行keccak256哈希得到的。
在这里插入图片描述
接下来将详细介绍Storage中的工作,主要是通过操作码SSTORE,SLOAD,SHA3来完成的。

3.1关键操作码

1.SSTORE(arg0,arg1): SSTORE操作码有两个参数,所以完整的写法应该是SSTORE(arg0,arg1),该操作码的作用是从栈顶弹出两个元素,第一个为arg0,第二个为arg1,将arg0作为Storage存储槽的键,arg1作为value存储到arg0键对应的槽中。

2.SLOAD(arg): SLOAD操作码只有一个参数arg,该操作码的作用是从键为arg的存储操作取出对应的值推入到栈中。

3.SHA3(arg0,arg1): SHA3操作码有两个参数,arg0为keccak256哈希对象在memory中的位置,arg1为要进行哈希运算的数据长度,例如SHA(0x00,0x40)就是将memory中从0开始往后的0x40长度的数据进行哈希运算。(看到这里,可能还会有人有疑问:为啥要关注SHA3操作码? 因为mapping类型的状态变量的键是一串哈希值,而那串哈希值其实就是通过SHA3算出来的)
在这里插入图片描述
对于刚才的合约,那两个mapping类型的变量,我们在字节码层面分析他们的key究竟是怎么来的:
在这里插入图片描述
EVM先将mapping类型变量的键推到memory中的0位槽,之后又将值推入到memory中的0x20槽
在这里插入图片描述
在这里插入图片描述
最后对memory中的前64字节的数据进行哈希运算,得到的结果就是该mapping变量在storage中的key值
在这里插入图片描述
是至于memory的工作方式,可以在我主页的另一篇文章EVM详解之Memory中查看。

四、小结

上述暂时就是作者对storage的大部分理解,若文章内容存在某些不当或者缺少某些内容,欢迎大家批评指正!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值