creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/FundVault.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport \"openzeppelin-contracts/security/Pausable.sol\";\nimport \"openzeppelin-contracts/security/ReentrancyGuard.sol\";\nimport \"openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol\";\n\nimport \"./ChainlinkAccessor.sol\";\nimport \"./interfaces/IBaseVault.sol\";\nimport \"./interfaces/IFundVault.sol\";\nimport \"./interfaces/IKycManager.sol\";\nimport \"./utils/AdminOperatorRoles.sol\";\nimport \"./utils/BytesQueue.sol\";\nimport \"./utils/ERC1404.sol\";\n\n/**\n * Represents a fund vault with offchain NAV and onchain assets for liquidity.\n *\n * Roles:\n * - Investors who can subscribe/redeem the fund\n * - Operators who manage day-to-day operations\n * - Admins who can handle operator tasks but also set economic parameters\n *\n * ## Operator Workflow\n * - Call {requestAdvanceEpoch} after each NAV report is published to update {_latestOffchainNAV}\n * - Call {requestRedemptionQueue} after assets have been deposited back into the vault to process queued redemptions\n * - Call {transferToTreasury} after deposits to move offchain\n */\ncontract FundVault is ERC4626, ReentrancyGuard, Pausable, ChainlinkAccessor, AdminOperatorRoles, ERC1404, IFundVault {\n    using Math for uint256;\n    using BytesQueue for BytesQueue.BytesDeque;\n\n    BytesQueue.BytesDeque _redemptionQueue;\n    uint256 public _latestOffchainNAV;\n\n    uint256 private constant BPS_UNIT = 10000;\n\n    uint256 public _minTxFee;\n    uint256 public _onchainFee;\n    uint256 public _offchainFee;\n    uint256 public _epoch;\n\n    address public _feeReceiver;\n    address public _treasury;\n\n    IBaseVault public _baseVault;\n    IKycManager public _kycManager;\n\n    mapping(address => bool) public _initialDeposit;\n    mapping(address => mapping(uint256 => uint256)) _depositAmount; // account => [epoch => amount]\n    mapping(address => mapping(uint256 => uint256)) _withdrawAmount; // account => [epoch => amount]\n\n    ////////////////////////////////////////////////////////////\n    // Init\n    ////////////////////////////////////////////////////////////\n\n    constructor(\n        IERC20 asset,\n        address operator,\n        address feeReceiver,\n        address treasury,\n        IBaseVault baseVault,\n        IKycManager kycManager,\n        address chainlinkToken,\n        address chainlinkOracle,\n        ChainlinkParameters memory chainlinkParams\n    ) ERC4626(asset) ERC20(\"Cogito TFUND\", \"TFUND\") {\n        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n        _grantRole(OPERATOR_ROLE, operator);\n\n        _feeReceiver = feeReceiver;\n        _treasury = treasury;\n        _baseVault = baseVault;\n        _kycManager = kycManager;\n\n        _minTxFee = 25 * 10 ** decimals(); // 25USDC\n\n        super.init(chainlinkParams, chainlinkToken, chainlinkOracle);\n    }\n\n    ////////////////////////////////////////////////////////////\n    // Admin functions: Setting addresses\n    ////////////////////////////////////////////////////////////\n\n    function setFeeReceiver(address feeReceiver) external onlyAdmin {\n        _feeReceiver = feeReceiver;\n        emit SetFeeReceiver(feeReceiver);\n    }\n\n    function setTreasury(address newAddress) external onlyAdmin {\n        _treasury = newAddress;\n        emit SetTreasury(newAddress);\n    }\n\n    function setBaseVault(address baseVault) external onlyAdmin {\n        _baseVault = IBaseVault(baseVault);\n        emit SetBaseVault(baseVault);\n    }\n\n    function setKycManager(address kycManager) external onlyAdmin {\n        _kycManager = IKycManager(kycManager);\n        emit SetKycManager(kycManager);\n    }\n\n    ////////////////////////////////////////////////////////////\n    // Admin/Operator functions\n    ////////////////////////////////////////////////////////////\n\n    function pause() external onlyAdminOrOperator {\n        _pause();\n    }\n\n    function unpause() external onlyAdminOrOperator {\n        _unpause();\n    }\n\n    /**\n     * Call after each NAV update has been published, in order to update {_latestOffchainNAV}.\n     * @notice Do not call more than once per day, since {_getServiceFee} calculates daily fees.\n     * @dev Handled in {_advanceEpoch}\n     */\n    function requestAdvanceEpoch() external onlyAdminOrOperator {\n        bytes32 requestId = super._requestTotalOffchainNAV(_msgSender(), 0, Action.ADVANCE_EPOCH, decimals());\n\n        emit RequestAdvanceEpoch(msg.sender, requestId);\n    }\n\n    /**\n     * Call after sufficient assets have been returned to the vault to process redemptions.\n     * @dev Handled in {_processRedemptionQueue}\n     */\n    function requestRedemptionQueue() external onlyAdminOrOperator {\n        if (_redemptionQueue.empty()) {\n            revert RedemptionQueueEmpty();\n        }\n\n        bytes32 requestId = super._requestTotalOffchainNAV(_msgSender(), 0, Action.REDEMPTION_QUEUE, decimals());\n\n        emit RequestRedemptionQueue(msg.sender, requestId);\n    }\n\n    /**\n     * Sweeps all asset to {_treasury}, keeping only the `targetReservesLevel` of assets\n     */\n    function transferExcessReservesToTreasury() external onlyAdminOrOperator {\n        uint256 amount = excessReserves();\n        if (amount == 0) {\n            revert NoExcessReserves();\n        }\n\n        transferToTreasury(asset(), amount);\n    }\n\n    /**\n     * Transfers any underlying assets to {_treasury}.\n     */\n    function transferToTreasury(address underlying, uint256 amount) public onlyAdminOrOperator {\n        if (_treasury == address(0)) {\n            revert InvalidAddress(_treasury);\n        }\n\n        if (underlying == asset() && amount > vaultNetAssets()) {\n            revert InsufficientBalance(vaultNetAssets(), amount);\n        }\n\n        SafeERC20.safeTransfer(IERC20(underlying), _treasury, amount);\n        emit TransferToTreasury(_treasury, asset(), amount);\n    }\n\n    /**\n     * Sets the minimum transaction fee\n     */\n    function setMinTxFee(uint256 newValue) external onlyAdminOrOperator {\n        _minTxFee = newValue;\n        emit SetMinTxFee(newValue);\n    }\n\n    /**\n     * Sends the accumulated onchain service fee to {_feeReceiver}\n     */\n    function claimOnchainServiceFee(uint256 amount) external onlyAdminOrOperator {\n        if (_feeReceiver == address(0)) {\n            revert InvalidAddress(_feeReceiver);\n        }\n\n        if (amount > _onchainFee) {\n            amount = _onchainFee;\n        }\n\n        _onchainFee -= amount;\n        SafeERC20.safeTransfer(IERC20(asset()), _feeReceiver, amount);\n        emit ClaimOnchainServiceFee(msg.sender, _feeReceiver, amount);\n    }\n\n    /**\n     * Sends the accumulated offchain service fee to {_feeReceiver}\n     */\n    function claimOffchainServiceFee(uint256 amount) external onlyAdminOrOperator {\n        if (_feeReceiver == address(0)) {\n            revert InvalidAddress(_feeReceiver);\n        }\n\n        if (amount > _offchainFee) {\n            amount = _offchainFee;\n        }\n\n        _offchainFee -= amount;\n        SafeERC20.safeTransfer(IERC20(asset()), _feeReceiver, amount);\n        emit ClaimOffchainServiceFee(msg.sender, _feeReceiver, amount);\n    }\n\n    /**\n     * Set the users as already deposited.\n     */\n    function bulkSetInitialDeposit(address[] calldata _investors) external onlyAdminOrOperator {\n        for (uint256 i = 0; i < _investors.length; i++) {\n            _initialDeposit[_investors[i]] = true;\n        }\n    }\n\n    ////////////////////////////////////////////////////////////\n    // Chainlink\n    ////////////////////////////////////////////////////////////\n\n    /**\n     * Handler for Chainlink requests. Always contains the latest NAV data.\n     * Processes deposits and redemptions, or updates epoch data\n     */\n    function fulfill(bytes32 requestId, uint256 latestOffchainNAV) external recordChainlinkFulfillment(requestId) {\n        _latestOffchainNAV = latestOffchainNAV;\n\n        (address investor, uint256 amount, Action action) = super.getRequestData(requestId);\n\n        if (action == Action.DEPOSIT) {\n            _processDeposit(investor, amount, requestId);\n        } else if (action == Action.REDEEM) {\n            _processRedemption(investor, amount, requestId);\n        } else if (action == Action.REDEMPTION_QUEUE) {\n            _processRedemptionQueue(requestId);\n        } else if (action == Action.ADVANCE_EPOCH) {\n            _advanceEpoch(requestId);\n        }\n        emit Fulfill(investor, requestId, latestOffchainNAV, amount, uint8(action));\n    }\n\n    ////////////////////////////////////////////////////////////\n    // Public entrypoints\n    ////////////////////////////////////////////////////////////\n\n    /**\n     * Subscribe to the fund.\n     * @dev Handled in {_processDeposit}\n     * @param assets Amount of {asset} to subscribe\n     * @param receiver Must be msg.sender\n     */\n    function deposit(uint256 assets, address receiver)\n        public\n        override\n        onlyCaller(receiver)\n        nonReentrant\n        whenNotPaused\n        returns (uint256)\n    {\n        // receiver is msg.sender\n        _kycManager.onlyKyc(receiver);\n        _kycManager.onlyNotBanned(receiver);\n\n        _validateDeposit(assets);\n        bytes32 requestId = super._requestTotalOffchainNAV(receiver, assets, Action.DEPOSIT, decimals());\n\n        emit RequestDeposit(receiver, assets, requestId);\n        return 0;\n    }\n\n    /**\n     * Redeem exact shares\n     * @dev Handled in {_processRedemption}\n     * @param shares Amount of shares to redeem\n     * @param receiver Must be msg.sender\n     * @param owner Must be msg.sender\n     */\n    function redeem(uint256 shares, address receiver, address owner)\n        public\n        override\n        onlyCaller(receiver)\n        onlyCaller(owner)\n        nonReentrant\n        whenNotPaused\n        returns (uint256)\n    {\n        // receiver is msg.sender\n        _kycManager.onlyKyc(receiver);\n        _kycManager.onlyNotBanned(receiver);\n\n        _validateRedemption(receiver, shares);\n        bytes32 requestId = super._requestTotalOffchainNAV(receiver, shares, Action.REDEEM, decimals());\n\n        emit RequestRedemption(receiver, shares, requestId);\n        return 0;\n    }\n\n    /**\n     * @notice Cannot be directly minted.\n     */\n    function mint(uint256, address) public pure override returns (uint256) {\n        revert();\n    }\n\n    /**\n     * @notice Asset balance may change between requesting and fulfilling, so using {withdraw} may result in\n     * leftover assets. Use {redeem} instead.\n     */\n    function withdraw(uint256, address, address) public pure override returns (uint256) {\n        revert();\n    }\n\n    ////////////////////////////////////////////////////////////\n    // Public getters\n    ////////////////////////////////////////////////////////////\n\n    function getRedemptionQueueInfo(uint256 index) external view returns (address investor, uint256 shares) {\n        if (_redemptionQueue.empty() || index > _redemptionQueue.length() - 1) {\n            return (address(0), 0);\n        }\n\n        bytes memory data = bytes(_redemptionQueue.at(index));\n        (investor, shares) = abi.decode(data, (address, uint256));\n    }\n\n    function getRedemptionQueueLength() external view returns (uint256) {\n        return _redemptionQueue.length();\n    }\n\n    /**\n     * Returns the maximum of the calculated fee and the minimum fee.\n     */\n    function getTxFee(uint256 assets) public view returns (uint256) {\n        return _minTxFee.max((assets * _baseVault.getTransactionFee()) / BPS_UNIT);\n    }\n\n    /**\n     * Returns the requested deposit/withdraw amount for the given user for the current epoch, and the net amount\n     */\n    function getUserEpochInfo(address user, uint256 epoch)\n        public\n        view\n        returns (uint256 depositAmt, uint256 withdrawAmt, uint256 delta)\n    {\n        depositAmt = _depositAmount[user][epoch];\n        withdrawAmt = _withdrawAmount[user][epoch];\n\n        delta = depositAmt >= withdrawAmt ? depositAmt - withdrawAmt : withdrawAmt - depositAmt;\n\n        return (depositAmt, withdrawAmt, delta);\n    }\n\n    /**\n     * @notice totalAssets(): returns the amount of vault assets (eg. USDC), including fees\n     *\n     * vaultNetAssets(): Returns vault assets, net fees\n     */\n    function vaultNetAssets() public view returns (uint256 amount) {\n        return uint256(0).max(totalAssets() - _onchainFee - _offchainFee);\n    }\n\n    /**\n     * combinedNetAssets(): Returns vault + offchain assets, net fees\n     */\n    function combinedNetAssets() public view returns (uint256 amount) {\n        return _latestOffchainNAV + vaultNetAssets();\n    }\n\n    /**\n     * excessReserves(): Returns the amount of assets in vault above the target reserve level, or 0 if below\n     */\n    function excessReserves() public view returns (uint256 amount) {\n        uint256 targetReserves = _baseVault.getTargetReservesLevel() * combinedNetAssets() / 100;\n        uint256 currentReserves = vaultNetAssets();\n        return (currentReserves - targetReserves).max(0);\n    }\n\n    /**\n     * Applies KYC checks on transfers. Sender/receiver cannot be banned.\n     * If strict, check both sender/receiver.\n     * If sender is US, check receiver.\n     * @dev will be called during: transfer, transferFrom, mint, burn\n     */\n    function _beforeTokenTransfer(address from, address to, uint256) internal view override {\n        // no restrictions on minting or burning, or self-transfers\n        if (from == address(0) || to == address(0) || to == address(this)) {\n            return;\n        }\n\n        uint8 restrictionCode = detectTransferRestriction(from, to, 0);\n        require(restrictionCode == SUCCESS_CODE, messageForTransferRestriction(restrictionCode));\n    }\n\n    /**\n     * After any user receives a token, mark as having deposited.\n     */\n    function _afterTokenTransfer(address, address to, uint256) internal override {\n        if (to != address(0) && !_initialDeposit[to]) {\n            _initialDeposit[to] = true;\n        }\n    }\n\n    ////////////////////////////////////////////////////////////\n    // ERC-1404 Overrides\n    ////////////////////////////////////////////////////////////\n\n    function detectTransferRestriction(address from, address to, uint256 /*value*/ )\n        public\n        view\n        override\n        returns (uint8 restrictionCode)\n    {\n        if (_kycManager.isBanned(from)) return REVOKED_OR_BANNED_CODE;\n        else if (_kycManager.isBanned(to)) return REVOKED_OR_BANNED_CODE;\n\n        if (_kycManager.isStrict()) {\n            if (!_kycManager.isKyc(from)) return DISALLOWED_OR_STOP_CODE;\n            else if (!_kycManager.isKyc(to)) return DISALLOWED_OR_STOP_CODE;\n        } else if (_kycManager.isUSKyc(from)) {\n            if (!_kycManager.isKyc(to)) return DISALLOWED_OR_STOP_CODE;\n        }\n        return SUCCESS_CODE;\n    }\n\n    ////////////////////////////////////////////////////////////\n    // ERC-4626 Overrides\n    ////////////////////////////////////////////////////////////\n\n    function _convertToAssets(uint256 shares, Math.Rounding rounding) internal view override returns (uint256 assets) {\n        uint256 supply = totalSupply();\n        return (supply == 0) ? shares : shares.mulDiv(combinedNetAssets(), supply, rounding);\n    }\n\n    function _convertToShares(uint256 assets, Math.Rounding rounding) internal view override returns (uint256 shares) {\n        uint256 supply = totalSupply();\n        return (assets == 0 || supply == 0) ? assets : assets.mulDiv(supply, combinedNetAssets(), rounding);\n    }\n\n    ////////////////////////////////////////////////////////////\n    // Internal\n    ////////////////////////////////////////////////////////////\n\n    /**\n     * Ensures deposit amount is within limits\n     */\n    function _validateDeposit(uint256 assets) internal view {\n        // gas saving by defining local variable\n        address sender = _msgSender();\n\n        (uint256 minDeposit, uint256 maxDeposit) = _baseVault.getMinMaxDeposit();\n        uint256 initialDeposit = _baseVault.getInitialDeposit();\n\n        if (assets > _getAssetBalance(sender)) {\n            revert InsufficientBalance(_getAssetBalance(sender), assets);\n        }\n        if (assets < minDeposit) {\n            revert MinimumDepositRequired(minDeposit);\n        }\n        if (!_initialDeposit[sender] && assets < initialDeposit) {\n            revert MinimumInitialDepositRequired(initialDeposit);\n        }\n        if (IERC20(asset()).allowance(sender, address(this)) < assets) {\n            revert InsufficientAllowance(IERC20(asset()).allowance(sender, address(this)), assets);\n        }\n\n        (uint256 depositAmt, uint256 withdrawAmt, uint256 delta) = getUserEpochInfo(sender, _epoch);\n\n        if (depositAmt >= withdrawAmt) {\n            // Net deposit\n            if (assets > maxDeposit - delta) {\n                revert MaximumDepositExceeded(maxDeposit);\n            }\n        } else {\n            // Net withdraw\n            if (assets > maxDeposit + delta) {\n                revert MaximumDepositExceeded(maxDeposit);\n            }\n        }\n    }\n\n    /**\n     * Transfers assets from investor to vault, and tx fees to {_feeReceiver}\n     */\n    function _processDeposit(address investor, uint256 assets, bytes32 requestId) internal {\n        uint256 txFee = getTxFee(assets);\n        uint256 actualAsset = assets - txFee;\n\n        uint256 shares = previewDeposit(actualAsset);\n        super._deposit(investor, investor, actualAsset, shares);\n\n        SafeERC20.safeTransferFrom(IERC20(asset()), investor, _feeReceiver, txFee);\n\n        _depositAmount[investor][_epoch] += actualAsset;\n        emit ProcessDeposit(investor, assets, shares, requestId, txFee, _feeReceiver);\n    }\n\n    /**\n     * Ensures withdraw amount is within limits\n     */\n    function _validateRedemption(address sender, uint256 share) internal view virtual {\n        if (share > balanceOf(sender)) {\n            revert InsufficientBalance(balanceOf(sender), share);\n        }\n\n        (uint256 minWithdraw, uint256 maxWithdraw) = _baseVault.getMinMaxWithdraw();\n        uint256 assets = previewRedeem(share);\n        if (assets < minWithdraw) {\n            revert MinimumWithdrawRequired(minWithdraw);\n        }\n\n        (uint256 depositAmt, uint256 withdrawAmt, uint256 delta) = getUserEpochInfo(sender, _epoch);\n\n        if (depositAmt >= withdrawAmt) {\n            // Net deposit\n            if (assets > maxWithdraw + delta) {\n                revert MaximumWithdrawExceeded(maxWithdraw);\n            }\n        } else {\n            // Net withdraw\n            if (assets > maxWithdraw - delta) {\n                revert MaximumWithdrawExceeded(maxWithdraw);\n            }\n        }\n    }\n\n    /**\n     * Burns shares and transfers assets to investor.\n     * NOTE: If insufficient asset liquidity, then queue for later\n     */\n    function _processRedemption(address investor, uint256 requestedShares, bytes32 requestId) internal {\n        if (requestedShares > balanceOf(investor)) {\n            revert InsufficientBalance(balanceOf(investor), requestedShares);\n        }\n        uint256 availableAssets = vaultNetAssets();\n        uint256 requestedAssets = previewRedeem(requestedShares);\n\n        uint256 actualShares = requestedShares;\n        uint256 actualAssets = requestedAssets;\n\n        // Requested assets are insufficient, use all available\n        if (actualAssets > availableAssets) {\n            actualAssets = availableAssets;\n            actualShares = previewWithdraw(actualAssets);\n        }\n\n        // Burn shares and transfer assets\n        if (actualAssets > 0) {\n            super._withdraw(investor, investor, investor, actualAssets, actualShares);\n        }\n\n        // Queue remaining shares for later\n        if (requestedShares > actualShares) {\n            uint256 remainingShares = requestedShares - actualShares;\n            _redemptionQueue.pushBack(abi.encode(investor, remainingShares, requestId));\n            super._transfer(investor, address(this), remainingShares);\n            emit AddToRedemptionQueue(investor, remainingShares, requestId);\n        }\n\n        _withdrawAmount[investor][_epoch] += requestedAssets;\n        emit ProcessRedemption(\n            investor, requestedAssets, requestedShares, requestId, availableAssets, actualAssets, actualShares\n        );\n    }\n\n    /**\n     * Processes queued redemptions until no assets are remaining.\n     * @dev May have remainders\n     */\n    function _processRedemptionQueue(bytes32 requestId) internal {\n        for (; !_redemptionQueue.empty();) {\n            bytes memory data = _redemptionQueue.front();\n            (address investor, uint256 shares, bytes32 prevId) = abi.decode(data, (address, uint256, bytes32));\n\n            uint256 assets = previewRedeem(shares);\n\n            // we allow users to drain this vault by design\n            if (assets > vaultNetAssets()) {\n                return;\n            }\n\n            _redemptionQueue.popFront();\n            super._withdraw(address(this), investor, address(this), assets, shares);\n\n            emit ProcessRedemptionQueue(investor, assets, shares, requestId, prevId);\n        }\n    }\n\n    /**\n     * Advances epoch and accrues fees based on {BaseVault-getOnchainAndOffChainServiceFeeRate}\n     */\n    function _advanceEpoch(bytes32 requestId) internal {\n        _epoch++;\n\n        (uint256 onchainFeeRate, uint256 offchainFeeRate) = _baseVault.getOnchainAndOffChainServiceFeeRate();\n\n        _onchainFee += _getServiceFee(vaultNetAssets(), onchainFeeRate);\n        _offchainFee += _getServiceFee(_latestOffchainNAV, offchainFeeRate);\n\n        emit ProcessAdvanceEpoch(_onchainFee, _offchainFee, _epoch, requestId);\n    }\n\n    function _getAssetBalance(address addr) internal view returns (uint256) {\n        return IERC20(asset()).balanceOf(addr);\n    }\n\n    function _getServiceFee(uint256 assets, uint256 rate) internal pure returns (uint256 fee) {\n        return (assets * rate) / (365 * BPS_UNIT);\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/security/Pausable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    bool private _paused;\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    constructor() {\n        _paused = false;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        _requireNotPaused();\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        _requirePaused();\n        _;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        require(!paused(), \"Pausable: paused\");\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        require(paused(), \"Pausable: not paused\");\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        _paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/security/ReentrancyGuard.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\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 ReentrancyGuard {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    constructor() {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/ERC4626.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/ERC4626.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../utils/SafeERC20.sol\";\nimport \"../../../interfaces/IERC4626.sol\";\nimport \"../../../utils/math/Math.sol\";\n\n/**\n * @dev Implementation of the ERC4626 \"Tokenized Vault Standard\" as defined in\n * https://eips.ethereum.org/EIPS/eip-4626[EIP-4626].\n *\n * This extension allows the minting and burning of \"shares\" (represented using the ERC20 inheritance) in exchange for\n * underlying \"assets\" through standardized {deposit}, {mint}, {redeem} and {burn} workflows. This contract extends\n * the ERC20 standard. Any additional extensions included along it would affect the \"shares\" token represented by this\n * contract and not the \"assets\" token which is an independent contract.\n *\n * [CAUTION]\n * ====\n * In empty (or nearly empty) ERC-4626 vaults, deposits are at high risk of being stolen through frontrunning\n * with a \"donation\" to the vault that inflates the price of a share. This is variously known as a donation or inflation\n * attack and is essentially a problem of slippage. Vault deployers can protect against this attack by making an initial\n * deposit of a non-trivial amount of the asset, such that price manipulation becomes infeasible. Withdrawals may\n * similarly be affected by slippage. Users can protect against this attack as well as unexpected slippage in general by\n * verifying the amount received is as expected, using a wrapper that performs these checks such as\n * https://github.com/fei-protocol/ERC4626#erc4626router-and-base[ERC4626Router].\n *\n * Since v4.9, this implementation uses virtual assets and shares to mitigate that risk. The `_decimalsOffset()`\n * corresponds to an offset in the decimal representation between the underlying asset's decimals and the vault\n * decimals. This offset also determines the rate of virtual shares to virtual assets in the vault, which itself\n * determines the initial exchange rate. While not fully preventing the attack, analysis shows that the default offset\n * (0) makes it non-profitable, as a result of the value being captured by the virtual shares (out of the attacker's\n * donation) matching the attacker's expected gains. With a larger offset, the attack becomes orders of magnitude more\n * expensive than it is profitable. More details about the underlying math can be found\n * xref:erc4626.adoc#inflation-attack[here].\n *\n * The drawback of this approach is that the virtual shares do capture (a very small) part of the value being accrued\n * to the vault. Also, if the vault experiences losses, the users try to exit the vault, the virtual shares and assets\n * will cause the first user to exit to experience reduced losses in detriment to the last users that will experience\n * bigger losses. Developers willing to revert back to the pre-v4.9 behavior just need to override the\n * `_convertToShares` and `_convertToAssets` functions.\n *\n * To learn more, check out our xref:ROOT:erc4626.adoc[ERC-4626 guide].\n * ====\n *\n * _Available since v4.7._\n */\nabstract contract ERC4626 is ERC20, IERC4626 {\n    using Math for uint256;\n\n    IERC20 private immutable _asset;\n    uint8 private immutable _underlyingDecimals;\n\n    /**\n     * @dev Set the underlying asset contract. This must be an ERC20-compatible contract (ERC20 or ERC777).\n     */\n    constructor(IERC20 asset_) {\n        (bool success, uint8 assetDecimals) = _tryGetAssetDecimals(asset_);\n        _underlyingDecimals = success ? assetDecimals : 18;\n        _asset = asset_;\n    }\n\n    /**\n     * @dev Attempts to fetch the asset decimals. A return value of false indicates that the attempt failed in some way.\n     */\n    function _tryGetAssetDecimals(IERC20 asset_) private view returns (bool, uint8) {\n        (bool success, bytes memory encodedDecimals) = address(asset_).staticcall(\n            abi.encodeWithSelector(IERC20Metadata.decimals.selector)\n        );\n        if (success && encodedDecimals.length >= 32) {\n            uint256 returnedDecimals = abi.decode(encodedDecimals, (uint256));\n            if (returnedDecimals <= type(uint8).max) {\n                return (true, uint8(returnedDecimals));\n            }\n        }\n        return (false, 0);\n    }\n\n    /**\n     * @dev Decimals are computed by adding the decimal offset on top of the underlying asset's decimals. This\n     * \"original\" value is cached during construction of the vault contract. If this read operation fails (e.g., the\n     * asset has not been created yet), a default of 18 is used to represent the underlying asset's decimals.\n     *\n     * See {IERC20Metadata-decimals}.\n     */\n    function decimals() public view virtual override(IERC20Metadata, ERC20) returns (uint8) {\n        return _underlyingDecimals + _decimalsOffset();\n    }\n\n    /** @dev See {IERC4626-asset}. */\n    function asset() public view virtual override returns (address) {\n        return address(_asset);\n    }\n\n    /** @dev See {IERC4626-totalAssets}. */\n    function totalAssets() public view virtual override returns (uint256) {\n        return _asset.balanceOf(address(this));\n    }\n\n    /** @dev See {IERC4626-convertToShares}. */\n    function convertToShares(uint256 assets) public view virtual override returns (uint256) {\n        return _convertToShares(assets, Math.Rounding.Down);\n    }\n\n    /** @dev See {IERC4626-convertToAssets}. */\n    function convertToAssets(uint256 shares) public view virtual override returns (uint256) {\n        return _convertToAssets(shares, Math.Rounding.Down);\n    }\n\n    /** @dev See {IERC4626-maxDeposit}. */\n    function maxDeposit(address) public view virtual override returns (uint256) {\n        return type(uint256).max;\n    }\n\n    /** @dev See {IERC4626-maxMint}. */\n    function maxMint(address) public view virtual override returns (uint256) {\n        return type(uint256).max;\n    }\n\n    /** @dev See {IERC4626-maxWithdraw}. */\n    function maxWithdraw(address owner) public view virtual override returns (uint256) {\n        return _convertToAssets(balanceOf(owner), Math.Rounding.Down);\n    }\n\n    /** @dev See {IERC4626-maxRedeem}. */\n    function maxRedeem(address owner) public view virtual override returns (uint256) {\n        return balanceOf(owner);\n    }\n\n    /** @dev See {IERC4626-previewDeposit}. */\n    function previewDeposit(uint256 assets) public view virtual override returns (uint256) {\n        return _convertToShares(assets, Math.Rounding.Down);\n    }\n\n    /** @dev See {IERC4626-previewMint}. */\n    function previewMint(uint256 shares) public view virtual override returns (uint256) {\n        return _convertToAssets(shares, Math.Rounding.Up);\n    }\n\n    /** @dev See {IERC4626-previewWithdraw}. */\n    function previewWithdraw(uint256 assets) public view virtual override returns (uint256) {\n        return _convertToShares(assets, Math.Rounding.Up);\n    }\n\n    /** @dev See {IERC4626-previewRedeem}. */\n    function previewRedeem(uint256 shares) public view virtual override returns (uint256) {\n        return _convertToAssets(shares, Math.Rounding.Down);\n    }\n\n    /** @dev See {IERC4626-deposit}. */\n    function deposit(uint256 assets, address receiver) public virtual override returns (uint256) {\n        require(assets <= maxDeposit(receiver), \"ERC4626: deposit more than max\");\n\n        uint256 shares = previewDeposit(assets);\n        _deposit(_msgSender(), receiver, assets, shares);\n\n        return shares;\n    }\n\n    /** @dev See {IERC4626-mint}.\n     *\n     * As opposed to {deposit}, minting is allowed even if the vault is in a state where the price of a share is zero.\n     * In this case, the shares will be minted without requiring any assets to be deposited.\n     */\n    function mint(uint256 shares, address receiver) public virtual override returns (uint256) {\n        require(shares <= maxMint(receiver), \"ERC4626: mint more than max\");\n\n        uint256 assets = previewMint(shares);\n        _deposit(_msgSender(), receiver, assets, shares);\n\n        return assets;\n    }\n\n    /** @dev See {IERC4626-withdraw}. */\n    function withdraw(uint256 assets, address receiver, address owner) public virtual override returns (uint256) {\n        require(assets <= maxWithdraw(owner), \"ERC4626: withdraw more than max\");\n\n        uint256 shares = previewWithdraw(assets);\n        _withdraw(_msgSender(), receiver, owner, assets, shares);\n\n        return shares;\n    }\n\n    /** @dev See {IERC4626-redeem}. */\n    function redeem(uint256 shares, address receiver, address owner) public virtual override returns (uint256) {\n        require(shares <= maxRedeem(owner), \"ERC4626: redeem more than max\");\n\n        uint256 assets = previewRedeem(shares);\n        _withdraw(_msgSender(), receiver, owner, assets, shares);\n\n        return assets;\n    }\n\n    /**\n     * @dev Internal conversion function (from assets to shares) with support for rounding direction.\n     */\n    function _convertToShares(uint256 assets, Math.Rounding rounding) internal view virtual returns (uint256) {\n        return assets.mulDiv(totalSupply() + 10 ** _decimalsOffset(), totalAssets() + 1, rounding);\n    }\n\n    /**\n     * @dev Internal conversion function (from shares to assets) with support for rounding direction.\n     */\n    function _convertToAssets(uint256 shares, Math.Rounding rounding) internal view virtual returns (uint256) {\n        return shares.mulDiv(totalAssets() + 1, totalSupply() + 10 ** _decimalsOffset(), rounding);\n    }\n\n    /**\n     * @dev Deposit/mint common workflow.\n     */\n    function _deposit(address caller, address receiver, uint256 assets, uint256 shares) internal virtual {\n        // If _asset is ERC777, `transferFrom` can trigger a reentrancy BEFORE the transfer happens through the\n        // `tokensToSend` hook. On the other hand, the `tokenReceived` hook, that is triggered after the transfer,\n        // calls the vault, which is assumed not malicious.\n        //\n        // Conclusion: we need to do the transfer before we mint so that any reentrancy would happen before the\n        // assets are transferred and before the shares are minted, which is a valid state.\n        // slither-disable-next-line reentrancy-no-eth\n        SafeERC20.safeTransferFrom(_asset, caller, address(this), assets);\n        _mint(receiver, shares);\n\n        emit Deposit(caller, receiver, assets, shares);\n    }\n\n    /**\n     * @dev Withdraw/redeem common workflow.\n     */\n    function _withdraw(\n        address caller,\n        address receiver,\n        address owner,\n        uint256 assets,\n        uint256 shares\n    ) internal virtual {\n        if (caller != owner) {\n            _spendAllowance(owner, caller, shares);\n        }\n\n        // If _asset is ERC777, `transfer` can trigger a reentrancy AFTER the transfer happens through the\n        // `tokensReceived` hook. On the other hand, the `tokensToSend` hook, that is triggered before the transfer,\n        // calls the vault, which is assumed not malicious.\n        //\n        // Conclusion: we need to do the transfer after the burn so that any reentrancy would happen after the\n        // shares are burned and after the assets are transferred, which is a valid state.\n        _burn(owner, shares);\n        SafeERC20.safeTransfer(_asset, receiver, assets);\n\n        emit Withdraw(caller, receiver, owner, assets, shares);\n    }\n\n    function _decimalsOffset() internal view virtual returns (uint8) {\n        return 0;\n    }\n}\n"
      },
      "src/ChainlinkAccessor.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport \"chainlink/ChainlinkClient.sol\";\n\nimport \"./interfaces/IChainlinkAccessor.sol\";\nimport \"./interfaces/IFundVault.sol\";\nimport \"./utils/AdminRole.sol\";\n\n/**\n * Wrapper for ChainlinkClient. Builds Chainlink requests\n */\nabstract contract ChainlinkAccessor is IChainlinkAccessor, ChainlinkClient, AdminRole {\n    using Chainlink for Chainlink.Request;\n\n    ChainlinkParameters _params;\n    mapping(bytes32 => RequestData) internal _requestIdToRequestData; // requestId => RequestData\n\n    /**\n     * @dev Initializes Chainlink parameters, token, and oracle.\n     * @param params Chainlink parameters containing fee, jobId, urlData, and paths.\n     * @param chainlinkToken Address of the Chainlink token.\n     * @param chainlinkOracle Address of the Chainlink oracle.\n     */\n    function init(ChainlinkParameters memory params, address chainlinkToken, address chainlinkOracle) internal {\n        _params.fee = params.fee;\n        _params.jobId = params.jobId;\n        _params.urlData = params.urlData;\n        _params.pathToOffchainAssets = params.pathToOffchainAssets;\n        _params.pathToTotalOffchainAssetAtLastClose = params.pathToTotalOffchainAssetAtLastClose;\n        setChainlinkOracle(chainlinkOracle);\n        setChainlinkToken(chainlinkToken);\n    }\n\n    /**\n     * Build and send request to offchain API for NAV data.\n     */\n    function _requestTotalOffchainNAV(address investor, uint256 amount, Action action, uint8 decimals)\n        internal\n        returns (bytes32 requestId)\n    {\n        Chainlink.Request memory req = buildChainlinkRequest(\n            _params.jobId,\n            // NOTE: this will be ignored and replace by address(this) during encode\n            address(0),\n            IFundVault(address(this)).fulfill.selector\n        );\n\n        // Set the URL to perform the GET request on\n        req.add(\n            \"get\",\n            _params.urlData // offchain assets url\n        );\n        if (action == Action.ADVANCE_EPOCH) {\n            req.add(\"path\", _params.pathToTotalOffchainAssetAtLastClose);\n        } else {\n            req.add(\"path\", _params.pathToOffchainAssets);\n        }\n\n        // Multiply the result by decimals\n        int256 timesAmount = int256(10 ** decimals);\n        req.addInt(\"times\", timesAmount);\n        RequestData memory requestData = RequestData(investor, amount, action);\n\n        requestId = sendChainlinkRequest(req, _params.fee);\n\n        // Add to mapping\n        _requestIdToRequestData[requestId] = requestData;\n    }\n\n    function setChainlinkOracleAddress(address newAddress) external onlyAdmin {\n        super.setChainlinkOracle(newAddress);\n        emit SetChainlinkOracleAddress(newAddress);\n    }\n\n    function setChainlinkFee(uint256 fee) external onlyAdmin {\n        _params.fee = fee;\n        emit SetChainlinkFee(fee);\n    }\n\n    function setChainlinkJobId(bytes32 jobId) external onlyAdmin {\n        _params.jobId = jobId;\n        emit SetChainlinkJobId(jobId);\n    }\n\n    function setChainlinkURLData(string memory url) external onlyAdmin {\n        _params.urlData = url;\n        emit SetChainlinkURLData(url);\n    }\n\n    function setPathToOffchainAssets(string memory path) external onlyAdmin {\n        _params.pathToOffchainAssets = path;\n        emit SetPathToOffchainAssets(path);\n    }\n\n    function setPathToTotalOffchainAssetAtLastClose(string memory path) external onlyAdmin {\n        _params.pathToTotalOffchainAssetAtLastClose = path;\n        emit SetPathToTotalOffchainAssetAtLastClose(path);\n    }\n\n    function getChainLinkParameters() external view returns (ChainlinkParameters memory params) {\n        params = _params;\n    }\n\n    function getRequestData(bytes32 requestId) public view returns (address investor, uint256 amount, Action action) {\n        investor = _requestIdToRequestData[requestId].investor;\n        amount = _requestIdToRequestData[requestId].amount;\n        action = _requestIdToRequestData[requestId].action;\n    }\n}\n"
      },
      "src/interfaces/IBaseVault.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport \"./Action.sol\";\n\ninterface IBaseVault {\n    event SetTransactionFee(uint256 transactionFee);\n    event SetInitialDeposit(uint256 initialDeposit);\n    event SetMinDeposit(uint256 minDeposit);\n    event SetMaxDeposit(uint256 maxDeposit);\n    event SetMinWithdraw(uint256 minWithdraw);\n    event SetMaxWithdraw(uint256 maxWithdraw);\n    event SetTargetReservesLevel(uint256 targetReservesLevel);\n    event SetOnchainServiceFeeRate(uint256 onchainServiceFeeRate);\n    event SetOffchainServiceFeeRate(uint256 offchainServiceFeeRate);\n\n    function getTransactionFee() external view returns (uint256 txFee);\n\n    function getMinMaxDeposit() external view returns (uint256 minDeposit, uint256 maxDeposit);\n\n    function getMinMaxWithdraw() external view returns (uint256 minWithdraw, uint256 maxWithdraw);\n\n    function getTargetReservesLevel() external view returns (uint256 targetReservesLevel);\n\n    function getOnchainAndOffChainServiceFeeRate()\n        external\n        view\n        returns (uint256 onchainFeeRate, uint256 offchainFeeRate);\n\n    function getInitialDeposit() external view returns (uint256 initialDeposit);\n}\n"
      },
      "src/interfaces/IFundVault.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport \"./IFundVaultEvents.sol\";\n\ninterface IFundVault is IFundVaultEvents {\n    function fulfill(bytes32 requestId, uint256 latestOffchainNAV) external;\n}\n"
      },
      "src/interfaces/IKycManager.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\ninterface IKycManager {\n    enum KycType {\n        NON_KYC,\n        US_KYC,\n        GENERAL_KYC\n    }\n\n    struct UserAddress {\n        address user;\n        KycType kycType;\n        bool isBanned;\n    }\n\n    struct User {\n        bool exists;\n        KycType kycType;\n        bool isBanned;\n    }\n\n    event GrantKyc(address _investor, KycType _kycType);\n    event RevokeKyc(address _investor, KycType _kycType);\n    event Banned(address _investor, bool _status);\n    event SetStrict(bool _status);\n\n    function onlyNotBanned(address investor) external view;\n\n    function onlyKyc(address investor) external view;\n\n    function isBanned(address investor) external view returns (bool);\n\n    function isKyc(address investor) external view returns (bool);\n\n    function isUSKyc(address investor) external view returns (bool);\n\n    function isNonUSKyc(address investor) external view returns (bool);\n\n    function isStrict() external view returns (bool);\n}\n"
      },
      "src/utils/AdminOperatorRoles.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport \"../interfaces/Errors.sol\";\nimport \"./AdminRole.sol\";\n\nabstract contract AdminOperatorRoles is AdminRole {\n    bytes32 public constant OPERATOR_ROLE = keccak256(\"OPERATOR_ROLE\");\n\n    modifier onlyAdminOrOperator() {\n        if (!hasRole(DEFAULT_ADMIN_ROLE, _msgSender()) && !hasRole(OPERATOR_ROLE, _msgSender())) {\n            revert PermissionDenied();\n        }\n        _;\n    }\n\n    modifier onlyCaller(address receiver) {\n        if (_msgSender() != receiver) {\n            revert InvalidAddress(receiver);\n        }\n        _;\n    }\n}\n"
      },
      "src/utils/BytesQueue.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/DoubleEndedQueue.sol)\npragma solidity ^0.8.19;\n\n// import \"../math/SafeCast.sol\";\n\n/**\n * @notice Forked from OpenZeppelin DoubleEndedQueue. Removes `popBack` and `pushFront`. Changes underlying data from `bytes32` to `bytes`.\n * \n * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of\n * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and\n * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that\n * the existing queue contents are left in storage.\n *\n * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be\n * used in storage, and not in memory.\n * ```\n * DoubleEndedQueue.Bytes32Deque queue;\n * ```\n *\n * _Available since v4.6._\n */\nlibrary BytesQueue {\n    /**\n     * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.\n     */\n    error Empty();\n\n    /**\n     * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.\n     */\n    error OutOfBounds();\n\n    /**\n     * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end\n     * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely\n     * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.\n     *\n     * Struct members have an underscore prefix indicating that they are \"private\" and should not be read or written to\n     * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and\n     * lead to unexpected behavior.\n     *\n     * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at\n     * data[end - 1].\n     */\n    struct BytesDeque {\n        int128 _begin;\n        int128 _end;\n        mapping(int128 => bytes) _data;\n    }\n\n    /**\n     * @dev Inserts an item at the end of the queue.\n     */\n    function pushBack(BytesDeque storage deque, bytes memory value) internal {\n        int128 backIndex = deque._end;\n        deque._data[backIndex] = value;\n        unchecked {\n            deque._end = backIndex + 1;\n        }\n    }\n\n    /**\n     * @dev Removes the item at the beginning of the queue and returns it.\n     *\n     * Reverts with `Empty` if the queue is empty.\n     */\n    function popFront(BytesDeque storage deque) internal returns (bytes memory value) {\n        if (empty(deque)) revert Empty();\n        int128 frontIndex = deque._begin;\n        value = deque._data[frontIndex];\n        delete deque._data[frontIndex];\n        unchecked {\n            deque._begin = frontIndex + 1;\n        }\n    }\n\n    /**\n     * @dev Returns the item at the beginning of the queue.\n     *\n     * Reverts with `Empty` if the queue is empty.\n     */\n    function front(BytesDeque storage deque) internal view returns (bytes memory value) {\n        if (empty(deque)) revert Empty();\n        int128 frontIndex = deque._begin;\n        return deque._data[frontIndex];\n    }\n\n    /**\n     * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at\n     * `length(deque) - 1`.\n     *\n     * Reverts with `OutOfBounds` if the index is out of bounds.\n     */\n    function at(BytesDeque storage deque, uint256 index) internal view returns (bytes memory value) {\n        // int256(deque._begin) is a safe upcast\n        int128 idx = _toInt128(int256(deque._begin) + _toInt256(index));\n        if (idx >= deque._end) revert OutOfBounds();\n        return deque._data[idx];\n    }\n\n    function _toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    function _toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n\n    /**\n     * @dev Resets the queue back to being empty.\n     *\n     * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses\n     * out on potential gas refunds.\n     */\n    function clear(BytesDeque storage deque) internal {\n        deque._begin = 0;\n        deque._end = 0;\n    }\n\n    /**\n     * @dev Returns the number of items in the queue.\n     */\n    function length(BytesDeque storage deque) internal view returns (uint256) {\n        // The interface preserves the invariant that begin <= end so we assume this will not overflow.\n        // We also assume there are at most int256.max items in the queue.\n        unchecked {\n            return uint256(int256(deque._end) - int256(deque._begin));\n        }\n    }\n\n    /**\n     * @dev Returns true if the queue is empty.\n     */\n    function empty(BytesDeque storage deque) internal view returns (bool) {\n        return deque._end <= deque._begin;\n    }\n}\n"
      },
      "src/utils/ERC1404.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport \"../interfaces/IERC1404.sol\";\nimport \"../interfaces/Errors.sol\";\n\nabstract contract ERC1404 is IERC1404 {\n    modifier notRestricted(address from, address to) {\n        uint8 restrictionCode = detectTransferRestriction(from, to, 0);\n        require(restrictionCode == SUCCESS_CODE, messageForTransferRestriction(restrictionCode));\n        _;\n    }\n\n    function detectTransferRestriction(address from, address to, uint256 value) public view virtual returns (uint8);\n\n    function messageForTransferRestriction(uint8 restrictionCode) public pure returns (string memory message) {\n        if (restrictionCode == SUCCESS_CODE) {\n            message = SUCCESS_MESSAGE;\n        } else if (restrictionCode == DISALLOWED_OR_STOP_CODE) {\n            message = DISALLOWED_OR_STOP_MESSAGE;\n        } else if (restrictionCode == REVOKED_OR_BANNED_CODE) {\n            message = REVOKED_OR_BANNED_MESSAGE;\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n    mapping(address => uint256) private _balances;\n\n    mapping(address => mapping(address => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * All two of these values are immutable: they can only be set once during\n     * construction.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the default value returned by this function, unless\n     * it's overridden.\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual override returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\n    function balanceOf(address account) public view virtual override returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - the caller must have a balance of at least `amount`.\n     */\n    function transfer(address to, uint256 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _transfer(owner, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     */\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n     * `transferFrom`. This is semantically equivalent to an infinite approval.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Emits an {Approval} event indicating the updated allowance. This is not\n     * required by the EIP. See the note at the beginning of {ERC20}.\n     *\n     * NOTE: Does not update the allowance if the current allowance\n     * is the maximum `uint256`.\n     *\n     * Requirements:\n     *\n     * - `from` and `to` cannot be the zero address.\n     * - `from` must have a balance of at least `amount`.\n     * - the caller must have allowance for ``from``'s tokens of at least\n     * `amount`.\n     */\n    function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\n        address spender = _msgSender();\n        _spendAllowance(from, spender, amount);\n        _transfer(from, to, amount);\n        return true;\n    }\n\n    /**\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        _approve(owner, spender, allowance(owner, spender) + addedValue);\n        return true;\n    }\n\n    /**\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `spender` must have allowance for the caller of at least\n     * `subtractedValue`.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n        address owner = _msgSender();\n        uint256 currentAllowance = allowance(owner, spender);\n        require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n        unchecked {\n            _approve(owner, spender, currentAllowance - subtractedValue);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Moves `amount` of tokens from `from` to `to`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * Requirements:\n     *\n     * - `from` cannot be the zero address.\n     * - `to` cannot be the zero address.\n     * - `from` must have a balance of at least `amount`.\n     */\n    function _transfer(address from, address to, uint256 amount) internal virtual {\n        require(from != address(0), \"ERC20: transfer from the zero address\");\n        require(to != address(0), \"ERC20: transfer to the zero address\");\n\n        _beforeTokenTransfer(from, to, amount);\n\n        uint256 fromBalance = _balances[from];\n        require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n        unchecked {\n            _balances[from] = fromBalance - amount;\n            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n            // decrementing then incrementing.\n            _balances[to] += amount;\n        }\n\n        emit Transfer(from, to, amount);\n\n        _afterTokenTransfer(from, to, amount);\n    }\n\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n     * the total supply.\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function _mint(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: mint to the zero address\");\n\n        _beforeTokenTransfer(address(0), account, amount);\n\n        _totalSupply += amount;\n        unchecked {\n            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n            _balances[account] += amount;\n        }\n        emit Transfer(address(0), account, amount);\n\n        _afterTokenTransfer(address(0), account, amount);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens from `account`, reducing the\n     * total supply.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     * - `account` must have at least `amount` tokens.\n     */\n    function _burn(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: burn from the zero address\");\n\n        _beforeTokenTransfer(account, address(0), amount);\n\n        uint256 accountBalance = _balances[account];\n        require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n        unchecked {\n            _balances[account] = accountBalance - amount;\n            // Overflow not possible: amount <= accountBalance <= totalSupply.\n            _totalSupply -= amount;\n        }\n\n        emit Transfer(account, address(0), amount);\n\n        _afterTokenTransfer(account, address(0), amount);\n    }\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     */\n    function _approve(address owner, address spender, uint256 amount) internal virtual {\n        require(owner != address(0), \"ERC20: approve from the zero address\");\n        require(spender != address(0), \"ERC20: approve to the zero address\");\n\n        _allowances[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n\n    /**\n     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n     *\n     * Does not update the allowance amount in case of infinite allowance.\n     * Revert if not enough allowance is available.\n     *\n     * Might emit an {Approval} event.\n     */\n    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n        uint256 currentAllowance = allowance(owner, spender);\n        if (currentAllowance != type(uint256).max) {\n            require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n            unchecked {\n                _approve(owner, spender, currentAllowance - amount);\n            }\n        }\n    }\n\n    /**\n     * @dev Hook that is called before any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * will be transferred to `to`.\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n    /**\n     * @dev Hook that is called after any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * has been transferred to `to`.\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.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    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) 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(IERC20 token, address spender, uint256 value) 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    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n     * Revert on invalid signature.\n     */\n    function safePermit(\n        IERC20Permit token,\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal {\n        uint256 nonceBefore = token.nonces(owner);\n        token.permit(owner, spender, value, deadline, v, r, s);\n        uint256 nonceAfter = token.nonces(owner);\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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        require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\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     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\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 cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return\n            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/interfaces/IERC4626.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC4626.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../token/ERC20/IERC20.sol\";\nimport \"../token/ERC20/extensions/IERC20Metadata.sol\";\n\n/**\n * @dev Interface of the ERC4626 \"Tokenized Vault Standard\", as defined in\n * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].\n *\n * _Available since v4.7._\n */\ninterface IERC4626 is IERC20, IERC20Metadata {\n    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);\n\n    event Withdraw(\n        address indexed sender,\n        address indexed receiver,\n        address indexed owner,\n        uint256 assets,\n        uint256 shares\n    );\n\n    /**\n     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.\n     *\n     * - MUST be an ERC-20 token contract.\n     * - MUST NOT revert.\n     */\n    function asset() external view returns (address assetTokenAddress);\n\n    /**\n     * @dev Returns the total amount of the underlying asset that is “managed” by Vault.\n     *\n     * - SHOULD include any compounding that occurs from yield.\n     * - MUST be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT revert.\n     */\n    function totalAssets() external view returns (uint256 totalManagedAssets);\n\n    /**\n     * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal\n     * scenario where all the conditions are met.\n     *\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT show any variations depending on the caller.\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n     * - MUST NOT revert.\n     *\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n     * from.\n     */\n    function convertToShares(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal\n     * scenario where all the conditions are met.\n     *\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT show any variations depending on the caller.\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n     * - MUST NOT revert.\n     *\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n     * from.\n     */\n    function convertToAssets(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,\n     * through a deposit call.\n     *\n     * - MUST return a limited value if receiver is subject to some deposit limit.\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.\n     * - MUST NOT revert.\n     */\n    function maxDeposit(address receiver) external view returns (uint256 maxAssets);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given\n     * current on-chain conditions.\n     *\n     * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit\n     *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called\n     *   in the same transaction.\n     * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the\n     *   deposit would be accepted, regardless if the user has enough tokens approved, etc.\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n     */\n    function previewDeposit(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.\n     *\n     * - MUST emit the Deposit event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   deposit execution, and are accounted for during deposit.\n     * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not\n     *   approving enough underlying tokens to the Vault contract, etc).\n     *\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n     */\n    function deposit(uint256 assets, address receiver) external returns (uint256 shares);\n\n    /**\n     * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.\n     * - MUST return a limited value if receiver is subject to some mint limit.\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.\n     * - MUST NOT revert.\n     */\n    function maxMint(address receiver) external view returns (uint256 maxShares);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given\n     * current on-chain conditions.\n     *\n     * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call\n     *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the\n     *   same transaction.\n     * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint\n     *   would be accepted, regardless if the user has enough tokens approved, etc.\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by minting.\n     */\n    function previewMint(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.\n     *\n     * - MUST emit the Deposit event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint\n     *   execution, and are accounted for during mint.\n     * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not\n     *   approving enough underlying tokens to the Vault contract, etc).\n     *\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n     */\n    function mint(uint256 shares, address receiver) external returns (uint256 assets);\n\n    /**\n     * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the\n     * Vault, through a withdraw call.\n     *\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n     * - MUST NOT revert.\n     */\n    function maxWithdraw(address owner) external view returns (uint256 maxAssets);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,\n     * given current on-chain conditions.\n     *\n     * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw\n     *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if\n     *   called\n     *   in the same transaction.\n     * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though\n     *   the withdrawal would be accepted, regardless if the user has enough shares, etc.\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n     */\n    function previewWithdraw(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.\n     *\n     * - MUST emit the Withdraw event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   withdraw execution, and are accounted for during withdraw.\n     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner\n     *   not having enough shares, etc).\n     *\n     * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n     * Those methods should be performed separately.\n     */\n    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);\n\n    /**\n     * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,\n     * through a redeem call.\n     *\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n     * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.\n     * - MUST NOT revert.\n     */\n    function maxRedeem(address owner) external view returns (uint256 maxShares);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,\n     * given current on-chain conditions.\n     *\n     * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call\n     *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the\n     *   same transaction.\n     * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the\n     *   redemption would be accepted, regardless if the user has enough shares, etc.\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by redeeming.\n     */\n    function previewRedeem(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.\n     *\n     * - MUST emit the Withdraw event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   redeem execution, and are accounted for during redeem.\n     * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner\n     *   not having enough shares, etc).\n     *\n     * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n     * Those methods should be performed separately.\n     */\n    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1, \"Math: mulDiv overflow\");\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n}\n"
      },
      "lib/chainlink/contracts/src/v0.8/ChainlinkClient.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"./Chainlink.sol\";\nimport \"./interfaces/ENSInterface.sol\";\nimport \"./interfaces/LinkTokenInterface.sol\";\nimport \"./interfaces/ChainlinkRequestInterface.sol\";\nimport \"./interfaces/OperatorInterface.sol\";\nimport \"./interfaces/PointerInterface.sol\";\nimport {ENSResolver as ENSResolver_Chainlink} from \"./vendor/ENSResolver.sol\";\n\n/**\n * @title The ChainlinkClient contract\n * @notice Contract writers can inherit this contract in order to create requests for the\n * Chainlink network\n */\nabstract contract ChainlinkClient {\n  using Chainlink for Chainlink.Request;\n\n  uint256 internal constant LINK_DIVISIBILITY = 10 ** 18;\n  uint256 private constant AMOUNT_OVERRIDE = 0;\n  address private constant SENDER_OVERRIDE = address(0);\n  uint256 private constant ORACLE_ARGS_VERSION = 1;\n  uint256 private constant OPERATOR_ARGS_VERSION = 2;\n  bytes32 private constant ENS_TOKEN_SUBNAME = keccak256(\"link\");\n  bytes32 private constant ENS_ORACLE_SUBNAME = keccak256(\"oracle\");\n  address private constant LINK_TOKEN_POINTER = 0xC89bD4E1632D3A43CB03AAAd5262cbe4038Bc571;\n\n  ENSInterface private s_ens;\n  bytes32 private s_ensNode;\n  LinkTokenInterface private s_link;\n  OperatorInterface private s_oracle;\n  uint256 private s_requestCount = 1;\n  mapping(bytes32 => address) private s_pendingRequests;\n\n  event ChainlinkRequested(bytes32 indexed id);\n  event ChainlinkFulfilled(bytes32 indexed id);\n  event ChainlinkCancelled(bytes32 indexed id);\n\n  /**\n   * @notice Creates a request that can hold additional parameters\n   * @param specId The Job Specification ID that the request will be created for\n   * @param callbackAddr address to operate the callback on\n   * @param callbackFunctionSignature function signature to use for the callback\n   * @return A Chainlink Request struct in memory\n   */\n  function buildChainlinkRequest(\n    bytes32 specId,\n    address callbackAddr,\n    bytes4 callbackFunctionSignature\n  ) internal pure returns (Chainlink.Request memory) {\n    Chainlink.Request memory req;\n    return req.initialize(specId, callbackAddr, callbackFunctionSignature);\n  }\n\n  /**\n   * @notice Creates a request that can hold additional parameters\n   * @param specId The Job Specification ID that the request will be created for\n   * @param callbackFunctionSignature function signature to use for the callback\n   * @return A Chainlink Request struct in memory\n   */\n  function buildOperatorRequest(\n    bytes32 specId,\n    bytes4 callbackFunctionSignature\n  ) internal view returns (Chainlink.Request memory) {\n    Chainlink.Request memory req;\n    return req.initialize(specId, address(this), callbackFunctionSignature);\n  }\n\n  /**\n   * @notice Creates a Chainlink request to the stored oracle address\n   * @dev Calls `chainlinkRequestTo` with the stored oracle address\n   * @param req The initialized Chainlink Request\n   * @param payment The amount of LINK to send for the request\n   * @return requestId The request ID\n   */\n  function sendChainlinkRequest(Chainlink.Request memory req, uint256 payment) internal returns (bytes32) {\n    return sendChainlinkRequestTo(address(s_oracle), req, payment);\n  }\n\n  /**\n   * @notice Creates a Chainlink request to the specified oracle address\n   * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to\n   * send LINK which creates a request on the target oracle contract.\n   * Emits ChainlinkRequested event.\n   * @param oracleAddress The address of the oracle for the request\n   * @param req The initialized Chainlink Request\n   * @param payment The amount of LINK to send for the request\n   * @return requestId The request ID\n   */\n  function sendChainlinkRequestTo(\n    address oracleAddress,\n    Chainlink.Request memory req,\n    uint256 payment\n  ) internal returns (bytes32 requestId) {\n    uint256 nonce = s_requestCount;\n    s_requestCount = nonce + 1;\n    bytes memory encodedRequest = abi.encodeWithSelector(\n      ChainlinkRequestInterface.oracleRequest.selector,\n      SENDER_OVERRIDE, // Sender value - overridden by onTokenTransfer by the requesting contract's address\n      AMOUNT_OVERRIDE, // Amount value - overridden by onTokenTransfer by the actual amount of LINK sent\n      req.id,\n      address(this),\n      req.callbackFunctionId,\n      nonce,\n      ORACLE_ARGS_VERSION,\n      req.buf.buf\n    );\n    return _rawRequest(oracleAddress, nonce, payment, encodedRequest);\n  }\n\n  /**\n   * @notice Creates a Chainlink request to the stored oracle address\n   * @dev This function supports multi-word response\n   * @dev Calls `sendOperatorRequestTo` with the stored oracle address\n   * @param req The initialized Chainlink Request\n   * @param payment The amount of LINK to send for the request\n   * @return requestId The request ID\n   */\n  function sendOperatorRequest(Chainlink.Request memory req, uint256 payment) internal returns (bytes32) {\n    return sendOperatorRequestTo(address(s_oracle), req, payment);\n  }\n\n  /**\n   * @notice Creates a Chainlink request to the specified oracle address\n   * @dev This function supports multi-word response\n   * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to\n   * send LINK which creates a request on the target oracle contract.\n   * Emits ChainlinkRequested event.\n   * @param oracleAddress The address of the oracle for the request\n   * @param req The initialized Chainlink Request\n   * @param payment The amount of LINK to send for the request\n   * @return requestId The request ID\n   */\n  function sendOperatorRequestTo(\n    address oracleAddress,\n    Chainlink.Request memory req,\n    uint256 payment\n  ) internal returns (bytes32 requestId) {\n    uint256 nonce = s_requestCount;\n    s_requestCount = nonce + 1;\n    bytes memory encodedRequest = abi.encodeWithSelector(\n      OperatorInterface.operatorRequest.selector,\n      SENDER_OVERRIDE, // Sender value - overridden by onTokenTransfer by the requesting contract's address\n      AMOUNT_OVERRIDE, // Amount value - overridden by onTokenTransfer by the actual amount of LINK sent\n      req.id,\n      req.callbackFunctionId,\n      nonce,\n      OPERATOR_ARGS_VERSION,\n      req.buf.buf\n    );\n    return _rawRequest(oracleAddress, nonce, payment, encodedRequest);\n  }\n\n  /**\n   * @notice Make a request to an oracle\n   * @param oracleAddress The address of the oracle for the request\n   * @param nonce used to generate the request ID\n   * @param payment The amount of LINK to send for the request\n   * @param encodedRequest data encoded for request type specific format\n   * @return requestId The request ID\n   */\n  function _rawRequest(\n    address oracleAddress,\n    uint256 nonce,\n    uint256 payment,\n    bytes memory encodedRequest\n  ) private returns (bytes32 requestId) {\n    requestId = keccak256(abi.encodePacked(this, nonce));\n    s_pendingRequests[requestId] = oracleAddress;\n    emit ChainlinkRequested(requestId);\n    require(s_link.transferAndCall(oracleAddress, payment, encodedRequest), \"unable to transferAndCall to oracle\");\n  }\n\n  /**\n   * @notice Allows a request to be cancelled if it has not been fulfilled\n   * @dev Requires keeping track of the expiration value emitted from the oracle contract.\n   * Deletes the request from the `pendingRequests` mapping.\n   * Emits ChainlinkCancelled event.\n   * @param requestId The request ID\n   * @param payment The amount of LINK sent for the request\n   * @param callbackFunc The callback function specified for the request\n   * @param expiration The time of the expiration for the request\n   */\n  function cancelChainlinkRequest(\n    bytes32 requestId,\n    uint256 payment,\n    bytes4 callbackFunc,\n    uint256 expiration\n  ) internal {\n    OperatorInterface requested = OperatorInterface(s_pendingRequests[requestId]);\n    delete s_pendingRequests[requestId];\n    emit ChainlinkCancelled(requestId);\n    requested.cancelOracleRequest(requestId, payment, callbackFunc, expiration);\n  }\n\n  /**\n   * @notice the next request count to be used in generating a nonce\n   * @dev starts at 1 in order to ensure consistent gas cost\n   * @return returns the next request count to be used in a nonce\n   */\n  function getNextRequestCount() internal view returns (uint256) {\n    return s_requestCount;\n  }\n\n  /**\n   * @notice Sets the stored oracle address\n   * @param oracleAddress The address of the oracle contract\n   */\n  function setChainlinkOracle(address oracleAddress) internal {\n    s_oracle = OperatorInterface(oracleAddress);\n  }\n\n  /**\n   * @notice Sets the LINK token address\n   * @param linkAddress The address of the LINK token contract\n   */\n  function setChainlinkToken(address linkAddress) internal {\n    s_link = LinkTokenInterface(linkAddress);\n  }\n\n  /**\n   * @notice Sets the Chainlink token address for the public\n   * network as given by the Pointer contract\n   */\n  function setPublicChainlinkToken() internal {\n    setChainlinkToken(PointerInterface(LINK_TOKEN_POINTER).getAddress());\n  }\n\n  /**\n   * @notice Retrieves the stored address of the LINK token\n   * @return The address of the LINK token\n   */\n  function chainlinkTokenAddress() internal view returns (address) {\n    return address(s_link);\n  }\n\n  /**\n   * @notice Retrieves the stored address of the oracle contract\n   * @return The address of the oracle contract\n   */\n  function chainlinkOracleAddress() internal view returns (address) {\n    return address(s_oracle);\n  }\n\n  /**\n   * @notice Allows for a request which was created on another contract to be fulfilled\n   * on this contract\n   * @param oracleAddress The address of the oracle contract that will fulfill the request\n   * @param requestId The request ID used for the response\n   */\n  function addChainlinkExternalRequest(address oracleAddress, bytes32 requestId) internal notPendingRequest(requestId) {\n    s_pendingRequests[requestId] = oracleAddress;\n  }\n\n  /**\n   * @notice Sets the stored oracle and LINK token contracts with the addresses resolved by ENS\n   * @dev Accounts for subnodes having different resolvers\n   * @param ensAddress The address of the ENS contract\n   * @param node The ENS node hash\n   */\n  function useChainlinkWithENS(address ensAddress, bytes32 node) internal {\n    s_ens = ENSInterface(ensAddress);\n    s_ensNode = node;\n    bytes32 linkSubnode = keccak256(abi.encodePacked(s_ensNode, ENS_TOKEN_SUBNAME));\n    ENSResolver_Chainlink resolver = ENSResolver_Chainlink(s_ens.resolver(linkSubnode));\n    setChainlinkToken(resolver.addr(linkSubnode));\n    updateChainlinkOracleWithENS();\n  }\n\n  /**\n   * @notice Sets the stored oracle contract with the address resolved by ENS\n   * @dev This may be called on its own as long as `useChainlinkWithENS` has been called previously\n   */\n  function updateChainlinkOracleWithENS() internal {\n    bytes32 oracleSubnode = keccak256(abi.encodePacked(s_ensNode, ENS_ORACLE_SUBNAME));\n    ENSResolver_Chainlink resolver = ENSResolver_Chainlink(s_ens.resolver(oracleSubnode));\n    setChainlinkOracle(resolver.addr(oracleSubnode));\n  }\n\n  /**\n   * @notice Ensures that the fulfillment is valid for this contract\n   * @dev Use if the contract developer prefers methods instead of modifiers for validation\n   * @param requestId The request ID for fulfillment\n   */\n  function validateChainlinkCallback(\n    bytes32 requestId\n  )\n    internal\n    recordChainlinkFulfillment(requestId) // solhint-disable-next-line no-empty-blocks\n  {}\n\n  /**\n   * @dev Reverts if the sender is not the oracle of the request.\n   * Emits ChainlinkFulfilled event.\n   * @param requestId The request ID for fulfillment\n   */\n  modifier recordChainlinkFulfillment(bytes32 requestId) {\n    require(msg.sender == s_pendingRequests[requestId], \"Source must be the oracle of the request\");\n    delete s_pendingRequests[requestId];\n    emit ChainlinkFulfilled(requestId);\n    _;\n  }\n\n  /**\n   * @dev Reverts if the request is already pending\n   * @param requestId The request ID for fulfillment\n   */\n  modifier notPendingRequest(bytes32 requestId) {\n    require(s_pendingRequests[requestId] == address(0), \"Request is already pending\");\n    _;\n  }\n}\n"
      },
      "src/interfaces/IChainlinkAccessor.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport \"./Action.sol\";\n\ninterface IChainlinkAccessor {\n    struct ChainlinkParameters {\n        bytes32 jobId;\n        uint256 fee;\n        string urlData;\n        string pathToOffchainAssets;\n        string pathToTotalOffchainAssetAtLastClose;\n    }\n\n    struct RequestData {\n        address investor;\n        uint256 amount;\n        Action action;\n    }\n\n    event SetChainlinkOracleAddress(address newAddress);\n    event SetChainlinkJobId(bytes32 jobId);\n    event SetChainlinkFee(uint256 fee);\n    event SetChainlinkURLData(string url);\n    event SetPathToOffchainAssets(string path);\n    event SetPathToTotalOffchainAssetAtLastClose(string path);\n}\n"
      },
      "src/utils/AdminRole.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport \"openzeppelin-contracts/access/AccessControl.sol\";\n\nabstract contract AdminRole is AccessControl {\n    modifier onlyAdmin() {\n        _checkRole(DEFAULT_ADMIN_ROLE);\n        _;\n    }\n}\n"
      },
      "src/interfaces/Action.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nenum Action {\n    DEPOSIT,\n    REDEEM,\n    ADVANCE_EPOCH,\n    REDEMPTION_QUEUE\n}\n\nstruct VaultParameters {\n    uint256 transactionFee;\n    uint256 initialDeposit;\n    uint256 minDeposit;\n    uint256 maxDeposit;\n    uint256 maxWithdraw;\n    uint256 targetReservesLevel;\n    uint256 onchainServiceFeeRate;\n    uint256 offchainServiceFeeRate;\n}\n"
      },
      "src/interfaces/IFundVaultEvents.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\ninterface IFundVaultEvents {\n    event SetFeeReceiver(address feeReceiver);\n    event SetTreasury(address newAddress);\n    event SetBaseVault(address baseVault);\n    event SetKycManager(address kycManager);\n    event SetMinTxFee(uint256 newValue);\n\n    event ClaimOnchainServiceFee(address caller, address receiver, uint256 amount);\n    event ClaimOffchainServiceFee(address caller, address receiver, uint256 amount);\n    event TransferToTreasury(address receiver, address asset, uint256 amount);\n\n    event RequestAdvanceEpoch(address caller, bytes32 requestId);\n    event ProcessAdvanceEpoch(\n        uint256 onchainFeeClaimable, uint256 offchainFeeClaimable, uint256 epoch, bytes32 requestId\n    );\n\n    event AddToRedemptionQueue(address investor, uint256 shares, bytes32 requestId);\n    event RequestRedemptionQueue(address caller, bytes32 requestId);\n    event ProcessRedemptionQueue(address investor, uint256 assets, uint256 shares, bytes32 requestId, bytes32 prevId);\n\n    event RequestDeposit(address receiver, uint256 assets, bytes32 requestId);\n    event ProcessDeposit(\n        address receiver, uint256 assets, uint256 shares, bytes32 requestId, uint256 txFee, address feeReceiver\n    );\n    event RequestRedemption(address receiver, uint256 shares, bytes32 requestId);\n    event ProcessRedemption(\n        address receiver,\n        uint256 requestedAssets,\n        uint256 requestedShares,\n        bytes32 requestId,\n        uint256 availableAssets,\n        uint256 actualAssets,\n        uint256 actualShares\n    );\n\n    event Fulfill(address investor, bytes32 requestId, uint256 _latestOffchainNAV, uint256 amount, uint8 action);\n}\n"
      },
      "src/interfaces/Errors.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n/**\n * @dev ERC-1066 codes\n * https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1066.md\n */\n\nuint8 constant SUCCESS_CODE = 0x01;\nuint8 constant DISALLOWED_OR_STOP_CODE = 0x10;\nuint8 constant REVOKED_OR_BANNED_CODE = 0x16;\nstring constant SUCCESS_MESSAGE = \"Success\";\nstring constant DISALLOWED_OR_STOP_MESSAGE = \"User is not KYCed\";\nstring constant REVOKED_OR_BANNED_MESSAGE = \"User is banned\";\n\nerror PermissionDenied();\nerror InvalidAddress(address addr);\nerror InvalidAmount(uint256 amount);\nerror UserMissingKyc(address user);\nerror UserBanned(address user);\nerror RedemptionQueueEmpty();\nerror NoExcessReserves();\nerror InsufficientBalance(uint256 current, uint256 needed);\nerror InsufficientAllowance(uint256 current, uint256 needed);\nerror MinimumDepositRequired(uint256 minimum);\nerror MinimumInitialDepositRequired(uint256 minimum);\nerror MaximumDepositExceeded(uint256 maximum);\nerror MinimumWithdrawRequired(uint256 minimum);\nerror MaximumWithdrawExceeded(uint256 maximum);\n"
      },
      "src/interfaces/IERC1404.sol": {
        "content": "pragma solidity ^0.8.19;\n\nimport \"openzeppelin-contracts/token/ERC20/IERC20.sol\";\n\ninterface IERC1404 is IERC20 {\n    /// @notice Detects if a transfer will be reverted and if so returns an appropriate reference code\n    /// @param from Sending address\n    /// @param to Receiving address\n    /// @param value Amount of tokens being transferred\n    /// @return Code by which to reference message for rejection reasoning\n    /// @dev Overwrite with your custom transfer restriction logic\n    function detectTransferRestriction(address from, address to, uint256 value) external view returns (uint8);\n\n    /// @notice Returns a human-readable message for a given restriction code\n    /// @param restrictionCode Identifier for looking up a message\n    /// @return Text showing the restriction's reasoning\n    /// @dev Overwrite with your custom message and restrictionCode handling\n    function messageForTransferRestriction(uint8 restrictionCode) external view returns (string memory);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\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 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    /**\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 `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, 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 `from` to `to` 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(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 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://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, \"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(address target, bytes memory data, uint256 value) 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        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, 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        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, 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        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or 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            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\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            /// @solidity memory-safe-assembly\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"
      },
      "lib/chainlink/contracts/src/v0.8/Chainlink.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {CBORChainlink} from \"./vendor/CBORChainlink.sol\";\nimport {BufferChainlink} from \"./vendor/BufferChainlink.sol\";\n\n/**\n * @title Library for common Chainlink functions\n * @dev Uses imported CBOR library for encoding to buffer\n */\nlibrary Chainlink {\n  uint256 internal constant defaultBufferSize = 256; // solhint-disable-line const-name-snakecase\n\n  using CBORChainlink for BufferChainlink.buffer;\n\n  struct Request {\n    bytes32 id;\n    address callbackAddress;\n    bytes4 callbackFunctionId;\n    uint256 nonce;\n    BufferChainlink.buffer buf;\n  }\n\n  /**\n   * @notice Initializes a Chainlink request\n   * @dev Sets the ID, callback address, and callback function signature on the request\n   * @param self The uninitialized request\n   * @param jobId The Job Specification ID\n   * @param callbackAddr The callback address\n   * @param callbackFunc The callback function signature\n   * @return The initialized request\n   */\n  function initialize(\n    Request memory self,\n    bytes32 jobId,\n    address callbackAddr,\n    bytes4 callbackFunc\n  ) internal pure returns (Chainlink.Request memory) {\n    BufferChainlink.init(self.buf, defaultBufferSize);\n    self.id = jobId;\n    self.callbackAddress = callbackAddr;\n    self.callbackFunctionId = callbackFunc;\n    return self;\n  }\n\n  /**\n   * @notice Sets the data for the buffer without encoding CBOR on-chain\n   * @dev CBOR can be closed with curly-brackets {} or they can be left off\n   * @param self The initialized request\n   * @param data The CBOR data\n   */\n  function setBuffer(Request memory self, bytes memory data) internal pure {\n    BufferChainlink.init(self.buf, data.length);\n    BufferChainlink.append(self.buf, data);\n  }\n\n  /**\n   * @notice Adds a string value to the request with a given key name\n   * @param self The initialized request\n   * @param key The name of the key\n   * @param value The string value to add\n   */\n  function add(Request memory self, string memory key, string memory value) internal pure {\n    self.buf.encodeString(key);\n    self.buf.encodeString(value);\n  }\n\n  /**\n   * @notice Adds a bytes value to the request with a given key name\n   * @param self The initialized request\n   * @param key The name of the key\n   * @param value The bytes value to add\n   */\n  function addBytes(Request memory self, string memory key, bytes memory value) internal pure {\n    self.buf.encodeString(key);\n    self.buf.encodeBytes(value);\n  }\n\n  /**\n   * @notice Adds a int256 value to the request with a given key name\n   * @param self The initialized request\n   * @param key The name of the key\n   * @param value The int256 value to add\n   */\n  function addInt(Request memory self, string memory key, int256 value) internal pure {\n    self.buf.encodeString(key);\n    self.buf.encodeInt(value);\n  }\n\n  /**\n   * @notice Adds a uint256 value to the request with a given key name\n   * @param self The initialized request\n   * @param key The name of the key\n   * @param value The uint256 value to add\n   */\n  function addUint(Request memory self, string memory key, uint256 value) internal pure {\n    self.buf.encodeString(key);\n    self.buf.encodeUInt(value);\n  }\n\n  /**\n   * @notice Adds an array of strings to the request with a given key name\n   * @param self The initialized request\n   * @param key The name of the key\n   * @param values The array of string values to add\n   */\n  function addStringArray(Request memory self, string memory key, string[] memory values) internal pure {\n    self.buf.encodeString(key);\n    self.buf.startArray();\n    for (uint256 i = 0; i < values.length; i++) {\n      self.buf.encodeString(values[i]);\n    }\n    self.buf.endSequence();\n  }\n}\n"
      },
      "lib/chainlink/contracts/src/v0.8/interfaces/ENSInterface.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface ENSInterface {\n  // Logged when the owner of a node assigns a new owner to a subnode.\n  event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\n\n  // Logged when the owner of a node transfers ownership to a new account.\n  event Transfer(bytes32 indexed node, address owner);\n\n  // Logged when the resolver for a node changes.\n  event NewResolver(bytes32 indexed node, address resolver);\n\n  // Logged when the TTL of a node changes\n  event NewTTL(bytes32 indexed node, uint64 ttl);\n\n  function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external;\n\n  function setResolver(bytes32 node, address resolver) external;\n\n  function setOwner(bytes32 node, address owner) external;\n\n  function setTTL(bytes32 node, uint64 ttl) external;\n\n  function owner(bytes32 node) external view returns (address);\n\n  function resolver(bytes32 node) external view returns (address);\n\n  function ttl(bytes32 node) external view returns (uint64);\n}\n"
      },
      "lib/chainlink/contracts/src/v0.8/interfaces/LinkTokenInterface.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface LinkTokenInterface {\n  function allowance(address owner, address spender) external view returns (uint256 remaining);\n\n  function approve(address spender, uint256 value) external returns (bool success);\n\n  function balanceOf(address owner) external view returns (uint256 balance);\n\n  function decimals() external view returns (uint8 decimalPlaces);\n\n  function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);\n\n  function increaseApproval(address spender, uint256 subtractedValue) external;\n\n  function name() external view returns (string memory tokenName);\n\n  function symbol() external view returns (string memory tokenSymbol);\n\n  function totalSupply() external view returns (uint256 totalTokensIssued);\n\n  function transfer(address to, uint256 value) external returns (bool success);\n\n  function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success);\n\n  function transferFrom(address from, address to, uint256 value) external returns (bool success);\n}\n"
      },
      "lib/chainlink/contracts/src/v0.8/interfaces/ChainlinkRequestInterface.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface ChainlinkRequestInterface {\n  function oracleRequest(\n    address sender,\n    uint256 requestPrice,\n    bytes32 serviceAgreementID,\n    address callbackAddress,\n    bytes4 callbackFunctionId,\n    uint256 nonce,\n    uint256 dataVersion,\n    bytes calldata data\n  ) external;\n\n  function cancelOracleRequest(\n    bytes32 requestId,\n    uint256 payment,\n    bytes4 callbackFunctionId,\n    uint256 expiration\n  ) external;\n}\n"
      },
      "lib/chainlink/contracts/src/v0.8/interfaces/OperatorInterface.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"./OracleInterface.sol\";\nimport \"./ChainlinkRequestInterface.sol\";\n\ninterface OperatorInterface is OracleInterface, ChainlinkRequestInterface {\n  function operatorRequest(\n    address sender,\n    uint256 payment,\n    bytes32 specId,\n    bytes4 callbackFunctionId,\n    uint256 nonce,\n    uint256 dataVersion,\n    bytes calldata data\n  ) external;\n\n  function fulfillOracleRequest2(\n    bytes32 requestId,\n    uint256 payment,\n    address callbackAddress,\n    bytes4 callbackFunctionId,\n    uint256 expiration,\n    bytes calldata data\n  ) external returns (bool);\n\n  function ownerTransferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success);\n\n  function distributeFunds(address payable[] calldata receivers, uint256[] calldata amounts) external payable;\n\n  function getAuthorizedSenders() external returns (address[] memory);\n\n  function setAuthorizedSenders(address[] calldata senders) external;\n\n  function getForwarder() external returns (address);\n}\n"
      },
      "lib/chainlink/contracts/src/v0.8/interfaces/PointerInterface.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface PointerInterface {\n  function getAddress() external view returns (address);\n}\n"
      },
      "lib/chainlink/contracts/src/v0.8/vendor/ENSResolver.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nabstract contract ENSResolver {\n  function addr(bytes32 node) public view virtual returns (address);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/access/AccessControl.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)\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 * ```solidity\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 * ```solidity\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. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\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);\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 virtual override returns (bool) {\n        return _roles[role].members[account];\n    }\n\n    /**\n     * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n     * Overriding this function changes the behavior of the {onlyRole} modifier.\n     *\n     * Format of the revert message is described in {_checkRole}.\n     *\n     * _Available since v4.6._\n     */\n    function _checkRole(bytes32 role) internal view virtual {\n        _checkRole(role, _msgSender());\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 virtual {\n        if (!hasRole(role, account)) {\n            revert(\n                string(\n                    abi.encodePacked(\n                        \"AccessControl: account \",\n                        Strings.toHexString(account),\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 virtual 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     * May emit a {RoleGranted} event.\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     * May emit a {RoleRevoked} event.\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 revoked `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     *\n     * May emit a {RoleRevoked} event.\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     * May emit a {RoleGranted} event.\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     * NOTE: This function is deprecated in favor of {_grantRole}.\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    /**\n     * @dev Grants `role` to `account`.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function _grantRole(bytes32 role, address account) internal virtual {\n        if (!hasRole(role, account)) {\n            _roles[role].members[account] = true;\n            emit RoleGranted(role, account, _msgSender());\n        }\n    }\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function _revokeRole(bytes32 role, address account) internal virtual {\n        if (hasRole(role, account)) {\n            _roles[role].members[account] = false;\n            emit RoleRevoked(role, account, _msgSender());\n        }\n    }\n}\n"
      },
      "lib/chainlink/contracts/src/v0.8/vendor/CBORChainlink.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.4.19;\n\nimport {BufferChainlink} from \"./BufferChainlink.sol\";\n\nlibrary CBORChainlink {\n  using BufferChainlink for BufferChainlink.buffer;\n\n  uint8 private constant MAJOR_TYPE_INT = 0;\n  uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1;\n  uint8 private constant MAJOR_TYPE_BYTES = 2;\n  uint8 private constant MAJOR_TYPE_STRING = 3;\n  uint8 private constant MAJOR_TYPE_ARRAY = 4;\n  uint8 private constant MAJOR_TYPE_MAP = 5;\n  uint8 private constant MAJOR_TYPE_TAG = 6;\n  uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7;\n\n  uint8 private constant TAG_TYPE_BIGNUM = 2;\n  uint8 private constant TAG_TYPE_NEGATIVE_BIGNUM = 3;\n\n  function encodeFixedNumeric(BufferChainlink.buffer memory buf, uint8 major, uint64 value) private pure {\n    if(value <= 23) {\n      buf.appendUint8(uint8((major << 5) | value));\n    } else if (value <= 0xFF) {\n      buf.appendUint8(uint8((major << 5) | 24));\n      buf.appendInt(value, 1);\n    } else if (value <= 0xFFFF) {\n      buf.appendUint8(uint8((major << 5) | 25));\n      buf.appendInt(value, 2);\n    } else if (value <= 0xFFFFFFFF) {\n      buf.appendUint8(uint8((major << 5) | 26));\n      buf.appendInt(value, 4);\n    } else {\n      buf.appendUint8(uint8((major << 5) | 27));\n      buf.appendInt(value, 8);\n    }\n  }\n\n  function encodeIndefiniteLengthType(BufferChainlink.buffer memory buf, uint8 major) private pure {\n    buf.appendUint8(uint8((major << 5) | 31));\n  }\n\n  function encodeUInt(BufferChainlink.buffer memory buf, uint value) internal pure {\n    if(value > 0xFFFFFFFFFFFFFFFF) {\n      encodeBigNum(buf, value);\n    } else {\n      encodeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(value));\n    }\n  }\n\n  function encodeInt(BufferChainlink.buffer memory buf, int value) internal pure {\n    if(value < -0x10000000000000000) {\n      encodeSignedBigNum(buf, value);\n    } else if(value > 0xFFFFFFFFFFFFFFFF) {\n      encodeBigNum(buf, uint(value));\n    } else if(value >= 0) {\n      encodeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(uint256(value)));\n    } else {\n      encodeFixedNumeric(buf, MAJOR_TYPE_NEGATIVE_INT, uint64(uint256(-1 - value)));\n    }\n  }\n\n  function encodeBytes(BufferChainlink.buffer memory buf, bytes memory value) internal pure {\n    encodeFixedNumeric(buf, MAJOR_TYPE_BYTES, uint64(value.length));\n    buf.append(value);\n  }\n\n  function encodeBigNum(BufferChainlink.buffer memory buf, uint value) internal pure {\n    buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_BIGNUM));\n    encodeBytes(buf, abi.encode(value));\n  }\n\n  function encodeSignedBigNum(BufferChainlink.buffer memory buf, int input) internal pure {\n    buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_NEGATIVE_BIGNUM));\n    encodeBytes(buf, abi.encode(uint256(-1 - input)));\n  }\n\n  function encodeString(BufferChainlink.buffer memory buf, string memory value) internal pure {\n    encodeFixedNumeric(buf, MAJOR_TYPE_STRING, uint64(bytes(value).length));\n    buf.append(bytes(value));\n  }\n\n  function startArray(BufferChainlink.buffer memory buf) internal pure {\n    encodeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY);\n  }\n\n  function startMap(BufferChainlink.buffer memory buf) internal pure {\n    encodeIndefiniteLengthType(buf, MAJOR_TYPE_MAP);\n  }\n\n  function endSequence(BufferChainlink.buffer memory buf) internal pure {\n    encodeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE);\n  }\n}\n"
      },
      "lib/chainlink/contracts/src/v0.8/vendor/BufferChainlink.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @dev A library for working with mutable byte buffers in Solidity.\n *\n * Byte buffers are mutable and expandable, and provide a variety of primitives\n * for writing to them. At any time you can fetch a bytes object containing the\n * current contents of the buffer. The bytes object should not be stored between\n * operations, as it may change due to resizing of the buffer.\n */\nlibrary BufferChainlink {\n  /**\n   * @dev Represents a mutable buffer. Buffers have a current value (buf) and\n   *      a capacity. The capacity may be longer than the current value, in\n   *      which case it can be extended without the need to allocate more memory.\n   */\n  struct buffer {\n    bytes buf;\n    uint256 capacity;\n  }\n\n  /**\n   * @dev Initializes a buffer with an initial capacity.\n   * @param buf The buffer to initialize.\n   * @param capacity The number of bytes of space to allocate the buffer.\n   * @return The buffer, for chaining.\n   */\n  function init(buffer memory buf, uint256 capacity) internal pure returns (buffer memory) {\n    if (capacity % 32 != 0) {\n      capacity += 32 - (capacity % 32);\n    }\n    // Allocate space for the buffer data\n    buf.capacity = capacity;\n    assembly {\n      let ptr := mload(0x40)\n      mstore(buf, ptr)\n      mstore(ptr, 0)\n      mstore(0x40, add(32, add(ptr, capacity)))\n    }\n    return buf;\n  }\n\n  /**\n   * @dev Initializes a new buffer from an existing bytes object.\n   *      Changes to the buffer may mutate the original value.\n   * @param b The bytes object to initialize the buffer with.\n   * @return A new buffer.\n   */\n  function fromBytes(bytes memory b) internal pure returns (buffer memory) {\n    buffer memory buf;\n    buf.buf = b;\n    buf.capacity = b.length;\n    return buf;\n  }\n\n  function resize(buffer memory buf, uint256 capacity) private pure {\n    bytes memory oldbuf = buf.buf;\n    init(buf, capacity);\n    append(buf, oldbuf);\n  }\n\n  function max(uint256 a, uint256 b) private pure returns (uint256) {\n    if (a > b) {\n      return a;\n    }\n    return b;\n  }\n\n  /**\n   * @dev Sets buffer length to 0.\n   * @param buf The buffer to truncate.\n   * @return The original buffer, for chaining..\n   */\n  function truncate(buffer memory buf) internal pure returns (buffer memory) {\n    assembly {\n      let bufptr := mload(buf)\n      mstore(bufptr, 0)\n    }\n    return buf;\n  }\n\n  /**\n   * @dev Writes a byte string to a buffer. Resizes if doing so would exceed\n   *      the capacity of the buffer.\n   * @param buf The buffer to append to.\n   * @param off The start offset to write to.\n   * @param data The data to append.\n   * @param len The number of bytes to copy.\n   * @return The original buffer, for chaining.\n   */\n  function write(\n    buffer memory buf,\n    uint256 off,\n    bytes memory data,\n    uint256 len\n  ) internal pure returns (buffer memory) {\n    require(len <= data.length);\n\n    if (off + len > buf.capacity) {\n      resize(buf, max(buf.capacity, len + off) * 2);\n    }\n\n    uint256 dest;\n    uint256 src;\n    assembly {\n      // Memory address of the buffer data\n      let bufptr := mload(buf)\n      // Length of existing buffer data\n      let buflen := mload(bufptr)\n      // Start address = buffer address + offset + sizeof(buffer length)\n      dest := add(add(bufptr, 32), off)\n      // Update buffer length if we're extending it\n      if gt(add(len, off), buflen) {\n        mstore(bufptr, add(len, off))\n      }\n      src := add(data, 32)\n    }\n\n    // Copy word-length chunks while possible\n    for (; len >= 32; len -= 32) {\n      assembly {\n        mstore(dest, mload(src))\n      }\n      dest += 32;\n      src += 32;\n    }\n\n    // Copy remaining bytes\n    unchecked {\n      uint256 mask = (256**(32 - len)) - 1;\n      assembly {\n        let srcpart := and(mload(src), not(mask))\n        let destpart := and(mload(dest), mask)\n        mstore(dest, or(destpart, srcpart))\n      }\n    }\n\n    return buf;\n  }\n\n  /**\n   * @dev Appends a byte string to a buffer. Resizes if doing so would exceed\n   *      the capacity of the buffer.\n   * @param buf The buffer to append to.\n   * @param data The data to append.\n   * @param len The number of bytes to copy.\n   * @return The original buffer, for chaining.\n   */\n  function append(\n    buffer memory buf,\n    bytes memory data,\n    uint256 len\n  ) internal pure returns (buffer memory) {\n    return write(buf, buf.buf.length, data, len);\n  }\n\n  /**\n   * @dev Appends a byte string to a buffer. Resizes if doing so would exceed\n   *      the capacity of the buffer.\n   * @param buf The buffer to append to.\n   * @param data The data to append.\n   * @return The original buffer, for chaining.\n   */\n  function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) {\n    return write(buf, buf.buf.length, data, data.length);\n  }\n\n  /**\n   * @dev Writes a byte to the buffer. Resizes if doing so would exceed the\n   *      capacity of the buffer.\n   * @param buf The buffer to append to.\n   * @param off The offset to write the byte at.\n   * @param data The data to append.\n   * @return The original buffer, for chaining.\n   */\n  function writeUint8(\n    buffer memory buf,\n    uint256 off,\n    uint8 data\n  ) internal pure returns (buffer memory) {\n    if (off >= buf.capacity) {\n      resize(buf, buf.capacity * 2);\n    }\n\n    assembly {\n      // Memory address of the buffer data\n      let bufptr := mload(buf)\n      // Length of existing buffer data\n      let buflen := mload(bufptr)\n      // Address = buffer address + sizeof(buffer length) + off\n      let dest := add(add(bufptr, off), 32)\n      mstore8(dest, data)\n      // Update buffer length if we extended it\n      if eq(off, buflen) {\n        mstore(bufptr, add(buflen, 1))\n      }\n    }\n    return buf;\n  }\n\n  /**\n   * @dev Appends a byte to the buffer. Resizes if doing so would exceed the\n   *      capacity of the buffer.\n   * @param buf The buffer to append to.\n   * @param data The data to append.\n   * @return The original buffer, for chaining.\n   */\n  function appendUint8(buffer memory buf, uint8 data) internal pure returns (buffer memory) {\n    return writeUint8(buf, buf.buf.length, data);\n  }\n\n  /**\n   * @dev Writes up to 32 bytes to the buffer. Resizes if doing so would\n   *      exceed the capacity of the buffer.\n   * @param buf The buffer to append to.\n   * @param off The offset to write at.\n   * @param data The data to append.\n   * @param len The number of bytes to write (left-aligned).\n   * @return The original buffer, for chaining.\n   */\n  function write(\n    buffer memory buf,\n    uint256 off,\n    bytes32 data,\n    uint256 len\n  ) private pure returns (buffer memory) {\n    if (len + off > buf.capacity) {\n      resize(buf, (len + off) * 2);\n    }\n\n    unchecked {\n      uint256 mask = (256**len) - 1;\n      // Right-align data\n      data = data >> (8 * (32 - len));\n      assembly {\n        // Memory address of the buffer data\n        let bufptr := mload(buf)\n        // Address = buffer address + sizeof(buffer length) + off + len\n        let dest := add(add(bufptr, off), len)\n        mstore(dest, or(and(mload(dest), not(mask)), data))\n        // Update buffer length if we extended it\n        if gt(add(off, len), mload(bufptr)) {\n          mstore(bufptr, add(off, len))\n        }\n      }\n    }\n    return buf;\n  }\n\n  /**\n   * @dev Writes a bytes20 to the buffer. Resizes if doing so would exceed the\n   *      capacity of the buffer.\n   * @param buf The buffer to append to.\n   * @param off The offset to write at.\n   * @param data The data to append.\n   * @return The original buffer, for chaining.\n   */\n  function writeBytes20(\n    buffer memory buf,\n    uint256 off,\n    bytes20 data\n  ) internal pure returns (buffer memory) {\n    return write(buf, off, bytes32(data), 20);\n  }\n\n  /**\n   * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed\n   *      the capacity of the buffer.\n   * @param buf The buffer to append to.\n   * @param data The data to append.\n   * @return The original buffer, for chhaining.\n   */\n  function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) {\n    return write(buf, buf.buf.length, bytes32(data), 20);\n  }\n\n  /**\n   * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed\n   *      the capacity of the buffer.\n   * @param buf The buffer to append to.\n   * @param data The data to append.\n   * @return The original buffer, for chaining.\n   */\n  function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) {\n    return write(buf, buf.buf.length, data, 32);\n  }\n\n  /**\n   * @dev Writes an integer to the buffer. Resizes if doing so would exceed\n   *      the capacity of the buffer.\n   * @param buf The buffer to append to.\n   * @param off The offset to write at.\n   * @param data The data to append.\n   * @param len The number of bytes to write (right-aligned).\n   * @return The original buffer, for chaining.\n   */\n  function writeInt(\n    buffer memory buf,\n    uint256 off,\n    uint256 data,\n    uint256 len\n  ) private pure returns (buffer memory) {\n    if (len + off > buf.capacity) {\n      resize(buf, (len + off) * 2);\n    }\n\n    uint256 mask = (256**len) - 1;\n    assembly {\n      // Memory address of the buffer data\n      let bufptr := mload(buf)\n      // Address = buffer address + off + sizeof(buffer length) + len\n      let dest := add(add(bufptr, off), len)\n      mstore(dest, or(and(mload(dest), not(mask)), data))\n      // Update buffer length if we extended it\n      if gt(add(off, len), mload(bufptr)) {\n        mstore(bufptr, add(off, len))\n      }\n    }\n    return buf;\n  }\n\n  /**\n   * @dev Appends a byte to the end of the buffer. Resizes if doing so would\n   * exceed the capacity of the buffer.\n   * @param buf The buffer to append to.\n   * @param data The data to append.\n   * @return The original buffer.\n   */\n  function appendInt(\n    buffer memory buf,\n    uint256 data,\n    uint256 len\n  ) internal pure returns (buffer memory) {\n    return writeInt(buf, buf.buf.length, data, len);\n  }\n}\n"
      },
      "lib/chainlink/contracts/src/v0.8/interfaces/OracleInterface.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface OracleInterface {\n  function fulfillOracleRequest(\n    bytes32 requestId,\n    uint256 payment,\n    address callbackAddress,\n    bytes4 callbackFunctionId,\n    uint256 expiration,\n    bytes32 data\n  ) external returns (bool);\n\n  function isAuthorizedSender(address node) external view returns (bool);\n\n  function withdraw(address recipient, uint256 amount) external;\n\n  function withdrawable() external view returns (uint256);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/access/IAccessControl.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\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"
      },
      "lib/openzeppelin-contracts/contracts/utils/Strings.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n    uint8 private constant _ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = Math.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            /// @solidity memory-safe-assembly\n            assembly {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\n     */\n    function toString(int256 value) internal pure returns (string memory) {\n        return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, Math.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        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] = _SYMBOLS[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n    }\n\n    /**\n     * @dev Returns true if the two strings are equal.\n     */\n    function equal(string memory a, string memory b) internal pure returns (bool) {\n        return keccak256(bytes(a)) == keccak256(bytes(b));\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\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"
      },
      "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n    /**\n     * @dev Returns the largest of two signed numbers.\n     */\n    function max(int256 a, int256 b) internal pure returns (int256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two signed numbers.\n     */\n    function min(int256 a, int256 b) internal pure returns (int256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two signed numbers without overflow.\n     * The result is rounded towards zero.\n     */\n    function average(int256 a, int256 b) internal pure returns (int256) {\n        // Formula from the book \"Hacker's Delight\"\n        int256 x = (a & b) + ((a ^ b) >> 1);\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\n    }\n\n    /**\n     * @dev Returns the absolute unsigned value of a signed value.\n     */\n    function abs(int256 n) internal pure returns (uint256) {\n        unchecked {\n            // must be unchecked in order to support `n = type(int256).min`\n            return uint256(n >= 0 ? n : -n);\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\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"
      }
    },
    "settings": {
      "remappings": [
        "chainlink/=lib/chainlink/contracts/src/v0.8/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "erc4626-tests/=lib/chainlink/contracts/foundry-lib/openzeppelin-contracts/lib/erc4626-tests/",
        "forge-std/=lib/forge-std/src/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
        "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
        "openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "libraries": {}
    }
  }}