contract OriginERC721_v2 is ERC721Enumerable, Ownable {
    string private _base;

    constructor(
        string memory name,
        string memory symbol,
        string memory baseURI
    ) ERC721(name, symbol) {
        _base = baseURI;
    }

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

    /**
     * @notice Return URI to contract metadata JSON file
     * @return URI to JSON file
     */
    function contractURI() public view returns (string memory) {
        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, "contract.json")) : "";
    }

    /**
     * @notice Change the base url for all NFTs
     */
    function setBaseURI(string calldata base) external onlyOwner {
        _base = base;
    }

    /**
     * @notice Mint multiple NFTs
     * @param to address that new NFTs will belong to
     * @param tokenIds ids of new NFTs to create
     * @param preApprove optional account that is pre-approved to move tokens
     *                   after token creation.
     */
    function massMint(
        address to,
        uint256[] calldata tokenIds,
        address preApprove
    ) external onlyOwner {
        for (uint256 i = 0; i < tokenIds.length; i++) {
            _mint(to, tokenIds[i]);
            if (preApprove != address(0)) {
                _approve(preApprove, tokenIds[i]);
            }
        }
    }

    /**
     * @notice Mint a single nft
     */
    function safeMint(address to, uint256 tokenId) external onlyOwner {
        _safeMint(to, tokenId);
    }

    /**
     * @notice Mint a single nft to a creator, then transfer to a user
     * @param creator address that will show as the creator of the NFT
     * @param to address that new NFTs will belong to
     * @param tokenId id of new NFT
     */
    function mintAndTransfer(
        address creator,
        address to,
        uint256 tokenId
    ) external onlyOwner {
        _mint(creator, tokenId);
        _safeTransfer(creator, to, tokenId, "");
    }
}
function contractURI() public view returns (string memory) {
    string memory baseURI = _baseURI();
    return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, "contract.json")) : "";
}

/**
 * @notice Return URI to contract metadata JSON file
 * @return URI to JSON file
 */