Skip to content

Instantly share code, notes, and snippets.

@nathan-websculpt
Created September 17, 2021 14:31
Show Gist options
  • Select an option

  • Save nathan-websculpt/96f5afb0432a31ed259e912e74ef6aa7 to your computer and use it in GitHub Desktop.

Select an option

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
Copy Markdown
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