宇宙链 宇宙链
Ctrl+D收藏宇宙链
首页 > 火币APP > 正文

深入Solidity数据存储位置——Storage

作者:

时间:1900/1/1 0:00:00

这是深入 Solidity 数据存储位置系列的另一篇。在今天的文章中,我们将更详细地介绍 EVM 中的一个重要数据位置:存储(Storage)。

我们将看到合约存储的布局是如何工作的,storage引用。我们还将使用OpenZeppelin和Compound中的一些合约来学习storage引用在实践中如何工作,同时顺便学习这些流行合约和协议背后的 Solidity 代码。

存储器的基础知识

与存储交互

函数参数中的存储指针

函数体中的存储指针

读取存储的成本。

结论

了解以太坊和基于 EVM 的链中的存储模型对于良好的智能合约开发至关重要。

你可以在智能合约上永久地存储数据,以便将来执行时可以访问它。每个智能合约都在自己的永久存储中保持其状态。它就像*"智能合约的迷你数据库 "*,但与其他数据库不同,这个数据库是可以公开访问的。所有存储在智能合约存储器中的值可供外部免费读取(通过静态调用),无需向区块链发送交易。

然而,向存储空间写入是相当昂贵的。事实上,就 Gas 成本而言,它是 EVM 中最昂贵的操作。存储的内容可以通过sendTransaction调用来改变。这种调用会改变状态。这就是为什么合约变量被称为状态变量的原因。

需要记住的一件事是,在以太坊和 EVM 的设计中,一个合约既不能读也不能写非自身定义的任何存储。合约 A 可以从另一个合约 B 的存储中读取或写入的唯一方法是当合约 B 暴露出使其能够这样做的函数。

智能合约的存储是一个持久的可读可写的数据位置。意思是说,如果数据在一次交易中被写入合约存储,一旦交易完成,它就会持久存在。在这个交易之后,读取合约存储将检索到之前这个交易所写入/更新的数据。

每个合约都有自己的存储,可以用以下规则来描述和绑定:

持有状态变量

在交易和函数调用之间持久存在

读取是免费的,但写入是昂贵的

合约存储在合约构建期间被预先分配。

驻留在存储中的变量在 Solidity 中被称为状态变量。

你应该记住关于合约存储的唯一事情是:

存储是持久保存和昂贵的!

将数据保存到存储中是 EVM 中需要最多的 Gas 的操作之一。

写入存储的实际成本是多少?

成本并不总是相同的,计算写入存储的 Gas 是相当复杂的公式,尤其是在最新的以太坊 2

}在上面的合约中,只有一个架子(=一个槽)。EVM 从 "0 号架子 "上加载变量,并将其卸载(到堆栈上)以呈现给你。

Solidity 的主要开发者chriseth这样描述合约的存储:

"你可以把存储看作是一个具有虚拟结构的大数组......一个在运行时不能改变的结构--它是由你合约中的状态变量决定的"。

从上面的例子中,我们可以看到,Solidity 为你合约中的每一个定义的状态变量分配了一个存储槽。对于静态大小的状态变量,存储槽是连续分配的,从 0 号槽开始,按照定义状态变量的顺序。

Chriseth 在这里的意思是: "存储不能在函数调用中创建"。事实上,如果必须是永久存在,通过调用函数来创建新的存储变量,也没有什么意义(不过,映射的情况略有不同)。

智能合约的存储是在合约构建过程中(在合约被部署时)预置的。这意味着合约存储的布局在合约创建时就已经确定了。该布局是基于你的合约级变量声明而 "成型 "的,并且这种布局不能被未来的方法调用所改变。

让我们用solc命令行工具看看上一个合约的实际存储布局,如果你运行下面的命令。

solc contracts/Owner

所有静态大小的变量都是按照它们被定义的顺序依次放入存储槽的。

全国政协委员刘尚希:激励推动银行在区块链等领域深入合作:全国政协委员、中国财政科学研究院院长刘尚希建议,在政策上支持开放银行构建,激励银行业善用我国金融科技领先和更本土化的优势,快速发展技术能力:发展线上服务能力和数字风控技术,实现线上线下业务融合;大力推动银行业部署下一代分布式金融信息系统,建设性能稳定、智能化运营的开放式系统架构,为开放银行建好硬件底座;激励推动银行在人工智能、区块链等核心关键技术领域进行深入合作。(中国经营报)[2020/5/23]

记住:每个存储槽最多可以容纳 32 字节长的值。

在我们上面的例子中,a和b是 32 字节长(因为它们的类型是uin256)。因此,它们被分配了自己的存储槽。

在我们之前的例子中没有什么特别之处。但是现在让我们考虑这样的情况:你有几个不同大小的 uint 变量,如下所示:

我们已经写了两个基本的函数来读取低级别的合约存储槽。看一下输出,我们得到以下结果:

Solidity 文档中指出:

"如果可能的话,少于 32 字节的多个连续项目会被打包到一个存储槽中...。

存储槽中的第一个项目被低阶对齐存储

因此,当变量小于 32 字节时,Solidity 尝试将一个以上的变量打包到一个存储槽中,如果它们能被容纳的话。因此,一个存储槽可以容纳一个以上的状态变量。

如果一个基本类型不适合存储槽的剩余空间,它将被移到下一个存储槽。对于以下 Solidity 合约。

pragma solidity ^0

它的存储布局会是这样的:

在存储槽 0 处读取 1 个值

读取存储槽 1 的数值.

读取存储槽 2 的值

让我们看一个更具体的例子,一个流行的 Defi 协议: Aave。

例子: Aave Pool

}这就是 solidity 在幕后所做的事情。当通过 getter 函数读取状态变量时,它将自动使用SLOAD操作码。例如,ERC20 中流行的name()或symbol()函数。这些函数除了返回状态变量外,不做其他事情。请看下面来自 OpenZeppelin 的屏幕截图。

来源:OpenZeppelin Github 代码库,ERC20

}让我们继续之前的例子,即 OpenZeppelin 的 ERC20 代币。如果我们部署 ERC20 代币合约并使用 Remix 调试constructor,我们将得到以下操作代码:

在 Remix 上试试,在部署 ERC20 代币后调试交易。

这条推文很好地描述了操作码SSTORE在 geth 客户端的作用。

solc 编译器的错误报告(截图取自 Remix)

Yul 中存储指针的偏移量的值是多少呢?在函数体中,一些变量可以是存储指针/存储引用。例如,这包括struct、array和mapping。对于这样的变量,在 Yul 中.offset总是为零,因为这样的变量总是占据了一个完整的存储槽,不能与其他变量紧密地挤在一起存储。

智能合约的存储空间,无论是初始化还是修改里面的数据,都要付出高昂的代价。虽然从合约存储中读取数据是免费的,但如果这些读取操作是改变状态的交易的一部分,我们还是应该考虑到向智能合约的存储读取时的 Gas 成本。

由于对存储的操作有很高的 Gas 成本,Solidity 文档中指出了一个重要的考虑。

应该将你存储在持久性存储中的内容减少到合约运行所需的程度。

建议尽可能地将某些数据存储在合约存储之外,以减少相关的 Gas 成本。

深入以太坊 , Part 2

Solidity 文档:状态变量在储存中的布局 g

openzeppelin-contracts/StorageSlot.sol

Solidity 中的数据表示

了解以太坊智能合约的存储

解剖智能合约的结构--功能、数据和变量

译文出自:登链翻译计划 译者:翻译小组 校对:Tiny 熊

本翻译由 Duet Protocol 赞助支持。

原文链接: https://betterprogramming.pub/all-about-solidity-data-locations-part-i-storage-e50604bfc1ad

登链翻译计划: https://github.com/lbc-team/Pioneer

翻译小组: https://learnblockchain.cn/people/412

Tiny 熊: https://learnblockchain.cn/people/15

深入Solidity数据存储位置: https://learnblockchain.cn/article/4864

OpenZeppelin: https://docs.openzeppelin.com/

Compound: https://compound.finance/docs

OpenZeppelin在他们的深入 EVM 第二部分文章中: https://blog.openzeppelin.com/ethereum-in-depth-part-2-6339cf6bddb9/

在他的文章中,Steve Marx: https://programtheblockchain.com/posts/2018/03/09/understanding-ethereum-smart-contract-storage/

Solidity文档: https://learnblockchain.cn/docs/solidity/internals/layout_in_storage.html

Pool: https://docs.aave.com/developers/core-contracts/pool

来源:Aave v3 Protocol, Pool.sol: https://github.com/aave/aave-v3-core/blob/master/contracts/protocol/pool/Pool.sol

来源:Aave v3, PoolStorage.sol: https://github.com/aave/aave-v3-core/blob/master/contracts/protocol/pool/PoolStorage.sol

来源:OpenZeppelin Github代码库,ERC20.sol: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol

在Remix上试试: https://remix.ethereum.org/?#code=Ly8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVApwcmFnbWEgc29saWRpdHkgXjAuOC40OwoKaW1wb3J0ICJAb3BlbnplcHBlbGluL2NvbnRyYWN0c0A0LjcuMC90b2tlbi9FUkMyMC9FUkMyMC5zb2wiOwppbXBvcnQgIkBvcGVuemVwcGVsaW4vY29udHJhY3RzQDQuNy4wL2FjY2Vzcy9Pd25hYmxlLnNvbCI7Cgpjb250cmFjdCBNeVRva2VuIGlzIEVSQzIwLCBPd25hYmxlIHsKICAgIGNvbnN0cnVjdG9yKCkgRVJDMjAoIk15VG9rZW4iLCAiTVRLIikgewogICAgICAgIF9taW50KG1zZy5zZW5kZXIsIDEwMDAwICogMTAgKiogZGVjaW1hbHMoKSk7CiAgICB9CgogICAgZnVuY3Rpb24gbWludChhZGRyZXNzIHRvLCB1aW50MjU2IGFtb3VudCkgcHVibGljIG9ubHlPd25lciB7CiAgICAgICAgX21pbnQodG8sIGFtb3VudCk7CiAgICB9Cn0K&optimize=false&runs=200&evmVersion=null&version=soljson-v0.8.7+commit.e28d00a7.js

faheel from Twitter.: https://twitter.com/721Orbit/status/1511961744238948356?s=20&t=KDGCQ4OwQ47e2NACgQ8WWg

来源:OpenZeppelin Github资源库中的Timer.sol: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Timers.sol

Uniswap: https://github.com/Uniswap/governance/blob/master/contracts/GovernorAlpha.sol

Indexed Finance: https://github.com/indexed-finance/governance/blob/master/contracts/governance/GovernorAlpha.sol

应该将你存储在持久性存储中的内容减少到合约运行所需的程度: https://learnblockchain.cn/docs/solidity/introduction-to-smart-contracts.html#index-10

深入以太坊 , Part 2: https://blog.openzeppelin.com/ethereum-in-depth-part-2-6339cf6bddb9/

Solidity 文档:状态变量在储存中的布局g: https://learnblockchain.cn/docs/solidity/internals/layout_in_storage.html

openzeppelin-contracts/StorageSlot.sol: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/StorageSlot.sol

Solidity中的数据表示: https://ethdebug.github.io/solidity-279"     src="https://img.jinse.cn/5363788_image3.png"   >

白话区块链

金色财经Maxwell

NFT中文社区

CoinDesk中文

达瓴智库

去中心化金融社区

金色荐读

肖飒lawyer

CT中文

ETH中文

ForesightNews

Beosin

标签:SOLTPSHTTSOLIDsol币一开始市值多少tps币行情CHTT币SOLID币

火币APP热门资讯
黑客松常客?一文速览默默发展的Web3邮箱赛道

原文来源:WhoKnows DAO最近两年,我们看到了许多打着去中心化的名号做邮箱服务的项目,甚至可以说,Web3 邮箱已经快要成为 Web3 黑客松的常客.

1900/1/1 0:00:00
存算一体化公链:Subspace Network 白皮书 ( Ⅰ )

本文转载自SubBase。Subspace Network 是Web3上支持大规模可扩展,同时提供存算一体化底层基础设施服务的模块化Layer-1,在此基础上,Subspace Network将致力于增强和连接其他区块链生态系统.

1900/1/1 0:00:00
香港加密牌照演变史

Web3 世界中,继新加坡流量减退后,香港重回亚洲加密世界的注意力中心。在不久前举行的“香港金融科技周”上(相关专题),香港特区政府正式发表《有关虚拟资产在港发展的政策宣言》,阐明政府为在香港发展具活力的虚拟资产行业和生态系统而制定的.

1900/1/1 0:00:00
金色Web3.0日报 | 法国、瑞士、新加坡将在外汇市场测试DeFi

DeFi数据 1、DeFi代币总市值:458.60亿美元 DeFi总市值及前十代币 数据来源:coingecko2、过去24小时去中心化交易所的交易量25.

1900/1/1 0:00:00
晚间必读 | 赵长鹏分享的15条为人处事原则及70条忠告

按:2022年10月13日Binance首席执行官赵长鹏发文分享了自己遵循的一些原则,非常值得大家学习。以下为15条为人处事原则.

1900/1/1 0:00:00
FTX事件后的思考:加密行业将何去何从?

文:knower 来源:knower's substack加密行业的终局止于此了吗?未来一年可能发生什么?下一个十年可能发生什么?也许是下个世纪可能发生什么?有没有人可以给你一个答案?当然没有.

1900/1/1 0:00:00