How Does Reentrancy Attack Work?
Below is an example to explain the working of a reentrancy attack:
- An attacker finds a smart contract that allows users to deposit funds and withdraw them at a later time.
- The attacker creates a malicious contract Contract B that repeatedly calls the deposit function of the vulnerable contract Contract A, depositing funds into the attacker’s own account.
- The attacker then calls the withdraw function of the vulnerable contract, withdrawing the deposited funds.
- Because the deposit function of the vulnerable contract is not properly protected against reentrancy, the attacker is able to repeatedly call the deposit function before calling the withdraw function, effectively stealing funds from the contract.
- The attacker continues to repeat the attack until they have stolen as many funds as they desire.
Below is an example of a simple smart contract that is vulnerable to reentrancy attacks:
Solidity
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.22 <0.9.0; /// @title A contract for demonstrate payable functions and addresses /// @author Jitendra Kumar /// @notice For now, this contract just show how payable functions and addresses can receive ether into the contract contract Reentrancy { mapping(address => uint) public balance; function deposit() public payable { balance[msg.sender] += msg.value; } function withdraw() public payable { require(balance[msg.sender] >= msg.value); payable(msg.sender).transfer(msg.value); balance[msg.sender] -= msg.value; } } |
Explanation: In this contract, the deposit function allows users to deposit funds into their account and the withdraw function allows users to withdraw their deposited funds. However, the contract does not properly check for reentrancy, so an attacker could create a malicious contract that repeatedly calls the deposit function before calling the withdraw function, effectively stealing funds from the contract.
Below is an example of how the contract can be modified to prevent reentrancy attacks:
Solidity
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.22 <0.9.0; /// @title A contract for demonstrate Reentrancy Attack /// @author Jitendra Kumar /// @notice For now, this contract just show how to protect Smart Contracts against a Reentrancy Attack contract Reentrancy { mapping(address => uint) public balance; bool public reentrancyLock; function deposit() public payable { require(!reentrancyLock); reentrancyLock = true ; balance[msg.sender] += msg.value; reentrancyLock = false ; } function withdraw() public payable{ require(balance[msg.sender] >= msg.value); payable(msg.sender).transfer(msg.value); balance[msg.sender] -= msg.value; } } |
Explanation: In this example, a reentrancyLock variable is added to the contract. The deposit function now checks if the reentrancyLock variable is true before allowing the deposit to occur. If the variable is true, the deposit will not occur and the attacker will not be able to steal funds. The reentrancyLock variable is set to true before the deposit and set back to false after, this way the contract can only be called once at a time.
It’s important to note that this is a simplified example and in real-world scenarios, contracts should be audited by experts and tested extensively to ensure they are secure.
Reentrancy Attack in Smart Contracts
Reentrancy attack in solidity repeatedly withdraws funds from the smart contract and transfers them. The article focuses on discussing Reentrancy Attacks in Smart Contracts. It occurs when a function makes an external call to another untrusted contract. The article focuses on discussing reentrancy attacks in smart contracts.
The following topics will be discussed here:
- What is a Reentrancy Attack?
- Example of Reentrancy Attack
- How Does Reentrancy Attack Work?
- Types of Reentrancy Attack
- Reentrancy Smart Contract Attack Examples
- Is the Reentrancy Attack Still a Significant Problem?
- How to Protect Smart Contracts Against a Reentrancy Attack?
Let’s start discussing each of these topics in detail.