什么是代币授权

在以太坊这类链上,USDT、USDC 这些代币各自是一份独立合约在记账。当你想在 Uniswap 这样的 DEX 上拿 USDT 换 ETH,麻烦来了 —— Uniswap 的合约并不能直接从你账上扣 USDT,它没有这个权限。

于是 ERC-20 标准设计了两步动作:你先调用代币合约的 approve(spender, amount),告诉这份 USDT 合约"我允许 Uniswap 这个地址,从我账上最多动用这么多 USDT";之后 Uniswap 执行兑换时,再调用 transferFrom 把币划走。第一步是"授权",第二步才是"花钱"。

这套机制是整个 DeFi 能跑起来的前提,DEX 兑换、借贷协议存款、跨链桥转币,背后几乎都有一次 approve。问题出在两点:授权的额度有效期。这两点没人逼你关心,钱包默认值往往替你做了最省事、也最危险的选择。

无限授权为什么是最大暗门

多数 DApp 弹出 approve 请求时,默认填的额度不是"这次要换的那点钱",而是 uint256 的最大值,约等于无限。理由很现实:授权一次无限额度,之后每次交易就不用再签 approve,体验顺滑。代价是你把这个币种的全部余额、以及未来转进来的余额,都交给了对方合约支配。

更关键的是有效期 —— 这份授权不会自己过期。你三年前为换一次币给某协议的无限授权,今天还在生效。哪天那份合约被攻破,或者它当初就是钓鱼合约在等收网,攻击者只要调一次 transferFrom,你那个币种的余额就一次性没了 —— 不需要你的私钥、不需要你再签任何东西,因为你早就签过了。

注意

无限授权 + 合约被攻破,是链上"睡着也会丢币"的典型路径。被掏空的人很多不是当天被钓,而是某次授权在很久以后被人利用。它和私钥泄露不同:私钥泄露是整个地址沦陷,授权被利用通常只损失被授权那个币种 —— 但你给十几个协议都开无限授权,就是在墙上开了十几扇门。

骗子盯上的就是你的授权

理解了授权机制,就能看懂大量钱包诈骗的真正套路:它们骗的不是私钥,而是骗你签下一笔授权或等价的签名。这也是为什么"我从没把助记词告诉别人,怎么还是丢币了"会发生 —— 你没泄露助记词,只是签错了一次授权。站里拆过几个真实案例,骗的都是授权这一环:

  • 假空投诱导你签 setApprovalForAll 的钓鱼局 —— 一个针对 NFT 的"全部授权"开关,签下去等于把整个系列的 NFT 交给对方处置。
  • 伪装成正经 DEX 的 EIP-2612 Permit 假兑换页 —— 你以为在签一次普通兑换,实际签的是一份链下授权。
  • 挂在 NFT 市场报价流程里的 Blur bid permit 陷阱 —— 用看似无害的"挂单签名"骗走授权。
  • 仿冒 Uniswap 的 Permit2 假签名 —— 针对的就是下文要讲的 Permit2 这套新机制。

这几个案例的共同点是:受害者签名那一刻,弹窗里要么是看不懂的十六进制,要么被精心包装成"正常操作"。防住它们靠的不只是"别乱点",更是看懂你正在授权什么、以及事后把多余的授权清掉。前者我们在 MetaMask 安全使用 · 8 个隐藏开关 里讲过签名解析怎么开;后者就是这篇要讲的检查与撤销。

第一步 · 怎么查出现有授权

你不可能凭记忆列出自己给过哪些授权 —— 玩了一两年的人列表往往长得吓人。好在授权是公开的链上数据,任何人都能查。常用三类工具:

区块浏览器的授权检查器

以太坊用 Etherscan,BNB Chain 用 BscScan,都内置了 Token Approval Checker(地址形如 etherscan.io/tokenapprovalchecker)。把地址粘进去,它会列出该地址发出的所有 ERC-20 / ERC-721 授权:被授权方(spender)是谁、额度多少、对应哪个代币,无限授权会被明确标成 Unlimited,一眼挑出来。

这是最权威的来源,数据直接来自链本身。缺点是按链分开 —— Etherscan 只看以太坊主网,你在 Arbitrum、Optimism、Base 上的授权得去对应浏览器查。每条链单独走一遍,别只查了主网就以为干净了。

revoke.cash 这类聚合工具

revoke.cash 是这个领域用得最多的第三方工具,把多条链的授权聚合到一个界面:连钱包或粘贴地址,它会跨链拉出你的全部授权,按额度和最后使用时间排序,无限额度、长期没动过的都会被标出来,还能直接在界面里发起撤销,不用跳回浏览器手动调合约。

说明

查授权是只读的:粘贴地址查询不需要连钱包、也不签任何东西,安全。只有真正撤销那步才需连钱包并签名付 gas。所以"先查、想清楚要撤哪些、再连钱包动手"更稳。访问这类工具务必手敲官方域名或用收藏夹,别从搜索广告或推特链接点进去 —— 仿冒站就靠这个钓人。

钱包内置的授权管理

现在不少钱包自己也带了授权管理面板。MetaMask 在 11.x 之后的版本里,可以在 token 详情或安全菜单里看到部分授权并直接撤销;一些移动钱包也在"设置 / 安全"里收了类似入口。内置工具胜在不用离开钱包,但覆盖的链和币种往往不如专门工具全。我自己的做法是日常用内置面板快速看一眼,定期大扫除时用浏览器 + revoke.cash 交叉核对。

第二步 · 怎么撤销

先记住一点:撤销也是一笔链上交易,要付 gas。它不是在网站上点一下就生效的设置,而是真往链上发交易、去改写代币合约里记录的授权额度。所以撤销前先确认钱包里有一点对应链的原生币(ETH、BNB 等)当矿工费。具体以 revoke.cash 为例,各工具流程大同小异:

  1. 连接钱包,并确认右上角显示的网络,是你要清理授权的那条链。要清几条链,就切几次网络分别处理。
  2. 在列表里挑出要撤的 spender。优先撤三类:额度是 Unlimited 的、最后使用时间很久远的、以及你压根认不出名字的合约。
  3. 点 Revoke,钱包会弹出一个交易请求。这一步会让你签名 —— 签之前看清楚它要做的事,正常撤销就是把额度改成 0,或把 setApprovalForAll 设回 false。
  4. 付 gas、等待确认。交易上链后,那份授权就失效了。

这里要分清两种授权的撤法。ERC-20 代币(USDT、USDC 这些)的授权是一个额度,撤销 = 把额度改成 0,你也可以不撤到 0、而是改成一个够用的小额度。ERC-721 / ERC-1155(NFT)常用的是 setApprovalForAll,它是一个开关,要么全开要么全关,撤销 = 把这个布尔值设回 false,没有"调小额度"这一说。

实测 · 示例

给一个用了三年多的主力地址做过一次彻底清理(以下为示例量级):跨四条链查出 40 多条授权,过半是无限额度,最久的一条来自两年前用过一次就再没碰的协议。逐个撤下来 gas 花了约十几美元,分两晚趁链上不忙时处理。

Permit 与 Permit2 的特殊性

上面讲的 approve 是链上授权,本身就是一笔交易、会留在交易历史里,所以查得到。但近几年流行的 Permit(EIP-2612)和 Uniswap 的 Permit2 是链下签名授权,这给排查带来了麻烦。

Permit 的设计初衷是省 gas:不用先发一笔 approve 交易,而是在链下签一个授权消息,把签名连同后续操作一起提交,授权和使用合并成一步。坏处是 —— 这个签名不一定在链上留下独立的 approve 记录,你翻交易历史可能根本看不到自己授权过什么。骗子正是利用这点,把恶意授权伪装成一次无害的签名。

Permit2 是 Uniswap 推的统一授权合约。逻辑是:你只对 Permit2 这一个合约做一次链上 approve(往往是无限额度),之后所有用到 Permit2 的应用都通过链下签名向它申请额度,由 Permit2 替它们动你的币。这把授权管理集中到一处,但也意味着 Permit2 合约本身就握着你币的大权限

排查 Permit2 的思路是:

  • 先查你对 Permit2 合约地址本身做过哪些 ERC-20 approve —— 这是链上记录,浏览器或 revoke.cash 都查得到。
  • 再查 Permit2 内部授权出去的额度:revoke.cash 这类工具已支持读取 Permit2 内部授权关系,能看到它又把额度转授给了哪些应用、额度多大、何时到期。
  • Permit2 的子授权可以带到期时间,但很多默认值仍给得很长。定期进去把不再用的子授权和过长有效期收掉。
注意

因为走链下签名,Permit / Permit2 弹窗里看到的常是一段结构化签名而非"转账交易",迷惑性更强。养成习惯:签名里出现 Permitspenderallowance 这类字眼,就停下来读清被授权方地址和额度,对不上预期就拒签。怎么让钱包把这些字段显示成人话,见 MetaMask 安全使用 讲签名解析那节。

最佳实践 · 把暴露面降到最低

查和撤是事后补救,真正省心的是从一开始就别把暴露面铺那么大。几条我自己一直守的规矩:

  • 用完即撤。用某个新协议或一次性 mint,交互完就把授权撤掉,等于交易完就把门关上。
  • 别给无限额度。approve 弹窗里能改额度就只给这次够用的数。多数主流钱包和 DApp 现在都支持自定义。
  • 定期审计。给自己定个节奏,比如每季度用 revoke.cash 跨链扫一遍,清掉无限的、久未用的、认不出的授权。
  • 大额资金用独立钱包,不连 DApp。这是最有效的物理隔离:主资产放一个从不连任何 DApp 的地址,日常交互用另一个只放小额的"前线"地址,前线被钓主资产也毫发无损。多地址分层可参考 钱包完整图谱
  • 看清楚再签。所有防御的最后一道都是签名前那三秒,读懂被授权方和额度,比任何工具都管用。

成本与几个常见误区

关于撤销,有几个误解值得说清楚,免得你白白慌张或白白放心。

误区一:撤销不要钱。不对,它是链上交易,要付 gas。所以没必要把每一条历史授权都撤掉 —— 优先撤无限额度的、不再用的、来路不明的;额度本就很小又是你信任的常用协议,可以留着,省下反复授权的 gas。

误区二:有授权 = 已经被盗。不对。授权只是"对方有可能动你的币",不等于币已被动。查出一堆无限授权别先吓自己,按风险高低排序、从最危险的开始撤即可。真正出事的前提是那份合约恶意或被攻破。

误区三:撤了就一劳永逸。不对。撤销只对这一次有效,下次再用同一协议它还会要你重新授权 —— 这很正常,按需给够用额度即可。撤销不是"拉黑",只是"收回这一次的钥匙"。

误区四:换了钱包 App,旧授权就没了。不对。授权绑定的是地址,不是你用哪个 App 打开它。只要旧地址里还有币,那些授权依然有效、依然是风险,得连进去撤;若旧地址已彻底清空且不再使用,可以不管,但更稳的是当它弃用、从此不往里转任何资产。

说回一个绕不开的角度:以上这套查、撤、审计的麻烦,本质上是自托管的代价 —— 你自己管私钥,也就得自己管授权。如果一部分资产你只想长期拿着、不打算频繁做链上交互,那放在像 Binance 这样的中心化交易所里,授权这件事压根不存在:平台替你托管,你不会因为签错一次授权而丢币(换来的是要信任平台本身)。自托管和托管各有取舍,按资产用途分开放更现实,这点在 冷钱包 vs 热钱包 里也展开讲过。

写在最后

代币授权是 DeFi 的底层管道,用得好让一切顺滑,疏忽了就成了钱包上一扇没关的门。这篇核心就三件事:知道授权是什么、定期查出自己给过哪些、把多余和危险的撤掉。再加一条贯穿始终的习惯 —— 签名前看清楚你正在授权什么。

今天就抽十分钟,用 revoke.cash 把常用地址扫一遍。大概率会查出几条你早忘了的无限授权 —— 撤掉它们,可能就挡掉了一次你永远不会知道的未来损失。

界面、工具更新很快,文中描述跟你看到的对不上,告诉我们 —— 会在 勘误页 记录。授权出事往往伴随签名被骗,建议把 MetaMask 安全使用 一起读了:那篇讲"签之前怎么看清",和这篇"签之后怎么收回"正好是一前一后两道防线。