Secure Smart Contract Development — Code Reentrancy in NFT Contracts
Aug 5 2022


Given the prosperity of NFT ecosystem on Ethereum and the increase of related security issues, we will post a series of blogs to introduce these security issues and give some suggestions for developers to secure contracts. In this blog, we will introduce the reentrancy issue in NFT contracts and how to mitigate the related vulnerability.

What is Reentrancy

According to wikipedia

In computing, a computer program or subroutine is called reentrant if multiple invocations can safely run concurrently on multiple processors, or on a single processor system, where a reentrant procedure can be interrupted in the middle of its execution and then safely be called again (“re-entered”) before its previous invocations complete execution.

In a smart contract, reentrancy can occur when a function executes an external call of another contract, which further invokes the original function (or other functions) before the original invocation returns. If the external call is controlled by an untrusted entity (e.g., a malicious contract), it can lead to an unexpected result. That’s because, in some functions, the result depends on the contract state. The contract state will be updated after the external call. However, the reentrant invocation of the function will use the old state instead of the updated one.

Reentrancy has been a prevalent issue in smart contracts, e.g., the MakerDAO attack, the ERC777 on Uniswap, and others (search Reentrancy on BlockSec Academy).

Reentrancy in NFT

For NFT contracts, there exist some implicit external function calls that could be neglected by developers. They include onERC721Received and onERC1155Received function. The onERC721Received function was designed to check whether the receiver contract can handle NFTs (to prevent the NFTs from being locked forever.) This function is invoked in the safeTransferFrom and _safeMint of the ERC721 contract. The similar one exists in the ERC1155 contract. Due to these external function calls, the reentrancy could happen without being noticed by contract developers.

Single-Function Reentrancy

The single-function reentrancy is the simpler form of reentrancy attack. In this kind of reentrancy attack, the re-invoked function is same with the original function. An attacker can invoke the function repeatedly before the first invocation of the function is completed. In NFT contracts, this usually happens in the functions related to the mint operation.

For instance, some NFT projects may give each user a chance to mint NFT freely, set the maximum supply of the whole project, or set the maximum amount of NFTs one user can hold. Usually, these constraints are checked before the actual mint operation. But if the states related to these constraints are updated after the safeMint function, the attacker can reenter this mint function and bypass the constraints since the related states are the same as the first invocation of this function. The HypeBears reentrancy attack posted in our previous blog is an example.

A more complicated single-function reentrancy occurs when safeMint function is used in a loop and the constraints are checked before the loop starts. In this scenario, even some states will be updated automatically before the external call, the remaining safeMint function calls in the loop can still bypass the validation since the loop has already started and the validation happens before the loop starts.

For instance, in the example shown in another post, the mintNFT function will check if the number of NFTs the user wants to mint plus the current supply can exceed the max supply. The safeMint function updates the total supply before the onERC721Received external call. An attacker can still exploit it since the safeMint function only increases the total supply by 1 each time. So if the attacker re-enter the mintNFT function in the first function call of safeMint in the loop, the total supply becomes old supply plus 1, instead of old supply plus the amount of NFTs that will be minted by the first call of mintNFT.

Cross-Function Reentrancy

Instead of entering the same function, the attacker can enter another function that shares or depends on the states with the origin function. We have detailed some cases in our previous blogs for the Revest case and the OMNI case.

Summary and Suggestions

Here are some suggestions for NFT smart contract developers to mitigate the reentrancy threat.

  1. Use the Checks-Effects-Interactions Pattern in your code.
  2. Be careful when you use any third-part library that will introduce external calls. For NFT contracts, be cautious with the implicit callback of onERC721Received and onERC1155Received function.

About BlockSec

BlockSec is a pioneering blockchain security company established in 2021 by a group of globally distinguished security experts. The company is committed to enhancing security and usability for the emerging Web3 world in order to facilitate its mass adoption. To this end, BlockSec provides smart contract and EVM chain security auditing services, the Phalcon platform for security development and blocking threats proactively, the MetaSleuth platform for fund tracking and investigation, and MetaDock extension for web3 builders surfing efficiently in the crypto world.

To date, the company has served over 300 esteemed clients such as MetaMask, Uniswap Foundation, Compound, Forta, and PancakeSwap, and received tens of millions of US dollars in two rounds of financing from preeminent investors, including Matrix Partners, Vitalbridge Capital, and Fenbushi Capital.

Official website:

Official Twitter account:

Sign up for the latest updates
#10: ThirdWeb Incident: Incompatibility Between Trusted Modules Exposes Vulnerability
Security Insights

#10: ThirdWeb Incident: Incompatibility Between Trusted Modules Exposes Vulnerability

This blog shows the vulnerability and attack caused by Incompatibility of commonly used modules.

#9: MEV Bot 0xd61492: From Predator to Prey in an Ingenious Exploit
Security Insights

#9: MEV Bot 0xd61492: From Predator to Prey in an Ingenious Exploit

On August 3, 2023, an MEV Bot on Arbitrum was attacked, resulting in $800K in loss. The root cause of this attack was **Insufficient User Input Verification**.

#8: SushiSwap Incident: A Clumsy Rescue Attempt Leads to a Series of Copycat Attacks
Case Studies

#8: SushiSwap Incident: A Clumsy Rescue Attempt Leads to a Series of Copycat Attacks

On April 9, 2023, SushiSwap became the target of an exploit due to an Unverified External Parameter. The total loss is about $3.3 million.

BlockSec uses cookies and other identifiers to analyze our traffic in accordance. We also share information about your use of our site with our analytics partners. By remaining on this website, you consent to our use of cookies and the Privacy Policy.