项目方换到新合约,你打开迁移页面,一枚代币都还没动,钱包就先让你给旧代币授权。这个弹窗看上去像是谁多加的一步。它不是。在 ERC-20 里,把余额交到你自己以外的任何对象手上,只有这一条路径;能不能读懂它,是一次迁移与一个被掏空的钱包之间的分界。
这份授权到底给出了什么
授权是往旧代币合约内部的一张账上写一个数。它针对一对地址记录一件事:某个具名的支出方可以从你的账户里转走多少这种代币。签下它不转移任何东西,不向项目方发送任何东西,也不构成任何兑换承诺。
在 ERC-20 代币标准里,这张账通过两个函数访问。`approve` 允许支出方从你的账户里反复提取,直至一个设定的额度;`transferFrom` 才是真正把代币从一个地址移到另一个地址的调用。标准把这一对呈现为一套提取流程,让合约代表你转移代币,而迁移合约只是这类合约中的一个,没有任何特殊地位。
这条记录存在哪里,比听上去更要紧。额度记在旧代币里,不在迁移合约里,所以它比迁移页面、比这次兑换、也比项目本身活得久。关掉标签页不会清掉它。
兑换合约为什么必须问
兑换必须先接管旧单位,才能给你记上新单位。合约无法自行伸手进你的账户,而关于你的余额,代币合约只听持有它的那个账户。
看起来的替代做法,是你自己用一次普通转账把旧代币发给合约。那确实转移了代币,也确实会失败:普通转账到账时不带任何调用,合约根本不知道这笔转账发生过,也就没有可以据以入账的东西。ERC-223 标准正是围绕这个失败写的。改用 `transferFrom` 拉取,合约就有了一次调用:在这一次调用里收下旧单位、付出新单位,而这次调用需要先有额度。
两笔交易,只有第二笔在兑换
授权与兑换是两笔独立的交易,各付各的 gas。ERC-2612 把这个形状讲得很直白:用户要与智能合约交互,就得发 2 笔交易,`approve` 与那次内部会调用 `transferFrom` 的合约调用。
正因为彼此独立,第一笔可以成功而第二笔照样失败。已经关闭的兑换窗口、已经被清空的兑付储备、被暂停的合约,这些授权一概看不见,它只写一个数然后返回。授权确认了,不等于它背后的迁移能跑通。
反向的坑在下一步。一次预演通过的兑换上链后照样可能回滚,预演回答的是某一刻的状态,而不是你的交易真正落进去的那一刻。兑换回滚时,你给出的额度分毫未动,仍然挂在那里。
有些迁移根本没有理由问
不是每种迁移都跑在额度上。你被告知的形态,应当与你收到的弹窗对得上。
| 迁移怎么跑 | 你要发出什么 | 这里该不该出现授权 |
|---|---|---|
| 兑换合约拉取你的旧单位 | 一次授权,再加一次兑换调用 | 该 |
| 你把旧代币转到公布的地址 | 一次普通转账 | 不该 |
| 按快照给在册持有人记账 | 什么都不发 | 不该 |
| 平台转换它自己的池内余额 | 什么都不发 | 不该 |
该让你停下的是第三行。宣布为自动发放的分发,没有任何环节需要你的额度,所以一个索要额度的页面,要的是这套迁移用不上的东西。注意到这处不匹配不花任何成本,也不依赖任何人对这个站点的判断。
弹窗里决定一切的三个字段
不管钱包怎么称呼,每个授权弹窗都带着同样三个字段。
| 字段 | 它授出什么 | 拿什么核对 |
|---|---|---|
| 代币 | 这条记录写进哪个合约的账 | 项目方自己公告里的旧合约地址 |
| 支出方 | 哪个地址可以从你账户里拉取 | 同一份公告里的迁移合约地址 |
| 数量 | 那个地址最多能拿走多少 | 你这一次打算兑换的份额 |
地址要整串比对。仿冒地址可以和真地址共享开头与结尾的若干字符,差异恰恰落在中间。
支出方这个字段承担着损失,这也是钱包抽干器不需要攻破任何东西的原因。它把自己的地址填进这个字段,让你签下一份有效且格式正确的授权。交易完全按写下的样子成功,余额稍后才离开,时点由攻击者定,不由你定。
当它要的是签名而不是交易
额度不总是以交易的形式到来。ERC-2612 在 ERC-20 标准上扩展出一个 `permit` 函数,允许用户用一条签名消息修改 allowance 映射,而不必经由 `msg.sender`;一条有效的 permit 会把该支出方的额度设为所述数值,把 nonce 加一,并发出一个授权事件。
由此而来的后果是:一个只让你签一条消息、没有 gas、没有待确认交易的界面,能授出的东西与一笔授权交易完全一致。它在你签下的那一刻也不会在你自己的交易记录里留下任何东西,因为这条签名消息是由别人提交的。
所以对签名请求要读同样三个字段。permit 里写着支出方与它要设定的数值,还有一个 deadline,规范要求当前区块时间不得晚于它。如果页面把这次签名说成登录或确认,而结构化数据里写着支出方与数量,那么会被执行的是结构化数据。
精确额度还是无限额度,以及留下的那条记录
举个例子。一个钱包持有 10,000 个旧单位,项目方已经开放兑换。先授权 2,500、兑换这一份、再拿到手的数量与公告比例核对一遍,就把这次迁移变成了你观察过的事,而不是你假定的事。剩下的 7,500 随后需要第二次授权,代价是多付一次 gas,这就是这套做法的全部成本。
无限授权省掉了第二次付费,换来的是对这种代币的长期许可,只要那条记录还在就一直有效。迁移合约保有拉取此后进入你账户的任何旧单位的权利,包括你多年后从一个旧钱包里找回的旧代币余额。
收尾要把剩下的清掉。精确额度会被它所服务的那次兑换消耗掉,超出的部分则留下一条活着的记录,而一份已经失去用途的代币授权,是一项没人再盯着的权限。把额度设回零本身也是一笔交易,同样要付 gas,所以在迁移结束之后专门去做这一步。
小结
迁移之所以索要授权,是因为 ERC-20 没有给它第二条拿走旧代币的路。授权本身是写进旧代币合约的一个数,指名一个地址和一个上限:它不转移任何东西,不证明它背后的迁移可用,也不会因为你关掉页面而失效。
于是整件事收敛成三项核对。这种迁移形态到底需不需要额度,支出方是不是项目方公布的那个地址,数量是不是你打算兑换的那一份。签名请求同样要过这三项;而一份已授出的额度比它周围的一切都活得久,所以兑换结束就把它清掉。想系统学习更多加密基础知识,可以关注 Bitbase(币贝)学院的后续内容。
相关阅读
币贝上与本主题相关的其他文章:
- 如何撤回治理委托
- 代币供应机制
- 布林带详解
风险披露:本文为 Bitbase(币贝)学院的科普内容,仅供教育与信息参考,不构成任何投资、交易、税务或财务建议。加密资产波动剧烈,请自行评估风险。本文撰写于 2026 年 9 月,请以官方最新信息为准。
参考资料
[1] 以太坊改进提案,ERC-20: Token Standard,approve 与 transferFrom 方法(状态:Final) eips.ethereum.org
[2] 以太坊改进提案,ERC-2612: Permit Extension for EIP-20 Signed Approvals,Abstract 与 Specification(状态:Final) eips.ethereum.org
[3] 以太坊改进提案,ERC-223: Token with transaction handling model,Motivation 一节(状态:Final) eips.ethereum.org






