本文介绍了ERC-7201提案,旨在解决Solidity合约存储槽中存在的DelegateCall安全风险和升级不便等问题。ERC-7201引入命名空间概念,通过特定算法为不同逻辑组件分配独立的存储区域,实现存储隔离、升级友好、模块化支持和工具兼容等优势。文章还提供了实现示例,展示了如何在合约中使用ERC-7201。
Solidity 合约将状态存储在存储槽中,这些存储槽是 32 字节的空间,从零开始按顺序标识。这种模式存在一些问题。
DelegateCall
执行逻辑时,多个合约将共享相同的存储空间并通过槽位更改存储,这带来了巨大的安全风险。所以这些是 ERC7201 想要解决的问题。
ERC-7201 引入了突破性的“命名空间”概念,使开发人员能够为不同的逻辑组件分配独立的存储区域。其主要功能包括:
ERC-7201 定义了一个用于计算存储根位置的独特公式:
keccak256(keccak256(namespace) - 1) & ~0xff
该公式确保:
这是示例合约
contract ERC7201Example is Extend {
/// @custom:storage-location erc7201:ERC7201Example
struct MainStorage {
uint256 x;
uint256 y;
}
// keccak256(abi.encode(uint256(keccak256("ERC7201Example")) - 1)) & ~bytes32(uint256(0xff));
bytes32 private constant MAIN_STORAGE_LOCATION = 0xcb9fa12623879b77d9ed7b1c782042856a80da112b7898c6b7012bb9c0588f00;
function _getMainStorage() private pure returns (MainStorage storage $) {
assembly {
$.slot := MAIN_STORAGE_LOCATION
}
}
function setX(uint256 _x) external {
MainStorage storage s = _getMainStorage();
s.x = _x;
}
function setY(uint256 _y) external {
MainStorage storage s = _getMainStorage();
s.y = _y;
}
}
这是使用不同存储位置的父合约
contract Extend {
/// @custom:storage-location erc7201:Extend
struct ExtendStorage {
uint256 e;
}
// keccak256(abi.encode(uint256(keccak256("Extend")) - 1)) & ~bytes32(uint256(0xff));
bytes32 private constant EXTEND_STORAGE_LOCATION =
0xdc7c3789c251966f77e4ff9dc602e16101d09d1cf2378a0a6c0a2e5b1148cf00;
function _getExtendStorage() private pure returns (ExtendStorage storage $) {
assembly {
$.slot := EXTEND_STORAGE_LOCATION
}
}
function setExtend(uint256 _e) external {
ExtendStorage storage s = _getExtendStorage();
s.e = _e;
}
}
你可以在 https://github.com/sunnybinb/contract-storage 中查看完整代码
以下是这种模式的一些优点
- 原文链接: blog.blockmagnates.com/e...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!