# Reentrancy Attack in ERC-1155

> Learn how attackers can exploit reentrancy vulnerabilities in ERC-1155 implementations to drain vault contracts, with an example real-world attack scenario.

- Canonical: https://ack3.ai/research/reentrancy-attack-in-erc-1155/
- Published: August 11, 2025
- Authors: Naoki Yoshida
- Category: Technical guide
- Topics: education, ethereum, exploit, hack, reentrancy-attack, tutorial, wake

Learn how attackers can exploit reentrancy vulnerabilities in ERC-1155 implementations to drain vault contracts. This practical example demonstrates a real-world attack scenario.

[ERC-1155](https://eips.ethereum.org/EIPS/eip-1155 "https://eips.ethereum.org/EIPS/eip-1155") is a multi-token standard for managing multiple token types in a single contract. While powerful, this flexibility creates potential attack vectors through external calls.

## Understanding the vulnerable contract

We’ll examine a simplified vault contract that demonstrates the reentrancy vulnerability. Here’s how it should work:

  * Users create ETH-locked NFTs via the `create` function
  * These NFTs can be freely transferred between users
  * Users unlock ETH using the `payEth` function
  * NFT holders can then `withdraw` ETH by burning their NFTs



Below is the vulnerable Vault contract implementation:

## Exploiting the vulnerability

The vulnerability lies in the `mint` function’s external call to `IERC1155Receiver(to).onERC1155Received()`. This call occurs before updating the `fnftsCreated` counter, creating a reentrancy opportunity.

### The attack vector

The attacker exploits two key contract features:

  * The `id_to_required_eth[nft_id]` mapping controls the ETH lock amount
  * The `nft_price[nft_id]` sets the price per individual NFT



### Attack steps

1\. Call `create` with a large `nftAmount` but small `value`
2\. During the mint callback, reenter with a small `nftAmount` but large `value`
3\. This sets a high `nft_price[nft_id]` for all NFTs
4\. Withdraw to receive: `total_nfts * high_price` in ETH

### Detailed attack flow

Let’s break down the attack step by step:

  1. **Initial creation**
     * Attacker calls `create(1000, 1 wei)`
     * Vault mints 1000 NFTs with ID = `k` (`getNextId()`)
  2. **Reentrancy attack**
     * During `onERC1155Received()` callback:
     * Attacker calls `create(1, 1 ether)`
     * Same `nft_id` (`k`) is used (counter not updated)
     * Sets `nft_price[k] = 1 ether`
  3. **Profit extraction**
     * Attacker unlocks with 1 ETH
     * Withdraws all 1001 NFTs
     * Receives 1001 ETH (1001 NFTs * 1 ETH price)



### Attacker contract

### Proof of concept

Below is the complete attack implementation with Wake testing framework:

Running this exploit successfully drains the vault:

![Wake test output showing successful vault drain](/research/media/2024/06/Screenshot-from-2024-06-19-11-52-22.png)

## Preventing the attack

Two key approaches can prevent this vulnerability:

  1. **Checks-effects-interactions pattern**
     * Update state variables before making external calls
     * This is the recommended approach
  2. **Reentrancy guard**
     * Use OpenZeppelin’s ReentrancyGuard
     * Adds a modifier to prevent reentrant calls



Here’s the fixed implementation:

## Key takeaways

  * ERC standards’ external calls can create unexpected reentrancy vectors
  * State variables shared across contracts need careful handling
  * Always update state before external calls
  * Consider using reentrancy guards as an additional safety measure



### Further reading

Explore our [Reentrancy Examples Repository](https://github.com/Ackee-Blockchain/reentrancy-examples "Reentrancy Examples Github Repository") for more attack vectors:

  * [Single Function Reentrancy](/research/single-function-reentrancy-attack/)
  * [Cross Function Reentrancy](/research/cross-function-reentrancy-attack/)
  * [Cross Contract Reentrancy](/research/cross-contract-reentrancy-attack/)
  * [Read Only Reentrancy](/research/read-only-reentrancy-attack/)
