From d63153b03d5eb1287021b2590e472988a7e983cc Mon Sep 17 00:00:00 2001 From: Iain Date: Mon, 25 Apr 2022 12:08:10 -0400 Subject: [PATCH] final code updates / cleanup --- contracts/ERC721Drop.sol | 26 ++++++++++------- scripts/snapshot.mjs | 60 ++++++++++++++++++++++++++++++++-------- 2 files changed, 64 insertions(+), 22 deletions(-) diff --git a/contracts/ERC721Drop.sol b/contracts/ERC721Drop.sol index 26f6f4b..2049957 100644 --- a/contracts/ERC721Drop.sol +++ b/contracts/ERC721Drop.sol @@ -30,7 +30,10 @@ contract ERC721Drop is IZoraDrop, OwnableSkeleton { - uint256 private constant VERSION = 2; + /// @dev This is the underlying contract version that is implemented by the interface + uint256 private constant VERSION = 3; + /// @dev This is the max mint batch size for the optimized ERC721A mint contract + uint256 private constant MAX_MINT_BATCH_SIZE = 8; using AddressUpgradeable for address payable; @@ -303,7 +306,7 @@ contract ERC721Drop is *** *** *** ---------------------------------- *** *** - ** */ + ***/ /** @dev This allows the user to purchase a edition edition @@ -339,13 +342,14 @@ contract ERC721Drop is return firstMintedTokenId; } - /// @dev Function to mint NFTs - /// @notice (important: Does not enforce max supply limit, enforce that limit earlier) + /// @notice Function to mint NFTs + /// @dev (important: Does not enforce max supply limit, enforce that limit earlier) + /// @dev This batches in size of 8 as per recommended by ERC721A creators /// @param to address to mint NFTs to /// @param quantity number of NFTs to mint function _mintNFTs(address to, uint256 quantity) internal { do { - uint256 toMint = quantity > 8 ? 8 : quantity; + uint256 toMint = quantity > MAX_MINT_BATCH_SIZE ? MAX_MINT_BATCH_SIZE : quantity; _mint({to: to, quantity: toMint, _data: "", safe: false}); quantity -= toMint; } while (quantity > 0); @@ -381,7 +385,9 @@ contract ERC721Drop is "Needs to be approved" ); require(msg.value == pricePerToken * quantity, "Wrong price"); - require(presaleMintsByAddress[_msgSender()] + quantity <= maxQuantity, TOO_MANY); + + presaleMintsByAddress[_msgSender()] += quantity; + require(presaleMintsByAddress[_msgSender()] <= maxQuantity, TOO_MANY); _mintNFTs(_msgSender(), quantity); uint256 firstMintedTokenId = _lastMintedTokenId() - quantity; @@ -393,8 +399,6 @@ contract ERC721Drop is firstPurchasedTokenId: firstMintedTokenId }); - presaleMintsByAddress[_msgSender()] += quantity; - return firstMintedTokenId; } @@ -487,8 +491,10 @@ contract ERC721Drop is ); // No need for gas limit to trusted address. - feeRecipient.sendValue(zoraFee); - funds -= zoraFee; + if (zoraFee > 0) { + feeRecipient.sendValue(zoraFee); + funds -= zoraFee; + } // No need for gas limit to trusted address. config.fundsRecipient.sendValue(funds); } diff --git a/scripts/snapshot.mjs b/scripts/snapshot.mjs index f35cf05..71e32e6 100644 --- a/scripts/snapshot.mjs +++ b/scripts/snapshot.mjs @@ -1,12 +1,48 @@ -import 'isomorphic-fetch' - -const indexer_result = await fetch("https://indexer-prod-mainnet.zora.co/v1/graphql", { - headers: { - Accept: "*/*", - "Content-Type": "application/json", - }, - body: '{"query":"query Token {\\n Token(where:{\\n tokenContract:{address:{_eq:\\"0xC9677Cd8e9652F1b1aaDd3429769b0Ef8D7A0425\\"}}\\n }\\n limit: 100\\n\\toffset: 0\\n) {\\n tokenId\\n owner\\n metadata {\\n json\\n }\\n }\\n}","variables":null,"operationName":"Token"}', - method: "POST", -}); - -console.log(indexer_result) \ No newline at end of file +import "isomorphic-fetch"; +import { writeFile } from "fs/promises"; +import esMain from "es-main"; + +async function fetchIndexer(contract, offset) { + const query = `{"query":"query Token {\\n Token(where:{\\n tokenContract:{address:{_eq:\\"${contract}\\"}}\\n }\\n limit: 100\\n\\toffset: ${offset}\\n) {\\n tokenId\\n owner\\n metadata {\\n json\\n }\\n }\\n}","variables":null,"operationName":"Token"}`; + console.log(query); + const result = await fetch( + "https://indexer-prod-mainnet.zora.co/v1/graphql", + { + headers: { + Accept: "*/*", + "Content-Type": "application/json", + }, + body: query, + method: "POST", + } + ); + const jsonResult = await result.json(); + const tokenData = jsonResult.data.Token; + return tokenData; +} + +async function fetchLoop(contract) { + let resultPart = []; + let results = []; + let offset = 0; + do { + resultPart = await fetchIndexer(contract, offset); + results = results.concat(resultPart); + console.log({ offset }); + offset += 100; + } while (resultPart.length > 0); + return results; +} + +async function fetchAllAddresses(contract) { + const results = await fetchLoop(contract); + console.log(`[results] has ${results.length} nfts`); + writeFile("./results.json", JSON.stringify(results, null, 2)); +} + +if (esMain(import.meta)) { + const contract = process.argv[2]; + console.log(`[result] fetching for contract: ${contract}`); + await fetchAllAddresses(contract); + console.log(`[result] done`); +}