# Tutorial
# What is Reentrancy Attack?
Reentrancy can occur when a program or contract makes a call to another program or contract and then continues to execute. Let’s understand it with a simple example.
Imagine you have an online bank account and you want to transfer money to your friend’s account. Your account has $100 and your friend’s account has $0. Your account has a function which can be called to transfer money to other accounts. Once you transfer the money, the function updates the balance in your account and your friend’s account.
Now, imagine a hacker found a vulnerability in the code of the function that allows the hacker to call the function multiple times before the balance is updated. So, when you transfer $10 to your friend’s account, the hacker can call the function multiple times, each time taking $10 from your account.
So, even though you transferred $10, the hacker can take $100 from your account by repeatedly calling the function before the balance is updated. This is a reentrancy attack, where the hacker repeatedly calls the transfer function, draining all of the account’s resources.
To demonstrate this attack, we have a MonsterBank contract and your task is to drain the balance from this contract.
HINT: Start with the withdrawAll function 😃
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
contract MonsterBank {
mapping (address => uint256) private balance;
address public owner;
constructor(address player_) payable {
balance[address(this)] = msg.value;
owner = player_;
}
function completed() external view returns (bool) {
return getBalance() == 0;
}
function deposit() external payable {
balance[msg.sender] += msg.value;
}
function withdrawAll() external {
uint256 current_balance = getUserBalance(msg.sender);
require(current_balance > 0, "Insufficient balance");
(bool success, ) = msg.sender.call{value: current_balance}("");
require(success, "Failed to send Ether");
balance[msg.sender] = 0;
}
function getBalance() public view returns (uint256) {
return address(this).balance;
}
function getUserBalance(address _user) public view returns (uint256) {
return balance[_user];
}
receive() external payable {}
fallback() external payable {}
}