pragma solidity ^0.8.12;







contract Kuroki is Ownable, ERC721A, MDDA {

    uint256 public immutable maxSupply = 5555;

    uint256 public maxMintAmount = 2;

    uint256 public whitelistPrice = 0.08 ether;

    uint256 public publicPrice = 0.1 ether;

    uint256 public whitelistSaleStartTime;

    uint256 public publicSaleStartTime;

    string private _baseTokenURI;



    // ======== MERKLE ROOT ========

    bytes32 public rootWL;

    bytes32 public rootOG;



    // Flag user after mint wl / og

    mapping(address => bool) private mintedUsers;



    constructor() ERC721A("Kuroki Genesis", "KUROKI") {}



    function publicMint(uint256 _mintAmount) external payable {

        uint256 supply = totalSupply();

        uint256 _saleStartTime = uint256(publicSaleStartTime);

        require(

            _saleStartTime != 0 && block.timestamp >= _saleStartTime,

            "Sale has not started yet"

        );

        require(_mintAmount <= maxMintAmount, "Can not mint this many");

        require(supply + _mintAmount <= maxSupply, "Reached max supply");

        require(msg.value >= publicPrice * _mintAmount);

        _safeMint(msg.sender, _mintAmount);

    }



    function mintDutchAuction(uint8 _quantity) external payable {

        DAHook(_quantity, totalSupply());

        _safeMint(msg.sender, _quantity);

    }



    function whitelistMint(bytes32[] memory proof) external payable {

        uint256 supply = totalSupply();

        uint256 _saleStartTime = uint256(whitelistSaleStartTime);

        require(

            _saleStartTime != 0 && block.timestamp >= _saleStartTime,

            "Sale has not started yet"

        );

        require(mintedUsers[msg.sender] == false, "Already minted");

        require(

            isValidWL(proof, keccak256(abi.encodePacked(msg.sender))),

            "Not a part of WL"

        );

        require(supply + 1 <= maxSupply, "Reached max supply");

        require(msg.value >= whitelistPrice);

        mintedUsers[msg.sender] = true;

        _safeMint(msg.sender, 1);

    }



    function ogMint(bytes32[] memory proof) external payable {

        uint256 supply = totalSupply();

        uint256 _saleStartTime = uint256(whitelistSaleStartTime);

        require(

            _saleStartTime != 0 && block.timestamp >= _saleStartTime,

            "Sale has not started yet"

        );

        require(mintedUsers[msg.sender] == false, "Already minted");

        require(

            isValidOG(proof, keccak256(abi.encodePacked(msg.sender))),

            "Not a part of OG"

        );

        require(supply + 2 <= maxSupply, "Reached max supply");

        require(msg.value >= whitelistPrice * 2);

        mintedUsers[msg.sender] = true;

        _safeMint(msg.sender, 2);

    }



    function isValidWL(bytes32[] memory proof, bytes32 leaf)

        public

        view

        returns (bool)

    {

        return MerkleProof.verify(proof, rootWL, leaf);

    }



    function isValidOG(bytes32[] memory proof, bytes32 leaf)

        public

        view

        returns (bool)

    {

        return MerkleProof.verify(proof, rootOG, leaf);

    }



    function getUserMinted() public view returns (bool) {

        return mintedUsers[msg.sender];

    }



    // For marketing etc.

    function devMint(uint256 quantity) external onlyOwner {

        require(totalSupply() + quantity <= maxSupply, "Reached max supply");

        _safeMint(msg.sender, quantity);

    }



    // only owner

    function setMaxMintAmount(uint256 _maxMintAmount) external onlyOwner {

        maxMintAmount = _maxMintAmount;

    }



    function setWhitelistPrice(uint256 _newPrice) external onlyOwner {

        whitelistPrice = _newPrice;

    }



    function setPublicPrice(uint256 _newPrice) external onlyOwner {

        publicPrice = _newPrice;

    }



    function _baseURI() internal view virtual override returns (string memory) {

        return _baseTokenURI;

    }



    function setBaseURI(string calldata baseURI) external onlyOwner {

        _baseTokenURI = baseURI;

    }



    function chWhitelistSaleStartTime(uint256 timestamp) external onlyOwner {

        whitelistSaleStartTime = timestamp;

    }



    function chPublicSaleStartTime(uint256 timestamp) external onlyOwner {

        publicSaleStartTime = timestamp;

    }



    function setRootWL(bytes32 _rootWL) external onlyOwner {

        rootWL = _rootWL;

    }



    function setRootOG(bytes32 _rootOG) external onlyOwner {

        rootOG = _rootOG;

    }



    function withdrawFunds() external onlyOwner {

        uint256 finalFunds = address(this).balance;

        (bool succ, ) = payable(msg.sender).call{value: finalFunds}("");

        require(succ, "transfer failed");

    }

}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"ApprovalToCurrentOwner","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DATA_SET","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DA_DECREMENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DA_DECREMENT_FREQUENCY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DA_ENDING_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DA_FINAL_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DA_MAX_QUANTITY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DA_QUANTITY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DA_STARTING_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DA_STARTING_TIMESTAMP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INITIAL_FUNDS_WITHDRAWN","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REFUND_ENDED","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"chPublicSaleStartTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"chWhitelistSaleStartTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"devMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUserMinted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_DAStartingPrice","type":"uint256"},{"internalType":"uint256","name":"_DAEndingPrice","type":"uint256"},{"internalType":"uint256","name":"_DADecrement","type":"uint256"},{"internalType":"uint256","name":"_DADecrementFrequency","type":"uint256"},{"internalType":"uint256","name":"_DAStartingTimestamp","type":"uint256"},{"internalType":"uint256","name":"_DAMaxQuantity","type":"uint256"},{"internalType":"uint256","name":"_DAQuantity","type":"uint256"}],"name":"initializeAuctionData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"bytes32","name":"leaf","type":"bytes32"}],"name":"isValidOG","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"bytes32","name":"leaf","type":"bytes32"}],"name":"isValidWL","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxMintAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_quantity","type":"uint8"}],"name":"mintDutchAuction","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"ogMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintAmount","type":"uint256"}],"name":"publicMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"publicPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicSaleStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"refundExtraETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rootOG","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rootWL","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_DAQuantity","type":"uint256"}],"name":"setDAQuantity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxMintAmount","type":"uint256"}],"name":"setMaxMintAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newPrice","type":"uint256"}],"name":"setPublicPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setRefundEnded","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_rootOG","type":"bytes32"}],"name":"setRootOG","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_rootWL","type":"bytes32"}],"name":"setRootWL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newPrice","type":"uint256"}],"name":"setWhitelistPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"userToTokenBatchPriceData","outputs":[{"internalType":"uint128","name":"pricePaid","type":"uint128"},{"internalType":"uint128","name":"quantityMinted","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"userToTokenBatches","outputs":[{"components":[{"internalType":"uint128","name":"pricePaid","type":"uint128"},{"internalType":"uint128","name":"quantityMinted","type":"uint128"}],"internalType":"struct MDDA.TokenBatchPriceData[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"whitelistMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"whitelistPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whitelistSaleStartTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"}]