You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

forge-std中storage slot是什么?如何指定编号?测试编号变更失败解惑

关于Solidity存储槽(Storage Slot)与Forge vm.store的解惑

1. 什么是Storage Slot?

以太坊合约的状态变量(比如NFT合约里的totalSupply、maxSupply这类持久化变量)都存储在区块链的「存储(Storage)」区域中。这个区域被划分为固定大小的单元——每个单元占32字节(即bytes32),每个单元就是一个存储槽(Storage Slot),槽位从0开始按顺序递增编号。

Solidity默认会按照合约中状态变量的声明顺序,依次为变量分配槽位(除非存在变量打包优化:比如多个uint128、bool这类小类型变量会被合并到同一个槽里,节省存储成本)。

2. 为什么你的代码里必须用槽位7?

在你的测试代码中,vm.store修改的是NFT合约里控制供应量上限的变量(比如totalSupply或maxSupply)所在的槽位——也就是第7个槽。当你把这个槽的值设为10000,就模拟了「已铸造数量达到上限」的状态,此时调用mintNft会触发MaxSupplyReached回滚,测试符合预期。

如果改成槽位8,你修改的是另一个无关变量的存储位置(比如合约的owner地址、某个配置参数等),此时供应量相关的变量并没有被篡改,mintNft不会触发回滚,vm.expectRevert断言失败,测试自然通不过。

3. 如何确定变量对应的存储槽?

  • 查看合约变量声明顺序:如果你的NFT合约状态变量是按顺序声明的,比如:
    contract MyNFT {
        address public owner; // 槽位0
        uint256 public maxSupply; // 槽位1
        uint256 public totalSupply; // 槽位2
        // ... 其他变量,直到第7个槽对应目标变量
    }
    
    可以按顺序数到目标变量的槽位(注意要排除变量打包合并的情况)。
  • 用Foundry工具验证:在测试中可以用vm.load读取指定槽的值,确认是否对应目标变量:
    bytes32 slotValue = vm.load(address(nftToken), bytes32(uint256(7)));
    console.log(uint256(slotValue)); // 打印该槽当前值,验证是否是要修改的变量
    
  • 查看编译后的存储布局:用forge build编译合约时,会在out/目录的合约JSON文件中生成存储布局,里面会明确列出每个状态变量对应的槽位。

内容的提问来源于stack exchange,提问作者Santiago

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 08:59:19