Solidity内存布局介绍 Layout in Memory and Storage

这篇具有很好参考价值的文章主要介绍了Solidity内存布局介绍 Layout in Memory and Storage。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Solidity reserves four 32-byte slots, with specific byte ranges (inclusive of endpoints) being used as follows:

0x00 - 0x3f (64 bytes): scratch space(暂存空间) for hashing methods  Hash方法的暂存空间.

0x40 - 0x5f (32 bytes): currently allocated memory size (aka. free memory pointer)

0x60 - 0x7f (32 bytes): zero slot

Solidity保留了四个32字节的插槽,具体的字节范围(包括端点)如下所示:

0x00-0x3f  (0-63)(64字节):哈希方法的暂存空间

0x5f (64-95)(32字节):当前分配的内存大小(也称为空闲内存指针)0x40-

0x60-0x7f (96-127)(32字节):零插槽,用于内存数组初始化的值,  0插槽不应该被写入东西.

0x80 (>128) 空闲指针所指向数据的存储开始位置. 0x80 (第5个槽位开始的位置,第4个槽位结束的位置.)

Scratch space can be used between statements (i.e. within inline assembly). The zero slot is used as initial value for dynamic memory arrays and should never be written to (the free memory pointer points to 0x80 initially).

暂存空间可以在statement之间被使用(比如内联汇编内部). zero 卡槽 被用于动态内存数组的初始值,永远不应该被写。  (空闲指针最原始指向0x80, 128的位置.)

Layout of State Variables in Storage

State variables of contracts are stored in storage in a compact way such that multiple values sometimes use the same storage slot. Except for dynamically-sized arrays and mappings (see below), data is stored contiguously item after item starting with the first state variable, which is stored in slot 0. For each variable, a size in bytes is determined according to its type. Multiple, contiguous items that need less than 32 bytes are packed into a single storage slot if possible, according to the following rules:

合约状态变量以一种紧凑性方式存储在storeage中, 比如多个values同时存储在一个slot中。 除了动态的尺寸的数组和mapping, 状态变量数据data从0插槽开始,一个接一个持续的存储到插槽. 对于每一个变量,数据字节的长度由变量类型来确定。 多个连续的变量数据项并且小于32字节长度的变量群,会被打包到一个单独的存储插槽中. 遵守以下规则:

  • The first item in a storage slot is stored lower-order aligned. 第一个数据,在存储插槽中, 低位对齐.

  • Value types use only as many bytes as are necessary to store them. 值类型仅仅占用足够存储他们的数据空间字节数就行了.

  • If a value type does not fit the remaining part of a storage slot, it is stored in the next storage slot.  如果插槽剩余的字节空间不足以存储值类型数据,则它会被存储在下一个插槽中.

  • Structs and array data always start a new slot and their items are packed tightly according to these rules.   struct 和 array的数据总是单独存储一个插槽,它们的内部项会依照这个规则紧凑的打包存储

  • Items following struct or array data always start a new storage slot. 在struct和array之后的存储的数据项,总是会开启一个新的存储插槽.

For contracts that use inheritance, the ordering of state variables is determined by the C3-linearized order of contracts starting with the most base-ward contract. If allowed by the above rules, state variables from different contracts do share the same storage slot.

对于使用继承的契约,状态变量的顺序由C3线性化的契约顺序决定,该顺序从最基本的合约开始。如果上述规则允许,来自不同合同的状态变量将共享同一存储槽。

Finally, in order to allow the EVM to optimize for this, ensure that you try to order your storage variables and struct members such that they can be packed tightly. For example, declaring your storage variables in the order of uint128, uint128, uint256 instead of uint128, uint256, uint128, as the former will only take up two slots of storage whereas the latter will take up three.

总之,为了最大的使EVM优化, 确保你尝试声明的存储变量和struct 成员的顺序,可以使得这些变量可以紧致的打包存放.  比如:状态变量声明顺序, uint128,uint128,uint256;  uint128,uint256,uint128.   前者占用2个插槽, 后者占用了3个.

Mappings and Dynamic Arrays

Due to their unpredictable size, mappings and dynamically-sized array types cannot be stored “in between” the state variables preceding and following them. Instead, they are considered to occupy only 32 bytes with regards to the rules above and the elements they contain are stored starting at a different storage slot that is computed using a Keccak-256 hash.

因为不可预测的数据大小, mapping和动态尺寸的数组,不能够存储在状态变量数据之间,之前或之后. 它们仅仅占据独立的32字节插槽,依赖上面的规则。 它们的元素存储在一个不同的插槽中,取决于用Keccak-256算法计算结果.

Assume the storage location of the mapping or array ends up being a slot p after applying the storage layout rules. For dynamic arrays, this slot stores the number of elements in the array (byte arrays and strings are an exception, see below). For mappings, the slot stays empty, but it is still needed to ensure that even if there are two mappings next to each other, their content ends up at different storage locations. 假设mapping和array的存储位置,在应用了存储布局规则后,存在一个p插槽. 对于动态数组,这个插槽存储数组的元素个数。(动态尺寸的字节数组和string是一个exception). 对于mapping,这个插槽保持为空, 但是mapping扔需要确保即使嵌套mapping,他们的内容最终会在一个不同的存储位置.    就是mapping和动态数组,string,bytes 需要至少两个slot去存储,第一个slot,称为主slot,存储数据结构本身的数据,比如长度,嵌套的结构地址,这个slot根据EVM系统内存分配获取.  另一个slot,根据hash算法,主slot得到数据地址.

The value corresponding to a mapping key k is located at keccak256(h(k) . p) where . is concatenation and h is a function that is applied to the key depending on its type:

mapping 的key   k对应的值,存储位置在keccak256(h(k) . p),  Hashmap的key对应的value的存储位置,是通过计算key和hash本身slot位置的Hash获得.

  • for value types, h pads the value to 32 bytes in the same way as when storing the value in memory.  如果key是值类型,h则会补位到32字节. 

  • for strings and byte arrays, h computes the keccak256 hash of the unpadded data.如果key是string或byte array,  h 会计算未补位的hash值, keccak256.

If the mapping value is a non-value type, the computed slot marks the start of the data. If the value is of struct type, for example, you have to add an offset corresponding to the struct member to reach the member.

如果mapping的值是非值类型,则计算的插槽标记数据的开始位置. 如果mapping的值是struct type,  你不得不添加一个offset去对应到结构里面的元素位置.

As an example, consider the following contract:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 <0.9.0;


contract C {
    struct S { uint16 a; uint16 b; uint256 c; }
    uint x;   // slot 0
    mapping(uint => mapping(uint => S)) data; // slot 1
}

Let us compute the storage location of data[4][9].c. The position of the mapping itself is 1 (the variable x with 32 bytes precedes it). This means data[4] is stored at keccak256(uint256(4) . uint256(1)). The type of data[4] is again a mapping and the data for data[4][9] starts at slot keccak256(uint256(9) . keccak256(uint256(4) . uint256(1))). The slot offset of the member c inside the struct S is 1 because a and b are packed in a single slot. This means the slot for data[4][9].c is keccak256(uint256(9) . keccak256(uint256(4) . uint256(1))) + 1. The c type of the value  is uint256, so it uses a single slot.

bytes and string (已经理解)

bytes and string are encoded identically. In general, the encoding is similar to bytes1[], in the sense that there is a slot for the array itself and a data area that is computed using a keccak256 hash of that slot’s position. However, for short values (shorter than 32 bytes) the array elements are stored together with the length in the same slot.

bytes 和 string 是相同的编码规则。一般来说, 编码规则和bytes1[]是一样的,有一个专门为数组本身存储的插槽p, 数据的存储位置通过hash 计算p的位置,keccak256(p)得到.  然而, 对于一个短值(小于32字节)数组元素和数组的长度一起存储在同一个插槽里.

Cleaning Up Variables

在EVM中,最终所有的值都会存储在256位的插槽里面。在某些情况下(in some case), 有的值类型小于256位,  这就需要把剩余位给清理了.  如果不清理,剩余位可能不是0, 会影响最终存储的值或混淆值存储. 意思你存储的值,可能失去保真了.文章来源地址https://www.toymoban.com/news/detail-595401.html

到了这里,关于Solidity内存布局介绍 Layout in Memory and Storage的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 弹性盒子布局 Flexbox Layout

    可以嵌套下去 1.display 属性 默认行排列 此时是 列拍 flex-direction属性——行布局 row 列布局:column flex-wrap 属性 折叠 flex-flow属性 包括 flex-direction 和flex-wrap flex-flow: row wrap 行排列 折叠 justify-content属性 元素在主轴上的对齐方式 左对齐 居中对齐 右对齐 两端对齐 拉手对齐 align

    2024年03月15日
    浏览(31)
  • Qt入门教程【Core篇】Layout布局(布局管理器、手动布局)

    😈 「CSDN主页」 :传送门 😈 「Bilibil首页」 :传送门 😈 「网易云课堂」 :传送门 😈 「CSDN学院」 :传送门 😈 「51CTO学院」 :传送门 😈 「本文的内容」 :Qt布局指南 😈 「动动你的小手」 : 点赞 👍 收藏 ⭐️ 评论 📝 界面开发首先要对整个界面进行布局,使窗体上

    2023年04月18日
    浏览(63)
  • Solidity中的calldata,storage,memory

    目录 calldata memory storage 三者之间的转换 storage作为参数,赋值到memory (1) (2) (3) storage作为参数,赋值给storage memory作为参数,赋值给memory memory作为参数,赋值给storage 官方文档对calldata的描述: Calldata is a non-modifiable, non-persistent area where function arguments are stored, and beha

    2024年01月23日
    浏览(31)
  • HTML布局(HTML Layout)简介

    HTML布局(HTML Layout)简介 HTML布局(HTML Layout)是创建一个网站时需要考虑的情况,合理设计网页中内容的排列方式,让网页看起来更加合理、美观,能产生引人注目的视觉效果。页面布局一般包括: 标题:前端的一部分,用于页面顶部。header标签用于在网页中添加标题部分

    2024年02月08日
    浏览(42)
  • 【CocosCreator入门】CocosCreator组件 | Layout(布局)组件

            Cocos Creator 是一款流行的游戏开发引擎,具有丰富的组件和工具,其中的Layout组件是一种用于实现节点自适应布局的重要组件。它可以根据不同的布局方式,自动调整子节点的位置和大小,从而实现节点的自适应布局。 目录 一、组件介绍 二、组件属性 三、布局类

    2023年04月22日
    浏览(37)
  • Unity 网格布局控件-Grid Layout Group

    Unity 网格布局控件-Grid Layout Group是Unity中的UGUI控件,用于在 UI 中创建网格布局, 它的作用是:自动将子对象排列成网格,即我们可以通过该组件对子对象按行和列的形式排列,根据指定的约束条件自动调整它们的大小和位置。通常我们使用它创建具有规律排列的 UI 元素,如

    2024年02月04日
    浏览(38)
  • 【CSS 20】website layout 网站布局 页眉 导航栏 列布局 不相等栏 页脚

    website layout 网站布局 header 页眉 页眉(header)通常位于网站顶部(或顶部导航菜单的正下方) 通常包含徽标(logo)或网站名称 navbar 导航栏 导航栏包含链接列表,以帮助访问者浏览您的网站 内容 使用哪种布局通常取决于您的目标用户 最常见的布局是以下布局之一(或将它

    2024年02月13日
    浏览(74)
  • Flutter 笔记 | Flutter 核心原理(三)布局(Layout )过程

    Layout(布局)过程主要是确定每一个组件的布局信息(大小和位置),Flutter 的布局过程如下: 父节点向子节点传递约束(constraints)信息,限制子节点的最大和最小宽高。 子节点根据约束信息确定自己的大小(size)。 父节点根据特定布局规则(不同布局组件会有不同的布

    2024年02月09日
    浏览(76)
  • 设置layout布局嵌套路由格式正确但是看不见页面问题

    一定确保格式正确.试试重置component路径 children: [

    2024年02月13日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包