---
title: 为什么 ETH 上玩 DeFi 要先授权
date: '2022-03-06 07:00:10'
draft: false
summary: 从 ERC20 的历史包袱解释 approve 机制，以及新链为什么应该换一种方式。
slug: why-defi-needs-approve-on-eth
syndication:
- platform: Weibo
  url: https://weibo.com/1648815335/Jyy5k8rQO
- platform: X / Twitter
  url: https://x.com/jolestar/status/1500365607539478529
tags:
- defi
- ethereum
- token
topics:
- crypto
type: post
---

最近看到 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 还远没有走到终局，新的链和新的资产系统，完全应该趁还来得及时，把这类老问题在更底层就处理掉。
