/////////////////////////////////////////////////////////////////////////// // // //▄▄▄█████▓ ██▀███ ██▓ ██▓███ ██▓ ▓█████ ██████ ██▓▒██ ██▒// //▓ ██▒ ▓▒▓██ ▒ ██▒▓██▒▓██░ ██▒▓██▒ ▓█ ▀ ▒██ ▒ ▓██▒▒▒ █ █ ▒░// //▒ ▓██░ ▒░▓██ ░▄█ ▒▒██▒▓██░ ██▓▒▒██░ ▒███ ░ ▓██▄ ▒██▒░░ █ ░// //░ ▓██▓ ░ ▒██▀▀█▄ ░██░▒██▄█▓▒ ▒▒██░ ▒▓█ ▄ ▒ ██▒░██░ ░ █ █ ▒ // // ▒██▒ ░ ░██▓ ▒██▒░██░▒██▒ ░ ░░██████▒░▒████▒ ▒██████▒▒░██░▒██▒ ▒██▒// // ▒ ░░ ░ ▒▓ ░▒▓░░▓ ▒▓▒░ ░ ░░ ▒░▓ ░░░ ▒░ ░ ▒ ▒▓▒ ▒ ░░▓ ▒▒ ░ ░▓ ░// // ░ ░▒ ░ ▒░ ▒ ░░▒ ░ ░ ░ ▒ ░ ░ ░ ░ ░ ░▒ ░ ░ ▒ ░░░ ░▒ ░// // ░ ░░ ░ ▒ ░░░ ░ ░ ░ ░ ░ ░ ▒ ░ ░ ░ // // ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ // /////////////////////////////////////////////////////////////////////////// //SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./ERC721A.sol"; import "./Ownable.sol"; contract AirDropNFT is ERC721A, Ownable { using Strings for uint256; string baseURI; string public baseExtension = ".json"; string public notRevealedUri; uint256 public maxSupply = 6666; uint256 public nftPerAddressLimit = 1; struct mintInfo { uint256[] tokenList; uint256 tokenID; } bool public paused = true; bool public revealed = false; bool public pausedBurn = true; mapping(address => mintInfo) mintedTokenIDs; mapping(address => uint256) public addressMintedBalance; mapping(address => bool) public whitelist; mapping(address => bool) public giveaway; mapping(address => bool) hasMintedGW; address[] mintedAddreses; uint256[] public silverMints; uint256[] public goldMints; address public constant LIQUID_METALS = 0xa09482c91afA7C24a4b5f46193209f0f9033f0Dd; constructor( string memory _name, string memory _symbol, string memory _initBaseURI, string memory _initNotRevealedUri ) ERC721A(_name, _symbol) { setBaseURI(_initBaseURI); setNotRevealedURI(_initNotRevealedUri); } // internal function _baseURI() internal view virtual override returns (string memory) { return baseURI; } // public function mint() public { uint256 supply = totalSupply(); uint256 balanceOfUser = ERC721A(LIQUID_METALS).balanceOf(msg.sender); require(!paused, "ERROR: Public sale is paused."); require(isWhitelisted(msg.sender), "ERROR: User is not whitelisted"); require(tx.origin == msg.sender, "ERROR: Origin doesnt match sender"); require(supply + 1 <= maxSupply, "ERROR: Too many tokens. Reduce mintAmount so that the totalSupply doesnt exceed maxSupply."); uint256 localnftPerAddressLimit = nftPerAddressLimit; uint256 senderMintCount = addressMintedBalance[msg.sender]; if(balanceOfUser >= 15) { localnftPerAddressLimit = 2; } require(senderMintCount + 1 <= localnftPerAddressLimit, "ERROR: Max NFT per address exceeded"); uint256[] memory userOwnedTokens = new uint256[](balanceOfUser); for (uint256 i = 0; i < balanceOfUser; i++) { userOwnedTokens[i] = ERC721A(LIQUID_METALS).tokenOfOwnerByIndex(msg.sender, i); } _safeMint(msg.sender, 1); addressMintedBalance[msg.sender] += 1; if (senderMintCount == 0) { mintedTokenIDs[msg.sender] = mintInfo(userOwnedTokens, supply); mintedAddreses.push(msg.sender); } else if (senderMintCount == 1) { goldMints.push(supply); } } function mintGiveaway() public { uint256 supply = totalSupply(); require(!paused, "Public sale is paused."); require(giveaway[msg.sender], "You are not in the competition winners list."); require(!hasMintedGW[msg.sender], "Giveaway already minted."); require(supply + 1 < maxSupply, "Too many tokens."); require(tx.origin == msg.sender, "Origin doesn't match sender"); _safeMint(msg.sender, 1); hasMintedGW[msg.sender] = true; silverMints.push(supply); } function mintAdmin(uint256 mintAmount) external onlyOwner { uint256 supply = totalSupply(); require(supply + mintAmount < maxSupply, "Too many tokens."); _safeMint(msg.sender, mintAmount); } function burnToken(uint256 tokenId) public { require(!pausedBurn, "Burn is paused"); _burn(tokenId); } function walletOfOwner(address _owner) public view returns (uint256[] memory) { uint256 ownerTokenCount = balanceOf(_owner); uint256[] memory tokenIds = new uint256[](ownerTokenCount); for (uint256 i; i < ownerTokenCount; i++) { tokenIds[i] = tokenOfOwnerByIndex(_owner, i); } return tokenIds; } function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { require( _exists(tokenId), "ERC721Metadata: URI query for nonexistent token" ); if(revealed == false) { return notRevealedUri; } string memory currentBaseURI = _baseURI(); return bytes(currentBaseURI).length > 0 ? string(abi.encodePacked(currentBaseURI, tokenId.toString(), baseExtension)) : ""; } function reveal() public onlyOwner { revealed = true; } function setNftPerAddressLimit(uint256 _limit) public onlyOwner { nftPerAddressLimit = _limit; } function setNotRevealedURI(string memory _notRevealedURI) public onlyOwner { notRevealedUri = _notRevealedURI; } function setBaseURI(string memory _newBaseURI) public onlyOwner { baseURI = _newBaseURI; } function setBaseExtension(string memory _newBaseExtension) public onlyOwner { baseExtension = _newBaseExtension; } function pause(bool _state) public onlyOwner { paused = _state; } function pauseBurn(bool _state) public onlyOwner { pausedBurn = _state; } function getMinters() public view returns (address[] memory minted) { return mintedAddreses; } function getSilvers() public view returns (uint256[] memory silvers) { return silverMints; } function getGolds() public view returns (uint256[] memory golds) { return goldMints; } function getMinterInfo(address _minter) public view returns (uint256[] memory minterLiquidMetals, uint256 mintedTokenID){ require(addressMintedBalance[_minter] >= 1, "ERROR: Address has not minted the NFT from the main sale."); mintInfo memory minterInfo = mintedTokenIDs[_minter]; return (minterInfo.tokenList, minterInfo.tokenID); } function isWhitelisted(address _user) public view returns (bool) { return whitelist[_user]; } function whitelistUsers(address[] calldata addresses) external onlyOwner { for (uint256 i = 0; i < addresses.length; i++) { whitelist[addresses[i]] = true; } } function isGiveaway(address _user) public view returns (bool) { return giveaway[_user]; } function addGiveaway(address[] calldata addresses) external onlyOwner { for (uint256 i = 0; i < addresses.length; i++) { giveaway[addresses[i]] = true; } } }