{"sources":{"Arkyn.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n/// @title ARKYN - daily-mint generative NFT collection on BNB Smart Chain.\n/// @notice 5,555 unique pieces. One free mint per wallet per day\n///         (the day rolls over at 00:00 UTC = 07:00 WIB), extra mints the\n///         same day cost 0.0002 BNB, max 10 paid per wallet per day.\n///         Rarity is drawn at mint: Common 70% / Rare 20% / Epic 8% /\n///         Legendary 2%, with hard per-rarity caps of 3,889 / 1,111 / 444 /\n///         111. Each token stores its rarity and a per-rarity variant index\n///         on-chain; tokenURI points at {baseURI}{rarity}/{variant}.json so\n///         every piece's pre-rendered art and metadata resolve statically.\n///         Tokens minted via a paid mint are flagged on-chain in\n///         paidMintOf: a future ARKYN token mining contract reads that\n///         flag to decide mining eligibility (paid-mint pieces only).\ncontract Arkyn {\n    string public name = \"ARKYN\";\n    string public symbol = \"ARKYN\";\n\n    uint256 public constant MAX_SUPPLY = 5555;\n    uint256 public constant PAID_PRICE = 0.0002 ether;\n    uint256 public constant MAX_PAID_PER_DAY = 10;\n\n    // rarity ids: 0 Common, 1 Rare, 2 Epic, 3 Legendary\n    uint256[4] public RARITY_CAPS = [3889, 1111, 444, 111];\n\n    address public owner;\n    bool public mintActive = true;\n    string public baseURI = \"https://arkyn.fun/metadata/\";\n\n    uint256 public totalMinted;\n    uint256[4] public rarityMinted;\n    mapping(uint256 => uint8) public rarityOf;\n    mapping(uint256 => uint32) public variantOf;\n    mapping(uint256 => bool) public paidMintOf; // true only for paid-mint tokens\n\n    mapping(address => uint256) public lastFreeDay; // day index of last free mint\n    mapping(address => uint256) public paidDay; // day index the paid counter belongs to\n    mapping(address => uint256) public paidCount; // paid mints used on paidDay\n\n    // ---- ERC-721 storage ----\n    mapping(uint256 => address) private _owners;\n    mapping(address => uint256) private _balances;\n    mapping(uint256 => address) private _tokenApprovals;\n    mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n    event Approval(address indexed owner_, address indexed approved, uint256 indexed tokenId);\n    event ApprovalForAll(address indexed owner_, address indexed operator, bool approved);\n    event Minted(address indexed minter, uint256 indexed tokenId, uint8 rarity, uint32 variant, bool paid);\n\n    modifier onlyOwner() {\n        require(msg.sender == owner, \"not owner\");\n        _;\n    }\n\n    constructor() {\n        owner = msg.sender;\n    }\n\n    /// @notice Current day index. Days roll at 00:00 UTC, which is 07:00 WIB.\n    function today() public view returns (uint256) {\n        return block.timestamp / 86400;\n    }\n\n    // ---------------------------------------------------------------- mint\n    function mintFree() external {\n        require(mintActive, \"mint paused\");\n        require(totalMinted < MAX_SUPPLY, \"sold out\");\n        uint256 d = today();\n        require(lastFreeDay[msg.sender] < d, \"free mint already used today\");\n        lastFreeDay[msg.sender] = d;\n        _mint(msg.sender, false);\n    }\n\n    function mintPaid() external payable {\n        require(mintActive, \"mint paused\");\n        require(totalMinted < MAX_SUPPLY, \"sold out\");\n        require(msg.value == PAID_PRICE, \"send exactly 0.0002 BNB\");\n        uint256 d = today();\n        if (paidDay[msg.sender] != d) {\n            paidDay[msg.sender] = d;\n            paidCount[msg.sender] = 0;\n        }\n        require(paidCount[msg.sender] < MAX_PAID_PER_DAY, \"daily paid limit reached\");\n        paidCount[msg.sender] += 1;\n        _mint(msg.sender, true);\n    }\n\n    function _mint(address to, bool paid) internal {\n        uint8 rarity = _drawRarity(to);\n        uint32 variant = uint32(rarityMinted[rarity]);\n        rarityMinted[rarity] += 1;\n        totalMinted += 1;\n        uint256 tokenId = totalMinted;\n        rarityOf[tokenId] = rarity;\n        variantOf[tokenId] = variant;\n        if (paid) paidMintOf[tokenId] = true;\n        _owners[tokenId] = to;\n        _balances[to] += 1;\n        emit Transfer(address(0), to, tokenId);\n        emit Minted(to, tokenId, rarity, variant, paid);\n    }\n\n    /// @dev Draws a rarity from the 70/20/8/2 weights using the previous\n    ///      block hash, then enforces the per-rarity caps: if the drawn\n    ///      tier is full, the highest tier with room is used instead.\n    function _drawRarity(address minter) internal view returns (uint8) {\n        uint256 roll = uint256(\n            keccak256(abi.encodePacked(blockhash(block.number - 1), minter, totalMinted, block.timestamp))\n        ) % 10000;\n        uint8 drawn;\n        if (roll < 200) drawn = 3;\n        else if (roll < 1000) drawn = 2;\n        else if (roll < 3000) drawn = 1;\n        else drawn = 0;\n        if (rarityMinted[drawn] < RARITY_CAPS[drawn]) return drawn;\n        for (uint8 t = 3; t > 0; t--) {\n            if (rarityMinted[t] < RARITY_CAPS[t]) return t;\n        }\n        return 0;\n    }\n\n    // ------------------------------------------------------------- metadata\n    function rarityName(uint8 r) public pure returns (string memory) {\n        if (r == 3) return \"legendary\";\n        if (r == 2) return \"epic\";\n        if (r == 1) return \"rare\";\n        return \"common\";\n    }\n\n    function tokenURI(uint256 tokenId) public view returns (string memory) {\n        require(_owners[tokenId] != address(0), \"nonexistent token\");\n        return string(\n            abi.encodePacked(baseURI, rarityName(rarityOf[tokenId]), \"/\", _toString(variantOf[tokenId]), \".json\")\n        );\n    }\n\n    function _toString(uint256 v) internal pure returns (string memory) {\n        if (v == 0) return \"0\";\n        uint256 digits;\n        uint256 tmp = v;\n        while (tmp > 0) {\n            digits++;\n            tmp /= 10;\n        }\n        bytes memory buf = new bytes(digits);\n        while (v > 0) {\n            digits--;\n            buf[digits] = bytes1(uint8(48 + (v % 10)));\n            v /= 10;\n        }\n        return string(buf);\n    }\n\n    // ------------------------------------------------------------ ERC-721\n    function balanceOf(address account) public view returns (uint256) {\n        require(account != address(0), \"zero address\");\n        return _balances[account];\n    }\n\n    function ownerOf(uint256 tokenId) public view returns (address) {\n        address o = _owners[tokenId];\n        require(o != address(0), \"nonexistent token\");\n        return o;\n    }\n\n    function approve(address to, uint256 tokenId) external {\n        address o = ownerOf(tokenId);\n        require(msg.sender == o || _operatorApprovals[o][msg.sender], \"not authorized\");\n        _tokenApprovals[tokenId] = to;\n        emit Approval(o, to, tokenId);\n    }\n\n    function getApproved(uint256 tokenId) public view returns (address) {\n        require(_owners[tokenId] != address(0), \"nonexistent token\");\n        return _tokenApprovals[tokenId];\n    }\n\n    function setApprovalForAll(address operator, bool approved) external {\n        _operatorApprovals[msg.sender][operator] = approved;\n        emit ApprovalForAll(msg.sender, operator, approved);\n    }\n\n    function isApprovedForAll(address account, address operator) public view returns (bool) {\n        return _operatorApprovals[account][operator];\n    }\n\n    function transferFrom(address from, address to, uint256 tokenId) public {\n        require(_isApprovedOrOwner(msg.sender, tokenId), \"not authorized\");\n        require(ownerOf(tokenId) == from, \"wrong from\");\n        require(to != address(0), \"zero address\");\n        _tokenApprovals[tokenId] = address(0);\n        _balances[from] -= 1;\n        _balances[to] += 1;\n        _owners[tokenId] = to;\n        emit Transfer(from, to, tokenId);\n    }\n\n    function safeTransferFrom(address from, address to, uint256 tokenId) external {\n        safeTransferFrom(from, to, tokenId, \"\");\n    }\n\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public {\n        transferFrom(from, to, tokenId);\n        if (to.code.length > 0) {\n            (bool ok, bytes memory ret) = to.call(\n                abi.encodeWithSelector(0x150b7a5e, msg.sender, from, tokenId, data)\n            );\n            require(\n                ok && ret.length == 32 && abi.decode(ret, (bytes4)) == bytes4(0x150b7a5e),\n                \"receiver cannot handle ERC721\"\n            );\n        }\n    }\n\n    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {\n        address o = ownerOf(tokenId);\n        return spender == o || _tokenApprovals[tokenId] == spender || _operatorApprovals[o][spender];\n    }\n\n    function supportsInterface(bytes4 interfaceId) public pure returns (bool) {\n        return interfaceId == 0x80ac58cd // ERC721\n            || interfaceId == 0x5b5e139f // ERC721Metadata\n            || interfaceId == 0x01ffc9a7; // ERC165\n    }\n\n    // --------------------------------------------------------------- admin\n    function setMintActive(bool active) external onlyOwner {\n        mintActive = active;\n    }\n\n    function setBaseURI(string calldata uri) external onlyOwner {\n        baseURI = uri;\n    }\n\n    /// @notice Moves all paid-mint proceeds to the owner wallet.\n    function withdraw() external onlyOwner {\n        uint256 amount = address(this).balance;\n        require(amount > 0, \"nothing to withdraw\");\n        (bool ok, ) = payable(owner).call{value: amount}(\"\");\n        require(ok, \"withdraw failed\");\n    }\n}\n"}},"abi":[{"type":"constructor","inputs":[],"stateMutability":"nonpayable"},{"name":"Approval","type":"event","inputs":[{"name":"owner_","type":"address","indexed":true,"internalType":"address"},{"name":"approved","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"name":"ApprovalForAll","type":"event","inputs":[{"name":"owner_","type":"address","indexed":true,"internalType":"address"},{"name":"operator","type":"address","indexed":true,"internalType":"address"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"name":"Minted","type":"event","inputs":[{"name":"minter","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"rarity","type":"uint8","indexed":false,"internalType":"uint8"},{"name":"variant","type":"uint32","indexed":false,"internalType":"uint32"},{"name":"paid","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"name":"Transfer","type":"event","inputs":[{"name":"from","type":"address","indexed":true,"internalType":"address"},{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"tokenId","type":"uint256","indexed":true,"internalType":"uint256"}],"anonymous":false},{"name":"MAX_PAID_PER_DAY","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"MAX_SUPPLY","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"PAID_PRICE","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"RARITY_CAPS","type":"function","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"approve","type":"function","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"balanceOf","type":"function","inputs":[{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"baseURI","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"getApproved","type":"function","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"isApprovedForAll","type":"function","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"lastFreeDay","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"mintActive","type":"function","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"mintFree","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"name":"mintPaid","type":"function","inputs":[],"outputs":[],"stateMutability":"payable"},{"name":"name","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"owner","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"ownerOf","type":"function","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"paidCount","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"paidDay","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"paidMintOf","type":"function","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"rarityMinted","type":"function","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"rarityName","type":"function","inputs":[{"name":"r","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"pure"},{"name":"rarityOf","type":"function","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"name":"safeTransferFrom","type":"function","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"safeTransferFrom","type":"function","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"},{"name":"data","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setApprovalForAll","type":"function","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setBaseURI","type":"function","inputs":[{"name":"uri","type":"string","internalType":"string"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setMintActive","type":"function","inputs":[{"name":"active","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"supportsInterface","type":"function","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"pure"},{"name":"symbol","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"today","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"tokenURI","type":"function","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"totalMinted","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"transferFrom","type":"function","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"variantOf","type":"function","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint32","internalType":"uint32"}],"stateMutability":"view"},{"name":"withdraw","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"}],"matchId":"59110931","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-11-11T16:55:57Z","match":"exact_match","chainId":"56","address":"0x69b0B5756671680766d232eb4b0f39a34BE5d852"}