跟我学 Solidity : 变量的存储
这篇文章主要介绍了跟我学 Solidity : 变量的存储 ,文中通过代码以及文档配合进行讲解,很详细,它对在座的每个人的研究和工作具有很经典的参考价值。 如果需要,让我们与区块链资料网一起学习。
https://www.interchains.cc/18707.html
跟我学 Solidity : 变量的存储是很好的区块链资料,他说明了区块链当中的经典原理,可以给我们提供资料,跟我学 Solidity : 变量的存储学习起来其实是很简单的,
不多的几个较为抽象的概念也很容易理解,之所以很多人感觉跟我学 Solidity : 变量的存储比较复杂,一方面是因为大多数的文档没有做到由浅入深地讲解,概念上没有注意先后顺序,给读者的理解带来困难
跟我学 Solidity : 变量的存储
- Solidity
Solidity 数据存储如何工作?
- 原文:https://medium.com/better-programming/learn-solidity-variables-part-2-f3b842f5bfb8 作者:wissal haji
- 译文出自:登链翻译计划
- 译者:翻译小组
- 本文永久链接:learnblockchain.cn/article…
欢迎阅读“跟我学习 Solidity ”系列中的另一篇文章。正如我在上一篇文章中保证过,我们将看到Solidity中数据存储的工作方式。
以太坊eth虚拟机(EVM)
在讨论Solidity中的数据存储之前,我想介绍一些有关以太坊eth虚拟机的知识,以使事情更清楚。
EVM的内部工作原理:
EVM上下文(来源:fullstacks.org)
当我们安装以太坊eth客户端时,它附带了EVM,EVM是专门创建来运行智能合约的轻量级操作系统。 EVM是基于堆栈计算机的模型的体系结构,这意味着该指令集被设计为用于堆栈而不是寄存器。EVM 操作码的列表在黄皮书中进行了描述,可以在“ 以太坊eth虚拟机(EVM)操作码和指令参考”中找到。
代码执行步骤如下:当交易触发智能合约代码执行时,将实例化EVM,并在EVM的ROM中加载要调用的合约的代码。程序计数器设置为零,从合约帐户的存储器中加载存储器,存储器全部设置为零,并且所有块和环境变量都已设置。然后代码被执行。
数据存储位置
现在让我们回到memory关键字,如Solidity 文档中所述。从版本0.5.0开始,所有复杂类型都必须给出一个明确的数据存储位置,并且有三个数据位置:memory(内存)
,storage(存储)
和calldata(调用数据)
。
注意:唯一可以省略数据位置的地方是状态变量,因为状态变量始终存储在帐户的存储空间中。
storage
(存储)
storage
中的数据被永久存储。其以键值形式存储。storage
中的数据写在区块链blockchain中(因此它们会更改状态),这就是为什么使用存储非常昂贵的原因。- 占用256位插槽的 gas成本为20,000。
- 修改
storage
的值将花费5,000 gas 。 - 清理存储插槽时(即将非零字节设置为零),将退还一定量的 gas 。
- 将数据保存在256位大小(32字节为一个字)的存储字段中。即使未完全占用每个插槽,也会产生成本。
memory
(内存)
memory
是一个字节数组,其插槽大小为256位(32个字节)。数据仅在函数执行期间存储,执行完之后,将其删除。它们不会保存到区块链blockchain中。- 读或写一个字(256位)需要3 gas 。
- 为了避免给矿工带来太多工作,在进行22次读写操作后,之后的读写成本开始上升。
calldata
(调用数据)
calldata
是一个不可修改的,非持久性的区域,用于存储函数参数,并且其行为基本上类似于memory
。- 外部函数的参数需要
calldata
,但也可用于其他变量。 - 它避免了复制,并确保了数据不能被修改。
- 带有
calldata
数据位置的数组和结构体也可以从函数中返回,但是不可以为这种类型赋值。
数据位置和赋值行为
如果你不想发生意外的行为,那么了解数据位置赋值的工作方式非常重要。
在赋值之间应用以下规则:
- 在
storage
和memory
之间(或来自calldata
)的赋值总是创建一个独立的副本。 - 从
memory
到memory
的赋值仅创建引用。这意味着对一个内存变量的更改在引用相同数据的所有其他内存变量中同样有效。 - 从
storage
到本地storage
变量的赋值也仅赋值一个引用。 - 所有其他到
storage
的赋值总是被复制。这种情况的示例是赋值给状态变量或storage
结构体类型的局部变量成员,即使局部变量本身只是一个引用。
让我们使用Remix debugger进行更详细的研究
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.7.0; contract DataLocationTest { uint[] stateVar = [1,4,5]; function foo() public{ // case 1 : 从存储中加载到内存 uint[] memory y = stateVar; // 复制 stateVar 到 y // case 2 : from memory to storage y[0] = 12; y[1] = 20; y[2] = 24; stateVar = y; // copy the content of y to stateVar // case 3 : from storage to storage uint[] storage z = stateVar; // z is a pointer to stateVar z[0] = 38; z[1] = 89; z[2] = 72; } }
创建一个新文件,复制上面的代码,然后部署合约。 现在尝试调用函数foo
。你将在控制台中看到交易的详细信息,并在其旁边有一个调试按钮。点击它。
你现在应该看到如下所示的调试器区域:
要单步执行(Step over)代码,请单击我以红色框中的箭头。
从storage
到memory
的赋值
你应该首先注意到,正如我们在EVM部分中提到的, 状态(Solidity State)部分加载了storage
的stateVar的内容,当然没有局部变量。
当你单步执行时,应该看到变量y
出现在局部变量(Solidity locals)部分中。继续执行(step over),你会注意到,为了分配必要的内存空间,需要使用很多字节码
并从storage
中加载每个字,然后将其复制到memory
中。这意味着要支付更多的 gas ,因此从storage
到memory
的赋值非常昂贵。
从memory
到storage
的赋值
让我们研究第二种情况:从memory
到storage
的赋值。
当你修改完存储在memory
中的副本并且想要将更改保存回storage
时,可以使用它。它同样消耗大量的 gas 。如果我们用调试器步骤详细信息中的剩余 gas (remaining gas)来计算 gas 差值,则为17,083 gas 。该操作使用了四个SSTORE操作码:第一个用于存储数组大小(保持不变,消耗800个 gas ),另外三个用于更新数组的值(每个消耗了5,000个 gas )。
从storage
到storage
的赋值
现在,让我们看一下情况三:从storage
到storage
的赋值。这次将创建一个新的局部变量,并包含与stateVar相同的内容。如果我们查看代码的执行过程,会注意到Solidity所做的,将包含数组长度的存储的第一个插槽地址入栈。根据文档,对于动态数组,插槽位置包含数组长度,用于计算包含数组数据的插槽位置。
来比较两者的 gas 成本:
第一种是将数据复制到memory
,然后更新并复制回 storage
, 使用21,629 gas ,
第二种是直接创建引用并更新状态, 使用 5,085 gas 。
那么很明显第二种方法是便宜得多。
但是,如果我们像这样直接更新状态变量呢,像这样:
stateVar[0] = 12;
也有可能但是,如果你要处理映射和嵌套数据类型(我们将在后面看到),则使用storage
指针可以让代码更具可读性。
为了使本文简短,而不会给你太多信息,我决定在下一篇文章继续介绍复杂的变量。我希望本文对你有所帮助,并且像往常一样,如果你想了解更多信息,请继续关注即将发布的文章。
参考文献
- Storage vs. Memory vs. Stack in Solidity & Ethereum: https://dlt-repo.net/storage-vs-memory-vs-stack-in-solidity-ethereum/
- The Ethereum Virtual Machine: https://fullstacks.org/materials/ethereumbook/14_evm.html
- ETHEREUM VIRTUAL MACHINE: https://ethereum.org/en/developers/docs/evm/
-
gas: https://ethereum.org/en/developers/docs/gas/
本翻译由 Cell Network 赞助支持。
部分转自网络,侵权联系删除www.interchains.cchttps://www.interchains.cc/18707.html
区块链知识分享网, 以太坊dapp资源网, 区块链教程, fabric教程下载, 区块链书籍下载, 区块链资料下载, 区块链视频教程下载, 区块链基础教程, 区块链入门教程, 区块链资源 » 跟我学 Solidity : 变量的存储