{"sources":{"src/CharmDaily.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.28;\n\nimport {ERC721} from \"openzeppelin-contracts/contracts/token/ERC721/ERC721.sol\";\nimport {ReentrancyGuard} from \"openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol\";\nimport {CharmDailyRenderer} from \"./CharmDailyRenderer.sol\";\nimport {CharmDailyRandom} from \"./CharmDailyRandom.sol\";\nimport {CharmDailyTickets} from \"./CharmDailyTickets.sol\";\nimport {CharmDailyLucky} from \"./CharmDailyLucky.sol\";\n\n/// @dev Binance Agent ID registry (ERC-721, tokenId == uint256(keccak256(bytes(handle)))).\ninterface IAgentId {\n    function handleOf(address wallet) external view returns (string memory);\n    function ownerOf(uint256 tokenId) external view returns (address);\n}\n\n/// @title sidecoo Daily\n/// @notice A lucky charm a day for every Binance Agent ID on BNB Smart Chain.\n///\n///  * Every draw needs an Agent ID. Daily allowances count per Agent ID (keccak256 of the handle), not per\n///    wallet, and reset at 00:00 UTC.\n///  * Free: one draw a day per Agent ID, plus the holder extra draws below. Entry: value-0 mint(qty),\n///    mint(), freeMint(), claim().\n///  * Paid: mint(qty) with value >= qty x PRICE, qty 1..9, at most 9 paid draws per Agent ID per day. Same\n///    price for everyone. Any amount above qty x PRICE is returned in the same transaction.\n///  * Bonus: every 3 paid draws in a day (counted across transactions) add 1 bonus draw in the same\n///    transaction. Bonus and free draws do not count toward the 9 paid draws.\n///  * Base odds for every draw: Common 75%, Rare 20%, Epic 4.5%, Legendary 0.5% (the weekly holder guarantee\n///    below can only raise a draw). Each week has 10 designs and every design is equally likely at every\n///    rarity (design and rarity are drawn independently).\n///  * Holder extras: registerHoldings() adds ticket points to the Agent ID, each ticket once in this\n///    contract. Earlier sidecoo NFTs count if they existed when this contract was deployed (table and cut-off\n///    ids in CharmDailyTickets); paid and bonus sidecoo Daily charms add 1/2/4/10 and source-3 weekly seals 5.\n///    Points 1-4: +1 free draw a day. 5-19: +2, and the first paid draw of each week is at least Rare.\n///    20+: +3, and the first paid draw of each week is at least Epic.\n///  * Reveal: a draw is set by the hash of block (mint block + 16), kept by RANDOM (see CharmDailyRandom):\n///    BLOCKHASH, then EIP-2935 history, then the first kept target hash after it, so every charm can always\n///    be revealed. Every draw keeps hashes and reveals earlier charms; anyone can call reveal(),\n///    saveHashes() and RANDOM.poke(this). Sealed charms cannot be transferred.\n///  * Weekly seal: seal(ids) burns all 10 designs of one week (any rarity) and mints that week's seal,\n///    numbered by completion order. A seal forged only from paid and bonus draws has source 3 and counts as a\n///    ticket; a seal with any free-draw charm in it has source 4 and does not.\n///  * Each draw also keeps up to 2 hashes and reveals at most 1 earlier charm, so its gas stays bounded.\n///  * Lucky charm: once DEPLOYER has bound the sidecoo Season contract (bindSeason, once) and its pool is live,\n///    LUCKY_BPS of every paid draw buys SIDECOO for the drawer in the same transaction (CharmDailyLucky);\n///    the rest goes to PAYEE. Before that, or if the buy fails, all of it goes to PAYEE.\n///  * The contract keeps no BNB. The metadata admin can only change image/link/description/design names; it\n///    cannot touch payments, odds, allowances or the season link.\ncontract CharmDaily is ERC721, ReentrancyGuard {\n    // ------------------------------------------------------------------ constants\n    /// @dev The collection name and symbol live only here (rename = change these two lines).\n    string private constant NAME = \"sidecoo Daily\";\n    string private constant SYMBOL = \"SCDAILY\";\n    uint256 public constant MAX_PAID_PER_DAY = 9;\n    uint256 public constant PRICE = 0.001 ether;\n    uint256 public constant ROYALTY_BPS = 500; // 5% to PAYEE (ERC-2981)\n    uint256 private constant BONUS_EVERY = 3;\n    uint256 private constant BASE_FREE_PER_DAY = 1;\n    uint256 private constant KINDS = 10;\n    uint256 private constant WEEK_DAYS = 7;\n    uint256 public constant REVEAL_DELAY = 16;\n    uint256 private constant MAX_BATCH = 32;\n\n    /// @dev odds out of 10,000 (Legendary 0.5%, Epic 4.5%, Rare 20%, Common the rest)\n    uint256 private constant LEGENDARY_BP = 50;\n    uint256 private constant EPIC_BP = 450;\n    uint256 private constant RARE_BP = 2000;\n\n    /// @dev tiers 0 Common, 1 Rare, 2 Epic, 3 Legendary; sources 0 free, 1 paid, 2 bonus, 3 / 4 weekly seal;\n    ///      ticket series 0 Pass, 1 Atlas S1, 2 Atlas II S2, 3 sidecoo Daily charm, 4 sidecoo Daily seal.\n    uint8 private constant SRC_FREE = 0;\n    uint8 private constant SRC_PAID = 1;\n    uint8 private constant SRC_BONUS = 2;\n    uint8 private constant SRC_SEAL = 3; // weekly seal, all 10 charms from paid or bonus draws\n    uint8 private constant SRC_SEAL_FREE = 4; // weekly seal with at least one free-draw charm\n\n    // ------------------------------------------------------------------ config\n    IAgentId public immutable AGENT_ID;\n    CharmDailyRenderer public immutable RENDERER;\n    CharmDailyRandom public immutable RANDOM;\n    CharmDailyTickets public immutable TICKETS;\n    address public immutable PAYEE;\n    uint256 public immutable START_DAY; // UTC day index of deployment; week 1 starts at its 00:00 UTC\n    CharmDailyLucky public immutable LUCKY;\n    uint256 public immutable LUCKY_BPS; // share of each paid draw that buys SIDECOO for the drawer once live\n    address public immutable DEPLOYER;\n\n    struct Config {\n        address agentId;\n        address renderer;\n        address random;\n        address tickets;\n        address payee;\n        address deployer; // the only account that may send the deployment transaction (tx.origin)\n        address lucky;\n        uint256 luckyBps;\n    }\n\n    // ------------------------------------------------------------------ state\n    struct Token {\n        uint32 week; // 0 = does not exist\n        uint64 agent; // agent index of the minter (0 for seals)\n        uint64 target; // reveal block (0 for seals)\n        uint8 tier;\n        uint8 kind;\n        uint8 floor; // minimum tier (weekly holder guarantee)\n        uint8 source;\n        bool revealed;\n        uint32 rank; // seal number within its week\n    }\n\n    struct Agent {\n        uint64 index;\n    }\n\n    struct Day {\n        uint8 free;\n        uint8 paid;\n        uint8 bonus;\n    }\n\n    struct WeekStats {\n        uint32 drawn;\n        uint32 seals;\n    }\n\n    mapping(uint256 => Token) private _tokens;\n    mapping(bytes32 => Agent) private _agents;\n    mapping(bytes32 => mapping(uint256 => Day)) private _days;\n    mapping(bytes32 => mapping(uint256 => bool)) private _firstPaidDone; // agent => week => first paid draw taken\n    mapping(uint64 => mapping(uint256 => uint16)) private _drawnMask; // agent index => week => designs revealed\n    mapping(uint256 => WeekStats) private _weeks;\n    mapping(uint256 => uint256) private _weekRevealed; // week => 4 x uint64 revealed counts by tier\n    uint64 private _agentCount;\n\n    uint256 public totalMinted;\n    uint256 public burned;\n    uint256 public sealedCount;\n    uint256 public revealCursor = 1;\n\n    // ------------------------------------------------------------------ events / errors\n    event Drawn(\n        address indexed to, bytes32 indexed agent, uint256 firstId, uint256 qty, uint8 source, uint256 targetBlock\n    );\n    event Revealed(uint256 indexed tokenId, uint256 indexed week, uint8 tier, uint8 kind);\n    event WeekSealForged(address indexed to, uint256 indexed week, uint256 indexed tokenId, uint256 rank);\n    event MetadataUpdate(uint256 _tokenId);\n\n    error BadConfig();\n    error NotDeployer();\n    error NoAgentId();\n    error BadQuantity();\n    error NoFreeDraw(uint256 left);\n    error DailyLimit(uint256 left);\n    error WrongPayment(uint256 required);\n    error PaymentFailed();\n    error RefundFailed();\n    error TooMany();\n    error NotRevealable(uint256 tokenId);\n    error SealedTransfer(uint256 tokenId);\n    error NotYourToken(uint256 tokenId);\n    error NotACharm(uint256 tokenId);\n    error WrongWeek(uint256 tokenId);\n    error DuplicateDesign(uint256 tokenId);\n    error NotRevealed(uint256 tokenId);\n\n    /// @dev START_DAY is read here, so only `c.deployer` may deploy this exact initcode (no one can deploy it\n    ///      first through the public CREATE2 factory and choose the start day). The payee cannot be the deployer\n    ///      (RENDERER keeps its metadata admin different from the payee).\n    constructor(Config memory c) ERC721(\"\", \"\") {\n        if (tx.origin != c.deployer) revert NotDeployer();\n        if (c.payee == c.deployer) revert BadConfig();\n        if (\n            c.agentId.code.length == 0 || c.lucky.code.length == 0 || c.payee == address(0)\n                || c.luckyBps > 5000\n        ) revert BadConfig();\n        AGENT_ID = IAgentId(c.agentId);\n        RENDERER = CharmDailyRenderer(c.renderer);\n        RANDOM = CharmDailyRandom(c.random);\n        TICKETS = CharmDailyTickets(c.tickets);\n        PAYEE = c.payee;\n        START_DAY = block.timestamp / 1 days;\n        LUCKY = CharmDailyLucky(c.lucky);\n        LUCKY_BPS = c.luckyBps;\n        DEPLOYER = c.deployer;\n    }\n\n    // ------------------------------------------------------------------ draw entry points\n    /// @notice value 0: qty free draws (up to today's free draws left). value >= qty x PRICE: qty paid draws.\n    function mint(uint256 qty) external payable nonReentrant {\n        _enter(qty);\n    }\n\n    /// @notice One free draw (value 0).\n    function mint() external nonReentrant {\n        _enter(1);\n    }\n\n    function freeMint() external nonReentrant {\n        _enter(1);\n    }\n\n    function claim() external nonReentrant {\n        _enter(1);\n    }\n\n    function _enter(uint256 qty) private {\n        bytes32 key = _agentKey(msg.sender); // STATICCALL to the Agent ID registry on every draw\n        _keep(2, 1); // bounded side work: at most 2 hashes kept and 1 earlier charm revealed\n        Agent storage a = _agentOf(key);\n        Day storage d = _days[key][today()];\n        uint256 points = TICKETS.pointsOf(address(this), key);\n\n        if (msg.value == 0) {\n            uint256 left = _freeLeft(points, d.free);\n            if (qty == 0 || qty > left) revert NoFreeDraw(left);\n            d.free = uint8(d.free + qty);\n            _draw(key, a.index, qty, SRC_FREE, 0);\n            return;\n        }\n\n        if (qty == 0 || qty > MAX_PAID_PER_DAY) revert BadQuantity();\n        uint256 paid = d.paid;\n        if (paid + qty > MAX_PAID_PER_DAY) revert DailyLimit(MAX_PAID_PER_DAY - paid);\n        uint256 cost = qty * PRICE;\n        if (msg.value < cost) revert WrongPayment(cost);\n\n        uint256 newPaid = paid + qty;\n        uint256 bonus = newPaid / BONUS_EVERY - d.bonus;\n        d.paid = uint8(newPaid);\n        d.bonus = uint8(d.bonus + bonus);\n\n        uint256 week = currentWeek();\n        uint8 floor;\n        if (!_firstPaidDone[key][week]) {\n            _firstPaidDone[key][week] = true;\n            floor = _guaranteeTier(points);\n        }\n        _draw(key, a.index, qty, SRC_PAID, floor);\n        if (bonus != 0) _draw(key, a.index, bonus, SRC_BONUS, 0);\n\n        // lucky share: LUCKY buys SIDECOO for the drawer, or passes it on to PAYEE (before launch / on failure)\n        uint256 lucky = cost * LUCKY_BPS / 10_000;\n        if (lucky != 0) {\n            (bool okL,) = address(LUCKY).call{value: lucky}(abi.encodeCall(CharmDailyLucky.buy, (msg.sender)));\n            if (!okL) lucky = 0;\n        }\n        (bool ok,) = PAYEE.call{value: cost - lucky}(\"\");\n        if (!ok) revert PaymentFailed();\n        uint256 excess = msg.value - cost;\n        if (excess != 0) {\n            (bool ok2,) = msg.sender.call{value: excess}(\"\");\n            if (!ok2) revert RefundFailed();\n        }\n    }\n\n    /// @dev Mints qty sealed charms; only the first one carries `firstFloor`.\n    function _draw(bytes32 key, uint64 agentIndex, uint256 qty, uint8 source, uint8 firstFloor) private {\n        uint256 target = block.number + REVEAL_DELAY;\n        RANDOM.queue(target); // no-op if already queued\n        uint32 week = uint32(currentWeek());\n        uint256 first = totalMinted + 1;\n        for (uint256 i; i < qty; ++i) {\n            _tokens[first + i] = Token(week, agentIndex, uint64(target), 0, 0, i == 0 ? firstFloor : 0, source, false, 0);\n            _mint(msg.sender, first + i); // no receiver callback\n        }\n        totalMinted = first + qty - 1;\n        sealedCount += qty;\n        _weeks[week].drawn += uint32(qty);\n        emit Drawn(msg.sender, key, first, qty, source, target);\n    }\n\n    // ------------------------------------------------------------------ holder extras\n    /// @notice Register tickets you hold for this Agent ID (rules and table in TICKETS). Each ticket counts once\n    ///         in this contract; points stay with the Agent ID. Series: 0 Pass, 1 Atlas S1, 2 Atlas II S2\n    ///         (minted before deployment), 3 sidecoo Daily charm (paid or bonus draw, revealed), 4 weekly seal (source 3),\n    ///         5 sidecoo Season NFT (3 points, once the season is bound).\n    ///         Calls TICKETS.register(agent, msg.sender, t) with the ticket list exactly as received.\n    function registerHoldings(CharmDailyTickets.Ticket[] calldata t) external returns (uint256 total) {\n        bytes32 key = _agentKey(msg.sender);\n        _agentOf(key);\n        address tickets = address(TICKETS);\n        bytes4 sel = CharmDailyTickets.register.selector;\n        assembly (\"memory-safe\") {\n            // register(bytes32 agent, address holder, Ticket[] t): head (agent, holder, offset 0x60), then the\n            // array (length + items) copied from this call's calldata\n            let start := sub(t.offset, 32) // the array's length word\n            let size := sub(calldatasize(), start)\n            let p := mload(0x40)\n            mstore(p, sel)\n            mstore(add(p, 4), key)\n            mstore(add(p, 36), caller())\n            mstore(add(p, 68), 0x60)\n            calldatacopy(add(p, 100), start, size)\n            let ok := call(gas(), tickets, 0, p, add(100, size), 0, 32)\n            if iszero(ok) {\n                returndatacopy(p, 0, returndatasize())\n                revert(p, returndatasize())\n            }\n            total := mload(0)\n        }\n    }\n\n    function pointsOf(bytes32 agent) public view returns (uint256) {\n        return TICKETS.pointsOf(address(this), agent);\n    }\n\n    /// @notice 0 none, 1 bronze (1-4 points), 2 silver (5-19), 3 gold (20+).\n    function _levelOf(uint256 points) private pure returns (uint8) {\n        return points >= 20 ? 3 : points >= 5 ? 2 : points >= 1 ? 1 : 0;\n    }\n\n    function _freeLeft(uint256 points, uint256 usedToday) private pure returns (uint256) {\n        uint256 total = BASE_FREE_PER_DAY + _levelOf(points);\n        return usedToday >= total ? 0 : total - usedToday;\n    }\n\n    /// @dev Minimum tier for the first paid draw of the week: silver Rare, gold Epic, else none.\n    function _guaranteeTier(uint256 points) private pure returns (uint8) {\n        uint8 l = _levelOf(points);\n        return l == 3 ? 2 : l == 2 ? 1 : 0;\n    }\n\n    // ------------------------------------------------------------------ weekly seal\n    /// @notice Burn one charm of each of the 10 designs of a week (any rarity) and receive that week's seal.\n    ///         The seal's source is 3 if all 10 came from paid or bonus draws, 4 if any came from a free draw.\n    function seal(uint256[10] calldata ids) external returns (uint256 sealId) {\n        uint32 week = _tokens[ids[0]].week;\n        uint256 mask;\n        uint8 src = SRC_SEAL;\n        for (uint256 i; i < KINDS; ++i) {\n            uint256 id = ids[i];\n            if (_ownerOf(id) != msg.sender) revert NotYourToken(id);\n            Token storage tk = _tokens[id];\n            if (tk.source >= SRC_SEAL) revert NotACharm(id);\n            if (!tk.revealed) revert NotRevealed(id);\n            if (tk.source == SRC_FREE) src = SRC_SEAL_FREE;\n            if (tk.week != week) revert WrongWeek(id);\n            uint256 bit = 1 << tk.kind;\n            if (mask & bit != 0) revert DuplicateDesign(id);\n            mask |= bit;\n            _burn(id);\n        }\n        burned += KINDS;\n        uint32 rank = ++_weeks[week].seals;\n        sealId = ++totalMinted;\n        _tokens[sealId] = Token(week, 0, 0, 0, 0, 0, src, true, rank);\n        _mint(msg.sender, sealId);\n        emit WeekSealForged(msg.sender, week, sealId, rank);\n    }\n\n    // ------------------------------------------------------------------ reveal\n    /// @notice Reveal one charm. Reverts if its hash is not available yet.\n    function reveal(uint256 tokenId) external {\n        RANDOM.keep(2); // bounded like a draw; saveHashes(n) keeps more\n        if (!_tryReveal(tokenId)) revert NotRevealable(tokenId);\n    }\n\n    /// @notice Keeper: keep up to n queued target hashes, then reveal up to n charms from the public cursor.\n    function saveHashes(uint256 n) external returns (uint256 kept, uint256 revealed) {\n        if (n == 0 || n > MAX_BATCH) revert TooMany();\n        return _keep(n, n);\n    }\n\n    /// @dev Keep up to `hashes` queued target hashes, then reveal up to `reveals` charms from the cursor.\n    function _keep(uint256 hashes, uint256 reveals) private returns (uint256 kept, uint256 done) {\n        kept = RANDOM.keep(hashes);\n        uint256 c = revealCursor;\n        uint256 last = totalMinted;\n        for (uint256 steps; steps < reveals * 4 && c <= last; ++steps) {\n            Token storage tk = _tokens[c];\n            if (tk.target != 0 && !tk.revealed) {\n                if (!_tryReveal(c)) break;\n                ++c;\n                if (++done == reveals) break;\n            } else {\n                ++c;\n            }\n        }\n        revealCursor = c;\n    }\n\n    function _tryReveal(uint256 id) private returns (bool) {\n        Token storage tk = _tokens[id];\n        if (tk.target == 0 || tk.revealed) return false;\n        bytes32 h = RANDOM.hashFor(address(this), tk.target);\n        if (h == 0) return false;\n        (uint8 tier, uint8 kind) = _drawOf(h, id);\n        if (tier < tk.floor) tier = tk.floor;\n        tk.tier = tier;\n        tk.kind = kind;\n        tk.revealed = true;\n        sealedCount -= 1;\n        _weekRevealed[tk.week] += 1 << (64 * tier);\n        _drawnMask[tk.agent][tk.week] |= uint16(1 << kind);\n        emit Revealed(id, tk.week, tier, kind);\n        emit MetadataUpdate(id);\n        return true;\n    }\n\n    /// @dev The fixed draw table (RENDERER.drawOf(this, h, id) is the public copy for recomputing results).\n    ///      Rarity and design come from independent bits of the same random word.\n    function _drawOf(bytes32 h, uint256 id) private view returns (uint8 tier, uint8 kind) {\n        uint256 rnd = uint256(keccak256(abi.encode(h, id, address(this))));\n        uint256 roll = rnd % 10_000;\n        tier = roll < LEGENDARY_BP ? 3 : roll < LEGENDARY_BP + EPIC_BP ? 2 : roll < LEGENDARY_BP + EPIC_BP + RARE_BP ? 1 : 0;\n        kind = uint8((rnd >> 128) % KINDS);\n    }\n\n    // ------------------------------------------------------------------ transfer lock\n    function _update(address to, uint256 tokenId, address auth) internal override returns (address) {\n        address from = _ownerOf(tokenId);\n        if (from != address(0) && !_tokens[tokenId].revealed) revert SealedTransfer(tokenId);\n        return super._update(to, tokenId, auth);\n    }\n\n    // ------------------------------------------------------------------ identity\n    function _agentKey(address w) private view returns (bytes32 key) {\n        bool ok;\n        (key, ok) = agentKeyOf(w);\n        if (!ok) revert NoAgentId();\n    }\n\n    /// @notice keccak256(handle) of the Agent ID held by `w`, checked against the registry's ownerOf.\n    function agentKeyOf(address w) public view returns (bytes32 key, bool ok) {\n        try AGENT_ID.handleOf(w) returns (string memory h) {\n            if (bytes(h).length == 0) return (0, false);\n            key = keccak256(bytes(h));\n        } catch {\n            return (0, false);\n        }\n        try AGENT_ID.ownerOf(uint256(key)) returns (address o) {\n            ok = o == w;\n        } catch {}\n        if (!ok) key = 0;\n    }\n\n    function _agentOf(bytes32 key) private returns (Agent storage a) {\n        a = _agents[key];\n        if (a.index == 0) a.index = ++_agentCount;\n    }\n\n    // ------------------------------------------------------------------ views\n    function today() public view returns (uint256) {\n        return block.timestamp / 1 days;\n    }\n\n    /// @notice Week number, 1 for the first 7 UTC days starting on the deployment day.\n    function currentWeek() public view returns (uint256) {\n        return (today() - START_DAY) / WEEK_DAYS + 1;\n    }\n\n    function weekStart(uint256 w) public view returns (uint256) {\n        if (w == 0) return 0;\n        return (START_DAY + (w - 1) * WEEK_DAYS) * 1 days;\n    }\n\n    function totalSupply() external view returns (uint256) {\n        return totalMinted - burned;\n    }\n\n    function mintOpen() external pure returns (bool) {\n        return true;\n    }\n\n    /// @notice No fixed supply: charms are drawn every day. Returned for tools that expect the getter.\n    function MAX_SUPPLY() external pure returns (uint256) {\n        return type(uint256).max;\n    }\n\n    /// @notice Paid draws per Agent ID per day (free and bonus draws come on top).\n    function MAX_PER_WALLET() external pure returns (uint256) {\n        return MAX_PAID_PER_DAY;\n    }\n\n    /// @notice The metadata admin (kept in RENDERER; it can only change display settings).\n    function owner() public view returns (address) {\n        return RENDERER.metadataAdmin();\n    }\n\n    /// @notice The bound sidecoo Season contract (0 until DEPLOYER binds it).\n    function SEASON() external view returns (address) {\n        return LUCKY.seasonOf(address(this));\n    }\n\n    /// @notice DEPLOYER, once: bind the sidecoo Season contract. LUCKY checks that its tickets read this\n    ///         contract and that its DEPLOYER and PAYEE match ours, and keeps the link.\n    function bindSeason(address season) external {\n        if (msg.sender != DEPLOYER) revert NotDeployer();\n        LUCKY.bind(season);\n    }\n\n    /// @notice End of the current week (00:00 UTC): the deadline to collect this week's designs.\n    function nextDeadline() external view returns (uint256) {\n        return weekStart(currentWeek() + 1);\n    }\n\n    /// @notice ERC-2981: ROYALTY_BPS of the sale price to PAYEE.\n    function royaltyInfo(uint256, uint256 salePrice) external view returns (address, uint256) {\n        return (PAYEE, salePrice * ROYALTY_BPS / 10_000);\n    }\n\n    /// @notice What mint(qty) needs from `w` right now. free = true: value 0 works (qty <= free draws left).\n    ///         Otherwise cost = qty x PRICE. tokens includes bonus. tokens = 0: mint(qty) would revert.\n    ///         Computed by RENDERER from agentOn() and pointsOf().\n    function quote(address, uint256)\n        external\n        view\n        returns (uint256 cost, uint256 tokens, uint256 bonus, bool free)\n    {\n        _forward(68);\n    }\n\n    /// @notice One-call summary for agents (fields in CharmDailyRenderer.Status; computed there from the\n    ///         getters below).\n    function status(address) external view returns (CharmDailyRenderer.Status memory) {\n        _forward(36);\n    }\n\n    /// @notice An Agent ID on UTC `day` and in `week`: draws that day (free, paid, bonus); bit k of `designs`\n    ///         set = design k of the week was drawn and revealed by it; firstPaidDone = its first paid draw of\n    ///         the week (the weekly guarantee) is taken.\n    function agentOn(bytes32 agent, uint256 day, uint256 week)\n        external\n        view\n        returns (uint256 free, uint256 paid, uint256 bonus, uint16 designs, bool firstPaidDone)\n    {\n        Day memory d = _days[agent][day];\n        uint64 idx = _agents[agent].index;\n        return (d.free, d.paid, d.bonus, idx == 0 ? 0 : _drawnMask[idx][week], _firstPaidDone[agent][week]);\n    }\n\n    /// @notice Week `w`: start and end (00:00 UTC), whether it is the current week, charms drawn, seals forged,\n    ///         revealed charms by rarity [Common, Rare, Epic, Legendary]. Computed by RENDERER from weekCounts().\n    function weekInfo(uint256)\n        external\n        view\n        returns (uint256 start, uint256 end, bool current, uint256 drawn, uint256 seals, uint256[4] memory revealedByTier)\n    {\n        _forward(36);\n    }\n\n    /// @notice Raw counters of week `w`: drawn, seals forged, and revealed counts packed as 4 x 64 bits by tier.\n    function weekCounts(uint256 w) external view returns (uint256 drawn, uint256 seals, uint256 revealedPacked) {\n        WeekStats storage ws = _weeks[w];\n        return (ws.drawn, ws.seals, _weekRevealed[w]);\n    }\n\n    /// @notice Token record: week, tier (0 Common..3 Legendary), design 0..9, source (0 free, 1 paid, 2 bonus,\n    ///         3 seal of paid/bonus charms, 4 seal with a free-draw charm), revealed, seal, seal number, reveal\n    ///         block, minimum tier, revealable now.\n    ///         Decoded by RENDERER from tokenRecord().\n    function tokenInfo(uint256)\n        external\n        view\n        returns (\n            uint256 week,\n            uint8 tier,\n            uint8 kind,\n            uint8 source,\n            bool revealed,\n            bool isSeal_,\n            uint256 sealRank,\n            uint256 targetBlock,\n            uint8 minTier,\n            bool revealable\n        )\n    {\n        _forward(36);\n    }\n\n    /// @notice The raw storage word of token `id` (struct Token, packed from the lowest bit: week 32, agent 64,\n    ///         target 64, tier 8, kind 8, floor 8, source 8, revealed 8, rank 32). 0 if it never existed.\n    function tokenRecord(uint256 id) external view returns (uint256 raw) {\n        Token storage t = _tokens[id];\n        assembly (\"memory-safe\") {\n            raw := sload(t.slot)\n        }\n    }\n\n    /// @notice Rarity of a revealed charm (0 Common .. 3 Legendary). Reverts for seals and sealed charms.\n    function tierOf(uint256 id) external view returns (uint8) {\n        _requireOwned(id);\n        Token memory t = _tokens[id];\n        if (t.source >= SRC_SEAL) revert NotACharm(id);\n        if (!t.revealed) revert NotRevealed(id);\n        return t.tier;\n    }\n\n    function isSeal(uint256 id) external view returns (bool) {\n        _requireOwned(id);\n        return _tokens[id].source >= SRC_SEAL;\n    }\n\n    // ------------------------------------------------------------------ metadata (rendered by RENDERER)\n    function tokenURI(uint256 id) public view override returns (string memory) {\n        _requireOwned(id);\n        _forward(36);\n    }\n\n    function contractURI() external view returns (string memory) {\n        _forward(4);\n    }\n\n    /// @dev RENDERER has the same function (same selector and arguments): call it with this call's first `len`\n    ///      calldata bytes and return its answer unchanged. RENDERER reads this contract as msg.sender.\n    function _forward(uint256 len) private view {\n        address r = address(RENDERER);\n        assembly (\"memory-safe\") {\n            let p := mload(0x40)\n            calldatacopy(p, 0, len)\n            let ok := staticcall(gas(), r, p, len, 0, 0)\n            returndatacopy(p, 0, returndatasize())\n            if iszero(ok) { revert(p, returndatasize()) }\n            return(p, returndatasize())\n        }\n    }\n\n    function name() public pure override returns (string memory) {\n        return NAME;\n    }\n\n    function symbol() public pure override returns (string memory) {\n        return SYMBOL;\n    }\n\n    function supportsInterface(bytes4 i) public view override returns (bool) {\n        return i == bytes4(0x49064906) || i == bytes4(0x2a55205a) || super.supportsInterface(i); // ERC-4906, ERC-2981\n    }\n}\n"},"lib/openzeppelin-contracts/contracts/token/ERC721/ERC721.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC721} from \"./IERC721.sol\";\nimport {IERC721Metadata} from \"./extensions/IERC721Metadata.sol\";\nimport {ERC721Utils} from \"./utils/ERC721Utils.sol\";\nimport {Context} from \"../../utils/Context.sol\";\nimport {Strings} from \"../../utils/Strings.sol\";\nimport {IERC165, ERC165} from \"../../utils/introspection/ERC165.sol\";\nimport {IERC721Errors} from \"../../interfaces/draft-IERC6093.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC-721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\nabstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {\n    using Strings for uint256;\n\n    // Token name\n    string private _name;\n\n    // Token symbol\n    string private _symbol;\n\n    mapping(uint256 tokenId => address) private _owners;\n\n    mapping(address owner => uint256) private _balances;\n\n    mapping(uint256 tokenId => address) private _tokenApprovals;\n\n    mapping(address owner => mapping(address operator => bool)) private _operatorApprovals;\n\n    /**\n     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n        return\n            interfaceId == type(IERC721).interfaceId ||\n            interfaceId == type(IERC721Metadata).interfaceId ||\n            super.supportsInterface(interfaceId);\n    }\n\n    /// @inheritdoc IERC721\n    function balanceOf(address owner) public view virtual returns (uint256) {\n        if (owner == address(0)) {\n            revert ERC721InvalidOwner(address(0));\n        }\n        return _balances[owner];\n    }\n\n    /// @inheritdoc IERC721\n    function ownerOf(uint256 tokenId) public view virtual returns (address) {\n        return _requireOwned(tokenId);\n    }\n\n    /// @inheritdoc IERC721Metadata\n    function name() public view virtual returns (string memory) {\n        return _name;\n    }\n\n    /// @inheritdoc IERC721Metadata\n    function symbol() public view virtual returns (string memory) {\n        return _symbol;\n    }\n\n    /// @inheritdoc IERC721Metadata\n    function tokenURI(uint256 tokenId) public view virtual returns (string memory) {\n        _requireOwned(tokenId);\n\n        string memory baseURI = _baseURI();\n        return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : \"\";\n    }\n\n    /**\n     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n     * by default, can be overridden in child contracts.\n     */\n    function _baseURI() internal view virtual returns (string memory) {\n        return \"\";\n    }\n\n    /// @inheritdoc IERC721\n    function approve(address to, uint256 tokenId) public virtual {\n        _approve(to, tokenId, _msgSender());\n    }\n\n    /// @inheritdoc IERC721\n    function getApproved(uint256 tokenId) public view virtual returns (address) {\n        _requireOwned(tokenId);\n\n        return _getApproved(tokenId);\n    }\n\n    /// @inheritdoc IERC721\n    function setApprovalForAll(address operator, bool approved) public virtual {\n        _setApprovalForAll(_msgSender(), operator, approved);\n    }\n\n    /// @inheritdoc IERC721\n    function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {\n        return _operatorApprovals[owner][operator];\n    }\n\n    /// @inheritdoc IERC721\n    function transferFrom(address from, address to, uint256 tokenId) public virtual {\n        if (to == address(0)) {\n            revert ERC721InvalidReceiver(address(0));\n        }\n        // Setting an \"auth\" arguments enables the `_isAuthorized` check which verifies that the token exists\n        // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.\n        address previousOwner = _update(to, tokenId, _msgSender());\n        if (previousOwner != from) {\n            revert ERC721IncorrectOwner(from, tokenId, previousOwner);\n        }\n    }\n\n    /// @inheritdoc IERC721\n    function safeTransferFrom(address from, address to, uint256 tokenId) public {\n        safeTransferFrom(from, to, tokenId, \"\");\n    }\n\n    /// @inheritdoc IERC721\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {\n        transferFrom(from, to, tokenId);\n        ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data);\n    }\n\n    /**\n     * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\n     *\n     * IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the\n     * core ERC-721 logic MUST be matched with the use of {_increaseBalance} to keep balances\n     * consistent with ownership. The invariant to preserve is that for any address `a` the value returned by\n     * `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`.\n     */\n    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\n        return _owners[tokenId];\n    }\n\n    /**\n     * @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.\n     */\n    function _getApproved(uint256 tokenId) internal view virtual returns (address) {\n        return _tokenApprovals[tokenId];\n    }\n\n    /**\n     * @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in\n     * particular (ignoring whether it is owned by `owner`).\n     *\n     * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this\n     * assumption.\n     */\n    function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {\n        return\n            spender != address(0) &&\n            (owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);\n    }\n\n    /**\n     * @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.\n     * Reverts if:\n     * - `spender` does not have approval from `owner` for `tokenId`.\n     * - `spender` does not have approval to manage all of `owner`'s assets.\n     *\n     * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this\n     * assumption.\n     */\n    function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {\n        if (!_isAuthorized(owner, spender, tokenId)) {\n            if (owner == address(0)) {\n                revert ERC721NonexistentToken(tokenId);\n            } else {\n                revert ERC721InsufficientApproval(spender, tokenId);\n            }\n        }\n    }\n\n    /**\n     * @dev Unsafe write access to the balances, used by extensions that \"mint\" tokens using an {ownerOf} override.\n     *\n     * NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that\n     * a uint256 would ever overflow from increments when these increments are bounded to uint128 values.\n     *\n     * WARNING: Increasing an account's balance using this function tends to be paired with an override of the\n     * {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership\n     * remain consistent with one another.\n     */\n    function _increaseBalance(address account, uint128 value) internal virtual {\n        unchecked {\n            _balances[account] += value;\n        }\n    }\n\n    /**\n     * @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner\n     * (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.\n     *\n     * The `auth` argument is optional. If the value passed is non 0, then this function will check that\n     * `auth` is either the owner of the token, or approved to operate on the token (by the owner).\n     *\n     * Emits a {Transfer} event.\n     *\n     * NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.\n     */\n    function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {\n        address from = _ownerOf(tokenId);\n\n        // Perform (optional) operator check\n        if (auth != address(0)) {\n            _checkAuthorized(from, auth, tokenId);\n        }\n\n        // Execute the update\n        if (from != address(0)) {\n            // Clear approval. No need to re-authorize or emit the Approval event\n            _approve(address(0), tokenId, address(0), false);\n\n            unchecked {\n                _balances[from] -= 1;\n            }\n        }\n\n        if (to != address(0)) {\n            unchecked {\n                _balances[to] += 1;\n            }\n        }\n\n        _owners[tokenId] = to;\n\n        emit Transfer(from, to, tokenId);\n\n        return from;\n    }\n\n    /**\n     * @dev Mints `tokenId` and transfers it to `to`.\n     *\n     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - `to` cannot be the zero address.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _mint(address to, uint256 tokenId) internal {\n        if (to == address(0)) {\n            revert ERC721InvalidReceiver(address(0));\n        }\n        address previousOwner = _update(to, tokenId, address(0));\n        if (previousOwner != address(0)) {\n            revert ERC721InvalidSender(address(0));\n        }\n    }\n\n    /**\n     * @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must not exist.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeMint(address to, uint256 tokenId) internal {\n        _safeMint(to, tokenId, \"\");\n    }\n\n    /**\n     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n     */\n    function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {\n        _mint(to, tokenId);\n        ERC721Utils.checkOnERC721Received(_msgSender(), address(0), to, tokenId, data);\n    }\n\n    /**\n     * @dev Destroys `tokenId`.\n     * The approval is cleared when the token is burned.\n     * This is an internal function that does not check if the sender is authorized to operate on the token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _burn(uint256 tokenId) internal {\n        address previousOwner = _update(address(0), tokenId, address(0));\n        if (previousOwner == address(0)) {\n            revert ERC721NonexistentToken(tokenId);\n        }\n    }\n\n    /**\n     * @dev Transfers `tokenId` from `from` to `to`.\n     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _transfer(address from, address to, uint256 tokenId) internal {\n        if (to == address(0)) {\n            revert ERC721InvalidReceiver(address(0));\n        }\n        address previousOwner = _update(to, tokenId, address(0));\n        if (previousOwner == address(0)) {\n            revert ERC721NonexistentToken(tokenId);\n        } else if (previousOwner != from) {\n            revert ERC721IncorrectOwner(from, tokenId, previousOwner);\n        }\n    }\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients\n     * are aware of the ERC-721 standard to prevent tokens from being forever locked.\n     *\n     * `data` is additional data, it has no specified format and it is sent in call to `to`.\n     *\n     * This internal function is like {safeTransferFrom} in the sense that it invokes\n     * {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.\n     * implement alternative mechanisms to perform token transfer, such as signature-based.\n     *\n     * Requirements:\n     *\n     * - `tokenId` token must exist and be owned by `from`.\n     * - `to` cannot be the zero address.\n     * - `from` cannot be the zero address.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function _safeTransfer(address from, address to, uint256 tokenId) internal {\n        _safeTransfer(from, to, tokenId, \"\");\n    }\n\n    /**\n     * @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is\n     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n     */\n    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {\n        _transfer(from, to, tokenId);\n        ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data);\n    }\n\n    /**\n     * @dev Approve `to` to operate on `tokenId`\n     *\n     * The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is\n     * either the owner of the token, or approved to operate on all tokens held by this owner.\n     *\n     * Emits an {Approval} event.\n     *\n     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\n     */\n    function _approve(address to, uint256 tokenId, address auth) internal {\n        _approve(to, tokenId, auth, true);\n    }\n\n    /**\n     * @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not\n     * emitted in the context of transfers.\n     */\n    function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual {\n        // Avoid reading the owner unless necessary\n        if (emitEvent || auth != address(0)) {\n            address owner = _requireOwned(tokenId);\n\n            // We do not use _isAuthorized because single-token approvals should not be able to call approve\n            if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) {\n                revert ERC721InvalidApprover(auth);\n            }\n\n            if (emitEvent) {\n                emit Approval(owner, to, tokenId);\n            }\n        }\n\n        _tokenApprovals[tokenId] = to;\n    }\n\n    /**\n     * @dev Approve `operator` to operate on all of `owner` tokens\n     *\n     * Requirements:\n     * - operator can't be the address zero.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\n        if (operator == address(0)) {\n            revert ERC721InvalidOperator(operator);\n        }\n        _operatorApprovals[owner][operator] = approved;\n        emit ApprovalForAll(owner, operator, approved);\n    }\n\n    /**\n     * @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned).\n     * Returns the owner.\n     *\n     * Overrides to ownership logic should be done to {_ownerOf}.\n     */\n    function _requireOwned(uint256 tokenId) internal view returns (address) {\n        address owner = _ownerOf(tokenId);\n        if (owner == address(0)) {\n            revert ERC721NonexistentToken(tokenId);\n        }\n        return owner;\n    }\n}\n"},"lib/openzeppelin-contracts/contracts/utils/ReentrancyGuard.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,\n * consider using {ReentrancyGuardTransient} instead.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant NOT_ENTERED = 1;\n    uint256 private constant ENTERED = 2;\n\n    uint256 private _status;\n\n    /**\n     * @dev Unauthorized reentrant call.\n     */\n    error ReentrancyGuardReentrantCall();\n\n    constructor() {\n        _status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be NOT_ENTERED\n        if (_status == ENTERED) {\n            revert ReentrancyGuardReentrantCall();\n        }\n\n        // Any calls to nonReentrant after this point will fail\n        _status = ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == ENTERED;\n    }\n}\n"},"src/CharmDailyRenderer.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.28;\n\nimport {Strings} from \"openzeppelin-contracts/contracts/utils/Strings.sol\";\nimport {Base64} from \"openzeppelin-contracts/contracts/utils/Base64.sol\";\n\n/// @dev The parts of sidecoo Daily the renderer reads.\ninterface IHashFor {\n    function hashFor(address space, uint256 target) external view returns (bytes32);\n}\n\ninterface ICharmDailyView {\n    function tokenRecord(uint256 id) external view returns (uint256 raw);\n    function RANDOM() external view returns (IHashFor);\n    function name() external view returns (string memory);\n    function PRICE() external view returns (uint256);\n    function weekStart(uint256 w) external view returns (uint256);\n    function weekCounts(uint256 w) external view returns (uint256 drawn, uint256 seals, uint256 revealedPacked);\n    function agentKeyOf(address w) external view returns (bytes32 key, bool ok);\n    function today() external view returns (uint256);\n    function currentWeek() external view returns (uint256);\n    function pointsOf(bytes32 agent) external view returns (uint256);\n    function agentOn(bytes32 agent, uint256 day, uint256 week)\n        external\n        view\n        returns (uint256 free, uint256 paid, uint256 bonus, uint16 designs, bool firstPaidDone);\n    function PAYEE() external view returns (address);\n    function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address, uint256);\n}\n\n/// @title sidecoo Daily metadata and status\n/// @notice On-chain JSON metadata and the status() summary for sidecoo Daily, plus the display settings the\n///         metadata admin may change:\n///         image base, external link, description and design names. Nothing here can touch\n///         payments, odds or allowances. tokenURI()/contractURI() read the calling contract (sidecoo Daily);\n///         rarity, design, week and draw type come from the token record written at reveal, never from who\n///         holds the token.\ncontract CharmDailyRenderer {\n    using Strings for uint256;\n\n    string public constant RULES =\n        \"One free lucky charm a day for every Agent ID. Base odds for every draw: Common 75%, Rare 20%, Epic 4.5%, Legendary 0.5%. Each week brings 10 designs, every design equally likely at every rarity. Collect all 10 of a week to forge that week's seal.\";\n\n    address public metadataAdmin;\n    /// @dev The sidecoo Daily payee; the metadata admin can never be this address.\n    address public immutable PAYEE;\n    string public imageBase;\n    string public externalUrl;\n    string public description;\n    mapping(uint256 => string[10]) private _designNames;\n\n    event MetadataAdminChanged(address indexed previous, address indexed next);\n    event DisplayChanged();\n\n    error NotAdmin();\n    error AdminIsPayee();\n\n    error UnsafeString();\n\n    struct T {\n        uint256 week;\n        uint8 tier;\n        uint8 kind;\n        uint8 source;\n        bool revealed;\n        bool isSeal;\n        uint256 rank;\n        uint256 target;\n        uint8 floor;\n    }\n\n    constructor(\n        address admin,\n        address payee,\n        string memory imageBase_,\n        string memory externalUrl_,\n        string memory description_\n    ) {\n        if (admin == payee) revert AdminIsPayee();\n        PAYEE = payee;\n        _requireJsonSafe(imageBase_);\n        _requireJsonSafe(externalUrl_);\n        _requireJsonSafe(description_);\n        metadataAdmin = admin;\n        imageBase = imageBase_;\n        externalUrl = externalUrl_;\n        description = description_;\n        emit MetadataAdminChanged(address(0), admin);\n    }\n\n    // ------------------------------------------------------------------ admin (display only)\n    modifier onlyAdmin() {\n        if (msg.sender != metadataAdmin) revert NotAdmin();\n        _;\n    }\n\n    function setImageBase(string calldata v) external onlyAdmin {\n        _requireJsonSafe(v);\n        imageBase = v;\n        emit DisplayChanged();\n    }\n\n    function setExternalUrl(string calldata v) external onlyAdmin {\n        _requireJsonSafe(v);\n        externalUrl = v;\n        emit DisplayChanged();\n    }\n\n    function setDescription(string calldata v) external onlyAdmin {\n        _requireJsonSafe(v);\n        description = v;\n        emit DisplayChanged();\n    }\n\n    function setDesignNames(uint256 week, string[10] calldata names) external onlyAdmin {\n        for (uint256 i; i < 10; ++i) {\n            _requireJsonSafe(names[i]);\n            _designNames[week][i] = names[i];\n        }\n        emit DisplayChanged();\n    }\n\n    /// @notice Hand over or renounce (address(0)) the metadata admin.\n    function setMetadataAdmin(address next) external onlyAdmin {\n        if (next == PAYEE) revert AdminIsPayee();\n        emit MetadataAdminChanged(metadataAdmin, next);\n        metadataAdmin = next;\n    }\n\n    // ------------------------------------------------------------------ status (for sidecoo Daily.status)\n    struct Status {\n        bool hasAgentId;\n        bytes32 agent;\n        uint256 day;\n        uint256 week;\n        uint256 nextResetAt;\n        uint256 freeToday; // free draws available today in total (1 + holder extra)\n        uint256 freeUsed;\n        uint256 freeLeft;\n        uint256 paidToday;\n        uint256 paidLeft;\n        uint256 bonusToday;\n        uint256 paidUntilNextBonus;\n        uint256 points;\n        uint8 level; // 0 none, 1 bronze, 2 silver, 3 gold; also the extra free draws a day\n        uint16 weekDesigns; // bit k set: design k of this week was drawn and revealed by this Agent ID\n        bool firstPaidDone; // the first paid draw of this week is taken (guarantee used if any)\n        uint8 guaranteeTier; // minimum tier the first paid draw of this week gets if not taken yet (0 = none)\n    }\n\n    /// @notice weekInfo() of the calling sidecoo Daily contract.\n    function weekInfo(uint256 w)\n        external\n        view\n        returns (uint256 start, uint256 end, bool current, uint256 drawn, uint256 seals, uint256[4] memory revealedByTier)\n    {\n        ICharmDailyView d = ICharmDailyView(msg.sender);\n        start = d.weekStart(w);\n        if (start == 0) return (0, 0, false, 0, 0, revealedByTier);\n        end = start + 7 days;\n        current = w == d.currentWeek();\n        uint256 packed;\n        (drawn, seals, packed) = d.weekCounts(w);\n        for (uint256 t; t < 4; ++t) revealedByTier[t] = (packed >> (64 * t)) & type(uint64).max;\n    }\n\n    /// @notice What mint(qty) needs from `w` in the calling sidecoo Daily contract right now (see its quote()).\n    function quote(address w, uint256 qty)\n        external\n        view\n        returns (uint256 cost, uint256 tokens, uint256 bonus, bool free)\n    {\n        ICharmDailyView d = ICharmDailyView(msg.sender);\n        (bytes32 key, bool ok) = d.agentKeyOf(w);\n        if (!ok || qty == 0) return (0, 0, 0, false);\n        (uint256 used, uint256 paid, uint256 given,,) = d.agentOn(key, d.today(), 0);\n        uint256 points = d.pointsOf(key);\n        uint256 freeTotal = 1 + (points >= 20 ? 3 : points >= 5 ? 2 : points >= 1 ? 1 : 0);\n        if (used + qty <= freeTotal) return (0, qty, 0, true);\n        if (paid + qty > 9) return (0, 0, 0, false);\n        bonus = (paid + qty) / 3 - given;\n        return (qty * d.PRICE(), qty + bonus, bonus, false);\n    }\n\n    /// @notice Summary of `w` in the calling sidecoo Daily contract.\n    function status(address w) external view returns (Status memory s) {\n        ICharmDailyView d = ICharmDailyView(msg.sender);\n        (s.agent, s.hasAgentId) = d.agentKeyOf(w);\n        s.day = d.today();\n        s.week = d.currentWeek();\n        s.nextResetAt = (s.day + 1) * 1 days;\n        if (!s.hasAgentId) return s;\n        uint256 paid;\n        (s.freeUsed, paid, s.bonusToday, s.weekDesigns, s.firstPaidDone) = d.agentOn(s.agent, s.day, s.week);\n        s.points = d.pointsOf(s.agent);\n        s.level = s.points >= 20 ? 3 : s.points >= 5 ? 2 : s.points >= 1 ? 1 : 0;\n        s.freeToday = 1 + s.level;\n        s.freeLeft = s.freeUsed >= s.freeToday ? 0 : s.freeToday - s.freeUsed;\n        s.paidToday = paid;\n        s.paidLeft = 9 - paid;\n        s.paidUntilNextBonus = paid >= 9 ? 0 : 3 - (paid % 3);\n        s.guaranteeTier = s.firstPaidDone ? 0 : s.level == 3 ? 2 : s.level == 2 ? 1 : 0;\n    }\n\n    // ------------------------------------------------------------------ rendering\n    function _info(uint256 id) private view returns (T memory) {\n        return _decode(ICharmDailyView(msg.sender).tokenRecord(id));\n    }\n\n    /// @dev Unpacks sidecoo Daily's struct Token word (see CharmDaily.tokenRecord).\n    function _decode(uint256 r) private pure returns (T memory t) {\n        t.week = uint32(r);\n        t.target = uint64(r >> 96);\n        t.tier = uint8(r >> 160);\n        t.kind = uint8(r >> 168);\n        t.floor = uint8(r >> 176);\n        t.source = uint8(r >> 184);\n        t.revealed = uint8(r >> 192) != 0;\n        t.rank = uint32(r >> 200);\n        t.isSeal = t.source >= 3 && t.week != 0;\n    }\n\n    /// @notice tokenInfo() of the calling sidecoo Daily contract.\n    function tokenInfo(uint256 id)\n        external\n        view\n        returns (\n            uint256 week,\n            uint8 tier,\n            uint8 kind,\n            uint8 source,\n            bool revealed,\n            bool isSeal_,\n            uint256 sealRank,\n            uint256 targetBlock,\n            uint8 minTier,\n            bool revealable\n        )\n    {\n        T memory t = _info(id);\n        revealable = t.target != 0 && !t.revealed && ICharmDailyView(msg.sender).RANDOM().hashFor(msg.sender, t.target) != 0;\n        return (t.week, t.tier, t.kind, t.source, t.revealed, t.isSeal, t.rank, t.target, t.floor, revealable);\n    }\n\n    function tierName(uint8 t) public pure returns (string memory) {\n        if (t == 0) return \"Common\";\n        if (t == 1) return \"Rare\";\n        if (t == 2) return \"Epic\";\n        return \"Legendary\";\n    }\n\n    function _tierFile(uint8 t) private pure returns (string memory) {\n        if (t == 0) return \"common\";\n        if (t == 1) return \"rare\";\n        if (t == 2) return \"epic\";\n        return \"legendary\";\n    }\n\n    function _sourceName(uint8 s) private pure returns (string memory) {\n        if (s == 0) return \"Daily free\";\n        if (s == 1) return \"Paid\";\n        return \"Bonus\";\n    }\n\n    /// @notice Name of design `kind` (0..9) of `week`; a default name until the metadata admin sets one.\n    function designName(uint256 week, uint256 kind) public view returns (string memory) {\n        string memory n = _designNames[week][kind];\n        if (bytes(n).length != 0) return n;\n        return string.concat(\"Week \", week.toString(), \" Charm \", (kind + 1).toString());\n    }\n\n    function tokenURI(uint256 id) external view returns (string memory) {\n        T memory t = _info(id);\n        string memory w = t.week.toString();\n        string memory head = string.concat('\",\"description\":\"', description, \" \", RULES, '\",\"external_url\":\"', externalUrl);\n        string memory json;\n        if (t.isSeal) {\n            json = string.concat(\n                '{\"name\":\"Week ', w, \" Seal #\", t.rank.toString(),\n                head,\n                '\",\"image\":\"', imageBase, \"w\", w, \"/seal.png\",\n                '\",\"attributes\":[{\"trait_type\":\"Week\",\"value\":\"', w,\n                '\"},{\"trait_type\":\"Type\",\"value\":\"Weekly Seal\"},{\"trait_type\":\"Seal number\",\"display_type\":\"number\",\"value\":',\n                t.rank.toString(), '},{\"trait_type\":\"Counts as ticket\",\"value\":\"', _ticketWord(t), '\"}]}'\n            );\n        } else if (!t.revealed) {\n            json = string.concat(\n                '{\"name\":\"Sealed Charm #', id.toString(),\n                head,\n                '\",\"image\":\"', imageBase, \"cover.png\",\n                '\",\"attributes\":[{\"trait_type\":\"Week\",\"value\":\"', w,\n                '\"},{\"trait_type\":\"Status\",\"value\":\"Sealed\"},{\"trait_type\":\"Draw\",\"value\":\"', _sourceName(t.source),\n                '\"},{\"trait_type\":\"Counts as ticket\",\"value\":\"', _ticketWord(t), '\"}]}'\n            );\n        } else {\n            string memory dn = designName(t.week, t.kind);\n            json = string.concat(\n                '{\"name\":\"', dn, \" #\", id.toString(),\n                head,\n                '\",\"image\":\"', imageBase, \"w\", w, \"/\", (uint256(t.kind) + 1).toString(), \"-\", _tierFile(t.tier), \".png\",\n                _revealedAttrs(t, w, dn)\n            );\n        }\n        return string.concat(\"data:application/json;base64,\", Base64.encode(bytes(json)));\n    }\n\n    function _revealedAttrs(T memory t, string memory w, string memory dn) private pure returns (string memory) {\n        return string.concat(\n            '\",\"attributes\":[{\"trait_type\":\"Charm\",\"value\":\"', dn,\n            '\"},{\"trait_type\":\"Rarity\",\"value\":\"', tierName(t.tier),\n            '\"},{\"trait_type\":\"Week\",\"value\":\"', w,\n            '\"},{\"trait_type\":\"Design\",\"value\":\"', (uint256(t.kind) + 1).toString(),\n            '\"},{\"trait_type\":\"Draw\",\"value\":\"', _sourceName(t.source),\n            '\"},{\"trait_type\":\"Counts as ticket\",\"value\":\"', _ticketWord(t), '\"}]}'\n        );\n    }\n\n    /// @notice Whether token `id` of sidecoo Daily `daily` counts as a ticket (the rule Daily and Season use),\n    ///         its seal flag and rarity: revealed charms from paid or bonus draws, seals forged only from such\n    ///         charms (source 3).\n    function ticketTier(address daily, uint256 id) external view returns (bool counts, bool isSeal_, uint8 tier) {\n        T memory t = _decode(ICharmDailyView(daily).tokenRecord(id));\n        isSeal_ = t.isSeal;\n        tier = t.tier;\n        counts = t.isSeal ? t.source == 3 : t.revealed && (t.source == 1 || t.source == 2);\n    }\n\n    /// @notice sidecoo Daily's fixed draw table, to recompute any result from its hash: base odds Legendary\n    ///         0.5%, Epic 4.5%, Rare 20%, Common 75%; design 0..9 from independent bits.\n    function drawOf(address daily, bytes32 h, uint256 id) external pure returns (uint8 tier, uint8 kind) {\n        uint256 rnd = uint256(keccak256(abi.encode(h, id, daily)));\n        uint256 roll = rnd % 10_000;\n        tier = roll < 50 ? 3 : roll < 500 ? 2 : roll < 2500 ? 1 : 0;\n        kind = uint8((rnd >> 128) % 10);\n    }\n\n    /// @dev Whether the token counts as a sidecoo ticket (same rule as ticketTier): charms from paid\n    ///      or bonus draws once revealed, seals forged only from such charms (source 3).\n    function _ticketWord(T memory t) private pure returns (string memory) {\n        if (t.isSeal) return t.source == 3 ? \"Yes\" : \"No\";\n        if (t.source == 0) return \"No\";\n        return t.revealed ? \"Yes\" : \"After reveal\";\n    }\n\n    function contractURI() external view returns (string memory) {\n        ICharmDailyView d = ICharmDailyView(msg.sender);\n        (, uint256 bps) = d.royaltyInfo(0, 10_000);\n        string memory json = string.concat(\n            '{\"name\":\"', d.name(),\n            '\",\"description\":\"', description, \" \", RULES,\n            '\",\"image\":\"', imageBase, \"cover.png\",\n            '\",\"external_link\":\"', externalUrl,\n            '\",\"seller_fee_basis_points\":', bps.toString(),\n            ',\"fee_recipient\":\"', Strings.toHexString(uint160(d.PAYEE()), 20), '\"}'\n        );\n        return string.concat(\"data:application/json;base64,\", Base64.encode(bytes(json)));\n    }\n\n    /// @dev Printable ASCII only (0x20..0x7e), and no quote or backslash, so the JSON always parses.\n    function _requireJsonSafe(string memory s) private pure {\n        bytes memory b = bytes(s);\n        for (uint256 i; i < b.length; ++i) {\n            bytes1 c = b[i];\n            if (c == '\"' || c == \"\\\\\" || uint8(c) < 0x20 || uint8(c) > 0x7e) revert UnsafeString();\n        }\n    }\n}\n"},"src/CharmDailyRandom.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.28;\n\n/// @title sidecoo Daily hash keeper\n/// @notice Keeps the block hashes that sealed charms are revealed from, so no charm can stay sealed for good.\n///         Every caller (a draw contract) has its own namespace, so there is no admin and no access list:\n///         a contract can only queue and keep targets in its own namespace.\n///\n///  * queue(target) adds a future reveal block for the caller; poke(space) adds one for any space that has no\n///    future target. Targets are kept in increasing order.\n///  * keep(n) processes up to n mined targets in order. A target whose hash is still readable is kept for\n///    good: BLOCKHASH for 256 blocks, then the EIP-2935 history contract for 8191 blocks.\n///  * hashFor(owner, target): the kept hash; else BLOCKHASH / history; else (the target was never kept in\n///    time) the hash of the first kept target after it. Kept targets are appended in order and never change,\n///    so this answer is fixed once it exists, and nobody can choose it.\ncontract CharmDailyRandom {\n    address public constant HISTORY = 0x0000F90827F1C53a10cb7A02335B175320002935;\n    uint256 public constant HISTORY_WINDOW = 8191;\n\n    struct Space {\n        uint64[] targets;\n        uint64[] kept;\n        uint256 cursor;\n        mapping(uint256 => bytes32) saved;\n    }\n\n    mapping(address => Space) private _spaces;\n\n    event HashSaved(address indexed space, uint256 indexed blockNumber, bytes32 hash);\n    event HashMissed(address indexed space, uint256 indexed blockNumber);\n\n    /// @notice Queue `target` (a future block) for the caller. Ignored unless it is above the last queued one.\n    function queue(uint256 target) external {\n        Space storage s = _spaces[msg.sender];\n        uint256 n = s.targets.length;\n        if (target <= block.number || (n != 0 && s.targets[n - 1] >= target)) return;\n        s.targets.push(uint64(target));\n    }\n\n    uint256 public constant POKE_DELAY = 16;\n\n    /// @notice Anyone: when no queued target of `space` is still in the future, queue block.number + 16 for it,\n    ///         so a charm whose own hash was missed always gets a later kept hash, even if nobody draws again.\n    function poke(address space) external returns (bool queued) {\n        Space storage s = _spaces[space];\n        uint256 n = s.targets.length;\n        if (n != 0 && s.targets[n - 1] >= block.number) return false;\n        s.targets.push(uint64(block.number + POKE_DELAY));\n        return true;\n    }\n\n    /// @notice Process up to `maxSteps` mined targets of the caller, in order.\n    function keep(uint256 maxSteps) external returns (uint256 kept) {\n        Space storage s = _spaces[msg.sender];\n        uint256 c = s.cursor;\n        uint256 n = s.targets.length;\n        for (uint256 steps; steps < maxSteps && c < n; ++steps) {\n            uint256 t = s.targets[c];\n            if (t >= block.number) break;\n            bytes32 h = s.saved[t];\n            if (h == 0) {\n                h = _readHash(t);\n                if (h != 0) {\n                    s.saved[t] = h;\n                    emit HashSaved(msg.sender, t, h);\n                } else {\n                    emit HashMissed(msg.sender, t);\n                }\n            }\n            if (h != 0) {\n                s.kept.push(uint64(t));\n                ++kept;\n            }\n            ++c;\n        }\n        s.cursor = c;\n    }\n\n    /// @notice The hash `target` resolves to for `space` now, or 0 if not available yet.\n    function hashFor(address space, uint256 target) public view returns (bytes32 h) {\n        Space storage s = _spaces[space];\n        h = s.saved[target];\n        if (h != 0 || block.number <= target) return h;\n        h = _readHash(target);\n        if (h != 0) return h;\n        uint256 k = _firstKeptAfter(s, target);\n        if (k != 0) h = s.saved[k];\n    }\n\n    /// @notice 0 not yet, 1 kept, 2 BLOCKHASH or history, 3 first later kept hash.\n    function hashPath(address space, uint256 target) external view returns (uint8) {\n        Space storage s = _spaces[space];\n        if (s.saved[target] != 0) return 1;\n        if (block.number <= target) return 0;\n        if (_readHash(target) != 0) return 2;\n        return _firstKeptAfter(s, target) != 0 ? 3 : 0;\n    }\n\n    function savedHash(address space, uint256 target) external view returns (bytes32) {\n        return _spaces[space].saved[target];\n    }\n\n    function cursorOf(address space) external view returns (uint256) {\n        return _spaces[space].cursor;\n    }\n\n    function targetsQueued(address space) external view returns (uint256) {\n        return _spaces[space].targets.length;\n    }\n\n    function keptCount(address space) external view returns (uint256) {\n        return _spaces[space].kept.length;\n    }\n\n    function _firstKeptAfter(Space storage s, uint256 target) private view returns (uint256) {\n        uint256 lo;\n        uint256 hi = s.kept.length;\n        while (lo < hi) {\n            uint256 mid = (lo + hi) >> 1;\n            if (s.kept[mid] <= target) lo = mid + 1;\n            else hi = mid;\n        }\n        return lo < s.kept.length ? s.kept[lo] : 0;\n    }\n\n    function _readHash(uint256 n) private view returns (bytes32 h) {\n        if (n >= block.number) return 0;\n        uint256 age = block.number - n;\n        if (age <= 256) return blockhash(n);\n        if (age > HISTORY_WINDOW || HISTORY.code.length == 0) return 0;\n        (bool ok, bytes memory data) = HISTORY.staticcall(abi.encode(n));\n        if (ok && data.length == 32) h = abi.decode(data, (bytes32));\n    }\n}\n"},"src/CharmDailyTickets.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.28;\n\ninterface IOwnerOf {\n    function ownerOf(uint256 tokenId) external view returns (address);\n}\n\n/// @dev sidecoo Agent Pass v2 mint counters.\ninterface IPassCounts {\n    function goldMinted() external view returns (uint256);\n    function freeMinted() external view returns (uint256);\n}\n\ninterface ITotalMinted {\n    function totalMinted() external view returns (uint256);\n}\n\n/// @dev What the registering contract (sidecoo Daily) tells about its own tokens.\ninterface IDailyTokens {\n    function ownerOf(uint256 tokenId) external view returns (address);\n    function tokenRecord(uint256 tokenId) external view returns (uint256 raw);\n    function SEASON() external view returns (address);\n}\n\n/// @dev Lucky Charm Atlas (season 1).\ninterface IAtlas1 {\n    struct Charm {\n        uint8 tier;\n        uint8 charm;\n        uint16 epoch;\n        bytes32 work;\n    }\n\n    function charmOf(uint256 tokenId) external view returns (Charm memory);\n}\n\n/// @dev Lucky Charm Atlas II (season 2).\ninterface IAtlas2 {\n    function tokenInfo(uint256 id)\n        external\n        view\n        returns (\n            uint8 round,\n            uint8 tier,\n            uint8 kind,\n            bool free,\n            bool revealed,\n            bool oneOfOne,\n            uint256 targetBlock,\n            bool revealable\n        );\n}\n\n/// @title sidecoo ticket table\n/// @notice Read-only ticket points for earlier sidecoo NFTs, checked live against ownerOf. Only NFTs that\n///         existed when this contract was deployed count: the cut-off ids are read from each contract's mint\n///         counters in the constructor and fixed (Pass GOLD 1..PASS_GOLD_CUTOFF, Pass standard\n///         501..500+PASS_FREE_CUTOFF, Atlas S1 1..ATLAS1_CUTOFF, Atlas II S2 1..ATLAS2_CUTOFF).\n///\n///  | Series | Contract           | Points                                                              |\n///  |--------|--------------------|---------------------------------------------------------------------|\n///  | 0      | sidecoo Pass       | token id 1..500 (GOLD) 3, others 1                                  |\n///  | 1      | Lucky Charm Atlas  | Common 2, Rare 4, Epic 10, Legendary 30; paid mint +1 (s1Paid)      |\n///  | 2      | Lucky Charm Atlas II | revealed only: Common 1, Rare 3, Epic 8, Legendary 25, 1 of 1 25; paid +1 |\n///  | 3      | the calling contract's own charms (sidecoo Daily) | Common 1, Rare 2, Epic 4, Legendary 10 |\n///  | 4      | the calling contract's own weekly seals forged only from paid/bonus charms | 5               |\n///  | 5      | sidecoo Season NFTs (the season bound to the calling contract; no cut-off) | 3               |\n///\n///  register() keeps, for each calling contract separately, which tickets were used and the points of each\n///  Agent ID: a contract can only write its own records, so there is no admin and no access list.\ncontract CharmDailyTickets {\n    struct Ticket {\n        uint8 series;\n        uint256 tokenId;\n    }\n\n    mapping(address => mapping(uint8 => mapping(uint256 => bool))) private _used;\n    mapping(address => mapping(bytes32 => uint256)) private _points;\n\n    event HoldingsRegistered(\n        address indexed space, bytes32 indexed agent, uint8 series, uint256 tokenId, uint256 points, uint256 total\n    );\n\n    error TooMany();\n    error BadSeries(uint256 index);\n    error TicketNotOwned(uint256 index);\n    error TicketUsed(uint256 index);\n    error TicketNotEligible(uint256 index);\n    error TicketAfterCutoff(uint256 index);\n\n    address public immutable PASS;\n    address public immutable ATLAS1;\n    address public immutable ATLAS2;\n\n    uint256 public constant PASS_GOLD_MAX_ID = 500;\n    /// @dev Atlas S1 free and paid mints interleave, so \"paid\" is read from a table of ids 1..636 built\n    ///      from the S1 Mined events (price > 0). Every later S1 id is paid: S1's 512 free charms were\n    ///      all minted by #636 (freeMinted == FREE_SUPPLY). Bit (id - 1), most significant bit first.\n    uint256 public constant S1_TABLE_MAX_ID = 636;\n    bytes public constant S1_PAID_BITMAP =\n        hex\"40000107000000000000000000000ebffde000c0000000000000040000000000000000002000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffff0\";\n\n    uint8 public constant OK = 0;\n    uint8 public constant NOT_OWNED = 1;\n    uint8 public constant NOT_ELIGIBLE = 2;\n    uint8 public constant AFTER_CUTOFF = 3;\n\n    /// @dev highest token id that counts, per series (fixed at deployment)\n    uint256 public immutable PASS_GOLD_CUTOFF; // GOLD ids 1..this\n    uint256 public immutable PASS_FREE_CUTOFF; // standard ids 501..500 + this\n    uint256 public immutable ATLAS1_CUTOFF;\n    uint256 public immutable ATLAS2_CUTOFF;\n\n    error BadConfig();\n    error NotDeployer();\n\n    /// @param deployer The only account that may send the deployment transaction (tx.origin). The cut-off ids\n    ///        are read here, so nobody else can choose the cut-off by deploying this exact initcode first.\n    constructor(address pass, address atlas1, address atlas2, address deployer) {\n        if (tx.origin != deployer) revert NotDeployer();\n        if (pass.code.length == 0 || atlas1.code.length == 0 || atlas2.code.length == 0) revert BadConfig();\n        PASS = pass;\n        ATLAS1 = atlas1;\n        ATLAS2 = atlas2;\n        PASS_GOLD_CUTOFF = IPassCounts(pass).goldMinted();\n        PASS_FREE_CUTOFF = IPassCounts(pass).freeMinted();\n        ATLAS1_CUTOFF = ITotalMinted(atlas1).totalMinted();\n        ATLAS2_CUTOFF = ITotalMinted(atlas2).totalMinted();\n        if (PASS_GOLD_CUTOFF > PASS_GOLD_MAX_ID) revert BadConfig();\n    }\n\n    /// @notice True if Atlas S1 token `id` was a paid mint.\n    function s1Paid(uint256 id) public pure returns (bool) {\n        if (id > S1_TABLE_MAX_ID) return true;\n        if (id == 0) return false;\n        uint256 i = id - 1;\n        return uint8(S1_PAID_BITMAP[i / 8]) & (uint8(1) << uint8(7 - i % 8)) != 0;\n    }\n\n    /// @notice True if token `id` of `series` existed when this contract was deployed.\n    function beforeCutoff(uint8 series, uint256 id) public view returns (bool) {\n        if (id == 0) return false;\n        if (series == 0) {\n            return id <= PASS_GOLD_MAX_ID ? id <= PASS_GOLD_CUTOFF : id <= PASS_GOLD_MAX_ID + PASS_FREE_CUTOFF;\n        }\n        if (series == 1) return id <= ATLAS1_CUTOFF;\n        if (series == 2) return id <= ATLAS2_CUTOFF;\n        return false;\n    }\n\n    uint256 public constant MAX_TICKETS = 30;\n\n    /// @notice Register tickets `holder` owns for Agent ID `agent` in the caller's records. Reverts on the first\n    ///         ticket that cannot count, naming its index. Returns the agent's new total.\n    function register(bytes32 agent, address holder, Ticket[] calldata t) external returns (uint256 total) {\n        if (t.length == 0 || t.length > MAX_TICKETS) revert TooMany();\n        total = _points[msg.sender][agent];\n        for (uint256 i; i < t.length; ++i) {\n            uint8 s = t[i].series;\n            uint256 id = t[i].tokenId;\n            if (s > 5) revert BadSeries(i);\n            if (_used[msg.sender][s][id]) revert TicketUsed(i);\n            (uint256 p, uint8 err) = _points3(msg.sender, s, id, holder);\n            if (err == NOT_OWNED) revert TicketNotOwned(i);\n            if (err == NOT_ELIGIBLE) revert TicketNotEligible(i);\n            if (err == AFTER_CUTOFF) revert TicketAfterCutoff(i);\n            _used[msg.sender][s][id] = true;\n            total += p;\n            emit HoldingsRegistered(msg.sender, agent, s, id, p, total);\n        }\n        _points[msg.sender][agent] = total;\n    }\n\n    function pointsOf(address space, bytes32 agent) external view returns (uint256) {\n        return _points[space][agent];\n    }\n\n    function used(address space, uint8 series, uint256 id) external view returns (bool) {\n        return _used[space][series][id];\n    }\n\n    /// @notice Preview: points each ticket would add for `holder` in `space`'s records (0 if it cannot count).\n    function ticketPoints(address space, address holder, Ticket[] calldata t)\n        external\n        view\n        returns (uint256 total, uint256[] memory each)\n    {\n        each = new uint256[](t.length);\n        for (uint256 i; i < t.length; ++i) {\n            uint8 s = t[i].series;\n            if (s > 5 || _used[space][s][t[i].tokenId]) continue;\n            (uint256 p, uint8 err) = _points3(space, s, t[i].tokenId, holder);\n            if (err == OK) {\n                each[i] = p;\n                total += p;\n            }\n        }\n    }\n\n    function _points3(address space, uint8 s, uint256 id, address holder) private view returns (uint256, uint8) {\n        if (s <= 2) return points(s, id, holder);\n        if (s == 5) {\n            // sidecoo Season NFT: 3 points, only once a season is bound to the caller\n            address season = IDailyTokens(space).SEASON();\n            if (season == address(0)) return (0, NOT_ELIGIBLE);\n            try IOwnerOf(season).ownerOf(id) returns (address o) {\n                return o == holder ? (3, OK) : (0, NOT_OWNED);\n            } catch {\n                return (0, NOT_OWNED);\n            }\n        }\n        try IDailyTokens(space).ownerOf(id) returns (address o) {\n            if (o != holder) return (0, NOT_OWNED);\n        } catch {\n            return (0, NOT_OWNED);\n        }\n        // struct Token word of sidecoo Daily: week (bits 0..31), tier (160), source (184), revealed (192)\n        uint256 r = IDailyTokens(space).tokenRecord(id);\n        uint8 tier = uint8(r >> 160);\n        uint8 src = uint8(r >> 184);\n        bool isSeal = src >= 3 && uint32(r) != 0;\n        // counts: revealed charms from paid (1) or bonus (2) draws; seals forged only from such charms (3)\n        bool counts = uint8(r >> 192) != 0 && (src == 1 || src == 2 || src == 3);\n        if (s == 4) return isSeal && counts ? (5, OK) : (0, NOT_ELIGIBLE);\n        if (isSeal || !counts) return (0, NOT_ELIGIBLE);\n        return (tier == 0 ? 1 : tier == 1 ? 2 : tier == 2 ? 4 : 10, OK);\n    }\n\n    /// @notice Earlier sidecoo NFTs: (points, OK) or (0, NOT_OWNED / NOT_ELIGIBLE / AFTER_CUTOFF).\n    function points(uint8 series, uint256 id, address holder) public view returns (uint256, uint8) {\n        if (series > 2) return (0, NOT_ELIGIBLE);\n        if (!beforeCutoff(series, id)) return (0, AFTER_CUTOFF);\n        address c = series == 0 ? PASS : series == 1 ? ATLAS1 : ATLAS2;\n        try IOwnerOf(c).ownerOf(id) returns (address o) {\n            if (o != holder || o == address(0)) return (0, NOT_OWNED);\n        } catch {\n            return (0, NOT_OWNED);\n        }\n        if (series == 0) return (id <= PASS_GOLD_MAX_ID ? 3 : 1, OK);\n        if (series == 1) {\n            try IAtlas1(c).charmOf(id) returns (IAtlas1.Charm memory ch) {\n                if (ch.tier > 3) return (0, NOT_ELIGIBLE);\n                uint256 p = ch.tier == 0 ? 2 : ch.tier == 1 ? 4 : ch.tier == 2 ? 10 : 30;\n                return (s1Paid(id) ? p + 1 : p, OK);\n            } catch {\n                return (0, NOT_ELIGIBLE);\n            }\n        }\n        try IAtlas2(c).tokenInfo(id) returns (uint8, uint8 tier, uint8, bool free, bool revealed, bool, uint256, bool) {\n            if (!revealed || tier > 4) return (0, NOT_ELIGIBLE);\n            uint256 p = tier == 0 ? 1 : tier == 1 ? 3 : tier == 2 ? 8 : 25;\n            return (free ? p : p + 1, OK);\n        } catch {\n            return (0, NOT_ELIGIBLE);\n        }\n    }\n}\n"},"src/CharmDailyLucky.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.28;\n\ninterface IWBNBLike {\n    function deposit() external payable;\n    function transfer(address to, uint256 amount) external returns (bool);\n}\n\ninterface IPairLike {\n    function token0() external view returns (address);\n    function token1() external view returns (address);\n    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n    function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external;\n}\n\ninterface ISeasonLike {\n    function TICKETS() external view returns (address);\n    function DEPLOYER() external view returns (address);\n    function PAYEE() external view returns (address);\n    function launched() external view returns (bool);\n    function pair() external view returns (address);\n    function token() external view returns (address);\n}\n\ninterface ISeasonTicketsLike {\n    function DAILY() external view returns (address);\n}\n\n/// @dev What the calling draw contract (sidecoo Daily) exposes.\ninterface IDailyLike {\n    function PAYEE() external view returns (address);\n    function DEPLOYER() external view returns (address);\n}\n\n/// @title sidecoo Daily lucky charm buyer\n/// @notice After the sidecoo Season pool is live, the share of each paid draw that sidecoo Daily sends here buys\n///         SIDECOO straight from the PancakeSwap V2 pair and sends it to the drawer. Before that, or if any step\n///         of the buy fails, the BNB goes on to the draw contract's PAYEE in the same transaction. This contract\n///         keeps no BNB and has no admin.\n///\n///  * Records are kept per calling contract (msg.sender): bind() links a caller to its season once, after\n///    checking that the season's tickets read that caller and that the season's DEPLOYER and PAYEE match the\n///    caller's (sidecoo Daily only calls it from bindSeason, DEPLOYER only). buy() always uses the caller's own\n///    season and PAYEE, so a contract can only spend its own BNB.\n///  * The buy talks to the pair directly: amount out from getReserves() with the 0.25% PancakeSwap V2 fee,\n///    WBNB in, pair.swap(..., drawer). No price limit is set (amounts per draw are small).\ncontract CharmDailyLucky {\n    IWBNBLike public immutable WBNB;\n\n    mapping(address => address) private _season;\n\n    event SeasonBound(address indexed daily, address indexed season);\n    event LuckyBuy(address indexed drawer, uint256 bnbIn, uint256 tokensOut);\n    /// @dev A buy was tried after launch and failed; the BNB went to PAYEE. reason: 3 pair not usable,\n    ///      4 zero amount out, 5 swap failed. (Before a season is bound or launched nothing is tried or logged.)\n    event LuckyBuySkipped(address indexed drawer, uint256 bnb, uint8 reason);\n\n    error AlreadyBound();\n    error NotOurSeason();\n    error OnlySelf();\n    error PayFailed();\n\n    constructor(address wbnb) {\n        WBNB = IWBNBLike(wbnb);\n    }\n\n    /// @notice The season bound to `daily` (0 until bound).\n    function seasonOf(address daily) external view returns (address) {\n        return _season[daily];\n    }\n\n    /// @notice Called by the draw contract (sidecoo Daily.bindSeason, DEPLOYER only), once: binds the caller\n    ///         to its sidecoo Season contract. Checks that the season's tickets read the caller and that the\n    ///         season's DEPLOYER and PAYEE are the caller's.\n    function bind(address season) external {\n        if (_season[msg.sender] != address(0)) revert AlreadyBound();\n        ISeasonLike s = ISeasonLike(season);\n        IDailyLike d = IDailyLike(msg.sender);\n        if (\n            season.code.length == 0 || ISeasonTicketsLike(s.TICKETS()).DAILY() != msg.sender\n                || s.DEPLOYER() != d.DEPLOYER() || s.PAYEE() != d.PAYEE()\n        ) revert NotOurSeason();\n        _season[msg.sender] = season;\n        emit SeasonBound(msg.sender, season);\n    }\n\n    /// @notice Called by the draw contract with its lucky share of a paid draw. Never reverts on a failed\n    ///         buy: the BNB then goes to the caller's PAYEE.\n    function buy(address drawer) external payable returns (uint256 out) {\n        address season = _season[msg.sender];\n        uint8 reason;\n        if (season == address(0)) reason = 1;\n        else if (!_launched(season)) reason = 2;\n        if (reason == 0) {\n            try this.swapFor{value: msg.value}(season, drawer) returns (uint256 o) {\n                if (o != 0) {\n                    emit LuckyBuy(drawer, msg.value, o);\n                    return o;\n                }\n            } catch (bytes memory err) {\n                uint256 c = err.length == 32 ? uint256(bytes32(err)) : 5;\n                reason = c >= 3 && c <= 5 ? uint8(c) : 5;\n            }\n            if (reason == 0) reason = 4;\n            emit LuckyBuySkipped(drawer, msg.value, reason);\n        }\n        (bool ok,) = IDailyLike(msg.sender).PAYEE().call{value: msg.value}(\"\");\n        if (!ok) revert PayFailed();\n    }\n\n    /// @dev External so a failure anywhere (including after WBNB reached the pair) is rolled back as a whole.\n    ///      Reverts with a 32-byte reason code (3 pair not usable, 4 zero amount out).\n    function swapFor(address season, address drawer) external payable returns (uint256 out) {\n        if (msg.sender != address(this)) revert OnlySelf();\n        address p = ISeasonLike(season).pair();\n        address t = ISeasonLike(season).token();\n        if (p.code.length == 0) _code(3);\n        address t0 = IPairLike(p).token0();\n        address t1 = IPairLike(p).token1();\n        bool wbnbIs0 = t0 == address(WBNB);\n        if (!(wbnbIs0 ? t1 == t : (t1 == address(WBNB) && t0 == t))) _code(3);\n        (uint112 r0, uint112 r1,) = IPairLike(p).getReserves();\n        (uint256 rIn, uint256 rOut) = wbnbIs0 ? (uint256(r0), uint256(r1)) : (uint256(r1), uint256(r0));\n        if (rIn == 0 || rOut == 0) _code(3);\n        uint256 inFee = msg.value * 9975;\n        out = inFee * rOut / (rIn * 10_000 + inFee);\n        if (out == 0) _code(4);\n        WBNB.deposit{value: msg.value}();\n        if (!WBNB.transfer(p, msg.value)) _code(5);\n        IPairLike(p).swap(wbnbIs0 ? 0 : out, wbnbIs0 ? out : 0, drawer, \"\");\n    }\n\n    function _launched(address season) private view returns (bool) {\n        try ISeasonLike(season).launched() returns (bool l) {\n            return l;\n        } catch {\n            return false;\n        }\n    }\n\n    function _code(uint256 c) private pure {\n        assembly (\"memory-safe\") {\n            mstore(0, c)\n            revert(0, 32)\n        }\n    }\n}\n"},"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC721/IERC721.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC165} from \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC-721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in ``owner``'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon\n     *   a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC-721 protocol to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or\n     *   {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon\n     *   a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC-721\n     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must\n     * understand this adds an external call which potentially creates a reentrancy vulnerability.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 tokenId) external;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external;\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the address zero.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool approved) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n"},"lib/openzeppelin-contracts/contracts/token/ERC721/extensions/IERC721Metadata.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity >=0.6.2;\n\nimport {IERC721} from \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n    /**\n     * @dev Returns the token collection name.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the token collection symbol.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n     */\n    function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n"},"lib/openzeppelin-contracts/contracts/token/ERC721/utils/ERC721Utils.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC721/utils/ERC721Utils.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC721Receiver} from \"../IERC721Receiver.sol\";\nimport {IERC721Errors} from \"../../../interfaces/draft-IERC6093.sol\";\n\n/**\n * @dev Library that provide common ERC-721 utility functions.\n *\n * See https://eips.ethereum.org/EIPS/eip-721[ERC-721].\n *\n * _Available since v5.1._\n */\nlibrary ERC721Utils {\n    /**\n     * @dev Performs an acceptance check for the provided `operator` by calling {IERC721Receiver-onERC721Received}\n     * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).\n     *\n     * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).\n     * Otherwise, the recipient must implement {IERC721Receiver-onERC721Received} and return the acceptance magic value to accept\n     * the transfer.\n     */\n    function checkOnERC721Received(\n        address operator,\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    ) internal {\n        if (to.code.length > 0) {\n            try IERC721Receiver(to).onERC721Received(operator, from, tokenId, data) returns (bytes4 retval) {\n                if (retval != IERC721Receiver.onERC721Received.selector) {\n                    // Token rejected\n                    revert IERC721Errors.ERC721InvalidReceiver(to);\n                }\n            } catch (bytes memory reason) {\n                if (reason.length == 0) {\n                    // non-IERC721Receiver implementer\n                    revert IERC721Errors.ERC721InvalidReceiver(to);\n                } else {\n                    assembly (\"memory-safe\") {\n                        revert(add(reason, 0x20), mload(reason))\n                    }\n                }\n            }\n        }\n    }\n}\n"},"lib/openzeppelin-contracts/contracts/utils/Context.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"},"lib/openzeppelin-contracts/contracts/utils/Strings.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/Strings.sol)\n\npragma solidity ^0.8.20;\n\nimport {Math} from \"./math/Math.sol\";\nimport {SafeCast} from \"./math/SafeCast.sol\";\nimport {SignedMath} from \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    using SafeCast for *;\n\n    bytes16 private constant HEX_DIGITS = \"0123456789abcdef\";\n    uint8 private constant ADDRESS_LENGTH = 20;\n    uint256 private constant SPECIAL_CHARS_LOOKUP =\n        (1 << 0x08) | // backspace\n            (1 << 0x09) | // tab\n            (1 << 0x0a) | // newline\n            (1 << 0x0c) | // form feed\n            (1 << 0x0d) | // carriage return\n            (1 << 0x22) | // double quote\n            (1 << 0x5c); // backslash\n\n    /**\n     * @dev The `value` string doesn't fit in the specified `length`.\n     */\n    error StringsInsufficientHexLength(uint256 value, uint256 length);\n\n    /**\n     * @dev The string being parsed contains characters that are not in scope of the given base.\n     */\n    error StringsInvalidChar();\n\n    /**\n     * @dev The string being parsed is not a properly formatted address.\n     */\n    error StringsInvalidAddressFormat();\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = Math.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            assembly (\"memory-safe\") {\n                ptr := add(add(buffer, 0x20), length)\n            }\n            while (true) {\n                ptr--;\n                assembly (\"memory-safe\") {\n                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\n     */\n    function toStringSigned(int256 value) internal pure returns (string memory) {\n        return string.concat(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value)));\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, Math.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        uint256 localValue = value;\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = HEX_DIGITS[localValue & 0xf];\n            localValue >>= 4;\n        }\n        if (localValue != 0) {\n            revert StringsInsufficientHexLength(value, length);\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal\n     * representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal\n     * representation, according to EIP-55.\n     */\n    function toChecksumHexString(address addr) internal pure returns (string memory) {\n        bytes memory buffer = bytes(toHexString(addr));\n\n        // hash the hex part of buffer (skip length + 2 bytes, length 40)\n        uint256 hashValue;\n        assembly (\"memory-safe\") {\n            hashValue := shr(96, keccak256(add(buffer, 0x22), 40))\n        }\n\n        for (uint256 i = 41; i > 1; --i) {\n            // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f)\n            if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) {\n                // case shift by xoring with 0x20\n                buffer[i] ^= 0x20;\n            }\n            hashValue >>= 4;\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Returns true if the two strings are equal.\n     */\n    function equal(string memory a, string memory b) internal pure returns (bool) {\n        return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));\n    }\n\n    /**\n     * @dev Parse a decimal string and returns the value as a `uint256`.\n     *\n     * Requirements:\n     * - The string must be formatted as `[0-9]*`\n     * - The result must fit into an `uint256` type\n     */\n    function parseUint(string memory input) internal pure returns (uint256) {\n        return parseUint(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseUint-string} that parses a substring of `input` located between position `begin` (included) and\n     * `end` (excluded).\n     *\n     * Requirements:\n     * - The substring must be formatted as `[0-9]*`\n     * - The result must fit into an `uint256` type\n     */\n    function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {\n        (bool success, uint256 value) = tryParseUint(input, begin, end);\n        if (!success) revert StringsInvalidChar();\n        return value;\n    }\n\n    /**\n     * @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character.\n     *\n     * NOTE: This function will revert if the result does not fit in a `uint256`.\n     */\n    function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) {\n        return _tryParseUintUncheckedBounds(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid\n     * character.\n     *\n     * NOTE: This function will revert if the result does not fit in a `uint256`.\n     */\n    function tryParseUint(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) internal pure returns (bool success, uint256 value) {\n        if (end > bytes(input).length || begin > end) return (false, 0);\n        return _tryParseUintUncheckedBounds(input, begin, end);\n    }\n\n    /**\n     * @dev Implementation of {tryParseUint-string-uint256-uint256} that does not check bounds. Caller should make sure that\n     * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\n     */\n    function _tryParseUintUncheckedBounds(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) private pure returns (bool success, uint256 value) {\n        bytes memory buffer = bytes(input);\n\n        uint256 result = 0;\n        for (uint256 i = begin; i < end; ++i) {\n            uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));\n            if (chr > 9) return (false, 0);\n            result *= 10;\n            result += chr;\n        }\n        return (true, result);\n    }\n\n    /**\n     * @dev Parse a decimal string and returns the value as a `int256`.\n     *\n     * Requirements:\n     * - The string must be formatted as `[-+]?[0-9]*`\n     * - The result must fit in an `int256` type.\n     */\n    function parseInt(string memory input) internal pure returns (int256) {\n        return parseInt(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and\n     * `end` (excluded).\n     *\n     * Requirements:\n     * - The substring must be formatted as `[-+]?[0-9]*`\n     * - The result must fit in an `int256` type.\n     */\n    function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) {\n        (bool success, int256 value) = tryParseInt(input, begin, end);\n        if (!success) revert StringsInvalidChar();\n        return value;\n    }\n\n    /**\n     * @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if\n     * the result does not fit in a `int256`.\n     *\n     * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.\n     */\n    function tryParseInt(string memory input) internal pure returns (bool success, int256 value) {\n        return _tryParseIntUncheckedBounds(input, 0, bytes(input).length);\n    }\n\n    uint256 private constant ABS_MIN_INT256 = 2 ** 255;\n\n    /**\n     * @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid\n     * character or if the result does not fit in a `int256`.\n     *\n     * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`.\n     */\n    function tryParseInt(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) internal pure returns (bool success, int256 value) {\n        if (end > bytes(input).length || begin > end) return (false, 0);\n        return _tryParseIntUncheckedBounds(input, begin, end);\n    }\n\n    /**\n     * @dev Implementation of {tryParseInt-string-uint256-uint256} that does not check bounds. Caller should make sure that\n     * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\n     */\n    function _tryParseIntUncheckedBounds(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) private pure returns (bool success, int256 value) {\n        bytes memory buffer = bytes(input);\n\n        // Check presence of a negative sign.\n        bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\n        bool positiveSign = sign == bytes1(\"+\");\n        bool negativeSign = sign == bytes1(\"-\");\n        uint256 offset = (positiveSign || negativeSign).toUint();\n\n        (bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end);\n\n        if (absSuccess && absValue < ABS_MIN_INT256) {\n            return (true, negativeSign ? -int256(absValue) : int256(absValue));\n        } else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) {\n            return (true, type(int256).min);\n        } else return (false, 0);\n    }\n\n    /**\n     * @dev Parse a hexadecimal string (with or without \"0x\" prefix), and returns the value as a `uint256`.\n     *\n     * Requirements:\n     * - The string must be formatted as `(0x)?[0-9a-fA-F]*`\n     * - The result must fit in an `uint256` type.\n     */\n    function parseHexUint(string memory input) internal pure returns (uint256) {\n        return parseHexUint(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseHexUint-string} that parses a substring of `input` located between position `begin` (included) and\n     * `end` (excluded).\n     *\n     * Requirements:\n     * - The substring must be formatted as `(0x)?[0-9a-fA-F]*`\n     * - The result must fit in an `uint256` type.\n     */\n    function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) {\n        (bool success, uint256 value) = tryParseHexUint(input, begin, end);\n        if (!success) revert StringsInvalidChar();\n        return value;\n    }\n\n    /**\n     * @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character.\n     *\n     * NOTE: This function will revert if the result does not fit in a `uint256`.\n     */\n    function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) {\n        return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an\n     * invalid character.\n     *\n     * NOTE: This function will revert if the result does not fit in a `uint256`.\n     */\n    function tryParseHexUint(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) internal pure returns (bool success, uint256 value) {\n        if (end > bytes(input).length || begin > end) return (false, 0);\n        return _tryParseHexUintUncheckedBounds(input, begin, end);\n    }\n\n    /**\n     * @dev Implementation of {tryParseHexUint-string-uint256-uint256} that does not check bounds. Caller should make sure that\n     * `begin <= end <= input.length`. Other inputs would result in undefined behavior.\n     */\n    function _tryParseHexUintUncheckedBounds(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) private pure returns (bool success, uint256 value) {\n        bytes memory buffer = bytes(input);\n\n        // skip 0x prefix if present\n        bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2(\"0x\"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\n        uint256 offset = hasPrefix.toUint() * 2;\n\n        uint256 result = 0;\n        for (uint256 i = begin + offset; i < end; ++i) {\n            uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i)));\n            if (chr > 15) return (false, 0);\n            result *= 16;\n            unchecked {\n                // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).\n                // This guarantees that adding a value < 16 will not cause an overflow, hence the unchecked.\n                result += chr;\n            }\n        }\n        return (true, result);\n    }\n\n    /**\n     * @dev Parse a hexadecimal string (with or without \"0x\" prefix), and returns the value as an `address`.\n     *\n     * Requirements:\n     * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}`\n     */\n    function parseAddress(string memory input) internal pure returns (address) {\n        return parseAddress(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseAddress-string} that parses a substring of `input` located between position `begin` (included) and\n     * `end` (excluded).\n     *\n     * Requirements:\n     * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}`\n     */\n    function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) {\n        (bool success, address value) = tryParseAddress(input, begin, end);\n        if (!success) revert StringsInvalidAddressFormat();\n        return value;\n    }\n\n    /**\n     * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly\n     * formatted address. See {parseAddress-string} requirements.\n     */\n    function tryParseAddress(string memory input) internal pure returns (bool success, address value) {\n        return tryParseAddress(input, 0, bytes(input).length);\n    }\n\n    /**\n     * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly\n     * formatted address. See {parseAddress-string-uint256-uint256} requirements.\n     */\n    function tryParseAddress(\n        string memory input,\n        uint256 begin,\n        uint256 end\n    ) internal pure returns (bool success, address value) {\n        if (end > bytes(input).length || begin > end) return (false, address(0));\n\n        bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2(\"0x\"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty\n        uint256 expectedLength = 40 + hasPrefix.toUint() * 2;\n\n        // check that input is the correct length\n        if (end - begin == expectedLength) {\n            // length guarantees that this does not overflow, and value is at most type(uint160).max\n            (bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end);\n            return (s, address(uint160(v)));\n        } else {\n            return (false, address(0));\n        }\n    }\n\n    function _tryParseChr(bytes1 chr) private pure returns (uint8) {\n        uint8 value = uint8(chr);\n\n        // Try to parse `chr`:\n        // - Case 1: [0-9]\n        // - Case 2: [a-f]\n        // - Case 3: [A-F]\n        // - otherwise not supported\n        unchecked {\n            if (value > 47 && value < 58) value -= 48;\n            else if (value > 96 && value < 103) value -= 87;\n            else if (value > 64 && value < 71) value -= 55;\n            else return type(uint8).max;\n        }\n\n        return value;\n    }\n\n    /**\n     * @dev Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata.\n     *\n     * WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped.\n     *\n     * NOTE: This function escapes all unicode characters, and not just the ones in ranges defined in section 2.5 of\n     * RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). ECMAScript's `JSON.parse` does recover escaped unicode\n     * characters that are not in this range, but other tooling may provide different results.\n     */\n    function escapeJSON(string memory input) internal pure returns (string memory) {\n        bytes memory buffer = bytes(input);\n        bytes memory output = new bytes(2 * buffer.length); // worst case scenario\n        uint256 outputLength = 0;\n\n        for (uint256 i; i < buffer.length; ++i) {\n            bytes1 char = bytes1(_unsafeReadBytesOffset(buffer, i));\n            if (((SPECIAL_CHARS_LOOKUP & (1 << uint8(char))) != 0)) {\n                output[outputLength++] = \"\\\\\";\n                if (char == 0x08) output[outputLength++] = \"b\";\n                else if (char == 0x09) output[outputLength++] = \"t\";\n                else if (char == 0x0a) output[outputLength++] = \"n\";\n                else if (char == 0x0c) output[outputLength++] = \"f\";\n                else if (char == 0x0d) output[outputLength++] = \"r\";\n                else if (char == 0x5c) output[outputLength++] = \"\\\\\";\n                else if (char == 0x22) {\n                    // solhint-disable-next-line quotes\n                    output[outputLength++] = '\"';\n                }\n            } else {\n                output[outputLength++] = char;\n            }\n        }\n        // write the actual length and deallocate unused memory\n        assembly (\"memory-safe\") {\n            mstore(output, outputLength)\n            mstore(0x40, add(output, shl(5, shr(5, add(outputLength, 63)))))\n        }\n\n        return string(output);\n    }\n\n    /**\n     * @dev Reads a bytes32 from a bytes array without bounds checking.\n     *\n     * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the\n     * assembly block as such would prevent some optimizations.\n     */\n    function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {\n        // This is not memory safe in the general case, but all calls to this private function are within bounds.\n        assembly (\"memory-safe\") {\n            value := mload(add(add(buffer, 0x20), offset))\n        }\n    }\n}\n"},"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"},"lib/openzeppelin-contracts/contracts/interfaces/draft-IERC6093.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC6093.sol)\npragma solidity >=0.8.4;\n\n/**\n * @dev Standard ERC-20 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.\n */\ninterface IERC20Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC20InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC20InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     * @param allowance Amount of tokens a `spender` is allowed to operate with.\n     * @param needed Minimum amount required to perform a transfer.\n     */\n    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC20InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.\n     * @param spender Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC20InvalidSpender(address spender);\n}\n\n/**\n * @dev Standard ERC-721 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.\n */\ninterface IERC721Errors {\n    /**\n     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.\n     * Used in balance queries.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721InvalidOwner(address owner);\n\n    /**\n     * @dev Indicates a `tokenId` whose `owner` is the zero address.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721NonexistentToken(uint256 tokenId);\n\n    /**\n     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param tokenId Identifier number of a token.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC721InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC721InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC721InsufficientApproval(address operator, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC721InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC721InvalidOperator(address operator);\n}\n\n/**\n * @dev Standard ERC-1155 Errors\n * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\n */\ninterface IERC1155Errors {\n    /**\n     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     * @param balance Current balance for the interacting account.\n     * @param needed Minimum amount required to perform a transfer.\n     * @param tokenId Identifier number of a token.\n     */\n    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\n\n    /**\n     * @dev Indicates a failure with the token `sender`. Used in transfers.\n     * @param sender Address whose tokens are being transferred.\n     */\n    error ERC1155InvalidSender(address sender);\n\n    /**\n     * @dev Indicates a failure with the token `receiver`. Used in transfers.\n     * @param receiver Address to which tokens are being transferred.\n     */\n    error ERC1155InvalidReceiver(address receiver);\n\n    /**\n     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     * @param owner Address of the current owner of a token.\n     */\n    error ERC1155MissingApprovalForAll(address operator, address owner);\n\n    /**\n     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\n     * @param approver Address initiating an approval operation.\n     */\n    error ERC1155InvalidApprover(address approver);\n\n    /**\n     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\n     * @param operator Address that may be allowed to operate on tokens without being their owner.\n     */\n    error ERC1155InvalidOperator(address operator);\n\n    /**\n     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\n     * Used in batch transfers.\n     * @param idsLength Length of the array of token identifiers\n     * @param valuesLength Length of the array of token amounts\n     */\n    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\n}\n"},"lib/openzeppelin-contracts/contracts/utils/Base64.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/Base64.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides a set of functions to operate with Base64 strings.\n */\nlibrary Base64 {\n    /**\n     * @dev Base64 Encoding/Decoding Table\n     * See sections 4 and 5 of https://datatracker.ietf.org/doc/html/rfc4648\n     */\n    string internal constant _TABLE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n    string internal constant _TABLE_URL = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\";\n\n    /**\n     * @dev Converts a `bytes` to its Bytes64 `string` representation.\n     */\n    function encode(bytes memory data) internal pure returns (string memory) {\n        return _encode(data, _TABLE, true);\n    }\n\n    /**\n     * @dev Converts a `bytes` to its Bytes64Url `string` representation.\n     * Output is not padded with `=` as specified in https://www.rfc-editor.org/rfc/rfc4648[rfc4648].\n     */\n    function encodeURL(bytes memory data) internal pure returns (string memory) {\n        return _encode(data, _TABLE_URL, false);\n    }\n\n    /**\n     * @dev Internal table-agnostic conversion\n     */\n    function _encode(bytes memory data, string memory table, bool withPadding) private pure returns (string memory) {\n        /**\n         * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence\n         * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol\n         */\n        if (data.length == 0) return \"\";\n\n        // If padding is enabled, the final length should be `bytes` data length divided by 3 rounded up and then\n        // multiplied by 4 so that it leaves room for padding the last chunk\n        // - `data.length + 2`  -> Prepare for division rounding up\n        // - `/ 3`              -> Number of 3-bytes chunks (rounded up)\n        // - `4 *`              -> 4 characters for each chunk\n        // This is equivalent to: 4 * Math.ceil(data.length / 3)\n        //\n        // If padding is disabled, the final length should be `bytes` data length multiplied by 4/3 rounded up as\n        // opposed to when padding is required to fill the last chunk.\n        // - `4 * data.length`  -> 4 characters for each chunk\n        // - ` + 2`             -> Prepare for division rounding up\n        // - `/ 3`              -> Number of 3-bytes chunks (rounded up)\n        // This is equivalent to: Math.ceil((4 * data.length) / 3)\n        uint256 resultLength = withPadding ? 4 * ((data.length + 2) / 3) : (4 * data.length + 2) / 3;\n\n        string memory result = new string(resultLength);\n\n        assembly (\"memory-safe\") {\n            // Prepare the lookup table (skip the first \"length\" byte)\n            let tablePtr := add(table, 1)\n\n            // Prepare result pointer, jump over length\n            let resultPtr := add(result, 0x20)\n            let dataPtr := data\n            let endPtr := add(data, mload(data))\n\n            // In some cases, the last iteration will read bytes after the end of the data. We cache the value, and\n            // set it to zero to make sure no dirty bytes are read in that section.\n            let afterPtr := add(endPtr, 0x20)\n            let afterCache := mload(afterPtr)\n            mstore(afterPtr, 0x00)\n\n            // Run over the input, 3 bytes at a time\n            for {} lt(dataPtr, endPtr) {} {\n                // Advance 3 bytes\n                dataPtr := add(dataPtr, 3)\n                let input := mload(dataPtr)\n\n                // To write each character, shift the 3 byte (24 bits) chunk\n                // 4 times in blocks of 6 bits for each character (18, 12, 6, 0)\n                // and apply logical AND with 0x3F to bitmask the least significant 6 bits.\n                // Use this as an index into the lookup table, mload an entire word\n                // so the desired character is in the least significant byte, and\n                // mstore8 this least significant byte into the result and continue.\n\n                mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n\n                mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n\n                mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n\n                mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))\n                resultPtr := add(resultPtr, 1) // Advance\n            }\n\n            // Reset the value that was cached\n            mstore(afterPtr, afterCache)\n\n            if withPadding {\n                // When data `bytes` is not exactly 3 bytes long\n                // it is padded with `=` characters at the end\n                switch mod(mload(data), 3)\n                case 1 {\n                    mstore8(sub(resultPtr, 1), 0x3d)\n                    mstore8(sub(resultPtr, 2), 0x3d)\n                }\n                case 2 {\n                    mstore8(sub(resultPtr, 1), 0x3d)\n                }\n            }\n        }\n\n        return result;\n    }\n}\n"},"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},"lib/openzeppelin-contracts/contracts/token/ERC721/IERC721Receiver.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity >=0.5.0;\n\n/**\n * @title ERC-721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC-721 asset contracts.\n */\ninterface IERC721Receiver {\n    /**\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n     * by `operator` from `from`, this function is called.\n     *\n     * It must return its Solidity selector to confirm the token transfer.\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be\n     * reverted.\n     *\n     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n     */\n    function onERC721Received(\n        address operator,\n        address from,\n        uint256 tokenId,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n"},"lib/openzeppelin-contracts/contracts/utils/math/Math.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.20;\n\nimport {Panic} from \"../Panic.sol\";\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Floor, // Toward negative infinity\n        Ceil, // Toward positive infinity\n        Trunc, // Toward zero\n        Expand // Away from zero\n    }\n\n    /**\n     * @dev Return the 512-bit addition of two uint256.\n     *\n     * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.\n     */\n    function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n        assembly (\"memory-safe\") {\n            low := add(a, b)\n            high := lt(low, a)\n        }\n    }\n\n    /**\n     * @dev Return the 512-bit multiplication of two uint256.\n     *\n     * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.\n     */\n    function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {\n        // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use\n        // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n        // variables such that product = high * 2²⁵⁶ + low.\n        assembly (\"memory-safe\") {\n            let mm := mulmod(a, b, not(0))\n            low := mul(a, b)\n            high := sub(sub(mm, low), lt(mm, low))\n        }\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a + b;\n            success = c >= a;\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a - b;\n            success = c <= a;\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            uint256 c = a * b;\n            assembly (\"memory-safe\") {\n                // Only true when the multiplication doesn't overflow\n                // (c / a == b) || (a == 0)\n                success := or(eq(div(c, a), b), iszero(a))\n            }\n            // equivalent to: success ? c : 0\n            result = c * SafeCast.toUint(success);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            success = b > 0;\n            assembly (\"memory-safe\") {\n                // The `DIV` opcode returns zero when the denominator is 0.\n                result := div(a, b)\n            }\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {\n        unchecked {\n            success = b > 0;\n            assembly (\"memory-safe\") {\n                // The `MOD` opcode returns zero when the denominator is 0.\n                result := mod(a, b)\n            }\n        }\n    }\n\n    /**\n     * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.\n     */\n    function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {\n        (bool success, uint256 result) = tryAdd(a, b);\n        return ternary(success, result, type(uint256).max);\n    }\n\n    /**\n     * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.\n     */\n    function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {\n        (, uint256 result) = trySub(a, b);\n        return result;\n    }\n\n    /**\n     * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.\n     */\n    function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {\n        (bool success, uint256 result) = tryMul(a, b);\n        return ternary(success, result, type(uint256).max);\n    }\n\n    /**\n     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\n     *\n     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\n     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\n     * one branch when needed, making this function more expensive.\n     */\n    function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {\n        unchecked {\n            // branchless ternary works because:\n            // b ^ (a ^ b) == a\n            // b ^ 0 == b\n            return b ^ ((a ^ b) * SafeCast.toUint(condition));\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return ternary(a > b, a, b);\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return ternary(a < b, a, b);\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds towards infinity instead\n     * of rounding towards zero.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (b == 0) {\n            // Guarantee the same behavior as in a regular Solidity division.\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n\n        // The following calculation ensures accurate ceiling division without overflow.\n        // Since a is non-zero, (a - 1) / b will not overflow.\n        // The largest possible result occurs when (a - 1) / b is type(uint256).max,\n        // but the largest value we can obtain is type(uint256).max - 1, which happens\n        // when a = type(uint256).max and b = 1.\n        unchecked {\n            return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);\n        }\n    }\n\n    /**\n     * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n     * denominator == 0.\n     *\n     * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by\n     * Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            (uint256 high, uint256 low) = mul512(x, y);\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (high == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return low / denominator;\n            }\n\n            // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.\n            if (denominator <= high) {\n                Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));\n            }\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [high low].\n            uint256 remainder;\n            assembly (\"memory-safe\") {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                high := sub(high, gt(remainder, low))\n                low := sub(low, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.\n            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.\n\n            uint256 twos = denominator & (0 - denominator);\n            assembly (\"memory-safe\") {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [high low] by twos.\n                low := div(low, twos)\n\n                // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from high into low.\n            low |= high * twos;\n\n            // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such\n            // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv ≡ 1 mod 2⁴.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also\n            // works in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶\n            inverse *= 2 - denominator * inverse; // inverse mod 2³²\n            inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴\n            inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸\n            inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is\n            // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high\n            // is no longer required.\n            result = low * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);\n    }\n\n    /**\n     * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.\n     */\n    function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {\n        unchecked {\n            (uint256 high, uint256 low) = mul512(x, y);\n            if (high >= 1 << n) {\n                Panic.panic(Panic.UNDER_OVERFLOW);\n            }\n            return (high << (256 - n)) | (low >> n);\n        }\n    }\n\n    /**\n     * @dev Calculates x * y >> n with full precision, following the selected rounding direction.\n     */\n    function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {\n        return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);\n    }\n\n    /**\n     * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.\n     *\n     * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.\n     * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.\n     *\n     * If the input value is not inversible, 0 is returned.\n     *\n     * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the\n     * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.\n     */\n    function invMod(uint256 a, uint256 n) internal pure returns (uint256) {\n        unchecked {\n            if (n == 0) return 0;\n\n            // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)\n            // Used to compute integers x and y such that: ax + ny = gcd(a, n).\n            // When the gcd is 1, then the inverse of a modulo n exists and it's x.\n            // ax + ny = 1\n            // ax = 1 + (-y)n\n            // ax ≡ 1 (mod n) # x is the inverse of a modulo n\n\n            // If the remainder is 0 the gcd is n right away.\n            uint256 remainder = a % n;\n            uint256 gcd = n;\n\n            // Therefore the initial coefficients are:\n            // ax + ny = gcd(a, n) = n\n            // 0a + 1n = n\n            int256 x = 0;\n            int256 y = 1;\n\n            while (remainder != 0) {\n                uint256 quotient = gcd / remainder;\n\n                (gcd, remainder) = (\n                    // The old remainder is the next gcd to try.\n                    remainder,\n                    // Compute the next remainder.\n                    // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd\n                    // where gcd is at most n (capped to type(uint256).max)\n                    gcd - remainder * quotient\n                );\n\n                (x, y) = (\n                    // Increment the coefficient of a.\n                    y,\n                    // Decrement the coefficient of n.\n                    // Can overflow, but the result is casted to uint256 so that the\n                    // next value of y is \"wrapped around\" to a value between 0 and n - 1.\n                    x - y * int256(quotient)\n                );\n            }\n\n            if (gcd != 1) return 0; // No inverse exists.\n            return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.\n        }\n    }\n\n    /**\n     * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.\n     *\n     * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is\n     * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that\n     * `a**(p-2)` is the modular multiplicative inverse of a in Fp.\n     *\n     * NOTE: this function does NOT check that `p` is a prime greater than `2`.\n     */\n    function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {\n        unchecked {\n            return Math.modExp(a, p - 2, p);\n        }\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)\n     *\n     * Requirements:\n     * - modulus can't be zero\n     * - underlying staticcall to precompile must succeed\n     *\n     * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make\n     * sure the chain you're using it on supports the precompiled contract for modular exponentiation\n     * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,\n     * the underlying function will succeed given the lack of a revert, but the result may be incorrectly\n     * interpreted as 0.\n     */\n    function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {\n        (bool success, uint256 result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).\n     * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying\n     * to operate modulo 0 or if the underlying precompile reverted.\n     *\n     * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain\n     * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in\n     * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack\n     * of a revert, but the result may be incorrectly interpreted as 0.\n     */\n    function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {\n        if (m == 0) return (false, 0);\n        assembly (\"memory-safe\") {\n            let ptr := mload(0x40)\n            // | Offset    | Content    | Content (Hex)                                                      |\n            // |-----------|------------|--------------------------------------------------------------------|\n            // | 0x00:0x1f | size of b  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x20:0x3f | size of e  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x40:0x5f | size of m  | 0x0000000000000000000000000000000000000000000000000000000000000020 |\n            // | 0x60:0x7f | value of b | 0x<.............................................................b> |\n            // | 0x80:0x9f | value of e | 0x<.............................................................e> |\n            // | 0xa0:0xbf | value of m | 0x<.............................................................m> |\n            mstore(ptr, 0x20)\n            mstore(add(ptr, 0x20), 0x20)\n            mstore(add(ptr, 0x40), 0x20)\n            mstore(add(ptr, 0x60), b)\n            mstore(add(ptr, 0x80), e)\n            mstore(add(ptr, 0xa0), m)\n\n            // Given the result < m, it's guaranteed to fit in 32 bytes,\n            // so we can use the memory scratch space located at offset 0.\n            success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)\n            result := mload(0x00)\n        }\n    }\n\n    /**\n     * @dev Variant of {modExp} that supports inputs of arbitrary length.\n     */\n    function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {\n        (bool success, bytes memory result) = tryModExp(b, e, m);\n        if (!success) {\n            Panic.panic(Panic.DIVISION_BY_ZERO);\n        }\n        return result;\n    }\n\n    /**\n     * @dev Variant of {tryModExp} that supports inputs of arbitrary length.\n     */\n    function tryModExp(\n        bytes memory b,\n        bytes memory e,\n        bytes memory m\n    ) internal view returns (bool success, bytes memory result) {\n        if (_zeroBytes(m)) return (false, new bytes(0));\n\n        uint256 mLen = m.length;\n\n        // Encode call args in result and move the free memory pointer\n        result = abi.encodePacked(b.length, e.length, mLen, b, e, m);\n\n        assembly (\"memory-safe\") {\n            let dataPtr := add(result, 0x20)\n            // Write result on top of args to avoid allocating extra memory.\n            success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)\n            // Overwrite the length.\n            // result.length > returndatasize() is guaranteed because returndatasize() == m.length\n            mstore(result, mLen)\n            // Set the memory pointer after the returned data.\n            mstore(0x40, add(dataPtr, mLen))\n        }\n    }\n\n    /**\n     * @dev Returns whether the provided byte array is zero.\n     */\n    function _zeroBytes(bytes memory byteArray) private pure returns (bool) {\n        for (uint256 i = 0; i < byteArray.length; ++i) {\n            if (byteArray[i] != 0) {\n                return false;\n            }\n        }\n        return true;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded\n     * towards zero.\n     *\n     * This method is based on Newton's method for computing square roots; the algorithm is restricted to only\n     * using integer operations.\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        unchecked {\n            // Take care of easy edge cases when a == 0 or a == 1\n            if (a <= 1) {\n                return a;\n            }\n\n            // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a\n            // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between\n            // the current value as `ε_n = | x_n - sqrt(a) |`.\n            //\n            // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root\n            // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is\n            // bigger than any uint256.\n            //\n            // By noticing that\n            // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`\n            // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar\n            // to the msb function.\n            uint256 aa = a;\n            uint256 xn = 1;\n\n            if (aa >= (1 << 128)) {\n                aa >>= 128;\n                xn <<= 64;\n            }\n            if (aa >= (1 << 64)) {\n                aa >>= 64;\n                xn <<= 32;\n            }\n            if (aa >= (1 << 32)) {\n                aa >>= 32;\n                xn <<= 16;\n            }\n            if (aa >= (1 << 16)) {\n                aa >>= 16;\n                xn <<= 8;\n            }\n            if (aa >= (1 << 8)) {\n                aa >>= 8;\n                xn <<= 4;\n            }\n            if (aa >= (1 << 4)) {\n                aa >>= 4;\n                xn <<= 2;\n            }\n            if (aa >= (1 << 2)) {\n                xn <<= 1;\n            }\n\n            // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).\n            //\n            // We can refine our estimation by noticing that the middle of that interval minimizes the error.\n            // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).\n            // This is going to be our x_0 (and ε_0)\n            xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)\n\n            // From here, Newton's method give us:\n            // x_{n+1} = (x_n + a / x_n) / 2\n            //\n            // One should note that:\n            // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a\n            //              = ((x_n² + a) / (2 * x_n))² - a\n            //              = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a\n            //              = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)\n            //              = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)\n            //              = (x_n² - a)² / (2 * x_n)²\n            //              = ((x_n² - a) / (2 * x_n))²\n            //              ≥ 0\n            // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n\n            //\n            // This gives us the proof of quadratic convergence of the sequence:\n            // ε_{n+1} = | x_{n+1} - sqrt(a) |\n            //         = | (x_n + a / x_n) / 2 - sqrt(a) |\n            //         = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |\n            //         = | (x_n - sqrt(a))² / (2 * x_n) |\n            //         = | ε_n² / (2 * x_n) |\n            //         = ε_n² / | (2 * x_n) |\n            //\n            // For the first iteration, we have a special case where x_0 is known:\n            // ε_1 = ε_0² / | (2 * x_0) |\n            //     ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))\n            //     ≤ 2**(2*e-4) / (3 * 2**(e-1))\n            //     ≤ 2**(e-3) / 3\n            //     ≤ 2**(e-3-log2(3))\n            //     ≤ 2**(e-4.5)\n            //\n            // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:\n            // ε_{n+1} = ε_n² / | (2 * x_n) |\n            //         ≤ (2**(e-k))² / (2 * 2**(e-1))\n            //         ≤ 2**(2*e-2*k) / 2**e\n            //         ≤ 2**(e-2*k)\n            xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5)  -- special case, see above\n            xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9)    -- general case with k = 4.5\n            xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18)   -- general case with k = 9\n            xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36)   -- general case with k = 18\n            xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72)   -- general case with k = 36\n            xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144)  -- general case with k = 72\n\n            // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision\n            // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either\n            // sqrt(a) or sqrt(a) + 1.\n            return xn - SafeCast.toUint(xn > a / xn);\n        }\n    }\n\n    /**\n     * @dev Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 x) internal pure returns (uint256 r) {\n        // If value has upper 128 bits set, log2 result is at least 128\n        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n        // If upper 64 bits of 128-bit half set, add 64 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n        // If upper 32 bits of 64-bit half set, add 32 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n        // If upper 16 bits of 32-bit half set, add 16 to result\n        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n        // If upper 8 bits of 16-bit half set, add 8 to result\n        r |= SafeCast.toUint((x >> r) > 0xff) << 3;\n        // If upper 4 bits of 8-bit half set, add 4 to result\n        r |= SafeCast.toUint((x >> r) > 0xf) << 2;\n\n        // Shifts value right by the current result and use it as an index into this lookup table:\n        //\n        // | x (4 bits) |  index  | table[index] = MSB position |\n        // |------------|---------|-----------------------------|\n        // |    0000    |    0    |        table[0] = 0         |\n        // |    0001    |    1    |        table[1] = 0         |\n        // |    0010    |    2    |        table[2] = 1         |\n        // |    0011    |    3    |        table[3] = 1         |\n        // |    0100    |    4    |        table[4] = 2         |\n        // |    0101    |    5    |        table[5] = 2         |\n        // |    0110    |    6    |        table[6] = 2         |\n        // |    0111    |    7    |        table[7] = 2         |\n        // |    1000    |    8    |        table[8] = 3         |\n        // |    1001    |    9    |        table[9] = 3         |\n        // |    1010    |   10    |        table[10] = 3        |\n        // |    1011    |   11    |        table[11] = 3        |\n        // |    1100    |   12    |        table[12] = 3        |\n        // |    1101    |   13    |        table[13] = 3        |\n        // |    1110    |   14    |        table[14] = 3        |\n        // |    1111    |   15    |        table[15] = 3        |\n        //\n        // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.\n        assembly (\"memory-safe\") {\n            r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256 of a positive value rounded towards zero.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 x) internal pure returns (uint256 r) {\n        // If value has upper 128 bits set, log2 result is at least 128\n        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;\n        // If upper 64 bits of 128-bit half set, add 64 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;\n        // If upper 32 bits of 64-bit half set, add 32 to result\n        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;\n        // If upper 16 bits of 32-bit half set, add 16 to result\n        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;\n        // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8\n        return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);\n        }\n    }\n\n    /**\n     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.\n     */\n    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {\n        return uint8(rounding) % 2 == 1;\n    }\n}\n"},"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeCast {\n    /**\n     * @dev Value doesn't fit in an uint of `bits` size.\n     */\n    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);\n\n    /**\n     * @dev An int value doesn't fit in an uint of `bits` size.\n     */\n    error SafeCastOverflowedIntToUint(int256 value);\n\n    /**\n     * @dev Value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);\n\n    /**\n     * @dev An uint value doesn't fit in an int of `bits` size.\n     */\n    error SafeCastOverflowedUintToInt(uint256 value);\n\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        if (value > type(uint248).max) {\n            revert SafeCastOverflowedUintDowncast(248, value);\n        }\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        if (value > type(uint240).max) {\n            revert SafeCastOverflowedUintDowncast(240, value);\n        }\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        if (value > type(uint232).max) {\n            revert SafeCastOverflowedUintDowncast(232, value);\n        }\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        if (value > type(uint224).max) {\n            revert SafeCastOverflowedUintDowncast(224, value);\n        }\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        if (value > type(uint216).max) {\n            revert SafeCastOverflowedUintDowncast(216, value);\n        }\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        if (value > type(uint208).max) {\n            revert SafeCastOverflowedUintDowncast(208, value);\n        }\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        if (value > type(uint200).max) {\n            revert SafeCastOverflowedUintDowncast(200, value);\n        }\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        if (value > type(uint192).max) {\n            revert SafeCastOverflowedUintDowncast(192, value);\n        }\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        if (value > type(uint184).max) {\n            revert SafeCastOverflowedUintDowncast(184, value);\n        }\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        if (value > type(uint176).max) {\n            revert SafeCastOverflowedUintDowncast(176, value);\n        }\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        if (value > type(uint168).max) {\n            revert SafeCastOverflowedUintDowncast(168, value);\n        }\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        if (value > type(uint160).max) {\n            revert SafeCastOverflowedUintDowncast(160, value);\n        }\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        if (value > type(uint152).max) {\n            revert SafeCastOverflowedUintDowncast(152, value);\n        }\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        if (value > type(uint144).max) {\n            revert SafeCastOverflowedUintDowncast(144, value);\n        }\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        if (value > type(uint136).max) {\n            revert SafeCastOverflowedUintDowncast(136, value);\n        }\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        if (value > type(uint128).max) {\n            revert SafeCastOverflowedUintDowncast(128, value);\n        }\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        if (value > type(uint120).max) {\n            revert SafeCastOverflowedUintDowncast(120, value);\n        }\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        if (value > type(uint112).max) {\n            revert SafeCastOverflowedUintDowncast(112, value);\n        }\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        if (value > type(uint104).max) {\n            revert SafeCastOverflowedUintDowncast(104, value);\n        }\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        if (value > type(uint96).max) {\n            revert SafeCastOverflowedUintDowncast(96, value);\n        }\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        if (value > type(uint88).max) {\n            revert SafeCastOverflowedUintDowncast(88, value);\n        }\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        if (value > type(uint80).max) {\n            revert SafeCastOverflowedUintDowncast(80, value);\n        }\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        if (value > type(uint72).max) {\n            revert SafeCastOverflowedUintDowncast(72, value);\n        }\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        if (value > type(uint64).max) {\n            revert SafeCastOverflowedUintDowncast(64, value);\n        }\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        if (value > type(uint56).max) {\n            revert SafeCastOverflowedUintDowncast(56, value);\n        }\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        if (value > type(uint48).max) {\n            revert SafeCastOverflowedUintDowncast(48, value);\n        }\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        if (value > type(uint40).max) {\n            revert SafeCastOverflowedUintDowncast(40, value);\n        }\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        if (value > type(uint32).max) {\n            revert SafeCastOverflowedUintDowncast(32, value);\n        }\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        if (value > type(uint24).max) {\n            revert SafeCastOverflowedUintDowncast(24, value);\n        }\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        if (value > type(uint16).max) {\n            revert SafeCastOverflowedUintDowncast(16, value);\n        }\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        if (value > type(uint8).max) {\n            revert SafeCastOverflowedUintDowncast(8, value);\n        }\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        if (value < 0) {\n            revert SafeCastOverflowedIntToUint(value);\n        }\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(248, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(240, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(232, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(224, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(216, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(208, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(200, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(192, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(184, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(176, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(168, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(160, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(152, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(144, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(136, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(128, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(120, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(112, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(104, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(96, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(88, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(80, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(72, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(64, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(56, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(48, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(40, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(32, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(24, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(16, value);\n        }\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        if (downcasted != value) {\n            revert SafeCastOverflowedIntDowncast(8, value);\n        }\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        if (value > uint256(type(int256).max)) {\n            revert SafeCastOverflowedUintToInt(value);\n        }\n        return int256(value);\n    }\n\n    /**\n     * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.\n     */\n    function toUint(bool b) internal pure returns (uint256 u) {\n        assembly (\"memory-safe\") {\n            u := iszero(iszero(b))\n        }\n    }\n}\n"},"lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.20;\n\nimport {SafeCast} from \"./SafeCast.sol\";\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n    /**\n     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.\n     *\n     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.\n     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute\n     * one branch when needed, making this function more expensive.\n     */\n    function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {\n        unchecked {\n            // branchless ternary works because:\n            // b ^ (a ^ b) == a\n            // b ^ 0 == b\n            return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));\n        }\n    }\n\n    /**\n     * @dev Returns the largest of two signed numbers.\n     */\n    function max(int256 a, int256 b) internal pure returns (int256) {\n        return ternary(a > b, a, b);\n    }\n\n    /**\n     * @dev Returns the smallest of two signed numbers.\n     */\n    function min(int256 a, int256 b) internal pure returns (int256) {\n        return ternary(a < b, a, b);\n    }\n\n    /**\n     * @dev Returns the average of two signed numbers without overflow.\n     * The result is rounded towards zero.\n     */\n    function average(int256 a, int256 b) internal pure returns (int256) {\n        // Formula from the book \"Hacker's Delight\"\n        int256 x = (a & b) + ((a ^ b) >> 1);\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\n    }\n\n    /**\n     * @dev Returns the absolute unsigned value of a signed value.\n     */\n    function abs(int256 n) internal pure returns (uint256) {\n        unchecked {\n            // Formula from the \"Bit Twiddling Hacks\" by Sean Eron Anderson.\n            // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,\n            // taking advantage of the most significant (or \"sign\" bit) in two's complement representation.\n            // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,\n            // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative).\n            int256 mask = n >> 255;\n\n            // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.\n            return uint256((n + mask) ^ mask);\n        }\n    }\n}\n"},"lib/openzeppelin-contracts/contracts/utils/Panic.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Helper library for emitting standardized panic codes.\n *\n * ```solidity\n * contract Example {\n *      using Panic for uint256;\n *\n *      // Use any of the declared internal constants\n *      function foo() { Panic.GENERIC.panic(); }\n *\n *      // Alternatively\n *      function foo() { Panic.panic(Panic.GENERIC); }\n * }\n * ```\n *\n * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].\n *\n * _Available since v5.1._\n */\n// slither-disable-next-line unused-state\nlibrary Panic {\n    /// @dev generic / unspecified error\n    uint256 internal constant GENERIC = 0x00;\n    /// @dev used by the assert() builtin\n    uint256 internal constant ASSERT = 0x01;\n    /// @dev arithmetic underflow or overflow\n    uint256 internal constant UNDER_OVERFLOW = 0x11;\n    /// @dev division or modulo by zero\n    uint256 internal constant DIVISION_BY_ZERO = 0x12;\n    /// @dev enum conversion error\n    uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;\n    /// @dev invalid encoding in storage\n    uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;\n    /// @dev empty array pop\n    uint256 internal constant EMPTY_ARRAY_POP = 0x31;\n    /// @dev array out of bounds access\n    uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;\n    /// @dev resource error (too large allocation or too large array)\n    uint256 internal constant RESOURCE_ERROR = 0x41;\n    /// @dev calling invalid internal function\n    uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;\n\n    /// @dev Reverts with a panic code. Recommended to use with\n    /// the internal constants with predefined codes.\n    function panic(uint256 code) internal pure {\n        assembly (\"memory-safe\") {\n            mstore(0x00, 0x4e487b71)\n            mstore(0x20, code)\n            revert(0x1c, 0x24)\n        }\n    }\n}\n"}},"abi":[{"type":"constructor","inputs":[{"name":"c","type":"tuple","components":[{"name":"agentId","type":"address","internalType":"address"},{"name":"renderer","type":"address","internalType":"address"},{"name":"random","type":"address","internalType":"address"},{"name":"tickets","type":"address","internalType":"address"},{"name":"payee","type":"address","internalType":"address"},{"name":"deployer","type":"address","internalType":"address"},{"name":"lucky","type":"address","internalType":"address"},{"name":"luckyBps","type":"uint256","internalType":"uint256"}],"internalType":"struct CharmDaily.Config"}],"stateMutability":"nonpayable"},{"name":"BadConfig","type":"error","inputs":[]},{"name":"BadQuantity","type":"error","inputs":[]},{"name":"DailyLimit","type":"error","inputs":[{"name":"left","type":"uint256","internalType":"uint256"}]},{"name":"DuplicateDesign","type":"error","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}]},{"name":"ERC721IncorrectOwner","type":"error","inputs":[{"name":"sender","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"},{"name":"owner","type":"address","internalType":"address"}]},{"name":"ERC721InsufficientApproval","type":"error","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"tokenId","type":"uint256","internalType":"uint256"}]},{"name":"ERC721InvalidApprover","type":"error","inputs":[{"name":"approver","type":"address","internalType":"address"}]},{"name":"ERC721InvalidOperator","type":"error","inputs":[{"name":"operator","type":"address","internalType":"address"}]},{"name":"ERC721InvalidOwner","type":"error","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"name":"ERC721InvalidReceiver","type":"error","inputs":[{"name":"receiver","type":"address","internalType":"address"}]},{"name":"ERC721InvalidSender","type":"error","inputs":[{"name":"sender","type":"address","internalType":"address"}]},{"name":"ERC721NonexistentToken","type":"error","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}]},{"name":"NoAgentId","type":"error","inputs":[]},{"name":"NoFreeDraw","type":"error","inputs":[{"name":"left","type":"uint256","internalType":"uint256"}]},{"name":"NotACharm","type":"error","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}]},{"name":"NotDeployer","type":"error","inputs":[]},{"name":"NotRevealable","type":"error","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}]},{"name":"NotRevealed","type":"error","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}]},{"name":"NotYourToken","type":"error","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}]},{"name":"PaymentFailed","type":"error","inputs":[]},{"name":"ReentrancyGuardReentrantCall","type":"error","inputs":[]},{"name":"RefundFailed","type":"error","inputs":[]},{"name":"SealedTransfer","type":"error","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}]},{"name":"TooMany","type":"error","inputs":[]},{"name":"WrongPayment","type":"error","inputs":[{"name":"required","type":"uint256","internalType":"uint256"}]},{"name":"WrongWeek","type":"error","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}]},{"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":"Drawn","type":"event","inputs":[{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"agent","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"firstId","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"qty","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"source","type":"uint8","indexed":false,"internalType":"uint8"},{"name":"targetBlock","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"MetadataUpdate","type":"event","inputs":[{"name":"_tokenId","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"Revealed","type":"event","inputs":[{"name":"tokenId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"week","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"tier","type":"uint8","indexed":false,"internalType":"uint8"},{"name":"kind","type":"uint8","indexed":false,"internalType":"uint8"}],"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":"WeekSealForged","type":"event","inputs":[{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"week","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"tokenId","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"rank","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"AGENT_ID","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract IAgentId"}],"stateMutability":"view"},{"name":"DEPLOYER","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"LUCKY","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract CharmDailyLucky"}],"stateMutability":"view"},{"name":"LUCKY_BPS","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"MAX_PAID_PER_DAY","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"MAX_PER_WALLET","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"name":"MAX_SUPPLY","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"pure"},{"name":"PAYEE","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"PRICE","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"RANDOM","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract CharmDailyRandom"}],"stateMutability":"view"},{"name":"RENDERER","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract CharmDailyRenderer"}],"stateMutability":"view"},{"name":"REVEAL_DELAY","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"ROYALTY_BPS","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"SEASON","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"START_DAY","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"TICKETS","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"contract CharmDailyTickets"}],"stateMutability":"view"},{"name":"agentKeyOf","type":"function","inputs":[{"name":"w","type":"address","internalType":"address"}],"outputs":[{"name":"key","type":"bytes32","internalType":"bytes32"},{"name":"ok","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"agentOn","type":"function","inputs":[{"name":"agent","type":"bytes32","internalType":"bytes32"},{"name":"day","type":"uint256","internalType":"uint256"},{"name":"week","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"free","type":"uint256","internalType":"uint256"},{"name":"paid","type":"uint256","internalType":"uint256"},{"name":"bonus","type":"uint256","internalType":"uint256"},{"name":"designs","type":"uint16","internalType":"uint16"},{"name":"firstPaidDone","type":"bool","internalType":"bool"}],"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":"owner","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"bindSeason","type":"function","inputs":[{"name":"season","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"burned","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"claim","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"name":"contractURI","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"name":"currentWeek","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"freeMint","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"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":"owner","type":"address","internalType":"address"},{"name":"operator","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"isSeal","type":"function","inputs":[{"name":"id","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"mint","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"name":"mint","type":"function","inputs":[{"name":"qty","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"payable"},{"name":"mintOpen","type":"function","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"pure"},{"name":"name","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"pure"},{"name":"nextDeadline","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"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":"pointsOf","type":"function","inputs":[{"name":"agent","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"quote","type":"function","inputs":[{"name":"","type":"address","internalType":"address"},{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"cost","type":"uint256","internalType":"uint256"},{"name":"tokens","type":"uint256","internalType":"uint256"},{"name":"bonus","type":"uint256","internalType":"uint256"},{"name":"free","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"registerHoldings","type":"function","inputs":[{"name":"t","type":"tuple[]","components":[{"name":"series","type":"uint8","internalType":"uint8"},{"name":"tokenId","type":"uint256","internalType":"uint256"}],"internalType":"struct CharmDailyTickets.Ticket[]"}],"outputs":[{"name":"total","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"reveal","type":"function","inputs":[{"name":"tokenId","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"revealCursor","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"royaltyInfo","type":"function","inputs":[{"name":"","type":"uint256","internalType":"uint256"},{"name":"salePrice","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"},{"name":"","type":"uint256","internalType":"uint256"}],"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":"saveHashes","type":"function","inputs":[{"name":"n","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"kept","type":"uint256","internalType":"uint256"},{"name":"revealed","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"seal","type":"function","inputs":[{"name":"ids","type":"uint256[10]","internalType":"uint256[10]"}],"outputs":[{"name":"sealId","type":"uint256","internalType":"uint256"}],"stateMutability":"nonpayable"},{"name":"sealedCount","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"setApprovalForAll","type":"function","inputs":[{"name":"operator","type":"address","internalType":"address"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"status","type":"function","inputs":[{"name":"","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"tuple","components":[{"name":"hasAgentId","type":"bool","internalType":"bool"},{"name":"agent","type":"bytes32","internalType":"bytes32"},{"name":"day","type":"uint256","internalType":"uint256"},{"name":"week","type":"uint256","internalType":"uint256"},{"name":"nextResetAt","type":"uint256","internalType":"uint256"},{"name":"freeToday","type":"uint256","internalType":"uint256"},{"name":"freeUsed","type":"uint256","internalType":"uint256"},{"name":"freeLeft","type":"uint256","internalType":"uint256"},{"name":"paidToday","type":"uint256","internalType":"uint256"},{"name":"paidLeft","type":"uint256","internalType":"uint256"},{"name":"bonusToday","type":"uint256","internalType":"uint256"},{"name":"paidUntilNextBonus","type":"uint256","internalType":"uint256"},{"name":"points","type":"uint256","internalType":"uint256"},{"name":"level","type":"uint8","internalType":"uint8"},{"name":"weekDesigns","type":"uint16","internalType":"uint16"},{"name":"firstPaidDone","type":"bool","internalType":"bool"},{"name":"guaranteeTier","type":"uint8","internalType":"uint8"}],"internalType":"struct CharmDailyRenderer.Status"}],"stateMutability":"view"},{"name":"supportsInterface","type":"function","inputs":[{"name":"i","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"symbol","type":"function","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"pure"},{"name":"tierOf","type":"function","inputs":[{"name":"id","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"name":"today","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"tokenInfo","type":"function","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"week","type":"uint256","internalType":"uint256"},{"name":"tier","type":"uint8","internalType":"uint8"},{"name":"kind","type":"uint8","internalType":"uint8"},{"name":"source","type":"uint8","internalType":"uint8"},{"name":"revealed","type":"bool","internalType":"bool"},{"name":"isSeal_","type":"bool","internalType":"bool"},{"name":"sealRank","type":"uint256","internalType":"uint256"},{"name":"targetBlock","type":"uint256","internalType":"uint256"},{"name":"minTier","type":"uint8","internalType":"uint8"},{"name":"revealable","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"tokenRecord","type":"function","inputs":[{"name":"id","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"raw","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"tokenURI","type":"function","inputs":[{"name":"id","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":"totalSupply","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":"weekCounts","type":"function","inputs":[{"name":"w","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"drawn","type":"uint256","internalType":"uint256"},{"name":"seals","type":"uint256","internalType":"uint256"},{"name":"revealedPacked","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"weekInfo","type":"function","inputs":[{"name":"","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"start","type":"uint256","internalType":"uint256"},{"name":"end","type":"uint256","internalType":"uint256"},{"name":"current","type":"bool","internalType":"bool"},{"name":"drawn","type":"uint256","internalType":"uint256"},{"name":"seals","type":"uint256","internalType":"uint256"},{"name":"revealedByTier","type":"uint256[4]","internalType":"uint256[4]"}],"stateMutability":"view"},{"name":"weekStart","type":"function","inputs":[{"name":"w","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"}],"matchId":"57941918","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-11-01T10:03:24Z","match":"exact_match","chainId":"56","address":"0x409Cfe3747f1ac20f267B50BCbB6a4E9406DA3a8"}