<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>ayeslick</title>
        <link>https://paragraph.com/@ayeslick</link>
        <description>undefined</description>
        <lastBuildDate>Thu, 03 Sep 2026 15:10:17 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>ayeslick</title>
            <url>https://storage.googleapis.com/papyrus_images/d0835cc97b34affeefd906388848e9d72e24852255f54dfa7fc9b27ae7741185.jpg</url>
            <link>https://paragraph.com/@ayeslick</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[This. Is. Not. A. Bug. 
Zora’s Yoink Yoink ]]></title>
            <link>https://paragraph.com/@ayeslick/this-is-not-a-bug-zora-s-yoink-yoink</link>
            <guid>7HHYqJ22ulWRmmpnT5T6</guid>
            <pubDate>Wed, 02 Apr 2025 02:17:02 GMT</pubDate>
            <description><![CDATA[Note: This was reported to Zora but the contract in question is depreciated. Link to the report.TLDR Zora’s built-in NFT marketplace lets operators accept bids using any ERC20 token. A malicious operator can exploit this by creating a custom ERC20 token that triggers external marketplace interactions during transfer. This allows the operator to sell an NFT to a buyer on another marketplace legitimately, then immediately steal the NFT back using Zora’s transfer logic, leaving the buyer empty-h...]]></description>
            <content:encoded><![CDATA[<blockquote><p>Note:</p><p>This was reported to Zora but the contract in question is depreciated.</p><p>Link to the <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://gist.github.com/ayeslick/0276c4cee7b67116e3c540a54ab05a72">report</a>.</p></blockquote><p><strong><em>TLDR</em></strong></p><p>Zora’s built-in NFT <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0xabefbc9fd2f806065b4f3c237d4b59d9a97bcac7">marketplace</a> lets operators accept bids using any ERC20 token. A malicious operator can exploit this by creating a custom ERC20 token that triggers external marketplace interactions during transfer. This allows the operator to sell an NFT to a buyer on another marketplace legitimately, then immediately steal the NFT back using Zora’s transfer logic, leaving the buyer empty-handed while keeping both the NFT and payment.</p><p><strong><em>details.</em></strong></p><p>Zora’s NFT marketplace is designed with flexibility in mind, allowing users to trade NFTs using <strong>any arbitrary ERC20 token</strong>. While flexible, this design carries implicit risks. Specifically, Zora’s marketplace does not properly account for scenarios where a malicious ERC20 token might execute custom logic during the bid finalization step, resulting in unintended state changes.</p><p>In simpler terms, Zora’s marketplace assumes ERC20 token transfers or approval calls are passive operations. However, a malicious operator can create custom ERC20 tokens containing active logic (hooks) that interact with external marketplaces, manipulating NFT ownership states mid-transaction.</p><p><strong>Step 1: NFT Listing and Bidding (External Marketplace)</strong></p><p>     • An operator mints a Zora NFT.</p><p>     • The operator lists this NFT on an external marketplace (e.g., OpenSea).</p><p>     • A customer sees the NFT and places a bid on the external marketplace.</p><p><strong>Step 2: Malicious ERC20 Token Setup (Zora Marketplace)</strong></p><p>     • The operator creates a <strong>custom ERC20 token</strong> under their complete control.</p><p>     • Using Zora’s built-in marketplace, the operator places a bid on his own NFT using this malicious ERC20 token.</p><p><strong>Step 3: Initiating the Exploit (Accepting Malicious Bid)</strong></p><p>     • The operator accepts his malicious bid via Zora’s marketplace.</p><p>     • This triggers Zora’s internal _finalizeTransfer() function to transfer the NFT.</p><p><strong>Step 4: Malicious Logic Executes During Transfer</strong></p><p>     • During _finalizeTransfer(), Zora’s marketplace invokes the malicious ERC20 token’s logic.</p><p>     • This custom ERC20 logic interacts with the external marketplace, automatically accepting the legitimate customer’s bid from Step 1.</p><p>     • The NFT is transferred from the operator to the customer, and payment is transferred to the operator.</p><p><strong>Step 5: YOINK</strong></p><p>     • Execution context now returns to Zora’s marketplace after the external sale.</p><p>     • Zora’s marketplace incorrectly assumes the NFT is still held by the operator. Due to this assumption, the marketplace proceeds to transfer the NFT <strong>from the customer to the operator</strong>.</p><p><strong>Final Outcome:</strong></p><p>     • The customer loses ownership of the NFT they purchased.</p><p>     • The operator retains both the customer’s payment and the NFT itself.</p>]]></content:encoded>
            <author>ayeslick@newsletter.paragraph.com (ayeslick)</author>
        </item>
        <item>
            <title><![CDATA[Crack In The Foundation ]]></title>
            <link>https://paragraph.com/@ayeslick/crack-in-the-foundation</link>
            <guid>nOhhrTN35VPzguFwWPzQ</guid>
            <pubDate>Thu, 27 Feb 2025 07:04:48 GMT</pubDate>
            <description><![CDATA[Note: The following is a fictionalized story of an out-of-scope report that I submitted to Foundation via Immunefi. The report is considered technically true but out of scope in part because of the belief that loss of reputation will prevent operators from using this exploit.I remember the day I decided to resell my NFT on Foundation like it was yesterday. The piece was a rare digital sculpture by a once-respected creator. I’d purchased it months earlier for a nice amount, believing in the ar...]]></description>
            <content:encoded><![CDATA[<blockquote><p>Note: The following is a fictionalized story of an out-of-scope report that I submitted to Foundation via Immunefi. The <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://gist.github.com/ayeslick/0eddad50cd5148c76945978a0df8aebe">report</a> is considered technically true but out of scope in part because of the belief that loss of reputation will prevent operators from using this exploit.</p></blockquote><p>I remember the day I decided to resell my NFT on Foundation like it was yesterday. The piece was a rare digital sculpture by a once-respected creator. I’d purchased it months earlier for a nice amount, believing in the artwork’s long-term value. It had since appreciated, and I was excited to finally cash in. But when the time came, I found myself in a baffling position: I got nothing. Not a single ETH. Not one wei. All the proceeds slipped right through my hands and into the creator’s wallet.</p><p>It didn’t make sense. I was no newbie to NFTs—surely I hadn’t misunderstood something so fundamental. I had sold other NFTs before, and they’d been straightforward: I list, buyer pays, I get my cut, the creator gets their royalty. But this time, everything looked correct on the surface… until my payout never appeared. I decided to investigate. And that’s where my journey down the rabbit hole began.</p><p><strong>Setting the Stage</strong></p><p>After my sale closed, I waited for the transaction confirmations and the usual notifications. Except the familiar chime of incoming ETH never arrived. I checked my wallet’s balance: unchanged. Confused, I hopped onto Etherscan to follow the transaction trail. The buyer’s payment had gone through. The contract had processed the sale. The platform fees were taken out. And then, according to the transaction logs, my portion of the revenue was sent directly to the creator.</p><p>I stared at the transaction details, perplexed. Why in the world would the creator receive the entire sum from what should have been a secondary sale? Sure, creators get royalties, but not everything. Had I clicked the wrong button? Set my sale price incorrectly? I replayed the listing process in my head, but it all seemed normal.</p><p><strong>Diving Into the Contracts</strong></p><p>With no other leads, I turned to the code. Foundation, like many NFT marketplaces, uses smart contracts that are public on the blockchain. I knew how to look at verified code on Etherscan, so eventually I pulled up the MarketUtils contract. Browsing through the code, I found the part where the fees were calculated—the function that determined how to split the sale price between me (the seller) and the creator.</p><p>Then I saw something that made me do a double-take. There, in the logic, was a snippet that felt like a hidden booby trap:</p><pre data-type="codeBlock" text="if (creatorRecipients[i] == options.seller) {

// If the seller is any of the recipients defined, assume a primary sale

creatorRev += sellerRev;

sellerRev = 0;

}
"><code><span class="hljs-keyword">if</span> (creatorRecipients[i] <span class="hljs-operator">=</span><span class="hljs-operator">=</span> options.seller) {

<span class="hljs-comment">// If the seller is any of the recipients defined, assume a primary sale</span>

creatorRev <span class="hljs-operator">+</span><span class="hljs-operator">=</span> sellerRev;

sellerRev <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;

}
</code></pre><p>Wait, what? This line meant that if my address—the seller’s address—appeared in the list of “creatorRecipients,” the code would treat the sale as if it were a <em>primary sale</em>. In a primary sale, the original creator is supposed to get almost everything less the platform fees. But I wasn’t the original creator. I was a secondary collector, trying to flip a piece on the secondary market. So why was my address popping up in that list?</p><p><strong>A Suspicious Override Contract</strong></p><p>I dug deeper. Foundation uses a royalty registry that allows creators to override default royalties with their own custom logic. This can be handy in a lot of legitimate scenarios—maybe a collective of artists shares revenue, or a charity receives part of the profits. But if a creator can add me, the seller, to that list of recipients, what then?</p><p>According to the code, if I’m listed as a creator recipient, the marketplace thinks it’s the first time this NFT is being sold. Suddenly, my rightful seller’s payout vanishes, merged into the creator’s pot.</p><p>As I followed the chain of contracts and calls, I discovered the culprit: the creator had registered an override contract that specifically listed my address as a “creator recipient.” That was bizarre, because I had no relationship with them. It looked like pure sabotage. And to ensure maximum mischief, they had cranked the creatorShares array so high that the code defaulted to paying only the first recipient in that list—which just so happened to be themselves.</p><p><strong>Finding the Smoking Gun on Etherscan</strong></p><p>I pulled up the override contract on Etherscan. It wasn’t well-known, had few interactions, and looked suspiciously like a bespoke trap. Inside, I could see the code logic specifying me as a recipient. My address, right there in black and white, lumped into the creator’s payout group.</p><p>I traced a few transactions and noticed how the contract was toggled on and off. The creator had set it up before my sale. Then, after the sale was done, they reverted to the original royalty setup. If someone came snooping later, they might never spot the scam unless they timed it just right.</p><p>To the outside world, it would appear as though the platform itself had made a deliberate decision to funnel all funds to the creator. But in reality, it was the code’s design interacting with malicious data provided by the creator’s override. Foundation’s marketplace logic had a loophole—one that let the creator manipulate a situation so that my address was treated as if I were the original artist, effectively zeroing out my cut.</p><p><strong>A Quiet Acceptance</strong></p><p>Armed with this information, I reached out to Foundation. I expected outrage, concern, or at the very least a swift patch. Instead, they seemed oddly unbothered. They considered the exploit “acceptable design.” According to them, the logic was working as intended: if a creator provides malicious data, that’s on the creator’s conscience, not the platform’s responsibility.</p><p>I gaped at my screen, incredulous. This was a blueprint for robbery, and they were okay with it, reasoning that a malicious creator would damage their reputation. But what about collectors like me who had just been robbed blind? Reputation damage doesn’t refill my empty wallet.</p><p><strong>Reflections on a Harsh Lesson</strong></p><p>As I sat back, I realized how vulnerable secondary sellers like me could be. I had stumbled into a hidden pitfall that most users probably never consider. When we trust platforms, we assume they protect both buyers and sellers from malicious actors. But in this case, the platform’s own fee logic and overrides combined into a perfect storm that let the creator siphon off what should have been my legitimate earnings.</p>]]></content:encoded>
            <author>ayeslick@newsletter.paragraph.com (ayeslick)</author>
        </item>
        <item>
            <title><![CDATA[Two Contracts, One Bug]]></title>
            <link>https://paragraph.com/@ayeslick/two-contracts-one-bug</link>
            <guid>1WR3ych3q3ObSGQcIGuy</guid>
            <pubDate>Thu, 05 Oct 2023 19:06:29 GMT</pubDate>
            <description><![CDATA[Summary:A critical vulnerability was identified in both Async Art’s NFTAuction and SuperRare’s SuperRareAuctionHouse contracts. The former had approximately ~30k at risk, while the latter faced a potential loss of ~430k. Funds in both protocols remain secure. I reached out to Async through Discord and SuperRare via the SEAL 911 service.Root Causes:1. Doesn’t account for non-standard NFTs deviating from the ERC-721 specification. 2. Lacks the ability to differentiate between auctions. 3. Absen...]]></description>
            <content:encoded><![CDATA[<h1 id="h-summary" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Summary:</h1><p>A critical vulnerability was identified in both Async Art’s NFTAuction and SuperRare’s SuperRareAuctionHouse contracts. The former had approximately ~30k at risk, while the latter faced a potential loss of ~430k. Funds in both protocols remain secure. I reached out to Async through Discord and SuperRare via the SEAL 911 service.</p><h1 id="h-root-causes" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Root Causes:</h1><p>1. Doesn’t account for non-standard NFTs deviating from the ERC-721 specification.</p><p>2. Lacks the ability to differentiate between auctions.</p><p>3. Absence of validation ensuring that the currency in a bid matches the currency in the auction.</p><h1 id="h-async-arts-vulnerability-and-exploit" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Async Art’s Vulnerability &amp; Exploit:</h1><h3 id="h-observations" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Observations:</h3><p>1. In Async’s NFTAuction contract, a seller can create an auction with a custom NFT and subsequently withdraw that NFT during the auction’s duration, then start another auction using the same NFT. This action results in the previous auction being superseded.</p><p>2. A bidder can bid on an NFT without it being actively auctioned. The contract doesn’t check the currency provided by the bidder during bid acceptance, necessitating sellers to be cautious when accepting bids.</p><p>My observations made me wonder if it would be possible to drain the contract of its ETH/ERC20s and it turns out that one can. Let’s see how.</p><p>One can use a custom NFT and valueless ERC20 to drain the NFTAuction contract of all its ETH. One does this by creating a sale using a valueless ERC20, an ERC20 one created, as the token, and a custom NFT one created as the NFT for sale. After the transaction to create the sale finishes one bids on his own NFT. The valueless ERC20s are sent to the contract and one is recorded as the highest bid. The sale price is greater than one’s bid. The bid price matches the amount one wants to withdraw from the NFTAuction contract. After the bid transaction finishes one calls the create sale function. Now the modifier should prevent one from doing this and in a standard NFT contract it would, however, the custom NFT one created shows one as the owner of the NFT. This allows one to pass new values to the sale. This time one sets the token to address(0) which is ETH. One also sets the buyNow price to the bid price. When the create sale function sees that the highestBid matches the buy now price it sends the bid price to one and the custom NFT.</p><p>After confirming this exploit with a Proof of Concept (PoC), I notified Async. Their team, leveraging my PoC, successfully secured ~30k worth of ETH, considering the NFTAuction is non-upgradable.</p><h1 id="h-superrares-vulnerability-and-exploit" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">SuperRare’s Vulnerability &amp; Exploit:</h1><p>Upon reviewing SuperRare’s code, I noticed striking similarities to the aforementioned Async vulnerability.</p><h3 id="h-observations" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Observations:</h3><p>Instead of creating a valueless ERC20 one has to use an approved ERC20. This is important since this is the crux of the exploit. Fortunately, SuperRare uses its own RARE token which one can easily acquire. Instead of placing a bid and then creating an auction one converts an offer to an auction via <code>convertOfferToAuction()</code>.</p><p>Once the offer is converted to an auction one can call the <code>configureAuction()</code> passing in similar parameters as one did when calling <code>convertOfferToAuction()</code> except one passes ETH as currency instead of RARE. This overwrites the previous auction created by the <code>convertOfferToAuction()</code> call but <em>doesn’t</em> overwrite the bid created in <code>convertOfferToAuction()</code>. When the auction ends one calls <code>endAuction()</code> and since <code>endAuction()</code> doesn’t verify that the currency in the bid matches the currency in the auction one receives the balance of ETH in SuperRareBazaar. Three addresses are used for this exploit; bidder, exploiter, and exploiter1.</p><h3 id="h-exploit-flow" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Exploit Flow:</h3><ol><li><p>Operator creates custom NFT and mints to exploiter address.</p></li><li><p>From the bidder’s address, the Operator places an offer on said NFT using the SuperRare token as currency.</p></li><li><p>From the exploiter’s address, the operator converts the offer to an auction. This creates the first auction. The custom NFT ignores the transferFrom call since it comes from SuperRareBazaar.</p></li><li><p>The operator transfers the NFT from exploiter to exploiter1.</p></li><li><p>From exploiter1 he configures the auction using similar parameters except he uses ETH instead of SuperRare’s RARE token as currency. This overwrites the previous auction but <em>doesn’t</em> overwrite the bid that was created when the offer was converted to an auction.</p></li><li><p>Once the auction ends the operator calls endAuction() from any address he owns and receives about ~211.16 ETH or $315,881. This leaves the contract with about ~0.000749ETH or $1.25.</p></li></ol><p>After validating this vulnerability using a local PoC and noticing the contract was active with ~500k at risk, I reached out to SuperRare. Despite initial communication challenges, the SEAL 911 service provided the necessary bridge to connect with SuperRare’s team. They promptly rectified the vulnerability and deployed the necessary fixes.</p><h1 id="h-links-to-reports" class="text-4xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Links To Reports:</h1><p>AsyncArt:</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://gist.github.com/ayeslick/02fcaaca9ed87555652464462438ba48">AsyncArt</a></p><p>SuperRare:</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://gist.github.com/ayeslick/956d97ef62e87584c7548ac0991b7fe3">SuperRare</a></p>]]></content:encoded>
            <author>ayeslick@newsletter.paragraph.com (ayeslick)</author>
        </item>
    </channel>
</rss>