---
title: allowance 误解与 ERC20 授权漏洞
date: '2018-05-24 13:39:34'
draft: false
summary: 很多智能合约漏洞不是源于复杂攻击技巧，而是开发者对一个看似基础的授权字段理解不完整，再叠加语言默认值和整数边界行为，最后把整个资产模型打穿。
slug: edu-allowance-underflow
syndication:
- platform: Weibo
  url: https://weibo.com/1648815335/4243232931889533
- platform: Weibo
  url: https://weibo.com/1648815335/Gi7JZ1321
tags:
- ethereum
- smart-contract
- erc20
- security
topics:
- blockchain
type: post
---

在慢雾区里看到 `EDU` 的一个智能合约漏洞，我的第一反应是：很多人抄智能合约时，可能根本没把 `allowance` 这个字段真正想明白。

`allowance` 的作用，本质上是允许用户授权第三方在一定额度内，从自己的账号里转账。它的设计目的，是为了让 `token` 能更自然地进入合约支付场景。

在 `ETH` 上实现这个机制，一般就是放一个嵌套 `map`，保存类似 “A 允许 B 从自己账户里转 10 块钱” 这样的授权关系。`approve` 方法就是干这个的。然后 `B` 就可以通过 `transferFrom` 来从 `A` 的账户里转账。

正常逻辑下，转账前当然应该先检查授权额度。但这个漏洞的问题在于：代码没有把这件事处理对，结果把授权额度一路减穿了。本来 `B` 最多只能扣 `10`，结果一下子就能把 `A` 账户里的余额全部拿走。

如果问题只停留在已有授权关系里，危害还没这么夸张。但 `ETH` 这类场景还有个默认规则：从 `map` 里取值时，如果这个键不存在，就会返回默认值，比如数字就是 `0`。

这就意味着，按这个逻辑，每个用户对其他任何用户，天然都“存在一个额度为 0 的授权”。而如果你的扣减逻辑又能把这个边界打穿，那问题就会从“授权检查有 bug”升级成“任何人都可能转走任意账户里的 token”。

严格说，`uint256` 不会真的变成负数，而是在减到 `0` 以后发生溢出。这里我沿用了当时解释这个漏洞时的直观说法，但本质问题就是：开发者把授权边界处理错了。

<!-- WEIBO_MEDIA_START -->
## 原微博中的媒体

![](./weibo-4243196630249985-1.jpg)

![](./weibo-4243196630249985-2.jpg)
<!-- WEIBO_MEDIA_END -->
