The ERC721 token has become the backbone of the NFT ecosystem, but the implementation contains subtle security risks that developers often overlook. The ERC721 standard includes a safety mechanism called Thee. ERC721Receiver
HOOK, designed to prevent the token from being lost when transmitted to a contract. However, this same mechanism introduces external calls that can be exploited through re -creation attacks.
In this article, how the attacker _safeMint
Even if the developer thinks that he has observed a safe coding practice, the external call of the function to bypass the minting minting limit and release the NFT collection.
Example: Expected use
that Masks
The contract extends the ERC721 and manages the NFT mining with the following constraints:
- Users can call
mintNFT
It functions for NFTS - Up to 20 NFTs per transaction
- Total source
MAX_NFT_SUPPLY
Vulnerable contract
Vulnerability occurs in external currencies IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data)
Within _safeMint
function.
The currency flow follows this pattern.
mintNFT
phone call_safeMint
_safeMint
phone call_safeMint
Set the argument_safeMint
phone call_checkOnERC721Received
_checkOnERC721Received
phone callIERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data)
The mask contract checks the number of NFTs at the start of the function. totalSupply()
use _tokenOwners.length()
.
This value will be updated next _tokenOwners.set(tokenId, to);
at _mint
Features and after that _checkOnERC721Received
It is called. Therefore, it does not seem to be re -creation at first.
But the condition mintNFT
Compare the current totalSupply
and numberOfNft
With ~ MAX_NFT_SUPPLY
.
When the attacker enters the for loop, the comparison uses old -fashioned. totalSupply
Values that allow excessive NFT mining.
Attack example
The attack is carried out through the following steps.
- Attacker
mintNFT(20)
- Let’s say value
totalSupply()
BeN
- that
_mint()
Function Update_tokenOwners
nowtotalSupply()
BeN+1
- function
_checkOnERC721Received
phone callonERC721Received()
In the attacker contract:- Attacker
mintNFT(20)
Through re -creation - At this moment
totalSupply()
BeN+1
No ~N+20
-This is a point - So we can create 18 additional NFTs
totalSupply()
ToN+1
- It checks whether it is
N+1+18
Less thanMAX_NFT_SUPPLY
But you need to confirmN+20+18
This must be returned - Repeat the process similarly
- Attacker
This is an attacker contract.
And this is an abuse.
The attacker successfully exceeds both the 20 NFT limit and the maximum number of solutions in one transaction, with 110 NFTs successfully MINTS.
prevention
Implement the reinvestment guard to prevent this vulnerability.
conclusion
The vulnerabilities proven here emphasize important lessons for smart contract developers. Even if you try to follow the established security pattern, such as the confirmation effect, if you introduce a loop with an external currency, an unexpected attack vector can be created. The safety function of the ERC721 standard is intended, but it can be a security debt without proper protection.
This case emphasizes the reason why comprehensive security audits and re -creation guards are essential for handling valuable assets in contract processing. As the Defi and NFT ecosystems continue to develop, developers must be wary of these subtle and destructive vulnerabilities that can bypass strong verification logic.
We maintain a reentrancy example GitHub repository that deals with other types of re -creation attacks and re -creations for each protocol.
We also wrote about re -creation attacks by type.
will
https://samczsun.com/the-dangers- of-surprising-code/