Untitled

mail@pastecode.io avatar
unknown
plain_text
2 years ago
6.4 kB
5
Indexable
Never
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract Nft is Context, ERC721, ERC721Enumerable, ERC721URIStorage, Ownable {
    using Counters for Counters.Counter;

    Counters.Counter public currentTokenId;
    string public baseTokenUri;
    uint256 public mintPrice;
    uint256 public whitelistMintPrice;
    uint256 public mintSupply;
    uint256 public royaltyPercentage;
    address public paymentSplitterContractAddress;
    address public burnerContractAddress;
    bool public mintingEnabled;
    bool public whitelistMintingEnabled;
    mapping(address => uint256) public freeMints;
    mapping(address => bool) public whitelistAddresses;

    bytes4 private constant _INTERFACE_ID_ERC2981 = 0x2a55205a;

    constructor(
        string memory _name,
        string memory _symbol,
        string memory _baseTokenUri,
        uint256 _mintPrice,
        uint256 _maxMintSupply,
        address _paymentSplitterContractAddress,
        address _burnerContractAddress,
        uint256 _whitelistMintPrice,
        uint256 _royaltyPercentage
    ) ERC721(_name, _symbol) {
        setNftMetadata(
            _baseTokenUri,
            _mintPrice,
            _maxMintSupply,
            _paymentSplitterContractAddress,
            _burnerContractAddress,
            _whitelistMintPrice,
            _royaltyPercentage
        );
        whitelistMintingEnabled = false;
        mintingEnabled = false;
    }

    modifier onlyMintingEnabled() {
        require(
            owner() == msg.sender ||
                mintingEnabled == true ||
                (whitelistMintingEnabled && whitelistAddresses[msg.sender]),
            "Minting is closed or this address isn't whitelisted."
        );
        _;
    }

    function setNftMetadata(
        string memory _baseTokenUri,
        uint256 _mintPrice,
        uint256 _maxMintSupply,
        address _paymentSplitterContractAddress,
        address _burnerContractAddress,
        uint256 _whitelistMintPrice,
        uint256 _royaltyPercentage
    ) public onlyOwner {
        baseTokenUri = _baseTokenUri;
        mintPrice = _mintPrice;
        mintSupply = _maxMintSupply;
        paymentSplitterContractAddress = _paymentSplitterContractAddress;
        burnerContractAddress = _burnerContractAddress;
        whitelistMintPrice = _whitelistMintPrice;
        royaltyPercentage = _royaltyPercentage;
    }

    function royaltyInfo(uint256 tokenId, uint256 salesprice) external view returns (address reciever, uint256 royaltyAmount) {
        uint256 royalty = salesprice * royaltyPercentage / 100;
        return (paymentSplitterContractAddress, royalty);
    }

    function setMintingEnabled(
        bool _mintingEnabled,
        bool _whitelistMintingEnabled
    ) public onlyOwner {
        mintingEnabled = _mintingEnabled;
        whitelistMintingEnabled = _whitelistMintingEnabled;
    }

    function getMintPrice(address userAddress) public view returns (uint256) {
        return whitelistAddresses[userAddress] ? whitelistMintPrice : mintPrice;
    }

    function mint(uint256 amount) public payable onlyMintingEnabled {
        require(
            msg.value == getMintPrice(msg.sender) * amount ||
                owner() == msg.sender,
            "Incorrect price sent."
        );
        require(
            currentTokenId.current() + amount <= mintSupply,
            "Not enough supply for mint amount requested."
        );

        for (uint256 i = 0; i < amount; i++) {
            // NFT IDs are 1-indexed, need to add +1 to the counter (0-indexed).
            _mint(msg.sender, currentTokenId.current() + 1);
            currentTokenId.increment();
        }

        if (owner() != msg.sender) {
            payable(paymentSplitterContractAddress).transfer(msg.value);
        }
    }

    function claimFreeMints(uint256 amount) public onlyMintingEnabled {
        require(freeMints[msg.sender] > 0, "No free mints for this address.");
        require(
            currentTokenId.current() + amount <= mintSupply,
            "Not enough supply for mint amount requested."
        );

        for (uint256 i = 0; i < amount; i++) {
            if (freeMints[msg.sender] > 0) {
                // NFT IDs are 1-indexed, need to add +1 to the counter (0-indexed).
                _mint(msg.sender, currentTokenId.current() + 1);
                currentTokenId.increment();
                freeMints[msg.sender]--;
            }
        }
    }

    function setWhitelistAddresses(
        address[] memory userAddresses,
        bool isWhitelisted
    ) public onlyOwner {
        for (uint256 i = 0; i < userAddresses.length; i++) {
            whitelistAddresses[userAddresses[i]] = isWhitelisted;
        }
    }

    function setFreeMintsForAddress(address userAddress, uint256 amount)
        public
        onlyOwner
    {
        freeMints[userAddress] = amount;
    }

    function burn(uint256 tokenId) public {
        transferFrom(msg.sender, burnerContractAddress, tokenId);
    }

    function _burn(uint256 tokenId)
        internal
        virtual
        override(ERC721, ERC721URIStorage)
    {
        return ERC721URIStorage._burn(tokenId);
    }

    function tokenURI(uint256 tokenId)
        public
        view
        override(ERC721, ERC721URIStorage)
        returns (string memory)
    {
        return ERC721URIStorage.tokenURI(tokenId);
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual override(ERC721, ERC721Enumerable) {
        super._beforeTokenTransfer(from, to, tokenId);
    }

    function _baseURI() internal view virtual override returns (string memory) {
        return baseTokenUri;
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(ERC721, ERC721Enumerable)
        returns (bool)
    {
        return interfaceId == _INTERFACE_ID_ERC2981 
            ? true
            : super.supportsInterface(interfaceId);
    }
}