存储兼容性:使用 "proxy" 设计模式和更改映射类型的 Solidity 可升级智能合约
Storage compatibility: Solidity upgradable smart contract using "proxy" design pattern and changing the mapping type
有人使用“代理”模式编写 upgradable smart contracts 吗?
我打算 upgrade/extend 我的旧智能合约,最初,我的代码如下所示:
mapping(address => uint256) balance;
我打算这样写:
struct PackedBalance {
uint256 balance;
uint256 locked_balance; // to support a new feature.
}
mapping(address => PackedBalance) balance;
我担心的是“存储”是否与“旧版本智能合约”兼容。
我刚刚阅读了“Layout of State Variables in Storage”。据我了解,它是兼容的。但是我是新手,所以想请教一些高手。
“兼容”意味着:我仍然可以读取现有存储槽的正确“余额”。我可以写“locked_balance”而不破坏任何东西(比如覆盖)。
是的,将映射中的 uint256
扩展到同一映射中的 struct
是安全的。
让我们调试这两个示例合约:
pragma solidity ^0.8;
contract MyContract {
mapping(address => uint256) balance;
function setBalanceForAddress(address _address, uint256 _balance) external {
balance[_address] = _balance;
}
}
pragma solidity ^0.8;
contract MyContract {
struct PackedBalance {
uint256 balance;
uint256 locked_balance;
}
mapping(address => PackedBalance) balance;
function setBalanceForAddress(address _address, uint256 _balance, uint256 _lockedBalance) external {
balance[_address] = PackedBalance(_balance, _lockedBalance);
}
}
address
总是 0x1231231231231231231231231231231231231231
(用于调试目的)。
第一个合约将uint256
字段存储到存储槽0xf100689cc6bb188feb3c0ef4658bee6e8042e58e79daebcd84870d7f336a8422
发送数据:
0x4fa1007300000000000000000000000012312312312312312312312312312312312312310000000000000000000000000000000000000000000000000000000000000064
重新混合调试器屏幕截图:
第二个合约将 struct
存储到插槽 0xf100689cc6bb188feb3c0ef4658bee6e8042e58e79daebcd84870d7f336a8422
(与第一个合约相同)和 0xf100689cc6bb188feb3c0ef4658bee6e8042e58e79daebcd84870d7f336a8423
(紧挨着它)。
发送数据:
0x6f7223d9000000000000000000000000123123123123123123123123123123123123123100000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064
重新混合调试器屏幕截图:
有人使用“代理”模式编写 upgradable smart contracts 吗? 我打算 upgrade/extend 我的旧智能合约,最初,我的代码如下所示:
mapping(address => uint256) balance;
我打算这样写:
struct PackedBalance {
uint256 balance;
uint256 locked_balance; // to support a new feature.
}
mapping(address => PackedBalance) balance;
我担心的是“存储”是否与“旧版本智能合约”兼容。
我刚刚阅读了“Layout of State Variables in Storage”。据我了解,它是兼容的。但是我是新手,所以想请教一些高手。
“兼容”意味着:我仍然可以读取现有存储槽的正确“余额”。我可以写“locked_balance”而不破坏任何东西(比如覆盖)。
是的,将映射中的 uint256
扩展到同一映射中的 struct
是安全的。
让我们调试这两个示例合约:
pragma solidity ^0.8;
contract MyContract {
mapping(address => uint256) balance;
function setBalanceForAddress(address _address, uint256 _balance) external {
balance[_address] = _balance;
}
}
pragma solidity ^0.8;
contract MyContract {
struct PackedBalance {
uint256 balance;
uint256 locked_balance;
}
mapping(address => PackedBalance) balance;
function setBalanceForAddress(address _address, uint256 _balance, uint256 _lockedBalance) external {
balance[_address] = PackedBalance(_balance, _lockedBalance);
}
}
address
总是 0x1231231231231231231231231231231231231231
(用于调试目的)。
第一个合约将uint256
字段存储到存储槽0xf100689cc6bb188feb3c0ef4658bee6e8042e58e79daebcd84870d7f336a8422
发送数据:
0x4fa1007300000000000000000000000012312312312312312312312312312312312312310000000000000000000000000000000000000000000000000000000000000064
重新混合调试器屏幕截图:
第二个合约将 struct
存储到插槽 0xf100689cc6bb188feb3c0ef4658bee6e8042e58e79daebcd84870d7f336a8422
(与第一个合约相同)和 0xf100689cc6bb188feb3c0ef4658bee6e8042e58e79daebcd84870d7f336a8423
(紧挨着它)。
发送数据:
0x6f7223d9000000000000000000000000123123123123123123123123123123123123123100000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000064
重新混合调试器屏幕截图: