以太坊智能合约部署完成之后,原有合约地址的字节码不能够直接修改,但可以通过特定架构实现业务逻辑的迭代更新,并不是完全没有调整空间。很多币圈用户容易混淆不可篡改和不可升级两个概念,区块链的不可篡改,指已经上链保存的代码、交易记录不能被抹除改写,不等于项目完全不能更新业务功能。普通合约一旦部署,以太坊虚拟机没有指令可以覆盖该地址已经存在的运行字节码,不管开发者还是普通用户,都无法直接重写这个地址上已经固化的代码内容,这是EVM底层机制带来的硬性约束。

行业主流实现合约更新的方案是代理模式,把存储数据的代理合约和执行业务的逻辑合约拆分成两个独立合约。代理合约地址对外保持不变,用户始终和这个地址交互,代币余额、用户配置等全部状态数据都保存在代理合约内部,本身不写复杂业务代码。依靠delegatecall底层操作码,代理会把外部全部调用转发到逻辑合约执行,代码运行时读取和写入代理这边的存储空间。当需要迭代或者修复漏洞时,开发者部署一份全新的逻辑合约,修改代理内部记录的逻辑合约指向地址,后续所有用户请求就会跑新的业务代码,旧逻辑合约的字节码依旧完整保存在链上,不会被删除改动。目前市面上多数DeFi项目、NFT项目大多采用ERC1967标准的UUPS或者透明代理架构完成这套升级逻辑。

除代理升级之外,还有合约整体迁移的备选方式,也就是直接部署一份全新完整合约,再把旧合约里面的资产、用户状态批量搬运过去。这种方式不用搭建代理架构,但弊端十分突出,旧地址代码完全维持原样,用户需要主动切换交互地址,平台前端、第三方工具、外部合约都要同步适配新地址。大批量数据迁移会产生高额gas消耗,部分用户还会继续停留在旧合约交互,很容易出现数据割裂,一般只在没有提前设计升级架构,出现重大漏洞需要紧急处理的时候才会选用。

可升级合约也会带来新的安全风险,这也是币圈参与者需要重点留意的细节。代理架构下升级权限掌握在管理员账户手里,如果私钥泄露或者团队作恶,可以随意替换逻辑合约,转移合约内存储的资产。开发阶段如果变量存储顺序设计出错,升级之后会发生存储槽冲突,直接造成用户数据错乱、资产异常。即便是成熟的代理标准,初始化函数保护、函数签名冲突等问题,依旧会成为攻击突破口。对于普通投资者,不能看见合约可以升级就默认项目安全,需要关注升级权限是否做时间锁、多签管理,判断项目方是否存在不受约束的单方面改动能力。
