<?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>Mint Fund</title>
        <link>https://paragraph.com/@thisiscarlos</link>
        <description>A Creative Resource for Artists</description>
        <lastBuildDate>Sun, 12 Apr 2026 05:09:44 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <image>
            <title>Mint Fund</title>
            <url>https://storage.googleapis.com/papyrus_images/51c901f077cc38a7365efd9ed3514ef99f4730a4ef3f0f5c40b80d276de60447.png</url>
            <link>https://paragraph.com/@thisiscarlos</link>
        </image>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[Mint Fund 2024: Artist Roundtables & Grants]]></title>
            <link>https://paragraph.com/@thisiscarlos/mint-fund-2024-artist-roundtables-grants</link>
            <guid>HdqWShq3UAdoUcIShdBC</guid>
            <pubDate>Tue, 05 Mar 2024 18:15:17 GMT</pubDate>
            <description><![CDATA[Apply to participate in an Artist Roundtable and receive a $500 USDC grant to create and mint your art Mint Fund is ramping up efforts in 2024 with new initiatives to support artists. Since beginning in 2021, Mint Fund has become a resource for artists from all over the world to onboard into crypto, receive funds to mint their works, and put their art onchain. This year, we continue on. Introducing Artist Roundtables Our hope is to create spaces for artists to come together, discuss their wor...]]></description>
            <content:encoded><![CDATA[<h3 id="h-apply-to-participate-in-an-artist-roundtable-and-receive-a-dollar500-usdc-grant-to-create-and-mint-your-art" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0"><strong>Apply to participate in an Artist Roundtable and receive a $500 USDC grant to create and mint your art</strong></h3><p><br>Mint Fund is ramping up efforts in 2024 with new initiatives to support artists. Since <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mint.mirror.xyz/5Dule_9ghkywLl6LzRbTnxriuCA1dKD94-7g8hRrpnY">beginning in 2021</a>, Mint Fund has become a resource for artists from all over the world to onboard into crypto, receive funds to mint their works, and put their art onchain. <br><br>This year, we continue on.</p><p><strong>Introducing Artist Roundtables</strong></p><p>Our hope is to create spaces for artists to come together, discuss their work, and become part of a community of like-minded peers. In a space that moves at lightspeed, fostering connections among artists, sharing resources, and offering mutual support will be critical for establishing enduring relationships. We want to become a hub for these kinds of interactions in 2024 with the introduction of <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.themint.fund/artist-roundtables">Artist Roundtables</a>.</p><p>Each month, we will host two Artist Roundtables. To participate, artists can submit a short application with information about their practice and the work they are interested in creating. A curated selection of 10 artists will be invited to join each Roundtable. If selected, please come prepared to share a bit about your work, along with any questions you may have about releasing your project onchain.</p><p><strong>How to Apply</strong></p><p>At the beginning of the month, we’ll open applications at <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.themint.fund/apply">themint.fund/apply</a>. Submit your application <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.google.com/forms/d/e/1FAIpQLSdCa4eA1mWK0ko4yvHA0TDfSh_smRzTEghMLHuSZTGnj7GqPA/viewform?usp=sf_link">here</a> before the deadline and let us know which session you are able to attend. We’re on the lookout to support artists who are undertaking ambitious projects and have new works that they would like to mint. Each session will include a range of artists working in a multitude of mediums from all over the world.</p><p>Once applications close, confirmation emails will be sent to selected artists to begin onboarding. If you’re not selected, you are welcome to apply again for an upcoming month.</p><p><strong>Receiving a Mint Fund Grant</strong></p><p>After each Artist Roundtable, we’ll send participating artists a $500 USDC grant to mint their work. The grant can be used towards the creation and minting of new work, on any chain or platform of an artist’s choosing.</p><p>Mint Fund will publish an editorial recap featuring all of the participating artists and works that were minted to bring more visibility to the projects.</p><p><strong>Plus, the Mint Fund Partner Program and Future Initiatives</strong></p><p>Along with the introduction of Artist Roundtables and Mint Fund grants, we will continue to accept applications for our <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.google.com/forms/d/e/1FAIpQLSfRKPUEWS48sdwELQGCatt1eO-DCsgTMME1ecQ5fJ5IgEUGlA/viewform?usp=sf_link">Partner Program</a>. If you are an organization, or an artist, creative, or curator looking to make a larger initiative or group show come to life, we encourage you to apply. Applications for the Partner Program are reviewed and accepted on a rolling basis.</p><p>Thank you to all who have made it possible for us to continue our Mint Fund efforts. We look forward to bringing even more artists into the fold in 2024 and beyond.</p>]]></content:encoded>
            <author>thisiscarlos@newsletter.paragraph.com (Mint Fund)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/5788fa40dc6365063b174e0c8de5680935f0a87a4c456c19e2e982ec0bef7830.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[Mint Fund 🍃 The Rewind & The Future]]></title>
            <link>https://paragraph.com/@thisiscarlos/mint-fund-the-rewind-the-future</link>
            <guid>UVkR4pUEu6CnGH4npby7</guid>
            <pubDate>Mon, 02 Aug 2021 07:11:50 GMT</pubDate>
            <description><![CDATA[RECAP 🍃 ONBOARDING & BATCHESOur goal at Mint Fund is to empower creatives. Largely, that has been through the thoughtful practice of onboarding global creatives to mint their first NFTs. We&apos;ve onboarded artists from 18 countries including the Philippines, Indonesia, Mexico, Venezuela, South Africa, Nigeria, Malaysia, and more. Selected artists complete onboarding and attend a series of workshops to then receive a grant. To date, Mint Fund has received ~42 ETH from ~74 contributors, and ...]]></description>
            <content:encoded><![CDATA[<h3 id="h-recap-onboarding-and-batches" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">RECAP 🍃 ONBOARDING &amp; BATCHES</h3><p>Our goal at <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://themint.fund/">Mint Fund</a> is to empower creatives. Largely, that has been through the thoughtful practice of onboarding global creatives to mint their first NFTs.</p><p>We&apos;ve onboarded artists from 18 countries including the Philippines, Indonesia, Mexico, Venezuela, South Africa, Nigeria, Malaysia, and more. Selected artists complete onboarding and attend a series of workshops to then receive a grant. To date, Mint Fund has received ~42 ETH from ~74 contributors, and we have distributed ~12 ETH in total to artists. With gratitude to all who have contributed to the fund, 44 NFTs have been successfully minted by artists representing a diverse range of perspectives, practices, locations, and identities.</p><p>Some of the incredibly talented artists to join Mint Fund include: 3D artist <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zora.co/rimbawangerilya">Rimbawan Gerilya</a>, multimedia artist <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://foundation.app/@TheCount">Moyosore Briggs</a>, photographer <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://foundation.app/@nft/nft-30176">Ashmit Galav</a>, designer <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://foundation.app/@ravi">Ravi Vasavan</a>, musician <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zora.co/0xd1CcB4472872c2488856226EC47B890c167ae2F7/1790">Eddington Again</a>, performance artist <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://foundation.app/@niall">Niall Ashley</a>, 3D artist <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://foundation.app/@thegladscientist/wool-wobble-40984">The Glad Scientist</a>, designer <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zora.co/0x2bD5d2e3d5852AD9960638083cb7c9F493E7A597/3003">Gian Ferrer</a>, illustrator <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zora.co/oplerou">O’Plerou</a>, animator <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://foundation.app/@tigris">Tigris Li</a>, concept artist <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://foundation.app/@Tondji">Tondji</a>, and so many more.</p><p>Behind-the-scenes, our core team continues to review applications based on curation criteria prioritizing BIPOC and LGBTQIA+ creators. With care and intention, we onboard batches, host workshops, and work closely with each artist throughout the minting process. Since we onboarded <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/themintfund/status/1389900035412746242">Batch 01</a> of 35 artists in late-February, we’ve reworked our process and took new learnings with us through to our latest Batch 04.</p><p>We also want to take a moment to thank all of the contributors who have volunteered to host educational workshops with us including <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/Cooopahtroopa">Cooper Turley</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/osinachiart">Osinachi</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/parisrouz">Paris Rouzati</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/parisrouz">Gabrielle Micheletti</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/shawnax">Shawna X</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/sven_eberwein">Sven Eberwein</a>, and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/TheNamesBria_">Bria Thomas</a>.</p><h3 id="h-initiatives-sothebys-and-the-digital-diaspora" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">INITIATIVES 🍃 SOTHEBY’S &amp; THE DIGITAL DIASPORA</h3><p>As our work to support a global network of artists progresses, we’ve garnered interest from organizations to further our mission. In May, Sotheby’s auction house organized <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.sothebys.com/en/buy/auction/2021/natively-digital-a-curated-nft-sale-2"><em>Natively Digital: A Curated NFT Sale.</em></a> As part of the lot, a percentage of the artwork sales will be donated to Mint Fund. We also had the opportunity to work with Michael Bouhanna, Deputy Director at Sotheby’s, and Ben Gentilli, founder of the Robert Alice Project, to identify an alumni of Mint Fund’s artist roster to participate in the auction. Brazilian artist, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/occult3d">Ikaro Cavalcante</a> (occulted), created a new work for the show—<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.sothebys.com/en/buy/auction/2021/natively-digital-a-curated-nft-sale-2/perennial-links"><em>Perennial Links</em></a>. Inclusion of work by an artist from Mint Fund gave us an important signal and glimpse into the future we are aiming to build, one where artists are able to achieve unimaginable heights by having access to minting NFTs alone.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/occult3d/status/1403227316432654336">https://twitter.com/occult3d/status/1403227316432654336</a></p><p>Along with our schedule of onboarding new creators through batches, Mint Fund was presented with the opportunity to provide support for <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://foundation.app/digital-diaspora"><em>The Digital Diaspora</em></a>. Curator <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/dianaesinclair">Diana Sinclair</a> of <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.towardsutopia.life/">Towards Utopia</a> organized an exhibition of NFTs from 18 artists across the African diaspora to be released on Juneteenth. A portion of funds raised through the NFT auctions were <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/towards_utopia/status/1414704795148070912">donated to G.L.I.T.S. and herstoryDAO</a>. Similar to the Sotheby’s project, Diana selected South African photographer <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://foundation.app/@ayeshachasm/rebirth-47730">Ayesha Kazim</a> to represent Mint Fund in the dual exhibition and auction fundraiser.</p><h3 id="h-future" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">FUTURE 🍃</h3><p><em>The Digital Diaspora</em> marked two inflection points for Mint Fund’s future: providing support for large-scale community-organized efforts, and collecting and preserving NFTs.</p><p>In the rapidly shifting and emergent space of NFTs, we are also evolving to further our mission of supporting and uplifting underrepresented creatives. We are proud to fund and support initiatives like <em>The Digital Diaspora</em> and look forward to utilizing the treasury for like-minded projects in the future. By participating in auctions and collecting <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://foundation.app/@blacksneakers/double-vision-47755"><em>Double Vision</em></a> by <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/BLACKKSNEAKERS">BLACKSNEAKERS</a>, we want to permanently record this moment in time and double down on our support for creators and initiatives that are pushing culture forward.</p><p>We will continue to onboard batches, but are now opening up applications for group shows and larger-initiatives to have access to Mint Fund’s treasury. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://forms.gle/skWBVwjad5Fn5np99">Apply here</a>.</p><h3 id="h-mint-fund-mission-statement" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">MINT FUND MISSION STATEMENT 🍃</h3><p>Mint Fund is a community dedicated to uplifting, supporting, and creating the next generation of global talent through NFTs. Mint Fund&apos;s goal is to create frictionless support for cultural communities to position their creatives for artistic success, longevity and becoming influential tastemakers in their own right.</p><p>By changing the state of play, we positively impact creativity, give larger agency for cultural communities to make their best works, leave rich histories for those who come after us, and build toward a more inclusive, equitable, and sustainable future.</p><p>themint.fund twitter.com/themintfund</p>]]></content:encoded>
            <author>thisiscarlos@newsletter.paragraph.com (Mint Fund)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/2b698637d01f51604dde8ac89443c8ef90f5d847a258e832bd7f8d618e47593d.png" length="0" type="image/png"/>
        </item>
        <item>
            <title><![CDATA[Introducing Mint Funds Recap Series - Batch 01 + NFT Auction]]></title>
            <link>https://paragraph.com/@thisiscarlos/introducing-mint-funds-recap-series-batch-01-nft-auction</link>
            <guid>iGwtCSAlMquKN7QxZDcU</guid>
            <pubDate>Wed, 05 May 2021 10:41:00 GMT</pubDate>
            <description><![CDATA[Update: A special thank you to David for winning the auction and for supporting this initiative. If you are one of 14 artists that minted on Mint Fund Batch 01, or $BOUNTY holder, you can claim your split below. A full breakdown of the split allocations can be found here. Mint Fund Recap Series - Batch 01On February 28th, we unveiled our first 35 artists. After two weeks of onboarding, planning, and networking, we knew it was time to mint. We instituted the “Round” method of minting works in ...]]></description>
            <content:encoded><![CDATA[<p><em>Update: A special thank you to </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/dave4506"><em>David</em></a><em> for winning the auction and for supporting this initiative. If you are one of 14 artists that minted on Mint Fund Batch 01, or $BOUNTY holder, you can claim your split below. A full breakdown of the split allocations can be found </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.google.com/spreadsheets/d/1TurnDk8wuCgNA2FYY0PeJGV0cQ2TiZloxkGz-32T9xc/edit?usp=sharing"><em>here.</em></a></p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0x32d3d3E3f45AE4594e9490Fab65025C928925D84">Mint Fund Recap Series - Batch 01</a></p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/2a45818ac04ce296a9d0d7edca66bf3f1c28ff072749ca490cd981de7ff1b162.jpg" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><p>On February 28th, we <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/themintfund/status/1365813777929756674">unveiled</a> our first 35 artists. After two weeks of onboarding, planning, and networking, we knew it was time to mint. We instituted the “Round” method of minting works in groups every Wednesday and Saturday. To date, 14 of those artists have successfully minted and released their first NFTs out into the world. This post serves as a highlight and reference to memorialize the group that started it all.</p><p><strong>Key Stats</strong></p><p>14 Artists From Argentina to Indonesia (Representing 6 Countries) 2 Workshops (Featuring Cooper Turley and Osinachi) 2 Weeks 4 Rounds</p><p><strong>Artists</strong></p><p>✺ <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/eddingtonagain">Eddington Again</a> ✺ <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/t0ndji">Tondji</a> ✺ <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/cy_tone">Cy Tone</a> ✺ <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/knnylrty">Kenneth Lartey</a> ✺ <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/RIMBAWANGERILYA">Rimbawan Gerilya</a> ✺ <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/ravivasavan">Ravi Vasavan</a> ✺ <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/niallashley_">Niall Ashley</a> ✺ <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/skykawano">Sky Kawano</a> ✺ <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/tigrisli">Tigris</a> ✺ <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/_acarimo">Baran Acar</a> ✺ <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/occult3d">Ikaro Cavalcante</a> ✺ <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/maggiemolinari">Magdalena Molinari</a> ✺ <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/artofdela">Christopher de la Guardia / Dela</a> ✺ <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/benmakgetlane">Ben Makgetlane</a></p><h2 id="h-what-we-learned" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">What We Learned</h2><p>During the onboarding &amp; minting process, We recognized a few things:</p><blockquote><p>Not everyone&apos;s NFT will sell immediately; Artists need more than just one stipend to mint creative works; Not every artist will mint in a specific timeframe.</p></blockquote><p>To accommodate this, and to celebrate all of our artists, we are experimenting with <strong>$RECAP NFTs</strong> — a special 1/1 gif that cycles through the artwork of our batch groups that will be auctioned off with the proceeds being split among each artist of that batch group, $BOUNTY holders, $BOUNTY NFT Auction Winner and Mint Fund DAO (a total of 47 recipients).</p><p>To do this, we are deploying Mint Fund&apos;s crowdfunded <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mint.mirror.xyz/mDws2xGmJCq55ehGDdcv8tGDCpSd_c_CfeqhexiKSqU">Reserve Auction ($BOUNTY)</a>, and using Mirror recently introduced Splits Auction feature.</p><p>We believe in redistribution at every level, and with our $RECAP series, we can ensure that artists can earn ETH so they can continue minting.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0xabEFBc9fD2F806065b4f3C237d4b59D9A97Bcac7">Token #3051</a></p><p><strong>Split Allocation</strong></p><p>14 Batch 01 Artists / 80% 31 $BOUNTY Holders / 10% $BOUNTY NFT Auction Winner / 5% MintFund DAO / 5%</p><p><em>The Final distribution percentage was rounded for simplicity. A full breakdown of the Batch 01 Split allocations can be found </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://docs.google.com/spreadsheets/d/1TurnDk8wuCgNA2FYY0PeJGV0cQ2TiZloxkGz-32T9xc/edit?usp=sharing"><em>here.</em></a></p><hr><h2 id="h-the-mints" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The Mints</h2><h3 id="h-round-one" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Round One</h3><p><strong>FIRST MINT ✺</strong> Vocalist and composer from Los Angeles, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/eddingtonagain">Eddington Again</a> style ranges from classic soul, R&amp;B bops, to experimental pop. <strong>Petrify:</strong> A visual collaboration with 011668. Sounds co-produced with Otxoa and Jerry Andrews.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="">NFT</a></p><p><strong>SECOND MINT ✺</strong> Deaf artist and designer, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/ravivasavan">Ravi Vasavan</a> lives, bakes, bikes, camps, sings, and loves in London. <strong>Ficus 1/3:</strong> After experiencing birth, existence, and death up-close, this work is reminder that we are in a constant state of rebirth.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="">NFT</a></p><p><strong>THIRD MINT ✺</strong> <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/knnylrty">Kenneth Lartey</a> is a filmmaker and DJ. <strong>Some Friend You Are:</strong> An unreleased work designed for legendary underground DMV artist Sir EU, originally used for one of his musical projects.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="">NFT</a></p><p><strong>FOURTH MINT ✺</strong> <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/cy_tone">Cy Tone</a> <strong>DISORDER:</strong> Inhale / Exhale / Inspire / Create &quot;All Content is Copyright-free, everyone can use it as he/she/they prefer, we don&apos;t give a [ˈfʌk]. Culture is a human heritage not a mass production tool.&quot; “test, experiments, results”</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="">NFT</a></p><p><strong>FIFTH MINT ✺</strong> Beninese 3D artist, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/t0ndji">Tondji</a> style mixes Afrofuturism and conceptual art. <strong>Na Hangbé:</strong> Tondji tells the story of Tassi Hangbé, the queen of the kingdom of Dahomey. Her history will not go untold any longer.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="">NFT</a></p><p><strong>SIXTH MINT ✺</strong> <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/RIMBAWANGERILYA">Rimbawan Gerilya</a> is a visual artist and VJ from S.E.Asia working mostly with the music scene. <strong>GMO Utility Trike:</strong> In 2020, Gabber Modus Operandi live gigs were cancelled. They brought the party to the masses through cyberspace with the help of Siko Setyanto, a dancer, and Rimbawan Gerilya, an animator.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="">NFT</a></p><hr><h3 id="h-round-two" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Round Two</h3><p><strong>FIRST MINT ✺</strong> <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/niallashley_">Niall Ashley</a> is a self-taught painter from Bristol, England. <strong>G-check:</strong> A depiction of roadmen in a non-binary context, questioning how we assume gender and overt masculinity.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="">NFT</a></p><p><strong>SECOND MINT ✺</strong> <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/tigrisli">Tigris</a> is 3D Motion Designer &amp; Creative Technologist exploring emotional intelligence and biometrics. Curves as Deep as the Ocean: unveils the depth of waves that uncover serenity and peace within one’s body of the ocean.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="">NFT</a></p><p><strong>THIRD MINT ✺</strong> Japanese/British artist <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/skykawano">Sky Kawano</a> specializes in mixed-media motion that captures chaos and ephemerality. <strong>TENACITY OF LIFE:</strong> A mixed-media digital poster inspired by the tenacity of ants as aspirational spirit animals.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="">NFT</a></p><hr><h3 id="h-round-three" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Round Three</h3><p><strong>FIRST MINT ✺</strong> <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/occult3d">Ikaro Cavalcante</a> is a Brazilian Artist focused on CGI and Artmedia. <strong>Flowers of non-death:</strong> is the artists genesis piece and the first work in the &quot;Blood Connection&quot; series of three pieces.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="">NFT</a></p><p><strong>SECOND MINT ✺</strong> <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/_acarimo">Baran Acar</a> is a digital artist and student based in Eskisehir, Turkey. <strong>Caution:</strong> 3D illustration. 3000x3750</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="">NFT</a></p><hr><h3 id="h-round-four" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Round Four</h3><p><strong>FIRST MINT ✺</strong> <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/maggiemolinari">Magdalena Molinari</a> is an Argentinian architect and artist. <strong>&quot;IRIS N1&quot;</strong> - A series of abstract video pieces where the colors from the sky and the circular movements are combined to create &quot;skylike&quot; sensations.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="">NFT</a></p><p><strong>SECOND MINT ✺</strong> <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/artofdela">Christopher de la Guardia / Dela</a> is an artist based out of Miami, Florida <strong>&quot;Beauty In Destruction&quot;</strong> is about getting rid of the old world and creating a new one. We are on the cusp of digital freedom.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="">NFT</a></p><p><strong>THIRD MINT ✺</strong> <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/benmakgetlane">Ben Makgetlane</a> is a minimalist illustrator &amp; graphic designer based in Pretoria, South Africa. <strong>Take Care:</strong> &quot;Part of a series where i reimagine some of my favorite album covers using my minimalist illustration style&quot;.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://rarible.com/token/0xd07dc4262bcdbf85190c01c996b4c06a461d2430:442193:0x1c9fefb363361b303f9ab3cb08395cf863461784">https://rarible.com/token/0xd07dc4262bcdbf85190c01c996b4c06a461d2430:442193:0x1c9fefb363361b303f9ab3cb08395cf863461784</a></p><hr><h2 id="h-whats-next" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">What’s Next?</h2><p>Get familiar with the MintFund artist community by joining our discord, or following us on twitter. We are in the process of minting our second batch of artists and currently curating our third and fourth groups. We are actively looking for community moderators in multiple timezones, efforts in localizing resources in most common languages, and programming for our growing artist body.</p><p><strong>MINT FUND NFT GALLERY + CURATION SPACE</strong> As we work with each creator to mint their first NFTs, we’ll be adding their work to our site. This is a space to nurture and highlight the artists we work with. A place to give them all some extra shine. In addition, we will enable auctions using the $BOUNTY auction method to help our artists sell their first NFTs. This also grants curators an opportunity to submit works for MintFund $BOUNTY holders to collect a % of the auction fee from curated sales.</p><p>Stay tuned. SOON™</p><h2 id="h-about-mintfund" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">About MintFund</h2><p>MintFund is a community project created with the sole purpose to build a support network for artists interested in bringing their art into the world of <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://linda.mirror.xyz/df649d61efb92c910464a4e74ae213c4cab150b9cbcc4b7fb6090fc77881a95d">NFTs</a>/<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://cryptomedia.wtf/">cryptomedia</a>.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://themint.fund/">MintFund</a> provides artists with the funds to mint NFTs (known as gas costs), and offers guidance, mentorship and advice for the growing community of cryptomedia artists. MintFund is accessible to all artists and we prioritize BIPOC and LGTBQIA+ artists, especially outside of North America and the European Union.</p>]]></content:encoded>
            <author>thisiscarlos@newsletter.paragraph.com (Mint Fund)</author>
        </item>
        <item>
            <title><![CDATA[$BOUNTY: Building Permissionless Reserve Auctions for NFTs]]></title>
            <link>https://paragraph.com/@thisiscarlos/bounty-building-permissionless-reserve-auctions-for-nfts</link>
            <guid>68w4Hf3HaMG7yUmvEhN9</guid>
            <pubDate>Sat, 06 Mar 2021 02:08:36 GMT</pubDate>
            <description><![CDATA[Update: $BOUNTY Crowdfund has been fully funded. Thank you to all contributors and supporters. We are currently coordinating a candidate search to hire the bounty developer and we are grateful to have the Mirror team assisting with technical evaluation of candidates and submissions. If you think you are the right candidate please email us at themintfund@gmail.com.We&apos;re excited to announce a new experiment. We&apos;re using crypto to crowdfund a bounty to bring reserve auction functionali...]]></description>
            <content:encoded><![CDATA[<p><em>Update: $BOUNTY Crowdfund has been fully funded. Thank you to all contributors and supporters. We are currently coordinating a candidate search to hire the bounty developer and we are grateful to have the Mirror team assisting with technical evaluation of candidates and submissions.</em></p><p><em>If you think you are the right candidate please email us at </em><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="mailto:themintfund@gmail.com"><em>themintfund@gmail.com</em></a><em>.</em></p><hr><p>We&apos;re excited to announce a new experiment. We&apos;re using crypto to crowdfund a bounty to bring reserve auction functionality to MintFund.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0x117f51cd7692649c794d841d6d561261b9769a7b">Crowdfund Embed</a></p><p>Reserve auctions have seen significant traction as a mechanism for selling NFTs, but they have typically been limited to proprietary marketplaces. MintFund&apos;s mission is to expand opportunity for artists hoping to break out into the crypto art scene. Part of that mission is providing open access to best-in-class tools that artists need to thrive.</p><p>Today, we&apos;re launching a Mirror crowdfund contract to create a bounty for a talented Solidity developer to implement a robust and completely permissionless version of reserve auctions for NFTs. Unlike the previous $ESSAY and $VALUE campaigns, the output of this bounty will be <em>written code</em> instead of <em>written text</em>.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/741ae88e84880fcb18b130984518919b51c6bc6a1e6a0375df0ac4debb218f0c.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><h2 id="h-how-it-works" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">How it Works</h2><ul><li><p>The bounty crowdfund has a hard-cap of 7 ETH</p></li><li><p>Backers can send ETH to the crowdfund in exchange for $BOUNTY tokens</p></li><li><p>If the funding target is hit, MintFund will hire a talented Solidity developer from the Ethereum community to implement the fully open-source smart contracts</p></li><li><p>The codebase will be posted on Mirror as permanent, public data and mirrored on GitHub</p></li><li><p>The codebase will be minted as an NFT on the Zora protocol, representing the first digitally unique and collectible codebase</p></li><li><p>The final code will be deployed on mainnet and used to auction off this NFT</p></li><li><p>If the NFT is sold, ETH will accrue to $BOUNTY tokens</p></li><li><p>$BOUNTY tokens can be traded like any ERC-20 token, or redeemed for underlying ETH</p></li><li><p>Participants in the crowdfund will be embedded in the code base forever as the supporters who made it possible</p></li></ul><p>25% of <strong>$BOUNTY</strong> tokens will be retained by MintFund and 5% will go to the developer, the remaining 70% will be distributed to <strong>$BOUNTY</strong> backers.</p><h2 id="h-the-power-of-reserve-auctions" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The Power of Reserve Auctions</h2><p>Since the advent of NFT transactions, reserve auctions have seen significant traction as a mechanism for selling NFTs. The hype, the intrigue, and the status involved in a singular moment in time where everyone&apos;s eyes are fixed upon a particular drop provides a narrative for all the artists who have sold work. Reserve auctions become a tool to connect both artist and collector, a story for communities to rally around—news to be told to the masses. They are a spotlight and turning point of an artist&apos;s career in the cryptosphere and we want to bring it to every artist. Reserve auctions started on SuperRare and have moved to other marketplaces such as Nifty Gateway. However, with a platform like Zora the permissionless nature of the zNFT smart contracts allows anyone to extend the bidding protocol, making it a great fit to add a reserve auction extension.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/c778ce292c0bac373084b081833d568dfcbeacd34bb3e157970133c011d3d6be.png" alt="" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="hide-figcaption"></figcaption></figure><h2 id="h-why" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Why?</h2><p>We believe that building the tools for creatives to push their best works unfettered by cost, access, and exposure yields the next generation of mind bending work and an ever growing community of shared talent, spirit, and wealth. MintFund is dedicated to giving all communities, with emphasis to BIPOC &amp; LGBTQIA folks, the means to take cryptomedia / NFTs by storm and move culture along with them. We recognize that the key to achieving our goal of launching life-changing creative careers on the blockchain is threefold:</p><ol><li><p>Cover gas fees to enable access to the tools to participate in the NFT ecosystem</p></li><li><p>Create tools for artists to increase their exposure and connect with collectors</p></li><li><p>Build a success-based funding source to ensure MintFund can continue to sustain its work without relying on donations</p></li></ol><h2 id="h-about-the-bounty-scope-of-work" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">About the Bounty / Scope of Work</h2><h3 id="h-requirements" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Requirements</h3><ol><li><p>Any owner of a Zora NFT should be able to permissionlessly kick off an auction. Kicking off an auction should not require deploying a new contract.</p></li><li><p>The auction should be configurable such that its constructor accepts (at minimum) two parameters</p><ol><li><p>Reserve Price (amount + currency address)</p></li><li><p>Auction Duration (ex. 24 hours)</p></li></ol></li><li><p>The auction should be binding, such that at the end of the Auction the highest bid is automatically accepted and the NFT is transferred to the highest bid&apos;s recipient address.</p></li><li><p>Bids on the auction are made in ETH and should be locked in escrow for the duration of the auction, but automatically returned if a higher bid is made.</p></li><li><p>If the Auction has not received a bid higher than the reserve price, the original owner can withdraw the NFT. Once a bid has been placed, the NFT is locked until the auction is completed.</p></li><li><p>Relevant events are emitted for each of the major function calls.</p></li></ol><h3 id="h-user-story" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">User Story</h3><ol><li><p>Alice grants permission to transfer the NFT to the auction contract</p></li><li><p>Calls <code>createAuction</code> with the tokenId, reservePrice, and creator address. This transfers the NFT to the contract.</p></li><li><p>Craig submits a bid below the reserve price, but it reverts</p></li><li><p>Bob calls <code>createBid</code> with a bid that is higher than the reserve price, which sets the currentBid to his address and amount.’ The contract receives Bob&apos;s ETH and holds it in escrow.</p></li><li><p>Craig calls <code>endAuction</code>, but it reverts because the current block time doesn&apos;t exceed the Auction&apos;s end-time</p></li><li><p>Danny calls <code>createBid</code>, which replaces Bob&apos;s bid as the current bid. Bob is refunded the ETH that he sent into the contract previously.</p></li><li><p>No new bids come in, and the current block time exceeds the Auction&apos;s end-time</p></li><li><p>Danny calls <code>endAuction</code>, which transfers the NFT to her address. Runs a payout according to the Zora market&apos;s BidShare data to send funds to the creator.</p></li></ol><h3 id="h-high-level-implementation-ideas" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">High Level Implementation Ideas</h3><p>Each <strong><em>Auction</em></strong> is described by the following data:</p><ul><li><p><strong>tokenId</strong>: The Zora market token ID for the NFT</p></li><li><p><strong>duration</strong>: The number seconds that the auction runs for after the first bid, e.g. 24 hours, which is extended with each new bid</p></li><li><p><strong>firstBidTime</strong>: Unix timestamp of the first bid</p></li><li><p><strong>reservePrice</strong>: Allow the creator to set a reserve price, below which the auction will not settle and the NFT is returned</p></li><li><p><strong>creator</strong>: Keep track of the creator in case we need to return the NFT. A single auction contract keeps track of multiple auctions, via a simple mapping of <strong>tokenId</strong> to <strong>Auction.</strong> This contract also keeps track of the current <strong><em>Bids</em></strong> for each <strong>Auction</strong>. Bids are mapped from tokenId to bid. A bid is composed of:</p></li><li><p>Bidder</p></li><li><p>Amount The contract has the following functionality:</p></li></ul><ul><li><p><strong>createAuction</strong>(uint tokenId, uint reservePrice, address creator)</p><ul><li><p>Instantiates an <strong>Auction</strong> using the given parameters, and transfers the NFT to the contract itself, <em>so that the contract controls the NFT</em></p></li><li><p><strong>createBid</strong> (uint amount, uint tokenId) external payable</p></li><li><p>Checks that amount is greater than the current bid, and greater than the reserve price</p></li><li><p>Check that the msg.value == amount</p></li><li><p>&quot;Start the clock&quot; and increases the duration by</p></li><li><p>Refund the previous bid</p></li></ul></li><li><p><strong>endAuction</strong>(uint tokenId)</p><ul><li><p>Checks that the current time is greater than the end time</p></li><li><p>Transfers the NFT to the highest bidder, if there is one and is greater-or-equal the reserve price, else transfers back to the creator</p></li></ul></li><li><p><strong>cancelAuction</strong>(uint tokenId)</p><ul><li><p>Can only be called by the creator</p></li><li><p>Checks if there are no bids</p></li><li><p>Transfers the NFT back to the creator</p></li></ul></li></ul><h2 id="h-whats-next" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">What&apos;s Next?</h2><p>This initiative, if executed successfully, will not only give new rise to creatives, but create a pipeline to mint their NFTs and expose them to the greater communities that have rallied around MintFund and our growing list of contributors and partners.</p><h2 id="h-about-mint-fund" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">About Mint Fund.</h2><p>MintFund is a community project created with the sole purpose to build a support network for artists interested in bringing their art into the world of<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://linda.mirror.xyz/df649d61efb92c910464a4e74ae213c4cab150b9cbcc4b7fb6090fc77881a95d"> NFTs</a>/<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://cryptomedia.wtf/">cryptomedia</a>. MintFund provides artists with the funds to mint NFTs (known as<a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://kb.myetherwallet.com/en/transactions/what-is-gas/"> gas costs</a>), and offers guidance, mentorship and advice for the growing community of cryptomedia artists. MintFund is accessible to all artists and we prioritize BIPOC and LGTBQIA+ artists, especially outside of North America and the European Union.</p>]]></content:encoded>
            <author>thisiscarlos@newsletter.paragraph.com (Mint Fund)</author>
        </item>
        <item>
            <title><![CDATA[The Auction: $BOUNTY Permissionless Reserve Auctions for NFTs]]></title>
            <link>https://paragraph.com/@thisiscarlos/the-auction-bounty-permissionless-reserve-auctions-for-nfts</link>
            <guid>ulIzMfhBbByNImCRweou</guid>
            <pubDate>Sat, 06 Mar 2021 00:51:09 GMT</pubDate>
            <description><![CDATA[Two weeks ago we asked our community to help bring open source NFT reserve auction functionality to the world. Today, we’re auctioning off that code (with the code!) as a 1/1 NFT. Token #1522 Reserve Auctions are a mechanism for selling NFTs widely credited with creating more value for artists, but they have typically been limited to proprietary marketplaces. We wanted to bring a robust and completely permissionless version to anyone who wants to use it. By open-sourcing this implementation o...]]></description>
            <content:encoded><![CDATA[<p>Two weeks ago we asked our community to help bring open source NFT reserve auction functionality to the world. Today, we’re auctioning off that code (with the code!) as a 1/1 NFT.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://etherscan.io/address/0xabEFBc9fD2F806065b4f3C237d4b59D9A97Bcac7">Token #1522</a></p><p>Reserve Auctions are a mechanism for selling NFTs widely credited with creating more value for artists, but they have typically been limited to proprietary marketplaces. We wanted to bring a robust and completely permissionless version to anyone who wants to use it.</p><p>By open-sourcing this implementation of a reserve auction, we hope to directly empower creators by giving them the tools they need to freely sell their work, on their terms.</p><p>In just over an hour we raised 7 ETH from 40 backers, who in turn received $BOUNTY tokens representing their patronage of this community-focused initiative.</p><p>What made this approach to crowdfunding even more unique is that the resulting smart contract code would be made open source, minted as an NFT and then auctioned off, with the value of the NFT flowing back to $BOUNTY holders. See all the details of $BOUNTY in the original crowdfund post.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://mint.mirror.xyz/mDws2xGmJCq55ehGDdcv8tGDCpSd_c_CfeqhexiKSqU">https://mint.mirror.xyz/mDws2xGmJCq55ehGDdcv8tGDCpSd_c_CfeqhexiKSqU</a></p><p>Today we’re excited to announce that <strong>$BOUNTY: The First Tokenized, Crowdfunded Smart Contract</strong> is officially minted and up for auction.</p><p>Importantly, this NFT is being auctioned using the auction code embedded in the NFT itself. Cue inception memes</p><p>At the end of this post is the initial commit of the smart contract code. Since this post is minted as an NFT, this code is immortalized as part of it. Owning this NFT means owning a 1/1 collectible representing the initial commit of the open-source implementation of reserve auctions, which will live on Mint Fund’s <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/mintfund/reserve-auction/blob/main/contracts/ReserveAuctionV3.sol">GitHub repo</a>.</p><h2 id="h-the-process" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>The Process</strong></h2><p>Initially Mint Fund created a bounty via a Mirror crowdfund to fund the development of an open source version of reserve auction smart contract, which was <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/okwme/core/blob/master/contracts/ReserveAuction.sol">fulfilled</a> by Solidity developer <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://twitter.com/billyrennekamp">Billy Rennekamp</a>.</p><p>The Mirror team took this code and improved on it until it was production ready. The <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/mintfund/reserve-auction/blob/main/contracts/ReserveAuctionV3.sol">final version</a> (included at the bottom of this post) was used to auction off two NFTs on April 1st, 2021 for a combined value of 26.1 ETH.</p><p>In a testament to open source collaboration and smart contract composability, this auction code builds on top of the open Zora NFT protocol and honors the creator share of zNFTs.</p><p>Furthermore, it also supports specifying a curator fee for facilitating the auction. This enables organizations like Mint Fund or other galleries a potential business model to sustain their operations .</p><p><em>We’d like to credit projects that have pioneered and improved on the reserve auction mechanism and experience, such as SuperRare and Foundation.</em></p><h2 id="h-next-steps" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Next Steps</h2><p>The <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://zora.co/">Zora</a> team is working on adding functionality to the reserve auction code that more fully utilizes the power of the Zora Protocol. Zora&apos;s update will support bidding in any ERC20 token, and honoring the sell-on-share fee that users will know from the Zora interface.</p><h2 id="h-what-dollarbounty-holders-get" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>What $BOUNTY holders get.</strong></h2><p>Following the initial crowdfund, $BOUNTY tokens were distributed to all backers. 25% of $BOUNTY tokens were retained by MintFund, with 5% allocated to the developer implementing the bounty. The remaining 70% were distributed to the $BOUNTY crowdfund backers.</p><p>$BOUNTY represents the shared value created through the crowdfunding, development and auction of the NFT. If the $BOUNTY NFT sells, the proceeds will go to the crowdfund and thereby the $BOUNTY backers. Holding $BOUNTY tokens also grant one access to a private channel on the Mint Fund discord only accessible by those holding at least 15 $BOUNTY.</p><h2 id="h-the-future-of-public-goods-funding" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">The future of public goods funding</h2><p>As far as we know, this has been the first experiment to combine crypto-native crowdfunding with public works minted as an NFT. Recently, Vitalik <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://vitalik.ca/general/2021/03/23/legitimacy.html">wrote</a> about the potential to use token incentives, NFTs, and decentralized governance to fund public goods like scientific research, local journalism, and poverty relief.</p><p>We believe this new model has the opportunity to create win-win scenarios for all parties involved: backers, creators, developers, collectors, and end-consumers of these funded projects.</p><p>MintFund hopes to see others experiment with this model and push the boundaries of how creative work is financed, produced, and owned using the internet and crypto-native tools.</p><h2 id="h-the-code" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0"><strong>The Code</strong></h2><pre data-type="codeBlock" text="// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.6.8;
pragma experimental ABIEncoderV2;

// OpenZeppelin library for performing math operations without overflows.
import {SafeMath} from &quot;@openzeppelin/contracts/math/SafeMath.sol&quot;;
// OpenZeppelin security library for preventing reentrancy attacks.
import {
    ReentrancyGuard
} from &quot;@openzeppelin/contracts/utils/ReentrancyGuard.sol&quot;;
// For interacting with Zora&apos;s Market contract.
import {IMarket} from &quot;./interfaces/IMarket.sol&quot;;
// For checking `supportsInterface`.
import {IERC165} from &quot;@openzeppelin/contracts/introspection/IERC165.sol&quot;;
// For interacting with NFT tokens.
import {IERC721} from &quot;@openzeppelin/contracts/token/ERC721/IERC721.sol&quot;;

contract IMediaModified {
    mapping(uint256 =&gt; address) public tokenCreators;
    address public marketContract;
}

interface IWETH {
    function deposit() external payable;

    function transfer(address to, uint256 value) external returns (bool);
}

contract ReserveAuctionV3 is ReentrancyGuard {
    // Use OpenZeppelin&apos;s SafeMath library to prevent overflows.
    using SafeMath for uint256;

    // ============ Constants ============

    // The minimum amount of time left in an auction after a new bid is created; 15 min.
    uint16 public constant TIME_BUFFER = 900;
    // The ETH needed above the current bid for a new bid to be valid; 0.001 ETH.
    uint8 public constant MIN_BID_INCREMENT_PERCENT = 10;
    // Interface constant for ERC721, to check values in constructor.
    bytes4 private constant ERC721_INTERFACE_ID = 0x80ac58cd;
    // Allows external read `getVersion()` to return a version for the auction.
    uint256 private constant RESERVE_AUCTION_VERSION = 1;

    // ============ Immutable Storage ============

    // The address of the ERC721 contract for tokens auctioned via this contract.
    address public immutable nftContract;
    // The address of the WETH contract, so that ETH can be transferred via
    // WETH if native ETH transfers fail.
    address public immutable wethAddress;
    // The address that initially is able to recover assets.
    address public immutable adminRecoveryAddress;

    // ============ Mutable Storage ============

    /**
     * To start, there will be an admin account that can recover funds
     * if anything goes wrong. Later, this public flag will be irrevocably
     * set to false, removing any admin privileges forever.
     *
     * To check if admin recovery is enabled, call the public function `adminRecoveryEnabled()`.
     */
    bool private _adminRecoveryEnabled;
    /**
     * The account `adminRecoveryAddress` can also pause the contracts
     * while _adminRecoveryEnabled is enabled. This prevents people from using
     * the contract if there is a known problem with it.
     */
    bool private _paused;

    // A mapping of all of the auctions currently running.
    mapping(uint256 =&gt; Auction) public auctions;

    // ============ Structs ============

    struct Auction {
        // The value of the current highest bid.
        uint256 amount;
        // The amount of time that the auction should run for,
        // after the first bid was made.
        uint256 duration;
        // The time of the first bid.
        uint256 firstBidTime;
        // The minimum price of the first bid.
        uint256 reservePrice;
        uint8 curatorFeePercent;
        // The address of the auction&apos;s curator. The curator
        // can cancel the auction if it hasn&apos;t had a bid yet.
        address curator;
        // The address of the current highest bid.
        address payable bidder;
        // The address that should receive funds once the NFT is sold.
        address payable fundsRecipient;
    }

    // ============ Events ============

    // All of the details of a new auction,
    // with an index created for the tokenId.
    event AuctionCreated(
        uint256 indexed tokenId,
        address nftContractAddress,
        uint256 duration,
        uint256 reservePrice,
        uint8 curatorFeePercent,
        address curator,
        address fundsRecipient
    );

    // All of the details of a new bid,
    // with an index created for the tokenId.
    event AuctionBid(
        uint256 indexed tokenId,
        address nftContractAddress,
        address sender,
        uint256 value
    );

    // All of the details of an auction&apos;s cancelation,
    // with an index created for the tokenId.
    event AuctionCanceled(
        uint256 indexed tokenId,
        address nftContractAddress,
        address curator
    );

    // All of the details of an auction&apos;s close,
    // with an index created for the tokenId.
    event AuctionEnded(
        uint256 indexed tokenId,
        address nftContractAddress,
        address curator,
        address winner,
        uint256 amount,
        address nftCreator,
        address payable fundsRecipient
    );

    // When the curator recevies fees, emit the details including the amount,
    // with an index created for the tokenId.
    event CuratorFeePercentTransfer(
        uint256 indexed tokenId,
        address curator,
        uint256 amount
    );

    // Emitted in the case that the contract is paused.
    event Paused(address account);
    // Emitted when the contract is unpaused.
    event Unpaused(address account);

    // ============ Modifiers ============

    // Reverts if the sender is not admin, or admin
    // functionality has been turned off.
    modifier onlyAdminRecovery() {
        require(
            // The sender must be the admin address, and
            // adminRecovery must be set to true.
            adminRecoveryAddress == msg.sender &amp;&amp; adminRecoveryEnabled(),
            &quot;Caller does not have admin privileges&quot;
        );
        _;
    }

    // Reverts if the sender is not the auction&apos;s curator.
    modifier onlyCurator(uint256 tokenId) {
        require(
            auctions[tokenId].curator == msg.sender,
            &quot;Can only be called by auction curator&quot;
        );
        _;
    }

    // Reverts if the contract is paused.
    modifier whenNotPaused() {
        require(!paused(), &quot;Contract is paused&quot;);
        _;
    }

    // Reverts if the auction does not exist.
    modifier auctionExists(uint256 tokenId) {
        // The auction exists if the curator is not null.
        require(!auctionCuratorIsNull(tokenId), &quot;Auction doesn&apos;t exist&quot;);
        _;
    }

    // Reverts if the auction exists.
    modifier auctionNonExistant(uint256 tokenId) {
        // The auction does not exist if the curator is null.
        require(auctionCuratorIsNull(tokenId), &quot;Auction already exists&quot;);
        _;
    }

    // Reverts if the auction is expired.
    modifier auctionNotExpired(uint256 tokenId) {
        require(
            // Auction is not expired if there&apos;s never been a bid, or if the
            // current time is less than the time at which the auction ends.
            auctions[tokenId].firstBidTime == 0 ||
                block.timestamp &lt; auctionEnds(tokenId),
            &quot;Auction expired&quot;
        );
        _;
    }

    // Reverts if the auction is not complete.
    // Auction is complete if there was a bid, and the time has run out.
    modifier auctionComplete(uint256 tokenId) {
        require(
            // Auction is complete if there has been a bid, and the current time
            // is greater than the auction&apos;s end time.
            auctions[tokenId].firstBidTime &gt; 0 &amp;&amp;
                block.timestamp &gt;= auctionEnds(tokenId),
            &quot;Auction hasn&apos;t completed&quot;
        );
        _;
    }

    // ============ Constructor ============

    constructor(
        address nftContract_,
        address wethAddress_,
        address adminRecoveryAddress_
    ) public {
        require(
            IERC165(nftContract_).supportsInterface(ERC721_INTERFACE_ID),
            &quot;Contract at nftContract_ address does not support NFT interface&quot;
        );
        // Initialize immutable memory.
        nftContract = nftContract_;
        wethAddress = wethAddress_;
        adminRecoveryAddress = adminRecoveryAddress_;
        // Initialize mutable memory.
        _paused = false;
        _adminRecoveryEnabled = true;
    }

    // ============ Create Auction ============

    function createAuction(
        uint256 tokenId,
        uint256 duration,
        uint256 reservePrice,
        uint8 curatorFeePercent,
        address curator,
        address payable fundsRecipient
    ) external nonReentrant whenNotPaused auctionNonExistant(tokenId) {
        // Check basic input requirements are reasonable.
        require(curator != address(0));
        require(fundsRecipient != address(0));
        require(curatorFeePercent &lt; 100, &quot;Curator fee should be &lt; 100&quot;);
        // Initialize the auction details, including null values.
        auctions[tokenId] = Auction({
            duration: duration,
            reservePrice: reservePrice,
            curatorFeePercent: curatorFeePercent,
            curator: curator,
            fundsRecipient: fundsRecipient,
            amount: 0,
            firstBidTime: 0,
            bidder: address(0)
        });
        // Transfer the NFT into this auction contract, from whoever owns it.
        IERC721(nftContract).transferFrom(
            IERC721(nftContract).ownerOf(tokenId),
            address(this),
            tokenId
        );
        // Emit an event describing the new auction.
        emit AuctionCreated(
            tokenId,
            nftContract,
            duration,
            reservePrice,
            curatorFeePercent,
            curator,
            fundsRecipient
        );
    }

    // ============ Create Bid ============

    function createBid(uint256 tokenId, uint256 amount)
        externalpayablenonReentrant
        whenNotPaused
        auctionExists(tokenId)
        auctionNotExpired(tokenId)
    {
        // Validate that the user&apos;s expected bid value matches the ETH deposit.
        require(amount == msg.value, &quot;Amount doesn&apos;t equal msg.value&quot;);
        require(amount &gt; 0, &quot;Amount must be greater than 0&quot;);
        // Check if the current bid amount is 0.
        if (auctions[tokenId].amount == 0) {
            // If so, it is the first bid.
            auctions[tokenId].firstBidTime = block.timestamp;
            // We only need to check if the bid matches reserve bid for the first bid,
            // since future checks will need to be higher than any previous bid.
            require(
                amount &gt;= auctions[tokenId].reservePrice,
                &quot;Must bid reservePrice or more&quot;
            );
        } else {
            // Check that the new bid is sufficiently higher than the previous bid, by
            // the percentage defined as MIN_BID_INCREMENT_PERCENT.
            require(
                amount &gt;=
                    auctions[tokenId].amount.add(
                        // Add 10% of the current bid to the current bid.
                        auctions[tokenId]
                            .amount
                            .mul(MIN_BID_INCREMENT_PERCENT)
                            .div(100)
                    ),
                &quot;Must bid more than last bid by MIN_BID_INCREMENT_PERCENT amount&quot;
            );

            // Refund the previous bidder.
            transferETHOrWETH(
                auctions[tokenId].bidder,
                auctions[tokenId].amount
            );
        }
        // Update the current auction.
        auctions[tokenId].amount = amount;
        auctions[tokenId].bidder = msg.sender;
        // Compare the auction&apos;s end time with the current time plus the 15 minute extension,
        // to see whether we&apos;re near the auctions end and should extend the auction.
        if (auctionEnds(tokenId) &lt; block.timestamp.add(TIME_BUFFER)) {
            // We add onto the duration whenever time increment is required, so
            // that the auctionEnds at the current time plus the buffer.
            auctions[tokenId].duration += block.timestamp.add(TIME_BUFFER).sub(
                auctionEnds(tokenId)
            );
        }
        // Emit the event that a bid has been made.
        emit AuctionBid(tokenId, nftContract, msg.sender, amount);
    }

    // ============ End Auction ============

    function endAuction(uint256 tokenId)
        externalnonReentrant
        whenNotPaused
        auctionComplete(tokenId)
    {
        // Store relevant auction data in memory for the life of this function.
        address winner = auctions[tokenId].bidder;
        uint256 amount = auctions[tokenId].amount;
        address curator = auctions[tokenId].curator;
        uint8 curatorFeePercent = auctions[tokenId].curatorFeePercent;
        address payable fundsRecipient = auctions[tokenId].fundsRecipient;
        // Remove all auction data for this token from storage.
        delete auctions[tokenId];
        // We don&apos;t use safeTransferFrom, to prevent reverts at this point,
        // which would break the auction.
        IERC721(nftContract).transferFrom(address(this), winner, tokenId);
        // First handle the curator&apos;s fee.
        if (curatorFeePercent &gt; 0) {
            // Determine the curator amount, which is some percent of the total.
            uint256 curatorAmount = amount.mul(curatorFeePercent).div(100);
            // Send it to the curator.
            transferETHOrWETH(curator, curatorAmount);
            // Subtract the curator amount from the total funds available
            // to send to the funds recipient and original NFT creator.
            amount = amount.sub(curatorAmount);
            // Emit the details of the transfer as an event.
            emit CuratorFeePercentTransfer(tokenId, curator, curatorAmount);
        }
        // Get the address of the original creator, so that we can split shares
        // if appropriate.
        address payable nftCreator =
            payable(
                address(IMediaModified(nftContract).tokenCreators(tokenId))
            );
        // If the creator and the recipient of the funds are the same
        // (and we expect this to be common), we can just do one transaction.
        if (nftCreator == fundsRecipient) {
            transferETHOrWETH(nftCreator, amount);
        } else {
            // Otherwise, we should determine the percent that goes to the creator.
            // Collect share data from Zora.
            uint256 creatorAmount =
                // Call the splitShare function on the market contract, which
                // takes in a Decimal and an amount.
                IMarket(IMediaModified(nftContract).marketContract())
                    .splitShare(
                    // Fetch the decimal from the BidShares data on the market.
                    IMarket(IMediaModified(nftContract).marketContract())
                        .bidSharesForToken(tokenId)
                        .creator,
                    // Specify the amount.
                    amount
                );
            // Send the creator&apos;s share to the creator.
            transferETHOrWETH(nftCreator, creatorAmount);
            // Send the remainder of the amount to the funds recipient.
            transferETHOrWETH(fundsRecipient, amount.sub(creatorAmount));
        }
        // Emit an event describing the end of the auction.
        emit AuctionEnded(
            tokenId,
            nftContract,
            curator,
            winner,
            amount,
            nftCreator,
            fundsRecipient
        );
    }

    // ============ Cancel Auction ============

    function cancelAuction(uint256 tokenId)
        externalnonReentrant
        auctionExists(tokenId)
        onlyCurator(tokenId)
    {
        // Check that there hasn&apos;t already been a bid for this NFT.
        require(
            uint256(auctions[tokenId].firstBidTime) == 0,
            &quot;Auction already started&quot;
        );
        // Pull the creator address before removing the auction.
        address curator = auctions[tokenId].curator;
        // Remove all data about the auction.
        delete auctions[tokenId];
        // Transfer the NFT back to the curator.
        IERC721(nftContract).transferFrom(address(this), curator, tokenId);
        // Emit an event describing that the auction has been canceled.
        emit AuctionCanceled(tokenId, nftContract, curator);
    }

    // ============ Admin Functions ============

    // Irrevocably turns off admin recovery.
    function turnOffAdminRecovery() external onlyAdminRecovery {
        _adminRecoveryEnabled = false;
    }

    function pauseContract() external onlyAdminRecovery {
        _paused = true;
        emit Paused(msg.sender);
    }

    function unpauseContract() external onlyAdminRecovery {
        _paused = false;
        emit Unpaused(msg.sender);
    }

    // Allows the admin to transfer any NFT from this contract
    // to the recovery address.
    function recoverNFT(uint256 tokenId) external onlyAdminRecovery {
        IERC721(nftContract).transferFrom(
            // From the auction contract.
            address(this),
            // To the recovery account.
            adminRecoveryAddress,
            // For the specified token.
            tokenId
        );
    }

    // Allows the admin to transfer any ETH from this contract to the recovery address.
    function recoverETH(uint256 amount)
        externalonlyAdminRecovery
        returns (bool success)
    {
        // Attempt an ETH transfer to the recovery account, and return true if it succeeds.
        success = attemptETHTransfer(adminRecoveryAddress, amount);
    }

    // ============ Miscellaneous Public and External ============

    // Returns true if the contract is paused.
    function paused() public view returns (bool) {
        return _paused;
    }

    // Returns true if admin recovery is enabled.
    function adminRecoveryEnabled() public view returns (bool) {
        return _adminRecoveryEnabled;
    }

    // Returns the version of the deployed contract.
    function getVersion() external pure returns (uint256 version) {
        version = RESERVE_AUCTION_VERSION;
    }

    // ============ Private Functions ============

    // Will attempt to transfer ETH, but will transfer WETH instead if it fails.
    function transferETHOrWETH(address to, uint256 value) private {
        // Try to transfer ETH to the given recipient.
        if (!attemptETHTransfer(to, value)) {
            // If the transfer fails, wrap and send as WETH, so that
            // the auction is not impeded and the recipient still
            // can claim ETH via the WETH contract (similar to escrow).
            IWETH(wethAddress).deposit{value: value}();
            IWETH(wethAddress).transfer(to, value);
            // At this point, the recipient can unwrap WETH.
        }
    }

    // Sending ETH is not guaranteed complete, and the method used here will return false if
    // it fails. For example, a contract can block ETH transfer, or might use
    // an excessive amount of gas, thereby griefing a new bidder.
    // We should limit the gas used in transfers, and handle failure cases.
    function attemptETHTransfer(address to, uint256 value)
        privatereturns (bool)
    {
        // Here increase the gas limit a reasonable amount above the default, and try
        // to send ETH to the recipient.
        // NOTE: This might allow the recipient to attempt a limited reentrancy attack.
        (bool success, ) = to.call{value: value, gas: 30000}(&quot;&quot;);
        return success;
    }

    // Returns true if the auction&apos;s curator is set to the null address.
    function auctionCuratorIsNull(uint256 tokenId) private view returns (bool) {
        // The auction does not exist if the curator is the null address,
        // since the NFT would not have been transferred in `createAuction`.
        return auctions[tokenId].curator == address(0);
    }

    // Returns the timestamp at which an auction will finish.
    function auctionEnds(uint256 tokenId) private view returns (uint256) {
        // Derived by adding the auction&apos;s duration to the time of the first bid.
        // NOTE: duration can be extended conditionally after each new bid is added.
        return auctions[tokenId].firstBidTime.add(auctions[tokenId].duration);
    }
}
"><code><span class="hljs-comment">// SPDX-License-Identifier: GPL-3.0-or-later</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">solidity</span> 0.6.8;</span>
<span class="hljs-meta"><span class="hljs-keyword">pragma</span> <span class="hljs-keyword">experimental</span> <span class="hljs-built_in">ABIEncoderV2</span>;</span>

<span class="hljs-comment">// OpenZeppelin library for performing math operations without overflows.</span>
<span class="hljs-keyword">import</span> {<span class="hljs-title">SafeMath</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@openzeppelin/contracts/math/SafeMath.sol"</span>;
<span class="hljs-comment">// OpenZeppelin security library for preventing reentrancy attacks.</span>
<span class="hljs-keyword">import</span> {
    <span class="hljs-title">ReentrancyGuard</span>
} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@openzeppelin/contracts/utils/ReentrancyGuard.sol"</span>;
<span class="hljs-comment">// For interacting with Zora's Market contract.</span>
<span class="hljs-keyword">import</span> {<span class="hljs-title">IMarket</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"./interfaces/IMarket.sol"</span>;
<span class="hljs-comment">// For checking `supportsInterface`.</span>
<span class="hljs-keyword">import</span> {<span class="hljs-title">IERC165</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@openzeppelin/contracts/introspection/IERC165.sol"</span>;
<span class="hljs-comment">// For interacting with NFT tokens.</span>
<span class="hljs-keyword">import</span> {<span class="hljs-title">IERC721</span>} <span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-string">"@openzeppelin/contracts/token/ERC721/IERC721.sol"</span>;

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">IMediaModified</span> </span>{
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">uint256</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> <span class="hljs-keyword">address</span>) <span class="hljs-keyword">public</span> tokenCreators;
    <span class="hljs-keyword">address</span> <span class="hljs-keyword">public</span> marketContract;
}

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">IWETH</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">deposit</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">payable</span></span></span>;

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transfer</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to, <span class="hljs-keyword">uint256</span> value</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>)</span>;
}

<span class="hljs-class"><span class="hljs-keyword">contract</span> <span class="hljs-title">ReserveAuctionV3</span> <span class="hljs-keyword">is</span> <span class="hljs-title">ReentrancyGuard</span> </span>{
    <span class="hljs-comment">// Use OpenZeppelin's SafeMath library to prevent overflows.</span>
    <span class="hljs-keyword">using</span> <span class="hljs-title">SafeMath</span> <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title"><span class="hljs-keyword">uint256</span></span>;

    <span class="hljs-comment">// ============ Constants ============</span>

    <span class="hljs-comment">// The minimum amount of time left in an auction after a new bid is created; 15 min.</span>
    <span class="hljs-keyword">uint16</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">constant</span> TIME_BUFFER <span class="hljs-operator">=</span> <span class="hljs-number">900</span>;
    <span class="hljs-comment">// The ETH needed above the current bid for a new bid to be valid; 0.001 ETH.</span>
    <span class="hljs-keyword">uint8</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">constant</span> MIN_BID_INCREMENT_PERCENT <span class="hljs-operator">=</span> <span class="hljs-number">10</span>;
    <span class="hljs-comment">// Interface constant for ERC721, to check values in constructor.</span>
    <span class="hljs-keyword">bytes4</span> <span class="hljs-keyword">private</span> <span class="hljs-keyword">constant</span> ERC721_INTERFACE_ID <span class="hljs-operator">=</span> <span class="hljs-number">0x80ac58cd</span>;
    <span class="hljs-comment">// Allows external read `getVersion()` to return a version for the auction.</span>
    <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">private</span> <span class="hljs-keyword">constant</span> RESERVE_AUCTION_VERSION <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;

    <span class="hljs-comment">// ============ Immutable Storage ============</span>

    <span class="hljs-comment">// The address of the ERC721 contract for tokens auctioned via this contract.</span>
    <span class="hljs-keyword">address</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">immutable</span> nftContract;
    <span class="hljs-comment">// The address of the WETH contract, so that ETH can be transferred via</span>
    <span class="hljs-comment">// WETH if native ETH transfers fail.</span>
    <span class="hljs-keyword">address</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">immutable</span> wethAddress;
    <span class="hljs-comment">// The address that initially is able to recover assets.</span>
    <span class="hljs-keyword">address</span> <span class="hljs-keyword">public</span> <span class="hljs-keyword">immutable</span> adminRecoveryAddress;

    <span class="hljs-comment">// ============ Mutable Storage ============</span>

    <span class="hljs-comment">/**
     * To start, there will be an admin account that can recover funds
     * if anything goes wrong. Later, this public flag will be irrevocably
     * set to false, removing any admin privileges forever.
     *
     * To check if admin recovery is enabled, call the public function `adminRecoveryEnabled()`.
     */</span>
    <span class="hljs-keyword">bool</span> <span class="hljs-keyword">private</span> _adminRecoveryEnabled;
    <span class="hljs-comment">/**
     * The account `adminRecoveryAddress` can also pause the contracts
     * while _adminRecoveryEnabled is enabled. This prevents people from using
     * the contract if there is a known problem with it.
     */</span>
    <span class="hljs-keyword">bool</span> <span class="hljs-keyword">private</span> _paused;

    <span class="hljs-comment">// A mapping of all of the auctions currently running.</span>
    <span class="hljs-keyword">mapping</span>(<span class="hljs-keyword">uint256</span> <span class="hljs-operator">=</span><span class="hljs-operator">></span> Auction) <span class="hljs-keyword">public</span> auctions;

    <span class="hljs-comment">// ============ Structs ============</span>

    <span class="hljs-keyword">struct</span> <span class="hljs-title">Auction</span> {
        <span class="hljs-comment">// The value of the current highest bid.</span>
        <span class="hljs-keyword">uint256</span> amount;
        <span class="hljs-comment">// The amount of time that the auction should run for,</span>
        <span class="hljs-comment">// after the first bid was made.</span>
        <span class="hljs-keyword">uint256</span> duration;
        <span class="hljs-comment">// The time of the first bid.</span>
        <span class="hljs-keyword">uint256</span> firstBidTime;
        <span class="hljs-comment">// The minimum price of the first bid.</span>
        <span class="hljs-keyword">uint256</span> reservePrice;
        <span class="hljs-keyword">uint8</span> curatorFeePercent;
        <span class="hljs-comment">// The address of the auction's curator. The curator</span>
        <span class="hljs-comment">// can cancel the auction if it hasn't had a bid yet.</span>
        <span class="hljs-keyword">address</span> curator;
        <span class="hljs-comment">// The address of the current highest bid.</span>
        <span class="hljs-keyword">address</span> <span class="hljs-keyword">payable</span> bidder;
        <span class="hljs-comment">// The address that should receive funds once the NFT is sold.</span>
        <span class="hljs-keyword">address</span> <span class="hljs-keyword">payable</span> fundsRecipient;
    }

    <span class="hljs-comment">// ============ Events ============</span>

    <span class="hljs-comment">// All of the details of a new auction,</span>
    <span class="hljs-comment">// with an index created for the tokenId.</span>
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">AuctionCreated</span>(<span class="hljs-params">
        <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">indexed</span> tokenId,
        <span class="hljs-keyword">address</span> nftContractAddress,
        <span class="hljs-keyword">uint256</span> duration,
        <span class="hljs-keyword">uint256</span> reservePrice,
        <span class="hljs-keyword">uint8</span> curatorFeePercent,
        <span class="hljs-keyword">address</span> curator,
        <span class="hljs-keyword">address</span> fundsRecipient
    </span>)</span>;

    <span class="hljs-comment">// All of the details of a new bid,</span>
    <span class="hljs-comment">// with an index created for the tokenId.</span>
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">AuctionBid</span>(<span class="hljs-params">
        <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">indexed</span> tokenId,
        <span class="hljs-keyword">address</span> nftContractAddress,
        <span class="hljs-keyword">address</span> sender,
        <span class="hljs-keyword">uint256</span> value
    </span>)</span>;

    <span class="hljs-comment">// All of the details of an auction's cancelation,</span>
    <span class="hljs-comment">// with an index created for the tokenId.</span>
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">AuctionCanceled</span>(<span class="hljs-params">
        <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">indexed</span> tokenId,
        <span class="hljs-keyword">address</span> nftContractAddress,
        <span class="hljs-keyword">address</span> curator
    </span>)</span>;

    <span class="hljs-comment">// All of the details of an auction's close,</span>
    <span class="hljs-comment">// with an index created for the tokenId.</span>
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">AuctionEnded</span>(<span class="hljs-params">
        <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">indexed</span> tokenId,
        <span class="hljs-keyword">address</span> nftContractAddress,
        <span class="hljs-keyword">address</span> curator,
        <span class="hljs-keyword">address</span> winner,
        <span class="hljs-keyword">uint256</span> amount,
        <span class="hljs-keyword">address</span> nftCreator,
        <span class="hljs-keyword">address</span> <span class="hljs-keyword">payable</span> fundsRecipient
    </span>)</span>;

    <span class="hljs-comment">// When the curator recevies fees, emit the details including the amount,</span>
    <span class="hljs-comment">// with an index created for the tokenId.</span>
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">CuratorFeePercentTransfer</span>(<span class="hljs-params">
        <span class="hljs-keyword">uint256</span> <span class="hljs-keyword">indexed</span> tokenId,
        <span class="hljs-keyword">address</span> curator,
        <span class="hljs-keyword">uint256</span> amount
    </span>)</span>;

    <span class="hljs-comment">// Emitted in the case that the contract is paused.</span>
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">Paused</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> account</span>)</span>;
    <span class="hljs-comment">// Emitted when the contract is unpaused.</span>
    <span class="hljs-function"><span class="hljs-keyword">event</span> <span class="hljs-title">Unpaused</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> account</span>)</span>;

    <span class="hljs-comment">// ============ Modifiers ============</span>

    <span class="hljs-comment">// Reverts if the sender is not admin, or admin</span>
    <span class="hljs-comment">// functionality has been turned off.</span>
    <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">onlyAdminRecovery</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">require</span>(
            <span class="hljs-comment">// The sender must be the admin address, and</span>
            <span class="hljs-comment">// adminRecovery must be set to true.</span>
            adminRecoveryAddress <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span> <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span> adminRecoveryEnabled(),
            <span class="hljs-string">"Caller does not have admin privileges"</span>
        );
        <span class="hljs-keyword">_</span>;
    }

    <span class="hljs-comment">// Reverts if the sender is not the auction's curator.</span>
    <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">onlyCurator</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> tokenId</span>) </span>{
        <span class="hljs-built_in">require</span>(
            auctions[tokenId].curator <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>,
            <span class="hljs-string">"Can only be called by auction curator"</span>
        );
        <span class="hljs-keyword">_</span>;
    }

    <span class="hljs-comment">// Reverts if the contract is paused.</span>
    <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">whenNotPaused</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">require</span>(<span class="hljs-operator">!</span>paused(), <span class="hljs-string">"Contract is paused"</span>);
        <span class="hljs-keyword">_</span>;
    }

    <span class="hljs-comment">// Reverts if the auction does not exist.</span>
    <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">auctionExists</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> tokenId</span>) </span>{
        <span class="hljs-comment">// The auction exists if the curator is not null.</span>
        <span class="hljs-built_in">require</span>(<span class="hljs-operator">!</span>auctionCuratorIsNull(tokenId), <span class="hljs-string">"Auction doesn't exist"</span>);
        <span class="hljs-keyword">_</span>;
    }

    <span class="hljs-comment">// Reverts if the auction exists.</span>
    <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">auctionNonExistant</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> tokenId</span>) </span>{
        <span class="hljs-comment">// The auction does not exist if the curator is null.</span>
        <span class="hljs-built_in">require</span>(auctionCuratorIsNull(tokenId), <span class="hljs-string">"Auction already exists"</span>);
        <span class="hljs-keyword">_</span>;
    }

    <span class="hljs-comment">// Reverts if the auction is expired.</span>
    <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">auctionNotExpired</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> tokenId</span>) </span>{
        <span class="hljs-built_in">require</span>(
            <span class="hljs-comment">// Auction is not expired if there's never been a bid, or if the</span>
            <span class="hljs-comment">// current time is less than the time at which the auction ends.</span>
            auctions[tokenId].firstBidTime <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span> <span class="hljs-operator">|</span><span class="hljs-operator">|</span>
                <span class="hljs-built_in">block</span>.<span class="hljs-built_in">timestamp</span> <span class="hljs-operator">&#x3C;</span> auctionEnds(tokenId),
            <span class="hljs-string">"Auction expired"</span>
        );
        <span class="hljs-keyword">_</span>;
    }

    <span class="hljs-comment">// Reverts if the auction is not complete.</span>
    <span class="hljs-comment">// Auction is complete if there was a bid, and the time has run out.</span>
    <span class="hljs-function"><span class="hljs-keyword">modifier</span> <span class="hljs-title">auctionComplete</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> tokenId</span>) </span>{
        <span class="hljs-built_in">require</span>(
            <span class="hljs-comment">// Auction is complete if there has been a bid, and the current time</span>
            <span class="hljs-comment">// is greater than the auction's end time.</span>
            auctions[tokenId].firstBidTime <span class="hljs-operator">></span> <span class="hljs-number">0</span> <span class="hljs-operator">&#x26;</span><span class="hljs-operator">&#x26;</span>
                <span class="hljs-built_in">block</span>.<span class="hljs-built_in">timestamp</span> <span class="hljs-operator">></span><span class="hljs-operator">=</span> auctionEnds(tokenId),
            <span class="hljs-string">"Auction hasn't completed"</span>
        );
        <span class="hljs-keyword">_</span>;
    }

    <span class="hljs-comment">// ============ Constructor ============</span>

    <span class="hljs-function"><span class="hljs-keyword">constructor</span>(<span class="hljs-params">
        <span class="hljs-keyword">address</span> nftContract_,
        <span class="hljs-keyword">address</span> wethAddress_,
        <span class="hljs-keyword">address</span> adminRecoveryAddress_
    </span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> </span>{
        <span class="hljs-built_in">require</span>(
            IERC165(nftContract_).supportsInterface(ERC721_INTERFACE_ID),
            <span class="hljs-string">"Contract at nftContract_ address does not support NFT interface"</span>
        );
        <span class="hljs-comment">// Initialize immutable memory.</span>
        nftContract <span class="hljs-operator">=</span> nftContract_;
        wethAddress <span class="hljs-operator">=</span> wethAddress_;
        adminRecoveryAddress <span class="hljs-operator">=</span> adminRecoveryAddress_;
        <span class="hljs-comment">// Initialize mutable memory.</span>
        _paused <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>;
        _adminRecoveryEnabled <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;
    }

    <span class="hljs-comment">// ============ Create Auction ============</span>

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createAuction</span>(<span class="hljs-params">
        <span class="hljs-keyword">uint256</span> tokenId,
        <span class="hljs-keyword">uint256</span> duration,
        <span class="hljs-keyword">uint256</span> reservePrice,
        <span class="hljs-keyword">uint8</span> curatorFeePercent,
        <span class="hljs-keyword">address</span> curator,
        <span class="hljs-keyword">address</span> <span class="hljs-keyword">payable</span> fundsRecipient
    </span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">nonReentrant</span> <span class="hljs-title">whenNotPaused</span> <span class="hljs-title">auctionNonExistant</span>(<span class="hljs-params">tokenId</span>) </span>{
        <span class="hljs-comment">// Check basic input requirements are reasonable.</span>
        <span class="hljs-built_in">require</span>(curator <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>));
        <span class="hljs-built_in">require</span>(fundsRecipient <span class="hljs-operator">!</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>));
        <span class="hljs-built_in">require</span>(curatorFeePercent <span class="hljs-operator">&#x3C;</span> <span class="hljs-number">100</span>, <span class="hljs-string">"Curator fee should be &#x3C; 100"</span>);
        <span class="hljs-comment">// Initialize the auction details, including null values.</span>
        auctions[tokenId] <span class="hljs-operator">=</span> Auction({
            duration: duration,
            reservePrice: reservePrice,
            curatorFeePercent: curatorFeePercent,
            curator: curator,
            fundsRecipient: fundsRecipient,
            amount: <span class="hljs-number">0</span>,
            firstBidTime: <span class="hljs-number">0</span>,
            bidder: <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>)
        });
        <span class="hljs-comment">// Transfer the NFT into this auction contract, from whoever owns it.</span>
        IERC721(nftContract).transferFrom(
            IERC721(nftContract).ownerOf(tokenId),
            <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>),
            tokenId
        );
        <span class="hljs-comment">// Emit an event describing the new auction.</span>
        <span class="hljs-keyword">emit</span> AuctionCreated(
            tokenId,
            nftContract,
            duration,
            reservePrice,
            curatorFeePercent,
            curator,
            fundsRecipient
        );
    }

    <span class="hljs-comment">// ============ Create Bid ============</span>

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createBid</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> tokenId, <span class="hljs-keyword">uint256</span> amount</span>)
        <span class="hljs-title">externalpayablenonReentrant</span>
        <span class="hljs-title">whenNotPaused</span>
        <span class="hljs-title">auctionExists</span>(<span class="hljs-params">tokenId</span>)
        <span class="hljs-title">auctionNotExpired</span>(<span class="hljs-params">tokenId</span>)
    </span>{
        <span class="hljs-comment">// Validate that the user's expected bid value matches the ETH deposit.</span>
        <span class="hljs-built_in">require</span>(amount <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">value</span>, <span class="hljs-string">"Amount doesn't equal msg.value"</span>);
        <span class="hljs-built_in">require</span>(amount <span class="hljs-operator">></span> <span class="hljs-number">0</span>, <span class="hljs-string">"Amount must be greater than 0"</span>);
        <span class="hljs-comment">// Check if the current bid amount is 0.</span>
        <span class="hljs-keyword">if</span> (auctions[tokenId].amount <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>) {
            <span class="hljs-comment">// If so, it is the first bid.</span>
            auctions[tokenId].firstBidTime <span class="hljs-operator">=</span> <span class="hljs-built_in">block</span>.<span class="hljs-built_in">timestamp</span>;
            <span class="hljs-comment">// We only need to check if the bid matches reserve bid for the first bid,</span>
            <span class="hljs-comment">// since future checks will need to be higher than any previous bid.</span>
            <span class="hljs-built_in">require</span>(
                amount <span class="hljs-operator">></span><span class="hljs-operator">=</span> auctions[tokenId].reservePrice,
                <span class="hljs-string">"Must bid reservePrice or more"</span>
            );
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-comment">// Check that the new bid is sufficiently higher than the previous bid, by</span>
            <span class="hljs-comment">// the percentage defined as MIN_BID_INCREMENT_PERCENT.</span>
            <span class="hljs-built_in">require</span>(
                amount <span class="hljs-operator">></span><span class="hljs-operator">=</span>
                    auctions[tokenId].amount.add(
                        <span class="hljs-comment">// Add 10% of the current bid to the current bid.</span>
                        auctions[tokenId]
                            .amount
                            .mul(MIN_BID_INCREMENT_PERCENT)
                            .div(<span class="hljs-number">100</span>)
                    ),
                <span class="hljs-string">"Must bid more than last bid by MIN_BID_INCREMENT_PERCENT amount"</span>
            );

            <span class="hljs-comment">// Refund the previous bidder.</span>
            transferETHOrWETH(
                auctions[tokenId].bidder,
                auctions[tokenId].amount
            );
        }
        <span class="hljs-comment">// Update the current auction.</span>
        auctions[tokenId].amount <span class="hljs-operator">=</span> amount;
        auctions[tokenId].bidder <span class="hljs-operator">=</span> <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>;
        <span class="hljs-comment">// Compare the auction's end time with the current time plus the 15 minute extension,</span>
        <span class="hljs-comment">// to see whether we're near the auctions end and should extend the auction.</span>
        <span class="hljs-keyword">if</span> (auctionEnds(tokenId) <span class="hljs-operator">&#x3C;</span> <span class="hljs-built_in">block</span>.<span class="hljs-built_in">timestamp</span>.add(TIME_BUFFER)) {
            <span class="hljs-comment">// We add onto the duration whenever time increment is required, so</span>
            <span class="hljs-comment">// that the auctionEnds at the current time plus the buffer.</span>
            auctions[tokenId].duration <span class="hljs-operator">+</span><span class="hljs-operator">=</span> <span class="hljs-built_in">block</span>.<span class="hljs-built_in">timestamp</span>.add(TIME_BUFFER).sub(
                auctionEnds(tokenId)
            );
        }
        <span class="hljs-comment">// Emit the event that a bid has been made.</span>
        <span class="hljs-keyword">emit</span> AuctionBid(tokenId, nftContract, <span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>, amount);
    }

    <span class="hljs-comment">// ============ End Auction ============</span>

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">endAuction</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> tokenId</span>)
        <span class="hljs-title">externalnonReentrant</span>
        <span class="hljs-title">whenNotPaused</span>
        <span class="hljs-title">auctionComplete</span>(<span class="hljs-params">tokenId</span>)
    </span>{
        <span class="hljs-comment">// Store relevant auction data in memory for the life of this function.</span>
        <span class="hljs-keyword">address</span> winner <span class="hljs-operator">=</span> auctions[tokenId].bidder;
        <span class="hljs-keyword">uint256</span> amount <span class="hljs-operator">=</span> auctions[tokenId].amount;
        <span class="hljs-keyword">address</span> curator <span class="hljs-operator">=</span> auctions[tokenId].curator;
        <span class="hljs-keyword">uint8</span> curatorFeePercent <span class="hljs-operator">=</span> auctions[tokenId].curatorFeePercent;
        <span class="hljs-keyword">address</span> <span class="hljs-keyword">payable</span> fundsRecipient <span class="hljs-operator">=</span> auctions[tokenId].fundsRecipient;
        <span class="hljs-comment">// Remove all auction data for this token from storage.</span>
        <span class="hljs-keyword">delete</span> auctions[tokenId];
        <span class="hljs-comment">// We don't use safeTransferFrom, to prevent reverts at this point,</span>
        <span class="hljs-comment">// which would break the auction.</span>
        IERC721(nftContract).transferFrom(<span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>), winner, tokenId);
        <span class="hljs-comment">// First handle the curator's fee.</span>
        <span class="hljs-keyword">if</span> (curatorFeePercent <span class="hljs-operator">></span> <span class="hljs-number">0</span>) {
            <span class="hljs-comment">// Determine the curator amount, which is some percent of the total.</span>
            <span class="hljs-keyword">uint256</span> curatorAmount <span class="hljs-operator">=</span> amount.mul(curatorFeePercent).div(<span class="hljs-number">100</span>);
            <span class="hljs-comment">// Send it to the curator.</span>
            transferETHOrWETH(curator, curatorAmount);
            <span class="hljs-comment">// Subtract the curator amount from the total funds available</span>
            <span class="hljs-comment">// to send to the funds recipient and original NFT creator.</span>
            amount <span class="hljs-operator">=</span> amount.sub(curatorAmount);
            <span class="hljs-comment">// Emit the details of the transfer as an event.</span>
            <span class="hljs-keyword">emit</span> CuratorFeePercentTransfer(tokenId, curator, curatorAmount);
        }
        <span class="hljs-comment">// Get the address of the original creator, so that we can split shares</span>
        <span class="hljs-comment">// if appropriate.</span>
        <span class="hljs-keyword">address</span> <span class="hljs-keyword">payable</span> nftCreator <span class="hljs-operator">=</span>
            <span class="hljs-keyword">payable</span>(
                <span class="hljs-keyword">address</span>(IMediaModified(nftContract).tokenCreators(tokenId))
            );
        <span class="hljs-comment">// If the creator and the recipient of the funds are the same</span>
        <span class="hljs-comment">// (and we expect this to be common), we can just do one transaction.</span>
        <span class="hljs-keyword">if</span> (nftCreator <span class="hljs-operator">=</span><span class="hljs-operator">=</span> fundsRecipient) {
            transferETHOrWETH(nftCreator, amount);
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-comment">// Otherwise, we should determine the percent that goes to the creator.</span>
            <span class="hljs-comment">// Collect share data from Zora.</span>
            <span class="hljs-keyword">uint256</span> creatorAmount <span class="hljs-operator">=</span>
                <span class="hljs-comment">// Call the splitShare function on the market contract, which</span>
                <span class="hljs-comment">// takes in a Decimal and an amount.</span>
                IMarket(IMediaModified(nftContract).marketContract())
                    .splitShare(
                    <span class="hljs-comment">// Fetch the decimal from the BidShares data on the market.</span>
                    IMarket(IMediaModified(nftContract).marketContract())
                        .bidSharesForToken(tokenId)
                        .creator,
                    <span class="hljs-comment">// Specify the amount.</span>
                    amount
                );
            <span class="hljs-comment">// Send the creator's share to the creator.</span>
            transferETHOrWETH(nftCreator, creatorAmount);
            <span class="hljs-comment">// Send the remainder of the amount to the funds recipient.</span>
            transferETHOrWETH(fundsRecipient, amount.sub(creatorAmount));
        }
        <span class="hljs-comment">// Emit an event describing the end of the auction.</span>
        <span class="hljs-keyword">emit</span> AuctionEnded(
            tokenId,
            nftContract,
            curator,
            winner,
            amount,
            nftCreator,
            fundsRecipient
        );
    }

    <span class="hljs-comment">// ============ Cancel Auction ============</span>

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">cancelAuction</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> tokenId</span>)
        <span class="hljs-title">externalnonReentrant</span>
        <span class="hljs-title">auctionExists</span>(<span class="hljs-params">tokenId</span>)
        <span class="hljs-title">onlyCurator</span>(<span class="hljs-params">tokenId</span>)
    </span>{
        <span class="hljs-comment">// Check that there hasn't already been a bid for this NFT.</span>
        <span class="hljs-built_in">require</span>(
            <span class="hljs-keyword">uint256</span>(auctions[tokenId].firstBidTime) <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-number">0</span>,
            <span class="hljs-string">"Auction already started"</span>
        );
        <span class="hljs-comment">// Pull the creator address before removing the auction.</span>
        <span class="hljs-keyword">address</span> curator <span class="hljs-operator">=</span> auctions[tokenId].curator;
        <span class="hljs-comment">// Remove all data about the auction.</span>
        <span class="hljs-keyword">delete</span> auctions[tokenId];
        <span class="hljs-comment">// Transfer the NFT back to the curator.</span>
        IERC721(nftContract).transferFrom(<span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>), curator, tokenId);
        <span class="hljs-comment">// Emit an event describing that the auction has been canceled.</span>
        <span class="hljs-keyword">emit</span> AuctionCanceled(tokenId, nftContract, curator);
    }

    <span class="hljs-comment">// ============ Admin Functions ============</span>

    <span class="hljs-comment">// Irrevocably turns off admin recovery.</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">turnOffAdminRecovery</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">onlyAdminRecovery</span> </span>{
        _adminRecoveryEnabled <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">pauseContract</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">onlyAdminRecovery</span> </span>{
        _paused <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;
        <span class="hljs-keyword">emit</span> Paused(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">unpauseContract</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">onlyAdminRecovery</span> </span>{
        _paused <span class="hljs-operator">=</span> <span class="hljs-literal">false</span>;
        <span class="hljs-keyword">emit</span> Unpaused(<span class="hljs-built_in">msg</span>.<span class="hljs-built_in">sender</span>);
    }

    <span class="hljs-comment">// Allows the admin to transfer any NFT from this contract</span>
    <span class="hljs-comment">// to the recovery address.</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">recoverNFT</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> tokenId</span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title">onlyAdminRecovery</span> </span>{
        IERC721(nftContract).transferFrom(
            <span class="hljs-comment">// From the auction contract.</span>
            <span class="hljs-keyword">address</span>(<span class="hljs-built_in">this</span>),
            <span class="hljs-comment">// To the recovery account.</span>
            adminRecoveryAddress,
            <span class="hljs-comment">// For the specified token.</span>
            tokenId
        );
    }

    <span class="hljs-comment">// Allows the admin to transfer any ETH from this contract to the recovery address.</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">recoverETH</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> amount</span>)
        <span class="hljs-title">externalonlyAdminRecovery</span>
        <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span> success</span>)
    </span>{
        <span class="hljs-comment">// Attempt an ETH transfer to the recovery account, and return true if it succeeds.</span>
        success <span class="hljs-operator">=</span> attemptETHTransfer(adminRecoveryAddress, amount);
    }

    <span class="hljs-comment">// ============ Miscellaneous Public and External ============</span>

    <span class="hljs-comment">// Returns true if the contract is paused.</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">paused</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
        <span class="hljs-keyword">return</span> _paused;
    }

    <span class="hljs-comment">// Returns true if admin recovery is enabled.</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">adminRecoveryEnabled</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">public</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
        <span class="hljs-keyword">return</span> _adminRecoveryEnabled;
    }

    <span class="hljs-comment">// Returns the version of the deployed contract.</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getVersion</span>(<span class="hljs-params"></span>) <span class="hljs-title"><span class="hljs-keyword">external</span></span> <span class="hljs-title"><span class="hljs-keyword">pure</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span> version</span>) </span>{
        version <span class="hljs-operator">=</span> RESERVE_AUCTION_VERSION;
    }

    <span class="hljs-comment">// ============ Private Functions ============</span>

    <span class="hljs-comment">// Will attempt to transfer ETH, but will transfer WETH instead if it fails.</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">transferETHOrWETH</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to, <span class="hljs-keyword">uint256</span> value</span>) <span class="hljs-title"><span class="hljs-keyword">private</span></span> </span>{
        <span class="hljs-comment">// Try to transfer ETH to the given recipient.</span>
        <span class="hljs-keyword">if</span> (<span class="hljs-operator">!</span>attemptETHTransfer(to, value)) {
            <span class="hljs-comment">// If the transfer fails, wrap and send as WETH, so that</span>
            <span class="hljs-comment">// the auction is not impeded and the recipient still</span>
            <span class="hljs-comment">// can claim ETH via the WETH contract (similar to escrow).</span>
            IWETH(wethAddress).deposit{<span class="hljs-built_in">value</span>: value}();
            IWETH(wethAddress).<span class="hljs-built_in">transfer</span>(to, value);
            <span class="hljs-comment">// At this point, the recipient can unwrap WETH.</span>
        }
    }

    <span class="hljs-comment">// Sending ETH is not guaranteed complete, and the method used here will return false if</span>
    <span class="hljs-comment">// it fails. For example, a contract can block ETH transfer, or might use</span>
    <span class="hljs-comment">// an excessive amount of gas, thereby griefing a new bidder.</span>
    <span class="hljs-comment">// We should limit the gas used in transfers, and handle failure cases.</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">attemptETHTransfer</span>(<span class="hljs-params"><span class="hljs-keyword">address</span> to, <span class="hljs-keyword">uint256</span> value</span>)
        <span class="hljs-title">privatereturns</span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>)
    </span>{
        <span class="hljs-comment">// Here increase the gas limit a reasonable amount above the default, and try</span>
        <span class="hljs-comment">// to send ETH to the recipient.</span>
        <span class="hljs-comment">// <span class="hljs-doctag">NOTE:</span> This might allow the recipient to attempt a limited reentrancy attack.</span>
        (<span class="hljs-keyword">bool</span> success, ) <span class="hljs-operator">=</span> to.<span class="hljs-built_in">call</span>{<span class="hljs-built_in">value</span>: value, <span class="hljs-built_in">gas</span>: <span class="hljs-number">30000</span>}(<span class="hljs-string">""</span>);
        <span class="hljs-keyword">return</span> success;
    }

    <span class="hljs-comment">// Returns true if the auction's curator is set to the null address.</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">auctionCuratorIsNull</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> tokenId</span>) <span class="hljs-title"><span class="hljs-keyword">private</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">bool</span></span>) </span>{
        <span class="hljs-comment">// The auction does not exist if the curator is the null address,</span>
        <span class="hljs-comment">// since the NFT would not have been transferred in `createAuction`.</span>
        <span class="hljs-keyword">return</span> auctions[tokenId].curator <span class="hljs-operator">=</span><span class="hljs-operator">=</span> <span class="hljs-keyword">address</span>(<span class="hljs-number">0</span>);
    }

    <span class="hljs-comment">// Returns the timestamp at which an auction will finish.</span>
    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">auctionEnds</span>(<span class="hljs-params"><span class="hljs-keyword">uint256</span> tokenId</span>) <span class="hljs-title"><span class="hljs-keyword">private</span></span> <span class="hljs-title"><span class="hljs-keyword">view</span></span> <span class="hljs-title"><span class="hljs-keyword">returns</span></span> (<span class="hljs-params"><span class="hljs-keyword">uint256</span></span>) </span>{
        <span class="hljs-comment">// Derived by adding the auction's duration to the time of the first bid.</span>
        <span class="hljs-comment">// <span class="hljs-doctag">NOTE:</span> duration can be extended conditionally after each new bid is added.</span>
        <span class="hljs-keyword">return</span> auctions[tokenId].firstBidTime.add(auctions[tokenId].duration);
    }
}
</code></pre>]]></content:encoded>
            <author>thisiscarlos@newsletter.paragraph.com (Mint Fund)</author>
        </item>
    </channel>
</rss>