代理合约中选择器冲突(Selector Clash)的另一个解决办法:通用可升级代理(UUPS,universal upgradeable proxy standard)。代码由OpenZeppelin
的UUPSUpgradeable
简化而成,不应用于生产。
UUPS
作为透明代理的替代方案,UUPS也能解决"选择器冲突"(Selector Clash),即合约存在两个选择器相同的函数,可能会造成严重后果。
UUPS(universal upgradeable proxy standard,通用可升级代理)将升级函数放在逻辑合约中。这样一来,如果有其它函数与升级函数存在“选择器冲突”,编译时就会报错。
下表中概括了普通可升级合约,透明代理,和UUPS的不同点:
这里重点是delegatecall的使用
如果用户A通过合约B(代理合约)去delegatecall
合约C(逻辑合约),语境仍是合约B的语境,msg.sender
仍是用户A而不是合约B。因此,UUPS合约可以将升级函数放在逻辑合约中,并检查调用者是否为管理员。
UUPS的代理合约
UUPS的代理合约看起来像是个不可升级的代理合约,非常简单,因为升级函数被放在了逻辑合约中。它包含3
个变量:
implementation
:逻辑合约地址。admin
:admin地址。words
:字符串,可以通过逻辑合约的函数改变。
它包含2
个函数
- 构造函数:初始化admin和逻辑合约地址。
fallback()
:回调函数,将调用委托给逻辑合约。