-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathReentrantSafe.sol
More file actions
59 lines (47 loc) · 1.66 KB
/
Copy pathReentrantSafe.sol
File metadata and controls
59 lines (47 loc) · 1.66 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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
contract MoneySafe {
mapping(address => uint) public userBalances;
bool internal re_lock;
function getBalance() public view returns (uint) {
return address(this).balance;
}
function getUserBalance() public view returns (uint) {
return userBalances[msg.sender];
}
function deposit() public payable {
userBalances[msg.sender] = userBalances[msg.sender] + msg.value;
}
modifier nonReentrant() {
require(!re_lock, "Reentrancy detected.");
re_lock = true;
_;
re_lock = false;
}
function withdrawBalance() public nonReentrant {
// Withdraw the whole balance of user
uint amountToWithdraw = userBalances[msg.sender];
userBalances[msg.sender] = 0;
(bool successfulWithdraw, ) = msg.sender.call{value:amountToWithdraw}("");
require(successfulWithdraw, "Failed to withdraw ether");
}
}
contract ReentrancyAttack {
MoneySafe public safe;
constructor(address _safeAddress) {
safe = MoneySafe(_safeAddress);
}
function getBalance() public view returns (uint) {
return address(this).balance;
}
fallback() external payable {
if (address(safe).balance >= 1 ether) {
safe.withdrawBalance();
}
}
function exploit() external payable {
require(msg.value >= 1 ether); // Send atleast 1 ETH to the attack contract
safe.deposit{value: 1 ether}(); // Deposit it in the MoneySafe
safe.withdrawBalance(); // Withdraw it back from the MoneySafe
}
}