当前位置:首页 > 技术 > 正文内容

Solidity中存储和内存的数据布局

访客 技术 2026年10月14日 1
  1. 存储(Storage)中的数据布局

1.1 基本原则(基本值类型)

  • 独立变量互不影响,因此非常安全。
  • 变量存储在slot中,共有2^256个slot,每个长度为256位。
  • 从0开始连续存储(动态数组和映射除外),当有连续几个变量都小于256位时,会尝试将它们放在同一个slot中。
  • 遵循以下规则:
  • 小于256位的数据存储在低阶位置(右边)。
  • Value types使用固定位数存储(例如uint128始终使用128位)。
  • 当前slot不够存时,会存在下一个slot中。
  • Structs和Array会在新的slot开始存储,并且紧密打包。
  • Struct和Array后面的数据,会单开一个slot。

1.2 动态数组和映射

由于动态数组和映射的不可预测性,它们不像普通状态变量那样紧跟着存储,而是占用一个新的slot,再根据特定规则存储。

动态数组

  • 在slot p的位置存储数组长度,在slot Keccak256(p)的位置开始存储数组元素。
Key Value
slot 0 其他数据
... ...
slot p 数组长度
... ...
slot Keccak256(p) 元素1
slot Keccak256(p) + 1 元素2
... ...
function getHash(uint256 value) public pure returns (bytes32) {
    return keccak256(abi.encodePacked(value));
}

映射

  • 在slot p的位置存储全0数据,表示此处是一个映射的开始。
  • 映射的key存储在slot Keccak256(h(k) . p),映射的value则直接存储在对应的slot中。
Key Value
slot 0 其他数据
... ...
slot p 全0 (映射起始)
... ...
slot Keccak256(h(key1) . p) key1.value
... ...
slot Keccak256(h(key2) . p) key2.value
... ...
示例1(多个连续映射)
contract Example {
    uint256 public a = 0x1;
    mapping (address => uint256) public b;
    mapping (address => uint256) public c;

    function addMapping() public {
        b[address(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4)] = 0xb11;
        c[address(0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB)] = 0xc11;

        b[address(0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2)] = 0xb22;
        c[address(0x617F2E2fD72FD9D5503197092aC168c91465E7f2)] = 0xc22;

        b[address(0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db)] = 0xb33;
        c[address(0x17F6AD8Ef982297579C203069C1DbfFE4348c372)] = 0xc33;
    }
}
示例2(多重映射)
contract Example {
    uint256 public a = 0x1;
    mapping (address => mapping (uint256 => uint256)) public data;

    function addMapping() public {
        data[address(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4)][3] = 4;
        data[address(0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2)][7] = 8;
    }
}

1.3 字符串和字节数组

字符串和字节数组的编码方式类似,但不同长度的编码方式有所不同。

长度不超过31字节

  • 新起一个slot,前31个字节存放数据,最后一个字节存放数据长度 * 2。
contract Example {
    bytes public b = "WZM";
    string public c = "WZM1230";
}

长度超过31字节

  • 在slot p的位置存储length * 2 + 1,在slot Keccak256(p)的位置开始存储数据。
contract Example {
    bytes public b = "WZMWZMWZMWZMWZMWZMWZMWZMWZMWZMWZM";
    string public c = "WZM1230WZM1230WZM1230WZM1230WZM1230";
}
  1. 内存(Memory)中的数据布局

  • 仅有string、bytes、array、struct使用内存。
  • 以太坊内存保留了前四个slot,分别是:
  • 0x00 - 0x1f, 0x20 - 0x3f:两个slot,存储散列方法。
  • 0x40 - 0x5f:当前分配的内存大小。
  • 0x60 - 0x7f:零slot(不能写入)。

每个元素均占用一个slot,与存储不同。

contract Example {
    struct Wallet {
        address addr;
        uint16 num;
    }

    function Demo() public {
        bytes memory a = "123";
        bytes8[] memory b = new bytes8[](0x3);
        string memory c = "WZM1230";
        Wallet memory wallet = Wallet(0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db, 0x123);
    }
}

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。