Page 44 - 《软件学报》2026年第1期
P. 44
郭涛 等: 智能合约可升级技术综述 41
受其他委派调用并执行管理员特定的逻辑, 如升级合约、更改权限等. 例如当存放当前实现合约的地址需要被更
新时, 透明代理发出 Upgraded 事件, 以便外部代理合约监听到实现合约的变更. 计算方式为 bytes32(uint256(keccak256
(“eip1967.proxy.implementation”))–1). 存储插槽也可以通过 AdminChanged 事件更新管理员地址. 计算方式为
bytes32(uint256(keccak256(“eip1967.proxy.admin”))–1).
如图 9, 为避免实现合约的版本迭代而造成的存储冲突, 代理合约和实现合约升级过程中共享相同的存储结
构. 两者通过直接继承相同的变量定义来确保存储布局完全一致, 使得实现合约的版本迭代可以与之前的版本无
缝兼容. 此外, 如图 10 使用恒定变量哈希的方法 (如 keccak256) 来定义存储槽的位置, 将每个关键变量存储在特
定的槽中. 这样即使实现合约版本升级, 新增或调整变量也不会影响已有存储的正确性, 从而保证向后兼容性. 伪
随机存储槽方法, 使新地址具有足够的随机性. 即便实现合约中的某个变量不慎占用同一槽位, 其影响也可以忽略
不计, 从而进一步降低潜在冲突的风险.
1 Proxy Implementation
2
3 address implementation address var1 碰撞!
4 mapping var2
5 uint256 var3
6 …
1 Proxy Implementation
2
3 address var1
4 mapping var2
5 uint256 var3
6 …
7 …
8 address implementation … 随机槽
图 9 透明代理存储布局示意图
图 10 继承存储函数
透明代理模式在提升用户体验和升级便捷性的同时, 需要在性能和安全性之间进行权衡. 首先是 Gas 消耗过
高问题, 透明代理的设计需要将升级逻辑存储在代理合约中, 这意味着调用类似 upgradeTo(address newImple-
mentation) 的函数时, 代理必须更新实现合约地址. 由于每次用户调用均需通过代理层转发到实现合约, 代理合约
承担额外的处理步骤, 从而增加 Gas 消耗, 使得透明代理的部署和运行成本高于普通合约. 其次是权限判定的复杂
性, 普通用户的调用应优先转发至实现合约, 而管理员调用应直接执行代理合约的升级逻辑. 为区分这两种情况,
代理合约需要额外的逻辑判断用户权限. 此外, 由于透明代理对权限的判断依赖管理员地址的存储加载, 在伊斯坦
布尔 (Istanbul) 分叉之后, 由于 Gas 计算规则的变化, 每次存储加载的成本进一步增加, 尤其是在读取管理员地址

