Post
为什么 ETH 上玩 DeFi 要先授权
从 ERC20 的历史包袱解释 approve 机制,以及新链为什么应该换一种方式。
最近看到 Solana 上又有人因为授权钓鱼出事,我又想起一个老问题:为什么在 ETH 上玩 DeFi,用户总要先做一次 approve 授权?
这个问题表面上看像是钱包交互细节,实际上背后是 ERC20 和 EVM 资产模型留下来的历史包袱。它在 Ethereum 生态里已经很难彻底改掉,但对新链和新资产模型来说,应该尽量一开始就把这类问题处理掉。
根子在于,以太坊上的大多数 Token 采用的是合约内记账模式。用户以为自己的 Token 在自己地址里,实际上更准确的说法是:合约内部维护了一张账本,记录每个地址名下有多少余额。Alice 给 Bob 转 XToken 时,Bob 的钱包只是收到了合约事件,再去 Token 合约里查询自己的余额。
但当 Alice 想把 XToken 交给某个 DeFi 合约 Y 来处理时,问题就来了。Y 合约没法像接收原生 ETH 那样天然知道“这笔 Token 是 Alice 打给我的,并且我要按她的意图去执行什么逻辑”。于是 ERC20 采用了另一条路:先由 Alice 通过 approve 授权 Y,允许 Y 从自己的余额里划走一定数量的 Token,再由 Y 调用 transferFrom 完成扣款。
这套机制把合约之间的可组合性交出来了,但也顺手打开了一个很大的安全面。只要用户给了无限授权,恶意合约、被攻破的合约,或者后续逻辑变化过的合约,都可能继续动用这部分余额。很多 DeFi 用户为了省事和省 gas,会默认给出长期无限授权,这也是授权风险一直反复出现的根源。
ETH 本身没有这个问题,不是因为 ETH 更“高级”,而是因为它是原生资产。合约接收 ETH 时,链本身会把这次转账交到合约执行上下文里,合约天然能感知到这笔资产的到来,也不需要 approve 这一步。后来大家为了在合约里更方便地统一处理资产,又把 ETH 包了一层做成 WETH,便利性是上去了,但安全边界也退回到了 ERC20 这一套模型里。
所以如果想从根本上解决这个问题,我觉得至少有三条线值得认真想清楚。
第一,合约之间应该有什么样的资产交互机制。像 ERC223、ERC777 这类标准,早就试图通过回调或更强的接收语义去解决这个问题,但它们一直没形成足够广的兼容面。
第二,链上的资产模型是不是应该尽量统一。假如 Token 也更接近 first-class asset,而不是永远只是一张合约里的余额表,很多授权问题就不会以今天这种形式出现。
第三,智能合约到底是什么。它只是一个替用户操作资产的程序,还是一个有独立状态、独立边界的自动化实体?只要这个问题没想清楚,用户资产、程序状态和资产控制权之间的关系就会一直缠在一起。
所以我现在更倾向于把 approve 看成一种历史兼容方案,而不是理所当然的默认设计。DeFi 还远没有走到终局,新的链和新的资产系统,完全应该趁还来得及时,把这类老问题在更底层就处理掉。