creation_sourcecode: {{
    "language": "Solidity",
    "settings": {
      "evmVersion": "london",
      "libraries": {},
      "metadata": {
        "bytecodeHash": "ipfs",
        "useLiteralContent": true
      },
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "remappings": [],
      "viaIR": true,
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      }
    },
    "sources": {
      "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/interfaces/IERC4626Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (interfaces/IERC4626.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../token/ERC20/IERC20Upgradeable.sol\";\nimport \"../token/ERC20/extensions/IERC20MetadataUpgradeable.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 IERC4626Upgradeable is IERC20Upgradeable, IERC20MetadataUpgradeable {\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(\n        uint256 assets,\n        address receiver,\n        address owner\n    ) 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(\n        uint256 shares,\n        address receiver,\n        address owner\n    ) external returns (uint256 assets);\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized < type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\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 This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20Upgradeable.sol\";\nimport \"./extensions/IERC20MetadataUpgradeable.sol\";\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"../../proxy/utils/Initializable.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 * 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 ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {\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     * The default value of {decimals} is 18. To select a different value for\n     * {decimals} you should overload it.\n     *\n     * All two of these values are immutable: they can only be set once during\n     * construction.\n     */\n    function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {\n        __ERC20_init_unchained(name_, symbol_);\n    }\n\n    function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\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 value {ERC20} uses, unless this function is\n     * 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(\n        address from,\n        address to,\n        uint256 amount\n    ) 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(\n        address from,\n        address to,\n        uint256 amount\n    ) 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(\n        address owner,\n        address spender,\n        uint256 amount\n    ) 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(\n        address owner,\n        address spender,\n        uint256 amount\n    ) 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(\n        address from,\n        address to,\n        uint256 amount\n    ) 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(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {}\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[45] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.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 IERC20Upgradeable {\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(\n        address from,\n        address to,\n        uint256 amount\n    ) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC4626Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.1) (token/ERC20/extensions/ERC4626.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20Upgradeable.sol\";\nimport \"../utils/SafeERC20Upgradeable.sol\";\nimport \"../../../interfaces/IERC4626Upgradeable.sol\";\nimport \"../../../utils/math/MathUpgradeable.sol\";\nimport \"../../../proxy/utils/Initializable.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: When the vault is empty or nearly empty, deposits are at high risk of being stolen through frontrunning with\n * 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 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 * _Available since v4.7._\n */\nabstract contract ERC4626Upgradeable is Initializable, ERC20Upgradeable, IERC4626Upgradeable {\n    using MathUpgradeable for uint256;\n\n    IERC20Upgradeable private _asset;\n    uint8 private _decimals;\n\n    /**\n     * @dev Set the underlying asset contract. This must be an ERC20-compatible contract (ERC20 or ERC777).\n     */\n    function __ERC4626_init(IERC20Upgradeable asset_) internal onlyInitializing {\n        __ERC4626_init_unchained(asset_);\n    }\n\n    function __ERC4626_init_unchained(IERC20Upgradeable asset_) internal onlyInitializing {\n        (bool success, uint8 assetDecimals) = _tryGetAssetDecimals(asset_);\n        _decimals = success ? assetDecimals : super.decimals();\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(IERC20Upgradeable asset_) private view returns (bool, uint8) {\n        (bool success, bytes memory encodedDecimals) = address(asset_).staticcall(\n            abi.encodeWithSelector(IERC20MetadataUpgradeable.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 read from the underlying asset in the constructor and cached. If this fails (e.g., the asset\n     * has not been created yet), the cached value is set to a default obtained by `super.decimals()` (which depends on\n     * inheritance but is most likely 18). Override this function in order to set a guaranteed hardcoded value.\n     * See {IERC20Metadata-decimals}.\n     */\n    function decimals() public view virtual override(IERC20MetadataUpgradeable, ERC20Upgradeable) returns (uint8) {\n        return _decimals;\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 shares) {\n        return _convertToShares(assets, MathUpgradeable.Rounding.Down);\n    }\n\n    /** @dev See {IERC4626-convertToAssets}. */\n    function convertToAssets(uint256 shares) public view virtual override returns (uint256 assets) {\n        return _convertToAssets(shares, MathUpgradeable.Rounding.Down);\n    }\n\n    /** @dev See {IERC4626-maxDeposit}. */\n    function maxDeposit(address) public view virtual override returns (uint256) {\n        return _isVaultCollateralized() ? type(uint256).max : 0;\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), MathUpgradeable.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, MathUpgradeable.Rounding.Down);\n    }\n\n    /** @dev See {IERC4626-previewMint}. */\n    function previewMint(uint256 shares) public view virtual override returns (uint256) {\n        return _convertToAssets(shares, MathUpgradeable.Rounding.Up);\n    }\n\n    /** @dev See {IERC4626-previewWithdraw}. */\n    function previewWithdraw(uint256 assets) public view virtual override returns (uint256) {\n        return _convertToShares(assets, MathUpgradeable.Rounding.Up);\n    }\n\n    /** @dev See {IERC4626-previewRedeem}. */\n    function previewRedeem(uint256 shares) public view virtual override returns (uint256) {\n        return _convertToAssets(shares, MathUpgradeable.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(\n        uint256 assets,\n        address receiver,\n        address owner\n    ) 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(\n        uint256 shares,\n        address receiver,\n        address owner\n    ) 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     * Will revert if assets > 0, totalSupply > 0 and totalAssets = 0. That corresponds to a case where any asset\n     * would represent an infinite amount of shares.\n     */\n    function _convertToShares(uint256 assets, MathUpgradeable.Rounding rounding) internal view virtual returns (uint256 shares) {\n        uint256 supply = totalSupply();\n        return\n            (assets == 0 || supply == 0)\n                ? _initialConvertToShares(assets, rounding)\n                : assets.mulDiv(supply, totalAssets(), rounding);\n    }\n\n    /**\n     * @dev Internal conversion function (from assets to shares) to apply when the vault is empty.\n     *\n     * NOTE: Make sure to keep this function consistent with {_initialConvertToAssets} when overriding it.\n     */\n    function _initialConvertToShares(\n        uint256 assets,\n        MathUpgradeable.Rounding /*rounding*/\n    ) internal view virtual returns (uint256 shares) {\n        return assets;\n    }\n\n    /**\n     * @dev Internal conversion function (from shares to assets) with support for rounding direction.\n     */\n    function _convertToAssets(uint256 shares, MathUpgradeable.Rounding rounding) internal view virtual returns (uint256 assets) {\n        uint256 supply = totalSupply();\n        return\n            (supply == 0) ? _initialConvertToAssets(shares, rounding) : shares.mulDiv(totalAssets(), supply, rounding);\n    }\n\n    /**\n     * @dev Internal conversion function (from shares to assets) to apply when the vault is empty.\n     *\n     * NOTE: Make sure to keep this function consistent with {_initialConvertToShares} when overriding it.\n     */\n    function _initialConvertToAssets(\n        uint256 shares,\n        MathUpgradeable.Rounding /*rounding*/\n    ) internal view virtual returns (uint256 assets) {\n        return shares;\n    }\n\n    /**\n     * @dev Deposit/mint common workflow.\n     */\n    function _deposit(\n        address caller,\n        address receiver,\n        uint256 assets,\n        uint256 shares\n    ) internal virtual {\n        // If _asset is ERC777, `transferFrom` can trigger a reenterancy 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        SafeERC20Upgradeable.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        SafeERC20Upgradeable.safeTransfer(_asset, receiver, assets);\n\n        emit Withdraw(caller, receiver, owner, assets, shares);\n    }\n\n    /**\n     * @dev Checks if vault is \"healthy\" in the sense of having assets backing the circulating shares.\n     */\n    function _isVaultCollateralized() private view returns (bool) {\n        return totalAssets() > 0 || totalSupply() == 0;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.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 \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\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"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/draft-IERC20PermitUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-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 IERC20PermitUpgradeable {\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"
      },
      "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/draft-IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n    using AddressUpgradeable for address;\n\n    function safeTransfer(\n        IERC20Upgradeable token,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(\n        IERC20Upgradeable token,\n        address from,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(\n        IERC20Upgradeable token,\n        address spender,\n        uint256 value\n    ) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    function safeIncreaseAllowance(\n        IERC20Upgradeable token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(\n        IERC20Upgradeable token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n        }\n    }\n\n    function safePermit(\n        IERC20PermitUpgradeable 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(IERC20Upgradeable token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        if (returndata.length > 0) {\n            // Return data is optional\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     *\n     * [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://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return 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(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (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 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"
      },
      "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\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    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.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 MathUpgradeable {\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(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) 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                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1);\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(\n        uint256 x,\n        uint256 y,\n        uint256 denominator,\n        Rounding rounding\n    ) 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 10, 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 * 8) < value ? 1 : 0);\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/access/Ownable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    constructor() {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
      },
      "@openzeppelin/contracts/proxy/Clones.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (proxy/Clones.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\n * deploying minimal proxy contracts, also known as \"clones\".\n *\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\n *\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\n * deterministic method.\n *\n * _Available since v3.4._\n */\nlibrary Clones {\n    /**\n     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\n     *\n     * This function uses the create opcode, which should never revert.\n     */\n    function clone(address implementation) internal returns (address instance) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes\n            // of the `implementation` address with the bytecode before the address.\n            mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))\n            // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.\n            mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))\n            instance := create(0, 0x09, 0x37)\n        }\n        require(instance != address(0), \"ERC1167: create failed\");\n    }\n\n    /**\n     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\n     *\n     * This function uses the create2 opcode and a `salt` to deterministically deploy\n     * the clone. Using the same `implementation` and `salt` multiple time will revert, since\n     * the clones cannot be deployed twice at the same address.\n     */\n    function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes\n            // of the `implementation` address with the bytecode before the address.\n            mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))\n            // Packs the remaining 17 bytes of `implementation` with the bytecode after the address.\n            mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3))\n            instance := create2(0, 0x09, 0x37, salt)\n        }\n        require(instance != address(0), \"ERC1167: create2 failed\");\n    }\n\n    /**\n     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n     */\n    function predictDeterministicAddress(\n        address implementation,\n        bytes32 salt,\n        address deployer\n    ) internal pure returns (address predicted) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let ptr := mload(0x40)\n            mstore(add(ptr, 0x38), deployer)\n            mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff)\n            mstore(add(ptr, 0x14), implementation)\n            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73)\n            mstore(add(ptr, 0x58), salt)\n            mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37))\n            predicted := keccak256(add(ptr, 0x43), 0x55)\n        }\n    }\n\n    /**\n     * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n     */\n    function predictDeterministicAddress(address implementation, bytes32 salt)\n        internal\n        view\n        returns (address predicted)\n    {\n        return predictDeterministicAddress(implementation, salt, address(this));\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.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(\n        address from,\n        address to,\n        uint256 amount\n    ) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-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"
      },
      "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-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    function safeTransfer(\n        IERC20 token,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    function safeIncreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n        }\n    }\n\n    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        if (returndata.length > 0) {\n            // Return data is optional\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.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     *\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://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return 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(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (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"
      },
      "@openzeppelin/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"
      },
      "@openzeppelin/contracts/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.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(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) 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                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1);\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(\n        uint256 x,\n        uint256 y,\n        uint256 denominator,\n        Rounding rounding\n    ) 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 10, 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 * 8) < value ? 1 : 0);\n        }\n    }\n}\n"
      },
      "contracts/HATVault.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Disclaimer https://github.com/hats-finance/hats-contracts/blob/main/DISCLAIMER.md\n\npragma solidity 0.8.16;\n\nimport \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC4626Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./tokenlock/TokenLockFactory.sol\";\nimport \"./interfaces/IHATVault.sol\";\nimport \"./interfaces/IHATClaimsManager.sol\";\nimport \"./interfaces/IRewardController.sol\";\nimport \"./HATVaultsRegistry.sol\";\n\n/** @title A Hats.finance vault which holds the funds for a specific project's\n* bug bounties\n* @author Hats.finance\n* @notice The HATVault can be deposited into in a permissionless manner using\n* the vault’s native token.\n*\n* Anyone can deposit the vault's native token into the vault and \n* recieve shares for it. Shares represent the user's relative part in the\n* vault, and when a bounty is paid out, users lose part of their deposits\n* (based on percentage paid), but keep their share of the vault.\n* Users also receive rewards for their deposits, which can be claimed at any\n* time.\n* To withdraw previously deposited tokens, a user must first send a withdraw\n* request, and the withdrawal will be made available after a pending period.\n* Withdrawals are not permitted during safety periods or while there is an \n* active claim for a bounty payout.\n*\n* This project is open-source and can be found at:\n* https://github.com/hats-finance/hats-contracts\n*/\ncontract HATVault is IHATVault, ERC4626Upgradeable, OwnableUpgradeable, ReentrancyGuardUpgradeable {\n    using SafeERC20 for IERC20;\n    using MathUpgradeable for uint256;\n\n    string public constant VERSION = \"3.0\";\n    uint256 public constant MAX_UINT = type(uint256).max;\n    uint256 public constant HUNDRED_PERCENT = 1e4;\n    uint256 public constant MAX_WITHDRAWAL_FEE = 2e2; // Max fee is 2%\n    uint256 public constant MINIMAL_AMOUNT_OF_SHARES = 1e3; // to reduce rounding errors, the number of shares is either 0, or > than this number\n\n    address public claimsManager;\n    IHATVaultsRegistry public registry;\n\n    // Time of when withdrawal period starts for every user that has an\n    // active withdraw request. (time when last withdraw request pending \n    // period ended, or 0 if last action was deposit or withdraw)\n    mapping(address => uint256) public withdrawEnableStartTime;\n    IRewardController[] public rewardControllers;\n    uint256 public withdrawalFee;\n    bool public vaultStarted;\n    bool public depositPause;\n    bool public withdrawPaused;\n    bool private _isEmergencyWithdraw;\n    bool private _vaultDestroyed;\n\n    modifier onlyClaimsManager() {\n        if (claimsManager != _msgSender()) revert OnlyClaimsManager();\n        _;\n    }\n\n    modifier onlyRegistryOwner() {\n        if (registry.owner() != _msgSender()) revert OnlyRegistryOwner();\n        _;\n    }\n\n    modifier onlyFeeSetter() {\n        if (registry.feeSetter() != msg.sender) revert OnlyFeeSetter();\n        _;\n    }\n\n    /** @notice See {IHATVault-initialize}. */\n    function initialize(address _claimsManager, IHATVault.VaultInitParams calldata _params) external initializer {\n        __ERC20_init(string.concat(\"Hats Vault \", _params.name), string.concat(\"HAT\", _params.symbol));\n        __ERC4626_init(IERC20MetadataUpgradeable(address(_params.asset)));\n        __ReentrancyGuard_init();\n        _transferOwnership(_params.owner);\n        for (uint256 i = 0; i < _params.rewardControllers.length;) { \n            _addRewardController(_params.rewardControllers[i]);\n            unchecked { ++i; }\n        }\n        claimsManager = _claimsManager;\n        depositPause = _params.isPaused;\n        registry = IHATVaultsRegistry(_msgSender());\n        emit SetVaultDescription(_params.descriptionHash);\n    }\n\n    /** @notice See {IHATVault-approveClaim}. */\n    function makePayout(uint256 _amount) external onlyClaimsManager {\n        IERC20(asset()).safeTransfer(address(_msgSender()), _amount);\n        emit VaultPayout(_amount);\n    }\n\n    /** @notice See {IHATVault-setWithdrawPaused}. */\n    function setWithdrawPaused(bool _withdrawPaused) external onlyClaimsManager {\n        withdrawPaused = _withdrawPaused;\n        emit SetWithdrawPaused(_withdrawPaused);\n    }\n\n    /** @notice See {IHATVault-destroyVault}. */\n    function startVault() external onlyClaimsManager {\n        vaultStarted = true;\n        emit VaultStarted();\n    }\n\n    /** @notice See {IHATVault-destroyVault}. */\n    function destroyVault() external onlyClaimsManager {\n        depositPause = true;\n        _vaultDestroyed = true;\n        emit VaultDestroyed();\n    }\n\n    /** @notice See {IHATVault-addRewardController}. */\n    function addRewardController(IRewardController _rewardController) external onlyRegistryOwner {\n        _addRewardController(_rewardController);\n    }\n\n    /** @notice See {IHATVault-setDepositPause}. */\n    function setDepositPause(bool _depositPause) external onlyOwner {\n        if (_vaultDestroyed)\n            revert CannotUnpauseDestroyedVault();\n        depositPause = _depositPause;\n        emit SetDepositPause(_depositPause);\n    }\n\n    /** @notice See {IHATVault-setVaultDescription}. */\n    function setVaultDescription(string calldata _descriptionHash) external onlyRegistryOwner {\n        emit SetVaultDescription(_descriptionHash);\n    }\n\n    /** @notice See {IHATVault-setWithdrawalFee}. */\n    function setWithdrawalFee(uint256 _fee) external onlyFeeSetter {\n        if (_fee > MAX_WITHDRAWAL_FEE) revert WithdrawalFeeTooBig();\n        withdrawalFee = _fee;\n        emit SetWithdrawalFee(_fee);\n    }\n\n    /* -------------------------------------------------------------------------------- */\n\n\n    /* ---------------------------------- Vault --------------------------------------- */\n\n    /** @notice See {IHATVault-withdrawRequest}. */\n    function withdrawRequest() external nonReentrant {\n        // set the withdrawEnableStartTime time to be withdrawRequestPendingPeriod from now\n        // solhint-disable-next-line not-rely-on-time\n        uint256 _withdrawEnableStartTime = block.timestamp + registry.getWithdrawRequestPendingPeriod();\n        address msgSender = _msgSender();\n        withdrawEnableStartTime[msgSender] = _withdrawEnableStartTime;\n        emit WithdrawRequest(msgSender, _withdrawEnableStartTime);\n    }\n\n    /** @notice See {IHATVault-withdrawAndClaim}. */\n    function withdrawAndClaim(uint256 assets, address receiver, address owner) external returns (uint256 shares) {\n        shares = withdraw(assets, receiver, owner);\n        _claimRewards(owner);\n    }\n\n    /** @notice See {IHATVault-redeemAndClaim}. */\n    function redeemAndClaim(uint256 shares, address receiver, address owner) external returns (uint256 assets) {\n        assets = redeem(shares, receiver, owner);\n        _claimRewards(owner);\n    }\n\n    /** @notice See {IHATVault-emergencyWithdraw}. */\n    function emergencyWithdraw(address receiver) external returns (uint256 assets) {\n        _isEmergencyWithdraw = true;\n        address msgSender = _msgSender();\n        assets = redeem(balanceOf(msgSender), receiver, msgSender);\n        _isEmergencyWithdraw = false;\n    }\n\n    /** @notice See {IHATVault-withdraw}. */\n    function withdraw(uint256 assets, address receiver, address owner) \n        public override(IHATVault, ERC4626Upgradeable) virtual returns (uint256) {\n        (uint256 _shares, uint256 _fee) = previewWithdrawAndFee(assets);\n        _withdraw(_msgSender(), receiver, owner, assets, _shares, _fee);\n\n        return _shares;\n    }\n\n    /** @notice See {IHATVault-redeem}. */\n    function redeem(uint256 shares, address receiver, address owner) \n        public override(IHATVault, ERC4626Upgradeable) virtual returns (uint256) {\n        (uint256 _assets, uint256 _fee) = previewRedeemAndFee(shares);\n        _withdraw(_msgSender(), receiver, owner, _assets, shares, _fee);\n\n        return _assets;\n    }\n\n    /** @notice See {IHATVault-deposit}. */\n    function deposit(uint256 assets, address receiver) public override(IHATVault, ERC4626Upgradeable) virtual returns (uint256) {\n        return super.deposit(assets, receiver);\n    }\n\n    /** @notice See {IHATVault-withdraw}. */\n    function withdraw(uint256 assets, address receiver, address owner, uint256 maxShares) public virtual returns (uint256) {\n        uint256 shares = withdraw(assets, receiver, owner);\n        if (shares > maxShares) revert WithdrawSlippageProtection();\n        return shares;\n    }\n\n    /** @notice See {IHATVault-redeem}. */\n    function redeem(uint256 shares, address receiver, address owner, uint256 minAssets) public virtual returns (uint256) {\n        uint256 assets = redeem(shares, receiver, owner);\n        if (assets < minAssets) revert RedeemSlippageProtection();\n        return assets;\n    }\n\n    /** @notice See {IHATVault-withdrawAndClaim}. */\n    function withdrawAndClaim(uint256 assets, address receiver, address owner, uint256 maxShares) external returns (uint256 shares) {\n        shares = withdraw(assets, receiver, owner, maxShares);\n        _claimRewards(owner);\n    }\n\n    /** @notice See {IHATVault-redeemAndClaim}. */\n    function redeemAndClaim(uint256 shares, address receiver, address owner, uint256 minAssets) external returns (uint256 assets) {\n        assets = redeem(shares, receiver, owner, minAssets);\n        _claimRewards(owner);\n    }\n\n    /** @notice See {IHATVault-deposit}. */\n    function deposit(uint256 assets, address receiver, uint256 minShares) external virtual returns (uint256) {\n        uint256 shares = deposit(assets, receiver);\n        if (shares < minShares) revert DepositSlippageProtection();\n        return shares;\n    }\n\n    /** @notice See {IHATVault-mint}. */\n    function mint(uint256 shares, address receiver, uint256 maxAssets) external virtual returns (uint256) {\n        uint256 assets = mint(shares, receiver);\n        if (assets > maxAssets) revert MintSlippageProtection();\n        return assets;\n    }\n\n    /** @notice See {IERC4626Upgradeable-maxDeposit}. */\n    function maxDeposit(address) public view virtual override(IERC4626Upgradeable, ERC4626Upgradeable) returns (uint256) {\n        return depositPause ? 0 : MAX_UINT;\n    }\n\n    /** @notice See {IERC4626Upgradeable-maxMint}. */\n    function maxMint(address) public view virtual override(IERC4626Upgradeable, ERC4626Upgradeable) returns (uint256) {\n        return depositPause ? 0 : MAX_UINT;\n    }\n\n    /** @notice See {IERC4626Upgradeable-maxWithdraw}. */\n    function maxWithdraw(address owner) public view virtual override(IERC4626Upgradeable, ERC4626Upgradeable) returns (uint256) {\n        if (withdrawPaused || !_isWithdrawEnabledForUser(owner)) return 0;\n        return previewRedeem(balanceOf(owner));\n    }\n\n    /** @notice See {IERC4626Upgradeable-maxRedeem}. */\n    function maxRedeem(address owner) public view virtual override(IERC4626Upgradeable, ERC4626Upgradeable) returns (uint256) {\n        if (withdrawPaused || !_isWithdrawEnabledForUser(owner)) return 0;\n        return balanceOf(owner);\n    }\n\n    /** @notice See {IERC4626Upgradeable-previewWithdraw}. */\n    function previewWithdraw(uint256 assets) public view virtual override(IERC4626Upgradeable, ERC4626Upgradeable) returns (uint256 shares) {\n        (shares,) = previewWithdrawAndFee(assets);\n    }\n\n    /** @notice See {IERC4626Upgradeable-previewRedeem}. */\n    function previewRedeem(uint256 shares) public view virtual override(IERC4626Upgradeable, ERC4626Upgradeable) returns (uint256 assets) {\n        (assets,) = previewRedeemAndFee(shares);\n    }\n\n    /** @notice See {IHATVault-previewWithdrawAndFee}. */\n    function previewWithdrawAndFee(uint256 assets) public view returns (uint256 shares, uint256 fee) {\n        uint256 _withdrawalFee = withdrawalFee;\n        fee = assets.mulDiv(_withdrawalFee, (HUNDRED_PERCENT - _withdrawalFee));\n        shares = _convertToShares(assets + fee, MathUpgradeable.Rounding.Up);\n    }\n\n    /** @notice See {IHATVault-previewRedeemAndFee}. */\n    function previewRedeemAndFee(uint256 shares) public view returns (uint256 assets, uint256 fee) {\n        uint256 _assetsPlusFee = _convertToAssets(shares, MathUpgradeable.Rounding.Down);\n        fee = _assetsPlusFee.mulDiv(withdrawalFee, HUNDRED_PERCENT);\n        unchecked { // fee will always be maximun 20% of _assetsPlusFee\n            assets = _assetsPlusFee - fee;\n        }\n    }\n\n    /* -------------------------------------------------------------------------------- */\n\n    /* --------------------------------- Helpers -------------------------------------- */\n\n    /**\n    * @dev Deposit funds to the vault. Can only be called if the committee had\n    * checked in and deposits are not paused.\n    * @param caller Caller of the action (msg.sender)\n    * @param receiver Reciever of the shares from the deposit\n    * @param assets Amount of vault's native token to deposit\n    * @param shares Respective amount of shares to be received\n    */\n    function _deposit(\n        address caller,\n        address receiver,\n        uint256 assets,\n        uint256 shares\n    ) internal override virtual nonReentrant {\n        if (!vaultStarted)\n            revert VaultNotStartedYet();\n        if (receiver == caller && withdrawEnableStartTime[receiver] != 0 ) {\n            // clear withdraw request if caller deposits in her own account\n            withdrawEnableStartTime[receiver] = 0;\n        }\n\n        super._deposit(caller, receiver, assets, shares);\n    }\n\n    // amount of shares correspond with assets + fee\n    function _withdraw(\n        address _caller,\n        address _receiver,\n        address _owner,\n        uint256 _assets,\n        uint256 _shares,\n        uint256 _fee\n    ) internal nonReentrant {\n        if (_assets == 0) revert WithdrawMustBeGreaterThanZero();\n        if (_caller != _owner) {\n            _spendAllowance(_owner, _caller, _shares);\n        }\n\n        _burn(_owner, _shares);\n\n        IERC20 _asset = IERC20(asset());\n        if (_fee > 0) {\n            _asset.safeTransfer(registry.owner(), _fee);\n        }\n        _asset.safeTransfer(_receiver, _assets);\n\n        emit Withdraw(_caller, _receiver, _owner, _assets, _shares);\n    }\n\n    /**\n    * @dev Claim rewards from the vault's reward controllers for the owner\n    * @param owner The owner of the rewards to claim for\n    */\n    function _claimRewards(address owner) internal {\n        for (uint256 i = 0; i < rewardControllers.length;) { \n            rewardControllers[i].claimReward(address(this), owner);\n            unchecked { ++i; }\n        }\n    }\n\n    function _beforeTokenTransfer(\n        address _from,\n        address _to,\n        uint256 _amount\n    ) internal virtual override {\n        if (_amount == 0) revert AmountCannotBeZero();\n        if (_from == _to) revert CannotTransferToSelf();\n        // deposit/mint/transfer\n        if (_to != address(0)) {\n            IHATVaultsRegistry _registry = registry;\n            if (_registry.isEmergencyPaused()) revert SystemInEmergencyPause();\n            // Cannot transfer or mint tokens to a user for which an active withdraw request exists\n            // because then we would need to reset their withdraw request\n            uint256 _withdrawEnableStartTime = withdrawEnableStartTime[_to];\n            if (_withdrawEnableStartTime != 0) {\n                // solhint-disable-next-line not-rely-on-time\n                if (block.timestamp <= _withdrawEnableStartTime + _registry.getWithdrawRequestEnablePeriod())\n                    revert CannotTransferToAnotherUserWithActiveWithdrawRequest();\n            }\n\n            for (uint256 i = 0; i < rewardControllers.length;) { \n                rewardControllers[i].commitUserBalance(_to, _amount, true);\n                unchecked { ++i; }\n            }\n        }\n        // withdraw/redeem/transfer\n        if (_from != address(0)) {\n            if (_amount > maxRedeem(_from)) revert RedeemMoreThanMax();\n            // if all is ok and withdrawal can be made - \n            // reset withdrawRequests[_pid][msg.sender] so that another withdrawRequest\n            // will have to be made before next withdrawal\n            withdrawEnableStartTime[_from] = 0;\n\n            if (!_isEmergencyWithdraw) {\n                for (uint256 i = 0; i < rewardControllers.length;) { \n                    rewardControllers[i].commitUserBalance(_from, _amount, false);\n                    unchecked { ++i; }\n                }\n            }\n        }\n    }\n\n    function _afterTokenTransfer(address, address, uint256) internal virtual override {\n        if (totalSupply() > 0 && totalSupply() < MINIMAL_AMOUNT_OF_SHARES) {\n          revert AmountOfSharesMustBeMoreThanMinimalAmount();\n        }\n    }\n\n    /**\n    * @dev Checks that the given user can perform a withdraw at this time\n    * @param _user Address of the user to check\n    */\n    function _isWithdrawEnabledForUser(address _user)\n        internal view\n        returns(bool)\n    {\n        IHATVaultsRegistry _registry = registry;\n        uint256 _withdrawPeriod = _registry.getWithdrawPeriod();\n        // disable withdraw for safetyPeriod (e.g 1 hour) after each withdrawPeriod (e.g 11 hours)\n        // solhint-disable-next-line not-rely-on-time\n        if (block.timestamp % (_withdrawPeriod + _registry.getSafetyPeriod()) >= _withdrawPeriod)\n            return false;\n        // check that withdrawRequestPendingPeriod had passed\n        uint256 _withdrawEnableStartTime = withdrawEnableStartTime[_user];\n        // solhint-disable-next-line not-rely-on-time\n        return (block.timestamp >= _withdrawEnableStartTime &&\n        // check that withdrawRequestEnablePeriod had not passed and that the\n        // last action was withdrawRequest (and not deposit or withdraw, which\n        // reset withdrawRequests[_user] to 0)\n        // solhint-disable-next-line not-rely-on-time\n            block.timestamp <= _withdrawEnableStartTime + _registry.getWithdrawRequestEnablePeriod());\n    }\n\n    function _addRewardController(IRewardController _rewardController) internal {\n        for (uint256 i = 0; i < rewardControllers.length;) { \n            if (_rewardController == rewardControllers[i]) revert DuplicatedRewardController();\n            unchecked { ++i; }\n        }\n        rewardControllers.push(_rewardController);\n        emit AddRewardController(_rewardController);\n    }\n\n    /* -------------------------------------------------------------------------------- */\n}\n"
      },
      "contracts/HATVaultsRegistry.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Disclaimer https://github.com/hats-finance/hats-contracts/blob/main/DISCLAIMER.md\n\npragma solidity 0.8.16;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport \"./tokenlock/TokenLockFactory.sol\";\nimport \"./interfaces/IHATVaultsRegistry.sol\";\nimport \"./interfaces/IHATVault.sol\";\n\n/** @title Registry to deploy Hats.finance vaults and manage shared parameters\n * @author Hats.finance\n * @notice Hats.finance is a proactive bounty protocol for white hat hackers and\n * security experts, where projects, community members, and stakeholders\n * incentivize protocol security and responsible disclosure.\n * Hats create scalable vaults using the project’s own token. The value of the\n * bounty increases with the success of the token and project.\n *\n * The owner of the registry has the permission to set time limits and bounty\n * parameters and change vaults' info, and to set the other registry roles -\n * fee setter and arbitrator.\n * The arbitrator can challenge submitted claims for bounty payouts made by\n * vaults' committees, approve them with a different bounty percentage or\n * dismiss them.\n * The fee setter can set the fee on withdrawals on all vaults.\n *\n * This project is open-source and can be found at:\n * https://github.com/hats-finance/hats-contracts\n *\n * @dev New hats.finance vaults should be created through a call to {createVault}\n * so that they are linked to the registry\n */\ncontract HATVaultsRegistry is IHATVaultsRegistry, Ownable {\n    using SafeERC20 for IERC20;\n    using Math for uint256;\n\n    // Used in {swapAndSend} to avoid a \"stack too deep\" error\n    struct SwapData {\n        uint256 amount;\n        uint256 amountUnused;\n        uint256 hatsReceived;\n        uint256 totalHackerReward;\n        uint256 governanceAmountSwapped;\n        uint256[] hackerRewards;\n        uint256 governanceHatReward;\n        uint256 usedPart;\n    }\n\n    uint16 public constant HUNDRED_PERCENT = 10000;\n    // the maximum percentage of the bounty that will be converted in HATs\n    uint16 public constant MAX_HAT_SPLIT = 3500;\n\n    address public hatVaultImplementation;\n    address public hatClaimsManagerImplementation;\n    address[] public hatVaults;\n    \n    // vault address => is visible\n    mapping(address => bool) public isVaultVisible;\n    // asset => hacker address => amount\n    mapping(address => mapping(address => uint256)) public hackersHatReward;\n    // asset => amount\n    mapping(address => uint256) public governanceHatReward;\n\n    // PARAMETERS FOR ALL VAULTS\n    IHATVaultsRegistry.GeneralParameters public generalParameters;\n    ITokenLockFactory public immutable tokenLockFactory;\n\n    // the token into which a part of the the bounty will be swapped into\n    IERC20 public HAT;\n    \n    // feeSetter sets the withdrawal fee\n    address public feeSetter;\n\n    // How the bountyGovernanceHAT and bountyHackerHATVested set how to divide the hats \n    // bounties of the vault, in percentages (out of `HUNDRED_PERCENT`)\n    // The precentages are taken from the total bounty\n \n    // the default percentage of the total bounty to be swapped to HATs and sent to governance\n    uint16 public defaultBountyGovernanceHAT;\n    // the default percentage of the total bounty to be swapped to HATs and sent to the hacker via vesting contract\n    uint16 public defaultBountyHackerHATVested;\n\n    address public defaultArbitrator;\n\n    bool public isEmergencyPaused;\n    uint32 public defaultChallengePeriod;\n    uint32 public defaultChallengeTimeOutPeriod;\n\n    /**\n    * @notice initialize -\n    * @param _hatVaultImplementation The hat vault implementation address.\n    * @param _hatClaimsManagerImplementation The hat claims manager implementation address.\n    * @param _hatGovernance The governance address.\n    * @param _HAT the HAT token address\n    * @param _bountyGovernanceHAT The default percentage of a claim's total\n    * bounty to be swapped for HAT and sent to the governance\n    * @param _bountyHackerHATVested The default percentage of a claim's total\n    * bounty to be swapped for HAT and sent to a vesting contract for the hacker\n    *   _bountyGovernanceHAT + _bountyHackerHATVested must be less\n    *    than `HUNDRED_PERCENT`.\n    * @param _tokenLockFactory Address of the token lock factory to be used\n    * to create a vesting contract for the approved claim reporter.\n    */\n    constructor(\n        address _hatVaultImplementation,\n        address _hatClaimsManagerImplementation,\n        address _hatGovernance,\n        address _defaultArbitrator,\n        address _HAT,\n        uint16 _bountyGovernanceHAT,\n        uint16 _bountyHackerHATVested,\n        ITokenLockFactory _tokenLockFactory\n    ) {\n        _transferOwnership(_hatGovernance);\n        hatVaultImplementation = _hatVaultImplementation;\n        hatClaimsManagerImplementation = _hatClaimsManagerImplementation;\n        HAT = IERC20(_HAT);\n\n        validateHATSplit(_bountyGovernanceHAT, _bountyHackerHATVested);\n        tokenLockFactory = _tokenLockFactory;\n        generalParameters = IHATVaultsRegistry.GeneralParameters({\n            hatVestingDuration: 90 days,\n            hatVestingPeriods: 90,\n            withdrawPeriod: 11 hours,\n            safetyPeriod: 1 hours,\n            setMaxBountyDelay: 2 days,\n            withdrawRequestEnablePeriod: 7 days,\n            withdrawRequestPendingPeriod: 7 days,\n            claimFee: 0\n        });\n\n        defaultBountyGovernanceHAT = _bountyGovernanceHAT;\n        defaultBountyHackerHATVested = _bountyHackerHATVested;\n        defaultArbitrator = _defaultArbitrator;\n        defaultChallengePeriod = 3 days;\n        defaultChallengeTimeOutPeriod = 125 days;\n        emit RegistryCreated(\n            _hatVaultImplementation,\n            _hatClaimsManagerImplementation,\n            _HAT,\n            address(_tokenLockFactory),\n            generalParameters,\n            _bountyGovernanceHAT,\n            _bountyHackerHATVested,\n            _hatGovernance,\n            _defaultArbitrator,\n            defaultChallengePeriod,\n            defaultChallengeTimeOutPeriod\n        );\n    }\n\n    /** @notice See {IHATVaultsRegistry-setVaultImplementations}. */\n    function setVaultImplementations(\n        address _hatVaultImplementation,\n        address _hatClaimsManagerImplementation\n    ) external onlyOwner {\n        hatVaultImplementation = _hatVaultImplementation;\n        hatClaimsManagerImplementation = _hatClaimsManagerImplementation;\n\n        emit SetHATVaultImplementation(_hatVaultImplementation);\n        emit SetHATClaimsManagerImplementation(_hatClaimsManagerImplementation);\n    }\n\n    /** @notice See {IHATVaultsRegistry-setSwapToken}. */\n    function setSwapToken(address _swapToken) external onlyOwner {\n        HAT = IERC20(_swapToken);\n        emit SetSwapToken(_swapToken);\n    }\n\n    /** @notice See {IHATVaultsRegistry-setEmergencyPaused}. */\n    function setEmergencyPaused(bool _isEmergencyPaused) external onlyOwner {\n        isEmergencyPaused = _isEmergencyPaused;\n        emit SetEmergencyPaused(_isEmergencyPaused);\n    }\n\n    /** @notice See {IHATVaultsRegistry-logClaim}. */\n    function logClaim(string calldata _descriptionHash) external payable {\n        uint256 _claimFee = generalParameters.claimFee;\n        if (_claimFee > 0) {\n            if (msg.value < _claimFee)\n                revert NotEnoughFeePaid();\n            // solhint-disable-next-line avoid-low-level-calls\n            (bool success,) = payable(owner()).call{value: msg.value}(\"\");\n            if (!success) revert ClaimFeeTransferFailed();\n        }\n        emit LogClaim(msg.sender, _descriptionHash);\n    }\n\n    /** @notice See {IHATVaultsRegistry-setDefaultHATBountySplit}. */\n    function setDefaultHATBountySplit(\n        uint16 _defaultBountyGovernanceHAT,\n        uint16 _defaultBountyHackerHATVested\n    ) external onlyOwner {\n        validateHATSplit(_defaultBountyGovernanceHAT, _defaultBountyHackerHATVested);\n        defaultBountyGovernanceHAT = _defaultBountyGovernanceHAT;\n        defaultBountyHackerHATVested = _defaultBountyHackerHATVested;\n        emit SetDefaultHATBountySplit(_defaultBountyGovernanceHAT, _defaultBountyHackerHATVested);\n\n    }\n   \n    /** @notice See {IHATVaultsRegistry-setDefaultArbitrator}. */\n    function setDefaultArbitrator(address _defaultArbitrator) external onlyOwner {\n        defaultArbitrator = _defaultArbitrator;\n        emit SetDefaultArbitrator(_defaultArbitrator);\n    }\n\n    /** @notice See {IHATVaultsRegistry-setDefaultChallengePeriod}. */\n    function setDefaultChallengePeriod(uint32 _defaultChallengePeriod) external onlyOwner {\n        validateChallengePeriod(_defaultChallengePeriod);\n        defaultChallengePeriod = _defaultChallengePeriod;\n        emit SetDefaultChallengePeriod(_defaultChallengePeriod);\n    }\n\n    /** @notice See {IHATVaultsRegistry-setDefaultChallengeTimeOutPeriod}. */\n    function setDefaultChallengeTimeOutPeriod(uint32 _defaultChallengeTimeOutPeriod) external onlyOwner {\n        validateChallengeTimeOutPeriod(_defaultChallengeTimeOutPeriod);\n        defaultChallengeTimeOutPeriod = _defaultChallengeTimeOutPeriod;\n        emit SetDefaultChallengeTimeOutPeriod(_defaultChallengeTimeOutPeriod);\n    }\n\n    /** @notice See {IHATVaultsRegistry-setFeeSetter}. */\n    function setFeeSetter(address _feeSetter) external onlyOwner {\n        feeSetter = _feeSetter;\n        emit SetFeeSetter(_feeSetter);\n    }\n\n    /** @notice See {IHATVaultsRegistry-setWithdrawRequestParams}. */\n    function setWithdrawRequestParams(uint32 _withdrawRequestPendingPeriod, uint32  _withdrawRequestEnablePeriod)\n        external \n        onlyOwner\n    {\n        if (_withdrawRequestPendingPeriod > 90 days)\n            revert WithdrawRequestPendingPeriodTooLong();\n        if (_withdrawRequestEnablePeriod < 6 hours)\n            revert WithdrawRequestEnabledPeriodTooShort();\n        if (_withdrawRequestEnablePeriod > 100 days)\n            revert WithdrawRequestEnabledPeriodTooLong();\n        generalParameters.withdrawRequestPendingPeriod = _withdrawRequestPendingPeriod;\n        generalParameters.withdrawRequestEnablePeriod = _withdrawRequestEnablePeriod;\n        emit SetWithdrawRequestParams(_withdrawRequestPendingPeriod, _withdrawRequestEnablePeriod);\n    }\n\n    /** @notice See {IHATVaultsRegistry-setClaimFee}. */\n    function setClaimFee(uint256 _fee) external onlyOwner {\n        generalParameters.claimFee = _fee;\n        emit SetClaimFee(_fee);\n    }\n\n    /** @notice See {IHATVaultsRegistry-setWithdrawSafetyPeriod}. */\n    function setWithdrawSafetyPeriod(uint32 _withdrawPeriod, uint32 _safetyPeriod) external onlyOwner { \n        if (_withdrawPeriod < 1 hours) revert WithdrawPeriodTooShort();\n        if (_safetyPeriod > 6 hours) revert SafetyPeriodTooLong();\n        generalParameters.withdrawPeriod = _withdrawPeriod;\n        generalParameters.safetyPeriod = _safetyPeriod;\n        emit SetWithdrawSafetyPeriod(_withdrawPeriod, _safetyPeriod);\n    }\n\n    /** @notice See {IHATVaultsRegistry-setHatVestingParams}. */\n    function setHatVestingParams(uint32 _duration, uint32 _periods) external onlyOwner {\n        if (_duration >= 180 days) revert HatVestingDurationTooLong();\n        if (_periods == 0) revert HatVestingPeriodsCannotBeZero();\n        if (_duration < _periods) revert HatVestingDurationSmallerThanPeriods();\n        generalParameters.hatVestingDuration = _duration;\n        generalParameters.hatVestingPeriods = _periods;\n        emit SetHatVestingParams(_duration, _periods);\n    }\n\n    /** @notice See {IHATVaultsRegistry-setMaxBountyDelay}. */\n    function setMaxBountyDelay(uint32 _delay) external onlyOwner {\n        if (_delay < 2 days) revert DelayTooShort();\n        generalParameters.setMaxBountyDelay = _delay;\n        emit SetMaxBountyDelay(_delay);\n    }\n\n    /** @notice See {IHATVaultsRegistry-createVault}. */\n    function createVault(\n        IHATVault.VaultInitParams calldata _vaultParams,\n        IHATClaimsManager.ClaimsManagerInitParams calldata _claimsManagerParams\n    ) external returns(address vault, address vaultClaimsManager) {\n        vault = Clones.clone(hatVaultImplementation);\n        vaultClaimsManager = Clones.clone(hatClaimsManagerImplementation);\n\n        IHATVault(vault).initialize(vaultClaimsManager, _vaultParams);\n        IHATClaimsManager(vaultClaimsManager).initialize(IHATVault(vault), _claimsManagerParams);\n\n        hatVaults.push(vault);\n\n        emit VaultCreated(vault, vaultClaimsManager, _vaultParams, _claimsManagerParams);\n    }\n\n    /** @notice See {IHATVaultsRegistry-setVaultVisibility}. */\n    function setVaultVisibility(address _vault, bool _visible) external onlyOwner {\n        isVaultVisible[_vault] = _visible;\n        emit SetVaultVisibility(_vault, _visible);\n    }\n\n    /** @notice See {IHATVaultsRegistry-addTokensToSwap}. */\n    function addTokensToSwap(\n        IERC20 _asset,\n        address _hacker,\n        uint256 _hackersHatReward,\n        uint256 _governanceHatReward\n    ) external {\n        hackersHatReward[address(_asset)][_hacker] += _hackersHatReward;\n        governanceHatReward[address(_asset)] += _governanceHatReward;\n        _asset.safeTransferFrom(msg.sender, address(this), _hackersHatReward + _governanceHatReward);\n    }\n\n    /** @notice See {IHATVaultsRegistry-swapAndSend}. */\n    function swapAndSend(\n        address _asset,\n        address[] calldata _beneficiaries,\n        uint256 _amountOutMinimum,\n        address _routingContract,\n        bytes calldata _routingPayload\n    ) external onlyOwner {\n        // Needed to avoid a \"stack too deep\" error\n        SwapData memory _swapData;\n        _swapData.hackerRewards = new uint256[](_beneficiaries.length);\n        _swapData.governanceHatReward = governanceHatReward[_asset];\n        _swapData.amount = _swapData.governanceHatReward;\n        for (uint256 i = 0; i < _beneficiaries.length;) { \n            _swapData.hackerRewards[i] = hackersHatReward[_asset][_beneficiaries[i]];\n            hackersHatReward[_asset][_beneficiaries[i]] = 0;\n            _swapData.amount += _swapData.hackerRewards[i]; \n            unchecked { ++i; }\n        }\n        if (_swapData.amount == 0) revert AmountToSwapIsZero();\n        IERC20 _HAT = HAT;\n        (_swapData.hatsReceived, _swapData.amountUnused) = _swapTokenForHAT(IERC20(_asset), _swapData.amount, _amountOutMinimum, _routingContract, _routingPayload);\n        \n        _swapData.usedPart = (_swapData.amount - _swapData.amountUnused);\n        _swapData.governanceAmountSwapped = _swapData.usedPart.mulDiv(_swapData.governanceHatReward, _swapData.amount);\n        governanceHatReward[_asset]  = _swapData.amountUnused.mulDiv(_swapData.governanceHatReward, _swapData.amount);\n\n        for (uint256 i = 0; i < _beneficiaries.length;) {\n            uint256 _hackerReward = _swapData.hatsReceived.mulDiv(_swapData.hackerRewards[i], _swapData.amount);\n            uint256 _hackerAmountSwapped = _swapData.usedPart.mulDiv(_swapData.hackerRewards[i], _swapData.amount);\n            _swapData.totalHackerReward += _hackerReward;\n            hackersHatReward[_asset][_beneficiaries[i]] = _swapData.amountUnused.mulDiv(_swapData.hackerRewards[i], _swapData.amount);\n            address _tokenLock;\n            if (_hackerReward > 0) {\n                // hacker gets her reward via vesting contract\n                _tokenLock = tokenLockFactory.createTokenLock(\n                    address(_HAT),\n                    0x0000000000000000000000000000000000000000, //this address as owner, so it can do nothing.\n                    _beneficiaries[i],\n                    _hackerReward,\n                    // solhint-disable-next-line not-rely-on-time\n                    block.timestamp, //start\n                    // solhint-disable-next-line not-rely-on-time\n                    block.timestamp + generalParameters.hatVestingDuration, //end\n                    generalParameters.hatVestingPeriods,\n                    0, // no release start\n                    0, // no cliff\n                    false, // not revocable\n                    true\n                );\n                _HAT.safeTransfer(_tokenLock, _hackerReward);\n            }\n            emit SwapAndSend(_beneficiaries[i], _hackerAmountSwapped, _hackerReward, _tokenLock);\n            unchecked { ++i; }\n        }\n        address _owner = owner(); \n        uint256 _amountToOwner = _swapData.hatsReceived - _swapData.totalHackerReward;\n        _HAT.safeTransfer(_owner, _amountToOwner);\n        emit SwapAndSend(_owner, _swapData.governanceAmountSwapped, _amountToOwner, address(0));\n    }\n\n    /** @notice See {IHATVaultsRegistry-getWithdrawPeriod}. */   \n      function getWithdrawPeriod() external view returns (uint256) {\n        return generalParameters.withdrawPeriod;\n    }\n\n    /** @notice See {IHATVaultsRegistry-getSafetyPeriod}. */   \n    function getSafetyPeriod() external view returns (uint256) {\n        return generalParameters.safetyPeriod;\n    }\n\n    /** @notice See {IHATVaultsRegistry-getWithdrawRequestEnablePeriod}. */   \n    function getWithdrawRequestEnablePeriod() external view returns (uint256) {\n        return generalParameters.withdrawRequestEnablePeriod;\n    }\n\n    /** @notice See {IHATVaultsRegistry-getWithdrawRequestPendingPeriod}. */   \n    function getWithdrawRequestPendingPeriod() external view returns (uint256) {\n        return generalParameters.withdrawRequestPendingPeriod;\n    }\n\n    /** @notice See {IHATVaultsRegistry-getSetMaxBountyDelay}. */   \n    function getSetMaxBountyDelay() external view returns (uint256) {\n        return generalParameters.setMaxBountyDelay;\n    }\n\n    /** @notice See {IHATVaultsRegistry-getNumberOfVaults}. */\n    function getNumberOfVaults() external view returns(uint256) {\n        return hatVaults.length;\n    }\n\n    function owner() public view override(IHATVaultsRegistry, Ownable) virtual returns (address) {\n        return Ownable.owner();\n    }\n\n    /** @notice See {IHATVaultsRegistry-validateHATSplit}. */\n    function validateHATSplit(uint16 _bountyGovernanceHAT, uint16 _bountyHackerHATVested) public pure {\n        if (_bountyGovernanceHAT + _bountyHackerHATVested > MAX_HAT_SPLIT)\n            revert TotalHatsSplitPercentageShouldBeUpToMaxHATSplit();\n    }\n\n    /** @notice See {IHATVaultsRegistry-validateChallengePeriod}. */\n    function validateChallengePeriod(uint32 _challengePeriod) public pure {\n        if (_challengePeriod < 1 days) revert ChallengePeriodTooShort();\n        if (_challengePeriod > 5 days) revert ChallengePeriodTooLong();\n    }\n\n    /** @notice See {IHATVaultsRegistry-validateChallengeTimeOutPeriod}. */\n    function validateChallengeTimeOutPeriod(uint32 _challengeTimeOutPeriod) public pure {\n        if (_challengeTimeOutPeriod < 2 days) revert ChallengeTimeOutPeriodTooShort();\n        if (_challengeTimeOutPeriod > 125 days) revert ChallengeTimeOutPeriodTooLong();\n    }\n    \n    /**\n    * @dev Use the given routing contract to swap the given token to HAT token\n    * @param _asset The token to swap\n    * @param _amount Amount of token to swap\n    * @param _amountOutMinimum Minimum amount of HAT tokens at swap\n    * @param _routingContract Routing contract to call for the swap\n    * @param _routingPayload Payload to send to the _routingContract for the \n    * swap\n    */\n    function _swapTokenForHAT(\n        IERC20 _asset,\n        uint256 _amount,\n        uint256 _amountOutMinimum,\n        address _routingContract,\n        bytes calldata _routingPayload)\n    internal\n    returns (uint256 hatsReceived, uint256 amountUnused)\n    {\n        IERC20 _HAT = HAT;\n        if (_asset == _HAT) {\n            return (_amount, 0);\n        }\n\n        IERC20(_asset).safeApprove(_routingContract, _amount);\n        uint256 _balanceBefore = _HAT.balanceOf(address(this));\n        uint256 _assetBalanceBefore = _asset.balanceOf(address(this));\n\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool success,) = _routingContract.call(_routingPayload);\n        if (!success) revert SwapFailed();\n        hatsReceived = _HAT.balanceOf(address(this)) - _balanceBefore;\n        amountUnused = _amount - (_assetBalanceBefore - _asset.balanceOf(address(this)));\n        if (hatsReceived < _amountOutMinimum)\n            revert AmountSwappedLessThanMinimum();\n\n        IERC20(_asset).safeApprove(address(_routingContract), 0);\n    }\n}\n"
      },
      "contracts/interfaces/IHATClaimsManager.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Disclaimer https://github.com/hats-finance/hats-contracts/blob/main/DISCLAIMER.md\n\npragma solidity 0.8.16;\n\nimport \"@openzeppelin/contracts-upgradeable/interfaces/IERC4626Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./IRewardController.sol\";\nimport \"./IHATVault.sol\";\nimport \"./IHATVaultsRegistry.sol\";\n\n/** @title Interface for Hats.finance Vaults\n * @author Hats.finance\n * @notice A HATVault holds the funds for a specific project's bug bounties.\n * Anyone can permissionlessly deposit into the HATVault using\n * the vault’s native token. When a bug is submitted and approved, the bounty \n * is paid out using the funds in the vault. Bounties are paid out as a\n * percentage of the vault. The percentage is set according to the severity of\n * the bug. Vaults have regular safety periods (typically for an hour twice a\n * day) which are time for the committee to make decisions.\n *\n * In addition to the roles defined in the IHATVaultsRegistry, every HATVault \n * has the roles:\n * Committee - The only address which can submit a claim for a bounty payout\n * and set the maximum bounty.\n * User - Anyone can deposit the vault's native token into the vault and \n * recieve shares for it. Shares represent the user's relative part in the\n * vault, and when a bounty is paid out, users lose part of their deposits\n * (based on percentage paid), but keep their share of the vault.\n * Users also receive rewards for their deposits, which can be claimed at any\n *  time.\n * To withdraw previously deposited tokens, a user must first send a withdraw\n * request, and the withdrawal will be made available after a pending period.\n * Withdrawals are not permitted during safety periods or while there is an \n * active claim for a bounty payout.\n *\n * Bounties are payed out distributed between a few channels, and that \n * distribution is set upon creation (the hacker gets part in direct transfer,\n * part in vested reward and part in vested HAT token, part gets rewarded to\n * the committee, part gets swapped to HAT token and burned and/or sent to Hats\n * governance).\n *\n * NOTE: Vaults should not use tokens which do not guarantee that the amount\n * specified is the amount transferred\n *\n * This project is open-source and can be found at:\n * https://github.com/hats-finance/hats-contracts\n */\ninterface IHATClaimsManager {\n\n    // How to divide the bounty - after deducting the part that is swapped to\n    // HAT tokens (and then sent to governance and vested to the hacker)\n    // values are in percentages and should add up to 100% (defined as 10000)\n    struct BountySplit {\n        // the percentage of reward sent to the hacker via vesting contract\n        uint16 hackerVested;\n        // the percentage of tokens that are sent directly to the hacker\n        uint16 hacker;\n        // the percentage sent to the committee\n        uint16 committee;\n    }\n\n    // How to divide a bounty for a claim that has been approved\n    // used to keep track of payouts, amounts are in vault's native token\n    struct ClaimBounty {\n        uint256 hacker;\n        uint256 hackerVested;\n        uint256 committee;\n        uint256 hackerHatVested;\n        uint256 governanceHat;\n    }\n\n    struct Claim {\n        bytes32 claimId;\n        address beneficiary;\n        uint16 bountyPercentage;\n        // the address of the committee at the time of the submission, so that this committee will\n        // be paid their share of the bounty in case the committee changes before claim approval\n        address committee;\n        uint32 createdAt;\n        uint32 challengedAt;\n        uint256 bountyGovernanceHAT;\n        uint256 bountyHackerHATVested;\n        address arbitrator;\n        uint32 challengePeriod;\n        uint32 challengeTimeOutPeriod;\n        bool arbitratorCanChangeBounty;\n        bool arbitratorCanChangeBeneficiary;\n    }\n\n    struct PendingMaxBounty {\n        uint16 maxBounty;\n        uint32 timestamp;\n    }\n\n    /**\n    * @notice Initialization parameters for the vault\n    * @param name The vault's name (concatenated as \"Hats Vault \" + name)\n    * @param symbol The vault's symbol (concatenated as \"HAT\" + symbol)\n    * @param rewardController The reward controller for the vault\n    * @param vestingDuration Duration of the vesting period of the vault's\n    * token vested part of the bounty\n    * @param vestingPeriods The number of vesting periods of the vault's token\n    * vested part of the bounty\n    * @param maxBounty The maximum percentage of the vault that can be paid\n    * out as a bounty\n    * @param bountySplit The way to split the bounty between the hacker, \n    * hacker vested, and committee.\n    *   Each entry is a number between 0 and `HUNDRED_PERCENT`.\n    *   Total splits should be equal to `HUNDRED_PERCENT`.\n    * @param bountyGovernanceHAT The HAT bounty for governance\n    * @param bountyHackerHATVested The HAT bounty vested for the hacker\n    * @param asset The vault's native token\n    * @param owner The address of the vault's owner \n    * @param committee The address of the vault's committee \n    * @param arbitrator The address of the vault's arbitrator\n    * @param arbitratorCanChangeBounty Can the arbitrator change a claim's bounty\n    * @param arbitratorCanChangeBeneficiary Can the arbitrator change a claim's beneficiary\n    * @param arbitratorCanSubmitClaims Can the arbitrator submit a claim\n    * @param isTokenLockRevocable can the committee revoke the token lock\n    * @dev Needed to avoid a \"stack too deep\" error\n    */\n    struct ClaimsManagerInitParams {\n        uint32 vestingDuration;\n        uint32 vestingPeriods;\n        uint16 maxBounty;\n        BountySplit bountySplit;\n        uint16 bountyGovernanceHAT;\n        uint16 bountyHackerHATVested;\n        address owner;\n        address committee;\n        address arbitrator;\n        bool arbitratorCanChangeBounty;\n        bool arbitratorCanChangeBeneficiary;\n        bool arbitratorCanSubmitClaims;\n        bool isTokenLockRevocable;\n    }\n\n    // Only committee\n    error OnlyCommittee();\n    // Active claim exists\n    error ActiveClaimExists();\n    // Safety period\n    error SafetyPeriod();\n    // Not safety period\n    error NotSafetyPeriod();\n    // Bounty percentage is higher than the max bounty\n    error BountyPercentageHigherThanMaxBounty();\n    // Only callable by arbitrator or after challenge timeout period\n    error OnlyCallableByArbitratorOrAfterChallengeTimeOutPeriod();\n    // No active claim exists\n    error NoActiveClaimExists();\n    // Claim Id specified is not the active claim Id\n    error ClaimIdIsNotActive();\n    // Not enough fee paid\n    error NotEnoughFeePaid();\n    // No pending max bounty\n    error NoPendingMaxBounty();\n    // Delay period for setting max bounty had not passed\n    error DelayPeriodForSettingMaxBountyHadNotPassed();\n    // Committee already checked in\n    error CommitteeAlreadyCheckedIn();\n    // Total bounty split % should be `HUNDRED_PERCENT`\n    error TotalSplitPercentageShouldBeHundredPercent();\n    // Vesting duration is too long\n    error VestingDurationTooLong();\n    // Vesting periods cannot be zero\n    error VestingPeriodsCannotBeZero();\n    // Vesting duration smaller than periods\n    error VestingDurationSmallerThanPeriods();\n    // Max bounty cannot be more than `MAX_BOUNTY_LIMIT` (unless if it is 100%)\n    error MaxBountyCannotBeMoreThanMaxBountyLimit();\n    // Committee bounty split cannot be more than `MAX_COMMITTEE_BOUNTY`\n    error CommitteeBountyCannotBeMoreThanMax();\n    // Only registry owner\n    error OnlyRegistryOwner();\n    // Set shares arrays must have same length\n    error SetSharesArraysMustHaveSameLength();\n    // Not enough user balance\n    error NotEnoughUserBalance();\n    // Only arbitrator or registry owner\n    error OnlyArbitratorOrRegistryOwner();\n    // Unchallenged claim can only be approved if challenge period is over\n    error UnchallengedClaimCanOnlyBeApprovedAfterChallengePeriod();\n    // Challenged claim can only be approved by arbitrator before the challenge timeout period\n    error ChallengedClaimCanOnlyBeApprovedByArbitratorUntilChallengeTimeoutPeriod();\n    // Claim has expired\n    error ClaimExpired();\n    // Challenge period is over\n    error ChallengePeriodEnded();\n    // Claim can be challenged only once\n    error ClaimAlreadyChallenged();\n    // Only callable if challenged\n    error OnlyCallableIfChallenged();\n    // System is in an emergency pause\n    error SystemInEmergencyPause();\n    // Cannot set a reward controller that was already used in the past\n    error CannotSetToPerviousRewardController();\n    // Payout must either be 100%, or up to the MAX_BOUNTY_LIMIT\n    error PayoutMustBeUpToMaxBountyLimitOrHundredPercent();\n\n\n    event SubmitClaim(\n        bytes32 indexed _claimId,\n        address _committee,\n        address indexed _submitter,\n        address indexed _beneficiary,\n        uint256 _bountyPercentage,\n        string _descriptionHash\n    );\n    event ChallengeClaim(bytes32 indexed _claimId);\n    event ApproveClaim(\n        bytes32 indexed _claimId,\n        address _committee,\n        address indexed _approver,\n        address indexed _beneficiary,\n        uint256 _bountyPercentage,\n        address _tokenLock,\n        ClaimBounty _claimBounty\n    );\n    event DismissClaim(bytes32 indexed _claimId);\n    event SetCommittee(address indexed _committee);\n    event SetVestingParams(\n        uint256 _duration,\n        uint256 _periods\n    );\n    event SetBountySplit(BountySplit _bountySplit);\n    event CommitteeCheckedIn();\n    event SetPendingMaxBounty(uint256 _maxBounty);\n    event SetMaxBounty(uint256 _maxBounty);\n    event SetHATBountySplit(uint256 _bountyGovernanceHAT, uint256 _bountyHackerHATVested);\n    event SetArbitrator(address indexed _arbitrator);\n    event SetChallengePeriod(uint256 _challengePeriod);\n    event SetChallengeTimeOutPeriod(uint256 _challengeTimeOutPeriod);\n    event SetArbitratorOptions(bool _arbitratorCanChangeBounty, bool _arbitratorCanChangeBeneficiary, bool _arbitratorCanSubmitClaims);\n\n    /**\n    * @notice Initialize a claims manager instance\n    * @param _vault The vault instance\n    * @param _params The claim manager's initialization parameters\n    * @dev See {IHATClaimsManager-ClaimsManagerInitParams} for more details\n    * @dev Called when the vault is created in {IHATVaultsRegistry-createVault}\n    */\n    function initialize(IHATVault _vault, ClaimsManagerInitParams calldata _params) external;\n\n    /* -------------------------------------------------------------------------------- */\n\n    /* ---------------------------------- Claim --------------------------------------- */\n\n    /**\n     * @notice Called by the committee to submit a claim for a bounty payout.\n     * This function should be called only on a safety period, when withdrawals\n     * are disabled, and while there's no other active claim. Cannot be called\n     * when the registry is in an emergency pause.\n     * Upon a call to this function by the committee the vault's withdrawals\n     * will be disabled until the claim is approved or dismissed. Also from the\n     * time of this call the arbitrator will have a period of \n     * {IHATVaultsRegistry.challengePeriod} to challenge the claim.\n     * @param _beneficiary The submitted claim's beneficiary\n     * @param _bountyPercentage The submitted claim's bug requested reward percentage\n     */\n    function submitClaim(\n        address _beneficiary, \n        uint16 _bountyPercentage, \n        string calldata _descriptionHash\n    )\n        external\n        returns (bytes32 claimId);\n\n   \n    /**\n    * @notice Called by the arbitrator or governance to challenge a claim for a bounty\n    * payout that had been previously submitted by the committee.\n    * Can only be called during the challenge period after submission of the\n    * claim.\n    * @param _claimId The claim ID\n    */\n    function challengeClaim(bytes32 _claimId) external;\n\n    /**\n    * @notice Approve a claim for a bounty submitted by a committee, and\n    * pay out bounty to hacker and committee. Also transfer to the \n    * IHATVaultsRegistry the part of the bounty that will be swapped to HAT \n    * tokens.\n    * If the claim had been previously challenged, this is only callable by\n    * the arbitrator. Otherwise, callable by anyone after challengePeriod had\n    * passed.\n    * @param _claimId The claim ID\n    * @param _bountyPercentage The percentage of the vault's balance that will\n    * be sent as a bounty. This value will be ignored if the caller is not the\n    * arbitrator.\n    * @param _beneficiary where the bounty will be sent to. This value will be \n    * ignored if the caller is not the arbitrator.\n    */\n    function approveClaim(bytes32 _claimId, uint16 _bountyPercentage, address _beneficiary)\n        external;\n\n    /**\n    * @notice Dismiss the active claim for bounty payout submitted by the\n    * committee.\n    * Called either by the arbitrator, or by anyone if the claim has timed out.\n    * @param _claimId The claim ID\n    */\n    function dismissClaim(bytes32 _claimId) external;\n\n    /* -------------------------------------------------------------------------------- */\n\n    /* ---------------------------------- Params -------------------------------------- */\n\n    /**\n    * @notice Set new committee address. Can be called by existing committee,\n    * or by the the vault's owner in the case that the committee hadn't checked in\n    * yet.\n    * @param _committee The address of the new committee \n    */\n    function setCommittee(address _committee) external;\n\n    /**\n    * @notice Called by the vault's owner to set the vesting params for the\n    * part of the bounty that the hacker gets vested in the vault's native\n    * token\n    * @param _duration Duration of the vesting period. Must be smaller than\n    * 120 days and bigger than `_periods`\n    * @param _periods Number of vesting periods. Cannot be 0.\n    */\n    function setVestingParams(uint32 _duration, uint32 _periods) external;\n\n    /**\n    * @notice Called by the vault's owner to set the vault token bounty split\n    * upon an approval.\n    * Can only be called if is no active claim and not during safety periods.\n    * @param _bountySplit The bounty split\n    */\n    function setBountySplit(BountySplit calldata _bountySplit) external;\n\n    /**\n    * @notice Called by the vault's committee to claim it's role.\n    * Deposits are enabled only after committee check in.\n    */\n    function committeeCheckIn() external;\n\n    /**\n    * @notice Called by the vault's owner to set a pending request for the\n    * maximum percentage of the vault that can be paid out as a bounty.\n    * Cannot be called if there is an active claim that has been submitted.\n    * Max bounty should be less than or equal to 90% (defined as 9000).\n    * It can also be set to 100%, but in this mode the vault will only allow\n    * payouts of the 100%, and the vault will become inactive forever afterwards.\n    * The pending value can be set by the owner after the time delay (of \n    * {IHATVaultsRegistry.generalParameters.setMaxBountyDelay}) had passed.\n    * @param _maxBounty The maximum bounty percentage that can be paid out\n    */\n    function setPendingMaxBounty(uint16 _maxBounty) external;\n\n    /**\n    * @notice Called by the vault's owner to set the vault's max bounty to\n    * the already pending max bounty.\n    * Cannot be called if there are active claims that have been submitted.\n    * Can only be called if there is a max bounty pending approval, and the\n    * time delay since setting the pending max bounty had passed.\n    */\n    function setMaxBounty() external;\n\n    /**\n    * @notice Called by the registry's owner to set the vault HAT token bounty \n    * split upon an approval.\n    * If the value passed is the special \"null\" value the vault will use the\n    * registry's default value.\n    * @param _bountyGovernanceHAT The HAT bounty for governance\n    * @param _bountyHackerHATVested The HAT bounty vested for the hacker\n    */\n    function setHATBountySplit(\n        uint16 _bountyGovernanceHAT,\n        uint16 _bountyHackerHATVested\n    ) \n        external;\n\n    /**\n    * @notice Called by the registry's owner to set the vault arbitrator\n    * If the value passed is the special \"null\" value the vault will use the\n    * registry's default value.\n    * @param _arbitrator The address of vault's arbitrator\n    */\n    function setArbitrator(address _arbitrator) external;\n\n    /**\n    * @notice Called by the registry's owner to set the period of time after\n    * a claim for a bounty payout has been submitted that it can be challenged\n    * by the arbitrator.\n    * If the value passed is the special \"null\" value the vault will use the\n    * registry's default value.\n    * @param _challengePeriod The vault's challenge period\n    */\n    function setChallengePeriod(uint32 _challengePeriod) external;\n\n    /**\n    * @notice Called by the registry's owner to set the period of time after\n    * which a claim for a bounty payout can be dismissed by anyone.\n    * If the value passed is the special \"null\" value the vault will use the\n    * registry's default value.\n    * @param _challengeTimeOutPeriod The vault's challenge timeout period\n    */\n    function setChallengeTimeOutPeriod(uint32 _challengeTimeOutPeriod)\n        external;\n\n    /**\n    * @notice Called by the registry's owner to set whether the arbitrator\n    * can change a claim bounty percentage and/ or beneficiary\n    * If the value passed is the special \"null\" value the vault will use the\n    * registry's default value.\n    * @param _arbitratorCanChangeBounty Whether the arbitrator can change a claim bounty percentage\n    * @param _arbitratorCanChangeBeneficiary Whether the arbitrator can change a claim beneficiary\n    */\n    function setArbitratorOptions(\n        bool _arbitratorCanChangeBounty,\n        bool _arbitratorCanChangeBeneficiary,\n        bool _arbitratorCanSubmitClaims\n    )\n        external;\n\n    /* -------------------------------------------------------------------------------- */\n\n    /* --------------------------------- Getters -------------------------------------- */\n\n    /** \n    * @notice Returns the max bounty that can be paid from the vault in percentages out of HUNDRED_PERCENT\n    * @return The max bounty\n    */\n    function maxBounty() external view returns(uint16);\n\n    /** \n    * @notice Returns the vault's registry\n    * @return The registry's address\n    */\n    function registry() external view returns(IHATVaultsRegistry);\n\n    /** \n    * @notice Returns whether the committee has checked in\n    * @return Whether the committee has checked in\n    */\n    function committeeCheckedIn() external view returns(bool);\n\n    /** \n    * @notice Returns the current active claim\n    * @return The current active claim\n    */\n    function getActiveClaim() external view returns(Claim memory);\n\n    /** \n    * @notice Returns the vault HAT bounty split part that goes to the governance\n    * If no specific value for this vault has been set, the registry's default\n    * value will be returned.\n    * @return The vault's HAT bounty split part that goes to the governance\n    */\n    function getBountyGovernanceHAT() external view returns(uint16);\n    \n    /** \n    * @notice Returns the vault HAT bounty split part that is vested for the hacker\n    * If no specific value for this vault has been set, the registry's default\n    * value will be returned.\n    * @return The vault's HAT bounty split part that is vested for the hacker\n    */\n    function getBountyHackerHATVested() external view returns(uint16);\n\n    /** \n    * @notice Returns the address of the vault's arbitrator\n    * If no specific value for this vault has been set, the registry's default\n    * value will be returned.\n    * @return The address of the vault's arbitrator\n    */\n    function getArbitrator() external view returns(address);\n\n    /** \n    * @notice Returns the period of time after a claim for a bounty payout has\n    * been submitted that it can be challenged by the arbitrator.\n    * If no specific value for this vault has been set, the registry's default\n    * value will be returned.\n    * @return The vault's challenge period\n    */\n    function getChallengePeriod() external view returns(uint32);\n\n    /** \n    * @notice Returns the period of time after which a claim for a bounty\n    * payout can be dismissed by anyone.\n    * If no specific value for this vault has been set, the registry's default\n    * value will be returned.\n    * @return The vault's challenge timeout period\n    */\n    function getChallengeTimeOutPeriod() external view returns(uint32);\n\n    /** \n    * @notice Returns the claims manager's version\n    * @return The claims manager's version\n    */\n    function VERSION() external view returns(string calldata);\n}\n"
      },
      "contracts/interfaces/IHATVault.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Disclaimer https://github.com/hats-finance/hats-contracts/blob/main/DISCLAIMER.md\n\npragma solidity 0.8.16;\n\nimport \"@openzeppelin/contracts-upgradeable/interfaces/IERC4626Upgradeable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./IRewardController.sol\";\nimport \"./IHATVaultsRegistry.sol\";\nimport \"./IHATClaimsManager.sol\";\n\n/** @title Interface for Hats.finance Vaults\n * @author Hats.finance\n * @notice A HATVault holds the funds for a specific project's bug bounties.\n * Anyone can permissionlessly deposit into the HATVault using\n * the vault’s native token. When a bug is submitted and approved, the bounty \n * is paid out using the funds in the vault. Bounties are paid out as a\n * percentage of the vault. The percentage is set according to the severity of\n * the bug. Vaults have regular safety periods (typically for an hour twice a\n * day) which are time for the committee to make decisions.\n *\n * In addition to the roles defined in the HATVaultsRegistry, every HATVault \n * has the roles:\n * Committee - The only address which can submit a claim for a bounty payout\n * and set the maximum bounty.\n * User - Anyone can deposit the vault's native token into the vault and \n * recieve shares for it. Shares represent the user's relative part in the\n * vault, and when a bounty is paid out, users lose part of their deposits\n * (based on percentage paid), but keep their share of the vault.\n * Users also receive rewards for their deposits, which can be claimed at any\n *  time.\n * To withdraw previously deposited tokens, a user must first send a withdraw\n * request, and the withdrawal will be made available after a pending period.\n * Withdrawals are not permitted during safety periods or while there is an \n * active claim for a bounty payout.\n *\n * Bounties are payed out distributed between a few channels, and that \n * distribution is set upon creation (the hacker gets part in direct transfer,\n * part in vested reward and part in vested HAT token, part gets rewarded to\n * the committee, part gets swapped to HAT token and burned and/or sent to Hats\n * governance).\n *\n * NOTE: Vaults should not use tokens which do not guarantee that the amount\n * specified is the amount transferred\n *\n * This project is open-source and can be found at:\n * https://github.com/hats-finance/hats-contracts\n */\ninterface IHATVault is IERC4626Upgradeable {\n\n    /**\n    * @notice Initialization parameters for the vault token\n    * @param name The vault's name (concatenated as \"Hats Vault \" + name)\n    * @param symbol The vault's symbol (concatenated as \"HAT\" + symbol)\n    * @param rewardController The reward controller for the vault\n    * @param asset The vault's native token\n    * @param owner The address of the vault's owner \n    * @param isPaused Whether to initialize the vault with deposits disabled\n    * @param descriptionHash The hash of the vault's description\n    */\n    struct VaultInitParams {\n        string name;\n        string symbol;\n        IRewardController[] rewardControllers;\n        IERC20 asset;\n        address owner;\n        bool isPaused;\n        string descriptionHash;\n    }\n\n    // Only claims manager can make this call\n    error OnlyClaimsManager();\n    // Only registry owner\n    error OnlyRegistryOwner();\n    // Vault not started yet\n    error VaultNotStartedYet();\n    // First deposit must return at least MINIMAL_AMOUNT_OF_SHARES\n    error AmountOfSharesMustBeMoreThanMinimalAmount();\n    // Withdraw amount must be greater than zero\n    error WithdrawMustBeGreaterThanZero();\n    // Cannot mint burn or transfer 0 amount of shares\n    error AmountCannotBeZero();\n    // Cannot transfer shares to self\n    error CannotTransferToSelf();\n    // Cannot deposit to another user with withdraw request\n    error CannotTransferToAnotherUserWithActiveWithdrawRequest();\n    // Redeem amount cannot be more than maximum for user\n    error RedeemMoreThanMax();\n    // Deposit passed max slippage\n    error DepositSlippageProtection();\n    // Mint passed max slippage\n    error MintSlippageProtection();\n    // Withdraw passed max slippage\n    error WithdrawSlippageProtection();\n    // Redeem passed max slippage\n    error RedeemSlippageProtection();\n    // Cannot add the same reward controller more than once\n    error DuplicatedRewardController();\n    // Fee must be less than or equal to 2%\n    error WithdrawalFeeTooBig();\n    // System is in an emergency pause\n    error SystemInEmergencyPause();\n    // Only fee setter\n    error OnlyFeeSetter();\n    // Cannot unpasue deposits for a vault that was destroyed\n    error CannotUnpauseDestroyedVault();\n\n    event AddRewardController(IRewardController indexed _newRewardController);\n    event SetWithdrawalFee(uint256 _newFee);\n    event VaultPayout(uint256 _amount);\n    event SetDepositPause(bool _depositPause);\n    event SetWithdrawPaused(bool _withdrawPaused);\n    event VaultStarted();\n    event VaultDestroyed();\n    event SetVaultDescription(string _descriptionHash);\n    event WithdrawRequest(\n        address indexed _beneficiary,\n        uint256 _withdrawEnableTime\n    );\n\n    /**\n    * @notice Initialize a vault token instance\n    * @param _claimsManager The vault's claims manager\n    * @param _params The vault token initialization parameters\n    * @dev See {IHATVault-VaultInitParams} for more details\n    * @dev Called when the vault token is created in {IHATVaultsRegistry-createVault}\n    */\n    function initialize(address _claimsManager, VaultInitParams calldata _params) external;\n\n    /**\n    * @notice Adds a reward controller to the reward controllers list\n    * @param _rewardController The reward controller to add\n    */\n    function addRewardController(IRewardController _rewardController) external;\n\n    /**\n    * @notice Called by the vault's owner to disable all deposits to the vault\n    * @param _depositPause Are deposits paused\n    */\n    function setDepositPause(bool _depositPause) external;\n\n    /**\n    * @notice Called by the registry's fee setter to set the fee for \n    * withdrawals from the vault.\n    * @param _fee The new fee. Must be smaller than or equal to `MAX_WITHDRAWAL_FEE`\n    */\n    function setWithdrawalFee(uint256 _fee) external;\n\n    /**\n    * @notice Make a payout out of the vault\n    * @param _amount The amount to send out for the payout\n    */\n    function makePayout(uint256 _amount) external;\n\n    /**\n    * @notice Called by the vault's claims manager to disable all withdrawals from the vault\n    * @param _withdrawPaused Are withdraws paused\n    */\n    function setWithdrawPaused(bool _withdrawPaused) external;\n\n    /**\n    * @notice Start the vault, deposits are disabled until the vault is first started\n    */\n    function startVault() external;\n\n\n    /**\n    * @notice Permanently disables deposits to the vault\n    */\n    function destroyVault() external;\n\n    /**\n    * @notice Called by the registry's owner to change the description of the\n    * vault in the Hats.finance UI\n    * @param _descriptionHash the hash of the vault's description\n    */\n    function setVaultDescription(string calldata _descriptionHash) external;\n    \n    /** \n    * @notice Returns the vault's version\n    * @return The vault's version\n    */\n    function VERSION() external view returns(string calldata);\n\n    /** \n    * @notice Returns the vault's registry\n    * @return The registry's address\n    */\n    function registry() external view returns(IHATVaultsRegistry);\n\n    /** \n    * @notice Returns the vault's registry\n    * @return The registry's address\n    */\n    function claimsManager() external view returns(address);\n\n    /**\n    * @notice Submit a request to withdraw funds from the vault.\n    * The request will only be approved if there is no previous active\n    * withdraw request.\n    * The request will be pending for a period of\n    * {HATVaultsRegistry.generalParameters.withdrawRequestPendingPeriod},\n    * after which a withdraw will be possible for a duration of\n    * {HATVaultsRegistry.generalParameters.withdrawRequestEnablePeriod}\n    */\n    function withdrawRequest() external;\n\n    /** \n    * @notice Withdraw previously deposited funds from the vault and claim\n    * the HAT reward that the user has earned.\n    * Can only be performed if a withdraw request has been previously\n    * submitted, and the pending period had passed, and while the withdraw\n    * enabled timeout had not passed. Withdrawals are not permitted during\n    * safety periods or while there is an active claim for a bounty payout.\n    * @param assets Amount of tokens to withdraw\n    * @param receiver Address of receiver of the funds\n    * @param owner Address of owner of the funds\n    * @dev See {IERC4626-withdraw}.\n    */\n    function withdrawAndClaim(uint256 assets, address receiver, address owner)\n        external \n        returns (uint256 shares);\n\n    /** \n    * @notice Redeem shares in the vault for the respective amount\n    * of underlying assets and claim the HAT reward that the user has earned.\n    * Can only be performed if a withdraw request has been previously\n    * submitted, and the pending period had passed, and while the withdraw\n    * enabled timeout had not passed. Withdrawals are not permitted during\n    * safety periods or while there is an active claim for a bounty payout.\n    * @param shares Amount of shares to redeem\n    * @param receiver Address of receiver of the funds \n    * @param owner Address of owner of the funds \n    * @dev See {IERC4626-redeem}.\n    */\n    function redeemAndClaim(uint256 shares, address receiver, address owner)\n        external \n        returns (uint256 assets);\n\n    /** \n    * @notice Redeem all of the user's shares in the vault for the respective amount\n    * of underlying assets without calling the reward controller, meaning user renounces\n    * their uncommited part of the reward.\n    * Can only be performed if a withdraw request has been previously\n    * submitted, and the pending period had passed, and while the withdraw\n    * enabled timeout had not passed. Withdrawals are not permitted during\n    * safety periods or while there is an active claim for a bounty payout.\n    * @param receiver Address of receiver of the funds \n    */\n    function emergencyWithdraw(address receiver) external returns (uint256 assets);\n\n    /** \n    * @notice Withdraw previously deposited funds from the vault, without\n    * transferring the accumulated rewards.\n    * Can only be performed if a withdraw request has been previously\n    * submitted, and the pending period had passed, and while the withdraw\n    * enabled timeout had not passed. Withdrawals are not permitted during\n    * safety periods or while there is an active claim for a bounty payout.\n    * @param assets Amount of tokens to withdraw\n    * @param receiver Address of receiver of the funds \n    * @param owner Address of owner of the funds \n    * @dev See {IERC4626-withdraw}.\n    */\n    function withdraw(uint256 assets, address receiver, address owner)\n        external \n        returns (uint256);\n\n    /** \n    * @notice Redeem shares in the vault for the respective amount\n    * of underlying assets, without transferring the accumulated reward.\n    * Can only be performed if a withdraw request has been previously\n    * submitted, and the pending period had passed, and while the withdraw\n    * enabled timeout had not passed. Withdrawals are not permitted during\n    * safety periods or while there is an active claim for a bounty payout.\n    * @param shares Amount of shares to redeem\n    * @param receiver Address of receiver of the funds \n    * @param owner Address of owner of the funds \n    * @dev See {IERC4626-redeem}.\n    */\n    function redeem(uint256 shares, address receiver, address owner)\n        external  \n        returns (uint256);\n\n    /**\n    * @dev Deposit funds to the vault. Can only be called if the committee had\n    * checked in and deposits are not paused, and the registry is not in an emergency pause.\n    * @param receiver Reciever of the shares from the deposit\n    * @param assets Amount of vault's native token to deposit\n    * @dev See {IERC4626-deposit}.\n    */\n    function deposit(uint256 assets, address receiver) \n        external\n        returns (uint256);\n\n    /**\n    * @dev Deposit funds to the vault. Can only be called if the committee had\n    * checked in and deposits are not paused, and the registry is not in an emergency pause.\n    * Allows to specify minimum shares to be minted for slippage protection.\n    * @param receiver Reciever of the shares from the deposit\n    * @param assets Amount of vault's native token to deposit\n    * @param minShares Minimum amount of shares to minted for the assets\n    */\n    function deposit(uint256 assets, address receiver, uint256 minShares) \n        external\n        returns (uint256);\n\n    /**\n    * @dev Deposit funds to the vault based on the amount of shares to mint specified.\n    * Can only be called if the committee had checked in and deposits are not paused,\n    * and the registry is not in an emergency pause.\n    * Allows to specify maximum assets to be deposited for slippage protection.\n    * @param receiver Reciever of the shares from the deposit\n    * @param shares Amount of vault's shares to mint\n    * @param maxAssets Maximum amount of assets to deposit for the shares\n    */\n    function mint(uint256 shares, address receiver, uint256 maxAssets) \n        external\n        returns (uint256);\n\n    /** \n    * @notice Withdraw previously deposited funds from the vault, without\n    * transferring the accumulated HAT reward.\n    * Can only be performed if a withdraw request has been previously\n    * submitted, and the pending period had passed, and while the withdraw\n    * enabled timeout had not passed. Withdrawals are not permitted during\n    * safety periods or while there is an active claim for a bounty payout.\n    * Allows to specify maximum shares to be burnt for slippage protection.\n    * @param assets Amount of tokens to withdraw\n    * @param receiver Address of receiver of the funds \n    * @param owner Address of owner of the funds\n    * @param maxShares Maximum amount of shares to burn for the assets\n    */\n    function withdraw(uint256 assets, address receiver, address owner, uint256 maxShares)\n        external \n        returns (uint256);\n\n    /** \n    * @notice Redeem shares in the vault for the respective amount\n    * of underlying assets, without transferring the accumulated reward.\n    * Can only be performed if a withdraw request has been previously\n    * submitted, and the pending period had passed, and while the withdraw\n    * enabled timeout had not passed. Withdrawals are not permitted during\n    * safety periods or while there is an active claim for a bounty payout.\n    * Allows to specify minimum assets to be received for slippage protection.\n    * @param shares Amount of shares to redeem\n    * @param receiver Address of receiver of the funds \n    * @param owner Address of owner of the funds\n    * @param minAssets Minimum amount of assets to receive for the shares\n    */\n    function redeem(uint256 shares, address receiver, address owner, uint256 minAssets)\n        external  \n        returns (uint256);\n\n    /** \n    * @notice Withdraw previously deposited funds from the vault and claim\n    * the HAT reward that the user has earned.\n    * Can only be performed if a withdraw request has been previously\n    * submitted, and the pending period had passed, and while the withdraw\n    * enabled timeout had not passed. Withdrawals are not permitted during\n    * safety periods or while there is an active claim for a bounty payout.\n    * Allows to specify maximum shares to be burnt for slippage protection.\n    * @param assets Amount of tokens to withdraw\n    * @param receiver Address of receiver of the funds\n    * @param owner Address of owner of the funds\n    * @param maxShares Maximum amount of shares to burn for the assets\n    * @dev See {IERC4626-withdraw}.\n    */\n    function withdrawAndClaim(uint256 assets, address receiver, address owner, uint256 maxShares)\n        external \n        returns (uint256 shares);\n\n    /** \n    * @notice Redeem shares in the vault for the respective amount\n    * of underlying assets and claim the HAT reward that the user has earned.\n    * Can only be performed if a withdraw request has been previously\n    * submitted, and the pending period had passed, and while the withdraw\n    * enabled timeout had not passed. Withdrawals are not permitted during\n    * safety periods or while there is an active claim for a bounty payout.\n    * Allows to specify minimum assets to be received for slippage protection.\n    * @param shares Amount of shares to redeem\n    * @param receiver Address of receiver of the funds \n    * @param owner Address of owner of the funds\n    * @param minAssets Minimum amount of assets to receive for the shares\n    * @dev See {IERC4626-redeem}.\n    */\n    function redeemAndClaim(uint256 shares, address receiver, address owner, uint256 minAssets)\n        external \n        returns (uint256 assets);\n\n    /** \n    * @notice Returns the amount of shares to be burned to give the user the exact\n    * amount of assets requested plus cover for the fee. Also returns the amount assets\n    * to be paid as fee.\n    * @return shares The amount of shares to be burned to get the requested amount of assets\n    * @return fee The amount of assets that will be paid as fee\n    */\n    function previewWithdrawAndFee(uint256 assets) external view returns (uint256 shares, uint256 fee);\n\n\n    /** \n    * @notice Returns the amount of assets to be sent to the user for the exact\n    * amount of shares to redeem. Also returns the amount assets to be paid as fee.\n    * @return assets amount of assets to be sent in exchange for the amount of shares specified\n    * @return fee The amount of assets that will be paid as fee\n    */\n    function previewRedeemAndFee(uint256 shares) external view returns (uint256 assets, uint256 fee);\n}\n"
      },
      "contracts/interfaces/IHATVaultsRegistry.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Disclaimer https://github.com/hats-finance/hats-contracts/blob/main/DISCLAIMER.md\n\npragma solidity 0.8.16;\n\nimport \"./IHATVault.sol\";\nimport \"./IHATClaimsManager.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/** @title Interface for the Hats.finance Vault Registry\n * @author hats.finance\n * @notice The Hats.finance Vault Registry is used to deploy Hats.finance\n * vaults and manage shared parameters.\n *\n * Hats.finance is a proactive bounty protocol for white hat hackers and\n * security experts, where projects, community members, and stakeholders\n * incentivize protocol security and responsible disclosure.\n * Hats create scalable vaults using the project’s own token. The value of the\n * bounty increases with the success of the token and project.\n *\n * The owner of the registry has the permission to set time limits and bounty\n * parameters and change vaults' info, and to set the other registry roles -\n * fee setter and arbitrator.\n * The arbitrator can challenge submitted claims for bounty payouts made by\n * vaults' committees, approve them with a different bounty percentage or\n * dismiss them.\n * The fee setter can set the fee on withdrawals on all vaults.\n *\n * This project is open-source and can be found at:\n * https://github.com/hats-finance/hats-contracts\n *\n * @dev New hats.finance vaults should be created through a call to {createVault}\n * so that they are linked to the registry\n */\ninterface IHATVaultsRegistry {\n\n    // a struct with parameters for all vaults\n    struct GeneralParameters {\n        // vesting duration for the part of the bounty given to the hacker in HAT tokens\n        uint32 hatVestingDuration;\n        // vesting periods for the part of the bounty given to the hacker in HAT tokens\n        uint32 hatVestingPeriods;\n        // withdraw enable period. safetyPeriod starts when finished.\n        uint32 withdrawPeriod;\n        // withdraw disable period - time for the committee to gather and decide on actions,\n        // withdrawals are not possible in this time. withdrawPeriod starts when finished.\n        uint32 safetyPeriod;\n        // period of time after withdrawRequestPendingPeriod where it is possible to withdraw\n        // (after which withdrawals are not possible)\n        uint32 withdrawRequestEnablePeriod;\n        // period of time that has to pass after withdraw request until withdraw is possible\n        uint32 withdrawRequestPendingPeriod;\n        // period of time that has to pass after setting a pending max\n        // bounty before it can be set as the new max bounty\n        uint32 setMaxBountyDelay;\n        // fee in ETH to be transferred with every logging of a claim\n        uint256 claimFee;\n    }\n\n    /**\n     * @notice Raised on {setWithdrawSafetyPeriod} if the withdraw period to\n     * be set is shorter than 1 hour\n     */\n    error WithdrawPeriodTooShort();\n\n    /**\n     * @notice Raised on {setWithdrawSafetyPeriod} if the safety period to\n     * be set is longer than 6 hours\n     */\n    error SafetyPeriodTooLong();\n\n    /**\n     * @notice Raised on {setWithdrawRequestParams} if the withdraw request\n     * pending period to be set is shorter than 3 months\n     */\n    error WithdrawRequestPendingPeriodTooLong();\n\n    /**\n     * @notice Raised on {setWithdrawRequestParams} if the withdraw request\n     * enabled period to be set is shorter than 6 hours\n     */\n    error WithdrawRequestEnabledPeriodTooShort();\n\n    /**\n     * @notice Raised on {setWithdrawRequestParams} if the withdraw request\n     * enabled period to be set is longer than 100 days\n     */\n    error WithdrawRequestEnabledPeriodTooLong();\n\n    /**\n     * @notice Raised on {setHatVestingParams} if the vesting duration to be\n     * set is longer than 180 days\n     */\n    error HatVestingDurationTooLong();\n\n    /**\n     * @notice Raised on {setHatVestingParams} if the vesting periods to be\n     * set is 0\n     */\n    error HatVestingPeriodsCannotBeZero();\n    \n    /**\n     * @notice Raised on {setHatVestingParams} if the vesting duration is \n     * smaller than the vesting periods\n     */\n    error HatVestingDurationSmallerThanPeriods();\n\n    /**\n     * @notice Raised on {setMaxBountyDelay} if the max bounty to be set is\n     * shorter than 2 days\n     */\n    error DelayTooShort();\n\n    /**\n     * @notice Raised on {swapAndSend} if the amount to swap is zero\n     */\n    error AmountToSwapIsZero();\n\n    /**\n     * @notice Raised on {swapAndSend} if the swap was not successful\n     */\n    error SwapFailed();\n    // Wrong amount received\n\n    /**\n     * @notice Raised on {swapAndSend} if the amount that was recieved in\n     * the swap was less than the minimum amount specified\n     */\n    error AmountSwappedLessThanMinimum();\n\n    /**\n     * @notice Raised on {setDefaultHATBountySplit} if the split to be set is\n     * greater than 20% (defined as 2000)\n     */\n    error TotalHatsSplitPercentageShouldBeUpToMaxHATSplit();\n\n    /**\n     * @notice Raised on {setDefaultChallengePeriod} if the challenge period\n     *  to be set is shorter than 1 day\n     */\n    error ChallengePeriodTooShort();\n\n    /**\n     * @notice Raised on {setDefaultChallengePeriod} if the challenge period\n     *  to be set is longer than 5 days\n     */\n    error ChallengePeriodTooLong();\n        \n    /**\n     * @notice Raised on {setDefaultChallengeTimeOutPeriod} if the challenge\n     * timeout period to be set is shorter than 1 day\n     */\n    error ChallengeTimeOutPeriodTooShort();\n\n    /**\n     * @notice Raised on {setDefaultChallengeTimeOutPeriod} if the challenge\n     * timeout period to be set is longer than 125 days\n     */\n    error ChallengeTimeOutPeriodTooLong();\n    \n    /**\n     * @notice Raised on {LogClaim} if the transaction was not sent with the\n     * amount of ETH specified as {generalParameters.claimFee}\n     */\n    error NotEnoughFeePaid();\n\n    /**\n     * @notice Raised on {LogClaim} if the transfer of the claim fee failed\n     */\n    error ClaimFeeTransferFailed();\n\n    /**\n     * @notice Emitted on deployment of the registry\n     * @param _hatVaultImplementation The HATVault implementation address\n     * @param _hatClaimsManagerImplementation The HATClaimsManager implementation address\n     * @param _HAT The HAT token address\n     * @param _tokenLockFactory The token lock factory address\n     * @param _generalParameters The registry's general parameters\n     * @param _bountyGovernanceHAT The HAT bounty for governance\n     * @param _bountyHackerHATVested The HAT bounty vested for the hacker\n     * @param _hatGovernance The registry's governance\n     * @param _defaultChallengePeriod The new default challenge period\n     * @param _defaultChallengeTimeOutPeriod The new default challenge timeout\n     */\n    event RegistryCreated(\n        address _hatVaultImplementation,\n        address _hatClaimsManagerImplementation,\n        address _HAT,\n        address _tokenLockFactory,\n        GeneralParameters _generalParameters,\n        uint256 _bountyGovernanceHAT,\n        uint256 _bountyHackerHATVested,\n        address _hatGovernance,\n        address _defaultArbitrator,\n        uint256 _defaultChallengePeriod,\n        uint256 _defaultChallengeTimeOutPeriod\n    );\n\n    /**\n     * @notice Emitted when a claim is logged\n     * @param _claimer The address of the claimer\n     * @param _descriptionHash - a hash of an ipfs encrypted file which\n     * describes the claim.\n     */\n    event LogClaim(address indexed _claimer, string _descriptionHash);\n\n    /**\n     * @notice Emitted when a new fee setter is set\n     * @param _feeSetter The address of the new fee setter\n     */\n    event SetFeeSetter(address indexed _feeSetter);\n\n    /**\n     * @notice Emitted when new withdraw request time limits are set\n     * @param _withdrawRequestPendingPeriod Time period where the withdraw\n     * request is pending\n     * @param _withdrawRequestEnablePeriod Time period after the peding period\n     * has ended during which withdrawal is enabled\n     */\n    event SetWithdrawRequestParams(\n        uint256 _withdrawRequestPendingPeriod,\n        uint256 _withdrawRequestEnablePeriod\n    );\n\n    /**\n     * @notice Emitted when a new fee for logging a claim for a bounty is set\n     * @param _fee Claim fee in ETH to be transferred on any call of {logClaim}\n     */\n    event SetClaimFee(uint256 _fee);\n\n    /**\n     * @notice Emitted when new durations are set for withdraw period and\n     * safety period\n     * @param _withdrawPeriod Amount of time during which withdrawals are\n     * enabled, and the bounty split can be changed by the governance\n     * @param _safetyPeriod Amount of time during which claims for bounties \n     * can be submitted and withdrawals are disabled\n     */\n    event SetWithdrawSafetyPeriod(\n        uint256 _withdrawPeriod,\n        uint256 _safetyPeriod\n    );\n\n    /**\n     * @notice Emitted when new HAT vesting parameters are set\n     * @param _duration The duration of the vesting period\n     * @param _periods The number of vesting periods\n     */\n    event SetHatVestingParams(uint256 _duration, uint256 _periods);\n\n    /**\n     * @notice Emitted when a new timelock delay for setting the\n     * max bounty is set\n     * @param _delay The time period for the delay\n     */\n    event SetMaxBountyDelay(uint256 _delay);\n\n    /**\n     * @notice Emitted when the UI visibility of a vault is changed\n     * @param _vault The address of the vault to update\n     * @param _visible Is this vault visible in the UI\n     */\n    event SetVaultVisibility(address indexed _vault, bool indexed _visible);\n\n    /** @dev Emitted when a new vault is created\n     * @param _vault The address of the vault to add to the registry\n     * @param _claimsManager The address of the vault's claims manager\n     * @param _vaultParams The vault initialization parameters\n     * @param _claimsManagerParams The vault's claims manager initialization parameters\n     */\n    event VaultCreated(\n        address indexed _vault,\n        address indexed _claimsManager,\n        IHATVault.VaultInitParams _vaultParams,\n        IHATClaimsManager.ClaimsManagerInitParams _claimsManagerParams\n    );\n    \n    /** @notice Emitted when a swap of vault tokens to HAT tokens is done and\n     * the HATS tokens are sent to beneficiary through vesting contract\n     * @param _beneficiary Address of beneficiary\n     * @param _amountSwapped Amount of vault's native tokens that was swapped\n     * @param _amountSent Amount of HAT tokens sent to beneficiary\n     * @param _tokenLock Address of the token lock contract that holds the HAT\n     * tokens (address(0) if no token lock is used)\n     */\n    event SwapAndSend(\n        address indexed _beneficiary,\n        uint256 _amountSwapped,\n        uint256 _amountSent,\n        address indexed _tokenLock\n    );\n\n    /**\n     * @notice Emitted when a new default HAT bounty split is set\n     * @param _defaultBountyGovernanceHAT The new default HAT bounty part sent to governance\n     * @param _defaultBountyHackerHATVested The new default HAT bounty part vseted for the hacker\n     */\n    event SetDefaultHATBountySplit(uint256 _defaultBountyGovernanceHAT, uint256 _defaultBountyHackerHATVested);\n\n    /**\n     * @notice Emitted when a new default arbitrator is set\n     * @param _defaultArbitrator The address of the new arbitrator\n     */\n    event SetDefaultArbitrator(address indexed _defaultArbitrator);\n\n    /**\n     * @notice Emitted when a new default challenge period is set\n     * @param _defaultChallengePeriod The new default challenge period\n     */ \n    event SetDefaultChallengePeriod(uint256 _defaultChallengePeriod);\n\n    /**\n     * @notice Emitted when a new default challenge timeout period is set\n     * @param _defaultChallengeTimeOutPeriod The new default challenge timeout\n     * period\n     */\n    event SetDefaultChallengeTimeOutPeriod(uint256 _defaultChallengeTimeOutPeriod);\n\n    /** @notice Emitted when the system is put into emergency pause/unpause\n     * @param _isEmergencyPaused Is the system in an emergency pause\n     */\n    event SetEmergencyPaused(bool _isEmergencyPaused);\n\n    /**\n     * @notice Emitted when a new swap token is set\n     * @param _swapToken The new swap token address\n     */\n    event SetSwapToken(address indexed _swapToken);\n\n    /**\n     * @notice Emitted when a new HATVault implementation is set\n     * @param _hatVaultImplementation The address of the new HATVault implementation\n     */\n    event SetHATVaultImplementation(address indexed _hatVaultImplementation);\n\n    /**\n     * @notice Emitted when a new HATClaimsManager implementation is set\n     * @param _hatClaimsManagerImplementation The address of the new HATClaimsManager implementation\n     */\n    event SetHATClaimsManagerImplementation(address indexed _hatClaimsManagerImplementation);\n\n    /**\n     * @notice Called by governance to pause/unpause the system in case of an\n     * emergency\n     * @param _isEmergencyPaused Is the system in an emergency pause\n     */\n    function setEmergencyPaused(bool _isEmergencyPaused) external;\n\n    /**\n     * @notice Called by governance to set a new swap token\n     * @param _swapToken the new swap token address\n     */\n    function setSwapToken(address _swapToken) external;\n\n    /**\n     * @notice Called by governance to set a new HATVault and HATVault implementation to be\n     * used by the registry for creating new vaults\n     * @param _hatVaultImplementation The address of the HATVault implementation\n     * @param _hatClaimsManagerImplementation The address of the HATClaimsManager implementation\n     */\n    function setVaultImplementations(address _hatVaultImplementation, address _hatClaimsManagerImplementation) external;\n\n    /**\n     * @notice Emit an event that includes the given _descriptionHash\n     * This can be used by the claimer as evidence that she had access to the\n     * information at the time of the call\n     * if a {generalParameters.claimFee} > 0, the caller must send that amount\n     * of ETH for the claim to succeed\n     * @param _descriptionHash - a hash of an IPFS encrypted file which \n     * describes the claim.\n     */\n    function logClaim(string calldata _descriptionHash) external payable;\n\n    /**\n     * @notice Called by governance to set the default percentage of each claim bounty\n     * that will be swapped for hats and sent to the governance or vested for the hacker\n     * @param _defaultBountyGovernanceHAT The HAT bounty for governance\n     * @param _defaultBountyHackerHATVested The HAT bounty vested for the hacker\n     */\n    function setDefaultHATBountySplit(\n        uint16 _defaultBountyGovernanceHAT,\n        uint16 _defaultBountyHackerHATVested\n    ) \n        external;\n\n    /** \n     * @dev Check that a given hats bounty split is legal, meaning that:\n     *   Each entry is a number between 0 and less than `MAX_HAT_SPLIT`.\n     *   Total splits should be less than `MAX_HAT_SPLIT`.\n     * function will revert in case the bounty split is not legal.\n     * @param _bountyGovernanceHAT The HAT bounty for governance\n     * @param _bountyHackerHATVested The HAT bounty vested for the hacker\n     */\n    function validateHATSplit(uint16 _bountyGovernanceHAT, uint16 _bountyHackerHATVested)\n         external\n         pure;\n\n    /**\n     * @notice Called by governance to set the default arbitrator.\n     * @param _defaultArbitrator The default arbitrator address\n     */\n    function setDefaultArbitrator(address _defaultArbitrator) external;\n\n    /**\n     * @notice Called by governance to set the default challenge period\n     * @param _defaultChallengePeriod The default challenge period\n     */\n    function setDefaultChallengePeriod(uint32 _defaultChallengePeriod) \n        external;\n\n    /**\n     * @notice Called by governance to set the default challenge timeout\n     * @param _defaultChallengeTimeOutPeriod The Default challenge timeout\n     */\n    function setDefaultChallengeTimeOutPeriod(\n        uint32 _defaultChallengeTimeOutPeriod\n    ) \n        external;\n\n    /**\n     * @notice Check that the given challenge period is legal, meaning that it\n     * is greater than 1 day and less than 5 days.\n     * @param _challengePeriod The challenge period to check\n     */\n    function validateChallengePeriod(uint32 _challengePeriod) external pure;\n\n    /**\n     * @notice Check that the given challenge timeout period is legal, meaning\n     * that it is greater than 2 days and less than 125 days.\n     * @param _challengeTimeOutPeriod The challenge timeout period to check\n     */\n    function validateChallengeTimeOutPeriod(uint32 _challengeTimeOutPeriod) external pure;\n   \n    /**\n     * @notice Called by governance to set the fee setter role\n     * @param _feeSetter Address of new fee setter\n     */\n    function setFeeSetter(address _feeSetter) external;\n\n    /**\n     * @notice Called by governance to set time limits for withdraw requests\n     * @param _withdrawRequestPendingPeriod Time period where the withdraw\n     * request is pending\n     * @param _withdrawRequestEnablePeriod Time period after the peding period\n     * has ended during which withdrawal is enabled\n     */\n    function setWithdrawRequestParams(\n        uint32 _withdrawRequestPendingPeriod,\n        uint32  _withdrawRequestEnablePeriod\n    )\n        external;\n\n    /**\n     * @notice Called by governance to set the fee for logging a claim for a\n     * bounty in any vault.\n     * @param _fee Claim fee in ETH to be transferred on any call of\n     * {logClaim}\n     */\n    function setClaimFee(uint256 _fee) external;\n\n    /**\n     * @notice Called by governance to set the withdraw period and safety\n     * period, which are always interchanging.\n     * The safety period is time that the committee can submit claims for \n     * bounty payouts, and during which withdrawals are disabled and the\n     * bounty split cannot be changed.\n     * @param _withdrawPeriod Amount of time during which withdrawals are\n     * enabled, and the bounty split can be changed by the governance. Must be\n     * at least 1 hour.\n     * @param _safetyPeriod Amount of time during which claims for bounties \n     * can be submitted and withdrawals are disabled. Must be at most 6 hours.\n     */\n    function setWithdrawSafetyPeriod(\n        uint32 _withdrawPeriod,\n        uint32 _safetyPeriod\n    ) \n        external;\n\n    /**\n     * @notice Called by governance to set vesting params for rewarding hackers\n     * with rewardToken, for all vaults\n     * @param _duration Duration of the vesting period. Must be less than 180\n     * days.\n     * @param _periods The number of vesting periods. Must be more than 0 and \n     * less then the vesting duration.\n     */\n    function setHatVestingParams(uint32 _duration, uint32 _periods) external;\n\n    /**\n     * @notice Called by governance to set the timelock delay for setting the\n     * max bounty (the time between setPendingMaxBounty and setMaxBounty)\n     * @param _delay The time period for the delay. Must be at least 2 days.\n     */\n    function setMaxBountyDelay(uint32 _delay) external;\n\n    /**\n     * @notice Create a new vault\n     * NOTE: Vaults should not use tokens which do not guarantee that the \n     * amount specified is the amount transferred\n     * @param _vaultParams The vault initialization parameters\n     * @param _vaultParams The vault token initialization parameters\n     * @return vault The address of the new vault\n     */\n    function createVault(\n        IHATVault.VaultInitParams calldata _vaultParams,\n        IHATClaimsManager.ClaimsManagerInitParams calldata _claimsManagerParams\n    ) external returns(address vault, address vaultClaimsManager);\n\n    /**\n     * @notice Called by governance to change the UI visibility of a vault\n     * @param _vault The address of the vault to update\n     * @param _visible Is this vault visible in the UI\n     * This parameter can be used by the UI to include or exclude the vault\n     */\n    function setVaultVisibility(address _vault, bool _visible) external;\n\n    /**\n     * @notice Transfer the part of the bounty that is supposed to be swapped\n     * into HAT tokens from the HATVault to the registry, and keep track of\n     * the amounts to be swapped and sent/burnt in a later transaction\n     * @param _asset The vault's native token\n     * @param _hacker The address of the beneficiary of the bounty\n     * @param _hackersHatReward The amount of the vault's native token to be\n     * swapped to HAT tokens and sent to the hacker via a vesting contract\n     * @param _governanceHatReward The amount of the vault's native token to\n     * be swapped to HAT tokens and sent to governance\n     */\n    function addTokensToSwap(\n        IERC20 _asset,\n        address _hacker,\n        uint256 _hackersHatReward,\n        uint256 _governanceHatReward\n    ) external;\n\n    /**\n     * @notice Called by governance to swap the given asset to HAT tokens and \n     * distribute the HAT tokens: Send to governance their share and send to\n     * beneficiaries their share through a vesting contract.\n     * @param _asset The address of the token to be swapped to HAT tokens\n     * @param _beneficiaries Addresses of beneficiaries\n     * @param _amountOutMinimum Minimum amount of HAT tokens at swap\n     * @param _routingContract Routing contract to call for the swap\n     * @param _routingPayload Payload to send to the _routingContract for the\n     * swap\n     */\n    function swapAndSend(\n        address _asset,\n        address[] calldata _beneficiaries,\n        uint256 _amountOutMinimum,\n        address _routingContract,\n        bytes calldata _routingPayload\n    ) external;\n  \n    /**\n     * @notice Returns the withdraw enable period for all vaults. The safety\n     * period starts when finished.\n     * @return Withdraw enable period for all vaults\n     */\n    function getWithdrawPeriod() external view returns (uint256);\n\n    /**\n     * @notice Returns the withdraw disable period - time for the committee to\n     * gather and decide on actions, withdrawals are not possible in this\n     * time. The withdraw period starts when finished.\n     * @return Safety period for all vaults\n     */\n    function getSafetyPeriod() external view returns (uint256);\n\n    /**\n     * @notice Returns the withdraw request enable period for all vaults -\n     * period of time after withdrawRequestPendingPeriod where it is possible\n     * to withdraw, and after which withdrawals are not possible.\n     * @return Withdraw request enable period for all vaults\n     */\n    function getWithdrawRequestEnablePeriod() external view returns (uint256);\n\n    /**\n     * @notice Returns the withdraw request pending period for all vaults -\n     * period of time that has to pass after withdraw request until withdraw\n     * is possible\n     * @return Withdraw request pending period for all vaults\n     */\n    function getWithdrawRequestPendingPeriod() external view returns (uint256);\n\n    /**\n     * @notice Returns the set max bounty delay for all vaults - period of\n     * time that has to pass after setting a pending max bounty before it can\n     * be set as the new max bounty\n     * @return Set max bounty delay for all vaults\n     */\n    function getSetMaxBountyDelay() external view returns (uint256);\n\n    /**\n     * @notice Returns the number of vaults that have been previously created\n     * @return The number of vaults in the registry\n     */\n    function getNumberOfVaults() external view returns(uint256);\n\n    /**\n     * @notice Get the fee setter address\n     * @return The address of the fee setter\n     */\n    function feeSetter() external view returns(address);\n\n    /**\n     * @notice Get whether the system is in an emergency pause\n     * @return Whether the system is in an emergency pause\n     */\n    function isEmergencyPaused() external view returns(bool);\n\n    /**\n     * @notice Get the owner address\n     * @return The address of the owner\n     */\n    function owner() external view returns(address);\n\n    /**\n     * @notice Get the default percentage of the total bounty to be swapped to HATs and sent to governance\n     * @return The default percentage of the total bounty to be swapped to HATs and sent to governance\n     */\n    function defaultBountyGovernanceHAT() external view returns(uint16);\n\n    /**\n     * @notice Get the default percentage of the total bounty to be swapped to HATs and sent to the hacker via vesting contract\n     * @return The default percentage of the total bounty to be swapped to HATs and sent to the hacker via vesting contract\n     */\n    function defaultBountyHackerHATVested() external view returns(uint16);\n\n    /**\n     * @notice Get the default arbitrator address\n     * @return The default arbitrator address\n     */\n    function defaultArbitrator() external view returns(address);\n\n    /**\n     * @notice Get the default challenge period\n     * @return The default challenge period\n     */\n    function defaultChallengePeriod() external view returns(uint32);\n\n    /**\n     * @notice Get the default challenge time out period\n     * @return The default challenge time out period\n     */\n    function defaultChallengeTimeOutPeriod() external view returns(uint32);\n}\n"
      },
      "contracts/interfaces/IRewardController.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.16;\n\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\ninterface IRewardController {\n    \n    error EpochLengthZero();\n    // Not enough rewards to transfer to user\n    error NotEnoughRewardsToTransferToUser();\n\n    event RewardControllerCreated(\n        address _rewardToken,\n        address _governance,\n        uint256 _startBlock,\n        uint256 _epochLength,\n        uint256[24] _epochRewardPerBlock\n    );\n    event SetEpochRewardPerBlock(uint256[24] _epochRewardPerBlock);\n    event SetAllocPoint(address indexed _vault, uint256 _prevAllocPoint, uint256 _allocPoint);\n    event VaultUpdated(address indexed _vault, uint256 _rewardPerShare, uint256 _lastProcessedVaultUpdate);\n    event UserBalanceCommitted(address indexed _vault, address indexed _user, uint256 _unclaimedReward, uint256 _rewardDebt);\n    event ClaimReward(address indexed _vault, address indexed _user, uint256 _amount);\n\n    /**\n     * @notice Initializes the reward controller\n     * @param _rewardToken The address of the ERC20 token to be distributed as rewards\n     * @param _governance The hats governance address, to be given ownership of the reward controller\n     * @param _startRewardingBlock The block number from which to start rewarding\n     * @param _epochLength The length of a rewarding epoch\n     * @param _epochRewardPerBlock The reward per block for each of the 24 epochs\n     */\n    function initialize(\n        address _rewardToken,\n        address _governance,\n        uint256 _startRewardingBlock,\n        uint256 _epochLength,\n        uint256[24] calldata _epochRewardPerBlock\n    ) external;\n\n    /**\n     * @notice Called by the owner to set the allocation points for a vault, meaning the\n     * vault's relative share of the total rewards\n     * @param _vault The address of the vault\n     * @param _allocPoint The allocation points for the vault\n     */\n    function setAllocPoint(address _vault, uint256 _allocPoint) external;\n\n    /**\n    * @notice Update the vault's reward per share, not more then once per block\n    * @param _vault The vault's address\n    */\n    function updateVault(address _vault) external;\n\n    /**\n    * @notice Called by the owner to set reward per epoch\n    * Reward can only be set for epochs which have not yet started\n    * @param _epochRewardPerBlock reward per block for each epoch\n    */\n    function setEpochRewardPerBlock(uint256[24] calldata _epochRewardPerBlock) external;\n\n    /**\n    * @notice Called by the vault to update a user claimable reward after deposit or withdraw.\n    * This call should never revert.\n    * @param _user The user address to updare rewards for\n    * @param _sharesChange The user of shared the user deposited or withdrew\n    * @param _isDeposit Whether user deposited or withdrew\n    */\n    function commitUserBalance(address _user, uint256 _sharesChange, bool _isDeposit) external;\n    /**\n    * @notice Transfer to the specified user their pending share of rewards.\n    * @param _vault The vault address\n    * @param _user The user address to claim for\n    */\n    function claimReward(address _vault, address _user) external;\n\n    /**\n    * @notice Calculate rewards for a vault by iterating over the history of totalAllocPoints updates,\n    * and sum up all rewards periods from vault.lastRewardBlock until current block number.\n    * @param _vault The vault address\n    * @param _fromBlock The block from which to start calculation\n    * @return reward The amount of rewards for the vault\n    */\n    function getVaultReward(address _vault, uint256 _fromBlock) external view returns(uint256 reward);\n\n    /**\n    * @notice Calculate the amount of rewards a user can claim for having contributed to a specific vault\n    * @param _vault The vault address\n    * @param _user The user for which the reward is calculated\n    */\n    function getPendingReward(address _vault, address _user) external view returns (uint256);\n\n    /**\n    * @notice Called by the owner to transfer any tokens held in this contract to the owner\n    * @param _token The token to sweep\n    * @param _amount The amount of token to sweep\n    */\n    function sweepToken(IERC20Upgradeable _token, uint256 _amount) external;\n\n}\n"
      },
      "contracts/tokenlock/ITokenLock.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.16;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface ITokenLock {\n\n    // -- Value Transfer --\n\n    function release() external;\n\n    function withdrawSurplus(uint256 _amount) external;\n\n    function sweepToken(IERC20 _token) external;\n\n    function revoke() external;\n\n    // -- Balances --\n\n    function currentBalance() external view returns (uint256);\n\n    // -- Time & Periods --\n\n    function currentTime() external view returns (uint256);\n\n    function duration() external view returns (uint256);\n\n    function sinceStartTime() external view returns (uint256);\n\n    function amountPerPeriod() external view returns (uint256);\n\n    function periodDuration() external view returns (uint256);\n\n    function currentPeriod() external view returns (uint256);\n\n    function passedPeriods() external view returns (uint256);\n\n    // -- Locking & Release Schedule --\n\n    function availableAmount() external view returns (uint256);\n\n    function vestedAmount() external view returns (uint256);\n\n    function releasableAmount() external view returns (uint256);\n\n    function totalOutstandingAmount() external view returns (uint256);\n\n    function surplusAmount() external view returns (uint256);\n}\n"
      },
      "contracts/tokenlock/ITokenLockFactory.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.16;\n\nimport \"./ITokenLock.sol\";\n\ninterface ITokenLockFactory {\n    // -- Factory --\n    function setMasterCopy(address _masterCopy) external;\n\n    function createTokenLock(\n        address _token,\n        address _owner,\n        address _beneficiary,\n        uint256 _managedAmount,\n        uint256 _startTime,\n        uint256 _endTime,\n        uint256 _periods,\n        uint256 _releaseStartTime,\n        uint256 _vestingCliffTime,\n        bool _revocable,\n        bool _canDelegate\n    ) external returns(address contractAddress);\n}\n"
      },
      "contracts/tokenlock/TokenLockFactory.sol": {
        "content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.8.16;\n\nimport \"@openzeppelin/contracts/proxy/Clones.sol\";\nimport \"./ITokenLockFactory.sol\";\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n\n/**\n * @title TokenLockFactory\n *  a factory of TokenLock contracts.\n *\n * This contract receives funds to make the process of creating TokenLock contracts\n * easier by distributing them the initial tokens to be managed.\n */\ncontract TokenLockFactory is ITokenLockFactory, Ownable {\n    // -- Errors --\n\n    error MasterCopyCannotBeZero();\n\n    // -- State --\n\n    address public masterCopy;\n    mapping(address => uint256) public nonce;\n\n    // -- Events --\n\n    event MasterCopyUpdated(address indexed masterCopy);\n\n    event TokenLockCreated(\n        address indexed contractAddress,\n        bytes32 indexed initHash,\n        address indexed beneficiary,\n        address token,\n        uint256 managedAmount,\n        uint256 startTime,\n        uint256 endTime,\n        uint256 periods,\n        uint256 releaseStartTime,\n        uint256 vestingCliffTime,\n        bool revocable,\n        bool canDelegate\n    );\n\n    /**\n     * Constructor.\n     * @param _masterCopy Address of the master copy to use to clone proxies\n     * @param _governance Owner of the factory\n     */\n    constructor(address _masterCopy, address _governance) {\n        _setMasterCopy(_masterCopy);\n        _transferOwnership(_governance);\n    }\n\n    // -- Factory --\n    /**\n     * @notice Creates and fund a new token lock wallet using a minimum proxy\n     * @param _token token to time lock\n     * @param _owner Address of the contract owner\n     * @param _beneficiary Address of the beneficiary of locked tokens\n     * @param _managedAmount Amount of tokens to be managed by the lock contract\n     * @param _startTime Start time of the release schedule\n     * @param _endTime End time of the release schedule\n     * @param _periods Number of periods between start time and end time\n     * @param _releaseStartTime Override time for when the releases start\n     * @param _revocable Whether the contract is revocable\n     * @param _canDelegate Whether the contract should call delegate\n     */\n    function createTokenLock(\n        address _token,\n        address _owner,\n        address _beneficiary,\n        uint256 _managedAmount,\n        uint256 _startTime,\n        uint256 _endTime,\n        uint256 _periods,\n        uint256 _releaseStartTime,\n        uint256 _vestingCliffTime,\n        bool _revocable,\n        bool _canDelegate\n    ) external override returns(address contractAddress) {\n        // Create contract using a minimal proxy and call initializer\n        bytes memory initializer = abi.encodeWithSignature(\n            \"initialize(address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,bool,bool)\",\n            _owner,\n            _beneficiary,\n            _token,\n            _managedAmount,\n            _startTime,\n            _endTime,\n            _periods,\n            _releaseStartTime,\n            _vestingCliffTime,\n            _revocable,\n            _canDelegate\n        );\n\n        contractAddress = _deployProxyPrivate(initializer,\n        _beneficiary,\n        _token,\n        _managedAmount,\n        _startTime,\n        _endTime,\n        _periods,\n        _releaseStartTime,\n        _vestingCliffTime,\n        _revocable,\n        _canDelegate);\n    }\n\n    /**\n     * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\n     * @param _masterCopy Address of contract bytecode to factory clone\n     */\n    function setMasterCopy(address _masterCopy) external override onlyOwner {\n        _setMasterCopy(_masterCopy);\n    }\n\n    function _setMasterCopy(address _masterCopy) internal {\n        if (_masterCopy == address(0))\n            revert MasterCopyCannotBeZero();\n        masterCopy = _masterCopy;\n        emit MasterCopyUpdated(_masterCopy);\n    }\n\n    // This private function is to handle stack too deep issue\n    function _deployProxyPrivate(\n        bytes memory _initializer,\n        address _beneficiary,\n        address _token,\n        uint256 _managedAmount,\n        uint256 _startTime,\n        uint256 _endTime,\n        uint256 _periods,\n        uint256 _releaseStartTime,\n        uint256 _vestingCliffTime,\n        bool _revocable,\n        bool _canDelegate\n    ) private returns (address contractAddress) {\n\n        contractAddress = Clones.cloneDeterministic(masterCopy, keccak256(abi.encodePacked(msg.sender, nonce[msg.sender]++, _initializer)));\n\n        Address.functionCall(contractAddress, _initializer);\n\n        emit TokenLockCreated(\n            contractAddress,\n            keccak256(_initializer),\n            _beneficiary,\n            _token,\n            _managedAmount,\n            _startTime,\n            _endTime,\n            _periods,\n            _releaseStartTime,\n            _vestingCliffTime,\n            _revocable,\n            _canDelegate\n        );\n    }\n}\n"
      }
    }
  }}