creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@solidstate/contracts/access/access_control/AccessControlInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { EnumerableSet } from '../../data/EnumerableSet.sol';\nimport { AddressUtils } from '../../utils/AddressUtils.sol';\nimport { UintUtils } from '../../utils/UintUtils.sol';\nimport { IAccessControlInternal } from './IAccessControlInternal.sol';\nimport { AccessControlStorage } from './AccessControlStorage.sol';\n\n/**\n * @title Role-based access control system\n * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license)\n */\nabstract contract AccessControlInternal is IAccessControlInternal {\n    using AddressUtils for address;\n    using EnumerableSet for EnumerableSet.AddressSet;\n    using UintUtils for uint256;\n\n    modifier onlyRole(bytes32 role) {\n        _checkRole(role);\n        _;\n    }\n\n    /*\n     * @notice query whether role is assigned to account\n     * @param role role to query\n     * @param account account to query\n     * @return whether role is assigned to account\n     */\n    function _hasRole(\n        bytes32 role,\n        address account\n    ) internal view virtual returns (bool) {\n        return\n            AccessControlStorage.layout().roles[role].members.contains(account);\n    }\n\n    /**\n     * @notice revert if sender does not have given role\n     * @param role role to query\n     */\n    function _checkRole(bytes32 role) internal view virtual {\n        _checkRole(role, msg.sender);\n    }\n\n    /**\n     * @notice revert if given account does not have given role\n     * @param role role to query\n     * @param account to query\n     */\n    function _checkRole(bytes32 role, address account) internal view virtual {\n        if (!_hasRole(role, account)) {\n            revert(\n                string(\n                    abi.encodePacked(\n                        'AccessControl: account ',\n                        account.toString(),\n                        ' is missing role ',\n                        uint256(role).toHexString(32)\n                    )\n                )\n            );\n        }\n    }\n\n    /*\n     * @notice query admin role for given role\n     * @param role role to query\n     * @return admin role\n     */\n    function _getRoleAdmin(\n        bytes32 role\n    ) internal view virtual returns (bytes32) {\n        return AccessControlStorage.layout().roles[role].adminRole;\n    }\n\n    /**\n     * @notice set role as admin role\n     * @param role role to set\n     * @param adminRole admin role to set\n     */\n    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n        bytes32 previousAdminRole = _getRoleAdmin(role);\n        AccessControlStorage.layout().roles[role].adminRole = adminRole;\n        emit RoleAdminChanged(role, previousAdminRole, adminRole);\n    }\n\n    /*\n     * @notice assign role to given account\n     * @param role role to assign\n     * @param account recipient of role assignment\n     */\n    function _grantRole(bytes32 role, address account) internal virtual {\n        AccessControlStorage.layout().roles[role].members.add(account);\n        emit RoleGranted(role, account, msg.sender);\n    }\n\n    /*\n     * @notice unassign role from given account\n     * @param role role to unassign\n     * @parm account\n     */\n    function _revokeRole(bytes32 role, address account) internal virtual {\n        AccessControlStorage.layout().roles[role].members.remove(account);\n        emit RoleRevoked(role, account, msg.sender);\n    }\n\n    /**\n     * @notice relinquish role\n     * @param role role to relinquish\n     */\n    function _renounceRole(bytes32 role) internal virtual {\n        _revokeRole(role, msg.sender);\n    }\n\n    /**\n     * @notice query role for member at given index\n     * @param role role to query\n     * @param index index to query\n     */\n    function _getRoleMember(\n        bytes32 role,\n        uint256 index\n    ) internal view virtual returns (address) {\n        return AccessControlStorage.layout().roles[role].members.at(index);\n    }\n\n    /**\n     * @notice query role for member count\n     * @param role role to query\n     */\n    function _getRoleMemberCount(\n        bytes32 role\n    ) internal view virtual returns (uint256) {\n        return AccessControlStorage.layout().roles[role].members.length();\n    }\n}\n"
      },
      "@solidstate/contracts/access/access_control/AccessControlStorage.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { EnumerableSet } from '../../data/EnumerableSet.sol';\n\nlibrary AccessControlStorage {\n    struct RoleData {\n        EnumerableSet.AddressSet members;\n        bytes32 adminRole;\n    }\n\n    struct Layout {\n        mapping(bytes32 => RoleData) roles;\n    }\n\n    bytes32 internal constant DEFAULT_ADMIN_ROLE = 0x00;\n\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('solidstate.contracts.storage.AccessControl');\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/access/access_control/IAccessControlInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @title Partial AccessControl interface needed by internal functions\n */\ninterface IAccessControlInternal {\n    event RoleAdminChanged(\n        bytes32 indexed role,\n        bytes32 indexed previousAdminRole,\n        bytes32 indexed newAdminRole\n    );\n\n    event RoleGranted(\n        bytes32 indexed role,\n        address indexed account,\n        address indexed sender\n    );\n\n    event RoleRevoked(\n        bytes32 indexed role,\n        address indexed account,\n        address indexed sender\n    );\n}\n"
      },
      "@solidstate/contracts/data/EnumerableMap.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\n/**\n * @title Map implementation with enumeration functions\n * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license)\n */\nlibrary EnumerableMap {\n    error EnumerableMap__IndexOutOfBounds();\n    error EnumerableMap__NonExistentKey();\n\n    struct MapEntry {\n        bytes32 _key;\n        bytes32 _value;\n    }\n\n    struct Map {\n        MapEntry[] _entries;\n        // 1-indexed to allow 0 to signify nonexistence\n        mapping(bytes32 => uint256) _indexes;\n    }\n\n    struct AddressToAddressMap {\n        Map _inner;\n    }\n\n    struct UintToAddressMap {\n        Map _inner;\n    }\n\n    function at(\n        AddressToAddressMap storage map,\n        uint256 index\n    ) internal view returns (address, address) {\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\n\n        return (\n            address(uint160(uint256(key))),\n            address(uint160(uint256(value)))\n        );\n    }\n\n    function at(\n        UintToAddressMap storage map,\n        uint256 index\n    ) internal view returns (uint256, address) {\n        (bytes32 key, bytes32 value) = _at(map._inner, index);\n        return (uint256(key), address(uint160(uint256(value))));\n    }\n\n    function contains(\n        AddressToAddressMap storage map,\n        address key\n    ) internal view returns (bool) {\n        return _contains(map._inner, bytes32(uint256(uint160(key))));\n    }\n\n    function contains(\n        UintToAddressMap storage map,\n        uint256 key\n    ) internal view returns (bool) {\n        return _contains(map._inner, bytes32(key));\n    }\n\n    function length(\n        AddressToAddressMap storage map\n    ) internal view returns (uint256) {\n        return _length(map._inner);\n    }\n\n    function length(\n        UintToAddressMap storage map\n    ) internal view returns (uint256) {\n        return _length(map._inner);\n    }\n\n    function get(\n        AddressToAddressMap storage map,\n        address key\n    ) internal view returns (address) {\n        return\n            address(\n                uint160(\n                    uint256(_get(map._inner, bytes32(uint256(uint160(key)))))\n                )\n            );\n    }\n\n    function get(\n        UintToAddressMap storage map,\n        uint256 key\n    ) internal view returns (address) {\n        return address(uint160(uint256(_get(map._inner, bytes32(key)))));\n    }\n\n    function set(\n        AddressToAddressMap storage map,\n        address key,\n        address value\n    ) internal returns (bool) {\n        return\n            _set(\n                map._inner,\n                bytes32(uint256(uint160(key))),\n                bytes32(uint256(uint160(value)))\n            );\n    }\n\n    function set(\n        UintToAddressMap storage map,\n        uint256 key,\n        address value\n    ) internal returns (bool) {\n        return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));\n    }\n\n    function remove(\n        AddressToAddressMap storage map,\n        address key\n    ) internal returns (bool) {\n        return _remove(map._inner, bytes32(uint256(uint160(key))));\n    }\n\n    function remove(\n        UintToAddressMap storage map,\n        uint256 key\n    ) internal returns (bool) {\n        return _remove(map._inner, bytes32(key));\n    }\n\n    function toArray(\n        AddressToAddressMap storage map\n    )\n        internal\n        view\n        returns (address[] memory keysOut, address[] memory valuesOut)\n    {\n        uint256 len = map._inner._entries.length;\n\n        keysOut = new address[](len);\n        valuesOut = new address[](len);\n\n        unchecked {\n            for (uint256 i; i < len; ++i) {\n                keysOut[i] = address(\n                    uint160(uint256(map._inner._entries[i]._key))\n                );\n                valuesOut[i] = address(\n                    uint160(uint256(map._inner._entries[i]._value))\n                );\n            }\n        }\n    }\n\n    function toArray(\n        UintToAddressMap storage map\n    )\n        internal\n        view\n        returns (uint256[] memory keysOut, address[] memory valuesOut)\n    {\n        uint256 len = map._inner._entries.length;\n\n        keysOut = new uint256[](len);\n        valuesOut = new address[](len);\n\n        unchecked {\n            for (uint256 i; i < len; ++i) {\n                keysOut[i] = uint256(map._inner._entries[i]._key);\n                valuesOut[i] = address(\n                    uint160(uint256(map._inner._entries[i]._value))\n                );\n            }\n        }\n    }\n\n    function keys(\n        AddressToAddressMap storage map\n    ) internal view returns (address[] memory keysOut) {\n        uint256 len = map._inner._entries.length;\n\n        keysOut = new address[](len);\n\n        unchecked {\n            for (uint256 i; i < len; ++i) {\n                keysOut[i] = address(\n                    uint160(uint256(map._inner._entries[i]._key))\n                );\n            }\n        }\n    }\n\n    function keys(\n        UintToAddressMap storage map\n    ) internal view returns (uint256[] memory keysOut) {\n        uint256 len = map._inner._entries.length;\n\n        keysOut = new uint256[](len);\n\n        unchecked {\n            for (uint256 i; i < len; ++i) {\n                keysOut[i] = uint256(map._inner._entries[i]._key);\n            }\n        }\n    }\n\n    function values(\n        AddressToAddressMap storage map\n    ) internal view returns (address[] memory valuesOut) {\n        uint256 len = map._inner._entries.length;\n\n        valuesOut = new address[](len);\n\n        unchecked {\n            for (uint256 i; i < len; ++i) {\n                valuesOut[i] = address(\n                    uint160(uint256(map._inner._entries[i]._value))\n                );\n            }\n        }\n    }\n\n    function values(\n        UintToAddressMap storage map\n    ) internal view returns (address[] memory valuesOut) {\n        uint256 len = map._inner._entries.length;\n\n        valuesOut = new address[](len);\n\n        unchecked {\n            for (uint256 i; i < len; ++i) {\n                valuesOut[i] = address(\n                    uint160(uint256(map._inner._entries[i]._value))\n                );\n            }\n        }\n    }\n\n    function _at(\n        Map storage map,\n        uint256 index\n    ) private view returns (bytes32, bytes32) {\n        if (index >= map._entries.length)\n            revert EnumerableMap__IndexOutOfBounds();\n\n        MapEntry storage entry = map._entries[index];\n        return (entry._key, entry._value);\n    }\n\n    function _contains(\n        Map storage map,\n        bytes32 key\n    ) private view returns (bool) {\n        return map._indexes[key] != 0;\n    }\n\n    function _length(Map storage map) private view returns (uint256) {\n        return map._entries.length;\n    }\n\n    function _get(Map storage map, bytes32 key) private view returns (bytes32) {\n        uint256 keyIndex = map._indexes[key];\n        if (keyIndex == 0) revert EnumerableMap__NonExistentKey();\n        unchecked {\n            return map._entries[keyIndex - 1]._value;\n        }\n    }\n\n    function _set(\n        Map storage map,\n        bytes32 key,\n        bytes32 value\n    ) private returns (bool) {\n        uint256 keyIndex = map._indexes[key];\n\n        if (keyIndex == 0) {\n            map._entries.push(MapEntry({ _key: key, _value: value }));\n            map._indexes[key] = map._entries.length;\n            return true;\n        } else {\n            unchecked {\n                map._entries[keyIndex - 1]._value = value;\n            }\n            return false;\n        }\n    }\n\n    function _remove(Map storage map, bytes32 key) private returns (bool) {\n        uint256 keyIndex = map._indexes[key];\n\n        if (keyIndex != 0) {\n            unchecked {\n                MapEntry storage last = map._entries[map._entries.length - 1];\n\n                // move last entry to now-vacant index\n                map._entries[keyIndex - 1] = last;\n                map._indexes[last._key] = keyIndex;\n            }\n\n            // clear last index\n            map._entries.pop();\n            delete map._indexes[key];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/data/EnumerableSet.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\n/**\n * @title Set implementation with enumeration functions\n * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license)\n */\nlibrary EnumerableSet {\n    error EnumerableSet__IndexOutOfBounds();\n\n    struct Set {\n        bytes32[] _values;\n        // 1-indexed to allow 0 to signify nonexistence\n        mapping(bytes32 => uint256) _indexes;\n    }\n\n    struct Bytes32Set {\n        Set _inner;\n    }\n\n    struct AddressSet {\n        Set _inner;\n    }\n\n    struct UintSet {\n        Set _inner;\n    }\n\n    function at(\n        Bytes32Set storage set,\n        uint256 index\n    ) internal view returns (bytes32) {\n        return _at(set._inner, index);\n    }\n\n    function at(\n        AddressSet storage set,\n        uint256 index\n    ) internal view returns (address) {\n        return address(uint160(uint256(_at(set._inner, index))));\n    }\n\n    function at(\n        UintSet storage set,\n        uint256 index\n    ) internal view returns (uint256) {\n        return uint256(_at(set._inner, index));\n    }\n\n    function contains(\n        Bytes32Set storage set,\n        bytes32 value\n    ) internal view returns (bool) {\n        return _contains(set._inner, value);\n    }\n\n    function contains(\n        AddressSet storage set,\n        address value\n    ) internal view returns (bool) {\n        return _contains(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    function contains(\n        UintSet storage set,\n        uint256 value\n    ) internal view returns (bool) {\n        return _contains(set._inner, bytes32(value));\n    }\n\n    function indexOf(\n        Bytes32Set storage set,\n        bytes32 value\n    ) internal view returns (uint256) {\n        return _indexOf(set._inner, value);\n    }\n\n    function indexOf(\n        AddressSet storage set,\n        address value\n    ) internal view returns (uint256) {\n        return _indexOf(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    function indexOf(\n        UintSet storage set,\n        uint256 value\n    ) internal view returns (uint256) {\n        return _indexOf(set._inner, bytes32(value));\n    }\n\n    function length(Bytes32Set storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    function length(AddressSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    function length(UintSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    function add(\n        Bytes32Set storage set,\n        bytes32 value\n    ) internal returns (bool) {\n        return _add(set._inner, value);\n    }\n\n    function add(\n        AddressSet storage set,\n        address value\n    ) internal returns (bool) {\n        return _add(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    function add(UintSet storage set, uint256 value) internal returns (bool) {\n        return _add(set._inner, bytes32(value));\n    }\n\n    function remove(\n        Bytes32Set storage set,\n        bytes32 value\n    ) internal returns (bool) {\n        return _remove(set._inner, value);\n    }\n\n    function remove(\n        AddressSet storage set,\n        address value\n    ) internal returns (bool) {\n        return _remove(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    function remove(\n        UintSet storage set,\n        uint256 value\n    ) internal returns (bool) {\n        return _remove(set._inner, bytes32(value));\n    }\n\n    function toArray(\n        Bytes32Set storage set\n    ) internal view returns (bytes32[] memory) {\n        return set._inner._values;\n    }\n\n    function toArray(\n        AddressSet storage set\n    ) internal view returns (address[] memory) {\n        bytes32[] storage values = set._inner._values;\n        address[] storage array;\n\n        assembly {\n            array.slot := values.slot\n        }\n\n        return array;\n    }\n\n    function toArray(\n        UintSet storage set\n    ) internal view returns (uint256[] memory) {\n        bytes32[] storage values = set._inner._values;\n        uint256[] storage array;\n\n        assembly {\n            array.slot := values.slot\n        }\n\n        return array;\n    }\n\n    function _at(\n        Set storage set,\n        uint256 index\n    ) private view returns (bytes32) {\n        if (index >= set._values.length)\n            revert EnumerableSet__IndexOutOfBounds();\n        return set._values[index];\n    }\n\n    function _contains(\n        Set storage set,\n        bytes32 value\n    ) private view returns (bool) {\n        return set._indexes[value] != 0;\n    }\n\n    function _indexOf(\n        Set storage set,\n        bytes32 value\n    ) private view returns (uint256) {\n        unchecked {\n            return set._indexes[value] - 1;\n        }\n    }\n\n    function _length(Set storage set) private view returns (uint256) {\n        return set._values.length;\n    }\n\n    function _add(\n        Set storage set,\n        bytes32 value\n    ) private returns (bool status) {\n        if (!_contains(set, value)) {\n            set._values.push(value);\n            set._indexes[value] = set._values.length;\n            status = true;\n        }\n    }\n\n    function _remove(\n        Set storage set,\n        bytes32 value\n    ) private returns (bool status) {\n        uint256 valueIndex = set._indexes[value];\n\n        if (valueIndex != 0) {\n            unchecked {\n                bytes32 last = set._values[set._values.length - 1];\n\n                // move last value to now-vacant index\n\n                set._values[valueIndex - 1] = last;\n                set._indexes[last] = valueIndex;\n            }\n            // clear last index\n\n            set._values.pop();\n            delete set._indexes[value];\n\n            status = true;\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/interfaces/IERC721Internal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\n/**\n * @title Partial ERC721 interface needed by internal functions\n */\ninterface IERC721Internal {\n    event Transfer(\n        address indexed from,\n        address indexed to,\n        uint256 indexed tokenId\n    );\n\n    event Approval(\n        address indexed owner,\n        address indexed operator,\n        uint256 indexed tokenId\n    );\n\n    event ApprovalForAll(\n        address indexed owner,\n        address indexed operator,\n        bool approved\n    );\n}\n"
      },
      "@solidstate/contracts/interfaces/IERC721Receiver.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\ninterface IERC721Receiver {\n    function onERC721Received(\n        address operator,\n        address from,\n        uint256 tokenId,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n"
      },
      "@solidstate/contracts/security/partially_pausable/IPartiallyPausableInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\ninterface IPartiallyPausableInternal {\n    error PartiallyPausable__PartiallyPaused();\n    error PartiallyPausable__NotPartiallyPaused();\n\n    event PartiallyPaused(address account, bytes32 key);\n    event PartiallyUnpaused(address account, bytes32 key);\n}\n"
      },
      "@solidstate/contracts/security/partially_pausable/PartiallyPausableInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IPartiallyPausableInternal } from './IPartiallyPausableInternal.sol';\nimport { PartiallyPausableStorage } from './PartiallyPausableStorage.sol';\n\n/**\n * @title Internal functions for PartiallyPausable security control module.\n */\nabstract contract PartiallyPausableInternal is IPartiallyPausableInternal {\n    modifier whenNotPartiallyPaused(bytes32 key) {\n        if (_partiallyPaused(key)) revert PartiallyPausable__PartiallyPaused();\n        _;\n    }\n\n    modifier whenPartiallyPaused(bytes32 key) {\n        if (!_partiallyPaused(key))\n            revert PartiallyPausable__NotPartiallyPaused();\n        _;\n    }\n\n    /**\n     * @notice query whether contract is paused in the scope of the given key\n     * @return status whether contract is paused in the scope of the given key\n     */\n    function _partiallyPaused(\n        bytes32 key\n    ) internal view virtual returns (bool status) {\n        status = PartiallyPausableStorage.layout().partiallyPaused[key];\n    }\n\n    /**\n     * @notice pause contract in the scope of given key\n     * @param key key whose scope to pause\n     */\n    function _partiallyPause(\n        bytes32 key\n    ) internal virtual whenNotPartiallyPaused(key) {\n        PartiallyPausableStorage.layout().partiallyPaused[key] = true;\n        emit PartiallyPaused(msg.sender, key);\n    }\n\n    /**\n     * @notice unpause contract in the scope of given key\n     * @param key key whose scope to unpause\n     */\n    function _partiallyUnpause(\n        bytes32 key\n    ) internal virtual whenPartiallyPaused(key) {\n        delete PartiallyPausableStorage.layout().partiallyPaused[key];\n        emit PartiallyUnpaused(msg.sender, key);\n    }\n}\n"
      },
      "@solidstate/contracts/security/partially_pausable/PartiallyPausableStorage.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nlibrary PartiallyPausableStorage {\n    struct Layout {\n        mapping(bytes32 => bool) partiallyPaused;\n    }\n\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('solidstate.contracts.storage.PartiallyPausable');\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/token/ERC721/base/ERC721BaseInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC721Receiver } from '../../../interfaces/IERC721Receiver.sol';\nimport { EnumerableMap } from '../../../data/EnumerableMap.sol';\nimport { EnumerableSet } from '../../../data/EnumerableSet.sol';\nimport { AddressUtils } from '../../../utils/AddressUtils.sol';\nimport { IERC721BaseInternal } from './IERC721BaseInternal.sol';\nimport { ERC721BaseStorage } from './ERC721BaseStorage.sol';\n\n/**\n * @title Base ERC721 internal functions\n */\nabstract contract ERC721BaseInternal is IERC721BaseInternal {\n    using AddressUtils for address;\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\n    using EnumerableSet for EnumerableSet.UintSet;\n\n    function _balanceOf(\n        address account\n    ) internal view virtual returns (uint256) {\n        if (account == address(0)) revert ERC721Base__BalanceQueryZeroAddress();\n        return ERC721BaseStorage.layout().holderTokens[account].length();\n    }\n\n    function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\n        address owner = ERC721BaseStorage.layout().tokenOwners.get(tokenId);\n        if (owner == address(0)) revert ERC721Base__InvalidOwner();\n        return owner;\n    }\n\n    function _exists(uint256 tokenId) internal view virtual returns (bool) {\n        return ERC721BaseStorage.layout().tokenOwners.contains(tokenId);\n    }\n\n    function _getApproved(\n        uint256 tokenId\n    ) internal view virtual returns (address) {\n        if (!_exists(tokenId)) revert ERC721Base__NonExistentToken();\n\n        return ERC721BaseStorage.layout().tokenApprovals[tokenId];\n    }\n\n    function _isApprovedForAll(\n        address account,\n        address operator\n    ) internal view virtual returns (bool) {\n        return ERC721BaseStorage.layout().operatorApprovals[account][operator];\n    }\n\n    function _isApprovedOrOwner(\n        address spender,\n        uint256 tokenId\n    ) internal view virtual returns (bool) {\n        if (!_exists(tokenId)) revert ERC721Base__NonExistentToken();\n\n        address owner = _ownerOf(tokenId);\n\n        return (spender == owner ||\n            _getApproved(tokenId) == spender ||\n            _isApprovedForAll(owner, spender));\n    }\n\n    function _mint(address to, uint256 tokenId) internal virtual {\n        if (to == address(0)) revert ERC721Base__MintToZeroAddress();\n        if (_exists(tokenId)) revert ERC721Base__TokenAlreadyMinted();\n\n        _beforeTokenTransfer(address(0), to, tokenId);\n\n        ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout();\n\n        l.holderTokens[to].add(tokenId);\n        l.tokenOwners.set(tokenId, to);\n\n        emit Transfer(address(0), to, tokenId);\n    }\n\n    function _safeMint(address to, uint256 tokenId) internal virtual {\n        _safeMint(to, tokenId, '');\n    }\n\n    function _safeMint(\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    ) internal virtual {\n        _mint(to, tokenId);\n        if (!_checkOnERC721Received(address(0), to, tokenId, data))\n            revert ERC721Base__ERC721ReceiverNotImplemented();\n    }\n\n    function _burn(uint256 tokenId) internal virtual {\n        address owner = _ownerOf(tokenId);\n\n        _beforeTokenTransfer(owner, address(0), tokenId);\n\n        ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout();\n\n        l.holderTokens[owner].remove(tokenId);\n        l.tokenOwners.remove(tokenId);\n\n        l.tokenApprovals[tokenId] = address(0);\n\n        emit Approval(owner, address(0), tokenId);\n        emit Transfer(owner, address(0), tokenId);\n    }\n\n    function _transfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual {\n        address owner = _ownerOf(tokenId);\n\n        if (owner != from) revert ERC721Base__NotTokenOwner();\n        if (to == address(0)) revert ERC721Base__TransferToZeroAddress();\n\n        _beforeTokenTransfer(from, to, tokenId);\n\n        ERC721BaseStorage.Layout storage l = ERC721BaseStorage.layout();\n\n        l.holderTokens[from].remove(tokenId);\n        l.holderTokens[to].add(tokenId);\n        l.tokenOwners.set(tokenId, to);\n        l.tokenApprovals[tokenId] = address(0);\n\n        emit Approval(owner, address(0), tokenId);\n        emit Transfer(from, to, tokenId);\n    }\n\n    function _transferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual {\n        _handleTransferMessageValue(from, to, tokenId, msg.value);\n        if (!_isApprovedOrOwner(msg.sender, tokenId))\n            revert ERC721Base__NotOwnerOrApproved();\n        _transfer(from, to, tokenId);\n    }\n\n    function _safeTransfer(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    ) internal virtual {\n        _transfer(from, to, tokenId);\n        if (!_checkOnERC721Received(from, to, tokenId, data))\n            revert ERC721Base__ERC721ReceiverNotImplemented();\n    }\n\n    function _safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual {\n        _safeTransferFrom(from, to, tokenId, '');\n    }\n\n    function _safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    ) internal virtual {\n        _handleTransferMessageValue(from, to, tokenId, msg.value);\n        if (!_isApprovedOrOwner(msg.sender, tokenId))\n            revert ERC721Base__NotOwnerOrApproved();\n        _safeTransfer(from, to, tokenId, data);\n    }\n\n    function _approve(address operator, uint256 tokenId) internal virtual {\n        _handleApproveMessageValue(operator, tokenId, msg.value);\n\n        address owner = _ownerOf(tokenId);\n\n        if (operator == owner) revert ERC721Base__SelfApproval();\n        if (msg.sender != owner && !_isApprovedForAll(owner, msg.sender))\n            revert ERC721Base__NotOwnerOrApproved();\n\n        ERC721BaseStorage.layout().tokenApprovals[tokenId] = operator;\n        emit Approval(owner, operator, tokenId);\n    }\n\n    function _setApprovalForAll(\n        address operator,\n        bool status\n    ) internal virtual {\n        if (operator == msg.sender) revert ERC721Base__SelfApproval();\n        ERC721BaseStorage.layout().operatorApprovals[msg.sender][\n            operator\n        ] = status;\n        emit ApprovalForAll(msg.sender, operator, status);\n    }\n\n    function _checkOnERC721Received(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes memory data\n    ) internal virtual returns (bool) {\n        if (!to.isContract()) {\n            return true;\n        }\n\n        bytes memory returnData = to.functionCall(\n            abi.encodeWithSelector(\n                IERC721Receiver(to).onERC721Received.selector,\n                msg.sender,\n                from,\n                tokenId,\n                data\n            ),\n            'ERC721: transfer to non ERC721Receiver implementer'\n        );\n\n        bytes4 returnValue = abi.decode(returnData, (bytes4));\n        return returnValue == type(IERC721Receiver).interfaceId;\n    }\n\n    /**\n     * @notice ERC721 hook, called before externally called approvals for processing of included message value\n     * @param operator beneficiary of approval\n     * @param tokenId id of transferred token\n     * @param value message value\n     */\n    function _handleApproveMessageValue(\n        address operator,\n        uint256 tokenId,\n        uint256 value\n    ) internal virtual {}\n\n    /**\n     * @notice ERC721 hook, called before externally called transfers for processing of included message value\n     * @param from sender of token\n     * @param to receiver of token\n     * @param tokenId id of transferred token\n     * @param value message value\n     */\n    function _handleTransferMessageValue(\n        address from,\n        address to,\n        uint256 tokenId,\n        uint256 value\n    ) internal virtual {}\n\n    /**\n     * @notice ERC721 hook, called before all transfers including mint and burn\n     * @dev function should be overridden and new implementation must call super\n     * @param from sender of token\n     * @param to receiver of token\n     * @param tokenId id of transferred token\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 tokenId\n    ) internal virtual {}\n}\n"
      },
      "@solidstate/contracts/token/ERC721/base/ERC721BaseStorage.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { EnumerableMap } from '../../../data/EnumerableMap.sol';\nimport { EnumerableSet } from '../../../data/EnumerableSet.sol';\n\nlibrary ERC721BaseStorage {\n    using EnumerableSet for EnumerableSet.UintSet;\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\n\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('solidstate.contracts.storage.ERC721Base');\n\n    struct Layout {\n        EnumerableMap.UintToAddressMap tokenOwners;\n        mapping(address => EnumerableSet.UintSet) holderTokens;\n        mapping(uint256 => address) tokenApprovals;\n        mapping(address => mapping(address => bool)) operatorApprovals;\n    }\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/token/ERC721/base/IERC721BaseInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC721Internal } from '../../../interfaces/IERC721Internal.sol';\n\n/**\n * @title ERC721 base interface\n */\ninterface IERC721BaseInternal is IERC721Internal {\n    error ERC721Base__NotOwnerOrApproved();\n    error ERC721Base__SelfApproval();\n    error ERC721Base__BalanceQueryZeroAddress();\n    error ERC721Base__ERC721ReceiverNotImplemented();\n    error ERC721Base__InvalidOwner();\n    error ERC721Base__MintToZeroAddress();\n    error ERC721Base__NonExistentToken();\n    error ERC721Base__NotTokenOwner();\n    error ERC721Base__TokenAlreadyMinted();\n    error ERC721Base__TransferToZeroAddress();\n}\n"
      },
      "@solidstate/contracts/token/ERC721/metadata/ERC721MetadataStorage.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nlibrary ERC721MetadataStorage {\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('solidstate.contracts.storage.ERC721Metadata');\n\n    struct Layout {\n        string name;\n        string symbol;\n        string baseURI;\n        mapping(uint256 => string) tokenURIs;\n    }\n\n    function layout() internal pure returns (Layout storage l) {\n        bytes32 slot = STORAGE_SLOT;\n        assembly {\n            l.slot := slot\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/utils/AddressUtils.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { UintUtils } from './UintUtils.sol';\n\nlibrary AddressUtils {\n    using UintUtils for uint256;\n\n    error AddressUtils__InsufficientBalance();\n    error AddressUtils__NotContract();\n    error AddressUtils__SendValueFailed();\n\n    function toString(address account) internal pure returns (string memory) {\n        return uint256(uint160(account)).toHexString(20);\n    }\n\n    function isContract(address account) internal view returns (bool) {\n        uint256 size;\n        assembly {\n            size := extcodesize(account)\n        }\n        return size > 0;\n    }\n\n    function sendValue(address payable account, uint256 amount) internal {\n        (bool success, ) = account.call{ value: amount }('');\n        if (!success) revert AddressUtils__SendValueFailed();\n    }\n\n    function functionCall(\n        address target,\n        bytes memory data\n    ) internal returns (bytes memory) {\n        return\n            functionCall(target, data, 'AddressUtils: failed low-level call');\n    }\n\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory error\n    ) internal returns (bytes memory) {\n        return _functionCallWithValue(target, data, 0, error);\n    }\n\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return\n            functionCallWithValue(\n                target,\n                data,\n                value,\n                'AddressUtils: failed low-level call with value'\n            );\n    }\n\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory error\n    ) internal returns (bytes memory) {\n        if (value > address(this).balance)\n            revert AddressUtils__InsufficientBalance();\n        return _functionCallWithValue(target, data, value, error);\n    }\n\n    /**\n     * @notice execute arbitrary external call with limited gas usage and amount of copied return data\n     * @dev derived from https://github.com/nomad-xyz/ExcessivelySafeCall (MIT License)\n     * @param target recipient of call\n     * @param gasAmount gas allowance for call\n     * @param value native token value to include in call\n     * @param maxCopy maximum number of bytes to copy from return data\n     * @param data encoded call data\n     * @return success whether call is successful\n     * @return returnData copied return data\n     */\n    function excessivelySafeCall(\n        address target,\n        uint256 gasAmount,\n        uint256 value,\n        uint16 maxCopy,\n        bytes memory data\n    ) internal returns (bool success, bytes memory returnData) {\n        returnData = new bytes(maxCopy);\n\n        assembly {\n            // execute external call via assembly to avoid automatic copying of return data\n            success := call(\n                gasAmount,\n                target,\n                value,\n                add(data, 0x20),\n                mload(data),\n                0,\n                0\n            )\n\n            // determine whether to limit amount of data to copy\n            let toCopy := returndatasize()\n\n            if gt(toCopy, maxCopy) {\n                toCopy := maxCopy\n            }\n\n            // store the length of the copied bytes\n            mstore(returnData, toCopy)\n\n            // copy the bytes from returndata[0:toCopy]\n            returndatacopy(add(returnData, 0x20), 0, toCopy)\n        }\n    }\n\n    function _functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory error\n    ) private returns (bytes memory) {\n        if (!isContract(target)) revert AddressUtils__NotContract();\n\n        (bool success, bytes memory returnData) = target.call{ value: value }(\n            data\n        );\n\n        if (success) {\n            return returnData;\n        } else if (returnData.length > 0) {\n            assembly {\n                let returnData_size := mload(returnData)\n                revert(add(32, returnData), returnData_size)\n            }\n        } else {\n            revert(error);\n        }\n    }\n}\n"
      },
      "@solidstate/contracts/utils/UintUtils.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\n/**\n * @title utility functions for uint256 operations\n * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts/ (MIT license)\n */\nlibrary UintUtils {\n    error UintUtils__InsufficientHexLength();\n\n    bytes16 private constant HEX_SYMBOLS = '0123456789abcdef';\n\n    function add(uint256 a, int256 b) internal pure returns (uint256) {\n        return b < 0 ? sub(a, -b) : a + uint256(b);\n    }\n\n    function sub(uint256 a, int256 b) internal pure returns (uint256) {\n        return b < 0 ? add(a, -b) : a - uint256(b);\n    }\n\n    function toString(uint256 value) internal pure returns (string memory) {\n        if (value == 0) {\n            return '0';\n        }\n\n        uint256 temp = value;\n        uint256 digits;\n\n        while (temp != 0) {\n            digits++;\n            temp /= 10;\n        }\n\n        bytes memory buffer = new bytes(digits);\n\n        while (value != 0) {\n            digits -= 1;\n            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n            value /= 10;\n        }\n\n        return string(buffer);\n    }\n\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        if (value == 0) {\n            return '0x00';\n        }\n\n        uint256 length = 0;\n\n        for (uint256 temp = value; temp != 0; temp >>= 8) {\n            unchecked {\n                length++;\n            }\n        }\n\n        return toHexString(value, length);\n    }\n\n    function toHexString(\n        uint256 value,\n        uint256 length\n    ) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = '0';\n        buffer[1] = 'x';\n\n        unchecked {\n            for (uint256 i = 2 * length + 1; i > 1; --i) {\n                buffer[i] = HEX_SYMBOLS[value & 0xf];\n                value >>= 4;\n            }\n        }\n\n        if (value != 0) revert UintUtils__InsufficientHexLength();\n\n        return string(buffer);\n    }\n}\n"
      },
      "contracts/facets/ReadableFacet.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.9;\n\n// Import necessary contract and library\nimport { AccessControlInternal } from \"@solidstate/contracts/access/access_control/AccessControlInternal.sol\";\nimport { ERC721MetadataStorage } from \"@solidstate/contracts/token/ERC721/metadata/ERC721MetadataStorage.sol\";\nimport { ERC721BaseInternal } from \"@solidstate/contracts/token/ERC721/base/ERC721BaseInternal.sol\";\nimport { PartiallyPausableInternal } from \"@solidstate/contracts/security/partially_pausable/PartiallyPausableInternal.sol\";\nimport \"../libraries/LibSilksHorseDiamond.sol\";\n\n/**\n * @title ReadableFacet\n * @dev A Solidity smart contract representing the Readable Facet of the SilksHorseDiamond contract.\n * This facet provides read-only functions to query information about seasons, payout tiers, horses, and pausing status.\n */\ncontract ReadableFacet is\n    AccessControlInternal,\n    PartiallyPausableInternal,\n    ERC721BaseInternal\n{\n    /**\n     * @dev Get information about a specific season.\n     * @param _seasonId The ID of the season to query.\n     * @return seasonId The ID of the season.\n     * @return description The description of the season.\n     * @return paused A boolean indicating whether the season is paused.\n     * @return valid A boolean indicating whether the season is valid.\n     */\n    function seasonInfo(\n        uint256 _seasonId\n    )\n    public\n    view\n    returns (\n        uint256 seasonId,\n        string memory description,\n        bool paused,\n        bool valid\n    ){\n        SeasonInfo storage ci = LibSilksHorseDiamond.layout().seasonInfos[_seasonId];\n        return (\n        ci.seasonId,\n        ci.description,\n        ci.paused,\n        ci.valid\n        );\n    }\n    \n    /**\n    * @dev Get information about the season associated with a specific horse token.\n    * @param _tokenId The ID of the horse token to query.\n    * @return tokenId The ID of the horse token.\n    * @return seasonId The ID of the associated season.\n    * @return description The description of the associated season.\n    * @return paused A boolean indicating whether the associated season is paused.\n    * @return valid A boolean indicating whether the associated season is valid.\n    */\n    function horseSeasonInfo(\n        uint256 _tokenId\n    )\n    public\n    view\n    returns (\n        uint256 tokenId,\n        uint256 seasonId,\n        string memory description,\n        bool paused,\n        bool valid\n    ){\n        LibSilksHorseDiamond.Layout storage lsh = LibSilksHorseDiamond.layout();\n        uint256 seasonId = lsh.horseSeasonInfo[_tokenId];\n        SeasonInfo storage hsi = lsh.seasonInfos[seasonId];\n        SeasonInfo storage defaultSeasonInfo = lsh.seasonInfos[lsh.defaultSeasonId];\n        SeasonInfo storage si = hsi.valid ? hsi : defaultSeasonInfo;\n        return (\n            _tokenId,\n            si.seasonId,\n            si.description,\n            si.paused,\n            si.valid\n        );\n    }\n    \n    /**\n     * @dev Get information about a specific payout tier.\n     * @param _payoutTier The ID of the payout tier to query.\n     * @return tierId The ID of the payout tier.\n     * @return description The description of the payout tier.\n     * @return price The price of the payout tier.\n     * @return maxPerTx The maximum quantity allowed per transaction for the payout tier.\n     * @return payoutPct The payout percentage for the payout tier.\n     * @return maxSupply The maximum number of horse for this tier.\n     * @return paused A boolean indicating whether the payout tier is paused.\n     * @return valid A boolean indicating whether the payout tier is valid.\n     */\n    function payoutTier(\n        uint256 _payoutTier\n    )\n    public\n    view\n    returns (\n        uint256 tierId,\n        string memory description,\n        uint256 price,\n        uint256 maxPerTx,\n        uint256 payoutPct,\n        uint256 maxSupply,\n        bool paused,\n        bool valid\n    ){\n        PayoutTier storage pt = LibSilksHorseDiamond.layout().payoutTiers[_payoutTier];\n        return (\n        pt.tierId,\n        pt.description,\n        pt.price,\n        pt.maxPerTx,\n        pt.payoutPct,\n        pt.maxSupply,\n        pt.paused,\n        pt.valid\n        );\n    }\n    \n    /**\n     * @dev Get information about the payout tier associated with a specific horse token.\n     * @param _tokenId The ID of the horse token to query.\n     * @return tokenId The ID of the horse token.\n     * @return tierId The ID of the associated payout tier.\n     * @return description The description of the payout tier.\n     * @return price The price of the payout tier.\n     * @return maxPerTx The maximum quantity allowed per transaction for the payout tier.\n     * @return payoutPct The payout percentage for the payout tier.\n     * @return maxSupply The maximum number of horse for this tier.\n     * @return paused A boolean indicating whether the payout tier is paused.\n     * @return valid A boolean indicating whether the payout tier is valid.\n     */\n    function horsePayoutTier(\n        uint256 _tokenId\n    )\n    public\n    view\n    returns (\n        uint256 tokenId,\n        uint256 tierId,\n        string memory description,\n        uint256 price,\n        uint256 maxPerTx,\n        uint256 payoutPct,\n        uint256 maxSupply,\n        bool paused,\n        bool valid\n    ){\n        if (_ownerOf(_tokenId) == address(0)){\n            revert(\"INV_TOKEN_ID\");\n        }\n        LibSilksHorseDiamond.Layout storage lsh = LibSilksHorseDiamond.layout();\n        uint256 payoutTierId = lsh.horsePayoutTier[_tokenId];\n        PayoutTier storage hpt = lsh.payoutTiers[payoutTierId];\n        PayoutTier storage defaultPayoutTier = lsh.payoutTiers[lsh.defaultPayoutTierId];\n        PayoutTier storage pt = hpt.valid ? hpt : defaultPayoutTier;\n        return (\n        _tokenId,\n        pt.tierId,\n        pt.description,\n        pt.price,\n        pt.maxPerTx,\n        pt.payoutPct,\n        pt.maxSupply,\n        pt.paused,\n        pt.valid\n        );\n    }\n    \n    /**\n    * @dev Get the base URI for metadata of NFTs.\n    * @return uri The base URI used for constructing the metadata URI of NFTs.\n    */\n    function baseURI()\n    public\n    view\n    returns (\n        string memory uri\n    )\n    {\n        return ERC721MetadataStorage.layout().baseURI;\n    }\n    \n    /**\n    * @dev Get the maximum number of horses allowed per wallet.\n    * @return maxHorsesPerWallet The maximum number of horses allowed per wallet.\n    */\n    function maxHorsesPerWallet()\n    public\n    view\n    returns (\n        uint256 maxHorsesPerWallet\n    )\n    {\n        // Retrieve the maximum number of horses per wallet from the contract's storage\n        return LibSilksHorseDiamond.layout().maxHorsesPerWallet;\n    }\n    \n    /**\n     * @dev Check if horse purchases are paused.\n     * @return paused A boolean indicating whether horse purchases are paused.\n     */\n    function horsePurchasesPaused()\n    public\n    view\n    returns (\n        bool paused\n    ){\n        return _partiallyPaused(HORSE_PURCHASING_PAUSED);\n    }\n\n    /**\n    * @dev Checks if an external address is allowed to perform external minting of horses.\n    * @param _externalAddress The external address to check.\n    * @return allowed A boolean indicating whether the address is allowed for external minting.\n    */\n    function isAllowedExternalMintAddress(\n        address _externalAddress\n    ) public\n    view\n    returns (\n        bool allowed\n    )\n    {\n        // Retrieve the allowed status of the external address from the contract storage\n        return LibSilksHorseDiamond.layout().allowedExternalMintAddresses[_externalAddress];\n    }\n    \n    /**\n     * @dev Check if an address has the CONTRACT_ADMIN_ROLE.\n     * @param _admin The address to check for the CONTRACT_ADMIN_ROLE.\n     * @return hasRole A boolean indicating whether the address has the CONTRACT_ADMIN_ROLE.\n     */\n    function hasContractAdminRole(\n        address _admin\n    )\n    public\n    view\n    returns (\n        bool hasRole\n    )\n    {\n        return _hasRole(CONTRACT_ADMIN_ROLE, _admin);\n    }\n    \n    /**\n     * @dev Check if an address has the MINT_ADMIN_ROLE.\n     * @param _admin The address to check for the MINT_ADMIN_ROLE.\n     * @return hasRole A boolean indicating whether the address has the MINT_ADMIN_ROLE.\n     */\n    function hasMintAdminRole(\n        address _admin\n    )\n    public\n    view\n    returns (\n        bool hasRole\n    )\n    {\n        return _hasRole(MINT_ADMIN_ROLE, _admin);\n    }\n    \n    /**\n     * @dev Get the next available token ID for minting horses.\n     * @return nextAvailableTokenId The next available token ID.\n     */\n    function nextAvailableTokenId()\n    public\n    view\n    returns (\n        uint256 nextAvailableTokenId\n    )\n    {\n        // Retrieve the next available token ID from the contract's storage.\n        return LibSilksHorseDiamond.layout().nextAvailableTokenId;\n    }\n    \n    /**\n     * @dev Get the value used when a horse to payout tier mapping does not exist.\n     * @return defaultPayoutTierId The default payout tier for horses.\n     */\n    function defaultPayoutTierId()\n    public\n    view\n    returns (\n        uint256 defaultPayoutTierId\n    )\n    {\n        return LibSilksHorseDiamond.layout().defaultPayoutTierId;\n    }\n    \n    /**\n     * @dev Get the value used when a horse to season mapping does not exist.\n     * @return defaultSeasonId The default season for horses.\n     */\n    function defaultSeasonId()\n    public\n    view\n    returns (\n        uint256 defaultSeasonId\n    )\n    {\n        return LibSilksHorseDiamond.layout().defaultSeasonId;\n    }\n}\n"
      },
      "contracts/libraries/LibSilksHorseDiamond.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.9;\n\nimport {EnumerableSet} from \"@solidstate/contracts/data/EnumerableSet.sol\";\n\nstruct SeasonInfo {\n    uint256 seasonId;\n    string description;\n    bool paused;\n    bool valid;\n}\n\nstruct PayoutTier {\n    uint256 tierId;\n    string description;\n    uint256 price;\n    uint256 maxPerTx;\n    uint256 payoutPct;\n    uint256 maxSupply;\n    bool paused;\n    bool valid;\n}\n\nenum MintMethod {\n    PURCHASE,\n    AIRDROP,\n    EXTERNAL_MINT\n}\n\nbytes32 constant CONTRACT_ADMIN_ROLE = keccak256(\"silks.contracts.roles.ContractAdminRole\");\nbytes32 constant MINT_ADMIN_ROLE = keccak256(\"silks.contracts.roles.MintAdminRole\");\n\nbytes32 constant HORSE_PURCHASING_PAUSED = keccak256('silks.contracts.paused.HorsePurchasing');\n\nerror InvalidAddress(address _address);\nerror InvalidSeason(uint256 _sent);\nerror InvalidPayoutTier(uint256 _sent);\nerror InvalidTokenId(uint256 _sent);\nerror InvalidIntValue(string _reason, uint256 _sent, uint256 _expected);\nerror InvalidStringValue(string _reason, string _sent, string _expected);\nerror InvalidExternalMintAddress(address _sender);\nerror MaxHorsesPerWalletExceeded(address _walletAddress);\nerror PayoutTierMaxSupplyExceeded(uint256 _payoutTier);\nerror MintFailed(string _reason, uint256 _seasonId, uint256 _payoutTier, uint256 _quantity, MintMethod _method, address _to);\n\nlibrary LibSilksHorseDiamond {\n    bytes32 internal constant STORAGE_SLOT = keccak256('silks.contracts.storage.SilksHorseDiamond');\n    \n    struct Layout {\n        mapping(uint256 => EnumerableSet.UintSet) seasonHorses;\n        mapping(uint256 => SeasonInfo) seasonInfos;\n        mapping(uint256 => PayoutTier) payoutTiers;\n        mapping(uint256 => PayoutTier) deprecated_horsePayoutTier; // deprecated\n        mapping(uint256 => EnumerableSet.UintSet) deprecated_payoutTierHorses;\n        mapping(uint256 => SeasonInfo) deprecated_horseSeasonInfo;\n        mapping(address => bool) allowedExternalMintAddresses;\n        uint256 maxHorsesPerWallet;\n        uint256 nextAvailableTokenId;\n        uint256 defaultPayoutTierId;\n        uint256 defaultSeasonId;\n        mapping(uint256 => uint256) horsePayoutTier;\n        mapping(uint256 => uint256) payoutTierHorseCount;\n        mapping(uint256 => uint256) horseSeasonInfo;\n    }\n    \n    function layout()\n    internal\n    pure\n    returns (\n        Layout storage l\n    ) {\n        bytes32 slot = STORAGE_SLOT;\n        assembly {\n            l.slot := slot\n        }\n    }\n}"
      }
    },
    "settings": {
      "evmVersion": "paris",
      "optimizer": {
        "enabled": false,
        "runs": 200
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}