以太坊原生部署完成的智能合约代码本身无法直接修改,但借助代理架构等特殊设计模式,可以在不改变用户交互地址的前提下替换业务执行逻辑,实现合约功能迭代,普通无代理架构的合约部署后字节码永久固化,不存在直接改写的途径。很多币圈用户容易混淆“修改合约字节码”和“替换执行逻辑”两个概念,区块链底层会把合约部署的完整字节码写入区块,全网节点同步保存,任何直接改写原有合约地址代码的交易都会被EVM拒绝,这是以太坊不可篡改特性的底层体现,也是很多DeFi协议信任基础的来源。想要调整合约行为,不能在原有合约地址上改动代码,只能依靠开发阶段提前预埋的技术方案,事后没有办法给普通合约强行加上修改能力。

代理模式是行业内最主流的合约升级手段,核心思路是把一份合约拆分为代理合约和逻辑合约两部分。代理合约作为用户唯一交互入口,固定地址不变,专门保存余额、配置参数等全部状态数据,自身几乎不写业务代码;逻辑合约承载交易、转账、权限校验这类实际业务逻辑,是可以被替换的部分。用户发起的每一笔交互,都会通过delegatecall操作码转发到逻辑合约执行,执行读写操作全部作用在代理合约的存储空间内,逻辑合约本身只提供代码不保存用户数据。当项目需要修复漏洞或者新增功能时,开发者部署一份全新逻辑合约,修改代理合约内记录的逻辑合约指向地址,外部用户依旧使用原来的合约地址,感知不到底层发生的变更。

代理升级也存在不少现实约束和安全隐患,并不是完全自由的修改。首先代理与逻辑合约必须严格对齐存储变量顺序,一旦新版本逻辑合约变量排布发生改动,就会出现存储槽冲突,直接造成用户资产数据错乱,这类漏洞在过往项目中多次出现。其次升级动作由管理员或者治理合约权限控制,如果管理员私钥泄露,攻击者就可以恶意替换逻辑合约,篡改业务规则盗取资产;不少项目会选择放弃管理员权限,一旦权限销毁,即便后续爆出高危漏洞,合约也彻底丧失升级能力。市面上分为透明代理、UUPS、Diamond多模块代理等不同标准,UUPS把升级接口放置在逻辑合约内部,代理本体代码更精简,是当下新项目使用较多的方案,而Diamond架构适合功能庞大、需要高频迭代的复杂协议。

除代理模式之外,合约迁移是另外一种备选方案。该方式不会复用旧合约地址,开发者部署完整的新版合约,再把旧合约中的用户余额、质押信息等状态批量迁移过去,需要用户主动切换至新地址交互。这种做法没有代理模式的存储冲突风险,但对用户体验影响较大,DApp前端、第三方工具、交易所都需要同步适配新合约地址,迁移过程中也存在数据搬运出错的风险。硬分叉属于极端特殊情况,全网节点同步修改客户端规则才能改变合约执行结果,历史上仅发生过极少数案例,属于社区层面重大决策,不能当作项目方常规修改合约的手段。
