合约升级后,之前签的授权还有效吗? 图 1
合约升级后,之前签的授权还有效吗? · 图 1

授权记录的宿主:代币合约而不是业务合约

要回答「合约升级后授权是否仍然有效」,先要分清你签的授权记录在哪里。对 ERC-20 代币说 approve,额度记录写进的是代币合约自己的存储,被授权方(spender)只是一个地址。绝大多数 DeFi 交互的授权对象是业务合约(金库、路由器、质押合约)。当项目方给业务合约做可升级改造——最常见的做法是留一个不动的代理地址,把背后的实现逻辑换掉——你当年对那个代理地址的授权记录分毫未动,新实现代码继续持有旧额度。结论因而相当直白:只要授权对象那个地址不变,无论它背后的代码换了几代,授权都仍然有效。风险也由此而来:被升级出的缺陷实现,或权限管理失守的代理合约,都能凭你几年前的那一次 approve 动用资产。

授权的生命周期怎么终结

一条授权只有三种结局:被授权地址主动用掉(用完或你正常走协议流程消耗掉)、你显式撤销、或(少数代币支持的)过期机制到期。它不会因为协议改名、版本迭代、页面下线而失效。判断哪些值得撤销的实用标准是:该协议是否仍在使用、授权对象是否还能对应到当前官方地址列表、额度是否无限。

两种终结方式的差异

方式一是调用 revoke(或 approve 一个零额度地址):语义上最干净——把 allowance 清零;需要一次链上交易和对应 Gas。方式二是「以零覆盖」:再调用一次 approve,把同一 spender 的额度改成零;在很多代币的实现里它与 revoke 走同一逻辑分支,消耗的 Gas 和生效速度基本一致,真正的意义在于部分钱包与老协议只提供 approve 入口,用零覆盖即可完成撤销,不必寻找专门的 revoke 按钮。两者都要等交易被打包才生效,不存在「即时生效」;也都要占用你的 Nonce——撤销交易排在你的正常交易序列里,若你在同一区块里密集操作,顺序由费率和打包规则决定,大额迁移场景建议撤销与转账分块完成,避免互相挤占。

建议的节奏

把「协议升级」当作固定排查触发器:每次常用协议发布新版本,核对其公告中的合约地址是否变更——地址没变、实现变了,你此前的授权自动指向新代码,值得重审一次;地址变了,则进入「新地址重新授权加旧地址撤销」的完整闭环。授权是持久化的钥匙,升级换了锁芯,钥匙不会自己消失,得由你亲手回收。

判断一个合约是不是可升级的

普通用户不用读代码也能大致判断授权对象的「升级属性」。区块浏览器里看三点:其一是合约是否标注为代理模式(浏览器通常直接标出 Proxy 字样或显示实现地址链接),标了代理就意味着背后的实现可能已经换过;其二是看合约的「编译器与源码验证」标签里有没有 Storage 层的独立地址指向另一个合约;其三是查该合约近期是否发生过「实现更换」类事件——在事件列表里筛选实现更新(Upgraded 事件)就能看到它的换芯历史。这些操作合起来不到五分钟,却能把「这个授权对象会随时间变代码吗」这个抽象问题变成一条可核对的事实。

如果对象确实是可升级合约,你面对的不是一个地址,而是一个会换脸的团队。对这类合约的授权策略应该相应收紧:只给刚好用完的额度而不是无限额度,长期不用的协议先撤销再说,升级公告发布时把它的历史授权重新审一遍。反过来,对不可升级、代码即终身的合约,授权的长期风险主要来自代码自身是否有缺陷,而不是管理权交接——两种风险的排查方向完全不同,混淆它们会让人在错误的地方放心、在错误的地方紧张。

一个容易忽略的细节:有些协议同时使用代理合约和独立的管理权限合约(升级管理员、权限管理员分开),一次「换管理密钥」的公告并不体现在合约地址变化上,却可能改变谁能升级它。这类治理层面的变动通常只在治理论坛和公告里可见,把它们纳入「常用协议订阅清单」,重大权限交接时才能和地址层的变化一起拼出完整图。

本指南只提供防御与处置建议,不构成任何投资建议。