creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@solidstate/contracts/access/ownable/IOwnable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC173 } from '../../interfaces/IERC173.sol';\n\ninterface IOwnable is IERC173 {}\n"
      },
      "@solidstate/contracts/access/ownable/IOwnableInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC173Internal } from '../../interfaces/IERC173Internal.sol';\n\ninterface IOwnableInternal is IERC173Internal {\n    error Ownable__NotOwner();\n    error Ownable__NotTransitiveOwner();\n}\n"
      },
      "@solidstate/contracts/access/ownable/ISafeOwnable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IOwnable } from './IOwnable.sol';\n\ninterface ISafeOwnable is IOwnable {\n    /**\n     * @notice get the nominated owner who has permission to call acceptOwnership\n     */\n    function nomineeOwner() external view returns (address);\n\n    /**\n     * @notice accept transfer of contract ownership\n     */\n    function acceptOwnership() external;\n}\n"
      },
      "@solidstate/contracts/access/ownable/OwnableInternal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC173 } from '../../interfaces/IERC173.sol';\nimport { AddressUtils } from '../../utils/AddressUtils.sol';\nimport { IOwnableInternal } from './IOwnableInternal.sol';\nimport { OwnableStorage } from './OwnableStorage.sol';\n\nabstract contract OwnableInternal is IOwnableInternal {\n    using AddressUtils for address;\n\n    modifier onlyOwner() {\n        if (msg.sender != _owner()) revert Ownable__NotOwner();\n        _;\n    }\n\n    modifier onlyTransitiveOwner() {\n        if (msg.sender != _transitiveOwner())\n            revert Ownable__NotTransitiveOwner();\n        _;\n    }\n\n    function _owner() internal view virtual returns (address) {\n        return OwnableStorage.layout().owner;\n    }\n\n    function _transitiveOwner() internal view virtual returns (address owner) {\n        owner = _owner();\n\n        while (owner.isContract()) {\n            try IERC173(owner).owner() returns (address transitiveOwner) {\n                owner = transitiveOwner;\n            } catch {\n                break;\n            }\n        }\n    }\n\n    function _transferOwnership(address account) internal virtual {\n        _setOwner(account);\n    }\n\n    function _setOwner(address account) internal virtual {\n        OwnableStorage.Layout storage l = OwnableStorage.layout();\n        emit OwnershipTransferred(l.owner, account);\n        l.owner = account;\n    }\n}\n"
      },
      "@solidstate/contracts/access/ownable/OwnableStorage.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nlibrary OwnableStorage {\n    struct Layout {\n        address owner;\n    }\n\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('solidstate.contracts.storage.Ownable');\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/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/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC165Internal } from './IERC165Internal.sol';\n\n/**\n * @title ERC165 interface registration interface\n * @dev see https://eips.ethereum.org/EIPS/eip-165\n */\ninterface IERC165 is IERC165Internal {\n    /**\n     * @notice query whether contract has registered support for given interface\n     * @param interfaceId interface id\n     * @return bool whether interface is supported\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "@solidstate/contracts/interfaces/IERC165Internal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC165Internal } from './IERC165Internal.sol';\n\n/**\n * @title ERC165 interface registration interface\n */\ninterface IERC165Internal {\n\n}\n"
      },
      "@solidstate/contracts/interfaces/IERC173.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC173Internal } from './IERC173Internal.sol';\n\n/**\n * @title Contract ownership standard interface\n * @dev see https://eips.ethereum.org/EIPS/eip-173\n */\ninterface IERC173 is IERC173Internal {\n    /**\n     * @notice get the ERC173 contract owner\n     * @return conrtact owner\n     */\n    function owner() external view returns (address);\n\n    /**\n     * @notice transfer contract ownership to new account\n     * @param account address of new owner\n     */\n    function transferOwnership(address account) external;\n}\n"
      },
      "@solidstate/contracts/interfaces/IERC173Internal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\n/**\n * @title Partial ERC173 interface needed by internal functions\n */\ninterface IERC173Internal {\n    event OwnershipTransferred(\n        address indexed previousOwner,\n        address indexed newOwner\n    );\n}\n"
      },
      "@solidstate/contracts/interfaces/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC20Internal } from './IERC20Internal.sol';\n\n/**\n * @title ERC20 interface\n * @dev see https://github.com/ethereum/EIPs/issues/20\n */\ninterface IERC20 is IERC20Internal {\n    /**\n     * @notice query the total minted token supply\n     * @return token supply\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @notice query the token balance of given account\n     * @param account address to query\n     * @return token balance\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @notice query the allowance granted from given holder to given spender\n     * @param holder approver of allowance\n     * @param spender recipient of allowance\n     * @return token allowance\n     */\n    function allowance(\n        address holder,\n        address spender\n    ) external view returns (uint256);\n\n    /**\n     * @notice grant approval to spender to spend tokens\n     * @dev prefer ERC20Extended functions to avoid transaction-ordering vulnerability (see https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729)\n     * @param spender recipient of allowance\n     * @param amount quantity of tokens approved for spending\n     * @return success status (always true; otherwise function should revert)\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @notice transfer tokens to given recipient\n     * @param recipient beneficiary of token transfer\n     * @param amount quantity of tokens to transfer\n     * @return success status (always true; otherwise function should revert)\n     */\n    function transfer(\n        address recipient,\n        uint256 amount\n    ) external returns (bool);\n\n    /**\n     * @notice transfer tokens to given recipient on behalf of given holder\n     * @param holder holder of tokens prior to transfer\n     * @param recipient beneficiary of token transfer\n     * @param amount quantity of tokens to transfer\n     * @return success status (always true; otherwise function should revert)\n     */\n    function transferFrom(\n        address holder,\n        address recipient,\n        uint256 amount\n    ) external returns (bool);\n}\n"
      },
      "@solidstate/contracts/interfaces/IERC20Internal.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\n/**\n * @title Partial ERC20 interface needed by internal functions\n */\ninterface IERC20Internal {\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    event Approval(\n        address indexed owner,\n        address indexed spender,\n        uint256 value\n    );\n}\n"
      },
      "@solidstate/contracts/interfaces/IERC721.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.8;\n\nimport { IERC165 } from './IERC165.sol';\nimport { IERC721Internal } from './IERC721Internal.sol';\n\n/**\n * @title ERC721 interface\n * @dev see https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721 is IERC721Internal, IERC165 {\n    /**\n     * @notice query the balance of given address\n     * @return balance quantity of tokens held\n     */\n    function balanceOf(address account) external view returns (uint256 balance);\n\n    /**\n     * @notice query the owner of given token\n     * @param tokenId token to query\n     * @return owner token owner\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @notice transfer token between given addresses, checking for ERC721Receiver implementation if applicable\n     * @param from sender of token\n     * @param to receiver of token\n     * @param tokenId token id\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external payable;\n\n    /**\n     * @notice transfer token between given addresses, checking for ERC721Receiver implementation if applicable\n     * @param from sender of token\n     * @param to receiver of token\n     * @param tokenId token id\n     * @param data data payload\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes calldata data\n    ) external payable;\n\n    /**\n     * @notice transfer token between given addresses, without checking for ERC721Receiver implementation if applicable\n     * @param from sender of token\n     * @param to receiver of token\n     * @param tokenId token id\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external payable;\n\n    /**\n     * @notice grant approval to given account to spend token\n     * @param operator address to be approved\n     * @param tokenId token to approve\n     */\n    function approve(address operator, uint256 tokenId) external payable;\n\n    /**\n     * @notice get approval status for given token\n     * @param tokenId token to query\n     * @return operator address approved to spend token\n     */\n    function getApproved(\n        uint256 tokenId\n    ) external view returns (address operator);\n\n    /**\n     * @notice grant approval to or revoke approval from given account to spend all tokens held by sender\n     * @param operator address to be approved\n     * @param status approval status\n     */\n    function setApprovalForAll(address operator, bool status) external;\n\n    /**\n     * @notice query approval status of given operator with respect to given address\n     * @param account address to query for approval granted\n     * @param operator address to query for approval received\n     * @return status whether operator is approved to spend tokens held by account\n     */\n    function isApprovedForAll(\n        address account,\n        address operator\n    ) external view returns (bool status);\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/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/enumerable/ERC721EnumerableInternal.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';\nimport { ERC721BaseStorage } from '../base/ERC721BaseStorage.sol';\n\nabstract contract ERC721EnumerableInternal {\n    using EnumerableMap for EnumerableMap.UintToAddressMap;\n    using EnumerableSet for EnumerableSet.UintSet;\n\n    /**\n     * @notice TODO\n     */\n    function _totalSupply() internal view returns (uint256) {\n        return ERC721BaseStorage.layout().tokenOwners.length();\n    }\n\n    /**\n     * @notice TODO\n     */\n    function _tokenOfOwnerByIndex(\n        address owner,\n        uint256 index\n    ) internal view returns (uint256) {\n        return ERC721BaseStorage.layout().holderTokens[owner].at(index);\n    }\n\n    /**\n     * @notice TODO\n     */\n    function _tokenByIndex(\n        uint256 index\n    ) internal view returns (uint256 tokenId) {\n        (tokenId, ) = ERC721BaseStorage.layout().tokenOwners.at(index);\n    }\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/helpers/IMarketPlaceHelper.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\ninterface IMarketPlaceHelper {\n    struct EncodedCall {\n        bytes data; //encoded call data\n        uint256 value; //call msg.value\n        address target; //call target address\n    }\n\n    /**\n     * @notice thrown when purchase call to target market is unsuccessfull\n     */\n    error MarketPlaceHelper__FailedPurchaseCall();\n\n    /**\n     * @notice thrown when list call to target market is unsuccessfull\n     */\n    error MarketPlaceHelper__FailedListCall();\n\n    /**\n     * @notice thrown when insufficient ETH is transferred\n     */\n    error MarketPlaceHelper__InsufficientETH();\n\n    /**\n     * @notice thrown when insufficient purchaseToken is transferred\n     */\n    error MarketPlaceHelper__InsufficientPurchaseToken();\n\n    /**\n     * @notice thrown when bid acceptance call fails\n     */\n    error MarketPlaceHelper__FailedAcceptBidCall();\n\n    /**\n     * @notice thrown when withdrawing + forwarding sale proceeds fails\n     */\n    error MarketPlaceHelper__FailedForwardSaleProceedsCall();\n\n    /**\n     * @notice purchasing call made to arbitrary marketplace\n     * @param calls array of EncodedCall structs containing information to execute the desired\n     * number of low level calls\n     * @param purchaseToken address of token used to transact - if address(0) ETH is used\n     * @param price purchase price\n     */\n    function purchaseAsset(\n        EncodedCall[] calldata calls,\n        address purchaseToken,\n        uint256 price\n    ) external payable;\n\n    /**\n     * @notice ERC721 listing call made to arbitrary marketplace\n     * @param calls encoded calls needed to list asset\n     */\n    function listAsset(EncodedCall[] memory calls) external;\n\n    /**\n     * @notice accept bid call made to arbitrary marketplace\n     * @param calls encoded calls needed to accept bid\n     */\n    function acceptAssetBid(EncodedCall[] memory calls) external;\n\n    /**\n     * @notice accept bid call made to arbitrary marketplace\n     * @param calls encoded calls needed to accept bid\n     * @return proceeds amount of ETH forwarded to msg.sender (which is the owner)\n     */\n    function forwardSaleProceeds(\n        EncodedCall[] memory calls\n    ) external payable returns (uint256 proceeds);\n}\n"
      },
      "contracts/interfaces/cryptopunk/ICryptoPunkMarket.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title Interface for CryptoPunkMarket\n */\ninterface ICryptoPunkMarket {\n    /**\n     * @notice offer made on a punk\n     * @param isForSale indicates whether punk may be bought instantly\n     * @param punkIndex the index of punk\n     * @param minValue the minimum price of punk in WEI\n     * @param onlySellTo if specified, is the only address a punk may be sold to\n     */\n    struct Offer {\n        bool isForSale;\n        uint256 punkIndex;\n        address seller;\n        uint256 minValue;\n        address onlySellTo;\n    }\n\n    /**\n     * @notice bid on a punk\n     * @param hasBid deprecated  (used nowhere in CryptoPunkMarket contract)\n     * @param punkIndex the index of the punk\n     * @param bidder the address which made the bid\n     * @param value the value of the bid in WEI\n     */\n    struct Bid {\n        bool hasBid;\n        uint256 punkIndex;\n        address bidder;\n        uint256 value;\n    }\n\n    /**\n     * @notice returns  highest bid on a punk\n     * @param punkIndex the index of the punk\n     * @return highest bid on the punk\n     */\n    function punkBids(uint256 punkIndex) external view returns (Bid memory);\n\n    /**\n     * @notice public mapping(uint => Offer) punksOfferedForSale;\n     * @param punkIndex the index of the punk\n     * @return offer currently active on the punk\n     */\n    function punksOfferedForSale(\n        uint256 punkIndex\n    ) external view returns (Offer memory);\n\n    /**\n     * @notice public mapping(uint => address) punkIndexToAddress;\n     * @param punkIndex index of the punk\n     * @return address to which the punk belongs to (or is assigned to)\n     */\n    function punkIndexToAddress(\n        uint256 punkIndex\n    ) external view returns (address);\n\n    /**\n     * @notice mapping(address => uint256) pendingWithdrawals mapping\n     * @param withdrawer address to which withdrawal is owed\n     * @return uint amount pending in ETH\n     */\n    function pendingWithdrawals(\n        address withdrawer\n    ) external view returns (uint256);\n\n    /**\n     * @notice purchase a punk\n     * @param punkIndex index of punk\n     */\n    function buyPunk(uint256 punkIndex) external payable;\n\n    /**\n     * @notice opens punk to instant purchase\n     * @param punkIndex the index of the punk\n     * @param minSalePriceInWei the minimum sale price of the punk in WEI\n     */\n    function offerPunkForSale(\n        uint256 punkIndex,\n        uint256 minSalePriceInWei\n    ) external;\n\n    /**\n     * @notice closes punk to instance purchase\n     * @param punkIndex index of punk\n     */\n    function punkNoLongerForSale(uint256 punkIndex) external;\n\n    /**\n     * @notice withdraws pending amount after punk sale\n     */\n    function withdraw() external;\n\n    /**\n     * @notice transfers a punk without a sale\n     * @param to address to transfer punk to\n     * @param punkIndex index of punk\n     */\n    function transferPunk(address to, uint256 punkIndex) external;\n\n    /**\n     * @notice accept a bid on a punk\n     * @dev note that the minPrice parameter checks that the bid to be accepted must be larger than some\n     * price defined by the caller of acceptBidForPunk to ensure the punk is not undersold.\n     * @param punkIndex index of punk\n     * @param minPrice minimum price of the bid in WEI\n     */\n    function acceptBidForPunk(uint256 punkIndex, uint256 minPrice) external;\n\n    /**\n     * @notice withdraw a bid on a punk\n     * @param punkIndex punk index\n     */\n    function withdrawBidForPunk(uint256 punkIndex) external;\n\n    /**\n     * @notice enter a bid on a punk\n     * @dev the bid amount is the msg.value attached to this call\n     * @param punkIndex punk index\n     */\n    function enterBidForPunk(uint256 punkIndex) external payable;\n}\n"
      },
      "contracts/interfaces/curve/IStableSwap.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\n/**\n * @title Interface for Curve StableSwap pool\n */\ninterface IStableSwap {\n    /**\n     * @notice Perform an exchange between two underlying coins\n     * @param i Index value for the underlying coin to send\n     * @param j Index valie of the underlying coin to receive\n     * @param _dx Amount of `i` being exchanged\n     * @param _min_dy Minimum amount of `j` to receive\n     * @return Actual amount of `j` received\n     */\n    function exchange(\n        int128 i,\n        int128 j,\n        uint256 _dx,\n        uint256 _min_dy\n    ) external payable returns (uint256);\n\n    /**\n     * @notice Perform an exchange between two underlying coins\n     * @param i Index value for the underlying coin to send\n     * @param j Index valie of the underlying coin to receive\n     * @param _dx Amount of `i` being exchanged\n     * @param _min_dy Minimum amount of `j` to receive\n     * @return Actual amount of `j` received\n     */\n    function exchange_underlying(\n        int128 i,\n        int128 j,\n        uint256 _dx,\n        uint256 _min_dy\n    ) external payable returns (uint256);\n\n    /**\n     * @notice Deposit coins into the pool\n     * @param _amounts List of amounts of coins to deposit\n     * @param _min_mint_amount Minimum amount of LP tokens to mint from the deposit\n     * @return amount of LP tokens received by depositing\n     */\n    function add_liquidity(\n        uint256[2] memory _amounts,\n        uint256 _min_mint_amount\n    ) external returns (uint256);\n\n    /**\n     * @notice Withdraw a single coin from the pool\n     * @param _burn_amount Amount of LP tokens to burn in the withdrawal\n     * @param i Index value of the coin to withdraw\n     * @param _min_received Minimum amount of coin to receive\n     * @return Amount of coin received\n     */\n    function remove_liquidity_one_coin(\n        uint256 _burn_amount,\n        int128 i,\n        uint256 _min_received\n    ) external payable returns (uint256);\n\n    /**\n     * @notice Calculate addition or reduction in token supply from a deposit or withdrawal\n     * @dev This calculation accounts for slippage, but not fees.\n     *      Needed to prevent front-running, not for precise calculations!\n     * @param _amounts Amount of each underlying coin being deposited\n     * @param _is_deposit set True for deposits, False for withdrawals\n     * @return Expected amount of LP tokens received\n     */\n    function calc_token_amount(\n        uint256[2] memory _amounts,\n        bool _is_deposit\n    ) external view returns (uint256);\n\n    /**\n     * @notice Calculate the amount received when withdrawing a single coin\n     * @param _token_amount Amount of LP tokens to burn in the withdrawal\n     * @param i Index value of the coin to withdraw\n     * @return Amount of coin received\n     */\n    function calc_withdraw_one_coin(\n        uint256 _token_amount,\n        int128 i\n    ) external view returns (uint256);\n\n    /**\n     * @notice The current virtual price of the pool LP token\n     * @dev Useful for calculating profits\n     * @return LP token virtual price normalized to 1e18\n     */\n    function get_virtual_price() external view returns (uint256);\n\n    /**\n     * @notice Get the amount received (“dy”) when swapping between two underlying assets within the pool.\n     * @param i Index value of the token to send.\n     * @param j Index value of the token to receive.\n     * @param dx: The amount of i being exchanged.\n     * @return amount of j received\n     */\n    function get_dy(\n        int128 i,\n        int128 j,\n        uint256 dx\n    ) external view returns (uint256);\n}\n"
      },
      "contracts/interfaces/insrt/IDawnOfInsrt.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @notice Dawn of Insrt token collection interface\n */\ninterface IDawnOfInsrt {\n    /**\n     * @notice returns tier of given token\n     * @param tokenId id of token to check\n     * @return tier tier of tokenId\n     */\n    function tokenTier(uint256 tokenId) external view returns (uint8 tier);\n}\n"
      },
      "contracts/interfaces/jpegd/IJpegCardsCigStaking.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\ninterface IJpegCardsCigStaking {\n    struct UserData {\n        uint256 stakedCig;\n        bool isStaking;\n    }\n\n    /// @notice Allows users to deposit one of their cigarette JPEG cards.\n    /// @param _idx The index of the NFT to stake.\n    function deposit(uint256 _idx) external;\n\n    /// @notice Allows users to withdraw their staked cigarette JPEG card.\n    /// @param _idx The index of the NFT to unstake.\n    function withdraw(uint256 _idx) external;\n\n    // @return Whether the user is staking a cigarette or not.\n    function isUserStaking(address _user) external view returns (bool);\n\n    /**\n     * @notice custom getter for user data\n     * @param user user address\n     * @return UserData UserData struct\n     */\n    function userData(address user) external view returns (UserData memory);\n\n    /**\n     * @notice custom getter for jpeg'd card collection\n     * @return address of jpeg'd card collection\n     */\n    function cards() external view returns (address);\n}\n"
      },
      "contracts/interfaces/jpegd/ILPFarming.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\n/**\n * @title Interface to jpeg'd LPFarming Contracts\n * @dev https://github.com/jpegd/core/blob/main/contracts/farming/LPFarming.sol\n * @dev Only whitelisted contracts may call these functions\n */\ninterface ILPFarming {\n    /// @dev Data relative to an LP pool\n    /// @param lpToken The LP token accepted by the pool\n    /// @param allocPoint Allocation points assigned to the pool. Determines the share of `rewardPerBlock` allocated to this pool\n    /// @param lastRewardBlock Last block number in which reward distribution occurred\n    /// @param accRewardPerShare Accumulated rewards per share, times 1e36. The amount of rewards the pool has accumulated per unit of LP token deposited\n    /// @param depositedAmount Total number of tokens deposited in the pool.\n    struct PoolInfo {\n        address lpToken;\n        uint256 allocPoint;\n        uint256 lastRewardBlock;\n        uint256 accRewardPerShare;\n        uint256 depositedAmount;\n    }\n\n    /// @dev Data relative to a user's staking position\n    /// @param amount The amount of LP tokens the user has provided\n    /// @param lastAccRewardPerShare The `accRewardPerShare` pool value at the time of the user's last claim\n    struct UserInfo {\n        uint256 amount;\n        uint256 lastAccRewardPerShare;\n    }\n\n    /**\n     * @notice getter for poolInfo struct in  PoolInfo array of JPEGd LPFarming contract\n     * @param index index of poolInfo in PoolInfo array\n     * @return PoolInfo[] array of PoolInfo structs\n     */\n    function poolInfo(uint256 index) external view returns (PoolInfo memory);\n\n    /**\n     * @notice getter for the userInfo mapping in JPEGd LPFarming contract\n     * @return UserInfo userInfo struct for user in JPEGd LPFarming pool with poolId\n     */\n    function userInfo(\n        uint256 poolId,\n        address user\n    ) external view returns (UserInfo memory);\n\n    /// @notice Frontend function used to calculate the amount of rewards `_user` can claim from the pool with id `_pid`\n    /// @param _pid The pool id\n    /// @param _user The address of the user\n    /// @return The amount of rewards claimable from `_pid` by user `_user`\n    function pendingReward(\n        uint256 _pid,\n        address _user\n    ) external view returns (uint256);\n\n    /// @notice Allows users to deposit `_amount` of LP tokens in the pool with id `_pid`. Non whitelisted contracts can't call this function\n    /// @dev Emits a {Deposit} event\n    /// @param _pid The id of the pool to deposit into\n    /// @param _amount The amount of LP tokens to deposit\n    function deposit(uint256 _pid, uint256 _amount) external;\n\n    /// @notice Allows users to withdraw `_amount` of LP tokens from the pool with id `_pid`. Non whitelisted contracts can't call this function\n    /// @dev Emits a {Withdraw} event\n    /// @param _pid The id of the pool to withdraw from\n    /// @param _amount The amount of LP tokens to withdraw\n    function withdraw(uint256 _pid, uint256 _amount) external;\n\n    /// @notice Allows users to claim rewards from the pool with id `_pid`. Non whitelisted contracts can't call this function\n    /// @dev Emits a {Claim} event\n    /// @param _pid The pool to claim rewards from\n    function claim(uint256 _pid) external;\n\n    /// @notice Allows users to claim rewards from all pools. Non whitelisted contracts can't call this function\n    /// @dev Emits a {ClaimAll} event\n    function claimAll() external;\n}\n"
      },
      "contracts/interfaces/jpegd/INFTEscrow.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\n/**\n * @title Interface to jpeg'd NFTEscrow Contracts\n * @dev https://github.com/jpegd/core/blob/main/contracts/escrow/NFTEscrow.sol\n */\ninterface INFTEscrow {\n    /// @notice This function returns the address where user `_owner` should send the `_idx` NFT to\n    /// @dev `precompute` computes the salt and the address relative to NFT at index `_idx` owned by `_owner`\n    /// @param _owner The owner of the NFT at index `_idx`\n    /// @param _idx The index of the NFT owner by `_owner`\n    /// @return salt The salt that's going to be used to deploy the {FlashEscrow} instance\n    /// @return predictedAddress The address where the {FlashEscrow} instance relative to `_owner` and `_idx` will be deployed to\n    function precompute(\n        address _owner,\n        uint256 _idx\n    ) external view returns (bytes32 salt, address predictedAddress);\n\n    function nftContract() external view returns (address collection);\n}\n"
      },
      "contracts/interfaces/jpegd/INFTVault.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\n/**\n * @title Interface to jpeg'd NFTVault Contracts\n * @dev https://github.com/jpegd/core/blob/main/contracts/vaults/NFTVault.sol\n */\ninterface INFTVault {\n    /// jpeg'd RATE struct\n    struct Rate {\n        uint128 numerator;\n        uint128 denominator;\n    }\n\n    /// jpeg'd vault settings struct\n    struct VaultSettings {\n        Rate debtInterestApr;\n        Rate creditLimitRate;\n        Rate liquidationLimitRate;\n        Rate cigStakedCreditLimitRate;\n        Rate cigStakedLiquidationLimitRate;\n        /// @custom:oz-renamed-from valueIncreaseLockRate\n        Rate unused12;\n        Rate organizationFeeRate;\n        Rate insurancePurchaseRate;\n        Rate insuranceLiquidationPenaltyRate;\n        uint256 insuranceRepurchaseTimeLimit;\n        uint256 borrowAmountCap;\n    }\n\n    /// jpeg'd vault BorrowType enum\n    enum BorrowType {\n        NOT_CONFIRMED,\n        NON_INSURANCE,\n        USE_INSURANCE\n    }\n\n    /// jpeg'd vault Position struct\n    struct Position {\n        BorrowType borrowType;\n        uint256 debtPrincipal;\n        uint256 debtPortion;\n        uint256 debtAmountForRepurchase;\n        uint256 liquidatedAt;\n        address liquidator;\n    }\n\n    /// @notice Allows users to open positions and borrow using an NFT\n    /// @dev emits a {Borrowed} event\n    /// @param _nftIndex The index of the NFT to be used as collateral\n    /// @param _amount The amount of PUSD to be borrowed. Note that the user will receive less than the amount requested,\n    /// the borrow fee and insurance automatically get removed from the amount borrowed\n    /// @param _useInsurance Whether to open an insured position. In case the position has already been opened previously,\n    /// this parameter needs to match the previous insurance mode. To change insurance mode, a user needs to close and reopen the position\n    function borrow(\n        uint256 _nftIndex,\n        uint256 _amount,\n        bool _useInsurance\n    ) external;\n\n    /// @param _nftIndex The NFT to return the value of\n    /// @return The value in USD of the NFT at index `_nftIndex`, with 18 decimals.\n    function getNFTValueUSD(uint256 _nftIndex) external view returns (uint256);\n\n    /// @param _nftIndex The NFT to return the credit limit of\n    /// @return The PETH/PUSD credit limit of the NFT at index `_nftIndex`.\n    function getCreditLimit(\n        address _owner,\n        uint256 _nftIndex\n    ) external view returns (uint256);\n\n    /**\n     * @notice getter for jpegdVault settings\n     * @return VaultSettings settings of jpegdVault\n     */\n    function settings() external view returns (VaultSettings memory);\n\n    /**\n     * @notice getter for owned of position opened in jpegdVault\n     * @param tokenId NFT id mapping to position owner\n     * @return address position owner address\n     */\n    function positionOwner(uint256 tokenId) external view returns (address);\n\n    /// @param _nftIndex The NFT to check\n    /// @return The PUSD debt interest accumulated by the NFT at index `_nftIndex`.\n    function getDebtInterest(uint256 _nftIndex) external view returns (uint256);\n\n    /// @return The floor value for the collection, in ETH.\n    function getFloorETH() external view returns (uint256);\n\n    /// @notice Allows users to repay a portion/all of their debt. Note that since interest increases every second,\n    /// a user wanting to repay all of their debt should repay for an amount greater than their current debt to account for the\n    /// additional interest while the repay transaction is pending, the contract will only take what's necessary to repay all the debt\n    /// @dev Emits a {Repaid} event\n    /// @param _nftIndex The NFT used as collateral for the position\n    /// @param _amount The amount of debt to repay. If greater than the position's outstanding debt, only the amount necessary to repay all the debt will be taken\n    function repay(uint256 _nftIndex, uint256 _amount) external;\n\n    /// @notice Allows a user to close a position and get their collateral back, if the position's outstanding debt is 0\n    /// @dev Emits a {PositionClosed} event\n    /// @param _nftIndex The index of the NFT used as collateral\n    function closePosition(uint256 _nftIndex) external;\n\n    /**\n     * @notice getter for position corresponding to tokenId\n     * @param tokenId NFT id mapping to position\n     * @return position corresponding to tokenId\n     */\n    function positions(uint256 tokenId) external view returns (Position memory);\n\n    /**\n     * @notice getter for total globabl debt in jpeg'd vault\n     * @return uin256 total global debt\n     */\n    function totalDebtAmount() external view returns (uint256);\n\n    /**\n     * @notice getter for the JPEG'd NFT Value provider contract address\n     * @return address of NFT Value provider\n     */\n    function nftValueProvider() external view returns (address);\n\n    /// @param _nftIndex The NFT to return the liquidation limit of\n    /// @return The PETH liquidation limit of the NFT at index `_nftIndex`.\n    function getLiquidationLimit(\n        address _owner,\n        uint256 _nftIndex\n    ) external view returns (uint256);\n\n    /**\n     * @notice returns underlying stablecoin (PETH/PUSD) of NFT Vault\n     * @return coin address of PETH/PUSD\n     */\n    function stablecoin() external view returns (address coin);\n\n    /**\n     * @notice returns underlying ERC721 collection of NFT Vault\n     * @return collection ERC721 collection address\n     */\n    function nftContract() external view returns (address collection);\n}\n"
      },
      "contracts/interfaces/jpegd/IVault.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\n/**\n * @title Interface to jpeg'd Vault Contracts\n * @dev https://github.com/jpegd/core/blob/main/contracts/vaults/erc20/Vault.sol\n * @dev Only whitelisted contracts may call these functions\n */\ninterface IVault {\n    struct Rate {\n        uint128 numerator;\n        uint128 denominator;\n    }\n\n    /// @notice Allows users to deposit `token`. Contracts can't call this function\n    /// @param _to The address to send the tokens to\n    /// @param _amount The amount to deposit\n    function deposit(\n        address _to,\n        uint256 _amount\n    ) external returns (uint256 shares);\n\n    /// @notice Allows users to withdraw tokens. Contracts can't call this function\n    /// @param _to The address to send the tokens to\n    /// @param _shares The amount of shares to burn\n    function withdraw(\n        address _to,\n        uint256 _shares\n    ) external returns (uint256 backingTokens);\n\n    /// @return The underlying tokens per share\n    function exchangeRate() external view returns (uint256);\n\n    /// @return assets The total amount of tokens managed by this vault and the underlying strategy\n    function totalAssets() external view returns (uint256 assets);\n\n    /**\n     * @notice custom getter for decimals of jpeg'd Vault underlying token\n     * @return uint8 decimals of jpeg'd Vault underlying token\n     */\n    function decimals() external view returns (uint8);\n\n    /**\n     * @notice custom getter for depositFeeRate in jpeg'd citadel\n     * @return Rate deposit fee rate\n     */\n    function depositFeeRate() external view returns (Rate memory);\n}\n"
      },
      "contracts/shard/IShardVaultAdmin.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { IMarketPlaceHelper } from '../helpers/IMarketPlaceHelper.sol';\n\n/**\n * @title ShardVaultAdmin interace\n */\ninterface IShardVaultAdmin {\n    /**\n     * @notice purchases a punk from CyrptoPunksMarket\n     * @param calls  array of EncodedCall structs containing information to execute necessary low level\n     * calls to purchase a punk\n     * @param punkId id of punk\n     */\n    function purchasePunk(\n        IMarketPlaceHelper.EncodedCall[] calldata calls,\n        uint256 punkId\n    ) external payable;\n\n    /**\n     * @notice borrows pETH by collateralizing a punk on JPEG'\n     * @dev insuring is explained here: https://github.com/jpegd/core/blob/7581b11fc680ab7004ea869226ba21be01fc0a51/contracts/vaults/NFTVault.sol#L563\n     * @param punkId id of punk\n     * @param borrowAmount amount to be borrowed\n     * @param insure whether to insure position\n     * @return pETH borrowed pETH\n     */\n    function collateralizePunkPETH(\n        uint256 punkId,\n        uint256 borrowAmount,\n        bool insure\n    ) external returns (uint256 pETH);\n\n    /**\n     * @notice borrows pETH in exchange for collaterlizing an ERC721 asset\n     * @param tokenId id of ERC721 asset\n     * @param insure whether to insure\n     * @return pETH the amount of pETH received for the collateralized ERC721 asset\n     */\n    function collateralizeERC721AssetPETH(\n        uint256 tokenId,\n        uint256 borrowAmount,\n        bool insure\n    ) external returns (uint256 pETH);\n\n    /**\n     * @notice stakes an amount of pETH into JPEGd autocompounder and then into JPEGd PETH_CITADEL\n     * @param amount amount of pETH to stake\n     * @param minCurveLP minimum LP to receive from pETH staking into curve\n     * @param poolInfoIndex the index of the poolInfo struct in PoolInfo array corresponding to\n     * the pool to deposit into\n     * @return shares deposited into JPEGd autocompounder\n     */\n    function stakePETH(\n        uint256 amount,\n        uint256 minCurveLP,\n        uint256 poolInfoIndex\n    ) external returns (uint256 shares);\n\n    /**\n     * @notice withdraw JPEG and ETH accrued protocol fees, and send to TREASURY address\n     * @return feesETH total ETH fees withdrawn\n     * @return feesJPEG total JPEG fees withdrawn\n     */\n    function withdrawFees()\n        external\n        returns (uint256 feesETH, uint256 feesJPEG);\n\n    /**\n     * @notice sets the acquisition fee BP\n     * @param feeBP basis points value of fee\n     */\n    function setAcquisitionFee(uint16 feeBP) external;\n\n    /**\n     * @notice sets the sale fee BP\n     * @param feeBP basis points value of fee\n     */\n    function setSaleFee(uint16 feeBP) external;\n\n    /**\n     * @notice sets the Yield fee BP\n     * @param feeBP basis points value of fee\n     */\n    function setYieldFee(uint16 feeBP) external;\n\n    /**\n     * @notice sets the maxSupply of shards\n     * @param maxSupply the maxSupply of shards\n     */\n    function setMaxSupply(uint64 maxSupply) external;\n\n    /**\n     * @notice sets the whitelistEndsAt timestamp\n     * @param whitelistEndsAt timestamp of whitelist end\n     */\n    function setWhitelistEndsAt(uint48 whitelistEndsAt) external;\n\n    /**\n     * @notice sets the maximum amount of shards to be minted during whitelist\n     * @param reservedSupply reserved shard amount\n     */\n    function setReservedSupply(uint64 reservedSupply) external;\n\n    /**\n     * @notice sets the isEnabled flag, allowing or prohibiting deposits\n     * @param isEnabled boolean value\n     */\n    function setIsEnabled(bool isEnabled) external;\n\n    /**\n     * @notice grants or revokes the 'authorized' state to an account\n     * @param account address of account to grant/revoke 'authorized'\n     * @param isAuthorized value of 'authorized' state\n     */\n    function setAuthorized(address account, bool isAuthorized) external;\n\n    /**\n     * @notice sets the whitelist deadline and allows deposits\n     * @param whitelistEndsAt whitelist deadline timestamp\n     * @param reservedSupply whitelist shard amount\n     */\n    function initiateWhitelistAndDeposits(\n        uint48 whitelistEndsAt,\n        uint64 reservedSupply\n    ) external;\n\n    /**\n     * @notice return the maximum shards a user is allowed to mint; theoretically a user may acquire more than this amount via transfers,\n     * but once this amount is exceeded said user may not deposit more\n     * @param maxMintBalance new maxMintBalance value\n     */\n    function setMaxMintBalance(uint64 maxMintBalance) external;\n\n    /**\n     * @notice unstakes from JPEG'd LPFarming, then from JPEG'd citadel, then from curve LP\n     * @param amount amount of shares of auto-compounder to burn\n     * @param minPETH minimum pETH to receive from curve pool\n     * @param poolInfoIndex the index of the JPEG'd LPFarming pool\n     * @return pETH pETH amount returned\n     */\n    function unstakePETH(\n        uint256 amount,\n        uint256 minPETH,\n        uint256 poolInfoIndex\n    ) external returns (uint256 pETH);\n\n    /**\n     * @notice liquidates all staked tokens in order to pay back loan, retrieves collateralized asset\n     * @param tokenId tokenId pertinent to position\n     * @param minPETH minimum pETH to receive from curveLP after unstake\n     * @param poolInfoIndex index of pool in lpFarming pool array\n     * @param minETH minimum amount of ETH to receive from curveLP after exchange\n     */\n    function closePositionPETH(\n        uint256 tokenId,\n        uint256 minPETH,\n        uint256 poolInfoIndex,\n        uint256 minETH\n    ) external;\n\n    /**\n     * @notice retrieves collateralized asset and transfers it to the TREASURY\n     * @notice assumes position has no outstanding debt\n     * @param tokenId tokenId pertinent to position\n     */\n    function directClosePosition(uint256 tokenId) external;\n\n    /**\n     * @notice makes a debt payment for a collateralized NFT in jpeg'd\n     * @param amount amount of pETH intended to be repaid\n     * @param minPETH minimum pETH to receive from curveLP\n     * @param poolInfoIndex index of pool in lpFarming pool array\n     * @param tokenId id of token position pertains to\n     * @return paidDebt amount of debt repaid\n     */\n    function repayLoanPETH(\n        uint256 amount,\n        uint256 minPETH,\n        uint256 poolInfoIndex,\n        uint256 tokenId\n    ) external returns (uint256 paidDebt);\n\n    /**\n     * @notice makes loan repayment in PETH without unstaking\n     * @param amount payment amount\n     * @param tokenId id of punk\n     */\n    function directRepayLoanPETH(uint256 amount, uint256 tokenId) external;\n\n    /**\n     * @notice lists a punk on CryptoPunk market place using MarketPlaceHelper contract\n     * @param calls encoded call array for listing the punk\n     * @param punkId id of punk to list\n     */\n    function listPunk(\n        IMarketPlaceHelper.EncodedCall[] memory calls,\n        uint256 punkId\n    ) external;\n\n    /**\n     * @notice stakes a jpeg card\n     * @param tokenId id of card in card collection\n     */\n    function stakeCard(uint256 tokenId) external;\n\n    /**\n     * @notice unstakes a jpeg card\n     * @param tokenId id of card in card collection\n     */\n    function unstakeCard(uint256 tokenId) external;\n\n    /**\n     * @notice transfers a jpeg card to an address\n     * @param tokenId id of card in card collection\n     * @param to address to transfer to\n     */\n    function transferCard(uint256 tokenId, address to) external;\n\n    /**\n     * @notice provides (makes available) yield in the form of ETH and JPEG tokens\n     * @dev unstakes some of the pETH position to convert to yield, and claims\n     * pending rewards in LP_FARM to receive JPEG\n     * @param autoComp amount of autoComp tokens to unstake\n     * @param minETH minimum ETH to receive after unstaking\n     * @param poolInfoIndex the index of the LP_FARM pool which corresponds to staking PETH-ETH curveLP\n     * @return providedETH total ETH provided as yield\n     * @return providedJPEG total JEPG provided as yield\n     */\n    function provideYieldPETH(\n        uint256 autoComp,\n        uint256 minETH,\n        uint256 poolInfoIndex\n    ) external payable returns (uint256 providedETH, uint256 providedJPEG);\n\n    /**\n     * @notice makes the any ETH besides the vault accrued fees claimable\n     */\n    function makeUnusedETHClaimable() external;\n\n    /**\n     * @notice accepts a punk bid and withdraws any proceeds generated from punk sales\n     * @dev called from marketPlaceHelper contract to transfer ETH proceeds from punk sale\n     * @param calls encoded calls required to accept bid on an asset\n     * @param punkId id of punk to accept bid on\n     */\n    function acceptPunkBid(\n        IMarketPlaceHelper.EncodedCall[] memory calls,\n        uint256 punkId\n    ) external;\n\n    /**\n     * @notice sets a new baseURI for ERC721Metadata\n     * @param baseURI the new baseURI\n     */\n    function setBaseURI(string memory baseURI) external;\n\n    /**\n     * @notice sets the new value of ltvBufferBP\n     * @param ltvBufferBP new value of ltvBufferBP\n     */\n    function setLtvBufferBP(uint16 ltvBufferBP) external;\n\n    /**\n     * @notice sets the new value of ltvDeviationBP\n     * @param ltvDeviationBP new value of ltvDeviationBP\n     */\n    function setLtvDeviationBP(uint16 ltvDeviationBP) external;\n\n    /**\n     * @notice transfers an ERC721 asset from the TREASURY in an \"over-the-counter\" (OTC) fashion\n     * @param tokenId id of ERC721 asset to transfer\n     * @param price amount of ETH to send to TREASURY in exchange for ERC721 asset\n     */\n    function transferERC721AssetOTC(uint256 tokenId, uint256 price) external;\n\n    /**\n     * @notice purhcases an ERC721 asset via MarketplaceHelper\n     * @param calls encoded calls to pass to MarketplaceHelper for ERC721 asset purchase\n     * @param tokenId id of ERC721 asset to purchase\n     * @param purchaseToken address of token used for purchase (normally ETH/WETH)\n     * @param price price in purchaseToken for ERC721 asset purchase\n     */\n    function purchaseERC721Asset(\n        IMarketPlaceHelper.EncodedCall[] calldata calls,\n        uint256 tokenId,\n        address purchaseToken,\n        uint256 price\n    ) external;\n\n    /**\n     * @notice receives proceeds from punks sold, and removes any required punkIds from ownedTokenIds\n     * @param calls encoded calls required to withdraw proceeds of sold punks\n     * @param punkIds ids of punk to remove\n     */\n    function receivePunkProceeds(\n        IMarketPlaceHelper.EncodedCall[] memory calls,\n        uint256[] memory punkIds\n    ) external;\n}\n"
      },
      "contracts/shard/IShardVaultInternal.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { IOwnableInternal } from '@solidstate/contracts/access/ownable/IOwnableInternal.sol';\n\ninterface IShardVaultInternal is IOwnableInternal {\n    struct JPEGParams {\n        address PETH;\n        address JPEG;\n        address JPEG_CARDS_CIG_STAKING;\n        address JPEG_CARDS;\n        address PETH_CITADEL;\n        address CURVE_PETH_POOL;\n        address LP_FARM;\n    }\n\n    struct AuxiliaryParams {\n        address PUNKS;\n        address DAWN_OF_INSRT;\n        address MARKETPLACE_HELPER;\n        address TREASURY;\n    }\n\n    /**\n     * @notice thrown when the deposit amount is not a multiple of shardSize\n     */\n    error ShardVault__InvalidDepositAmount();\n\n    /**\n     * @notice thrown when the maximum capital has been reached or vault has invested\n     */\n    error ShardVault__DepositForbidden();\n\n    /**\n     * @notice thrown when the withdraw amount exceeds the owed shards to the sender\n     */\n    error ShardVault__InsufficientShards();\n\n    /**\n     * @notice thrown when the maximum capital has been reached or vault has invested\n     */\n    error ShardVault__WithdrawalForbidden();\n\n    /**\n     * @notice thrown when attempt to purchase a punk is made when collection is not punks\n     */\n    error ShardVault__CollectionNotPunks();\n\n    /**\n     * @notice thrown when attempting to act on an unowned asset\n     */\n    error ShardVault__NotOwned();\n\n    /**\n     * @notice thrown when setting a basis point fee value larger than 10000\n     */\n    error ShardVault__BasisExceeded();\n\n    /**\n     * @notice thrown when function called by non-protocol owner\n     */\n    error ShardVault__NotProtocolOwner();\n\n    /**\n     * @notice thrown when function called by non-authorized account\n     */\n    error ShardVault__NotAuthorized();\n\n    /**\n     * @notice thrown when function called by non-shard owner\n     */\n    error ShardVault__NotShardOwner();\n\n    /**\n     * @notice thrown when attempting to borrow after target LTV amount is reached\n     */\n    error ShardVault__TargetLTVReached();\n\n    /**\n     * @notice thrown when attempting to act without being whitelisted\n     */\n    error ShardVault__NotWhitelisted();\n\n    /**\n     * @notice thrown when attempting to call a disabled function\n     */\n    error ShardVault__NotEnabled();\n\n    /**\n     * @notice thrown when attempting to set whitelist deadline without setting reserved shards\n     */\n    error ShardVault__NoReservedShards();\n\n    /**\n     * @notice thrown when user is attempting to deposit after owning (minting) max shards\n     */\n    error ShardVault__MaxMintBalance();\n\n    /**\n     * @notice thrown when caller is not shard collection\n     */\n    error ShardVault__NotShardCollection();\n\n    /**\n     * @notice thrown when the actual downpayment amount is too small\n     */\n    error ShardVault__DownPaymentInsufficient();\n\n    /**\n     * @notice thrown when attempting to claim yield before yield claiming is initialized\n     */\n    error ShardVault__YieldClaimingForbidden();\n\n    /**\n     * @notice thrown when attempting to claim excess ETH after yield claiming is initialized\n     */\n    error ShardVault__ClaimingExcessETHForbidden();\n\n    /**\n     * @notice thrown when attempting to withdraw fees with treasury address == address(0)\n     */\n    error ShardVault__TreasuryIsZeroAddress();\n\n    /**\n     * @notice thrown when attempting to set a reserved supply larger than max supply\n     */\n    error ShardVault__ExceededMaxSupply();\n\n    /**\n     * @notice thrown when setting a max supply which is smaller than total supply\n     */\n    error ShardVault__MaxSupplyTooSmall();\n\n    /**\n     * @notice thrown when attempting to reduce yield fee whilst not owning DawnOfInsrt token used to reduce yield fee\n     */\n    error ShardVault__NotDawnOfInsrtTokenOwner();\n\n    /**\n     * @notice thrown when the purchase of an ERC721Asset via MarketplaceHelper has not lead to the ownership of an ERC721Asset\n     */\n    error ShardVault__ERC721AssetNotRecevied();\n\n    /**\n     * @notice thrown when the vault does not have enough ETH to account for an ETH transfer + respective fee\n     */\n    error ShardVault__InsufficientETH();\n\n    /**\n     * @notice emitted when baseURI is set\n     * @param baseURI the new baseURI for ERC721Metadata\n     */\n    event SetBaseURI(string baseURI);\n\n    /**\n     * @notice emitted when whitelistEndsAt is set\n     * @param whitelistEndsAt the new whitelistEndsAt timestamp\n     */\n    event SetWhitelistEndsAt(uint48 whitelistEndsAt);\n\n    /**\n     * @notice emitted when reservedSupply is set\n     * @param reservedSupply the new reservedSupply\n     */\n    event SetReservedSupply(uint64 reservedSupply);\n\n    /**\n     * @notice emitted when isEnabled is set\n     * @param isEnabled the new isEnabled value\n     */\n    event SetIsEnabled(bool isEnabled);\n\n    /**\n     * @notice emitted when maxMintBalance is set\n     * @param maxMintBalance the new maxMintBalance\n     */\n    event SetMaxMintBalance(uint64 maxMintBalance);\n\n    /**\n     * @notice emitted when maxSupply is set\n     * @param maxSupply the new maxSupply\n     */\n    event SetMaxSupply(uint64 maxSupply);\n\n    /**\n     * @notice emitted when protocol fees are withdrawn\n     * @param feesETH amount of ETH withdrawn as fees\n     * @param feesJPEG amount of JPEG withdrawn as fees\n     */\n    event WithdrawFees(uint256 feesETH, uint256 feesJPEG);\n\n    /**\n     * @notice emitted when sale fee is set\n     * @param feeBP the new sale fee basis points\n     */\n    event SetSaleFee(uint16 feeBP);\n\n    /**\n     * @notice emitted when acquisition fee is set\n     * @param feeBP the new acquisition fee basis points\n     */\n    event SetAcquisitionFee(uint16 feeBP);\n\n    /**\n     * @notice emitted when yield fee is set\n     * @param feeBP the new yield fee basis points\n     */\n    event SetYieldFee(uint16 feeBP);\n\n    /**\n     * @notice emitted when the authorized status of an account is set\n     * @param account address of account\n     * @param isAuthorized authorized status\n     */\n    event SetAuthorized(address account, bool isAuthorized);\n\n    /**\n     * @notice emitted when a punk is purchased by the vault\n     * @param punkId purchased punk id\n     */\n    event PurchasePunk(uint256 punkId);\n\n    /**\n     * @notice emitted when unused ETH is made available to claim\n     */\n    event MakeUnusedETHClaimable();\n\n    /**\n     * @notice emitted when a punk is collateralized for pETH\n     * @param pETH received pETH for collateralization\n     */\n    event CollaterlizePunkPETH(uint256 pETH);\n\n    /**\n     * @notice emitted when an ERC721 asset is collateralized for pETH\n     * @param pETH received pETH for collateralization\n     */\n    event CollateralizeERC721AssetPETH(uint256 pETH);\n\n    /**\n     * @notice emitted when PETH is staked\n     * @param shares lpFarm shares received after 3rd staking stage\n     */\n    event StakePETH(uint256 shares);\n\n    /**\n     * @notice emitted when part of the position in unstaked and a PETH loan is repaid\n     * @param paidDebt amount of PETH debt paid\n     */\n    event RepayLoanPETH(uint256 paidDebt);\n\n    /**\n     * @notice emitted when a direct loan repayment is made\n     * @param token address of JPEG 'stablecoin' used for repayment\n     * @param amount amount of 'stablecoin' repaid\n     * @param punkId id of punk for which debt is reduced\n     */\n    event DirectRepayLoan(address token, uint256 amount, uint256 punkId);\n\n    /**\n     * @notice emitted when a JPEG position of an asset in a PETH vault is closed\n     * @param tokenId id of asset\n     * @param receivedETH ETH received when surplus PETH is converted\n     */\n    event ClosePositionPETH(uint256 tokenId, uint256 receivedETH);\n\n    /**\n     * @notice emitted when a bid is accepted on a punk\n     * @param punkId id of punk\n     */\n    event AccetPunkBid(uint256 punkId);\n\n    /**\n     * @notice emitted when a punk is listed on crypto punk marketplace\n     * @param punkId id of punk\n     */\n    event ListPunk(uint256 punkId);\n\n    /**\n     * @notice emitted when proceeds are received from crypto punk marketplace\n     * @param proceeds amount of ETH received as proceedds\n     */\n    event ReceivePunkProceeds(uint256 proceeds);\n\n    /**\n     * @notice emitted when part of the staked position is unstaked to receive pETH\n     * @param pETH amount of pETH received\n     */\n    event UnstakePETH(uint256 pETH);\n\n    /**\n     * @notice emitted when yield is provided in a PETH vault\n     * @param providedETH amount of ETH provided\n     * @param providedJPEG amount of JPEG provided\n     */\n    event ProvideYieldPETH(uint256 providedETH, uint256 providedJPEG);\n\n    /**\n     * @notice emitted when a new ltvBufferBP value is set\n     * @param ltvBufferBP new value of ltvBufferBP\n     */\n    event SetLtvBufferBP(uint16 ltvBufferBP);\n\n    /**\n     * @notice emitted when a new ltvDeviationBP value is set\n     * @param ltvDeviationBP new value of ltvDeviationBP\n     */\n    event SetLtvDeviationBP(uint16 ltvDeviationBP);\n\n    /**\n     * @notice emitted when an ERC721 is transferred from the treasury to the vault in exchange for ETH\n     * @param tokenId id of ERC721 asset\n     */\n    event TransferERC721AssetOTC(uint256 tokenId);\n\n    /**\n     * @notice emitted when an ERC721 asset is purchased by the vault\n     * @param tokenId id of ERC721 asset\n     */\n    event PurchaseERC721Asset(uint256 tokenId);\n}\n"
      },
      "contracts/shard/ShardVaultAdmin.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { IShardVaultAdmin } from './IShardVaultAdmin.sol';\nimport { ShardVaultInternal } from './ShardVaultInternal.sol';\nimport { ShardVaultStorage } from './ShardVaultStorage.sol';\nimport { IMarketPlaceHelper } from '../helpers/IMarketPlaceHelper.sol';\n\ncontract ShardVaultAdmin is ShardVaultInternal, IShardVaultAdmin {\n    constructor(\n        JPEGParams memory jpegParams,\n        AuxiliaryParams memory auxiliaryParams\n    ) ShardVaultInternal(jpegParams, auxiliaryParams) {}\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function purchasePunk(\n        IMarketPlaceHelper.EncodedCall[] calldata calls,\n        uint256 punkId\n    ) external payable onlyProtocolOwner {\n        _purchasePunk(calls, punkId);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function collateralizePunkPETH(\n        uint256 punkId,\n        uint256 borrowAmount,\n        bool insure\n    ) external onlyAuthorized returns (uint256 pETH) {\n        pETH = _collateralizePunkPETH(punkId, borrowAmount, insure);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function collateralizeERC721AssetPETH(\n        uint256 tokenId,\n        uint256 borrowAmount,\n        bool insure\n    ) external onlyAuthorized returns (uint256 pETH) {\n        pETH = _collateralizeERC721AssetPETH(tokenId, borrowAmount, insure);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function stakePETH(\n        uint256 amount,\n        uint256 minCurveLP,\n        uint256 poolInfoIndex\n    ) external onlyProtocolOwner returns (uint256 shares) {\n        return _stakePETH(amount, minCurveLP, poolInfoIndex);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function setAcquisitionFee(uint16 feeBP) external onlyProtocolOwner {\n        _setAcquisitionFee(feeBP);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function setSaleFee(uint16 feeBP) external onlyProtocolOwner {\n        _setSaleFee(feeBP);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function setYieldFee(uint16 feeBP) external onlyProtocolOwner {\n        _setYieldFee(feeBP);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function setMaxSupply(uint64 maxSupply) external onlyProtocolOwner {\n        _setMaxSupply(maxSupply);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function setWhitelistEndsAt(\n        uint48 whitelistEndsAt\n    ) external onlyProtocolOwner {\n        _setWhitelistEndsAt(whitelistEndsAt);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function setReservedSupply(\n        uint64 reservedSupply\n    ) external onlyProtocolOwner {\n        _setReservedSupply(reservedSupply);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function unstakePETH(\n        uint256 amount,\n        uint256 minPETH,\n        uint256 poolInfoIndex\n    ) external onlyProtocolOwner returns (uint256 pETH) {\n        pETH = _unstakePETH(amount, minPETH, poolInfoIndex);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function setIsEnabled(bool isEnabled) external onlyProtocolOwner {\n        _setIsEnabled(isEnabled);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function initiateWhitelistAndDeposits(\n        uint48 whitelistEndsAt,\n        uint64 reservedSupply\n    ) external onlyProtocolOwner {\n        _setReservedSupply(reservedSupply);\n        _setWhitelistEndsAt(whitelistEndsAt);\n        _setIsEnabled(true);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function closePositionPETH(\n        uint256 tokenId,\n        uint256 minTokenAmount,\n        uint256 poolInfoIndex,\n        uint256 minETH\n    ) external onlyProtocolOwner {\n        _closePositionPETH(tokenId, minTokenAmount, poolInfoIndex, minETH);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function directClosePosition(uint256 tokenId) external onlyProtocolOwner {\n        _directClosePosition(tokenId);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function withdrawFees()\n        external\n        onlyProtocolOwner\n        returns (uint256 feesETH, uint256 feesJPEG)\n    {\n        (feesETH, feesJPEG) = _withdrawFees();\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function setMaxMintBalance(\n        uint64 maxMintBalance\n    ) external onlyProtocolOwner {\n        _setMaxMintBalance(maxMintBalance);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function setAuthorized(\n        address account,\n        bool isAuthorized\n    ) external onlyProtocolOwner {\n        _setAuthorized(account, isAuthorized);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function repayLoanPETH(\n        uint256 amount,\n        uint256 minPETH,\n        uint256 poolInfoIndex,\n        uint256 tokenId\n    ) external onlyAuthorized returns (uint256 paidDebt) {\n        paidDebt = _repayLoanPETH(amount, minPETH, poolInfoIndex, tokenId);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function directRepayLoanPETH(\n        uint256 amount,\n        uint256 tokenId\n    ) external onlyAuthorized {\n        _directRepayLoan(PETH, amount, tokenId);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function listPunk(\n        IMarketPlaceHelper.EncodedCall[] memory calls,\n        uint256 punkId\n    ) external onlyProtocolOwner {\n        _listPunk(calls, punkId);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function stakeCard(uint256 tokenId) external onlyProtocolOwner {\n        _stakeCard(tokenId);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function unstakeCard(uint256 tokenId) external onlyProtocolOwner {\n        _unstakeCard(tokenId);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function provideYieldPETH(\n        uint256 autoComp,\n        uint256 minETH,\n        uint256 poolInfoIndex\n    )\n        external\n        payable\n        onlyProtocolOwner\n        returns (uint256 providedETH, uint256 providedJPEG)\n    {\n        (providedETH, providedJPEG) = _provideYieldPETH(\n            autoComp,\n            minETH,\n            poolInfoIndex\n        );\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function transferCard(\n        uint256 tokenId,\n        address to\n    ) external onlyProtocolOwner {\n        _transferCard(tokenId, to);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function makeUnusedETHClaimable() external onlyProtocolOwner {\n        _makeUnusedETHClaimable();\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function acceptPunkBid(\n        IMarketPlaceHelper.EncodedCall[] memory calls,\n        uint256 punkId\n    ) external onlyProtocolOwner {\n        _acceptPunkBid(calls, punkId);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function setBaseURI(string memory baseURI) external onlyProtocolOwner {\n        _setBaseURI(baseURI);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function setLtvBufferBP(uint16 ltvBufferBP) external onlyProtocolOwner {\n        _setLtvBufferBP(ltvBufferBP);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function setLtvDeviationBP(\n        uint16 ltvDeviationBP\n    ) external onlyProtocolOwner {\n        _setLtvDeviationBP(ltvDeviationBP);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function transferERC721AssetOTC(\n        uint256 tokenId,\n        uint256 price\n    ) external onlyProtocolOwner {\n        _transferERC721AssetOTC(tokenId, price);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function purchaseERC721Asset(\n        IMarketPlaceHelper.EncodedCall[] calldata calls,\n        uint256 tokenId,\n        address purchaseToken,\n        uint256 price\n    ) external onlyProtocolOwner {\n        _purchaseERC721Asset(calls, tokenId, purchaseToken, price);\n    }\n\n    /**\n     * @inheritdoc IShardVaultAdmin\n     */\n    function receivePunkProceeds(\n        IMarketPlaceHelper.EncodedCall[] memory calls,\n        uint256[] memory punkIds\n    ) external onlyProtocolOwner {\n        _receivePunkProceeds(calls, punkIds);\n    }\n}\n"
      },
      "contracts/shard/ShardVaultInternal.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { AddressUtils } from '@solidstate/contracts/utils/AddressUtils.sol';\nimport { EnumerableSet } from '@solidstate/contracts/data/EnumerableSet.sol';\nimport { IERC20 } from '@solidstate/contracts/interfaces/IERC20.sol';\nimport { IERC173 } from '@solidstate/contracts/interfaces/IERC173.sol';\nimport { IERC721 } from '@solidstate/contracts/interfaces/IERC721.sol';\nimport { OwnableInternal } from '@solidstate/contracts/access/ownable/OwnableInternal.sol';\nimport { ERC721BaseInternal } from '@solidstate/contracts/token/ERC721/base/ERC721BaseInternal.sol';\nimport { ERC721EnumerableInternal } from '@solidstate/contracts/token/ERC721/enumerable/ERC721EnumerableInternal.sol';\nimport { ERC721MetadataStorage } from '@solidstate/contracts/token/ERC721/metadata/ERC721MetadataStorage.sol';\n\nimport { IShardVaultInternal } from './IShardVaultInternal.sol';\nimport { ShardVaultStorage } from './ShardVaultStorage.sol';\nimport { ICryptoPunkMarket } from '../interfaces/cryptopunk/ICryptoPunkMarket.sol';\nimport { IStableSwap } from '../interfaces/curve/IStableSwap.sol';\nimport { IJpegCardsCigStaking } from '../interfaces/jpegd/IJpegCardsCigStaking.sol';\nimport { IDawnOfInsrt } from '../interfaces/insrt/IDawnOfInsrt.sol';\nimport { ILPFarming } from '../interfaces/jpegd/ILPFarming.sol';\nimport { INFTEscrow } from '../interfaces/jpegd/INFTEscrow.sol';\nimport { INFTVault } from '../interfaces/jpegd/INFTVault.sol';\nimport { IVault } from '../interfaces/jpegd/IVault.sol';\nimport { IMarketPlaceHelper } from '../helpers/IMarketPlaceHelper.sol';\nimport { IWhitelist } from '../whitelist/IWhitelist.sol';\n\n/**\n * @title Shard Vault internal functions\n * @dev inherited by all Shard Vault implementation contracts\n */\nabstract contract ShardVaultInternal is\n    IShardVaultInternal,\n    OwnableInternal,\n    ERC721BaseInternal,\n    ERC721EnumerableInternal\n{\n    using AddressUtils for address payable;\n    using EnumerableSet for EnumerableSet.UintSet;\n\n    address internal immutable PETH;\n    address internal immutable JPEG;\n    address internal immutable PUNKS;\n    address internal immutable PETH_CITADEL;\n    address internal immutable LP_FARM;\n    address internal immutable CURVE_PETH_POOL;\n    address internal immutable MARKETPLACE_HELPER;\n    address internal immutable JPEG_CARDS_CIG_STAKING;\n    address internal immutable JPEG_CARDS;\n    address internal immutable DAWN_OF_INSRT;\n    address internal immutable TREASURY;\n    uint256 internal constant BASIS_POINTS = 10000;\n    uint256 internal constant CURVE_BASIS = 10000000000;\n    uint256 internal constant CURVE_FEE = 4000000;\n    uint256 internal constant TIER0_FEE_COEFFICIENT = 9000;\n    uint256 internal constant TIER1_FEE_COEFFICIENT = 7500;\n    uint256 internal constant TIER2_FEE_COEFFICIENT = 6000;\n    uint256 internal constant TIER3_FEE_COEFFICIENT = 4000;\n    uint256 internal constant TIER4_FEE_COEFFICIENT = 2000;\n\n    constructor(\n        JPEGParams memory jpegParams,\n        AuxiliaryParams memory auxiliaryParams\n    ) {\n        PETH = jpegParams.PETH;\n        PETH_CITADEL = jpegParams.PETH_CITADEL;\n        LP_FARM = jpegParams.LP_FARM;\n        CURVE_PETH_POOL = jpegParams.CURVE_PETH_POOL;\n        JPEG = jpegParams.JPEG;\n        JPEG_CARDS_CIG_STAKING = jpegParams.JPEG_CARDS_CIG_STAKING;\n        JPEG_CARDS = jpegParams.JPEG_CARDS;\n\n        PUNKS = auxiliaryParams.PUNKS;\n        DAWN_OF_INSRT = auxiliaryParams.DAWN_OF_INSRT;\n        MARKETPLACE_HELPER = auxiliaryParams.MARKETPLACE_HELPER;\n        TREASURY = auxiliaryParams.TREASURY;\n    }\n\n    modifier onlyProtocolOwner() {\n        _onlyProtocolOwner(msg.sender);\n        _;\n    }\n\n    modifier onlyAuthorized() {\n        _onlyAuthorized(msg.sender);\n        _;\n    }\n\n    /**\n     * @notice deposits ETH in exchange for shards\n     * @param data any encoded data required to perform whitelist check\n     */\n    function _deposit(bytes calldata data) internal {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n\n        if (!l.isEnabled) {\n            revert ShardVault__NotEnabled();\n        }\n\n        uint64 maxSupply = l.maxSupply;\n        uint64 maxMintBalance = l.maxMintBalance;\n        uint256 balance = _balanceOf(msg.sender);\n\n        if (balance >= maxMintBalance) {\n            revert ShardVault__MaxMintBalance();\n        }\n\n        if (block.timestamp < l.whitelistEndsAt) {\n            _enforceWhitelist(l.whitelist, msg.sender, data);\n            maxSupply = l.reservedSupply;\n        }\n\n        uint256 amount = msg.value;\n        uint256 shardValue = l.shardValue;\n        uint256 totalSupply = _totalSupply();\n\n        if (amount % shardValue != 0 || amount == 0) {\n            revert ShardVault__InvalidDepositAmount();\n        }\n        if (totalSupply == maxSupply || l.isInvested) {\n            revert ShardVault__DepositForbidden();\n        }\n\n        uint256 shards = amount / shardValue;\n        uint256 excessShards;\n\n        if (balance + shards > maxMintBalance) {\n            excessShards = shards + balance - maxMintBalance;\n            shards -= excessShards;\n        }\n\n        if (shards + totalSupply > maxSupply) {\n            excessShards += shards + totalSupply - maxSupply;\n            shards = maxSupply - totalSupply;\n        }\n\n        unchecked {\n            uint256 count = l.totalMintCount;\n            for (uint256 i = 1; i <= shards; ++i) {\n                _mint(msg.sender, count + i);\n            }\n            l.totalMintCount += uint64(shards);\n        }\n\n        if (excessShards > 0) {\n            payable(msg.sender).sendValue(excessShards * shardValue);\n        }\n    }\n\n    /**\n     * @notice burn held shards before NFT acquisition and withdraw corresponding ETH\n     * @param shardIds list of ids of shards to burn\n     */\n    function _withdraw(uint256[] memory shardIds) internal {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n\n        if (l.isInvested || _totalSupply() == l.maxSupply) {\n            revert ShardVault__WithdrawalForbidden();\n        }\n\n        uint16 shards = uint16(shardIds.length);\n        _enforceSufficientBalance(msg.sender, shards);\n\n        unchecked {\n            for (uint256 i; i < shards; ++i) {\n                uint256 shardId = shardIds[i];\n                _enforceShardOwnership(msg.sender, shardId);\n                _burn(shardId);\n            }\n        }\n\n        payable(msg.sender).sendValue(shards * l.shardValue);\n    }\n\n    /**\n     * @notice purchases a punk from CryptoPunkMarket\n     * @param calls  array of EncodedCall structs containing information to execute necessary low level\n     * calls to purchase a punk\n     * @param punkId id of punk\n     */\n    function _purchasePunk(\n        IMarketPlaceHelper.EncodedCall[] calldata calls,\n        uint256 punkId\n    ) internal {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n\n        if (l.collection != PUNKS) {\n            revert ShardVault__CollectionNotPunks();\n        }\n\n        uint256 price = ICryptoPunkMarket(PUNKS)\n            .punksOfferedForSale(punkId)\n            .minValue;\n\n        IMarketPlaceHelper(l.marketPlaceHelper).purchaseAsset{ value: price }(\n            calls,\n            address(0),\n            price\n        );\n\n        if (l.ownedTokenIds.length() == 0) {\n            l.isInvested = true;\n        }\n        l.accruedFees += (price * l.acquisitionFeeBP) / BASIS_POINTS;\n        l.ownedTokenIds.add(punkId);\n        emit PurchasePunk(punkId);\n    }\n\n    /**\n     * @notice makes the any ETH besides the vault accrued fees claimable\n     */\n    function _makeUnusedETHClaimable() internal {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n        l.cumulativeETHPerShard +=\n            (address(this).balance - l.accruedFees) /\n            _totalSupply();\n\n        emit MakeUnusedETHClaimable();\n    }\n\n    function _collateralizePunkPETH(\n        uint256 punkId,\n        uint256 borrowAmount,\n        bool insure\n    ) internal returns (uint256 pETH) {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n\n        pETH = _collateralizePunk(\n            punkId,\n            borrowAmount,\n            insure,\n            l.jpegdVault,\n            PETH\n        );\n\n        emit CollaterlizePunkPETH(pETH);\n    }\n\n    /**\n     * @notice borrows pETH in exchange for collaterlizing an ERC721 asset\n     * @param tokenId id of ERC721 asset\n     * @param insure whether to insure\n     * @return pETH the amount of pETH received for the collateralized ERC721 asset\n     */\n    function _collateralizeERC721AssetPETH(\n        uint256 tokenId,\n        uint256 borrowAmount,\n        bool insure\n    ) internal returns (uint256 pETH) {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n\n        pETH = _collateralizeERC721Asset(\n            tokenId,\n            borrowAmount,\n            insure,\n            l.jpegdVault,\n            PETH\n        );\n\n        emit CollateralizeERC721AssetPETH(pETH);\n    }\n\n    /**\n     * @notice stakes an amount of pETH into JPEGd autocompounder and then into JPEGd PETH_CITADEL\n     * @param amount amount of pETH to stake\n     * @param minCurveLP minimum LP to receive from pETH staking into curve\n     * @param poolInfoIndex the index of the poolInfo struct in PoolInfo array corresponding to\n     * the pool to deposit into\n     * @return shares deposited into JPEGd autocompounder\n     */\n    function _stakePETH(\n        uint256 amount,\n        uint256 minCurveLP,\n        uint256 poolInfoIndex\n    ) internal returns (uint256 shares) {\n        //pETH is in position 1 in the curve meta pool\n        shares = _stake(\n            amount,\n            minCurveLP,\n            poolInfoIndex,\n            PETH,\n            CURVE_PETH_POOL,\n            PETH_CITADEL,\n            [0, amount]\n        );\n        emit StakePETH(shares);\n    }\n\n    /**\n     * @notice withdraw JPEG and ETH accrued protocol fees, and send to TREASURY address\n     * @return feesETH total ETH fees withdrawn\n     * @return feesJPEG total JPEG fees withdrawn\n     */\n    function _withdrawFees()\n        internal\n        returns (uint256 feesETH, uint256 feesJPEG)\n    {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n\n        feesETH = l.accruedFees;\n        feesJPEG = l.accruedJPEG;\n\n        l.accruedFees -= feesETH;\n        l.accruedJPEG -= feesJPEG;\n\n        IERC20(JPEG).transfer(TREASURY, feesJPEG);\n        payable(TREASURY).sendValue(feesETH);\n        emit WithdrawFees(feesETH, feesJPEG);\n    }\n\n    /**\n     * @notice sets the sale fee BP\n     * @param feeBP basis points value of fee\n     */\n    function _setSaleFee(uint16 feeBP) internal {\n        _enforceBasis(feeBP);\n        ShardVaultStorage.layout().saleFeeBP = feeBP;\n        emit SetSaleFee(feeBP);\n    }\n\n    /**\n     * @notice sets the acquisition fee BP\n     * @param feeBP basis points value of fee\n     */\n    function _setAcquisitionFee(uint16 feeBP) internal {\n        _enforceBasis(feeBP);\n        ShardVaultStorage.layout().acquisitionFeeBP = feeBP;\n        emit SetAcquisitionFee(feeBP);\n    }\n\n    /**\n     * @notice sets the Yield fee BP\n     * @param feeBP basis points value of fee\n     */\n    function _setYieldFee(uint16 feeBP) internal {\n        _enforceBasis(feeBP);\n        ShardVaultStorage.layout().yieldFeeBP = feeBP;\n        emit SetYieldFee(feeBP);\n    }\n\n    /**\n     * @notice grants or revokes the 'authorized' state to an account\n     * @param account address of account to grant/revoke 'authorized'\n     * @param isAuthorized value of 'authorized' state\n     */\n    function _setAuthorized(address account, bool isAuthorized) internal {\n        ShardVaultStorage.layout().authorized[account] = isAuthorized;\n        emit SetAuthorized(account, isAuthorized);\n    }\n\n    /**\n     * @notice unstakes from JPEG'd LPFarming, then from JPEG'd citadel, then from curve LP\n     * @param amount amount of shares of auto-compounder to burn\n     * @param minPETH minimum pETH to receive from curve pool\n     * @param poolInfoIndex the index of the JPEG'd LPFarming pool\n     * @return pETH pETH amount returned\n     */\n    function _unstakePETH(\n        uint256 amount,\n        uint256 minPETH,\n        uint256 poolInfoIndex\n    ) internal returns (uint256 pETH) {\n        //pETH is in position 1 in the curve meta pool\n        pETH = _unstake(\n            amount,\n            minPETH,\n            poolInfoIndex,\n            PETH_CITADEL,\n            CURVE_PETH_POOL,\n            1\n        );\n\n        emit UnstakePETH(pETH);\n    }\n\n    function _unstake(\n        uint256 autoCompAmount,\n        uint256 minTokenAmount,\n        uint256 poolInfoIndex,\n        address citadel,\n        address pool,\n        int128 curveID\n    ) internal returns (uint256 tokenAmount) {\n        ILPFarming(LP_FARM).withdraw(poolInfoIndex, autoCompAmount);\n\n        uint256 curveLP = IVault(citadel).withdraw(\n            address(this),\n            IERC20(ILPFarming(LP_FARM).poolInfo(poolInfoIndex).lpToken)\n                .balanceOf(address(this))\n        );\n\n        tokenAmount = IStableSwap(pool).remove_liquidity_one_coin(\n            curveLP,\n            curveID,\n            minTokenAmount\n        );\n    }\n\n    /**\n     * @notice liquidates all staked tokens in order to pay back loan, retrieves collateralized asset\n     * @param tokenId tokenId pertinent to position\n     * @param minPETH minimum pETH to receive from curveLP after unstake\n     * @param poolInfoIndex index of pool in lpFarming pool array\n     * @param minETH minimum amount of ETH to receive from curveLP after exchange\n     */\n    function _closePositionPETH(\n        uint256 tokenId,\n        uint256 minPETH,\n        uint256 poolInfoIndex,\n        uint256 minETH\n    ) internal {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n\n        uint256 peth = _closePosition(\n            tokenId,\n            minPETH,\n            poolInfoIndex,\n            l.jpegdVault,\n            PETH,\n            PETH_CITADEL,\n            CURVE_PETH_POOL,\n            int128(1)\n        );\n\n        IERC20(PETH).approve(CURVE_PETH_POOL, peth);\n        uint256 eth = IStableSwap(CURVE_PETH_POOL).exchange(\n            int128(1),\n            int128(0),\n            peth,\n            minETH\n        );\n\n        l.cumulativeETHPerShard += eth / _totalSupply();\n        emit ClosePositionPETH(tokenId, eth);\n    }\n\n    /**\n     * @notice retrieves collateralized asset and transfers it to the TREASURY\n     * @notice assumes position has no outstanding debt\n     * @param tokenId tokenId pertinent to position\n     */\n    function _directClosePosition(uint256 tokenId) internal {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n\n        INFTVault(l.jpegdVault).closePosition(tokenId);\n\n        ICryptoPunkMarket(PUNKS).transferPunk(TREASURY, tokenId);\n    }\n\n    /**\n     * @notice lists a punk on CryptoPunk market place using MarketPlaceHelper contract\n     * @param calls encoded call array for listing the punk\n     * @param punkId id of punk to list\n     */\n    function _listPunk(\n        IMarketPlaceHelper.EncodedCall[] memory calls,\n        uint256 punkId\n    ) internal {\n        address marketPlaceHelper = _marketplaceHelper();\n        ICryptoPunkMarket(PUNKS).transferPunk(marketPlaceHelper, punkId);\n        IMarketPlaceHelper(marketPlaceHelper).listAsset(calls);\n        emit ListPunk(punkId);\n    }\n\n    /**\n     * @notice makes a debt payment for a collateralized NFT in jpeg'd\n     * @param amount amount of pETH intended to be repaid\n     * @param minPETH minimum pETH to receive from curveLP\n     * @param poolInfoIndex index of pool in lpFarming pool array\n     * @param tokenId id of token position pertains to\n     * @return paidDebt amount of debt repaid\n     */\n    function _repayLoanPETH(\n        uint256 amount,\n        uint256 minPETH,\n        uint256 poolInfoIndex,\n        uint256 tokenId\n    ) internal returns (uint256 paidDebt) {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n        address jpegdVault = l.jpegdVault;\n\n        uint256 autoComp = _queryAutoCompForPETH(amount);\n        paidDebt = _unstakePETH(autoComp, minPETH, poolInfoIndex);\n\n        if (amount > paidDebt) {\n            revert ShardVault__DownPaymentInsufficient();\n        }\n\n        IERC20(PETH).approve(jpegdVault, paidDebt);\n        INFTVault(jpegdVault).repay(tokenId, paidDebt);\n        emit RepayLoanPETH(paidDebt);\n    }\n\n    /**\n     * @notice makes loan repayment without unstaking\n     * @param token payment token\n     * @param amount payment amount\n     * @param tokenId id of punk\n     */\n    function _directRepayLoan(\n        address token,\n        uint256 amount,\n        uint256 tokenId\n    ) internal {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n\n        IERC20(token).approve(l.jpegdVault, amount);\n        INFTVault(l.jpegdVault).repay(tokenId, amount);\n    }\n\n    /**\n     * @notice accepts a punk bid and withdraws any proceeds generated from punk sales\n     * @dev called from marketPlaceHelper contract to transfer ETH proceeds from punk sale\n     * @param calls encoded calls required to accept bid on an asset\n     * @param punkId id of punk to accept bid on\n     */\n    function _acceptPunkBid(\n        IMarketPlaceHelper.EncodedCall[] memory calls,\n        uint256 punkId\n    ) internal {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n        IMarketPlaceHelper(l.marketPlaceHelper).acceptAssetBid(calls);\n        l.ownedTokenIds.remove(punkId);\n        emit AccetPunkBid(punkId);\n    }\n\n    /**\n     * @notice receives proceeds from punks sold, and removes any required punkIds from ownedTokenIds\n     * @param calls encoded calls required to withdraw proceeds of sold punks\n     * @param punkIds ids of punk to remove\n     */\n    function _receivePunkProceeds(\n        IMarketPlaceHelper.EncodedCall[] memory calls,\n        uint256[] memory punkIds\n    ) internal {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n\n        uint256 proceeds = IMarketPlaceHelper(l.marketPlaceHelper)\n            .forwardSaleProceeds(calls);\n        uint256 saleFee = (proceeds * l.saleFeeBP) / BASIS_POINTS;\n        l.accruedFees += saleFee;\n        l.cumulativeETHPerShard += (proceeds - saleFee) / _totalSupply();\n\n        uint256 idLength = punkIds.length;\n        if (idLength > 0) {\n            unchecked {\n                for (uint256 i; i < idLength; i++) {\n                    l.ownedTokenIds.remove(punkIds[i]);\n                }\n            }\n        }\n\n        emit ReceivePunkProceeds(proceeds);\n    }\n\n    /**\n     * @notice sets the maxSupply of shards\n     * @param maxSupply the maxSupply of shards\n     */\n    function _setMaxSupply(uint64 maxSupply) internal {\n        if (maxSupply < _totalSupply()) {\n            revert ShardVault__MaxSupplyTooSmall();\n        }\n        ShardVaultStorage.layout().maxSupply = maxSupply;\n\n        emit SetMaxSupply(maxSupply);\n    }\n\n    /**\n     * @notice provides yield in the form of ETH and JPEG tokens, by unstaking part of the pETH position to convert to yield,\n     * and claiming pending rewards in LP_FARM to receive JPEG and increasing EPS/JPS respectively\n     * @param autoComp amount of autoComp tokens to unstake\n     * @param minETH minimum ETH to receive after unstaking\n     * @param poolInfoIndex the index of the LP_FARM pool which corresponds to staking PETH-ETH curveLP\n     * @return providedETH total ETH provided as yield\n     * @return providedJPEG total JEPG provided as yield\n     */\n    function _provideYieldPETH(\n        uint256 autoComp,\n        uint256 minETH,\n        uint256 poolInfoIndex\n    ) internal returns (uint256 providedETH, uint256 providedJPEG) {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n\n        providedETH = _unstake(\n            autoComp,\n            minETH,\n            poolInfoIndex,\n            PETH_CITADEL,\n            CURVE_PETH_POOL,\n            int128(0) //ETH index in curve pool\n        );\n\n        providedJPEG = ILPFarming(LP_FARM).pendingReward(\n            poolInfoIndex,\n            address(this)\n        );\n        ILPFarming(LP_FARM).claim(poolInfoIndex);\n\n        if (!l.isYieldClaiming) {\n            l.isYieldClaiming = true;\n        }\n\n        uint256 totalSupply = _totalSupply();\n        l.cumulativeETHPerShard += providedETH / totalSupply;\n        l.cumulativeJPEGPerShard += providedJPEG / totalSupply;\n\n        emit ProvideYieldPETH(providedETH, providedJPEG);\n    }\n\n    /**\n     * @notice sends excess ETH left over after vault has invested, to the msg.sender\n     * @param shardIds array of shard IDs to claim with\n     */\n    function _claimExcessETH(uint256[] memory shardIds) internal {\n        _claimExcessETH(msg.sender, shardIds);\n    }\n\n    /**\n     * @notice sends yield in the form of ETH + JPEG tokens to msg.sender\n     * @param shardIds array of shard IDs to claim with\n     * @param tokenIdDOI Dawn of INSRT token ID used to apply yieldFeeBP discount\n     */\n    function _claimYield(\n        uint256[] memory shardIds,\n        uint256 tokenIdDOI\n    ) internal {\n        _claimYield(msg.sender, shardIds, tokenIdDOI);\n    }\n\n    /**\n     * @notice claim yield/excess ETH upon shard transfer\n     * @dev only SHARD_COLLECTION proxy may call\n     * @param from address transferring\n     * @param to address receiving\n     * @param shardId id of shard being transferred\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 shardId\n    ) internal virtual override {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n\n        uint256[] memory shardIds;\n        uint256[] memory temp = new uint256[](1);\n        temp[0] = shardId;\n        shardIds = temp;\n\n        if (from != address(0)) {\n            if (l.isYieldClaiming) {\n                _claimYield(from, shardIds, type(uint256).max);\n            }\n\n            if (!l.isYieldClaiming && l.isInvested) {\n                _claimExcessETH(from, shardIds);\n            }\n        }\n    }\n\n    /**\n     * @notice sets the whitelistEndsAt timestamp\n     * @param whitelistEndsAt timestamp of whitelist end\n     */\n    function _setWhitelistEndsAt(uint48 whitelistEndsAt) internal {\n        ShardVaultStorage.layout().whitelistEndsAt = whitelistEndsAt;\n        emit SetWhitelistEndsAt(whitelistEndsAt);\n    }\n\n    /**\n     * @notice sets the maximum amount of shard to be minted during whitelist\n     * @param reservedSupply whitelist shard amount\n     */\n    function _setReservedSupply(uint64 reservedSupply) internal {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n\n        if (l.maxSupply < reservedSupply) {\n            revert ShardVault__ExceededMaxSupply();\n        }\n\n        l.reservedSupply = reservedSupply;\n        emit SetReservedSupply(reservedSupply);\n    }\n\n    /**\n     * @notice sets the isEnabled flag\n     * @param isEnabled boolean value\n     */\n    function _setIsEnabled(bool isEnabled) internal {\n        ShardVaultStorage.layout().isEnabled = isEnabled;\n        emit SetIsEnabled(isEnabled);\n    }\n\n    /**\n     * @notice return the maximum shards a user is allowed to mint; theoretically a user may acquire more than this amount via transfers,\n     * but once this amount is exceeded said user may not deposit more\n     * @param maxMintBalance new maxMintBalance value\n     */\n    function _setMaxMintBalance(uint64 maxMintBalance) internal {\n        ShardVaultStorage.layout().maxMintBalance = maxMintBalance;\n        emit SetMaxMintBalance(maxMintBalance);\n    }\n\n    /**\n     * @notice sets a new baseURI for ERC721Metadata\n     * @param baseURI the new baseURI\n     */\n    function _setBaseURI(string memory baseURI) internal {\n        ERC721MetadataStorage.layout().baseURI = baseURI;\n        emit SetBaseURI(baseURI);\n    }\n\n    /**\n     * @notice sets the new value of ltvBufferBP\n     * @param ltvBufferBP new value of ltvBufferBP\n     */\n    function _setLtvBufferBP(uint16 ltvBufferBP) internal {\n        _enforceBasis(ltvBufferBP);\n        ShardVaultStorage.layout().ltvBufferBP = ltvBufferBP;\n        emit SetLtvBufferBP(ltvBufferBP);\n    }\n\n    /**\n     * @notice sets the new value of ltvDeviationBP\n     * @param ltvDeviationBP new value of ltvDeviationBP\n     */\n    function _setLtvDeviationBP(uint16 ltvDeviationBP) internal {\n        _enforceBasis(ltvDeviationBP);\n        ShardVaultStorage.layout().ltvDeviationBP = ltvDeviationBP;\n        emit SetLtvDeviationBP(ltvDeviationBP);\n    }\n\n    /**\n     * @notice stakes a jpeg card\n     * @param tokenId id of card in card collection\n     */\n    function _stakeCard(uint256 tokenId) internal {\n        IERC721(JPEG_CARDS).approve(JPEG_CARDS_CIG_STAKING, tokenId);\n        IJpegCardsCigStaking(JPEG_CARDS_CIG_STAKING).deposit(tokenId);\n    }\n\n    /**\n     * @notice unstakes a jpeg card\n     * @param tokenId id of card in card collection\n     */\n    function _unstakeCard(uint256 tokenId) internal {\n        IJpegCardsCigStaking(JPEG_CARDS_CIG_STAKING).withdraw(tokenId);\n    }\n\n    /**\n     * @notice transfers a jpeg card to an address\n     * @param tokenId id of card in card collection\n     * @param to address to transfer to\n     */\n    function _transferCard(uint256 tokenId, address to) internal {\n        IERC721(JPEG_CARDS).transferFrom(address(this), to, tokenId);\n    }\n\n    /**\n     * @notice transfers an ERC721 asset from the TREASURY in an \"over-the-counter\" (OTC) fashion\n     * @param tokenId id of ERC721 asset to transfer\n     * @param price amount of ETH to send to TREASURY in exchange for ERC721 asset\n     */\n    function _transferERC721AssetOTC(uint256 tokenId, uint256 price) internal {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n\n        IERC721(l.collection).safeTransferFrom(\n            TREASURY,\n            address(this),\n            tokenId\n        );\n\n        uint256 fee = (price * l.acquisitionFeeBP) / BASIS_POINTS;\n        if (fee + price > address(this).balance) {\n            revert ShardVault__InsufficientETH();\n        }\n\n        if (l.ownedTokenIds.length() == 0) {\n            l.isInvested = true;\n        }\n        l.accruedFees += fee;\n        l.ownedTokenIds.add(tokenId);\n\n        payable(TREASURY).sendValue(price);\n\n        emit TransferERC721AssetOTC(tokenId);\n    }\n\n    /**\n     * @notice transfers a specified amount of pETH to the TREASURY\n     * @param amount amount of pETH to transfer\n     */\n    function _transferPETH(uint256 amount) internal {\n        IERC20(PETH).transfer(TREASURY, amount);\n    }\n\n    /**\n     * @notice purhcases an ERC721 asset via MarketplaceHelper\n     * @param calls encoded calls to pass to MarketplaceHelper for ERC721 asset purchase\n     * @param tokenId id of ERC721 asset to purchase\n     * @param purchaseToken address of token used for purchase (normally ETH/WETH)\n     * @param price price in purchaseToken for ERC721 asset purchase\n     */\n    function _purchaseERC721Asset(\n        IMarketPlaceHelper.EncodedCall[] calldata calls,\n        uint256 tokenId,\n        address purchaseToken,\n        uint256 price\n    ) internal {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n        uint256 value;\n\n        if (purchaseToken == address(0)) {\n            value = price;\n        } else {\n            IERC20(purchaseToken).transfer(l.marketPlaceHelper, price);\n        }\n\n        IMarketPlaceHelper(l.marketPlaceHelper).purchaseAsset{ value: value }(\n            calls,\n            purchaseToken,\n            price\n        );\n\n        if (IERC721(l.collection).ownerOf(tokenId) != address(this)) {\n            revert ShardVault__ERC721AssetNotRecevied();\n        }\n\n        // if (l.ownedTokenIds.length() == 0) {\n        //     l.isInvested = true;\n        // }\n        // l.accruedFees += (price * l.acquisitionFeeBP) / BASIS_POINTS;\n        // l.ownedTokenIds.add(tokenId);\n\n        emit PurchaseERC721Asset(tokenId);\n    }\n\n    /**\n     * @notice returns sum of total fees (sale, yield, acquisition) accrued over the entire lifetime of the vault; accounts for fee withdrawals\n     * @return fees accrued fees\n     */\n    function _accruedFees() internal view returns (uint256 fees) {\n        fees = ShardVaultStorage.layout().accruedFees;\n    }\n\n    /**\n     * @notice returns sum of total jpeg due to yield fee accrued over the entire lifetime of the vault\n     * @dev accounts for jpeg withdrawals\n     * @return jpeg accrued jpeg\n     */\n    function _accruedJPEG() internal view returns (uint256 jpeg) {\n        jpeg = ShardVaultStorage.layout().accruedJPEG;\n    }\n\n    /**\n     * @notice returns acquisition fee BP\n     * @return acquisitionFeeBP basis points of acquisition fee\n     */\n    function _acquisitionFeeBP()\n        internal\n        view\n        returns (uint16 acquisitionFeeBP)\n    {\n        acquisitionFeeBP = ShardVaultStorage.layout().acquisitionFeeBP;\n    }\n\n    /**\n     * @notice returns sale fee BP\n     * @return saleFeeBP basis points of sale fee\n     */\n    function _saleFeeBP() internal view returns (uint16 saleFeeBP) {\n        saleFeeBP = ShardVaultStorage.layout().saleFeeBP;\n    }\n\n    /**\n     * @notice returns yield fee BP\n     * @return yieldFeeBP basis points of yield fee\n     */\n    function _yieldFeeBP() internal view returns (uint16 yieldFeeBP) {\n        yieldFeeBP = ShardVaultStorage.layout().yieldFeeBP;\n    }\n\n    /**\n     * @notice return the maximum shards a user is allowed to mint; theoretically a user may acquire more than this amount via transfers,\n     * but once this amount is exceeded said user may not deposit more\n     * @return maxBalance maxMintBalance value\n     */\n    function _maxMintBalance() internal view returns (uint64 maxBalance) {\n        maxBalance = ShardVaultStorage.layout().maxMintBalance;\n    }\n\n    /**\n     * @notice returns vault-wide amount of shards that can still be minted\n     * @return supply amount of shards which can still be minted\n     */\n    function _remainingSupply() internal view returns (uint256 supply) {\n        supply = ShardVaultStorage.layout().maxSupply - _totalSupply();\n    }\n\n    /**\n     * @notice returns the authorized status of an account\n     * @param account address to check status of\n     * @return isAuthorized authorized status of account\n     */\n    function _isAuthorized(\n        address account\n    ) internal view returns (bool isAuthorized) {\n        isAuthorized = ShardVaultStorage.layout().authorized[account];\n    }\n\n    /**\n     * @notice check to ensure account is whitelisted (holding a DAWN_OF_INSRT token or added to optinal mintWhitelist)\n     * @param whitelist address of whitelist contract\n     * @param account address to check\n     * @param data any encoded data required to perform whitelist check\n     */\n    function _enforceWhitelist(\n        address whitelist,\n        address account,\n        bytes calldata data\n    ) internal view {\n        bool isWhitelisted;\n\n        if (\n            IERC721(DAWN_OF_INSRT).balanceOf(account) > 0 ||\n            IWhitelist(whitelist).isWhitelisted(address(this), account, data)\n        ) {\n            isWhitelisted = true;\n        } else {\n            revert ShardVault__NotWhitelisted();\n        }\n    }\n\n    /**\n     * @notice returns address of marketplaceHelper proxy\n     * @return marketplaceHelper address of marketplaceHelper proxy\n     */\n    function _marketplaceHelper()\n        internal\n        view\n        returns (address marketplaceHelper)\n    {\n        marketplaceHelper = ShardVaultStorage.layout().marketPlaceHelper;\n    }\n\n    /**\n     * @notice returns underlying collection address\n     * @return collection address of underlying collection\n     */\n    function _collection() internal view returns (address collection) {\n        collection = ShardVaultStorage.layout().collection;\n    }\n\n    /**\n     * @notice returns underlying jpegdVault address\n     * @return jpegdVault address of underlying jpegdVault\n     */\n    function _jpegdVault() internal view returns (address jpegdVault) {\n        jpegdVault = ShardVaultStorage.layout().jpegdVault;\n    }\n\n    /**\n     * @notice returns the value of the LTV buffer in basis points\n     * @return ltvBufferBP value of LTV buffer in basis points\n     */\n    function _ltvBufferBP() internal view returns (uint16 ltvBufferBP) {\n        ltvBufferBP = ShardVaultStorage.layout().ltvBufferBP;\n    }\n\n    /**\n     * @notice returns the value of the LTV deviation in basis points\n     * @return ltvDeviationBP value of LTV buffer deviation in basis points\n     */\n    function _ltvDeviationBP() internal view returns (uint16 ltvDeviationBP) {\n        ltvDeviationBP = ShardVaultStorage.layout().ltvDeviationBP;\n    }\n\n    /**\n     * @notice returns the JPEG claimed by a given shard\n     * @param shardId id of shard to check\n     * @return claimedJPEGPerShard claimed JPEG for given shard\n     */\n    function _claimedJPEGPerShard(\n        uint256 shardId\n    ) internal view returns (uint256 claimedJPEGPerShard) {\n        claimedJPEGPerShard = ShardVaultStorage.layout().claimedJPEGPerShard[\n            shardId\n        ];\n    }\n\n    /**\n     * @notice returns the ETH claimed by a given shard\n     * @param shardId id of shard to check\n     * @return claimedETHPerShard claimed ETH for given shard\n     */\n    function _claimedETHPerShard(\n        uint256 shardId\n    ) internal view returns (uint256 claimedETHPerShard) {\n        claimedETHPerShard = ShardVaultStorage.layout().claimedETHPerShard[\n            shardId\n        ];\n    }\n\n    /**\n     * @notice returns the cumulative JPEG per shard value\n     * @return cumulativeJPEGPerShard cumulative JPEG per shard value\n     */\n    function _cumulativeJPEGPerShard()\n        internal\n        view\n        returns (uint256 cumulativeJPEGPerShard)\n    {\n        cumulativeJPEGPerShard = ShardVaultStorage\n            .layout()\n            .cumulativeJPEGPerShard;\n    }\n\n    /**\n     * @notice returns the cumulative ETH per shard value\n     * @return cumulativeETHPerShard cumulative ETH per shard value\n     */\n    function _cumulativeETHPerShard()\n        internal\n        view\n        returns (uint256 cumulativeETHPerShard)\n    {\n        cumulativeETHPerShard = ShardVaultStorage\n            .layout()\n            .cumulativeETHPerShard;\n    }\n\n    /**\n     * @notice returns the yield claiming status of the vault\n     * @return isYieldClaiming the yield claiming status of the vault\n     */\n    function _isYieldClaiming() internal view returns (bool isYieldClaiming) {\n        isYieldClaiming = ShardVaultStorage.layout().isYieldClaiming;\n    }\n\n    /**\n     * @notice returns timestamp of whitelist end\n     * @return whitelistEndsAt timestamp of whitelist end\n     */\n    function _whitelistEndsAt() internal view returns (uint48 whitelistEndsAt) {\n        whitelistEndsAt = ShardVaultStorage.layout().whitelistEndsAt;\n    }\n\n    /**\n     * @notice returns treasury address\n     * @return treasury address of treasury\n     */\n    function _treasury() internal view returns (address treasury) {\n        treasury = TREASURY;\n    }\n\n    /**\n     * @notice check to ensure account owns a given shardId corresponding to a shard\n     * @param account address to check\n     * @param shardId shardId to check\n     */\n    function _enforceShardOwnership(\n        address account,\n        uint256 shardId\n    ) internal view {\n        if (account != _ownerOf(shardId)) {\n            revert ShardVault__NotShardOwner();\n        }\n    }\n\n    /**\n     * @notice check to ensure an account has a balance larger than amount\n     * @param account address to check\n     * @param amount amount to check\n     */\n    function _enforceSufficientBalance(\n        address account,\n        uint256 amount\n    ) internal view {\n        if (amount > _balanceOf(account)) {\n            revert ShardVault__InsufficientShards();\n        }\n    }\n\n    /**\n     * @notice check to ensure yield claiming is initialized\n     */\n    function _enforceYieldClaiming() internal view {\n        if (!ShardVaultStorage.layout().isYieldClaiming) {\n            revert ShardVault__YieldClaimingForbidden();\n        }\n    }\n\n    /**\n     * @notice check to ensure yield claiming is not initialized and vault is invested\n     */\n    function _enforceNotYieldClaimingAndInvested() internal view {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n        if (l.isYieldClaiming || !l.isInvested) {\n            revert ShardVault__ClaimingExcessETHForbidden();\n        }\n    }\n\n    /**\n     * @notice returns the isEnabled status of the vault\n     * @return isEnabled status of isEnabled of the vault\n     */\n    function _isEnabled() internal view returns (bool isEnabled) {\n        isEnabled = ShardVaultStorage.layout().isEnabled;\n    }\n\n    /**\n     * @notice returns the address of the whitelist proxy\n     * @return whitelist whitelist proxy address\n     */\n    function _whitelist() internal view returns (address whitelist) {\n        whitelist = ShardVaultStorage.layout().whitelist;\n    }\n\n    function _onlyProtocolOwner(address account) internal view {\n        if (account != _protocolOwner()) {\n            revert ShardVault__NotProtocolOwner();\n        }\n    }\n\n    function _onlyAuthorized(address account) internal view {\n        if (\n            account != _protocolOwner() &&\n            ShardVaultStorage.layout().authorized[account] == false\n        ) {\n            revert ShardVault__NotAuthorized();\n        }\n    }\n\n    /**\n     * @notice returns the protocol owner\n     * @return address of the protocol owner\n     */\n    function _protocolOwner() internal view returns (address) {\n        return IERC173(_owner()).owner();\n    }\n\n    /**\n     * @notice returns maximum possible minted shards\n     * @return maxSupply maximum possible minted shards\n     */\n    function _maxSupply() internal view returns (uint64 maxSupply) {\n        maxSupply = ShardVaultStorage.layout().maxSupply;\n    }\n\n    /**\n     * @notice returns ETH value of a shard\n     * @return shardValue ETH value of a shard\n     */\n    function _shardValue() internal view returns (uint256 shardValue) {\n        shardValue = ShardVaultStorage.layout().shardValue;\n    }\n\n    /**\n     * @notice return isInvested flag state; indicates whether last asset purchase has been made\n     * @return isInvested isInvested flag\n     */\n    function _isInvested() internal view returns (bool isInvested) {\n        isInvested = ShardVaultStorage.layout().isInvested;\n    }\n\n    /**\n     * @notice return amount of shards reserved for whitelist\n     * @return reserverdShards amount of shards reserved for whitelist\n     */\n    function _reservedSupply() internal view returns (uint64 reserverdShards) {\n        reserverdShards = ShardVaultStorage.layout().reservedSupply;\n    }\n\n    /**\n     * @notice return array with owned token IDs\n     * @return ownedTokenIds  array of owned token IDs\n     */\n    function _ownedTokenIds()\n        internal\n        view\n        returns (uint256[] memory ownedTokenIds)\n    {\n        ownedTokenIds = ShardVaultStorage.layout().ownedTokenIds.toArray();\n    }\n\n    /**\n     * @notice applies a discount on yield fee\n     * @param account address to check for discount\n     * @param tokenId Dawn of Insrt token Id\n     * @param rawYieldFeeBP the undiscounted yield fee in basis points\n     */\n    function _discountYieldFeeBP(\n        address account,\n        uint256 tokenId,\n        uint16 rawYieldFeeBP\n    ) internal view returns (uint16 yieldFeeBP) {\n        if (tokenId == type(uint256).max) {\n            yieldFeeBP = rawYieldFeeBP;\n        } else {\n            if (account != IERC721(DAWN_OF_INSRT).ownerOf(tokenId)) {\n                revert ShardVault__NotDawnOfInsrtTokenOwner();\n            }\n            uint8 tier = IDawnOfInsrt(DAWN_OF_INSRT).tokenTier(tokenId);\n\n            uint256 discount;\n            if (tier == 0) {\n                discount = TIER0_FEE_COEFFICIENT;\n            } else if (tier == 1) {\n                discount = TIER1_FEE_COEFFICIENT;\n            } else if (tier == 2) {\n                discount = TIER2_FEE_COEFFICIENT;\n            } else if (tier == 3) {\n                discount = TIER3_FEE_COEFFICIENT;\n            } else {\n                discount = TIER4_FEE_COEFFICIENT;\n            }\n\n            yieldFeeBP = uint16((rawYieldFeeBP * discount) / BASIS_POINTS);\n        }\n    }\n\n    /**\n     * @notice returns amount of AutoComp LP shares needed to be burnt during unstaking\n     * to result in a given amount of pETH\n     * @param pETH desired pETH amount\n     * @return autoComp required AutoComp LP shares\n     */\n    function _queryAutoCompForPETH(\n        uint256 pETH\n    ) internal view returns (uint256 autoComp) {\n        //note: does not account for fees, not meant for precise calculations.\n        //      this is alright because it acts as a small 'buffer' to the amount\n        //      necessary for the downpayment to impact the debt as intended\n        uint256 curveLP = IStableSwap(CURVE_PETH_POOL).calc_token_amount(\n            [0, pETH],\n            false\n        );\n\n        // //note: accounts for fees;\n        uint256 curveLPAccountingFee = (curveLP * CURVE_BASIS) /\n            (CURVE_BASIS - CURVE_FEE);\n\n        autoComp =\n            (curveLPAccountingFee * 10 ** IVault(PETH_CITADEL).decimals()) /\n            IVault(PETH_CITADEL).exchangeRate();\n    }\n\n    /**\n     * @notice returns total debt owed to jpeg'd vault for a given token\n     * @param jpegdVault address of jpeg'd NFT vault\n     * @param tokenId id of token position pertains to\n     * @return debt total debt owed\n     */\n    function _totalDebt(\n        address jpegdVault,\n        uint256 tokenId\n    ) internal view returns (uint256 debt) {\n        debt =\n            INFTVault(jpegdVault).getDebtInterest(tokenId) +\n            INFTVault(jpegdVault).positions(tokenId).debtPrincipal;\n    }\n\n    /**\n     * @notice enforces that a value cannot exceed BASIS_POINTS\n     * @param value the value to check\n     */\n    function _enforceBasis(uint16 value) internal pure {\n        if (value > 10000) revert ShardVault__BasisExceeded();\n    }\n\n    function _collateralizePunk(\n        uint256 punkId,\n        uint256 borrowAmount,\n        bool insure,\n        address jpegdVault,\n        address token\n    ) private returns (uint256 amount) {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n\n        uint256 creditLimit = INFTVault(jpegdVault).getCreditLimit(\n            address(this),\n            punkId\n        );\n\n        uint256 targetLTV = creditLimit -\n            (creditLimit * (l.ltvBufferBP + l.ltvDeviationBP)) /\n            BASIS_POINTS;\n\n        if (INFTVault(jpegdVault).positionOwner(punkId) != address(0)) {\n            uint256 principal = INFTVault(jpegdVault)\n                .positions(punkId)\n                .debtPrincipal;\n            uint256 debtInterest = INFTVault(jpegdVault).getDebtInterest(\n                punkId\n            );\n\n            if (borrowAmount + principal + debtInterest > targetLTV) {\n                if (targetLTV < principal + debtInterest) {\n                    revert ShardVault__TargetLTVReached();\n                }\n                borrowAmount = targetLTV - principal - debtInterest;\n            }\n        } else {\n            if (borrowAmount > targetLTV) {\n                borrowAmount = targetLTV;\n            }\n\n            (, address flashEscrow) = INFTEscrow(l.jpegdVaultHelper).precompute(\n                address(this),\n                punkId\n            );\n            ICryptoPunkMarket(PUNKS).transferPunk(flashEscrow, punkId);\n        }\n\n        uint256 oldBalance = IERC20(token).balanceOf(address(this));\n\n        INFTVault(jpegdVault).borrow(punkId, borrowAmount, insure);\n\n        amount = IERC20(token).balanceOf(address(this)) - oldBalance;\n    }\n\n    function _collateralizeERC721Asset(\n        uint256 tokenId,\n        uint256 borrowAmount,\n        bool insure,\n        address jpegdVault,\n        address token\n    ) private returns (uint256 amount) {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n\n        uint256 creditLimit = INFTVault(jpegdVault).getCreditLimit(\n            address(this),\n            tokenId\n        );\n\n        uint256 targetLTV = creditLimit -\n            (creditLimit * (l.ltvBufferBP + l.ltvDeviationBP)) /\n            BASIS_POINTS;\n\n        if (INFTVault(jpegdVault).positionOwner(tokenId) != address(0)) {\n            uint256 debt = _totalDebt(jpegdVault, tokenId);\n\n            if (borrowAmount + debt > targetLTV) {\n                if (targetLTV < debt) {\n                    revert ShardVault__TargetLTVReached();\n                }\n                borrowAmount = targetLTV - debt;\n            }\n        } else {\n            if (borrowAmount > targetLTV) {\n                borrowAmount = targetLTV;\n            }\n\n            IERC721(l.collection).approve(jpegdVault, tokenId);\n        }\n\n        uint256 oldBalance = IERC20(token).balanceOf(address(this));\n\n        INFTVault(jpegdVault).borrow(tokenId, borrowAmount, insure);\n\n        amount = IERC20(token).balanceOf(address(this)) - oldBalance;\n    }\n\n    function _stake(\n        uint256 amount,\n        uint256 minCurveLP,\n        uint256 poolInfoIndex,\n        address token,\n        address pool,\n        address citadel,\n        uint256[2] memory amounts\n    ) private returns (uint256 shares) {\n        IERC20(token).approve(pool, amount);\n        uint256 curveLP = IStableSwap(pool).add_liquidity(amounts, minCurveLP);\n\n        IERC20(pool).approve(citadel, curveLP);\n        shares = IVault(citadel).deposit(address(this), curveLP);\n\n        IERC20(ILPFarming(LP_FARM).poolInfo(poolInfoIndex).lpToken).approve(\n            LP_FARM,\n            shares\n        );\n\n        ILPFarming(LP_FARM).deposit(poolInfoIndex, shares);\n    }\n\n    /**\n     * @notice liquidates all staked tokens in order to pay back loan, retrieves collateralized asset\n     * @param tokenId tokenId pertinent to position\n     * @param minTokenAmount minimum token (pETH/pUSD) to receive from curveLP\n     * @param poolInfoIndex index of pool in lpFarming pool array\n     * @param jpegdVault address of jpeg'd NFT Vault\n     * @param token address of PETH or PUSD\n     * @param citadel address of jpeg citadel\n     * @param pool address of Curve pool\n     * @param curveID curve pool index of token to receive\n     * @return surplus amount of PETH/PUSD left over after paying outstanding debt\n     */\n    function _closePosition(\n        uint256 tokenId,\n        uint256 minTokenAmount,\n        uint256 poolInfoIndex,\n        address jpegdVault,\n        address token,\n        address citadel,\n        address pool,\n        int128 curveID\n    ) private returns (uint256 surplus) {\n        uint256 debt = _totalDebt(jpegdVault, tokenId);\n\n        uint256 tokenAmount = _unstake(\n            _queryAutoCompForPETH(debt),\n            minTokenAmount,\n            poolInfoIndex,\n            citadel,\n            pool,\n            curveID\n        );\n\n        IERC20(token).approve(jpegdVault, debt);\n        INFTVault(jpegdVault).repay(tokenId, debt);\n        INFTVault(jpegdVault).closePosition(tokenId);\n\n        surplus = tokenAmount - debt;\n    }\n\n    /**\n     * @notice sends excess ETH left over after vault has invested\n     * @param account address making the claim\n     * @param shardIds array of shard IDs to claim with\n     */\n    function _claimExcessETH(\n        address account,\n        uint256[] memory shardIds\n    ) private {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n\n        uint256 tokens = shardIds.length;\n\n        _enforceNotYieldClaimingAndInvested();\n        _enforceSufficientBalance(account, tokens);\n\n        uint256 cumulativeETHPerShard = l.cumulativeETHPerShard;\n        uint256 totalETH;\n        uint256 claimedETHPerShard;\n\n        unchecked {\n            for (uint256 i; i < tokens; ++i) {\n                uint256 shardId = shardIds[i];\n                _enforceShardOwnership(account, shardId);\n\n                claimedETHPerShard =\n                    cumulativeETHPerShard -\n                    l.claimedETHPerShard[shardId];\n                totalETH += claimedETHPerShard;\n                l.claimedETHPerShard[shardId] += claimedETHPerShard;\n            }\n        }\n\n        payable(account).sendValue(totalETH);\n    }\n\n    /**\n     * @notice sends yield in the form of ETH + JPEG tokens to account\n     * @param account address making the yield claim\n     * @param shardIds array of shard IDs to claim with\n     * @param tokenIdDOI Dawn of INSRT token ID used to apply yieldFeeBP discount\n     */\n    function _claimYield(\n        address account,\n        uint256[] memory shardIds,\n        uint256 tokenIdDOI\n    ) private {\n        ShardVaultStorage.Layout storage l = ShardVaultStorage.layout();\n\n        uint256 tokens = shardIds.length;\n\n        _enforceYieldClaiming();\n        _enforceSufficientBalance(account, tokens);\n\n        //parameters for ETH claiming\n        uint256 cumulativeETHPerShard = l.cumulativeETHPerShard;\n        uint256 totalETH;\n        uint256 claimedETHPerShard;\n        //parameters for JPEG claiming\n        uint256 cumulativeJPEGPerShard = l.cumulativeJPEGPerShard;\n        uint256 totalJPEG;\n        uint256 claimedJPEGPerShard;\n\n        unchecked {\n            for (uint256 i; i < tokens; ++i) {\n                uint256 shardId = shardIds[i];\n                _enforceShardOwnership(account, shardId);\n\n                //account for claimable ETH\n                claimedETHPerShard =\n                    cumulativeETHPerShard -\n                    l.claimedETHPerShard[shardId];\n                totalETH += claimedETHPerShard;\n                l.claimedETHPerShard[shardId] += claimedETHPerShard;\n\n                //account for claimable JPEG\n                claimedJPEGPerShard =\n                    cumulativeJPEGPerShard -\n                    l.claimedJPEGPerShard[shardId];\n                totalJPEG += claimedJPEGPerShard;\n                l.claimedJPEGPerShard[shardId] += claimedJPEGPerShard;\n            }\n        }\n\n        uint16 yieldFeeBP = _discountYieldFeeBP(\n            account,\n            tokenIdDOI,\n            l.yieldFeeBP\n        );\n\n        //apply fees\n        uint256 ETHfee = (totalETH * yieldFeeBP) / BASIS_POINTS;\n        l.accruedFees += ETHfee;\n\n        uint256 jpegFee = (totalJPEG * yieldFeeBP) / BASIS_POINTS;\n        l.accruedJPEG += jpegFee;\n\n        //transfer yield\n        IERC20(JPEG).transfer(account, totalJPEG - jpegFee);\n        payable(account).sendValue(totalETH - ETHfee);\n    }\n}\n"
      },
      "contracts/shard/ShardVaultStorage.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { EnumerableSet } from '@solidstate/contracts/data/EnumerableSet.sol';\n\nlibrary ShardVaultStorage {\n    struct Layout {\n        uint256 shardValue;\n        uint256 accruedFees;\n        uint256 accruedJPEG;\n        uint256 cumulativeETHPerShard;\n        uint256 cumulativeJPEGPerShard;\n        mapping(uint256 => uint256) claimedETHPerShard;\n        mapping(uint256 => uint256) claimedJPEGPerShard;\n        address collection;\n        uint48 whitelistEndsAt;\n        uint16 saleFeeBP;\n        uint16 acquisitionFeeBP;\n        uint16 yieldFeeBP;\n        uint64 maxSupply;\n        uint64 maxMintBalance;\n        uint64 reservedSupply;\n        uint16 ltvBufferBP;\n        uint16 ltvDeviationBP;\n        bool isInvested;\n        bool isEnabled;\n        bool isPUSDVault; //unused\n        bool isYieldClaiming;\n        address marketPlaceHelper;\n        address jpegdVault;\n        address jpegdVaultHelper;\n        address jpegdLP;\n        EnumerableSet.UintSet ownedTokenIds;\n        mapping(address => bool) authorized;\n        uint64 totalMintCount;\n        address whitelist;\n    }\n\n    bytes32 internal constant STORAGE_SLOT =\n        keccak256('insrt.contracts.storage.ShardVault');\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"
      },
      "contracts/whitelist/IWhitelist.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity ^0.8.0;\n\nimport { ISafeOwnable } from '@solidstate/contracts/access/ownable/ISafeOwnable.sol';\n\n/**\n * @title General whitelist interface for Insrt product instances\n */\ninterface IWhitelist is ISafeOwnable {\n    /**\n     * @notice returns whitelisted state of a given account for an Insrt product instance (eg ShardVault)\n     * @param instance address of Insrt product instance\n     * @param account account to check whitelisted state for\n     * @param data any encoded data required to perform whitelist check\n     * @return isWhitelisted whitelist state of account for given Insrt product instance\n     */\n    function isWhitelisted(\n        address instance,\n        address account,\n        bytes calldata data\n    ) external view returns (bool isWhitelisted);\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "viaIR": true,
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}