存储间隙是在基础合约中保留存储槽的约定,允许该合约的未来版本用完这些槽而不影响子合约的存储布局。

要创建存储间隙,请在基础合约中声明一个具有初始槽数的固定大小数组。这可以是一个数组,uint256以便每个元素保留一个 32 字节的槽。为数组使用名称gap或以 开头的名称,以便 OpenZeppelin Upgrades 能够识别间隙

一个存储槽 Solidity 有多大?
32字节
存储就像一个键值数据结构,用于保存 Solidity 智能合约的状态变量值。将存储想象成一个数组将有助于我们更好地理解它。这个存储“阵列”中的每个空间称为一个槽,并保存32 个字节的数据(256 位)。

# 占用2个存储插槽 (storage slot)
uint256 base1;
uint256 base2; // 32 bytes

# 占用1个slot
uint128 base2a; // 16 bytes
uint128 base2b; // 16 bytes – continues from the same slot as above

# 综合: 占用2个slot
uint256 base1; // 32 bytes
uint128 base2a; // 16 bytes
uint128 base2b; // 16 bytes – continues from the same slot as above

# 不占用插槽
bytes32 private constant _RETURN_VALUE = keccak256(“ERC3156FlashBorrower.onFlashLoan”);

# 各占用1个插槽
mapping(uint256 => uint256) private _totalSupply;
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;

# hardhat 验证slot 比对验证槽位
upgrades.validateUpgrade(PROXY, upgradeable);

Solidity 中的整数被限制在一个特定的范围内。例如,对于 uint32,这是 0 到 2**32 – 1。 有两种模式在这些类型上进行算术。“包装” 或 “未检查” 模式和 “检查” 模式。 默认情况下,算术总是 “检查” 模式的,这意味着如果一个操作的结果超出了该类型的值范围, 调用将通过一个 失败的断言 而被恢复。 您可以用 unchecked { … }。 更多的细节可以在关于 未检查 的章节中找到。更多内容 https://docs.soliditylang.org/zh/v0.8.17/types.html

推荐阅读
https://coinsbench.com/solidity-layout-and-access-of-storage-variables-simply-explained-1ce964d7c738