Blog

Category:Developers
How to Detect Reentrancy Attacks Using ZIION Tools
profile
Ziion
05.25.2023

In this blog, we will take a closer look at reentrancy attacks, their impact on some well-known blockchain protocols, and the tools and techniques to discover and mitigate them.

Introduction to Reentrancy Attacks

Reentrancy attacks are prevalent and dangerous vulnerabilities in smart contracts, particularly those built on the Ethereum blockchain. In a reentrancy attack, an attacker exploits a contract by repeatedly calling a function before the first call has finished executing. This allows the attacker to potentially withdraw more funds than intended or manipulate the contract's state in unintended ways.

These attacks occur due to the nature of smart contracts and the way they interact with the different blockchains. The attacker takes advantage of poor coding practices, such as the contract making external calls before updating its state, and exploits the inherent trust that contracts have in each other.

Well-known Protocols That Fell Victim to Reentrancy Attacks

Reentrancy attacks have impacted several high-profile protocols and projects in the blockchain ecosystem. Some notable examples include:

The Sentiment Attack

On April 4th, 2023, the Sentiment Protocol on the Arbitrum Chain faced an attack due to a read-only reentrancy vulnerability. The main issue was a view-only reentrancy bug in balancer pools that surfaced when taking out liquidity, and one of the returned tokens was ETH. Because the entry point involved a non-changing view call, it couldn't be secured by a reentrancy guard, enabling the attacker to control the execution and run harmful code. The attacker managed to use a harmful contract before updating pool balances, which allowed them to steal about $1 million by employing overpriced collateral. Fortunately, the attacker returned nearly 90% of the stolen funds.

The Dynamic Finance Hack

On February 22, 2023, Dynamic Finance, a smart money market aggregator built on multiple blockchain networks, suffered a loss of 73 BNB due to insufficient reentrancy protection. The attack involved exploiting a reentrancy bug in the StakingDYNA contract's deposit tracking system. In the aftermath, the price of the $DYNA token dropped by over 90%, and the team announced plans to upgrade the contract with a reentrancy guard, audit the protocol, buy back tokens, and distribute them to affected users. 

How to Detect Reentrancy Attacks in a Smart Contract Using ZIION Tools

To discover reentrancy attacks in smart contracts, several tools can be used to analyze the code and identify vulnerabilities. Tools can be used in conjunction with manual code reviews, testing, and best practices to effectively discover reentrancy attacks in your smart contracts. 

But before using tools, you need to install them and configure them manually which can take a good amount of your time. To avoid wasting time, you can use ZIION, which comes prepared with 100+ tools like Slither. To install ZIION, follow the instructions in this article and start your journey with blockchain development and security auditing.

While more advanced reentrancy attacks require careful manual code review, which takes time and expertise to learn, let’s look at a simple Solidity example using some automated tools pre-installed in ZIION.

Slither is an open-source static analysis framework for smart contracts written in Solidity. It can identify various vulnerabilities, including reentrancy attacks, and provides recommendations to fix them.

For the demonstration, we will be using a simple smart contract which is vulnerable to a reentrancy attack:

pragma solidity ^0.8.0;

contract VulnerableBank {

    mapping(address => uint256) public balances;

    function deposit() external payable {

        require(msg.value > 0, "Must deposit a positive amount");

        balances[msg.sender] += msg.value;

    }

    function withdraw() external {

        uint256 amountToWithdraw = balances[msg.sender];

        require(amountToWithdraw > 0, "Insufficient balance");

        // Vulnerable external call without updating the state first

        (bool success, ) = msg.sender.call{value: amountToWithdraw}("");

        require(success, "Withdrawal failed");

        // State update after the external call

        balances[msg.sender] = 0;

    }

}


Here’s the step-by-step guide to using Slither to detect a reentrancy attack:

Step 1: Analyzing your smart contract

Navigate to the directory containing your smart contract's .sol files. Run the following command to analyze your contract using Slither:

Slither run example

Replace “smart_contract.sol” with the name of the smart contract that you want to scan.

Step 2: Reviewing the analysis

Slither will analyze the smart contract and provide a report on detected issues, including reentrancy vulnerabilities. It will indicate the specific function(s) and line numbers where the vulnerabilities were found.

For example, you might see a report similar to this:

Slither output with issue detected

Step 3: Investigate the reported vulnerabilities

Examine the reported vulnerabilities in your smart contract code. Investigate the external calls and state variables involved in the reported reentrancy issue. Understand the control flow of your contract and determine if the reported issue is a genuine vulnerability or a false positive.

Step 4: Apply fixes

If you confirm that the reported issue is a genuine vulnerability, apply appropriate fixes to your smart contract code. To remediate reentrancy attacks in smart contracts, developers should employ security practices such as implementing reentrancy guards (mutex), following the Checks-Effects-Interactions pattern, updating contract states before external calls, using the "pull" method for payouts, avoiding low-level functions, leveraging Solidity's built-in modifiers like 'nonReentrant', conducting thorough security audits, and utilizing formal verification tools. 


Here’s the fixed code:

pragma solidity ^0.8.0;

contract SecureBank {

    mapping(address => uint256) public balances;

    function deposit() external payable {

        require(msg.value > 0, "Must deposit a positive amount");

        balances[msg.sender] += msg.value;

    }

    function withdraw() external {

        uint256 amountToWithdraw = balances[msg.sender];

        require(amountToWithdraw > 0, "Insufficient balance");

        // Secure state update before the external call

        balances[msg.sender] = 0;

        // Safe external call after updating the state

        (bool success, ) = msg.sender.call{value: amountToWithdraw}("");

        require(success, "Withdrawal failed");

    }

}

Step 5: Re-run Slither

After applying fixes, re-run Slither to ensure that the changes have resolved the reported vulnerabilities. Repeat the process of investigating, fixing, and re-running Slither until your contract is free of reentrancy vulnerabilities.

In addition to utilizing tools and automated testing, manual code review is crucial to the smart contract development process, playing a vital role in detecting reentrancy attacks. This process entails the examination of the contract's source code by experienced developers or security specialists who can pinpoint vulnerabilities and suggest remedial measures. 

ZIION streamlines the manual code review process by incorporating VSCodium and an array of helpful extensions. Enhance your smart contract development experience with ZIION — download it today!

Get Started Today