代币授权(approve)的风险与撤销
见过最冤的一类损失,是这样的:私钥没泄露、助记词好好的、硬件钱包也插着,结果某个早就忘了的旧授权,被翻出来一刀把代币划走。受害者往往一脸懵——"我什么都没做啊"。问题就出在那个"什么都没做"上:当初点的那个授权,一直没关。这篇就讲清楚授权这件事,以及怎么把忘记关的口子一个个堵上。
approve 和 allowance 到底是什么
先把两个名词说清。在以太坊这类链上,大部分代币遵循一个叫 ERC-20 的标准。这套标准里有两个相关的东西:approve(授权)和 allowance(授权额度)。
道理其实很生活化。你的代币记在你的地址名下,别的合约默认动不了。但很多场景需要合约替你转币——比如你在某个去中心化交易所做兑换,得让它的合约把你的代币拿去和别人的换。为此你要先做一次 approve,告诉这个代币合约:"允许某某合约,最多动用我这种代币 X 个。"这个被允许的上限,就是 allowance。之后该合约在额度范围内转你的币,就不用每次再问你了。
所以授权本身不是坏事,是链上交互的必要机制。问题出在两个细节上:一是这个额度可以设成"无限",二是授权一旦给出去,不会自己过期——你不主动撤销,它就一直挂着。关于 ERC-20 授权机制的标准定义,可以参考以太坊官方的开发者文档(ethereum.org developers docs),它把 approve / transferFrom 这套流程讲得比较清楚;想从安全角度理解授权为何危险,以太坊的安全页也专门提醒过"留意你签下的每一笔授权"。
无限授权的隐患在哪
为什么很多 dApp 默认让你签"无限授权"?因为方便——授权一次,以后无论交互多少次都不用再签、不用再付那笔授权的 gas,体验顺。对正经项目来说,这通常没事。但隐患藏在两个假设里,而这两个假设并不总成立。
第一个假设是"这个合约是安全的、不会被攻破"。可合约也可能有漏洞,也可能被攻击者控制。一旦你授权的那个合约出了事,你给它的额度有多大,潜在损失就有多大。无限授权意味着:理论上它能把你钱包里这种代币全部划走,不只是你当时交互的那一点。
第二个假设是"我以后还会用它"。可你很可能只用了一次就再也没碰,但那个无限授权还静静地挂在那里,几个月、几年。时间越长,你越想不起来当初授权给了谁,风险却一直在累积。这就是为什么很多被盗发生在"我明明什么都没做"的时刻——动手的是一个早被遗忘的旧口子。
更稳的做法,是在钱包支持的情况下,把授权额度改成"够这次用就行"的具体数额,而不是无限。多签一点 gas、多点一下,换来的是风险被框在一笔交易的体量里。安全和便利在这儿要你自己掂量,但至少要知道默认那个"无限"意味着什么。
恶意合约怎么利用授权盗币
把骗局拆开看,你就明白为什么授权钓鱼这么阴。整个过程,你的私钥和助记词从头到尾都没泄露——是你亲手授权的,所以硬件钱包也拦不住。
- 第一步,做个诱饵。骗子搭一个假的空投领取页、假的 mint 页、假的"钱包升级/解锁"页,界面做得和正经项目几乎一样,域名差一两个字母,或者买广告排在前面。
- 第二步,引你连钱包、签授权。页面让你"连接钱包领取",然后弹出一个授权确认。很多人这时只看到"领取空投"几个字,没细看那笔授权要动的是什么、额度多大,就点了确认。
- 第三步,翻脸划币。授权一旦落到骗子的合约手里,它就在额度范围内(如果是无限授权,就是全部)把你的代币转走。你可能当场就被划空,也可能过段时间才被收割——反正口子开着,对方什么时候动手由它决定。
还有一种更隐蔽的变体,是诱导你签一个"离线授权"类的签名(比如 Permit 这类)。它不发起链上交易、不花你 gas,界面上看着像无害的"登录签名",但签下去等于授了权。所以"不花 gas 的签名"不等于"安全的签名",照样要看清内容。识别这些假页面、假入口的更多手法,看怎么识别假钱包与钓鱼;想从头理解链上交互的整体风险,看Web3 钱包是什么那篇的风险章节。
怎么定期检查和撤销授权
好消息是:授权是链上的公开记录,能查、能撤。把它当成定期体检,钱包就清爽很多。
查。有一些公开的授权查询工具,输入你的地址(注意:只输地址,地址是公开信息,绝不输入助记词或私钥),就能列出你这个地址给哪些合约授了哪种代币、额度多大。重点盯三类:额度是"无限"的、授权对象你已经记不起来的、很久没再交互过的。
撤。对那些不再需要的授权,发起一笔撤销交易(把额度改回 0),就把口子关上了。撤销本身是链上操作,要花一点 gas。别因为舍不得这点 gas 就放着——相比潜在损失,这点成本微不足道。
多久查一次。没有标准答案,但给个参考:高频玩 DeFi、经常连新 dApp 的人,建议每隔一段时间就清一轮;偶尔交互的人,至少在每次集中操作之后回头清一次。养成"交互完顺手撤掉不再用的授权"的习惯最省心。
想先快速摸清自己钱包里有没有明显的高风险授权,可以用我们的授权风险自查过一遍,它全程本地运行、不收集你的输入,只帮你把该警惕的点列出来。如果你担心自己容易被钓鱼套路带走,再做一次防钓鱼测验查查自己的薄弱环节。
签名前怎么看清授权对象
撤销是补救,看清是预防。每次钱包弹出确认框,别急着点,花十秒看这几样:
- 这是不是一笔授权?看交易类型。是 approve / 授权 / setApprovalForAll(NFT 的全量授权)这类,就要格外警惕。
- 授权给谁?看被授权的合约地址,确认它是你正在交互的那个正经项目,而不是一个陌生地址。
- 授权多大额度?如果显示的是无限、或一个大得离谱的数字,问自己这次交互真需要这么多吗。能改额度就改成够用就行。
- 动的是哪种代币?确认它要动的代币和你预期一致。
- 这个站可信吗?核对域名,是不是从官方入口进来的。不确定就取消,没有哪笔交互是"错过就没了"非签不可的——那种紧迫感本身常常就是钓鱼的话术。
NFT 这边还有个专门要小心的:setApprovalForAll 是把你某个系列下的全部 NFT 的转移权一次性授出去,一旦授给恶意合约,整个系列都可能被搬空。看到这类授权,更要确认对象是不是你真的信任的市场或合约。地址本身的大小写校验和机制(EIP-55)能帮你识别一部分手误地址,但它防不了你授权给错的合约——看清对象这一步无可替代。
把防授权这几条变成习惯
说到底,授权风险防的不是某个高深的技术攻击,而是"图省事"和"忘了关"这两个人之常情。把下面这几条变成肌肉记忆,你就堵住了链上一大类损失:
- 能设具体额度就别签无限授权。
- 每次交互完,顺手撤掉不再需要的授权。
- 每隔一段时间,集中清一轮旧授权。
- 签名前看清:是不是授权、授给谁、多大额度、哪种代币。
- "不花 gas 的签名"也可能是授权,照样看清。
- 查授权只输地址,永远不输助记词和私钥。
授权只是自托管安全里的一环。它和助记词保管、防钓鱼、地址核对是连在一起的——任何一环松了,其他环节做得再好也可能前功尽弃。想把这几件事串成一套完整的防线,去读自托管完全指南。