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 计算规则的变化, 每次存储加载的成本进一步增加, 尤其是在读取管理员地址
   39   40   41   42   43   44   45   46   47   48   49