{"id":765,"date":"2025-08-11T14:16:40","date_gmt":"2025-08-11T12:16:40","guid":{"rendered":"https:\/\/ackee.xyz\/blog\/?p=765"},"modified":"2025-08-11T14:17:34","modified_gmt":"2025-08-11T12:17:34","slug":"reentrancy-attack-in-erc-1155","status":"publish","type":"post","link":"https:\/\/ackee.xyz\/blog\/reentrancy-attack-in-erc-1155\/","title":{"rendered":"Reentrancy Attack in ERC-1155"},"content":{"rendered":"<p class=\"p1\">Learn how attackers can exploit reentrancy vulnerabilities in ERC-1155 implementations to drain vault contracts. This practical example demonstrates a real-world attack scenario.<\/p>\n<div>\n<div><a title=\"https:\/\/eips.ethereum.org\/EIPS\/eip-1155\" href=\"https:\/\/eips.ethereum.org\/EIPS\/eip-1155\" data-href=\"https:\/\/eips.ethereum.org\/EIPS\/eip-1155\">ERC-1155<\/a> 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.<\/div>\n<\/div>\n<h2 id=\"contracts\" class=\"code-line\" dir=\"auto\" data-line=\"6\">Understanding the vulnerable contract<\/h2>\n<p class=\"code-line\" dir=\"auto\" data-line=\"8\">We&#8217;ll examine a simplified vault contract that demonstrates the reentrancy vulnerability. Here&#8217;s how it should work:<\/p>\n<ul class=\"code-line\" dir=\"auto\" data-line=\"12\">\n<li class=\"code-line\" dir=\"auto\" data-line=\"12\">Users create ETH-locked NFTs via the <code class=\"codehl\">create<\/code> function<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"13\">These NFTs can be freely transferred between users<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"14\">Users unlock ETH using the <code class=\"codehl\">payEth<\/code> function<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"15\">NFT holders can then <code class=\"codehl\">withdraw<\/code> ETH by burning their NFTs<\/li>\n<\/ul>\n<p class=\"code-line\" dir=\"auto\" data-line=\"17\">Below is the vulnerable Vault contract implementation:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/MeditationDuck\/440e96f99a652c1803e72d0b82b909b4.js\"><\/script><\/p>\n<h2 id=\"attack-example\" class=\"code-line\" dir=\"auto\" data-line=\"110\">Exploiting the vulnerability<\/h2>\n<p class=\"code-line\" dir=\"auto\" data-line=\"112\">The vulnerability lies in the <code class=\"codehl\">mint<\/code> function&#8217;s external call to <code class=\"codehl\">IERC1155Receiver(to).onERC1155Received()<\/code>. This call occurs before updating the <code>fnftsCreated<\/code> counter, creating a reentrancy opportunity.<\/p>\n<h3>The attack vector<\/h3>\n<p class=\"code-line\" dir=\"auto\" data-line=\"116\">The attacker exploits two key contract features:<\/p>\n<ul>\n<li>The <code class=\"codehl\">id_to_required_eth[nft_id]<\/code> mapping controls the ETH lock amount<\/li>\n<li>The <code class=\"codehl\">nft_price[nft_id]<\/code> sets the price per individual NFT<\/li>\n<\/ul>\n<h3>Attack steps<\/h3>\n<p class=\"code-line\" dir=\"auto\" data-line=\"126\">1. Call <code class=\"codehl\">create<\/code> with a large <code class=\"codehl\">nftAmount<\/code> but small <code class=\"codehl\">value<\/code><br \/>\n2. During the mint callback, reenter with a small <code class=\"codehl\">nftAmount<\/code> but large <code class=\"codehl\">value<\/code><br \/>\n3. This sets a high <code class=\"codehl\">nft_price[nft_id]<\/code> for all NFTs<br \/>\n4. Withdraw to receive: <code class=\"codehl\">total_nfts * high_price<\/code> in ETH<\/p>\n<h3>Detailed attack flow<\/h3>\n<p class=\"code-line\" dir=\"auto\" data-line=\"131\">Let&#8217;s break down the attack step by step:<\/p>\n<ol>\n<li><strong>Initial creation<\/strong>\n<ul>\n<li>Attacker calls <code class=\"codehl\">create(1000, 1 wei)<\/code><\/li>\n<li>Vault mints 1000 NFTs with ID = <code class=\"codehl\">k<\/code> (<code class=\"codehl\">getNextId()<\/code>)<\/li>\n<\/ul>\n<\/li>\n<li><strong>Reentrancy attack<\/strong>\n<ul>\n<li>During <code class=\"codehl\">onERC1155Received()<\/code> callback:<\/li>\n<li>Attacker calls <code class=\"codehl\">create(1, 1 ether)<\/code><\/li>\n<li>Same <code class=\"codehl\">nft_id<\/code> (<code class=\"codehl\">k<\/code>) is used (counter not updated)<\/li>\n<li>Sets <code class=\"codehl\">nft_price[k] = 1 ether<\/code><\/li>\n<\/ul>\n<\/li>\n<li><strong>Profit extraction<\/strong>\n<ul>\n<li>Attacker unlocks with 1 ETH<\/li>\n<li>Withdraws all 1001 NFTs<\/li>\n<li>Receives 1001 ETH (1001 NFTs * 1 ETH price)<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<h3 id=\"attacker-contract\" class=\"code-line\" dir=\"auto\" data-line=\"145\">Attacker contract<\/h3>\n<p><script src=\"https:\/\/gist.github.com\/MeditationDuck\/bc694bf12710791a5ba8a8664798eb08.js\"><\/script><\/p>\n<h3 id=\"wake-code\" class=\"code-line\" dir=\"auto\" data-line=\"212\">Proof of concept<\/h3>\n<p>Below is the complete attack implementation with Wake testing framework:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/MeditationDuck\/7b646c33b8d130a674dc635e43471e73.js\"><\/script><\/p>\n<p>Running this exploit successfully drains the vault:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-766\" src=\"https:\/\/abchprod.wpengine.com\/wp-content\/uploads\/2024\/06\/Screenshot-from-2024-06-19-11-52-22.png\" alt=\"Wake test output showing successful vault drain\" width=\"1335\" height=\"550\" srcset=\"https:\/\/ackee.xyz\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-from-2024-06-19-11-52-22.png 1335w, https:\/\/ackee.xyz\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-from-2024-06-19-11-52-22-300x124.png 300w, https:\/\/ackee.xyz\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-from-2024-06-19-11-52-22-1024x422.png 1024w, https:\/\/ackee.xyz\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-from-2024-06-19-11-52-22-768x316.png 768w, https:\/\/ackee.xyz\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-from-2024-06-19-11-52-22-370x152.png 370w, https:\/\/ackee.xyz\/blog\/wp-content\/uploads\/2024\/06\/Screenshot-from-2024-06-19-11-52-22-760x313.png 760w\" sizes=\"auto, (max-width: 1335px) 100vw, 1335px\" \/><\/p>\n<h2 id=\"prevention\" class=\"code-line\" dir=\"auto\" data-line=\"216\">Preventing the attack<\/h2>\n<p>Two key approaches can prevent this vulnerability:<\/p>\n<ol>\n<li><strong>Checks-effects-interactions pattern<\/strong>\n<ul>\n<li>Update state variables before making external calls<\/li>\n<li>This is the recommended approach<\/li>\n<\/ul>\n<\/li>\n<li><strong>Reentrancy guard<\/strong>\n<ul>\n<li>Use OpenZeppelin&#8217;s ReentrancyGuard<\/li>\n<li>Adds a modifier to prevent reentrant calls<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>Here&#8217;s the fixed implementation:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/MeditationDuck\/4697d18bb90657d14c8460f44bce1aba.js\"><\/script><\/p>\n<h2 id=\"conclusion\" class=\"code-line\" dir=\"auto\" data-line=\"222\">Key takeaways<\/h2>\n<ul>\n<li>ERC standards&#8217; external calls can create unexpected reentrancy vectors<\/li>\n<li>State variables shared across contracts need careful handling<\/li>\n<li>Always update state before external calls<\/li>\n<li>Consider using reentrancy guards as an additional safety measure<\/li>\n<\/ul>\n<h3>Further reading<\/h3>\n<p>Explore our <a title=\"Reentrancy Examples Github Repository\" href=\"https:\/\/github.com\/Ackee-Blockchain\/reentrancy-examples\">Reentrancy Examples Repository<\/a> for more attack vectors:<\/p>\n<ul>\n<li><a href=\"https:\/\/ackee.xyz\/blog\/single-function-reentrancy-attack\/\">Single Function Reentrancy<\/a><\/li>\n<li><a href=\"https:\/\/ackee.xyz\/blog\/cross-function-reentrancy-attack\/\">Cross Function Reentrancy<\/a><\/li>\n<li><a href=\"https:\/\/ackee.xyz\/blog\/cross-contract-reentrancy-attack\/\">Cross Contract Reentrancy<\/a><\/li>\n<li><a href=\"https:\/\/ackee.xyz\/blog\/read-only-reentrancy-attack\/\">Read Only Reentrancy<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>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 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&#8217;ll examine a simplified vault contract that demonstrates the reentrancy vulnerability.&hellip;<\/p>\n","protected":false},"author":24,"featured_media":1038,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[61,10,85,84,63,103],"tags":[96,14,86,138],"class_list":["post-765","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-education","category-ethereum","category-exploits","category-hacks","category-tutorial","category-wake","tag-educational","tag-exploit","tag-hack","tag-reentrancy-attack"],"aioseo_notices":[],"featured_image_src":"https:\/\/ackee.xyz\/blog\/wp-content\/uploads\/2025\/04\/ERC-777-600x400.png","featured_image_src_square":"https:\/\/ackee.xyz\/blog\/wp-content\/uploads\/2025\/04\/ERC-777-600x600.png","author_info":{"display_name":"Naoki Yoshida","author_link":"https:\/\/ackee.xyz\/blog\/author\/naoki-yoshida\/"},"_links":{"self":[{"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/posts\/765","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/users\/24"}],"replies":[{"embeddable":true,"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/comments?post=765"}],"version-history":[{"count":0,"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/posts\/765\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/media\/1038"}],"wp:attachment":[{"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/media?parent=765"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/categories?post=765"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/tags?post=765"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}