我在本地 hardhat 节点上升级了我的 FleetRegistry 代理。V1 里注册了 37 台设备。我用 scripts/upgrade.js 部署了 V2 的实现,然后在代理上调用了 upgradeToAndCall(implAddr, "0x")。

升级后:

  • 在代理上调用 deviceCount() 返回 0
  • devices(id) 仍然能返回旧的条目,所以 mapping 没丢
  • registrationFee() 返回 37,但从来没人设置过费用,所以 registerDevice 现在要收 37 wei

一开始我以为是空 data 的 upgradeToAndCall 把代理里的什么东西重置了。后来我又觉得 .openzeppelin/ 里的 manifest 过期了,就把它删了。没有任何变化。

我不明白为什么一个计数器变成了 0,而其他数据都正常。

V1 的状态变量:

mapping(bytes32 => Device) public devices;
uint32 public minFwVersion;
uint256 public deviceCount;

V2:

mapping(bytes32 => Device) public devices;
uint32 public minFwVersion;
uint256 public registrationFee; // new in V2, kept next to the other config
uint256 public deviceCount;

升级脚本没有调用 upgrades.validateUpgrade。我在那里写了条注释,说 UUPS 已经通过 proxiableUUID 拒绝有问题的实现了。

函数除了费用检查之外都一样。Solidity 0.8.24,OpenZeppelin upgradeable contracts,装了 hardhat-upgrades 插件。

问题是出在我的 V2 合约里,还是出在我升级的方式上?我现在没法运行这个项目,所以只能描述我当时看到的情况。