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

泰岳区块链-合约面试题之 solidity 合约 Mapping 存储 面试题:Solidity中Map是如何存储的? 泰岳区块链采用的是EVM solidity合约。那么Map在solidity合约里面到底怎么存储的呢?我们写一个测试用例来测试一下。 pragma solidity ^0.6.0; // SPDX-License-Identifier: MIT contract Test1{ uint256 public pID; uint256 public rID; string public contractName; ... 阅读详情

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, 会影响最终存储的值或混淆值存储. 意思你存储的值,可能失去保真了.

Solidity之Mappings篇 你只需要通过传入**_KeyType**参数给getter就能返回**_ValueType.**关键数据不是储存在一个mapping中的,相反的它的keccak256 hash值用来存储关键数据指向的value值。Solidity中****Mappings**** 的概念类似于java中的hashmap或者python中的dictionnary。可以记录一个counter的计数器,来告诉你mapping的长度当有新增的value值的时候。# 关于****Mappings**** 阅读详情

相关推荐

智能合约从入门到精通:Solidity语法之内存变量的布局和状态变量的存储模型

简介:在前面我们已经讲过Solidity语言的一些语法内容,在矩阵元JUICE开放平台的JIDE开发时,一定要注意Layout in Memory和Layout of State Variables in Storage,即内存变量的布局和状态变量的存储模型。内存变量的布局(Layout in Memory)Solidity预留了3个32字节大小的槽位:0-64:哈希方法的暂存空间(scratch...

区块链技术 1350

深入理解Solidity——内存布局

内存布局(Layout in Memory) Solidity预留了4个32字节大小的槽位: 0x00 - 0x3f: 哈希方法的暂存空间(scratch space) 0x40 - 0x5f: 前已分配内存大小,也称空闲内存指针(free memory pointer) 0x60 - 0x7f: 零槽(zero slot) 暂存空间可在语句之间使用(如在内联编译时使用)。零槽用作动态内...

黄嘉成的博客 1779

提示词工程的几个参数

低 temperature + 低 top-p:输出最稳定、最可靠,适合需要准确性和一致性的场景。高 temperature + 高 top-p:输出最多样化、最富有创意,适合需要灵感和探索的场景。Max Length:您可以通过调整max length来控制大模型生成的 token 数。指定 Max Length 有助于防止大模型生成冗长或不相关的响应并控制成本。是一个字符串,可以阻止模型生成 token,指定是控制大模型响应长度和结构的另一种方法。例如,您可以通过添加 “11” 作为。

weixin_44212787的博客 1826

Solidity Storage底层管理

Solidity Storage底层管理

mutourend2010@gmail.com 1836

Win10环境下VS2019离线部署OnnxRuntime的完整指南

本文提供了在Windows 10系统下,为Visual Studio 2019进行OnnxRuntime离线部署的完整教程。针对网络受限环境,详细讲解了如何获取正确的离线安装包、配置本地NuGet源,并逐步指导项目配置与测试,确保AI模型在C++环境中顺利运行。

weixin_29205061的博客 400

【学习笔记】无人机(UAV)在3GPP系统中的增强支持(四)-无人机系统(UAS)命令与控制(C2)通信用例

UTM向5G网络提供无人机系统C2通信所需的信息,例如服务类别、无人机系统服务的流量类型、授权的无人机系统服务所需的QoS以及无人机系统服务的订阅。遵循模型B的网络辅助C2模型,为了确保UAS操作的C2通信的服务可用性和可靠性,特别是当无人机在操作员的视线之外(BLOS)飞行时,为无人机提供支持冗余的C2通信链路。如果需要创建额外的C2通信连接或更改现有数据连接的配置以进行C2通信,则5G网络会根据无人机系统的授权服务信息和C2通信中所需的QoS和优先级,修改或分配一个或多个C2通信流量的QoS流。

u011376987的博客 2052

Solidity中的EVM内存布局

自由内存指针初始化指向的位置。:向内存地址p存储32字节。:从内存地址p取出32字节。

BeanGuohui的博客 582

Anaconda详细安装及使用教程(带图文)

Anacond的介绍 Anaconda指的是一个开源的Python发行版本,其包含了conda、Python等180多个科学包及其依赖项。因为包含了大量的科学包,Anaconda的下载文件比较大(约531 MB),如果只需要某些包,或者需要节省带宽或存储空间,也可以使用Miniconda这个较小的发行版(仅包含conda和Python)。 Conda是一个开源的包、环境管理器,可以用于...

代码帮 186万+

solidity入门学习——mapping

今天我们来学习下映射的用法,具体以网站的注册过程为例。 一、solidity中,映射的关键字为mapping,首先我们先来定义两个mapping, mapping(address =>uint) idmapping和mapping(uint =>string) namemapping。idmapping用来表示地址变量和整型变量的对应关系,在注册过程中用来表示账户地址和注册号;name...

qinmiaofu的博客 6386

HC32F460的GPIO重映射实战:如何用3步搞定SPI引脚冲突问题

本文详细介绍了HC32F460的GPIO重映射功能,通过三步操作解决SPI引脚冲突问题。文章解析了HC32F460的FuncGroup功能分组机制,提供了具体的寄存器配置步骤和验证技巧,并对比了与传统方案的性能优势,帮助工程师灵活配置引脚,优化硬件设计。

t4y5u6i7o的博客 918

AF3​​​​​​​ Msa、TemplateHit、HitMetadata类解读

Msa:处理 多序列比对 (MSA) 结果,为 AlphaFold3 提供 序列进化信息。 TemplateHit:存储 查询序列与模板结构的比对信息,用于 筛选模板。 HitMetadata:提供 比对模板的 PDB 结构信息,帮助 解析和使用模板数据。

qq_27390023的博客 818

以太坊Solidity的Storage/Memory/Calldata layout

以太坊Solidity的Storage/Memory/Calldata layout

mutourend2010@gmail.com 692

K-Core, K-Shell & K-Crust傻傻分不清楚

K-Core(K-核)就是所有大于等于K的K-Shell的并集;K-Crust(K-皮)就是所有小于等于K的K-shell的并集。

欢迎订阅 -- 小源笔迹 2256

Solidity进阶必知问题

这些是 Solidity 汇编中的一些常用操作和函数,但需要注意的是,使用汇编需要对 EVM 有一定的了解,以及对底层操作的风险和影响有清晰的认识。存储中的数据是持久化的,意味着它们将一直保存在区块链上,即使合约的代码被更新。以上只是一些常见的安全漏洞和问题,在开发智能合约时,最好遵循最佳实践和安全指南,并考虑使用已经经过审查和测试的库来避免这些问题。合约中的存储布局会根据变量的声明顺序决定槽位的分配。这样的设计可以有效地利用存储槽位,避免了不必要的嵌套,并将相似的数据存储在数组和映射中。

海豹姥爷的博客 534

基于STC8G1K08A单片机的PCA捕获外部信号(100~1000HZ)程序实现

基于STC8G1K08A单片机的PCA捕获外部信号(100~1000HZ)程序实现

weixin_74013772的博客 255

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

深入理解Solidity——存储中状态变量的布局

存储中状态变量的布局(Layout of State Variables in Storage) 静态尺寸大小的变量(除了映射和动态尺寸大小的数组类型(的其他类型变量))在存储中,是从位置0连续存储。如果可能的话,不足32个字节的多个条目被紧凑排列在一个单一的存储块,参见以下规则: 在存储块中的第一项是存储低阶对齐的。 基本类型只使用了正好存储它们的字节数。 如果一个基本类型不适合存储块的剩...

黄嘉成的博客 1818

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

智能合约从入门到精通:Solidity语法之内存变量的布局和状态变量的存储模型...

简介:在前面我们已经讲过Solidity语言的一些语法内容,在矩阵元JUICE开放平台的JIDE开发时,一定要注意Layout in Memory和Layout of State Variables in Storage,即内存变量的布局和状态变量的存储模型。内存变量的布局(Layout in Memory) Solidity预留了3个32字节大小的槽位: 0-64:哈希方法的暂存空间(scr...

weixin_33767813的博客 322

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

以太坊solidity内存(memory与storage)与结构体

1.要是函数以结构体作为参数,那么函数修饰符必须有private/internal。1.要是函数以结构体作为参数,那么函数修饰符必须有private/internal。1.要是函数以结构体作为参数,那么函数修饰符必须有private/internal。2.storage可以接受storage的值,并且storage的改动。4.enum的返回值(存储)是uint类型,且满足最小匹配原则返回。2.storage可以接受memory的值。2.storage可以接受memory的值。4.storage的改动。

yueyue763184的博客 2538

【无标题】solidity的内存分配(mload 0x40)

在某些情况下,我们希望在solidity中构造一个buffer,首先我们应该为这个buffer分配内存。在solidity中,只有bytes这样的结构给我们用,但是现在切片和替换对应位置的数据的操作在bytes上不容易实现。我们只好借助于assembly来完成,首先就是为buffer分配内存。 直接上代码: struct buffer { bytes buf; uint capacity; } function init(buffer memory buf, uint capacity)...

h_sn9999的专栏 1万+

solidity笔记(7)——存储区域memory storage stack——2021.5.12

solidity笔记(7)——存储区域memory storage stack一丶memory:二丶storage:三丶stack:四丶存储区域:五丶注意事项:四丶上一篇:solidity笔记(6)——modifier用法 一丶memory: 内存memory,用于暂存数据。其中存储的内容会在函数被调用(包括外部函数)时擦除,所以其使用开销相对较小。 二丶storage: 存储storage,贮存了合约声明中所有的变量。 虚拟机会为每份合约分别划出一片独立的 存储storage 区域,并在函数相互调用

weixin_43402353的博客 1756

以太坊智能合约语言Solidity - 6 内存、引用与持久化存储

关于结构体、枚举、引用、指针的介绍

weixin_51487151的博客 5207

Solidity中的数据存储与EVM内存分配机制

—— 首先,为了更好地理解EVM(以太坊虚拟机)中的内存管理机制,我们还是先来看看Solidity中的基本数据类型。        -值类型:        包括整型(int/uint),地址型(address),布尔(Booleans),定长字节数组(fixed byte arrays),枚举类型(Enums)...在内的基本数据类型,在合约中都是以值的类型进行传递(赋值);        -引...

yjhzxhyzq123的博客 2369

Solidity入门(3)

引用类型: 引用类型可以通过多个不同的名称修改它的值,而值类型的变量,每次都有独立的副本。因此,必须比值类型更谨慎地处理引用类型。 目前,引用类型包括结构,数组和映射,如果使用引用类型,则必须明确指明数据存储哪种类型的位置(空间)里: 内存memory即数据在内存中,因此数据仅在其生命周期内(函数调用期间)有效。不能用于外部调用。存贮在内存中 存储storage状态变量保存的位置,只要合约存在就一直存储.存储在区块链中 调用数据calldata用来保存函数参数的特殊数据位置,是一个只读位置。...

weixin_49489840的博客 3084

『0007』- Solidity状态变量、局部变量与memory 、storage之间的爱恨情仇

孔壹学院:国内区块链职业教育领先品牌 作者:黎跃春,区块链、高可用架构工程师 微信:liyc1215 QQ群:348924182 博客:http://liyuechun.org 在上一节中,我们了解了Solidity类型中哪些是值类型,哪些是引用类型,以及值类型与引用类型的简单对比。本篇教程中,我们将全面讲解memory,storage在Solidity开发中的作用,以及值类型、

孔壹学院 1万+

solidity智能合约[26]-mapping

mappingmapping是一张表,存储key-value对。更准确的说,mapping是一张hash映射表,内部并没有存储真实的key值。mapping用例下面的案例模拟了一个登陆网站,将地址与id绑定在一起。id又与姓名绑定在一起。123456789101112131415161718192021222324pragma solidity ^0.4.23;contrac...

weixin_33849942的博客 416

Solidity 数组、结构体、Mapping、枚举

Solidity数组MappingEnum结构体 数组 数组可以在声明时指定长度,也可以动态调整大小。 对于 存储storage 的数组来说,元素类型可以是任意的(即元素也可以是数组类型,映射类型或者结构体)。 对于 内存memory 的数组来说,元素类型不能是映射类型,如果作为 public 函数的参数,它只能是 ABI 类型。 一个元素类型为 T,固定长度为 k 的数组可以声明为 T[k],而动态数组声明为 T[]。 举个例子,一个长度为 5,元素类型为 uint 的动态数组的数组,应声明为 uint

lzDevastator的博客 1528
上一篇: Inline Assembly 内联汇编总结
下一篇: Spring的 webFlux 和 webMVC
gridlayout
博客等级 码龄19年 12粉丝 26原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值