> For the complete documentation index, see [llms.txt](https://zokyo-auditing-tutorials.gitbook.io/zokyo-tutorials/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://zokyo-auditing-tutorials.gitbook.io/zokyo-tutorials/tutorial-65-erc721-and-nfts/preventing-reentrancy-when-using-safeerc721.md).

# Preventing Reentrancy When Using SafeERC721

The `SafeERC721` library from OpenZeppelin is often used to ensure the safe transfer of ERC-721 tokens by verifying that contracts correctly implement the `onERC721Received` interface. However, **this does not automatically protect against reentrancy attacks**. The use of `onERC721Received` creates an external call to the recipient contract, which opens a potential reentrancy attack vector if the recipient contract is malicious or incorrectly implemented.

This tutorial focuses on how reentrancy vulnerabilities can arise when using `SafeERC721` and what precautions to take to ensure your contracts are secure.

***

#### Understanding `SafeERC721` and Reentrancy

OpenZeppelin's `SafeERC721` provides a safer way to transfer non-fungible tokens (NFTs) by ensuring that the recipient contract implements the `IERC721Receiver` interface. The key point of vulnerability lies in the **`onERC721Received` hook**. When transferring a token using `safeTransferFrom`, the transfer process checks whether the recipient is a contract. If it is, the contract must implement the `onERC721Received` function.

Here’s a simplified version of how `safeTransferFrom` works:

```solidity
solidityCopy codefunction safeTransferFrom(
    address from,
    address to,
    uint256 tokenId,
    bytes memory data
) public {
    _transfer(from, to, tokenId);

    if (to.isContract()) {
        require(
            IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, data) ==
            IERC721Receiver.onERC721Received.selector,
            "ERC721: transfer to non ERC721Receiver implementer"
        );
    }
}
```

After the token is transferred, the contract calls `onERC721Received` on the recipient. This is where the risk of **reentrancy** comes into play.

***

#### The Risk of Reentrancy in `onERC721Received`

The **`onERC721Received`** hook is executed by the recipient contract after the token transfer is initiated. A malicious contract could use this function to perform reentrant calls, such as calling back into the original contract and executing additional operations before the original transaction has finished processing. This can result in the contract being in an inconsistent state and exploited by the attacker.

`onERC721Received` function is used to re-enter the original contract and perform an additional `call` before the first transfer completes. If your contract doesn’t guard against reentrancy, it could allow an attacker to transfer tokens multiple times or manipulate the contract’s state.

***

#### How to Prevent Reentrancy When Using `SafeERC721`

To protect against reentrancy attacks when using `SafeERC721`, you need to:

1. **Use OpenZeppelin's `ReentrancyGuard` modifier**: This prevents functions from being called recursively during the execution of a transaction.
2. **Update state variables before making external calls**: Always update the contract's state before calling `safeTransferFrom` or any other external function to avoid having an outdated state during a reentrancy attempt.
