合约升级
- 1 min设计一个可升级的合约
在处理可升级合约时,经常使用存储槽来避免存储冲突。 该库有助于在不需要内联汇编的情况下读取和写入此类插槽。
该库中的函数返回包含可用于读取或写入的“值”成员的 Slot 结构。 设置 ERC1967 实现槽的示例用法:
proxy contract
// ERC1967Proxy is Proxy, ERC1967Upgrade
// UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade
// UUPSUpgradeableMock is CountersImpl, UUPSUpgradeable
library StorageSlot{
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
}
contract ERC1967Proxy{
// 这是EIP1967的提议,这个位置slot留给代理合约升级,编译器会避免使用这个地址
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
function _setImplementation(address newImplementation) private {
require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
}