Skip to content

Instantly share code, notes, and snippets.

@nathan-websculpt
Created September 17, 2021 14:31
Show Gist options
  • Save nathan-websculpt/96f5afb0432a31ed259e912e74ef6aa7 to your computer and use it in GitHub Desktop.
Save nathan-websculpt/96f5afb0432a31ed259e912e74ef6aa7 to your computer and use it in GitHub Desktop.
The fix for ReentrancyAttackExample.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Attackee {
mapping(address => uint) public attackeeBalances;
function depositIntoAttackee() external payable {
attackeeBalances[msg.sender] += msg.value;
}
function withdrawFromAttackee() public {
uint senderBalance = attackeeBalances[msg.sender];
require(senderBalance > 0);
attackeeBalances[msg.sender] = 0;
(bool success, ) = address(msg.sender).call{ value: senderBalance }("");
require(success, "withdrawFromAttackee failed to send");
}
function getBalanceFromAttackee() public view returns (uint) {
return address(this).balance;
}
}
contract Attacker {
Attackee public contractToAttack;
constructor(address _contractToAttackAddress) {
contractToAttack = Attackee(_contractToAttackAddress);
}
//this is called when Attackee sends Ether to this contract (Attacker)
fallback() external payable {
//comment this out to allow the withdrawal
if(address(contractToAttack).balance >= 1 ether) {
contractToAttack.withdrawFromAttackee();
}
}
function depositIntoAttackee() public payable {
require(msg.value >= 1 ether);
contractToAttack.depositIntoAttackee{value: msg.value}();
}
function performAttack() public {
contractToAttack.withdrawFromAttackee();
}
function getBalanceFromAttacker() public view returns (uint) {
return address(this).balance;
}
}
@nathan-websculpt
Copy link
Author

Used as an example in This Blog Post

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment