// SPDX-License-Identifier: MIT

pragma solidity 0.8.9;

import "erc721a/contracts/ERC721A.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

/*
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@     @@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@            @@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@               @@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@                @@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@                 @@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@  /            @ @@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@ #              @@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@ @             @@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@       (@/#@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@       @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
*/

contract Kosekai is ERC721A, Ownable {
    enum SaleStatus {
        PAUSED,
        SPIRITLIST,
        PUBLIC,
        CLOSED
    }

    using Strings for uint256;
    using ECDSA for bytes32;

    // Set default sale state as paused
    SaleStatus public saleStatus = SaleStatus.PAUSED;

    string private preRevealURI;
    string private postRevealBaseURI;

    // Sale Settings

    // Reserved Tokens used for Ethereal Airdrops and Mods.
    uint256 public constant RESERVED_TOKENS = 200; // 200

    // Ethereals will be airdropped 1 free Kosekai for minting 2.
    uint256 public constant MAX_ETHEREAL_MINT = 2;
    uint256 public constant MAX_SPIRIT_LIST_MINT = 2;
    uint256 public constant MAX_PUBLIC_MINT = 3;
    uint256 public constant MAX_MOD_MINT = 7;
    uint256 public constant MAX_FREE_MINT = 1; // < 5 free mint winners

    uint256 public maxSupply = 5678;

    // Prices
    uint256 public spiritListCost = 0.05 ether;
    uint256 public publicCost = 0.09 ether;

    // Check Lists
    // Ethereals will be airdropped one free Kosekai for minting two.
    bytes32 public etherealListMerkleRoot;
    bytes32 public spiritListMerkleRoot;
    bytes32 public freeMintListMerkleRoot; // < 5 free mint winners
    bytes32 public modListMerkleRoot;

    // Quantity checks
    mapping(address => uint256) public etherealMintedAmount;
    mapping(address => uint256) public spiritListMintedAmount;
    mapping(address => uint256) public freeMintListMintedAmount;
    mapping(address => uint256) public publicMintedAmount;
    mapping(address => uint256) public modMintedAmount;

    // Reveal vars
    bool public revealed = false;

    event Minted(address indexed receiver, uint256 quantity);

    constructor(string memory _initNotRevealedUri)
        ERC721A("Kosekai Collective", "KOSEKAI")
    {
        preRevealURI = _initNotRevealedUri;
        _mint(msg.sender, RESERVED_TOKENS);
    }

    // ------ METADATA
    function setPreRevealURI(string memory _URI) external onlyOwner {
        preRevealURI = _URI;
    }

    function setPostRevealBaseURI(string memory _URI) external onlyOwner {
        postRevealBaseURI = _URI;
    }

    // ------ Prevention from minting off of Contract
    modifier callerIsUser() {
        require(tx.origin == msg.sender, "The caller is another contract");
        _;
    }

    // ------ TOKEN URI
    // Before reveal, return same pre-reveal URI
    // After reveal, return post-reveal URI
    function tokenURI(uint256 _tokenId)
        public
        view
        override
        returns (string memory)
    {
        require(
            _exists(_tokenId),
            "ERC721Metadata: URI query for nonexistent token"
        );
        if (!revealed)
            return string(abi.encodePacked(preRevealURI, _tokenId.toString()));
        return string(abi.encodePacked(postRevealBaseURI, _tokenId.toString()));
    }

    function _startTokenId() internal pure override returns (uint256) {
        return 1;
    }

    // ------ SET SALE STATUS
    function setSaleStatus(SaleStatus _status) external onlyOwner {
        saleStatus = _status;
    }

    // ------ MERKLE ROOTS TO VERIFY ON LISTS
    function setMerkleRoots(
        bytes32 _spiritListMerkleRoot,
        bytes32 _modListMerkleRoot,
        bytes32 _etherealListMerkleRoot,
        bytes32 _freeMintListMerkleRoot
    ) external onlyOwner {
        spiritListMerkleRoot = _spiritListMerkleRoot;
        modListMerkleRoot = _modListMerkleRoot;
        etherealListMerkleRoot = _etherealListMerkleRoot;
        freeMintListMerkleRoot = _freeMintListMerkleRoot;
    }

    function setSpiritListMerkleRoot(bytes32 _spiritListMerkleRoot)
        external
        onlyOwner
    {
        spiritListMerkleRoot = _spiritListMerkleRoot;
    }

    function setModListMerkleRoot(bytes32 _modListMerkleRoot)
        external
        onlyOwner
    {
        modListMerkleRoot = _modListMerkleRoot;
    }

    function setEtherealListMerkleRoot(bytes32 _etherealListMerkleRoot)
        external
        onlyOwner
    {
        etherealListMerkleRoot = _etherealListMerkleRoot;
    }

    function setFreeMintListMerkleRoot(bytes32 _freeMintListMerkleRoot)
        external
        onlyOwner
    {
        freeMintListMerkleRoot = _freeMintListMerkleRoot;
    }

    //  ------ ETHEREAL SALE
    //  ------ Ethereals will be airdropped one free Kosekai for minting two
    function etherealSale(bytes32[] memory _proof, uint8 _quantity)
        external
        payable
        callerIsUser
    {
        require(
            saleStatus == SaleStatus.SPIRITLIST ||
                saleStatus == SaleStatus.PUBLIC,
            "ETHEREAL SALE NOT ACTIVE"
        );
        require(
            MerkleProof.verify(
                _proof,
                etherealListMerkleRoot,
                keccak256(abi.encodePacked(msg.sender))
            ),
            "MINTER IS NOT ON ETHEREAL LIST"
        );
        require(_quantity >= 1, "QUANTITY MUST BE GREATER OR EQUAL TO 1");
        require(!revealed, "NO MINTS POSTREVEAL");
        require(
            totalSupply() + _quantity <= maxSupply,
            "MAX CAP OF KOSEKAI EXCEEDED"
        );
        require(
            etherealMintedAmount[msg.sender] + _quantity <= MAX_ETHEREAL_MINT,
            "QUANTITY EXCEEDS MAXIMUM FOR THIS WALLET"
        );

        require(msg.value == spiritListCost * _quantity, "INCORRECT ETH SENT");

        etherealMintedAmount[msg.sender] += _quantity;
        _mint(msg.sender, _quantity);

        emit Minted(msg.sender, _quantity);
    }

    function spiritListSale(bytes32[] memory _proof, uint8 _quantity)
        external
        payable
        callerIsUser
    {
        require(
            saleStatus == SaleStatus.SPIRITLIST ||
                saleStatus == SaleStatus.PUBLIC,
            "SPIRITLIST SALE NOT ACTIVE"
        );
        require(
            MerkleProof.verify(
                _proof,
                spiritListMerkleRoot,
                keccak256(abi.encodePacked(msg.sender))
            ),
            "MINTER IS NOT ON SPIRIT LIST"
        );
        require(_quantity >= 1, "QUANTITY MUST BE GREATER OR EQUAL TO 1");
        require(!revealed, "NO MINTS POSTREVEAL");
        require(
            totalSupply() + _quantity <= maxSupply,
            "MAX CAP OF KOSEKAI EXCEEDED"
        );
        require(
            spiritListMintedAmount[msg.sender] + _quantity <=
                MAX_SPIRIT_LIST_MINT,
            "QUANTITY EXCEEDS MAXIMUM FOR THIS WALLET"
        );
        require(msg.value == spiritListCost * _quantity, "INCORRECT ETH SENT");

        spiritListMintedAmount[msg.sender] += _quantity;
        _mint(msg.sender, _quantity);

        emit Minted(msg.sender, _quantity);
    }

    // ------ < 5 free mint winners
    function freeMintListSale(bytes32[] memory _proof, uint8 _quantity)
        external
        callerIsUser
    {
        require(
            saleStatus == SaleStatus.SPIRITLIST ||
                saleStatus == SaleStatus.PUBLIC,
            "FREE MINT SALE NOT ACTIVE"
        );
        require(
            MerkleProof.verify(
                _proof,
                freeMintListMerkleRoot,
                keccak256(abi.encodePacked(msg.sender))
            ),
            "MINTER IS NOT ON FREE MINT LIST"
        );
        require(_quantity >= 1, "QUANTITY MUST BE GREATER OR EQUAL TO 1");
        require(!revealed, "NO MINTS POSTREVEAL");
        require(
            totalSupply() + _quantity <= maxSupply,
            "MAX CAP OF KOSEKAI EXCEEDED"
        );
        require(
            freeMintListMintedAmount[msg.sender] + _quantity <= MAX_FREE_MINT,
            "QUANTITY EXCEEDS MAXIMUM FOR THIS WALLET"
        );

        freeMintListMintedAmount[msg.sender] += _quantity;
        _mint(msg.sender, _quantity);

        emit Minted(msg.sender, _quantity);
    }

    function publicListSale(uint8 _quantity) external payable callerIsUser {
        require(saleStatus == SaleStatus.PUBLIC, "PUBLIC SALE NOT ACTIVE");
        require(_quantity >= 1, "QUANTITY MUST BE GREATER OR EQUAL TO 1");
        require(!revealed, "NO MINTS POSTREVEAL");
        require(
            totalSupply() + _quantity <= maxSupply,
            "MAX CAP OF KOSEKAI EXCEEDED"
        );
        require(
            publicMintedAmount[msg.sender] + _quantity <= MAX_PUBLIC_MINT,
            "QUANTITY EXCEEDS MAXIMUM FOR THIS WALLET"
        );
        require(msg.value == publicCost * _quantity, "INCORRECT ETH SENT");

        publicMintedAmount[msg.sender] += _quantity;
        _mint(msg.sender, _quantity);

        emit Minted(msg.sender, _quantity);
    }

    function modListSale(bytes32[] memory _proof, uint8 _quantity)
        external
        callerIsUser
    {
        require(
            saleStatus == SaleStatus.SPIRITLIST ||
                saleStatus == SaleStatus.PUBLIC,
            "MOD SALE NOT ACTIVE"
        );
        require(
            MerkleProof.verify(
                _proof,
                modListMerkleRoot,
                keccak256(abi.encodePacked(msg.sender))
            ),
            "MINTER IS NOT ON MOD LIST"
        );
        require(_quantity >= 1, "QUANTITY MUST BE GREATER OR EQUAL TO 1");
        require(!revealed, "NO MINTS POSTREVEAL");
        require(
            totalSupply() + _quantity <= maxSupply,
            "MAX CAP OF KOSEKAI EXCEEDED"
        );
        require(modMintedAmount[msg.sender] + _quantity <= MAX_MOD_MINT, "QUANTITY EXCEEDS MAXIMUM FOR THIS WALLET");

        modMintedAmount[msg.sender] += _quantity;
        _mint(msg.sender, _quantity);

        emit Minted(msg.sender, _quantity);
    }

    function setRevealed(bool _revealed) external onlyOwner {
        revealed = _revealed;
    }

    function numberMinted(address _owner) public view returns (uint256) {
        return _numberMinted(_owner);
    }

    function getOwnershipData(uint256 _tokenId)
        external
        view
        returns (TokenOwnership memory)
    {
        return _ownershipOf(_tokenId);
    }

    // ------ DECREASE MAX SUPPLY ONLY
    function setMaxSupply(uint256 amount) external onlyOwner {
        require(
            amount < maxSupply,
            "Cannot increase supply greater than current max supply!"
        );
        maxSupply = amount;
    }

    function changeSpiritListCost(uint256 newCost) external onlyOwner {
        spiritListCost = newCost;
    }

    function changePublicCost(uint256 newCost) external onlyOwner {
        publicCost = newCost;
    }

    // ------ WITHDRAW FUNDS
    function withdraw() external onlyOwner {
        (bool success, ) = msg.sender.call{value: address(this).balance}("");
        if (!success) {
            revert("Ether transfer failed");
        }
    }
}
[{"inputs":[{"internalType":"string","name":"_initNotRevealedUri","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"ApproveToCaller","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","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":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"Minted","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":"MAX_ETHEREAL_MINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FREE_MINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_MOD_MINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PUBLIC_MINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SPIRIT_LIST_MINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESERVED_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"newCost","type":"uint256"}],"name":"changePublicCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newCost","type":"uint256"}],"name":"changeSpiritListCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"etherealListMerkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"etherealMintedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"},{"internalType":"uint8","name":"_quantity","type":"uint8"}],"name":"etherealSale","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"freeMintListMerkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"freeMintListMintedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"},{"internalType":"uint8","name":"_quantity","type":"uint8"}],"name":"freeMintListSale","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":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getOwnershipData","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"},{"internalType":"uint24","name":"extraData","type":"uint24"}],"internalType":"struct IERC721A.TokenOwnership","name":"","type":"tuple"}],"stateMutability":"view","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":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"modListMerkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"},{"internalType":"uint8","name":"_quantity","type":"uint8"}],"name":"modListSale","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"modMintedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"numberMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[],"name":"publicCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"_quantity","type":"uint8"}],"name":"publicListSale","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"publicMintedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revealed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[],"name":"saleStatus","outputs":[{"internalType":"enum Kosekai.SaleStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_etherealListMerkleRoot","type":"bytes32"}],"name":"setEtherealListMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_freeMintListMerkleRoot","type":"bytes32"}],"name":"setFreeMintListMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setMaxSupply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_spiritListMerkleRoot","type":"bytes32"},{"internalType":"bytes32","name":"_modListMerkleRoot","type":"bytes32"},{"internalType":"bytes32","name":"_etherealListMerkleRoot","type":"bytes32"},{"internalType":"bytes32","name":"_freeMintListMerkleRoot","type":"bytes32"}],"name":"setMerkleRoots","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_modListMerkleRoot","type":"bytes32"}],"name":"setModListMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_URI","type":"string"}],"name":"setPostRevealBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_URI","type":"string"}],"name":"setPreRevealURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_revealed","type":"bool"}],"name":"setRevealed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum Kosekai.SaleStatus","name":"_status","type":"uint8"}],"name":"setSaleStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_spiritListMerkleRoot","type":"bytes32"}],"name":"setSpiritListMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"spiritListCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"spiritListMerkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"spiritListMintedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"},{"internalType":"uint8","name":"_quantity","type":"uint8"}],"name":"spiritListSale","outputs":[],"stateMutability":"payable","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":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]