这是深入Solidity数据存储位置系列的另一篇。在今天的文章中,我们将更详细地介绍EVM中的一个重要数据位置:存储。
我们将看到合约存储的布局是如何工作的,storage引用。我们还将使用OpenZeppelin和Compound中的一些合约来学习storage引用在实践中如何工作,同时顺便学习这些流行合约和协议背后的Solidity代码。
目录
介绍
存储的布局
存储器的基础知识
与存储交互
函数参数中的存储指针
函数体中的存储指针
读取存储的成本。
结论
介绍
了解以太坊和基于EVM的链中的存储模型对于良好的智能合约开发至关重要。
你可以在智能合约上永久地存储数据,以便将来执行时可以访问它。每个智能合约都在自己的永久存储中保持其状态。它就像*"智能合约的迷你数据库"*,但与其他数据库不同,这个数据库是可以公开访问的。所有存储在智能合约存储器中的值可供外部免费读取,无需向区块链发送交易。
然而,向存储空间写入是相当昂贵的。事实上,就Gas成本而言,它是EVM中最昂贵的操作。存储的内容可以通过sendTransaction调用来改变。这种调用会改变状态。这就是为什么合约变量被称为状态变量的原因。
需要记住的一件事是,在以太坊和EVM的设计中,一个合约既不能读也不能写非自身定义的任何存储。合约A可以从另一个合约B的存储中读取或写入的唯一方法是当合约B暴露出使其能够这样做的函数。
存储的基本原理
智能合约的存储是一个持久的可读可写的数据位置。意思是说,如果数据在一次交易中被写入合约存储,一旦交易完成,它就会持久存在。在这个交易之后,读取合约存储将检索到之前这个交易所写入/更新的数据。
金色相对论| 相里朋:无币区块链需对共识机制及底层技术加大探索:本期金色相对论中,对于无币区块链的共识及其技术如何应用在场景中,高级工程师、工业和信息化部电子第五研究所区块链主管相里朋表示,“Token”一直都有,而当前业内的底层技术创新还乏善可陈,多数应用解决方案尚处于研制或探索试用阶段,鲜有与业务深度融合的成功案例,行业应用层次普遍偏低。高举通证经济大旗,落地之路却步步维艰,虚拟代币涌现出无数泡沫。
当前社会并非所有场景都需要虚拟代币/通证(token)来激励,且“无币”区块链同样也支持共识机制、分布式存储、点对点通信技术及密码学技术,也可对多方参与的结果达成共识。既使在“无币”区块链方向,只要敢想敢探索,解决实际问题,也能涌现出一大批优秀案例。[2018/9/29]
每个合约都有自己的存储,可以用以下规则来描述和绑定:
持有状态变量
在交易和函数调用之间持久存在
读取是免费的,但写入是昂贵的
合约存储在合约构建期间被预先分配。
驻留在存储中的变量在Solidity中被称为状态变量。
你应该记住关于合约存储的唯一事情是:
存储是持久保存和昂贵的!
将数据保存到存储中是EVM中需要最多的Gas的操作之一。
写入存储的实际成本是多少?
成本并不总是相同的,计算写入存储的Gas是相当复杂的公式,尤其是在最新的以太坊2
所有静态大小的变量都是按照它们被定义的顺序依次放入存储槽的。
记住:每个存储槽最多可以容纳32字节长的值。
在我们上面的例子中,a和b是32字节长。因此,它们被分配了自己的存储槽。
将状态变量打包在一个存储槽中
分析 | 金色盘面:BTC期货合约持仓变化:金色盘面综合分析: 据OKEX数据显示,OKEX的BTC期货合约持仓达到89069左右。做多账户60%,做空账户38%,短线看多头仓位从高位64%减至61%;主力多头平均持仓比例为23.34%,主力空头平均持仓比例为19.15%,由于短线累计升幅较大,空头主力开始试探性增仓,多头主力依然占优。截止发稿,OKEX现货价格为6555,期货合约当周BTC0817价格为6514,贴水接近40点。[2018/8/18]
在我们之前的例子中没有什么特别之处。但是现在让我们考虑这样的情况:你有几个不同大小的uint变量,如下所示:
pragma?solidity?^0
它的存储布局会是这样的:
因此,一个变量的"地址"由两个部分组成。 槽号:变量所在的位置。 变量开始的字节偏移量。 让我们继续看一些基本的汇编代码,以便更好地理解。看看下面的合约和它的函数: contract?Storage?{??uint64?a?=?1;??uint64?b?=?2;??uint128?c?=?3;function?getSlotNumbers()?public?view?returns(uint256?slotA,?uint256?slotB,?uint256?slotC)?{????assembly?{????slotA?:=?a.slot??????slotB?:=?b.slot??????slotC?:=?c.slot????}}??function?getVariableOffsets()?public?view?returns(uint256?offsetA,?uint256?offsetB,?uint256?offsetC)?{??assembly?{??????????offsetA?:=?a.offset????????????offsetB?:=?b.offset????????????offsetC?:=?c.offset????????}}} 金色财经现场报道 Huobi Australia将成为火币全球化布局的重中之重 将被打造成澳洲领先的数字资产交易平台:此次火币集团品牌升级发布会也在位于?尔本的全球首个非盈利性区块链知识中心 Blockchain Centre 设立了分会场。 新闻发布会上,火币集团正式公布了与 Blockchain Global合资经营的 Huobi Australia 交易平台的核心发展规划。火币澳洲 CEO Adrian Harrison 出席了此次发布会澳洲分会场,并表示即将上线的 Huobi Australia 交易平台将成为火币全球化布局的重中之重。 Blockchain Global COO Jenny Qin表示,“火币集团的全球化品牌知名度和顶级技术团队加上 Blockchain Global 在澳洲当地优质资源的助力,Huobi Australia 无疑将被打造成澳大利亚最领先、最知名的数字资产交易平台。”[2018/6/6] 通过Remix运行这两个函数可以得到以下输出: 要检索变量c所指向的槽,使用c.slot,要检索字节偏移量,使用c.offset。仅使用c本身会导致错误: function?ReadVariableC()?public?view?returns?(uint64?value)?{assembly?{????????value?:=?sload(c)????}} 上面的代码将不会被编译,并会出现以下错误 有一点也要提到的是,在内联汇编中,你不能向存储变量的.slot或.offset赋值: 《金色讲堂》第二期即将开讲 中国社科院研究生院特聘教授王彬生前来授课:5月22日晚八点,《金色讲堂》第二期正式开讲,中国社科院研究生院特聘教授王彬生前来授课演讲。针对当下火爆的区块链市场,中国社科院研究生院特聘教授王彬生对区块链市场含义及发展逻辑进行解读。从信息传递成本接近零是这场区块链运动的时代前提到美元消失和新技术出现的展望等6个方面,对区块链市场进行深入的解读,让学员能够深入的了解的区块链市场的发展逻辑。[2018/5/22] function?doesNotCompile()?public?{????assembly?{????????a.slot?:=?8????????a.offset?:=?9????}} solc编译器的错误报告 Yul中存储指针的偏移量的值是多少呢?在函数体中,一些变量可以是存储指针/存储引用。例如,这包括struct、array和mapping。对于这样的变量,在Yul中.offset总是为零,因为这样的变量总是占据了一个完整的存储槽,不能与其他变量紧密地挤在一起存储。 结论 智能合约的存储空间,无论是初始化还是修改里面的数据,都要付出高昂的代价。虽然从合约存储中读取数据是免费的,但如果这些读取操作是改变状态的交易的一部分,我们还是应该考虑到向智能合约的存储读取时的Gas成本。 由于对存储的操作有很高的Gas成本,Solidity文档中指出了一个重要的考虑。 应该将你存储在持久性存储中的内容减少到合约运行所需的程度。 建议尽可能地将某些数据存储在合约存储之外,以减少相关的Gas成本。 金色财经数据播报 美元、USDT的比特币交易货币占比较一个月前相比均出现下跌现象:据cryptocompare数据显示,在比特币的交易货币占比中,美元交易占比目前为18.19%,交易额为4.27亿美元,与一个月前的6.98亿美元相比,交易额下跌了2.71亿美元;USDT目前的交易占比为17.23%,交易额为4.02亿美元,与一个月前的4.87亿美元相比,交易额下跌了0.85亿美元。[2018/5/21] 参考资料 深入以太坊,Part2 Solidity文档:状态变量在储存中的布局g openzeppelin-contracts/StorageSlot.sol Solidity中的数据表示 了解以太坊智能合约的存储 解剖智能合约的结构--功能、数据和变量 译文出自:登链翻译计划译者:翻译小组?校对:Tiny熊 本翻译由DuetProtocol赞助支持。 原文链接: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/ 在他的文章中,SteveMarx: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 来源:Aavev3Protocol,Pool.sol:https://github.com/aave/aave-v3-core/blob/master/contracts/protocol/pool/Pool.sol 来源:Aavev3,PoolStorage.sol:https://github.com/aave/aave-v3-core/blob/master/contracts/protocol/pool/PoolStorage.sol 来源:OpenZeppelinGithub代码库,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 faheelfromTwitter.:https://twitter.com/721Orbit/status/1511961744238948356?s=20&t=KDGCQ4OwQ47e2NACgQ8WWg 来源:OpenZeppelinGithub资源库中的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 IndexedFinance:https://github.com/indexed-finance/governance/blob/master/contracts/governance/GovernorAlpha.sol 应该将你存储在持久性存储中的内容减少到合约运行所需的程度:https://learnblockchain.cn/docs/solidity/introduction-to-smart-contracts.html#index-10 深入以太坊,Part2: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"?> 郑重声明: 本文版权归原作者所有, 转载文章仅为传播更多信息之目的, 如作者信息标记有误, 请第一时间联系我们修改或删除, 多谢。