{{
  "language": "Solidity",
  "sources": {
    "contracts/vault/AssetVault.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.18;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC721/utils/ERC721HolderUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC1155/utils/ERC1155HolderUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\n\nimport \"../interfaces/IAssetVault.sol\";\nimport \"../interfaces/ICallDelegator.sol\";\nimport \"../external/interfaces/IPunks.sol\";\nimport \"../external/interfaces/ISuperRareV1.sol\";\n\nimport \"./CallWhitelistDelegation.sol\";\nimport \"./CallWhitelistApprovals.sol\";\nimport \"./OwnableERC721.sol\";\n\nimport {\n    AV_WithdrawsDisabled,\n    AV_WithdrawsEnabled,\n    AV_AlreadyInitialized,\n    AV_MissingAuthorization,\n    AV_NonWhitelistedCall,\n    AV_NonWhitelistedApproval,\n    AV_TooManyItems,\n    AV_LengthMismatch,\n    AV_ZeroAddress,\n    AV_NonWhitelistedDelegation\n} from \"../errors/Vault.sol\";\n\n/**\n * @title AssetVault\n * @author Non-Fungible Technologies, Inc.\n *\n * The Asset Vault is a vault for the storage of collateralized assets.\n * Designed for one-time use, like a piggy bank. Once withdrawals are enabled,\n * and the bank is broken, the vault can no longer be used or transferred.\n *\n * It starts in a deposit-only state. Funds cannot be withdrawn at this point. When\n * the owner calls \"enableWithdraw()\", the state is set to a withdrawEnabled state.\n * Withdraws cannot be disabled once enabled. This restriction protects integrations\n * and purchasers of AssetVaults from unexpected withdrawal and frontrunning attacks.\n * For example: someone buys an AV assuming it contains token X, but I withdraw token X\n * immediately before the sale concludes.\n *\n * @dev Asset Vaults support arbitrary external calls by either:\n *     - the current owner of the vault\n *     - someone who the current owner \"delegates\" through the ICallDelegator interface\n *\n * This is to enable airdrop claims by borrowers during loans and other forms of NFT utility.\n * In practice, LoanCore delegates to the borrower during the period of an open loan.\n * Arcade.xyz maintains an allowed and restricted list of calls to balance between utility and security.\n *\n * Implementation warning: AssetVault is an OwnableERC721, which means that ownership of this contract\n * is tracked by a separate ERC721 contract defined by calling `_setNFT()`. In the current implementation,\n * the deployer is the VaultFactory, an ERC721 contract whose token ownership corresponds to vault ownership.\n * If this contract is modified or extended, or the deployer of a given AssetVault is not an ERC721 contract,\n * ownership will not work as intended.\n */\ncontract AssetVault is\n    IAssetVault,\n    OwnableERC721,\n    Initializable,\n    ERC1155HolderUpgradeable,\n    ERC721HolderUpgradeable,\n    ReentrancyGuardUpgradeable\n{\n    using AddressUpgradeable for address;\n    using AddressUpgradeable for address payable;\n    using SafeERC20Upgradeable for IERC20Upgradeable;\n\n    // ============================================ STATE ==============================================\n\n    /// @notice True if withdrawals are allowed out of this vault.\n    /// @dev Note once set to true, it cannot be reverted back to false.\n    bool public override withdrawEnabled;\n\n    /// @notice Whitelist contract to determine if a given external call is allowed.\n    address public override whitelist;\n\n    /// @notice The maximum number of items that can be withdrawn from a vault at once.\n    uint256 public constant MAX_WITHDRAW_ITEMS = 25;\n\n    // ========================================== CONSTRUCTOR ===========================================\n\n    /**\n     * @dev Initializes values so initialize cannot be called on template.\n     */\n    constructor() {\n        withdrawEnabled = true;\n        OwnableERC721._setNFT(msg.sender);\n    }\n\n    // ========================================== INITIALIZER ===========================================\n\n    /**\n     * @notice Initializes the contract, used on clone deployments. In practice,\n     *         always called by the VaultFactory contract.\n     *\n     * @param _whitelist            The contract maintaining the whitelist of allowed\n     *                              arbitrary calls.\n     */\n    function initialize(address _whitelist) external override initializer {\n        if (withdrawEnabled || ownershipToken != address(0)) revert AV_AlreadyInitialized(ownershipToken);\n        // set ownership to inherit from the factory who deployed us\n        // The factory should have a tokenId == uint256(address(this))\n        // whose owner has ownership control over this contract\n        OwnableERC721._setNFT(msg.sender);\n        whitelist = _whitelist;\n\n        __ReentrancyGuard_init();\n    }\n\n    // ========================================= VIEW FUNCTIONS =========================================\n\n    /**\n     * @inheritdoc OwnableERC721\n     */\n    function owner() public view override returns (address ownerAddress) {\n        return OwnableERC721.owner();\n    }\n\n    // ===================================== WITHDRAWAL OPERATIONS ======================================\n\n    /**\n     * @notice Enables withdrawals on the vault. Irreversible. Caller must be the\n     *         owner of the underlying ownership NFT.\n     *\n     * @dev Any integration should be aware that a withdraw-enabled vault cannot\n     *      be transferred (will revert).\n     *\n     */\n    function enableWithdraw() external override onlyOwner onlyWithdrawDisabled {\n        withdrawEnabled = true;\n        emit WithdrawEnabled(msg.sender);\n    }\n\n    /**\n     * @notice Withdraw entire balance of a given ERC20 token from the vault.\n     *         The vault must be in a \"withdrawEnabled\" state (non-transferrable),\n     *         and the caller must be the owner.\n     *\n     * @param token                 The ERC20 token to withdraw.\n     * @param to                    The recipient of the withdrawn funds.\n     */\n    function withdrawERC20(address token, address to) external override onlyOwner onlyWithdrawEnabled {\n        if (to == address(0)) revert AV_ZeroAddress(\"to\");\n\n        uint256 balance = IERC20(token).balanceOf(address(this));\n        IERC20Upgradeable(token).safeTransfer(to, balance);\n        emit WithdrawERC20(msg.sender, token, to, balance);\n    }\n\n    /**\n     * @notice Withdraw a specific ERC721 token from the vault. The vault must\n     *         be in a \"withdrawEnabled\" state (non-transferrable), and the caller\n     *         must be the owner. The specified token must exist and be owned by\n     *         this contract.\n     *\n     * @param token                 The token to withdraw.\n     * @param tokenId               The ID of the NFT to withdraw.\n     * @param to                    The recipient of the withdrawn token.\n     */\n    function withdrawERC721(\n        address token,\n        uint256 tokenId,\n        address to\n    ) external override onlyOwner onlyWithdrawEnabled {\n        _withdrawERC721(token, tokenId, to);\n    }\n\n    /**\n     * @notice Withdraw entire balance of a given ERC1155 token from the vault.\n     *         The vault must be in a \"withdrawEnabled\" state (non-transferrable),\n     *         and the caller must be the owner.\n     *\n     * @param token                 The ERC1155 token to withdraw.\n     * @param tokenId               The ID of the token to withdraw.\n     * @param to                    The recipient of the withdrawn funds.\n     */\n    function withdrawERC1155(\n        address token,\n        uint256 tokenId,\n        address to\n    ) external override onlyOwner onlyWithdrawEnabled {\n        _withdrawERC1155(token, tokenId, to);\n    }\n\n    /**\n     * @notice Batch withdraw assets from the vault. The vault must be in a\n     *         \"withdrawEnabled\" state (non-transferrable), and the caller must\n     *         be the owner.\n     *\n     * @dev This function is used to withdraw multiple ERC721 and ERC1155 tokens\n     *      from the vault. The caller must specify the token type (ERC721 or\n     *      ERC1155) and the token ID for each token to withdraw. The caller\n     *      must also specify the recipient of the withdrawal. Refer to the\n     *      MAX_WITHDRAW_ITEMS state constant for the maximum number of vault\n     *      items that can be withdrawn per function call.\n     *\n     * @param tokens                An array of tokens address to withdraw.\n     * @param tokenIds              An array of tokenIds to withdraw.\n     * @param tokenTypes            An arrary of token types to withdraw.\n     * @param to                    The recipient of the withdrawn tokens.\n     */\n    // solhint-disable-next-line code-complexity\n    function withdrawBatch(\n        address[] calldata tokens,\n        uint256[] calldata tokenIds,\n        TokenType[] calldata tokenTypes,\n        address to\n    ) external override onlyOwner onlyWithdrawEnabled {\n        uint256 tokensLength = tokens.length;\n        if (tokensLength > MAX_WITHDRAW_ITEMS) revert AV_TooManyItems(tokensLength);\n        if (tokensLength != tokenIds.length) revert AV_LengthMismatch(\"tokenId\");\n        if (tokensLength != tokenTypes.length) revert AV_LengthMismatch(\"tokenType\");\n\n        for (uint256 i = 0; i < tokensLength;) {\n            if (tokens[i] == address(0)) revert AV_ZeroAddress(\"token\");\n\n            if (tokenTypes[i] == TokenType.ERC721) {\n                _withdrawERC721(tokens[i], tokenIds[i], to);\n            } else {\n                _withdrawERC1155(tokens[i], tokenIds[i], to);\n            }\n\n            // Can never overflow because length is bounded by MAX_WITHDRAW_ITEMS\n            unchecked {\n                i++;\n            }\n        }\n    }\n\n    /**\n     * @notice Withdraw entire balance of ETH from the vault.\n     *         The vault must be in a \"withdrawEnabled\" state (non-transferrable),\n     *         and the caller must be the owner.\n     *\n     * @param to                    The recipient of the withdrawn funds.\n     */\n    function withdrawETH(address to) external override onlyOwner onlyWithdrawEnabled nonReentrant {\n        if (to == address(0)) revert AV_ZeroAddress(\"to\");\n\n        // perform transfer\n        uint256 balance = address(this).balance;\n        // sendValue() internally uses call() which passes along all of\n        // the remaining gas, potentially introducing an attack vector\n        payable(to).sendValue(balance);\n        emit WithdrawETH(msg.sender, to, balance);\n    }\n\n    /**\n     * @notice Withdraw cryptoPunk from the vault.\n     *         The vault must be in a \"withdrawEnabled\" state (non-transferrable),\n     *         and the caller must be the owner.\n     *\n     * @param punks                 The CryptoPunk contract address.\n     * @param punkIndex             The index of the CryptoPunk to withdraw (i.e. token ID).\n     * @param to                    The recipient of the withdrawn punk.\n     */\n    function withdrawPunk(\n        address punks,\n        uint256 punkIndex,\n        address to\n    ) external override onlyOwner onlyWithdrawEnabled {\n        if (to == address(0)) revert AV_ZeroAddress(\"to\");\n\n        IPunks(punks).transferPunk(to, punkIndex);\n        emit WithdrawPunk(msg.sender, punks, to, punkIndex);\n    }\n\n    /**\n     * @notice Withdraw SuperRare V1 from the vault.\n     *         Vault must have withdraw enabled.\n     *         Caller must be owner.\n     *\n     * @param superRareV1           SuperRare V1 contract address\n     * @param tokenId               tokenId to withdraw\n     * @param to                    recipient of the token\n     */\n    function withdrawSuperRareV1(\n        address superRareV1,\n        uint256 tokenId,\n        address to\n    ) external override onlyOwner onlyWithdrawEnabled {\n        if (to == address(0)) revert AV_ZeroAddress(\"to\");\n\n        ISuperRareV1(superRareV1).transfer(to, tokenId);\n        emit WithdrawSuperRareV1(msg.sender, superRareV1, to, tokenId);\n    }\n\n    // ====================================== UTILITY OPERATIONS ========================================\n\n    /**\n     * @notice Call a function on an external contract. Intended for claiming airdrops\n     *         and other forms of NFT utility. All allowed calls are whitelist by the\n     *         \"whitelist\" contract. The vault must have withdrawals disabled, and the caller\n     *         must either be the owner, or the owner must have explicitly\n     *         delegated this ability to the caller through ICallDelegator interface.\n     *\n     * @param to                    The contract address to call.\n     * @param data                  The data to call the contract with.\n     */\n    function call(\n        address to,\n        bytes calldata data\n    ) external override onlyAllowedCallers onlyWithdrawDisabled nonReentrant {\n        if (!ICallWhitelist(whitelist).isWhitelisted(to, bytes4(data[:4]))) {\n            revert AV_NonWhitelistedCall(to, bytes4(data[:4]));\n        }\n\n        to.functionCall(data);\n\n        emit Call(msg.sender, to, data);\n    }\n\n    /**\n     * @notice Approve a token for spending by an external contract. Note that any token\n     *         approved in the whitelist does not make good collateral, because the allowed\n     *         spender may be able to withdraw it from the vault.\n     *\n     * @param token                 The token to approve.\n     * @param spender               The approved spender.\n     * @param amount                The amount to approve.\n     */\n    function callApprove(\n        address token,\n        address spender,\n        uint256 amount\n    ) external override onlyAllowedCallers onlyWithdrawDisabled nonReentrant {\n        if (!CallWhitelistApprovals(whitelist).isApproved(token, spender)) {\n            revert AV_NonWhitelistedApproval(token, spender);\n        }\n\n        // Do approval\n        IERC20Upgradeable(token).safeApprove(spender, amount);\n\n        emit Approve(msg.sender, token, spender, amount);\n    }\n\n    /**\n     * @notice Increase token allowance for spending by an external contract. Note that any\n     *         token approved in the whitelist does not make good collateral, because the\n     *         allowed spender may be able to withdraw it from the vault.\n     *\n     * @param token                 The token to approve.\n     * @param spender               The approved spender.\n     * @param amount                The amount to increase allowance by.\n     */\n    function callIncreaseAllowance(\n        address token,\n        address spender,\n        uint256 amount\n    ) external override onlyAllowedCallers onlyWithdrawDisabled nonReentrant {\n        if (!CallWhitelistApprovals(whitelist).isApproved(token, spender)) {\n            revert AV_NonWhitelistedApproval(token, spender);\n        }\n\n        // increase spender allowance\n        IERC20Upgradeable(token).safeIncreaseAllowance(spender, amount);\n\n        emit IncreaseAllowance(msg.sender, token, spender, amount);\n    }\n\n    /**\n     * @notice Decrease token allowance for spending by an external contract. Note that any\n     *         token approved in the whitelist does not make good collateral, because the\n     *         allowed spender may be able to withdraw it from the vault.\n     *\n     * @param token                 The token to approve.\n     * @param spender               The approved spender.\n     * @param amount                The amount to decrease allowance by.\n     */\n    function callDecreaseAllowance(\n        address token,\n        address spender,\n        uint256 amount\n    ) external override onlyAllowedCallers onlyWithdrawDisabled nonReentrant {\n        if (!CallWhitelistApprovals(whitelist).isApproved(token, spender)) {\n            revert AV_NonWhitelistedApproval(token, spender);\n        }\n\n        // decrease spender allowance\n        IERC20Upgradeable(token).safeDecreaseAllowance(spender, amount);\n\n        emit DecreaseAllowance(msg.sender, token, spender, amount);\n    }\n\n    /**\n     * @notice Delegate a token held by the vault to an external contract. This token must\n     *         be whitelisted for delegation by the CallWhitelistDelegation contract. This\n     *         will grant delegation powers for all tokens within this contract held by the vault.\n     *\n     * @param token                 The token to delegate.\n     * @param target                The address to delegate to (the hot wallet).\n     * @param enable                Whether to enable or disable delegation.\n     */\n    function callDelegateForContract(\n        address token,\n        address target,\n        bool enable\n    ) external override onlyAllowedCallers onlyWithdrawDisabled nonReentrant {\n        if (!CallWhitelistDelegation(whitelist).isDelegationApproved(token)) {\n            revert AV_NonWhitelistedDelegation(token);\n        }\n\n        // Do delegation\n        CallWhitelistDelegation(whitelist).registry().delegateForContract(target, token, enable);\n\n        emit DelegateContract(msg.sender, token, target, enable);\n    }\n\n    /**\n     * @notice Delegate a specific tokenId held by the vault to an external contract. This token must\n     *         be whitelisted for delegation by the CallWhitelistDelegation contract. This\n     *         will grant delegation powers for only the specified tokenId within the token.\n     *\n     * @param token                 The token to delegate.\n     * @param target                The address to delegate to (the hot wallet).\n     * @param tokenId               The token ID to delegate.\n     * @param enable                Whether to enable or disable delegation.\n     */\n    function callDelegateForToken(\n        address token,\n        address target,\n        uint256 tokenId,\n        bool enable\n    ) external override onlyAllowedCallers onlyWithdrawDisabled nonReentrant {\n        if (!CallWhitelistDelegation(whitelist).isDelegationApproved(token)) {\n            revert AV_NonWhitelistedDelegation(token);\n        }\n\n        // Do delegation\n        CallWhitelistDelegation(whitelist).registry().delegateForToken(target, token, tokenId, enable);\n\n        emit DelegateToken(msg.sender, token, target, tokenId, enable);\n    }\n\n    /**\n     * @notice Revoke all delegations the vault has granted to an external contract. For individual\n     *         revocations per-contract and perToken, use callDelegateForContract and callDelegateForToken\n     *         with enabled set to false.\n     */\n     function callRevokeAllDelegates() external override onlyAllowedCallers onlyWithdrawDisabled nonReentrant {\n        CallWhitelistDelegation(whitelist).registry().revokeAllDelegates();\n\n        emit DelegateRevoke(msg.sender);\n     }\n\n    // ============================================ HELPERS =============================================\n\n    /**\n     * @dev Private function to withdraw a ERC721 token from the vault.\n     *\n     * @param token                 The token to withdraw.\n     * @param tokenId               The ID of the NFT to withdraw.\n     * @param to                    The recipient of the withdrawn token.\n     */\n    function _withdrawERC721(\n        address token,\n        uint256 tokenId,\n        address to\n    ) private {\n        if (to == address(0)) revert AV_ZeroAddress(\"to\");\n\n        IERC721Upgradeable(token).safeTransferFrom(address(this), to, tokenId);\n\n        emit WithdrawERC721(msg.sender, token, to, tokenId);\n    }\n\n    /**\n     * @dev Private function to withdraw ERC1155 tokens from the vault.\n     *\n     * @param token                 The token to withdraw.\n     * @param tokenId               The ID of the token to withdraw.\n     * @param to                    The recipient of the withdrawn funds.\n     */\n    function _withdrawERC1155(\n        address token,\n        uint256 tokenId,\n        address to\n    ) private {\n        if (to == address(0)) revert AV_ZeroAddress(\"to\");\n\n        uint256 balance = IERC1155(token).balanceOf(address(this), tokenId);\n        IERC1155Upgradeable(token).safeTransferFrom(address(this), to, tokenId, balance, \"\");\n\n        emit WithdrawERC1155(msg.sender, token, to, tokenId, balance);\n    }\n\n    /**\n     * @dev For any utility function, check whether the caller is the owner or has been\n     *      approved via the ICallDelegator interface by the owner.\n     */\n    modifier onlyAllowedCallers() {\n        if (msg.sender != owner() && !ICallDelegator(owner()).canCallOn(msg.sender, address(this))) {\n            revert AV_MissingAuthorization(msg.sender);\n        }\n\n        _;\n    }\n\n    /**\n     * @dev For methods only callable with withdraws enabled (all withdrawal operations).\n     */\n    modifier onlyWithdrawEnabled() {\n        if (!withdrawEnabled) revert AV_WithdrawsDisabled();\n        _;\n    }\n\n    /**\n     * @dev For methods only callable with withdraws disabled (call operations and enabling withdraws).\n     */\n    modifier onlyWithdrawDisabled() {\n        if (withdrawEnabled) revert AV_WithdrawsEnabled();\n        _;\n    }\n\n    /**\n     * @dev Fallback \"receive Ether\" function. Contract can hold Ether\n     *      which can be accessed using withdrawETH.\n     */\n    receive() external payable {}\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165Upgradeable.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721Upgradeable is IERC165Upgradeable {\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in ``owner``'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external;\n\n    /**\n     * @dev Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the caller.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool _approved) external;\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes calldata data\n    ) external;\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155Upgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165Upgradeable.sol\";\n\n/**\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155Upgradeable is IERC165Upgradeable {\n    /**\n     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\n     */\n    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\n\n    /**\n     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\n     * transfers.\n     */\n    event TransferBatch(\n        address indexed operator,\n        address indexed from,\n        address indexed to,\n        uint256[] ids,\n        uint256[] values\n    );\n\n    /**\n     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\n     * `approved`.\n     */\n    event ApprovalForAll(address indexed account, address indexed operator, bool approved);\n\n    /**\n     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\n     *\n     * If an {URI} event was emitted for `id`, the standard\n     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\n     * returned by {IERC1155MetadataURI-uri}.\n     */\n    event URI(string value, uint256 indexed id);\n\n    /**\n     * @dev Returns the amount of tokens of token type `id` owned by `account`.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function balanceOf(address account, uint256 id) external view returns (uint256);\n\n    /**\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\n     *\n     * Requirements:\n     *\n     * - `accounts` and `ids` must have the same length.\n     */\n    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\n        external\n        view\n        returns (uint256[] memory);\n\n    /**\n     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\n     *\n     * Emits an {ApprovalForAll} event.\n     *\n     * Requirements:\n     *\n     * - `operator` cannot be the caller.\n     */\n    function setApprovalForAll(address operator, bool approved) external;\n\n    /**\n     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\n     *\n     * See {setApprovalForAll}.\n     */\n    function isApprovedForAll(address account, address operator) external view returns (bool);\n\n    /**\n     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n     *\n     * Emits a {TransferSingle} event.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.\n     * - `from` must have a balance of tokens of type `id` of at least `amount`.\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n     * acceptance magic value.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 id,\n        uint256 amount,\n        bytes calldata data\n    ) external;\n\n    /**\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\n     *\n     * Emits a {TransferBatch} event.\n     *\n     * Requirements:\n     *\n     * - `ids` and `amounts` must have the same length.\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n     * acceptance magic value.\n     */\n    function safeBatchTransferFrom(\n        address from,\n        address to,\n        uint256[] calldata ids,\n        uint256[] calldata amounts,\n        bytes calldata data\n    ) external;\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n    using AddressUpgradeable for address;\n\n    function safeTransfer(\n        IERC20Upgradeable token,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(\n        IERC20Upgradeable token,\n        address from,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(\n        IERC20Upgradeable token,\n        address spender,\n        uint256 value\n    ) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    function safeIncreaseAllowance(\n        IERC20Upgradeable token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(\n        IERC20Upgradeable token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        if (returndata.length > 0) {\n            // Return data is optional\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/token/ERC721/utils/ERC721HolderUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721ReceiverUpgradeable.sol\";\nimport \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC721Receiver} interface.\n *\n * Accepts all token transfers.\n * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or {IERC721-setApprovalForAll}.\n */\ncontract ERC721HolderUpgradeable is Initializable, IERC721ReceiverUpgradeable {\n    function __ERC721Holder_init() internal initializer {\n        __ERC721Holder_init_unchained();\n    }\n\n    function __ERC721Holder_init_unchained() internal initializer {\n    }\n    /**\n     * @dev See {IERC721Receiver-onERC721Received}.\n     *\n     * Always returns `IERC721Receiver.onERC721Received.selector`.\n     */\n    function onERC721Received(\n        address,\n        address,\n        uint256,\n        bytes memory\n    ) public virtual override returns (bytes4) {\n        return this.onERC721Received.selector;\n    }\n    uint256[50] private __gap;\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/token/ERC1155/utils/ERC1155HolderUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./ERC1155ReceiverUpgradeable.sol\";\nimport \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ncontract ERC1155HolderUpgradeable is Initializable, ERC1155ReceiverUpgradeable {\n    function __ERC1155Holder_init() internal initializer {\n        __ERC165_init_unchained();\n        __ERC1155Receiver_init_unchained();\n        __ERC1155Holder_init_unchained();\n    }\n\n    function __ERC1155Holder_init_unchained() internal initializer {\n    }\n    function onERC1155Received(\n        address,\n        address,\n        uint256,\n        uint256,\n        bytes memory\n    ) public virtual override returns (bytes4) {\n        return this.onERC1155Received.selector;\n    }\n\n    function onERC1155BatchReceived(\n        address,\n        address,\n        uint256[] memory,\n        uint256[] memory,\n        bytes memory\n    ) public virtual override returns (bytes4) {\n        return this.onERC1155BatchReceived.selector;\n    }\n    uint256[50] private __gap;\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     */\n    bool private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Modifier to protect an initializer function from being invoked twice.\n     */\n    modifier initializer() {\n        require(_initializing || !_initialized, \"Initializable: contract is already initialized\");\n\n        bool isTopLevelCall = !_initializing;\n        if (isTopLevelCall) {\n            _initializing = true;\n            _initialized = true;\n        }\n\n        _;\n\n        if (isTopLevelCall) {\n            _initializing = false;\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal initializer {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal initializer {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and make it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        // On the first call to nonReentrant, _notEntered will be true\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n\n        _;\n\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n    uint256[49] private __gap;\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize, which returns 0 for contracts in\n        // construction, since the code is only stored at the end of the\n        // constructor execution.\n\n        uint256 size;\n        assembly {\n            size := extcodesize(account)\n        }\n        return size > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCall(target, data, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        require(isContract(target), \"Address: call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            // Look for revert reason and bubble it up if present\n            if (returndata.length > 0) {\n                // The easiest way to bubble the revert reason is using memory via assembly\n\n                assembly {\n                    let returndata_size := mload(returndata)\n                    revert(add(32, returndata), returndata_size)\n                }\n            } else {\n                revert(errorMessage);\n            }\n        }\n    }\n}\n"
    },
    "contracts/interfaces/IAssetVault.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.18;\n\ninterface IAssetVault {\n    // ============= Enums ==============\n\n    enum TokenType { ERC721, ERC1155 }\n\n    // ============= Events ==============\n\n    event WithdrawEnabled(address operator);\n    event WithdrawERC20(address indexed operator, address indexed token, address recipient, uint256 amount);\n    event WithdrawERC721(address indexed operator, address indexed token, address recipient, uint256 tokenId);\n    event WithdrawPunk(address indexed operator, address indexed token, address recipient, uint256 tokenId);\n    event WithdrawSuperRareV1(address indexed operator, address indexed token, address recipient, uint256 tokenId);\n\n    event WithdrawERC1155(\n        address indexed operator,\n        address indexed token,\n        address recipient,\n        uint256 tokenId,\n        uint256 amount\n    );\n\n    event WithdrawETH(address indexed operator, address indexed recipient, uint256 amount);\n    event Call(address indexed operator, address indexed to, bytes data);\n    event Approve(address indexed operator, address indexed token, address indexed spender, uint256 amount);\n    event IncreaseAllowance(address indexed operator, address indexed token, address indexed spender, uint256 amount);\n    event DecreaseAllowance(address indexed operator, address indexed token, address indexed spender, uint256 amount);\n    event DelegateContract(address indexed operator, address indexed token, address indexed target, bool enabled);\n    event DelegateToken(address indexed operator, address indexed token, address indexed target, uint256 tokenId, bool enabled);\n    event DelegateRevoke(address indexed operator);\n\n    // ================= Initializer ==================\n\n    function initialize(address _whitelist) external;\n\n    // ================ View Functions ================\n\n    function withdrawEnabled() external view returns (bool);\n\n    function whitelist() external view returns (address);\n\n    // ================ Withdrawal Operations ================\n\n    function enableWithdraw() external;\n\n    function withdrawERC20(address token, address to) external;\n\n    function withdrawERC721(\n        address token,\n        uint256 tokenId,\n        address to\n    ) external;\n\n    function withdrawERC1155(\n        address token,\n        uint256 tokenId,\n        address to\n    ) external;\n\n    function withdrawBatch(\n        address[] calldata tokens,\n        uint256[] calldata tokenIds,\n        TokenType[] calldata tokenTypes,\n        address to\n    ) external;\n\n    function withdrawETH(address to) external;\n\n    function withdrawPunk(\n        address punks,\n        uint256 punkIndex,\n        address to\n    ) external;\n\n    function withdrawSuperRareV1(\n        address superRareV1,\n        uint256 tokenId,\n        address to\n    ) external;\n\n    // ================ Utility Operations ================\n\n    function call(address to, bytes memory data) external;\n\n    function callApprove(address token, address spender, uint256 amount) external;\n\n    function callIncreaseAllowance(address token, address spender, uint256 amount) external;\n\n    function callDecreaseAllowance(address token, address spender, uint256 amount) external;\n\n    function callDelegateForContract(address token, address target, bool enable) external;\n\n    function callDelegateForToken(address token, address target, uint256 tokenId, bool enable) external;\n\n    function callRevokeAllDelegates() external;\n}\n"
    },
    "contracts/interfaces/ICallDelegator.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.18;\n\ninterface ICallDelegator {\n    // ============== View Functions ==============\n\n    function canCallOn(address caller, address vault) external view returns (bool);\n}\n"
    },
    "contracts/external/interfaces/IPunks.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.18;\n\ninterface IPunks {\n    function balanceOf(address owner) external view returns (uint256);\n\n    function punkIndexToAddress(uint256 punkIndex) external view returns (address owner);\n\n    function buyPunk(uint256 punkIndex) external;\n\n    function transferPunk(address to, uint256 punkIndex) external;\n}\n"
    },
    "contracts/external/interfaces/ISuperRareV1.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.18;\n\ninterface ISuperRareV1 {\n    function balanceOf(address _owner) external view returns (uint256 _balance);\n\n    function ownerOf(uint256 _tokenId) external view returns (address _owner);\n\n    function transfer(address _to, uint256 _tokenId) external;\n\n    function approve(address _to, uint256 _tokenId) external;\n\n    function takeOwnership(uint256 _tokenId) external;\n}"
    },
    "contracts/vault/CallWhitelistDelegation.sol": {
      "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.18;\n\nimport \"../external/interfaces/IDelegationRegistry.sol\";\n\nimport \"./CallWhitelist.sol\";\n\nimport { CWD_RegistryAlreadySet, CWD_ZeroAddress } from \"../errors/Vault.sol\";\n\n/**\n * @title CallWhitelistDelegation\n * @author Non-Fungible Technologies, Inc.\n *\n * Adds delegation functionality to CallWhitelist, allowing the\n * whitelist manager to decide which collections can be used with\n * the DelegateCash registry. Each token should be considered for\n * possible implications of delegation before adding to the whitelist.\n *\n * If a token is on the whitelist, delegateForContract and delegateForToken\n * will be enabled for that token.\n *\n * WARNING: adding these functions to the core CallWhitelist whitelist will bypass\n * the delegation functions that check the whitelist for which tokens can\n * be delegated. The whitelist manager should take care not to use both the core\n * whitelist for delegation as well as the delegation whitelist.\n */\ncontract CallWhitelistDelegation is CallWhitelist {\n    event DelegationSet(address indexed caller, address indexed token, bool isApproved);\n    event RegistryChanged(address indexed caller, address indexed registry);\n\n    // ============================================ STATE ==============================================\n\n    // ================= Whitelist State ==================\n\n    /// @notice Tokens approved for delegation.\n    /// @dev    token -> isApproved\n    mapping(address => bool) private delegationApproved;\n\n    /// @notice The delegation registry for the whitelist.\n    IDelegationRegistry public registry;\n\n    // ========================================== CONSTRUCTOR ===========================================\n\n    /**\n     * @dev Initializes values so initialize cannot be called on template.\n     */\n    constructor(address _registry) {\n        if (_registry == address(0)) revert CWD_ZeroAddress();\n\n        registry = IDelegationRegistry(_registry);\n    }\n\n    // ========================================= VIEW FUNCTIONS =========================================\n\n    /**\n     * @notice Returns true if the given spender is approved to spend the given token.\n     *\n     * @param token                     The token approval to check.\n     *\n     * @return isDelegationApproved     True if the token can be delegated, else false.\n     */\n    function isDelegationApproved(address token) public view returns (bool) {\n        return delegationApproved[token];\n    }\n\n    // ======================================== UPDATE OPERATIONS =======================================\n\n    /**\n     * @notice Sets approval status of a given token for a spender. Note that this is\n     *         NOT a token approval - it is permission to register a delegation from\n     *         the vault.\n     *\n     * @param token                The token approval to set.\n     * @param _isApproved          Whether the token should be approved.\n     */\n    function setDelegationApproval(address token, bool _isApproved) external onlyRole(WHITELIST_MANAGER_ROLE) {\n        delegationApproved[token] = _isApproved;\n\n        emit DelegationSet(msg.sender, token, _isApproved);\n    }\n\n    /**\n     * @notice Sets the registry for the whitelist. Should only be used in case\n     *         of delegate cash migration to new registry.\n     *\n     * @param _registry             The new registry.\n     */\n    function setRegistry(address _registry) external onlyRole(ADMIN_ROLE) {\n        if (address(registry) == _registry) revert CWD_RegistryAlreadySet();\n\n        registry = IDelegationRegistry(_registry);\n\n        emit RegistryChanged(msg.sender, _registry);\n    }\n}\n"
    },
    "contracts/vault/CallWhitelistApprovals.sol": {
      "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.18;\n\nimport \"./CallWhitelist.sol\";\n\n/**\n * @title CallWhitelistApprovals\n * @author Non-Fungible Technologies, Inc.\n *\n * Adds approvals functionality to CallWhitelist. Certain spenders\n * can be approved for tokens on vaults, with the requisite ability\n * to withdraw. Should not be used for tokens acting as collateral.\n *\n * The contract owner can add or remove approved token/spender pairs.\n */\ncontract CallWhitelistApprovals is CallWhitelist {\n    event ApprovalSet(address indexed caller, address indexed token, address indexed spender, bool isApproved);\n\n    // ============================================ STATE ==============================================\n\n    // ================= Whitelist State ==================\n\n    /// @notice Approved spenders of vault tokens.\n    /// @dev    token -> spender -> isApproved\n    mapping(address => mapping(address => bool)) private approvals;\n\n    /**\n     * @notice Returns true if the given spender is approved to spend the given token.\n     *\n     * @param token                The token approval to check.\n     * @param spender              The token spender.\n     *\n     * @return isApproved          True if approved, else false.\n     */\n    function isApproved(address token, address spender) public view returns (bool) {\n        return approvals[token][spender];\n    }\n\n    // ======================================== UPDATE OPERATIONS =======================================\n\n    /**\n     * @notice Sets approval status of a given token for a spender. Note that this is\n     *         NOT a token approval - it is permission to create a token approval from\n     *         the asset vault.\n     *\n     * @param token                The token approval to set.\n     * @param spender              The token spender.\n     * @param _isApproved          Whether the spender should be approved.\n     */\n    function setApproval(address token, address spender, bool _isApproved) external onlyRole(WHITELIST_MANAGER_ROLE) {\n        approvals[token][spender] = _isApproved;\n        emit ApprovalSet(msg.sender, token, spender, _isApproved);\n    }\n}\n"
    },
    "contracts/vault/OwnableERC721.sol": {
      "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.18;\n\nimport \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\n\nimport { OERC721_CallerNotOwner } from \"../errors/Vault.sol\";\n\n/**\n * @title OwnableERC721\n * @author Non-Fungible Technologies, Inc.\n *\n * Uses ERC721 ownership for access control to a set of contracts.\n * Ownership of underlying contract determined by ownership of a token ID,\n * where the token ID converts to an on-chain address.\n */\nabstract contract OwnableERC721 {\n    event SetOwnershipToken(address indexed caller, address indexed ownershipToken);\n\n    // ============================================ STATE ==============================================\n\n    /// @dev The ERC721 token that contract owners should have ownership of.\n    address public ownershipToken;\n\n    // ========================================= VIEW FUNCTIONS =========================================\n\n    /**\n     * @notice Specifies the owner of the underlying token ID, derived\n     *         from the contract address of the contract implementing.\n     *\n     * @return ownerAddress         The owner of the underlying token derived from\n     *                              the calling address.\n     */\n    function owner() public view virtual returns (address ownerAddress) {\n        return IERC721(ownershipToken).ownerOf(uint256(uint160(address(this))));\n    }\n\n    // ============================================ HELPERS =============================================\n\n    /**\n     * @dev Set the ownership token - the ERC721 that specified who controls\n     *      defined addresses.\n     *\n     * @param _ownershipToken       The address of the ERC721 token that defines ownership.\n     */\n    function _setNFT(address _ownershipToken) internal {\n        ownershipToken = _ownershipToken;\n\n        emit SetOwnershipToken(msg.sender, _ownershipToken);\n    }\n\n    /**\n     * @dev Similar to Ownable - checks the method is being called by the owner,\n     *      where the owner is defined by the token ID in the ownership token which\n     *      maps to the calling contract address.\n     */\n    modifier onlyOwner() {\n        if (owner() != msg.sender) revert OERC721_CallerNotOwner(msg.sender);\n        _;\n    }\n}\n"
    },
    "contracts/errors/Vault.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.18;\n\n/**\n * @title VaultErrors\n * @author Non-Fungible Technologies, Inc.\n *\n * This file contains all custom errors for vault contracts used by the protocol.\n * All errors prefixed by the contract that throws them (e.g., \"AV_\" for Asset Vault).\n * Errors located in one place to make it possible to holistically look at all\n * asset vault failure cases.\n */\n\n// ==================================== Asset Vault ======================================\n/// @notice All errors prefixed with AV_, to separate from other contracts in the protocol.\n\n/**\n * @notice Vault withdraws must be enabled.\n */\nerror AV_WithdrawsDisabled();\n\n/**\n * @notice Vault withdraws enabled.\n */\nerror AV_WithdrawsEnabled();\n\n/**\n * @notice Asset vault already initialized.\n *\n * @param ownershipToken                    Caller of initialize function in asset vault contract.\n */\nerror AV_AlreadyInitialized(address ownershipToken);\n\n/**\n * @notice CanCallOn authorization returned false.\n *\n * @param caller                             Msg.sender of the function call.\n */\nerror AV_MissingAuthorization(address caller);\n\n/**\n * @notice Call disallowed.\n *\n * @param to                                The contract address to call.\n * @param data                              The data to call the contract with.\n */\nerror AV_NonWhitelistedCall(address to, bytes4 data);\n\n/**\n * @notice Approval disallowed.\n *\n * @param token                             The token to approve.\n * @param spender                           The spender to approve.\n */\nerror AV_NonWhitelistedApproval(address token, address spender);\n\n/**\n * @notice Cannot withdraw more than 25 items from a vault at a time.\n *\n * @param arrayLength                  Total elements provided.\n */\nerror AV_TooManyItems(uint256 arrayLength);\n\n/**\n * @notice The length of either the tokenIds or tokenTypes array does not match\n *         the length of the tokenAddress array.\n *\n * @param arrayType                    Array type that does not match tokenAddress array length.\n */\nerror AV_LengthMismatch(string arrayType);\n\n/**\n * @notice Zero address passed in where not allowed.\n *\n * @param addressType                  The name of the parameter for which a zero address was provided.\n */\nerror AV_ZeroAddress(string addressType);\n\n/**\n * @notice Delegation disallowed.\n *\n * @param token                             The token to delegate.\n */\nerror AV_NonWhitelistedDelegation(address token);\n\n// ==================================== Ownable ERC721 ======================================\n/// @notice All errors prefixed with OERC721_, to separate from other contracts in the protocol.\n\n/**\n * @notice Function caller is not the owner.\n *\n * @param caller                             Msg.sender of the function call.\n */\nerror OERC721_CallerNotOwner(address caller);\n\n// ==================================== Vault Factory ======================================\n/// @notice All errors prefixed with VF_, to separate from other contracts in the protocol.\n\n/**\n * @notice Zero address passed in where not allowed.\n *\n * @param addressType                  The name of the parameter for which a zero address was provided.\n */\nerror VF_ZeroAddress(string addressType);\n\n/**\n * @notice Global index out of bounds.\n *\n * @param tokenId                            AW-V2 tokenId of the asset vault.\n */\nerror VF_TokenIdOutOfBounds(uint256 tokenId);\n\n/**\n * @notice Cannot transfer with withdraw enabled.\n *\n * @param tokenId                            AW-V2 tokenId of the asset vault.\n */\nerror VF_NoTransferWithdrawEnabled(uint256 tokenId);\n\n/**\n * @notice Not enough msg.value sent for the required mint fee.\n *\n * @param value                              The msg.value.\n * @param requiredMintFee                    The required mint fee.\n */\nerror VF_InsufficientMintFee(uint256 value, uint256 requiredMintFee);\n\n/**\n * @notice Non-existant token id provided as argument.\n *\n * @param tokenId                       The ID of the token to lookup the URI for.\n */\nerror VF_DoesNotExist(uint256 tokenId);\n\n// ================================== Call Whitelist ======================================\n/// @notice All errors prefixed with CW_, to separate from other contracts in the protocol.\n\n/**\n * @notice Cannot whitelist a call which has already been whitelisted.\n *\n * @param callee                             The contract to be added to CallWhitelist mapping.\n * @param selector                           The function selector to be added to CallWhitelist mapping.\n */\nerror CW_AlreadyWhitelisted(address callee, bytes4 selector);\n\n/**\n * @notice Cannot remove a call from the CallWhitelist that has not yet been added.\n *\n * @param callee                             The contract to be removed from CallWhitelist mapping.\n * @param selector                           The function selector to be removed from CallWhitelist mapping.\n */\nerror CW_NotWhitelisted(address callee, bytes4 selector);\n\n// ================================== Call Whitelist Delegation ======================================\n\n/**\n * @notice Zero address passed in the constructor.\n */\nerror CWD_ZeroAddress();\n\n/**\n * @notice The registry address provided is currently set as the registry.\n */\nerror CWD_RegistryAlreadySet();\n\n"
    },
    "@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165Upgradeable {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) external returns (bool);\n\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721ReceiverUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721ReceiverUpgradeable {\n    /**\n     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n     * by `operator` from `from`, this function is called.\n     *\n     * It must return its Solidity selector to confirm the token transfer.\n     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n     *\n     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.\n     */\n    function onERC721Received(\n        address operator,\n        address from,\n        uint256 tokenId,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/token/ERC1155/utils/ERC1155ReceiverUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC1155ReceiverUpgradeable.sol\";\nimport \"../../../utils/introspection/ERC165Upgradeable.sol\";\nimport \"../../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\nabstract contract ERC1155ReceiverUpgradeable is Initializable, ERC165Upgradeable, IERC1155ReceiverUpgradeable {\n    function __ERC1155Receiver_init() internal initializer {\n        __ERC165_init_unchained();\n        __ERC1155Receiver_init_unchained();\n    }\n\n    function __ERC1155Receiver_init_unchained() internal initializer {\n    }\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165Upgradeable) returns (bool) {\n        return interfaceId == type(IERC1155ReceiverUpgradeable).interfaceId || super.supportsInterface(interfaceId);\n    }\n    uint256[50] private __gap;\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/token/ERC1155/IERC1155ReceiverUpgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165Upgradeable.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155ReceiverUpgradeable is IERC165Upgradeable {\n    /**\n        @dev Handles the receipt of a single ERC1155 token type. This function is\n        called at the end of a `safeTransferFrom` after the balance has been updated.\n        To accept the transfer, this must return\n        `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n        (i.e. 0xf23a6e61, or its own function selector).\n        @param operator The address which initiated the transfer (i.e. msg.sender)\n        @param from The address which previously owned the token\n        @param id The ID of the token being transferred\n        @param value The amount of tokens being transferred\n        @param data Additional data with no specified format\n        @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n    */\n    function onERC1155Received(\n        address operator,\n        address from,\n        uint256 id,\n        uint256 value,\n        bytes calldata data\n    ) external returns (bytes4);\n\n    /**\n        @dev Handles the receipt of a multiple ERC1155 token types. This function\n        is called at the end of a `safeBatchTransferFrom` after the balances have\n        been updated. To accept the transfer(s), this must return\n        `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n        (i.e. 0xbc197c81, or its own function selector).\n        @param operator The address which initiated the batch transfer (i.e. msg.sender)\n        @param from The address which previously owned the token\n        @param ids An array containing ids of each token being transferred (order and length must match values array)\n        @param values An array containing amounts of each token being transferred (order and length must match ids array)\n        @param data Additional data with no specified format\n        @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n    */\n    function onERC1155BatchReceived(\n        address operator,\n        address from,\n        uint256[] calldata ids,\n        uint256[] calldata values,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n"
    },
    "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165Upgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {\n    function __ERC165_init() internal initializer {\n        __ERC165_init_unchained();\n    }\n\n    function __ERC165_init_unchained() internal initializer {\n    }\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IERC165Upgradeable).interfaceId;\n    }\n    uint256[50] private __gap;\n}\n"
    },
    "contracts/external/interfaces/IDelegationRegistry.sol": {
      "content": "// SPDX-License-Identifier: CC0-1.0\n\npragma solidity 0.8.18;\n\n/**\n * @notice Sourced from:\n * https://docs.delegate.cash/delegatecash/technical-documentation/delegation-registry/idelegationregistry.sol\n */\n\n/**\n * @title An immutable registry contract to be deployed as a standalone primitive\n * @dev See EIP-5639, new project launches can read previous cold wallet -> hot wallet delegations\n *      from here and integrate those permissions into their flow\n */\ninterface IDelegationRegistry {\n    /// @notice Delegation type\n    enum DelegationType {\n        NONE,\n        ALL,\n        CONTRACT,\n        TOKEN\n    }\n\n    /// @notice Info about a single delegation, used for onchain enumeration\n    struct DelegationInfo {\n        DelegationType type_;\n        address vault;\n        address delegate;\n        address contract_;\n        uint256 tokenId;\n    }\n\n    /// @notice Info about a single contract-level delegation\n    struct ContractDelegation {\n        address contract_;\n        address delegate;\n    }\n\n    /// @notice Info about a single token-level delegation\n    struct TokenDelegation {\n        address contract_;\n        uint256 tokenId;\n        address delegate;\n    }\n\n    /// @notice Emitted when a user delegates their entire wallet\n    event DelegateForAll(address vault, address delegate, bool value);\n\n    /// @notice Emitted when a user delegates a specific contract\n    event DelegateForContract(address vault, address delegate, address contract_, bool value);\n\n    /// @notice Emitted when a user delegates a specific token\n    event DelegateForToken(address vault, address delegate, address contract_, uint256 tokenId, bool value);\n\n    /// @notice Emitted when a user revokes all delegations\n    event RevokeAllDelegates(address vault);\n\n    /// @notice Emitted when a user revoes all delegations for a given delegate\n    event RevokeDelegate(address vault, address delegate);\n\n    /**\n     * -----------  WRITE -----------\n     */\n\n    /**\n     * @notice Allow the delegate to act on your behalf for all contracts\n     * @param delegate The hotwallet to act on your behalf\n     * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking\n     */\n    function delegateForAll(address delegate, bool value) external;\n\n    /**\n     * @notice Allow the delegate to act on your behalf for a specific contract\n     * @param delegate The hotwallet to act on your behalf\n     * @param contract_ The address for the contract you're delegating\n     * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking\n     */\n    function delegateForContract(address delegate, address contract_, bool value) external;\n\n    /**\n     * @notice Allow the delegate to act on your behalf for a specific token\n     * @param delegate The hotwallet to act on your behalf\n     * @param contract_ The address for the contract you're delegating\n     * @param tokenId The token id for the token you're delegating\n     * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking\n     */\n    function delegateForToken(address delegate, address contract_, uint256 tokenId, bool value) external;\n\n    /**\n     * @notice Revoke all delegates\n     */\n    function revokeAllDelegates() external;\n\n    /**\n     * @notice Revoke a specific delegate for all their permissions\n     * @param delegate The hotwallet to revoke\n     */\n    function revokeDelegate(address delegate) external;\n\n    /**\n     * @notice Remove yourself as a delegate for a specific vault\n     * @param vault The vault which delegated to the msg.sender, and should be removed\n     */\n    function revokeSelf(address vault) external;\n\n    /**\n     * -----------  READ -----------\n     */\n\n    /**\n     * @notice Returns all active delegations a given delegate is able to claim on behalf of\n     * @param delegate The delegate that you would like to retrieve delegations for\n     * @return info Array of DelegationInfo structs\n     */\n    function getDelegationsByDelegate(address delegate) external view returns (DelegationInfo[] memory);\n\n    /**\n     * @notice Returns an array of wallet-level delegates for a given vault\n     * @param vault The cold wallet who issued the delegation\n     * @return addresses Array of wallet-level delegates for a given vault\n     */\n    function getDelegatesForAll(address vault) external view returns (address[] memory);\n\n    /**\n     * @notice Returns an array of contract-level delegates for a given vault and contract\n     * @param vault The cold wallet who issued the delegation\n     * @param contract_ The address for the contract you're delegating\n     * @return addresses Array of contract-level delegates for a given vault and contract\n     */\n    function getDelegatesForContract(address vault, address contract_) external view returns (address[] memory);\n\n    /**\n     * @notice Returns an array of contract-level delegates for a given vault's token\n     * @param vault The cold wallet who issued the delegation\n     * @param contract_ The address for the contract holding the token\n     * @param tokenId The token id for the token you're delegating\n     * @return addresses Array of contract-level delegates for a given vault's token\n     */\n    function getDelegatesForToken(address vault, address contract_, uint256 tokenId)\n        external\n        view\n        returns (address[] memory);\n\n    /**\n     * @notice Returns all contract-level delegations for a given vault\n     * @param vault The cold wallet who issued the delegations\n     * @return delegations Array of ContractDelegation structs\n     */\n    function getContractLevelDelegations(address vault)\n        external\n        view\n        returns (ContractDelegation[] memory delegations);\n\n    /**\n     * @notice Returns all token-level delegations for a given vault\n     * @param vault The cold wallet who issued the delegations\n     * @return delegations Array of TokenDelegation structs\n     */\n    function getTokenLevelDelegations(address vault) external view returns (TokenDelegation[] memory delegations);\n\n    /**\n     * @notice Returns true if the address is delegated to act on the entire vault\n     * @param delegate The hotwallet to act on your behalf\n     * @param vault The cold wallet who issued the delegation\n     */\n    function checkDelegateForAll(address delegate, address vault) external view returns (bool);\n\n    /**\n     * @notice Returns true if the address is delegated to act on your behalf for a token contract or an entire vault\n     * @param delegate The hotwallet to act on your behalf\n     * @param contract_ The address for the contract you're delegating\n     * @param vault The cold wallet who issued the delegation\n     */\n    function checkDelegateForContract(address delegate, address vault, address contract_)\n        external\n        view\n        returns (bool);\n\n    /**\n     * @notice Returns true if the address is delegated to act on your behalf for a specific token, the token's contract or an entire vault\n     * @param delegate The hotwallet to act on your behalf\n     * @param contract_ The address for the contract you're delegating\n     * @param tokenId The token id for the token you're delegating\n     * @param vault The cold wallet who issued the delegation\n     */\n    function checkDelegateForToken(address delegate, address vault, address contract_, uint256 tokenId)\n        external\n        view\n        returns (bool);\n}\n"
    },
    "contracts/vault/CallWhitelist.sol": {
      "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.18;\n\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/access/AccessControlEnumerable.sol\";\n\nimport \"../interfaces/ICallWhitelist.sol\";\n\nimport \"./CallBlacklist.sol\";\n\nimport {\n    CW_AlreadyWhitelisted,\n    CW_NotWhitelisted\n} from \"../errors/Vault.sol\";\n\n/**\n * @title CallWhitelist\n * @author Non-Fungible Technologies, Inc.\n *\n * Maintains a whitelist for calls that can be made from an AssetVault.\n * Intended to be used to allow for \"claim\" and other-utility based\n * functions while an asset is being held in escrow. Some functions\n * are blacklisted, e.g. transfer functions, to prevent callers from\n * being able to circumvent withdrawal rules for escrowed assets.\n * Whitelists are specified in terms of \"target contract\" (callee)\n * and function selector.\n *\n * The contract owner can add or remove items from the whitelist.\n */\ncontract CallWhitelist is AccessControlEnumerable, CallBlacklist, ICallWhitelist {\n    using SafeERC20 for IERC20;\n\n    // ============================================ STATE ==============================================\n\n    // =================== Constants =====================\n\n    bytes32 public constant ADMIN_ROLE = keccak256(\"ADMIN\");\n    bytes32 public constant WHITELIST_MANAGER_ROLE = keccak256(\"WHITELIST_MANAGER\");\n\n    // ================= Whitelist State ==================\n\n    /**\n     * @notice Whitelist of callable functions on contracts. Maps addresses that\n     *         can be called to function selectors which can be called on it.\n     *         For example, if we want to allow function call 0x0000 on a contract\n     *         at 0x1111, the mapping will contain whitelist[0x1111][0x0000] = true.\n     */\n    mapping(address => mapping(bytes4 => bool)) private whitelist;\n\n    // ========================================= CONSTRUCTOR ===========================================\n\n    /**\n     * @notice Creates a new call whitelist contract, setting up required roles.\n     */\n    constructor() {\n        _setupRole(ADMIN_ROLE, msg.sender);\n\n        _setRoleAdmin(ADMIN_ROLE, ADMIN_ROLE);\n        _setRoleAdmin(WHITELIST_MANAGER_ROLE, ADMIN_ROLE);\n    }\n\n    // ========================================= VIEW FUNCTIONS =========================================\n\n    /**\n     * @notice Returns true if the given function on the given callee is whitelisted.\n     *\n     * @param callee                The contract that is intended to be called.\n     * @param selector              The function selector that is intended to be called.\n     *\n     * @return isWhitelisted        True if whitelisted, else false.\n     */\n    function isWhitelisted(address callee, bytes4 selector) external view override returns (bool) {\n        return !isBlacklisted(selector) && whitelist[callee][selector];\n    }\n\n    // ======================================== UPDATE OPERATIONS =======================================\n\n    /**\n     * @notice Add the given callee and selector to the whitelist. Can only be called by owner.\n     *\n     * @dev    A blacklist supersedes a whitelist, so should not add blacklisted selectors.\n     *         Calls which are already whitelisted will revert.\n     *\n     * @param callee                The contract to whitelist.\n     * @param selector              The function selector to whitelist.\n     */\n    function add(address callee, bytes4 selector) external override onlyRole(WHITELIST_MANAGER_ROLE) {\n        mapping(bytes4 => bool) storage calleeWhitelist = whitelist[callee];\n\n        if (calleeWhitelist[selector]) revert CW_AlreadyWhitelisted(callee, selector);\n        calleeWhitelist[selector] = true;\n\n        emit CallAdded(msg.sender, callee, selector);\n    }\n\n    /**\n     * @notice Remove the given callee and selector from the whitelist. Can only be called by owner.\n     *\n     * @dev   Calls which are not already whitelisted will revert.\n     *\n     * @param callee                The contract to whitelist.\n     * @param selector              The function selector to whitelist.\n     */\n    function remove(address callee, bytes4 selector) external override onlyRole(WHITELIST_MANAGER_ROLE) {\n        mapping(bytes4 => bool) storage calleeWhitelist = whitelist[callee];\n\n        if (!calleeWhitelist[selector]) revert CW_NotWhitelisted(callee, selector);\n        calleeWhitelist[selector] = false;\n\n        emit CallRemoved(msg.sender, callee, selector);\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    function safeTransfer(\n        IERC20 token,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    function safeIncreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        if (returndata.length > 0) {\n            // Return data is optional\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts/access/AccessControlEnumerable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControlEnumerable.sol\";\nimport \"./AccessControl.sol\";\nimport \"../utils/structs/EnumerableSet.sol\";\n\n/**\n * @dev Extension of {AccessControl} that allows enumerating the members of each role.\n */\nabstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {\n    using EnumerableSet for EnumerableSet.AddressSet;\n\n    mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev Returns one of the accounts that have `role`. `index` must be a\n     * value between 0 and {getRoleMemberCount}, non-inclusive.\n     *\n     * Role bearers are not sorted in any particular way, and their ordering may\n     * change at any point.\n     *\n     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n     * you perform all queries on the same block. See the following\n     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n     * for more information.\n     */\n    function getRoleMember(bytes32 role, uint256 index) public view override returns (address) {\n        return _roleMembers[role].at(index);\n    }\n\n    /**\n     * @dev Returns the number of accounts that have `role`. Can be used\n     * together with {getRoleMember} to enumerate all bearers of a role.\n     */\n    function getRoleMemberCount(bytes32 role) public view override returns (uint256) {\n        return _roleMembers[role].length();\n    }\n\n    /**\n     * @dev Overload {grantRole} to track enumerable memberships\n     */\n    function grantRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) {\n        super.grantRole(role, account);\n        _roleMembers[role].add(account);\n    }\n\n    /**\n     * @dev Overload {revokeRole} to track enumerable memberships\n     */\n    function revokeRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) {\n        super.revokeRole(role, account);\n        _roleMembers[role].remove(account);\n    }\n\n    /**\n     * @dev Overload {renounceRole} to track enumerable memberships\n     */\n    function renounceRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) {\n        super.renounceRole(role, account);\n        _roleMembers[role].remove(account);\n    }\n\n    /**\n     * @dev Overload {_setupRole} to track enumerable memberships\n     */\n    function _setupRole(bytes32 role, address account) internal virtual override {\n        super._setupRole(role, account);\n        _roleMembers[role].add(account);\n    }\n}\n"
    },
    "contracts/interfaces/ICallWhitelist.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.18;\n\ninterface ICallWhitelist {\n    // ============= Events ==============\n\n    event CallAdded(address operator, address callee, bytes4 selector);\n    event CallRemoved(address operator, address callee, bytes4 selector);\n\n    // ================ View Functions ================\n\n    function isWhitelisted(address callee, bytes4 selector) external view returns (bool);\n\n    // ================ Update Operations ================\n\n    function add(address callee, bytes4 selector) external;\n\n    function remove(address callee, bytes4 selector) external;\n}\n"
    },
    "contracts/vault/CallBlacklist.sol": {
      "content": "// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.18;\n\nimport \"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\n\n//solhint-disable max-line-length\n\n/**\n * @title CallBlacklist\n * @author Non-Fungible Technologies, Inc.\n *\n * Library contract maintaining an immutable blacklist for any CallWhitelist contract\n * (or CallWhitelistApprovals). These functions can never be called through the vault's\n * `call` functionality. Note that CallWhitelistApprovals still allows approvals to take\n * place based on certain spenders set in `setApproval`.\n */\nabstract contract CallBlacklist {\n    // ============================================ STATE ==============================================\n\n    // ============= Global Immutable State ==============\n\n    /**\n     * @dev Global blacklist for transfer functions.\n     */\n    bytes4 private constant ERC20_TRANSFER = IERC20.transfer.selector;\n    bytes4 private constant ERC20_ERC721_APPROVE = IERC20.approve.selector;\n    bytes4 private constant ERC20_ERC721_TRANSFER_FROM = IERC20.transferFrom.selector;\n    bytes4 private constant ERC20_INCREASE_ALLOWANCE = bytes4(keccak256(\"increaseAllowance(address,uint256)\"));\n    bytes4 private constant ERC20_BURN = bytes4(keccak256(\"burn(address,uint256)\"));\n    bytes4 private constant ERC20_BURN_FROM = bytes4(keccak256(\"burnFrom(address,uint256)\"));\n\n    bytes4 private constant ERC721_SAFE_TRANSFER_FROM = bytes4(keccak256(\"safeTransferFrom(address,address,uint256)\"));\n    bytes4 private constant ERC721_SAFE_TRANSFER_FROM_DATA = bytes4(keccak256(\"safeTransferFrom(address,address,uint256,bytes)\"));\n    bytes4 private constant ERC721_ERC1155_SET_APPROVAL = IERC721.setApprovalForAll.selector;\n    bytes4 private constant ERC721_BURN = bytes4(keccak256(\"burn(uint256)\"));\n\n    bytes4 private constant ERC1155_SAFE_TRANSFER_FROM = IERC1155.safeTransferFrom.selector;\n    bytes4 private constant ERC1155_SAFE_BATCH_TRANSFER_FROM = IERC1155.safeBatchTransferFrom.selector;\n    bytes4 private constant ERC1155_BURN = bytes4(keccak256(\"burn(address,uint256,uint256)\"));\n    bytes4 private constant ERC1155_BURN_BATCH = bytes4(keccak256(\"burn(address,uint256[],uint256[])\"));\n\n    bytes4 private constant PUNKS_TRANSFER = bytes4(keccak256(\"transferPunk(address,uint256)\"));\n    bytes4 private constant PUNKS_OFFER = bytes4(keccak256(\"offerPunkForSale(uint256,uint256)\"));\n    bytes4 private constant PUNKS_OFFER_TO_ADDRESS = bytes4(keccak256(\"offerPunkForSaleToAddress(uint256,uint256,address)\"));\n    bytes4 private constant PUNKS_BUY = bytes4(keccak256(\"buyPunk(uint256)\"));\n\n    bytes4 private constant SUPERRARE_SET_SALE_PRICE = bytes4(keccak256(\"setSalePrice(uint256,uint256)\"));\n    bytes4 private constant SUPERRARE_ACCEPT_BID = bytes4(keccak256(\"acceptBid(uint256)\"));\n    // SuperRare transfer already blacklisted - same elector as IERC20.transfer\n    // SuperRare approve already blacklisted - same elector as IERC20.approve\n\n    // ================= Blacklist State ==================\n\n    /**\n     * @notice Returns true if the given function selector is on the global blacklist.\n     *         Blacklisted function selectors cannot be called on any contract.\n     *\n     * @param selector              The function selector to check.\n     *\n     * @return isBlacklisted        True if blacklisted, else false.\n     */\n    function isBlacklisted(bytes4 selector) public pure returns (bool) {\n        return\n            selector == ERC20_TRANSFER ||\n            selector == ERC20_ERC721_APPROVE ||\n            selector == ERC20_ERC721_TRANSFER_FROM ||\n            selector == ERC20_INCREASE_ALLOWANCE ||\n            selector == ERC20_BURN ||\n            selector == ERC20_BURN_FROM ||\n            selector == ERC721_SAFE_TRANSFER_FROM ||\n            selector == ERC721_SAFE_TRANSFER_FROM_DATA ||\n            selector == ERC721_ERC1155_SET_APPROVAL ||\n            selector == ERC721_BURN ||\n            selector == ERC1155_SAFE_TRANSFER_FROM ||\n            selector == ERC1155_SAFE_BATCH_TRANSFER_FROM ||\n            selector == ERC1155_BURN ||\n            selector == ERC1155_BURN_BATCH ||\n            selector == PUNKS_TRANSFER ||\n            selector == PUNKS_OFFER ||\n            selector == PUNKS_OFFER_TO_ADDRESS ||\n            selector == PUNKS_BUY ||\n            selector == SUPERRARE_SET_SALE_PRICE ||\n            selector == SUPERRARE_ACCEPT_BID;\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) external returns (bool);\n\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
    },
    "@openzeppelin/contracts/utils/Address.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize, which returns 0 for contracts in\n        // construction, since the code is only stored at the end of the\n        // constructor execution.\n\n        uint256 size;\n        assembly {\n            size := extcodesize(account)\n        }\n        return size > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCall(target, data, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        require(isContract(target), \"Address: call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(isContract(target), \"Address: delegate call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            // Look for revert reason and bubble it up if present\n            if (returndata.length > 0) {\n                // The easiest way to bubble the revert reason is using memory via assembly\n\n                assembly {\n                    let returndata_size := mload(returndata)\n                    revert(add(32, returndata), returndata_size)\n                }\n            } else {\n                revert(errorMessage);\n            }\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts/access/IAccessControlEnumerable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\n\n/**\n * @dev External interface of AccessControlEnumerable declared to support ERC165 detection.\n */\ninterface IAccessControlEnumerable is IAccessControl {\n    /**\n     * @dev Returns one of the accounts that have `role`. `index` must be a\n     * value between 0 and {getRoleMemberCount}, non-inclusive.\n     *\n     * Role bearers are not sorted in any particular way, and their ordering may\n     * change at any point.\n     *\n     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure\n     * you perform all queries on the same block. See the following\n     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]\n     * for more information.\n     */\n    function getRoleMember(bytes32 role, uint256 index) external view returns (address);\n\n    /**\n     * @dev Returns the number of accounts that have `role`. Can be used\n     * together with {getRoleMember} to enumerate all bearers of a role.\n     */\n    function getRoleMemberCount(bytes32 role) external view returns (uint256);\n}\n"
    },
    "@openzeppelin/contracts/access/AccessControl.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n *     require(hasRole(MY_ROLE, msg.sender));\n *     ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n    struct RoleData {\n        mapping(address => bool) members;\n        bytes32 adminRole;\n    }\n\n    mapping(bytes32 => RoleData) private _roles;\n\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n    /**\n     * @dev Modifier that checks that an account has a specific role. Reverts\n     * with a standardized message including the required role.\n     *\n     * The format of the revert reason is given by the following regular expression:\n     *\n     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n     *\n     * _Available since v4.1._\n     */\n    modifier onlyRole(bytes32 role) {\n        _checkRole(role, _msgSender());\n        _;\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) public view override returns (bool) {\n        return _roles[role].members[account];\n    }\n\n    /**\n     * @dev Revert with a standard message if `account` is missing `role`.\n     *\n     * The format of the revert reason is given by the following regular expression:\n     *\n     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n     */\n    function _checkRole(bytes32 role, address account) internal view {\n        if (!hasRole(role, account)) {\n            revert(\n                string(\n                    abi.encodePacked(\n                        \"AccessControl: account \",\n                        Strings.toHexString(uint160(account), 20),\n                        \" is missing role \",\n                        Strings.toHexString(uint256(role), 32)\n                    )\n                )\n            );\n        }\n    }\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\n        return _roles[role].adminRole;\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     */\n    function renounceRole(bytes32 role, address account) public virtual override {\n        require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event. Note that unlike {grantRole}, this function doesn't perform any\n     * checks on the calling account.\n     *\n     * [WARNING]\n     * ====\n     * This function should only be called from the constructor when setting\n     * up the initial roles for the system.\n     *\n     * Using this function in any other way is effectively circumventing the admin\n     * system imposed by {AccessControl}.\n     * ====\n     */\n    function _setupRole(bytes32 role, address account) internal virtual {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Sets `adminRole` as ``role``'s admin role.\n     *\n     * Emits a {RoleAdminChanged} event.\n     */\n    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n        bytes32 previousAdminRole = getRoleAdmin(role);\n        _roles[role].adminRole = adminRole;\n        emit RoleAdminChanged(role, previousAdminRole, adminRole);\n    }\n\n    function _grantRole(bytes32 role, address account) private {\n        if (!hasRole(role, account)) {\n            _roles[role].members[account] = true;\n            emit RoleGranted(role, account, _msgSender());\n        }\n    }\n\n    function _revokeRole(bytes32 role, address account) private {\n        if (hasRole(role, account)) {\n            _roles[role].members[account] = false;\n            emit RoleRevoked(role, account, _msgSender());\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/structs/EnumerableSet.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n *     // Add the library methods\n *     using EnumerableSet for EnumerableSet.AddressSet;\n *\n *     // Declare a set state variable\n *     EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n    // To implement this library for multiple types with as little code\n    // repetition as possible, we write it in terms of a generic Set type with\n    // bytes32 values.\n    // The Set implementation uses private functions, and user-facing\n    // implementations (such as AddressSet) are just wrappers around the\n    // underlying Set.\n    // This means that we can only create new EnumerableSets for types that fit\n    // in bytes32.\n\n    struct Set {\n        // Storage of set values\n        bytes32[] _values;\n        // Position of the value in the `values` array, plus 1 because index 0\n        // means a value is not in the set.\n        mapping(bytes32 => uint256) _indexes;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function _add(Set storage set, bytes32 value) private returns (bool) {\n        if (!_contains(set, value)) {\n            set._values.push(value);\n            // The value is stored at length-1, but we add 1 to all indexes\n            // and use 0 as a sentinel value\n            set._indexes[value] = set._values.length;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function _remove(Set storage set, bytes32 value) private returns (bool) {\n        // We read and store the value's index to prevent multiple reads from the same storage slot\n        uint256 valueIndex = set._indexes[value];\n\n        if (valueIndex != 0) {\n            // Equivalent to contains(set, value)\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\n            // This modifies the order of the array, as noted in {at}.\n\n            uint256 toDeleteIndex = valueIndex - 1;\n            uint256 lastIndex = set._values.length - 1;\n\n            if (lastIndex != toDeleteIndex) {\n                bytes32 lastvalue = set._values[lastIndex];\n\n                // Move the last value to the index where the value to delete is\n                set._values[toDeleteIndex] = lastvalue;\n                // Update the index for the moved value\n                set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex\n            }\n\n            // Delete the slot where the moved value was stored\n            set._values.pop();\n\n            // Delete the index for the deleted slot\n            delete set._indexes[value];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function _contains(Set storage set, bytes32 value) private view returns (bool) {\n        return set._indexes[value] != 0;\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function _length(Set storage set) private view returns (uint256) {\n        return set._values.length;\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function _at(Set storage set, uint256 index) private view returns (bytes32) {\n        return set._values[index];\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function _values(Set storage set) private view returns (bytes32[] memory) {\n        return set._values;\n    }\n\n    // Bytes32Set\n\n    struct Bytes32Set {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _add(set._inner, value);\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _remove(set._inner, value);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n        return _contains(set._inner, value);\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(Bytes32Set storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n        return _at(set._inner, index);\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n        return _values(set._inner);\n    }\n\n    // AddressSet\n\n    struct AddressSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(AddressSet storage set, address value) internal returns (bool) {\n        return _add(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(AddressSet storage set, address value) internal returns (bool) {\n        return _remove(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(AddressSet storage set, address value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(AddressSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(AddressSet storage set, uint256 index) internal view returns (address) {\n        return address(uint160(uint256(_at(set._inner, index))));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(AddressSet storage set) internal view returns (address[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        address[] memory result;\n\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n\n    // UintSet\n\n    struct UintSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(UintSet storage set, uint256 value) internal returns (bool) {\n        return _add(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(UintSet storage set, uint256 value) internal returns (bool) {\n        return _remove(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function length(UintSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n        return uint256(_at(set._inner, index));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(UintSet storage set) internal view returns (uint256[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        uint256[] memory result;\n\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n}\n"
    },
    "@openzeppelin/contracts/access/IAccessControl.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n    /**\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n     *\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n     * {RoleAdminChanged} not being emitted signaling this.\n     *\n     * _Available since v3.1._\n     */\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n    /**\n     * @dev Emitted when `account` is granted `role`.\n     *\n     * `sender` is the account that originated the contract call, an admin role\n     * bearer except when using {AccessControl-_setupRole}.\n     */\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Emitted when `account` is revoked `role`.\n     *\n     * `sender` is the account that originated the contract call:\n     *   - if using `revokeRole`, it is the admin role bearer\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\n     */\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) external view returns (bool);\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     */\n    function renounceRole(bytes32 role, address account) external;\n}\n"
    },
    "@openzeppelin/contracts/utils/Context.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/Strings.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        // Inspired by OraclizeAPI's implementation - MIT licence\n        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n        if (value == 0) {\n            return \"0\";\n        }\n        uint256 temp = value;\n        uint256 digits;\n        while (temp != 0) {\n            digits++;\n            temp /= 10;\n        }\n        bytes memory buffer = new bytes(digits);\n        while (value != 0) {\n            digits -= 1;\n            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n            value /= 10;\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        if (value == 0) {\n            return \"0x00\";\n        }\n        uint256 temp = value;\n        uint256 length = 0;\n        while (temp != 0) {\n            length++;\n            temp >>= 8;\n        }\n        return toHexString(value, length);\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = _HEX_SYMBOLS[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/introspection/ERC165.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"
    },
    "@openzeppelin/contracts/utils/introspection/IERC165.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
    },
    "@openzeppelin/contracts/token/ERC1155/IERC1155.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155 is IERC165 {\n    /**\n     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\n     */\n    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\n\n    /**\n     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\n     * transfers.\n     */\n    event TransferBatch(\n        address indexed operator,\n        address indexed from,\n        address indexed to,\n        uint256[] ids,\n        uint256[] values\n    );\n\n    /**\n     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\n     * `approved`.\n     */\n    event ApprovalForAll(address indexed account, address indexed operator, bool approved);\n\n    /**\n     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\n     *\n     * If an {URI} event was emitted for `id`, the standard\n     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\n     * returned by {IERC1155MetadataURI-uri}.\n     */\n    event URI(string value, uint256 indexed id);\n\n    /**\n     * @dev Returns the amount of tokens of token type `id` owned by `account`.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function balanceOf(address account, uint256 id) external view returns (uint256);\n\n    /**\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\n     *\n     * Requirements:\n     *\n     * - `accounts` and `ids` must have the same length.\n     */\n    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\n        external\n        view\n        returns (uint256[] memory);\n\n    /**\n     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\n     *\n     * Emits an {ApprovalForAll} event.\n     *\n     * Requirements:\n     *\n     * - `operator` cannot be the caller.\n     */\n    function setApprovalForAll(address operator, bool approved) external;\n\n    /**\n     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\n     *\n     * See {setApprovalForAll}.\n     */\n    function isApprovedForAll(address account, address operator) external view returns (bool);\n\n    /**\n     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n     *\n     * Emits a {TransferSingle} event.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.\n     * - `from` must have a balance of tokens of type `id` of at least `amount`.\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n     * acceptance magic value.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 id,\n        uint256 amount,\n        bytes calldata data\n    ) external;\n\n    /**\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\n     *\n     * Emits a {TransferBatch} event.\n     *\n     * Requirements:\n     *\n     * - `ids` and `amounts` must have the same length.\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n     * acceptance magic value.\n     */\n    function safeBatchTransferFrom(\n        address from,\n        address to,\n        uint256[] calldata ids,\n        uint256[] calldata amounts,\n        bytes calldata data\n    ) external;\n}\n"
    },
    "@openzeppelin/contracts/token/ERC721/IERC721.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n    /**\n     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n     */\n    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n    /**\n     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n     */\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    /**\n     * @dev Returns the number of tokens in ``owner``'s account.\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    /**\n     * @dev Returns the owner of the `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function ownerOf(uint256 tokenId) external view returns (address owner);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n     * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external;\n\n    /**\n     * @dev Transfers `tokenId` token from `from` to `to`.\n     *\n     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 tokenId\n    ) external;\n\n    /**\n     * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n     * The approval is cleared when the token is transferred.\n     *\n     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n     *\n     * Requirements:\n     *\n     * - The caller must own the token or be an approved operator.\n     * - `tokenId` must exist.\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address to, uint256 tokenId) external;\n\n    /**\n     * @dev Returns the account approved for `tokenId` token.\n     *\n     * Requirements:\n     *\n     * - `tokenId` must exist.\n     */\n    function getApproved(uint256 tokenId) external view returns (address operator);\n\n    /**\n     * @dev Approve or remove `operator` as an operator for the caller.\n     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n     *\n     * Requirements:\n     *\n     * - The `operator` cannot be the caller.\n     *\n     * Emits an {ApprovalForAll} event.\n     */\n    function setApprovalForAll(address operator, bool _approved) external;\n\n    /**\n     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n     *\n     * See {setApprovalForAll}\n     */\n    function isApprovedForAll(address owner, address operator) external view returns (bool);\n\n    /**\n     * @dev Safely transfers `tokenId` token from `from` to `to`.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `tokenId` token must exist and be owned by `from`.\n     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n     *\n     * Emits a {Transfer} event.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 tokenId,\n        bytes calldata data\n    ) external;\n}\n"
    }
  },
  "settings": {
    "metadata": {
      "bytecodeHash": "none"
    },
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "libraries": {}
  }
}}