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

PWM控制技术+Simulink仿真详解

想要理解SVPWM控制技术,首先要了解PWM控制技术。 PWM控制技术就是对脉冲宽度进行调制的技术,通过对一系列脉冲宽度进行调制来等效获得所需要的波形(包括形状和幅值)。 PWM控制的基本原理:冲量(窄脉冲的面积)相等而形状不同的窄脉冲加在具有惯性的环节上时,其效果(输出响应波形)基本相同,即面积等效原理;用一系列幅值相等,宽度按一定规律变化的高频脉冲序列代替期望的输出波形,多用于逆变电路的控制; PWM信号生成的方法有:计算法、调制法、跟踪法,主要对调制法进行详解 ...

小师兄的学习记录 5万+

Solidity Storage底层管理

Solidity Storage底层管理

mutourend2010@gmail.com 1836

scanpy单细胞转录组python教程(四):单样本数据分析之降维聚类及细胞注释

本文介绍了使用scanpy进行单细胞转录组分析的降维聚类和细胞注释流程。首先通过PCA降维并可视化主成分贡献,然后使用不同分辨率参数(0.2-1.0)进行Leiden聚类。通过Wilcoxon检验鉴定marker基因,并基于经典marker基因手动注释细胞类型。最后对低质量细胞群进行过滤,并重新计算邻居图和UMAP可视化。流程中包含PCA方差分析、多分辨率聚类比较、marker基因筛选和基于UMAP的细胞类型可视化等关键步骤,为后续分析奠定基础。

qq_42090739的博客 942

国土变更调查中六类拓扑错误的成因分析与高效修复实践

本文深入分析了国土变更调查中六类拓扑错误的成因,包括边界不一致和不规则图形等常见问题,并提出了高效的自动化修复实践。通过智能咬合算法、引力-斥力平衡模型等核心技术,显著提升了修复效率,节省人工质检时间70%。文章还分享了实战中的避坑指南和黄金法则,为相关从业人员提供了宝贵经验。

weixin_29202213的博客 359

Solidity中的EVM内存布局

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

BeanGuohui的博客 582

一篇讲透:豆包、元宝、DeepSeek、Kimi、WorkBuddy,职场里到底怎么分工

这篇文章深入分析了当前主流AI工具(WorkBuddy、豆包、腾讯元宝、DeepSeek、Kimi)的特点和使用场景,帮助读者根据不同工作需求选择合适的AI助手。核心观点包括: AI工具各有所长:豆包适合快速创作初稿,元宝擅长信息检索整理,DeepSeek强于逻辑分析,Kimi专精文本处理,WorkBuddy则更适合任务推进和成果交付。 使用前需明确需求:是要创意发散、信息整理,还是任务执行?不同阶段应选用不同工具组合。 提供了6个具体职场场景的解决方案,包括文章创作、课程设计、会议纪要等,并给出详细的操作

weixin_39284145的博客 1万+

solidity入门学习——mapping

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

qinmiaofu的博客 6386

Windows 24H2下eNSP AR_40启动失败的终极修复指南

本文针对Windows 11 24H2更新后eNSP AR_40路由器启动失败的问题,提供了终极修复方案。核心在于解决系统强制虚拟化安全(VBS/Hyper-V)与老版模拟软件的兼容性冲突。指南详细介绍了安装关键系统更新KB5053656、精细调整Windows虚拟化功能以及后续排错步骤,帮助用户在24H2系统上稳定运行eNSP进行网络实验。

weixin_29233333的博客 507

基于51单片机+SYN6288语音播报

51单片机控制SYN6288语音播报资料SYN6288模块原理图语音合成命令接线如何接线实现原理程序代码main.csyn6288.cuart.cdelay.c基于 51单片机的其他项目基于51单片机+遥控灯基于51单片机+LCD1602显示基于51单片机+红外遥控解码+LCD1602显示基于51单片机+DHT11温湿度+LCD1602显示基于51单片机+DS18B20温度测温器+LCD1602显示尾声 资料 我用的是绿深电子技术的模块,资料也挺齐全的。也有相关例程。 SYN6288模块原理图 语音合成

weixin_47457689的博客 3万+

以太坊Solidity的Storage/Memory/Calldata layout

以太坊Solidity的Storage/Memory/Calldata layout

mutourend2010@gmail.com 692

CODESYS EtherCAT通讯断了怎么办?手把手教你用ST语言写状态监测程序(附完整代码)

本文详细解析了CODESYS平台下EtherCAT通讯中断的故障排查与恢复方法,通过ST语言编写状态监测程序实现链路监测、故障隔离和伺服恢复。文章包含完整代码示例,帮助工程师快速诊断EtherCAT网络问题,提升工业自动化设备的运行稳定性。

weixin_30919571的博客 209

Solidity进阶必知问题

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

海豹姥爷的博客 534

【AUTOSAR SystemServices】AUTOSAR CP中Watchdog Manager模块技术解析

本文深入解析了AUTOSAR中的Watchdog Manager模块实现。该模块通过多层次监督机制(Alive/Deadline/Logical Supervision)确保系统安全运行,具备动态模式切换和分级故障处理能力。 关键实现包括: 数据结构设计:包含监督实体状态结构体(实时状态维护)、监督配置结构体(支持模式切换)和全局状态信息(系统级监控) 核心流程优化:初始化采用事务性设计,检查点处理通过条件编译优化,主监控循环采用流水线式并行处理 监督机制实现:Alive监督采用滑动窗口算法,Deadlin

1039

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

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

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

黄嘉成的博客 1818

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

智能合约从入门到精通: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

WINCC7.3破解文件

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

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

以太坊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、付费专栏及课程。

余额充值