-
Notifications
You must be signed in to change notification settings - Fork 0
/
Reentrancy.sol
77 lines (59 loc) · 1.79 KB
/
Reentrancy.sol
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
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.10;
/*
Reentrancy
- What is reentrancy?
- Remix code and demo
- Preventative techniques
*/
contract EtherStore {
mapping(address => uint256) public balances;
bool internal locked;
modifier noReentrant() {
require(!locked, "No re-entrancy");
locked = true;
_;
locked = false;
}
function deposit() public payable {
balances[msg.sender] += msg.value;
}
function withdraw(uint256 _amount) public noReentrant {
// DANGEROUS CODE
// require(balances[msg.sender] >= _amount);
// (bool sent, ) = msg.sender.call{value: _amount}("");
// require(sent, "Failed to send Ether");
// balances[msg.sender] -= _amount;
// PREVENTION CODE
require(balances[msg.sender] >= _amount);
balances[msg.sender] -= _amount;
(bool sent, ) = msg.sender.call{value: _amount}("");
require(sent, "Failed to send Ether");
}
function getBalance() public view returns (uint) {
return address(this).balance;
}
}
contract Attack {
EtherStore public etherStore;
constructor(address _etherStoreAddress) public {
etherStore = EtherStore(_etherStoreAddress);
}
fallback() external payable {
if (address(etherStore).balance >= 1 ether) {
etherStore.withdraw(1 ether);
}
}
function attack() external payable {
require(msg.value >= 1 ether);
// // 0.5
// etherStore.deposit.value(1 ether)();
// // 0.6
// etherStore.deposit{value: 1 ether}();
etherStore.deposit{value: 1 ether}();
etherStore.withdraw(1 ether);
}
function getBalance() public view returns (uint) {
return address(this).balance;
}
}