什么是代币授权
在以太坊这类链上,USDT、USDC 这些代币各自是一份独立合约在记账。当你想在 Uniswap 这样的 DEX 上拿 USDT 换 ETH,麻烦来了 —— Uniswap 的合约并不能直接从你账上扣 USDT,它没有这个权限。
于是 ERC-20 标准设计了两步动作:你先调用代币合约的 approve(spender, amount),告诉这份 USDT 合约"我允许 Uniswap 这个地址,从我账上最多动用这么多 USDT";之后 Uniswap 执行兑换时,再调用 transferFrom 把币划走。第一步是"授权",第二步才是"花钱"。
DEX 兑换、借贷协议存款、跨链桥转币,背后几乎都有一次 approve。要留意的是两点:授权的额度和有效期。
无限授权为什么危险
DApp 弹出 approve 请求时,提出的额度常常不是这次要换的那点钱,而是无限。ethereum.org 的 撤销授权指南 解释过原因:项目方这样做是为了让你以后每次交易不用再签一次 approve。代价是你把这个币种的全部余额、以及未来转进来的余额,都交给了对方合约支配,哪怕你已经把资金从那个平台取走。
再看有效期。同一份指南写明,代币授权不会过期。假设你三年前为换一次币给过某协议无限授权,今天它还在生效。哪天那份合约被攻破,或者它本来就是钓鱼合约,攻击者只要调一次 transferFrom,你那个币种的余额就没了。不需要你的私钥,也不需要你再签任何东西。
授权被利用和私钥泄露是两回事。私钥泄露是整个地址失守;授权被利用,损失的是被授权的那个币种、那个额度以内的部分。两者的处置也不同:授权出问题靠撤销,私钥或助记词泄露了撤销没有用,见 私钥或助记词泄露了怎么办。
没泄露助记词也丢币:骗的是哪几种授权
有一类钱包骗局要的不是私钥,而是让你亲手签下一笔授权,或者一份效果等同于授权的签名。没把助记词告诉过任何人却丢了币,先往这个方向查。下面四种签名都能被这样利用:
- setApprovalForAll:NFT 的全部授权开关,签下去等于把这个合约下你所有的 NFT 交给对方处置。
- Permit(EIP-2612)签名:页面看起来在做一次普通兑换,实际让你签的是一份链下授权。
- NFT 市场的批量挂单签名:MetaMask 帮助中心的 Signature phishing 一页举过仿冒 Blur 挂单流程的例子,签下去的消息可以让对方取走账户里的全部 NFT。
- Permit2 签名:同一页也点了名,下文单独讲。
这几种的共同点是:签名那一刻,弹窗里要么是看不懂的结构化数据,要么被包装成正常操作。防它们靠两件事:签之前看清自己在授权什么,签之后把多余的授权清掉。前一件见 MetaMask 安全设置怎么调 和 钓鱼诈骗图鉴,后一件就是下面的检查与撤销。
怎么查自己给过哪些授权
授权是公开的链上数据,用地址就能查,不用凭记忆。ethereum.org 的指南列的工具有 Etherscan、Blockscout、Revoke.cash、Unrekt、EverRevoke。下面写其中两个,再加 MetaMask 自带的入口。
Etherscan 的 Token Approval Checker
入口是 etherscan.io/tokenapprovalchecker,也可以从 Etherscan 顶部 More 菜单里的 Token Approvals 进去。输入钱包地址,选代币类型(ERC20、ERC721、ERC1155),打开 Show all approvals,就能看到这个地址在以太坊主网上给出去的授权。这几步出自 Revoke.cash 的 撤销教程,它把 Etherscan 的做法也一并写了。
区块浏览器是按链分开的。Etherscan 只看以太坊主网,BNB Chain 上的授权要去 BscScan 的同名页面,Polygon 去 Polygonscan。用过几条链,就查几条链。
Revoke.cash
Revoke.cash 把多条链做在一个界面里。按它自己的教程:在搜索栏输入钱包地址或 ENS 名(也可以连接钱包),选好网络,授权列表加载出来后可以排序、筛选,或者按被授权方(spender)的地址搜索。怀疑最近签过恶意授权时,它建议按从新到旧排序,最新的排在最前面。
查授权只需要输入地址,不必连接钱包,也不用签任何东西。真正撤销那一步才要连钱包、签名、付 gas。建议先查清楚、想好要撤哪些,再连钱包动手。打开这类工具时自己输入域名或用收藏夹,不要从搜索广告、社交平台的帖子或私信里的链接点进去,仿冒的撤销工具就是这样把人引过去的。
MetaMask Portfolio 的 spending caps 页
用 MetaMask 的话,官方的 撤销授权说明 里写了一个自带入口:MetaMask Portfolio 的 spending caps 页,可以查看授权并直接发起撤销,支持以太坊主网、Polygon 和 BNB Chain。它覆盖的链比 Revoke.cash 少。建议平时用它看一眼,做彻底清理时再用区块浏览器和 Revoke.cash 各查一遍,互相对照。
怎么撤销授权
先记住一点:撤销也是一笔链上交易,要付 gas。它是往链上发一笔交易,去改写代币合约里记录的授权额度,不是在网站上点一下就生效的设置。所以撤销前先确认钱包里有一点对应链的原生币(ETH、BNB 等)付网络费。下面四步对照 ethereum.org 的 撤销授权指南,各工具的流程差不多:
- 连接钱包,钱包和工具选同一条链。工具只会列出当前所选网络上的授权。要清几条链,就切几次网络分别处理。
- 在列表里挑出要撤的。优先撤三类:无限额度的、早就不用的、认不出是谁的合约。ethereum.org 的说法是全部撤掉也没有坏处,只是下次再用那个合约时要重新授权。
- 点 Revoke,在钱包里确认。钱包会弹出一个交易请求,签之前看清它要做的事:正常的撤销是把额度改成 0,或把 setApprovalForAll 设回 false。
- 付网络费,等确认,再刷新。按 ethereum.org 的说法,视网络情况要等一分钟到几分钟。交易确认后刷新工具页面,确认那条授权已经不在列表里。
两种授权的撤法不一样。ERC-20 代币(USDT、USDC 这些)的授权是一个额度,撤销就是把额度改成 0;也可以不撤到 0,改成一个够用的小数,Revoke.cash 里点授权旁边的铅笔图标就能改。NFT(ERC-721、ERC-1155)常用的 setApprovalForAll 是一个开关,只有全开和全关,撤销就是把它设回 false,没有调小额度这一说。
撤完怎么确认撤干净了
撤完一轮,再做四件事:
- 换一个工具复查。用 Revoke.cash 撤的,再到对应链的区块浏览器 Token Approval Checker 里看一遍,反过来也一样。两边都查不到,才算这条链清完。
- 每条用过的链都查。同一个地址在以太坊、Arbitrum、BNB Chain、Polygon 上的授权各记各的,主网清了不代表别的链也清了。
- Permit2 的两层都看。对 Permit2 合约的那条授权,和 Permit2 里面再给出去的额度,是两处,见下一节。
- 回头核对自己签过的每一笔。在区块浏览器里打开刚才那几笔交易,确认调用的是
approve且额度为 0,或setApprovalForAll且参数为 false。
有一种骗法专门冒充撤销工具:帖子或私信告诉你收到了可疑空投、必须马上去某个网站撤销授权。几个识别点:网址不是你自己输入的官方域名;页面把一长串授权全部标红,催你立刻处理;钱包弹窗里要你签的是 setApprovalForAll 且参数为 true、额度是 unlimited,或者是一份 Permit 签名。这些都是在给出新授权,不是撤销,一律拒绝。另外,别人空投给你的陌生代币,你没给它授权过,也就没有什么可撤的,放着不动就行。
Permit 签名和 Permit2 额度怎么排查
上面讲的 approve 是链上授权,本身就是一笔交易,会留在交易历史里,所以查得到。Permit(EIP-2612)和 Uniswap 的 Permit2 用到的是链下签名,排查方式不一样。
签过可疑的 Permit 签名,还能作废吗
Permit 让你不用先发一笔 approve 交易,而是在链下签一条授权消息。按 Revoke.cash 的 Permit 签名说明,这条签名要等拿到它的一方提交上链,授权才被激活;在那之前,你翻交易历史和授权列表都看不到它。骗局利用的就是这一点。
同一页给了两个阶段的处置:
- 还没被激活时:有可能抢先把签名作废,入口在 Revoke.cash 账户页的 Signatures 标签。它也写明这通常很难做到,因为骗子往往会尽快激活。
- 已经被激活后:它就是一条普通授权,会出现在授权列表里,照常撤销。
所以怀疑签错了 Permit,两件事一起做:马上去 Signatures 标签和授权列表里处理,同时把这个地址里对应的代币转到另一个没签过这份签名的地址。MetaMask 的 Signature phishing 一页给的也是这两条:撤销,并把有风险的代币转走。即使发现时币已经被转走,Revoke.cash 也建议照样撤掉那条授权,因为它以后还能被再用一次。
Permit2 有两层授权
Permit2 是 Uniswap 团队做的授权合约。按 Revoke.cash 的 Permit2 说明,它分两层:
- 第一层:你给 Permit2 合约本身一次无限额度的链上 approve。这是普通的链上授权,区块浏览器和 Revoke.cash 都查得到。Revoke.cash 的建议是不再用时把它撤掉。
- 第二层:Permit2 再把额度分给具体的应用。这一层的授权都带到期时间,到期自动失效。到期时间设得太远的,可以在 Revoke.cash 里手动撤销或修改。
排查时两层都要看:先看有没有给 Permit2 合约的授权、还用不用得上;再看 Permit2 里面分出去的额度,把认不出的、到期时间很远的撤掉。
Permit 和 Permit2 的弹窗里是一段结构化签名,看上去不像转账。签名内容里出现 Permit、spender、allowance 这类字眼时,先读清被授权方的地址、额度和到期时间,对不上预期就拒签。MetaMask 确认页会给哪些提示,见 MetaMask 安全设置怎么调。
平时怎么少留授权
查和撤是事后补救。平时少留授权,事后要清的就少。几条建议:
- 用完就撤。用某个新协议或一次性 mint,交互完就把授权撤掉。
- 别给无限额度。授权确认页里能改额度,就只给这次够用的数。MetaMask 里怎么改,见 授权弹窗里的无限额度怎么改小。
- 定期检查。MetaMask 帮助中心举的例子是每月一次;链上交互少的地址可以拉长。每次把无限的、久未用的、认不出的清掉。
- 大额资金放在不连 DApp 的地址。主要资产放一个从不连任何 DApp 的地址,日常交互用另一个只放小额的地址。小额地址签错了授权,主要资产不受影响。钱包怎么分类,见 钱包有哪几类。
- 看清楚再签。签名前读清被授权方和额度,这一步工具替不了你。
撤销授权要花钱吗?几个常见误解
撤销不要钱?要。它是链上交易,要付 gas。所以不必把每一条历史授权都撤掉:优先撤无限额度的、不再用的、来路不明的;额度本来就小、又是你一直在用的协议,可以留着,省下反复授权的 gas。
有授权就是已经被盗?不是。授权只是对方有可能动你的币,不等于币已经被动。查出一堆无限授权时,按风险高低排个序,从最危险的开始撤。出事的前提是那份合约有恶意或被攻破。
撤了就一劳永逸?不是。撤的是这一条授权,下次再用同一个协议,它还会要你重新授权。这很正常,按需给够用的额度就行。
换了钱包 App,旧授权就没了?没有。授权记在地址上,和你用哪个 App 打开这个地址无关。授权一直有效,这个地址以后进来的币同样受它管,要连进去撤。
在网站上断开钱包连接,等于撤销?不等于。ethereum.org 的指南和 MetaMask 帮助中心都写明,断开连接不会移除代币授权,只有撤销才会。
撤销会影响我在协议里的质押或借贷吗?ethereum.org 的指南答的是不会:撤销授权不会结束你的质押、流动性或借贷仓位,收益照常。
最后分清一件事:如果丢币的原因是助记词或私钥本身泄露,撤销授权没有用,处置顺序见 私钥或助记词泄露了怎么办。