creation_sourcecode: {{
    "sources": {
      "lib/openzeppelin-contracts/contracts/access/AccessControl.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n *     require(hasRole(MY_ROLE, msg.sender));\n *     ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n    struct RoleData {\n        mapping(address => bool) members;\n        bytes32 adminRole;\n    }\n\n    mapping(bytes32 => RoleData) private _roles;\n\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n    /**\n     * @dev Modifier that checks that an account has a specific role. Reverts\n     * with a standardized message including the required role.\n     *\n     * The format of the revert reason is given by the following regular expression:\n     *\n     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n     *\n     * _Available since v4.1._\n     */\n    modifier onlyRole(bytes32 role) {\n        _checkRole(role);\n        _;\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n        return _roles[role].members[account];\n    }\n\n    /**\n     * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n     * Overriding this function changes the behavior of the {onlyRole} modifier.\n     *\n     * Format of the revert message is described in {_checkRole}.\n     *\n     * _Available since v4.6._\n     */\n    function _checkRole(bytes32 role) internal view virtual {\n        _checkRole(role, _msgSender());\n    }\n\n    /**\n     * @dev Revert with a standard message if `account` is missing `role`.\n     *\n     * The format of the revert reason is given by the following regular expression:\n     *\n     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n     */\n    function _checkRole(bytes32 role, address account) internal view virtual {\n        if (!hasRole(role, account)) {\n            revert(\n                string(\n                    abi.encodePacked(\n                        \"AccessControl: account \",\n                        Strings.toHexString(account),\n                        \" is missing role \",\n                        Strings.toHexString(uint256(role), 32)\n                    )\n                )\n            );\n        }\n    }\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n        return _roles[role].adminRole;\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been revoked `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function renounceRole(bytes32 role, address account) public virtual override {\n        require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event. Note that unlike {grantRole}, this function doesn't perform any\n     * checks on the calling account.\n     *\n     * May emit a {RoleGranted} event.\n     *\n     * [WARNING]\n     * ====\n     * This function should only be called from the constructor when setting\n     * up the initial roles for the system.\n     *\n     * Using this function in any other way is effectively circumventing the admin\n     * system imposed by {AccessControl}.\n     * ====\n     *\n     * NOTE: This function is deprecated in favor of {_grantRole}.\n     */\n    function _setupRole(bytes32 role, address account) internal virtual {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Sets `adminRole` as ``role``'s admin role.\n     *\n     * Emits a {RoleAdminChanged} event.\n     */\n    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n        bytes32 previousAdminRole = getRoleAdmin(role);\n        _roles[role].adminRole = adminRole;\n        emit RoleAdminChanged(role, previousAdminRole, adminRole);\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function _grantRole(bytes32 role, address account) internal virtual {\n        if (!hasRole(role, account)) {\n            _roles[role].members[account] = true;\n            emit RoleGranted(role, account, _msgSender());\n        }\n    }\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function _revokeRole(bytes32 role, address account) internal virtual {\n        if (hasRole(role, account)) {\n            _roles[role].members[account] = false;\n            emit RoleRevoked(role, account, _msgSender());\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/access/IAccessControl.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n    /**\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n     *\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n     * {RoleAdminChanged} not being emitted signaling this.\n     *\n     * _Available since v3.1._\n     */\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n    /**\n     * @dev Emitted when `account` is granted `role`.\n     *\n     * `sender` is the account that originated the contract call, an admin role\n     * bearer except when using {AccessControl-_setupRole}.\n     */\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Emitted when `account` is revoked `role`.\n     *\n     * `sender` is the account that originated the contract call:\n     *   - if using `revokeRole`, it is the admin role bearer\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\n     */\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) external view returns (bool);\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     */\n    function renounceRole(bytes32 role, address account) external;\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n *     doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n *     token.safeTransferFrom(msg.sender, address(this), value);\n *     ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\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     * CAUTION: See Security Considerations above.\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(IERC20 token, address spender, uint256 value) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n     * Revert on invalid signature.\n     */\n    function safePermit(\n        IERC20Permit token,\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal {\n        uint256 nonceBefore = token.nonces(owner);\n        token.permit(owner, spender, value, deadline, v, r, s);\n        uint256 nonceAfter = token.nonces(owner);\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     *\n     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return\n            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     *\n     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Strings.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\nimport \"./math/SignedMath.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n    uint8 private constant _ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = Math.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            /// @solidity memory-safe-assembly\n            assembly {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `int256` to its ASCII `string` decimal representation.\n     */\n    function toString(int256 value) internal pure returns (string memory) {\n        return string(abi.encodePacked(value < 0 ? \"-\" : \"\", toString(SignedMath.abs(value))));\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, Math.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = _SYMBOLS[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n    }\n\n    /**\n     * @dev Returns true if the two strings are equal.\n     */\n    function equal(string memory a, string memory b) internal pure returns (bool) {\n        return keccak256(bytes(a)) == keccak256(bytes(b));\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1, \"Math: mulDiv overflow\");\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard signed math utilities missing in the Solidity language.\n */\nlibrary SignedMath {\n    /**\n     * @dev Returns the largest of two signed numbers.\n     */\n    function max(int256 a, int256 b) internal pure returns (int256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two signed numbers.\n     */\n    function min(int256 a, int256 b) internal pure returns (int256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two signed numbers without overflow.\n     * The result is rounded towards zero.\n     */\n    function average(int256 a, int256 b) internal pure returns (int256) {\n        // Formula from the book \"Hacker's Delight\"\n        int256 x = (a & b) + ((a ^ b) >> 1);\n        return x + (int256(uint256(x) >> 255) & (a ^ b));\n    }\n\n    /**\n     * @dev Returns the absolute unsigned value of a signed value.\n     */\n    function abs(int256 n) internal pure returns (uint256) {\n        unchecked {\n            // must be unchecked in order to support `n = type(int256).min`\n            return uint256(n >= 0 ? n : -n);\n        }\n    }\n}\n"
      },
      "lib/solady/src/utils/ECDSA.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Gas optimized ECDSA wrapper.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol)\n/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol)\n///\n/// @dev Note:\n/// - The recovery functions use the ecrecover precompile (0x1).\n///\n/// WARNING! Do NOT use signatures as unique identifiers.\n/// Please use EIP712 with a nonce included in the digest to prevent replay attacks.\n/// This implementation does NOT check if a signature is non-malleable.\nlibrary ECDSA {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                        CUSTOM ERRORS                       */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The signature is invalid.\n    error InvalidSignature();\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                    RECOVERY OPERATIONS                     */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    // Note: as of Solady version 0.0.68, these functions will\n    // revert upon recovery failure for more safety by default.\n\n    /// @dev Recovers the signer's address from a message digest `hash`,\n    /// and the `signature`.\n    ///\n    /// This function does NOT accept EIP-2098 short form signatures.\n    /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098\n    /// short form signatures instead.\n    function recover(bytes32 hash, bytes memory signature) internal view returns (address result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n            let signatureLength := mload(signature)\n            mstore(0x00, hash)\n            mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.\n            mstore(0x40, mload(add(signature, 0x20))) // `r`.\n            mstore(0x60, mload(add(signature, 0x40))) // `s`.\n            result :=\n                mload(\n                    staticcall(\n                        gas(), // Amount of gas left for the transaction.\n                        eq(signatureLength, 65), // Address of `ecrecover`.\n                        0x00, // Start of input.\n                        0x80, // Size of input.\n                        0x01, // Start of output.\n                        0x20 // Size of output.\n                    )\n                )\n            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n            if iszero(returndatasize()) {\n                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x60, 0) // Restore the zero slot.\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /// @dev Recovers the signer's address from a message digest `hash`,\n    /// and the `signature`.\n    ///\n    /// This function does NOT accept EIP-2098 short form signatures.\n    /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098\n    /// short form signatures instead.\n    function recoverCalldata(bytes32 hash, bytes calldata signature)\n        internal\n        view\n        returns (address result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n            mstore(0x00, hash)\n            mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.\n            calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.\n            result :=\n                mload(\n                    staticcall(\n                        gas(), // Amount of gas left for the transaction.\n                        eq(signature.length, 65), // Address of `ecrecover`.\n                        0x00, // Start of input.\n                        0x80, // Size of input.\n                        0x01, // Start of output.\n                        0x20 // Size of output.\n                    )\n                )\n            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n            if iszero(returndatasize()) {\n                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x60, 0) // Restore the zero slot.\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /// @dev Recovers the signer's address from a message digest `hash`,\n    /// and the EIP-2098 short form signature defined by `r` and `vs`.\n    ///\n    /// This function only accepts EIP-2098 short form signatures.\n    /// See: https://eips.ethereum.org/EIPS/eip-2098\n    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n            mstore(0x00, hash)\n            mstore(0x20, add(shr(255, vs), 27)) // `v`.\n            mstore(0x40, r)\n            mstore(0x60, shr(1, shl(1, vs))) // `s`.\n            result :=\n                mload(\n                    staticcall(\n                        gas(), // Amount of gas left for the transaction.\n                        1, // Address of `ecrecover`.\n                        0x00, // Start of input.\n                        0x80, // Size of input.\n                        0x01, // Start of output.\n                        0x20 // Size of output.\n                    )\n                )\n            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n            if iszero(returndatasize()) {\n                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x60, 0) // Restore the zero slot.\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /// @dev Recovers the signer's address from a message digest `hash`,\n    /// and the signature defined by `v`, `r`, `s`.\n    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)\n        internal\n        view\n        returns (address result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n            mstore(0x00, hash)\n            mstore(0x20, and(v, 0xff))\n            mstore(0x40, r)\n            mstore(0x60, s)\n            result :=\n                mload(\n                    staticcall(\n                        gas(), // Amount of gas left for the transaction.\n                        1, // Address of `ecrecover`.\n                        0x00, // Start of input.\n                        0x80, // Size of input.\n                        0x01, // Start of output.\n                        0x20 // Size of output.\n                    )\n                )\n            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n            if iszero(returndatasize()) {\n                mstore(0x00, 0x8baa579f) // `InvalidSignature()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x60, 0) // Restore the zero slot.\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                   TRY-RECOVER OPERATIONS                   */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    // WARNING!\n    // These functions will NOT revert upon recovery failure.\n    // Instead, they will return the zero address upon recovery failure.\n    // It is critical that the returned address is NEVER compared against\n    // a zero address (e.g. an uninitialized address variable).\n\n    /// @dev Recovers the signer's address from a message digest `hash`,\n    /// and the `signature`.\n    ///\n    /// This function does NOT accept EIP-2098 short form signatures.\n    /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098\n    /// short form signatures instead.\n    function tryRecover(bytes32 hash, bytes memory signature)\n        internal\n        view\n        returns (address result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n            let signatureLength := mload(signature)\n            mstore(0x00, hash)\n            mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.\n            mstore(0x40, mload(add(signature, 0x20))) // `r`.\n            mstore(0x60, mload(add(signature, 0x40))) // `s`.\n            pop(\n                staticcall(\n                    gas(), // Amount of gas left for the transaction.\n                    eq(signatureLength, 65), // Address of `ecrecover`.\n                    0x00, // Start of input.\n                    0x80, // Size of input.\n                    0x40, // Start of output.\n                    0x20 // Size of output.\n                )\n            )\n            mstore(0x60, 0) // Restore the zero slot.\n            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n            result := mload(xor(0x60, returndatasize()))\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /// @dev Recovers the signer's address from a message digest `hash`,\n    /// and the `signature`.\n    ///\n    /// This function does NOT accept EIP-2098 short form signatures.\n    /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098\n    /// short form signatures instead.\n    function tryRecoverCalldata(bytes32 hash, bytes calldata signature)\n        internal\n        view\n        returns (address result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n            mstore(0x00, hash)\n            mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.\n            calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.\n            pop(\n                staticcall(\n                    gas(), // Amount of gas left for the transaction.\n                    eq(signature.length, 65), // Address of `ecrecover`.\n                    0x00, // Start of input.\n                    0x80, // Size of input.\n                    0x40, // Start of output.\n                    0x20 // Size of output.\n                )\n            )\n            mstore(0x60, 0) // Restore the zero slot.\n            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n            result := mload(xor(0x60, returndatasize()))\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /// @dev Recovers the signer's address from a message digest `hash`,\n    /// and the EIP-2098 short form signature defined by `r` and `vs`.\n    ///\n    /// This function only accepts EIP-2098 short form signatures.\n    /// See: https://eips.ethereum.org/EIPS/eip-2098\n    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs)\n        internal\n        view\n        returns (address result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n            mstore(0x00, hash)\n            mstore(0x20, add(shr(255, vs), 27)) // `v`.\n            mstore(0x40, r)\n            mstore(0x60, shr(1, shl(1, vs))) // `s`.\n            pop(\n                staticcall(\n                    gas(), // Amount of gas left for the transaction.\n                    1, // Address of `ecrecover`.\n                    0x00, // Start of input.\n                    0x80, // Size of input.\n                    0x40, // Start of output.\n                    0x20 // Size of output.\n                )\n            )\n            mstore(0x60, 0) // Restore the zero slot.\n            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n            result := mload(xor(0x60, returndatasize()))\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /// @dev Recovers the signer's address from a message digest `hash`,\n    /// and the signature defined by `v`, `r`, `s`.\n    function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)\n        internal\n        view\n        returns (address result)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n            mstore(0x00, hash)\n            mstore(0x20, and(v, 0xff))\n            mstore(0x40, r)\n            mstore(0x60, s)\n            pop(\n                staticcall(\n                    gas(), // Amount of gas left for the transaction.\n                    1, // Address of `ecrecover`.\n                    0x00, // Start of input.\n                    0x80, // Size of input.\n                    0x40, // Start of output.\n                    0x20 // Size of output.\n                )\n            )\n            mstore(0x60, 0) // Restore the zero slot.\n            // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.\n            result := mload(xor(0x60, returndatasize()))\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                     HASHING OPERATIONS                     */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns an Ethereum Signed Message, created from a `hash`.\n    /// This produces a hash corresponding to the one signed with the\n    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)\n    /// JSON-RPC method as part of EIP-191.\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x20, hash) // Store into scratch space for keccak256.\n            mstore(0x00, \"\\x00\\x00\\x00\\x00\\x19Ethereum Signed Message:\\n32\") // 28 bytes.\n            result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`.\n        }\n    }\n\n    /// @dev Returns an Ethereum Signed Message, created from `s`.\n    /// This produces a hash corresponding to the one signed with the\n    /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign)\n    /// JSON-RPC method as part of EIP-191.\n    /// Note: Supports lengths of `s` up to 999999 bytes.\n    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let sLength := mload(s)\n            let o := 0x20\n            mstore(o, \"\\x19Ethereum Signed Message:\\n\") // 26 bytes, zero-right-padded.\n            mstore(0x00, 0x00)\n            // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`.\n            for { let temp := sLength } 1 {} {\n                o := sub(o, 1)\n                mstore8(o, add(48, mod(temp, 10)))\n                temp := div(temp, 10)\n                if iszero(temp) { break }\n            }\n            let n := sub(0x3a, o) // Header length: `26 + 32 - o`.\n            // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes.\n            returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20))\n            mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header.\n            result := keccak256(add(s, sub(0x20, n)), add(n, sLength))\n            mstore(s, sLength) // Restore the length.\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                   EMPTY CALLDATA HELPERS                   */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns an empty calldata bytes.\n    function emptySignature() internal pure returns (bytes calldata signature) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            signature.length := 0\n        }\n    }\n}\n"
      },
      "lib/solady/src/utils/FixedPointMathLib.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Arithmetic library with operations for fixed-point numbers.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/FixedPointMathLib.sol)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)\nlibrary FixedPointMathLib {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                       CUSTOM ERRORS                        */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The operation failed, as the output exceeds the maximum value of uint256.\n    error ExpOverflow();\n\n    /// @dev The operation failed, as the output exceeds the maximum value of uint256.\n    error FactorialOverflow();\n\n    /// @dev The operation failed, due to an overflow.\n    error RPowOverflow();\n\n    /// @dev The operation failed, due to an multiplication overflow.\n    error MulWadFailed();\n\n    /// @dev The operation failed, either due to a\n    /// multiplication overflow, or a division by a zero.\n    error DivWadFailed();\n\n    /// @dev The multiply-divide operation failed, either due to a\n    /// multiplication overflow, or a division by a zero.\n    error MulDivFailed();\n\n    /// @dev The division failed, as the denominator is zero.\n    error DivFailed();\n\n    /// @dev The full precision multiply-divide operation failed, either due\n    /// to the result being larger than 256 bits, or a division by a zero.\n    error FullMulDivFailed();\n\n    /// @dev The output is undefined, as the input is less-than-or-equal to zero.\n    error LnWadUndefined();\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                         CONSTANTS                          */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The scalar of ETH and most ERC20s.\n    uint256 internal constant WAD = 1e18;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*              SIMPLIFIED FIXED POINT OPERATIONS             */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Equivalent to `(x * y) / WAD` rounded down.\n    function mulWad(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`.\n            if mul(y, gt(x, div(not(0), y))) {\n                mstore(0x00, 0xbac65e5b) // `MulWadFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := div(mul(x, y), WAD)\n        }\n    }\n\n    /// @dev Equivalent to `(x * y) / WAD` rounded up.\n    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`.\n            if mul(y, gt(x, div(not(0), y))) {\n                mstore(0x00, 0xbac65e5b) // `MulWadFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := add(iszero(iszero(mod(mul(x, y), WAD))), div(mul(x, y), WAD))\n        }\n    }\n\n    /// @dev Equivalent to `(x * WAD) / y` rounded down.\n    function divWad(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to `require(y != 0 && (WAD == 0 || x <= type(uint256).max / WAD))`.\n            if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) {\n                mstore(0x00, 0x7c5f487d) // `DivWadFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := div(mul(x, WAD), y)\n        }\n    }\n\n    /// @dev Equivalent to `(x * WAD) / y` rounded up.\n    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to `require(y != 0 && (WAD == 0 || x <= type(uint256).max / WAD))`.\n            if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) {\n                mstore(0x00, 0x7c5f487d) // `DivWadFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := add(iszero(iszero(mod(mul(x, WAD), y))), div(mul(x, WAD), y))\n        }\n    }\n\n    /// @dev Equivalent to `x` to the power of `y`.\n    /// because `x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)`.\n    function powWad(int256 x, int256 y) internal pure returns (int256) {\n        // Using `ln(x)` means `x` must be greater than 0.\n        return expWad((lnWad(x) * y) / int256(WAD));\n    }\n\n    /// @dev Returns `exp(x)`, denominated in `WAD`.\n    function expWad(int256 x) internal pure returns (int256 r) {\n        unchecked {\n            // When the result is < 0.5 we return zero. This happens when\n            // x <= floor(log(0.5e18) * 1e18) ~ -42e18\n            if (x <= -42139678854452767551) return r;\n\n            /// @solidity memory-safe-assembly\n            assembly {\n                // When the result is > (2**255 - 1) / 1e18 we can not represent it as an\n                // int. This happens when x >= floor(log((2**255 - 1) / 1e18) * 1e18) ~ 135.\n                if iszero(slt(x, 135305999368893231589)) {\n                    mstore(0x00, 0xa37bfec9) // `ExpOverflow()`.\n                    revert(0x1c, 0x04)\n                }\n            }\n\n            // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96\n            // for more intermediate precision and a binary basis. This base conversion\n            // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78.\n            x = (x << 78) / 5 ** 18;\n\n            // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers\n            // of two such that exp(x) = exp(x') * 2**k, where k is an integer.\n            // Solving this gives k = round(x / log(2)) and x' = x - k * log(2).\n            int256 k = ((x << 96) / 54916777467707473351141471128 + 2 ** 95) >> 96;\n            x = x - k * 54916777467707473351141471128;\n\n            // k is in the range [-61, 195].\n\n            // Evaluate using a (6, 7)-term rational approximation.\n            // p is made monic, we'll multiply by a scale factor later.\n            int256 y = x + 1346386616545796478920950773328;\n            y = ((y * x) >> 96) + 57155421227552351082224309758442;\n            int256 p = y + x - 94201549194550492254356042504812;\n            p = ((p * y) >> 96) + 28719021644029726153956944680412240;\n            p = p * x + (4385272521454847904659076985693276 << 96);\n\n            // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n            int256 q = x - 2855989394907223263936484059900;\n            q = ((q * x) >> 96) + 50020603652535783019961831881945;\n            q = ((q * x) >> 96) - 533845033583426703283633433725380;\n            q = ((q * x) >> 96) + 3604857256930695427073651918091429;\n            q = ((q * x) >> 96) - 14423608567350463180887372962807573;\n            q = ((q * x) >> 96) + 26449188498355588339934803723976023;\n\n            /// @solidity memory-safe-assembly\n            assembly {\n                // Div in assembly because solidity adds a zero check despite the unchecked.\n                // The q polynomial won't have zeros in the domain as all its roots are complex.\n                // No scaling is necessary because p is already 2**96 too large.\n                r := sdiv(p, q)\n            }\n\n            // r should be in the range (0.09, 0.25) * 2**96.\n\n            // We now need to multiply r by:\n            // * the scale factor s = ~6.031367120.\n            // * the 2**k factor from the range reduction.\n            // * the 1e18 / 2**96 factor for base conversion.\n            // We do this all at once, with an intermediate result in 2**213\n            // basis, so the final right shift is always by a positive amount.\n            r = int256(\n                (uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k)\n            );\n        }\n    }\n\n    /// @dev Returns `ln(x)`, denominated in `WAD`.\n    function lnWad(int256 x) internal pure returns (int256 r) {\n        unchecked {\n            /// @solidity memory-safe-assembly\n            assembly {\n                if iszero(sgt(x, 0)) {\n                    mstore(0x00, 0x1615e638) // `LnWadUndefined()`.\n                    revert(0x1c, 0x04)\n                }\n            }\n\n            // We want to convert x from 10**18 fixed point to 2**96 fixed point.\n            // We do this by multiplying by 2**96 / 10**18. But since\n            // ln(x * C) = ln(x) + ln(C), we can simply do nothing here\n            // and add ln(2**96 / 10**18) at the end.\n\n            // Compute k = log2(x) - 96.\n            int256 k;\n            /// @solidity memory-safe-assembly\n            assembly {\n                k := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n                k := or(k, shl(6, lt(0xffffffffffffffff, shr(k, x))))\n                k := or(k, shl(5, lt(0xffffffff, shr(k, x))))\n                k := or(k, shl(4, lt(0xffff, shr(k, x))))\n                k := or(k, shl(3, lt(0xff, shr(k, x))))\n                k := or(k, shl(2, lt(0xf, shr(k, x))))\n                k := sub(or(k, byte(shr(k, x), hex\"00000101020202020303030303030303\")), 96)\n            }\n\n            // Reduce range of x to (1, 2) * 2**96\n            // ln(2^k * x) = k * ln(2) + ln(x)\n            x = int256(uint256(x << uint256(159 - k)) >> 159);\n\n            // Evaluate using a (8, 8)-term rational approximation.\n            // p is made monic, we will multiply by a scale factor later.\n            int256 p = x + 3273285459638523848632254066296;\n            p = ((p * x) >> 96) + 24828157081833163892658089445524;\n            p = ((p * x) >> 96) + 43456485725739037958740375743393;\n            p = ((p * x) >> 96) - 11111509109440967052023855526967;\n            p = ((p * x) >> 96) - 45023709667254063763336534515857;\n            p = ((p * x) >> 96) - 14706773417378608786704636184526;\n            p = p * x - (795164235651350426258249787498 << 96);\n\n            // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n            // q is monic by convention.\n            int256 q = x + 5573035233440673466300451813936;\n            q = ((q * x) >> 96) + 71694874799317883764090561454958;\n            q = ((q * x) >> 96) + 283447036172924575727196451306956;\n            q = ((q * x) >> 96) + 401686690394027663651624208769553;\n            q = ((q * x) >> 96) + 204048457590392012362485061816622;\n            q = ((q * x) >> 96) + 31853899698501571402653359427138;\n            q = ((q * x) >> 96) + 909429971244387300277376558375;\n            /// @solidity memory-safe-assembly\n            assembly {\n                // Div in assembly because solidity adds a zero check despite the unchecked.\n                // The q polynomial is known not to have zeros in the domain.\n                // No scaling required because p is already 2**96 too large.\n                r := sdiv(p, q)\n            }\n\n            // r is in the range (0, 0.125) * 2**96\n\n            // Finalization, we need to:\n            // * multiply by the scale factor s = 5.549…\n            // * add ln(2**96 / 10**18)\n            // * add k * ln(2)\n            // * multiply by 10**18 / 2**96 = 5**18 >> 78\n\n            // mul s * 5e18 * 2**96, base is now 5**18 * 2**192\n            r *= 1677202110996718588342820967067443963516166;\n            // add ln(2) * k * 5e18 * 2**192\n            r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k;\n            // add ln(2**96 / 10**18) * 5e18 * 2**192\n            r += 600920179829731861736702779321621459595472258049074101567377883020018308;\n            // base conversion: mul 2**18 / 2**192\n            r >>= 174;\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                  GENERAL NUMBER UTILITIES                  */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Calculates `floor(a * b / d)` with full precision.\n    /// Throws if result overflows a uint256 or when `d` is zero.\n    /// Credit to Remco Bloemen under MIT license: https://2π.com/21/muldiv\n    function fullMulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            for {} 1 {} {\n                // 512-bit multiply `[p1 p0] = x * y`.\n                // Compute the product mod `2**256` and mod `2**256 - 1`\n                // then use the Chinese Remainder Theorem to reconstruct\n                // the 512 bit result. The result is stored in two 256\n                // variables such that `product = p1 * 2**256 + p0`.\n\n                // Least significant 256 bits of the product.\n                let p0 := mul(x, y)\n                let mm := mulmod(x, y, not(0))\n                // Most significant 256 bits of the product.\n                let p1 := sub(mm, add(p0, lt(mm, p0)))\n\n                // Handle non-overflow cases, 256 by 256 division.\n                if iszero(p1) {\n                    if iszero(d) {\n                        mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.\n                        revert(0x1c, 0x04)\n                    }\n                    result := div(p0, d)\n                    break\n                }\n\n                // Make sure the result is less than `2**256`. Also prevents `d == 0`.\n                if iszero(gt(d, p1)) {\n                    mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.\n                    revert(0x1c, 0x04)\n                }\n\n                /*------------------- 512 by 256 division --------------------*/\n\n                // Make division exact by subtracting the remainder from `[p1 p0]`.\n                // Compute remainder using mulmod.\n                let r := mulmod(x, y, d)\n                // `t` is the least significant bit of `d`.\n                // Always greater or equal to 1.\n                let t := and(d, sub(0, d))\n                // Divide `d` by `t`, which is a power of two.\n                d := div(d, t)\n                // Invert `d mod 2**256`\n                // Now that `d` is an odd number, it has an inverse\n                // modulo `2**256` such that `d * inv = 1 mod 2**256`.\n                // Compute the inverse by starting with a seed that is correct\n                // correct for four bits. That is, `d * inv = 1 mod 2**4`.\n                let inv := xor(mul(3, d), 2)\n                // Now use Newton-Raphson iteration to improve the precision.\n                // Thanks to Hensel's lifting lemma, this also works in modular\n                // arithmetic, doubling the correct bits in each step.\n                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**8\n                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**16\n                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**32\n                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**64\n                inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**128\n                result :=\n                    mul(\n                        // Divide [p1 p0] by the factors of two.\n                        // Shift in bits from `p1` into `p0`. For this we need\n                        // to flip `t` such that it is `2**256 / t`.\n                        or(mul(sub(p1, gt(r, p0)), add(div(sub(0, t), t), 1)), div(sub(p0, r), t)),\n                        // inverse mod 2**256\n                        mul(inv, sub(2, mul(d, inv)))\n                    )\n                break\n            }\n        }\n    }\n\n    /// @dev Calculates `floor(x * y / d)` with full precision, rounded up.\n    /// Throws if result overflows a uint256 or when `d` is zero.\n    /// Credit to Uniswap-v3-core under MIT license:\n    /// https://github.com/Uniswap/v3-core/blob/contracts/libraries/FullMath.sol\n    function fullMulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) {\n        result = fullMulDiv(x, y, d);\n        /// @solidity memory-safe-assembly\n        assembly {\n            if mulmod(x, y, d) {\n                result := add(result, 1)\n                if iszero(result) {\n                    mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.\n                    revert(0x1c, 0x04)\n                }\n            }\n        }\n    }\n\n    /// @dev Returns `floor(x * y / d)`.\n    /// Reverts if `x * y` overflows, or `d` is zero.\n    function mulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to require(d != 0 && (y == 0 || x <= type(uint256).max / y))\n            if iszero(mul(d, iszero(mul(y, gt(x, div(not(0), y)))))) {\n                mstore(0x00, 0xad251c27) // `MulDivFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := div(mul(x, y), d)\n        }\n    }\n\n    /// @dev Returns `ceil(x * y / d)`.\n    /// Reverts if `x * y` overflows, or `d` is zero.\n    function mulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Equivalent to require(d != 0 && (y == 0 || x <= type(uint256).max / y))\n            if iszero(mul(d, iszero(mul(y, gt(x, div(not(0), y)))))) {\n                mstore(0x00, 0xad251c27) // `MulDivFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := add(iszero(iszero(mod(mul(x, y), d))), div(mul(x, y), d))\n        }\n    }\n\n    /// @dev Returns `ceil(x / d)`.\n    /// Reverts if `d` is zero.\n    function divUp(uint256 x, uint256 d) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if iszero(d) {\n                mstore(0x00, 0x65244e4e) // `DivFailed()`.\n                revert(0x1c, 0x04)\n            }\n            z := add(iszero(iszero(mod(x, d))), div(x, d))\n        }\n    }\n\n    /// @dev Returns `max(0, x - y)`.\n    function zeroFloorSub(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := mul(gt(x, y), sub(x, y))\n        }\n    }\n\n    /// @dev Exponentiate `x` to `y` by squaring, denominated in base `b`.\n    /// Reverts if the computation overflows.\n    function rpow(uint256 x, uint256 y, uint256 b) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := mul(b, iszero(y)) // `0 ** 0 = 1`. Otherwise, `0 ** n = 0`.\n            if x {\n                z := xor(b, mul(xor(b, x), and(y, 1))) // `z = isEven(y) ? scale : x`\n                let half := shr(1, b) // Divide `b` by 2.\n                // Divide `y` by 2 every iteration.\n                for { y := shr(1, y) } y { y := shr(1, y) } {\n                    let xx := mul(x, x) // Store x squared.\n                    let xxRound := add(xx, half) // Round to the nearest number.\n                    // Revert if `xx + half` overflowed, or if `x ** 2` overflows.\n                    if or(lt(xxRound, xx), shr(128, x)) {\n                        mstore(0x00, 0x49f7642b) // `RPowOverflow()`.\n                        revert(0x1c, 0x04)\n                    }\n                    x := div(xxRound, b) // Set `x` to scaled `xxRound`.\n                    // If `y` is odd:\n                    if and(y, 1) {\n                        let zx := mul(z, x) // Compute `z * x`.\n                        let zxRound := add(zx, half) // Round to the nearest number.\n                        // If `z * x` overflowed or `zx + half` overflowed:\n                        if or(xor(div(zx, x), z), lt(zxRound, zx)) {\n                            // Revert if `x` is non-zero.\n                            if iszero(iszero(x)) {\n                                mstore(0x00, 0x49f7642b) // `RPowOverflow()`.\n                                revert(0x1c, 0x04)\n                            }\n                        }\n                        z := div(zxRound, b) // Return properly scaled `zxRound`.\n                    }\n                }\n            }\n        }\n    }\n\n    /// @dev Returns the square root of `x`.\n    function sqrt(uint256 x) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // `floor(sqrt(2**15)) = 181`. `sqrt(2**15) - 181 = 2.84`.\n            z := 181 // The \"correct\" value is 1, but this saves a multiplication later.\n\n            // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\n            // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\n\n            // Let `y = x / 2**r`. We check `y >= 2**(k + 8)`\n            // but shift right by `k` bits to ensure that if `x >= 256`, then `y >= 256`.\n            let r := shl(7, lt(0xffffffffffffffffffffffffffffffffff, x))\n            r := or(r, shl(6, lt(0xffffffffffffffffff, shr(r, x))))\n            r := or(r, shl(5, lt(0xffffffffff, shr(r, x))))\n            r := or(r, shl(4, lt(0xffffff, shr(r, x))))\n            z := shl(shr(1, r), z)\n\n            // Goal was to get `z*z*y` within a small factor of `x`. More iterations could\n            // get y in a tighter range. Currently, we will have y in `[256, 256*(2**16))`.\n            // We ensured `y >= 256` so that the relative difference between `y` and `y+1` is small.\n            // That's not possible if `x < 256` but we can just verify those cases exhaustively.\n\n            // Now, `z*z*y <= x < z*z*(y+1)`, and `y <= 2**(16+8)`, and either `y >= 256`, or `x < 256`.\n            // Correctness can be checked exhaustively for `x < 256`, so we assume `y >= 256`.\n            // Then `z*sqrt(y)` is within `sqrt(257)/sqrt(256)` of `sqrt(x)`, or about 20bps.\n\n            // For `s` in the range `[1/256, 256]`, the estimate `f(s) = (181/1024) * (s+1)`\n            // is in the range `(1/2.84 * sqrt(s), 2.84 * sqrt(s))`,\n            // with largest error when `s = 1` and when `s = 256` or `1/256`.\n\n            // Since `y` is in `[256, 256*(2**16))`, let `a = y/65536`, so that `a` is in `[1/256, 256)`.\n            // Then we can estimate `sqrt(y)` using\n            // `sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2**18`.\n\n            // There is no overflow risk here since `y < 2**136` after the first branch above.\n            z := shr(18, mul(z, add(shr(r, x), 65536))) // A `mul()` is saved from starting `z` at 181.\n\n            // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n            z := shr(1, add(z, div(x, z)))\n\n            // If `x+1` is a perfect square, the Babylonian method cycles between\n            // `floor(sqrt(x))` and `ceil(sqrt(x))`. This statement ensures we return floor.\n            // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\n            z := sub(z, lt(div(x, z), z))\n        }\n    }\n\n    /// @dev Returns the cube root of `x`.\n    /// Credit to bout3fiddy and pcaversaccio under AGPLv3 license:\n    /// https://github.com/pcaversaccio/snekmate/blob/main/src/utils/Math.vy\n    function cbrt(uint256 x) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n            r := or(r, shl(4, lt(0xffff, shr(r, x))))\n            r := or(r, shl(3, lt(0xff, shr(r, x))))\n\n            z := div(shl(div(r, 3), shl(lt(0xf, shr(r, x)), 0xf)), xor(7, mod(r, 3)))\n\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n            z := div(add(add(div(x, mul(z, z)), z), z), 3)\n\n            z := sub(z, lt(div(x, mul(z, z)), z))\n        }\n    }\n\n    /// @dev Returns the square root of `x`, denominated in `WAD`.\n    function sqrtWad(uint256 x) internal pure returns (uint256 z) {\n        unchecked {\n            z = 10 ** 9;\n            if (x <= type(uint256).max / 10 ** 36 - 1) {\n                x *= 10 ** 18;\n                z = 1;\n            }\n            z *= sqrt(x);\n        }\n    }\n\n    /// @dev Returns the cube root of `x`, denominated in `WAD`.\n    function cbrtWad(uint256 x) internal pure returns (uint256 z) {\n        unchecked {\n            z = 10 ** 12;\n            if (x <= (type(uint256).max / 10 ** 36) * 10 ** 18 - 1) {\n                if (x >= type(uint256).max / 10 ** 36) {\n                    x *= 10 ** 18;\n                    z = 10 ** 6;\n                } else {\n                    x *= 10 ** 36;\n                    z = 1;\n                }\n            }\n            z *= cbrt(x);\n        }\n    }\n\n    /// @dev Returns the factorial of `x`.\n    function factorial(uint256 x) internal pure returns (uint256 result) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if iszero(lt(x, 58)) {\n                mstore(0x00, 0xaba0f2a2) // `FactorialOverflow()`.\n                revert(0x1c, 0x04)\n            }\n            for { result := 1 } x { x := sub(x, 1) } { result := mul(result, x) }\n        }\n    }\n\n    /// @dev Returns the log2 of `x`.\n    /// Equivalent to computing the index of the most significant bit (MSB) of `x`.\n    /// Returns 0 if `x` is zero.\n    function log2(uint256 x) internal pure returns (uint256 r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n            r := or(r, shl(4, lt(0xffff, shr(r, x))))\n            r := or(r, shl(3, lt(0xff, shr(r, x))))\n            r := or(r, shl(2, lt(0xf, shr(r, x))))\n            r := or(r, byte(shr(r, x), hex\"00000101020202020303030303030303\"))\n        }\n    }\n\n    /// @dev Returns the log2 of `x`, rounded up.\n    /// Returns 0 if `x` is zero.\n    function log2Up(uint256 x) internal pure returns (uint256 r) {\n        r = log2(x);\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := add(r, lt(shl(r, 1), x))\n        }\n    }\n\n    /// @dev Returns the log10 of `x`.\n    /// Returns 0 if `x` is zero.\n    function log10(uint256 x) internal pure returns (uint256 r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if iszero(lt(x, 100000000000000000000000000000000000000)) {\n                x := div(x, 100000000000000000000000000000000000000)\n                r := 38\n            }\n            if iszero(lt(x, 100000000000000000000)) {\n                x := div(x, 100000000000000000000)\n                r := add(r, 20)\n            }\n            if iszero(lt(x, 10000000000)) {\n                x := div(x, 10000000000)\n                r := add(r, 10)\n            }\n            if iszero(lt(x, 100000)) {\n                x := div(x, 100000)\n                r := add(r, 5)\n            }\n            r := add(r, add(gt(x, 9), add(gt(x, 99), add(gt(x, 999), gt(x, 9999)))))\n        }\n    }\n\n    /// @dev Returns the log10 of `x`, rounded up.\n    /// Returns 0 if `x` is zero.\n    function log10Up(uint256 x) internal pure returns (uint256 r) {\n        r = log10(x);\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := add(r, lt(exp(10, r), x))\n        }\n    }\n\n    /// @dev Returns the log256 of `x`.\n    /// Returns 0 if `x` is zero.\n    function log256(uint256 x) internal pure returns (uint256 r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n            r := or(r, shl(4, lt(0xffff, shr(r, x))))\n            r := or(shr(3, r), lt(0xff, shr(r, x)))\n        }\n    }\n\n    /// @dev Returns the log256 of `x`, rounded up.\n    /// Returns 0 if `x` is zero.\n    function log256Up(uint256 x) internal pure returns (uint256 r) {\n        r = log256(x);\n        /// @solidity memory-safe-assembly\n        assembly {\n            r := add(r, lt(shl(shl(3, r), 1), x))\n        }\n    }\n\n    /// @dev Returns the average of `x` and `y`.\n    function avg(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        unchecked {\n            z = (x & y) + ((x ^ y) >> 1);\n        }\n    }\n\n    /// @dev Returns the average of `x` and `y`.\n    function avg(int256 x, int256 y) internal pure returns (int256 z) {\n        unchecked {\n            z = (x >> 1) + (y >> 1) + (((x & 1) + (y & 1)) >> 1);\n        }\n    }\n\n    /// @dev Returns the absolute value of `x`.\n    function abs(int256 x) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(sub(0, shr(255, x)), add(sub(0, shr(255, x)), x))\n        }\n    }\n\n    /// @dev Returns the absolute distance between `x` and `y`.\n    function dist(int256 x, int256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(mul(xor(sub(y, x), sub(x, y)), sgt(x, y)), sub(y, x))\n        }\n    }\n\n    /// @dev Returns the minimum of `x` and `y`.\n    function min(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(x, mul(xor(x, y), lt(y, x)))\n        }\n    }\n\n    /// @dev Returns the minimum of `x` and `y`.\n    function min(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(x, mul(xor(x, y), slt(y, x)))\n        }\n    }\n\n    /// @dev Returns the maximum of `x` and `y`.\n    function max(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(x, mul(xor(x, y), gt(y, x)))\n        }\n    }\n\n    /// @dev Returns the maximum of `x` and `y`.\n    function max(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(x, mul(xor(x, y), sgt(y, x)))\n        }\n    }\n\n    /// @dev Returns `x`, bounded to `minValue` and `maxValue`.\n    function clamp(uint256 x, uint256 minValue, uint256 maxValue)\n        internal\n        pure\n        returns (uint256 z)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(x, mul(xor(x, minValue), gt(minValue, x)))\n            z := xor(z, mul(xor(z, maxValue), lt(maxValue, z)))\n        }\n    }\n\n    /// @dev Returns `x`, bounded to `minValue` and `maxValue`.\n    function clamp(int256 x, int256 minValue, int256 maxValue) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := xor(x, mul(xor(x, minValue), sgt(minValue, x)))\n            z := xor(z, mul(xor(z, maxValue), slt(maxValue, z)))\n        }\n    }\n\n    /// @dev Returns greatest common divisor of `x` and `y`.\n    function gcd(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            for { z := x } y {} {\n                let t := y\n                y := mod(z, y)\n                z := t\n            }\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                   RAW NUMBER OPERATIONS                    */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns `x + y`, without checking for overflow.\n    function rawAdd(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        unchecked {\n            z = x + y;\n        }\n    }\n\n    /// @dev Returns `x + y`, without checking for overflow.\n    function rawAdd(int256 x, int256 y) internal pure returns (int256 z) {\n        unchecked {\n            z = x + y;\n        }\n    }\n\n    /// @dev Returns `x - y`, without checking for underflow.\n    function rawSub(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        unchecked {\n            z = x - y;\n        }\n    }\n\n    /// @dev Returns `x - y`, without checking for underflow.\n    function rawSub(int256 x, int256 y) internal pure returns (int256 z) {\n        unchecked {\n            z = x - y;\n        }\n    }\n\n    /// @dev Returns `x * y`, without checking for overflow.\n    function rawMul(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        unchecked {\n            z = x * y;\n        }\n    }\n\n    /// @dev Returns `x * y`, without checking for overflow.\n    function rawMul(int256 x, int256 y) internal pure returns (int256 z) {\n        unchecked {\n            z = x * y;\n        }\n    }\n\n    /// @dev Returns `x / y`, returning 0 if `y` is zero.\n    function rawDiv(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := div(x, y)\n        }\n    }\n\n    /// @dev Returns `x / y`, returning 0 if `y` is zero.\n    function rawSDiv(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := sdiv(x, y)\n        }\n    }\n\n    /// @dev Returns `x % y`, returning 0 if `y` is zero.\n    function rawMod(uint256 x, uint256 y) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := mod(x, y)\n        }\n    }\n\n    /// @dev Returns `x % y`, returning 0 if `y` is zero.\n    function rawSMod(int256 x, int256 y) internal pure returns (int256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := smod(x, y)\n        }\n    }\n\n    /// @dev Returns `(x + y) % d`, return 0 if `d` if zero.\n    function rawAddMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := addmod(x, y, d)\n        }\n    }\n\n    /// @dev Returns `(x * y) % d`, return 0 if `d` if zero.\n    function rawMulMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            z := mulmod(x, y, d)\n        }\n    }\n}\n"
      },
      "lib/solady/src/utils/SafeTransferLib.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\n///\n/// @dev Note:\n/// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection.\n/// - For ERC20s, this implementation won't check that a token has code,\n///   responsibility is delegated to the caller.\nlibrary SafeTransferLib {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                       CUSTOM ERRORS                        */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev The ETH transfer has failed.\n    error ETHTransferFailed();\n\n    /// @dev The ERC20 `transferFrom` has failed.\n    error TransferFromFailed();\n\n    /// @dev The ERC20 `transfer` has failed.\n    error TransferFailed();\n\n    /// @dev The ERC20 `approve` has failed.\n    error ApproveFailed();\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                         CONSTANTS                          */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes.\n    uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300;\n\n    /// @dev Suggested gas stipend for contract receiving ETH to perform a few\n    /// storage reads and writes, but low enough to prevent griefing.\n    uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                       ETH OPERATIONS                       */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants.\n    //\n    // The regular variants:\n    // - Forwards all remaining gas to the target.\n    // - Reverts if the target reverts.\n    // - Reverts if the current contract has insufficient balance.\n    //\n    // The force variants:\n    // - Forwards with an optional gas stipend\n    //   (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases).\n    // - If the target reverts, or if the gas stipend is exhausted,\n    //   creates a temporary contract to force send the ETH via `SELFDESTRUCT`.\n    //   Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758.\n    // - Reverts if the current contract has insufficient balance.\n    //\n    // The try variants:\n    // - Forwards with a mandatory gas stipend.\n    // - Instead of reverting, returns whether the transfer succeeded.\n\n    /// @dev Sends `amount` (in wei) ETH to `to`.\n    function safeTransferETH(address to, uint256 amount) internal {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) {\n                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n                revert(0x1c, 0x04)\n            }\n        }\n    }\n\n    /// @dev Sends all the ETH in the current contract to `to`.\n    function safeTransferAllETH(address to) internal {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Transfer all the ETH and check if it succeeded or not.\n            if iszero(call(gas(), to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {\n                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n                revert(0x1c, 0x04)\n            }\n        }\n    }\n\n    /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.\n    function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if lt(selfbalance(), amount) {\n                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n                revert(0x1c, 0x04)\n            }\n            if iszero(call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)) {\n                mstore(0x00, to) // Store the address in scratch space.\n                mstore8(0x0b, 0x73) // Opcode `PUSH20`.\n                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\n                if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\n            }\n        }\n    }\n\n    /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`.\n    function forceSafeTransferAllETH(address to, uint256 gasStipend) internal {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if iszero(call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {\n                mstore(0x00, to) // Store the address in scratch space.\n                mstore8(0x0b, 0x73) // Opcode `PUSH20`.\n                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\n                if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\n            }\n        }\n    }\n\n    /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`.\n    function forceSafeTransferETH(address to, uint256 amount) internal {\n        /// @solidity memory-safe-assembly\n        assembly {\n            if lt(selfbalance(), amount) {\n                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.\n                revert(0x1c, 0x04)\n            }\n            if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, codesize(), 0x00, codesize(), 0x00)) {\n                mstore(0x00, to) // Store the address in scratch space.\n                mstore8(0x0b, 0x73) // Opcode `PUSH20`.\n                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\n                if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\n            }\n        }\n    }\n\n    /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`.\n    function forceSafeTransferAllETH(address to) internal {\n        /// @solidity memory-safe-assembly\n        assembly {\n            // forgefmt: disable-next-item\n            if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {\n                mstore(0x00, to) // Store the address in scratch space.\n                mstore8(0x0b, 0x73) // Opcode `PUSH20`.\n                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\n                if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.\n            }\n        }\n    }\n\n    /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.\n    function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)\n        internal\n        returns (bool success)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            success := call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)\n        }\n    }\n\n    /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`.\n    function trySafeTransferAllETH(address to, uint256 gasStipend)\n        internal\n        returns (bool success)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            success := call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                      ERC20 OPERATIONS                      */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.\n    /// Reverts upon failure.\n    ///\n    /// The `from` account must have at least `amount` approved for\n    /// the current contract to manage.\n    function safeTransferFrom(address token, address from, address to, uint256 amount) internal {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n            mstore(0x60, amount) // Store the `amount` argument.\n            mstore(0x40, to) // Store the `to` argument.\n            mstore(0x2c, shl(96, from)) // Store the `from` argument.\n            mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.\n            // Perform the transfer, reverting upon failure.\n            if iszero(\n                and( // The arguments of `and` are evaluated from right to left.\n                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n                    call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)\n                )\n            ) {\n                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x60, 0) // Restore the zero slot to zero.\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /// @dev Sends all of ERC20 `token` from `from` to `to`.\n    /// Reverts upon failure.\n    ///\n    /// The `from` account must have their entire balance approved for\n    /// the current contract to manage.\n    function safeTransferAllFrom(address token, address from, address to)\n        internal\n        returns (uint256 amount)\n    {\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Cache the free memory pointer.\n            mstore(0x40, to) // Store the `to` argument.\n            mstore(0x2c, shl(96, from)) // Store the `from` argument.\n            mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`.\n            // Read the balance, reverting upon failure.\n            if iszero(\n                and( // The arguments of `and` are evaluated from right to left.\n                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.\n                    staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)\n                )\n            ) {\n                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`.\n            amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it.\n            // Perform the transfer, reverting upon failure.\n            if iszero(\n                and( // The arguments of `and` are evaluated from right to left.\n                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n                    call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)\n                )\n            ) {\n                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x60, 0) // Restore the zero slot to zero.\n            mstore(0x40, m) // Restore the free memory pointer.\n        }\n    }\n\n    /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.\n    /// Reverts upon failure.\n    function safeTransfer(address token, address to, uint256 amount) internal {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x14, to) // Store the `to` argument.\n            mstore(0x34, amount) // Store the `amount` argument.\n            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.\n            // Perform the transfer, reverting upon failure.\n            if iszero(\n                and( // The arguments of `and` are evaluated from right to left.\n                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\n                )\n            ) {\n                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\n        }\n    }\n\n    /// @dev Sends all of ERC20 `token` from the current contract to `to`.\n    /// Reverts upon failure.\n    function safeTransferAll(address token, address to) internal returns (uint256 amount) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.\n            mstore(0x20, address()) // Store the address of the current contract.\n            // Read the balance, reverting upon failure.\n            if iszero(\n                and( // The arguments of `and` are evaluated from right to left.\n                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.\n                    staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)\n                )\n            ) {\n                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x14, to) // Store the `to` argument.\n            amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it.\n            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.\n            // Perform the transfer, reverting upon failure.\n            if iszero(\n                and( // The arguments of `and` are evaluated from right to left.\n                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\n                )\n            ) {\n                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\n        }\n    }\n\n    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.\n    /// Reverts upon failure.\n    function safeApprove(address token, address to, uint256 amount) internal {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x14, to) // Store the `to` argument.\n            mstore(0x34, amount) // Store the `amount` argument.\n            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.\n            // Perform the approval, reverting upon failure.\n            if iszero(\n                and( // The arguments of `and` are evaluated from right to left.\n                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\n                )\n            ) {\n                mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.\n                revert(0x1c, 0x04)\n            }\n            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\n        }\n    }\n\n    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.\n    /// If the initial attempt to approve fails, attempts to reset the approved amount to zero,\n    /// then retries the approval again (some tokens, e.g. USDT, requires this).\n    /// Reverts upon failure.\n    function safeApproveWithRetry(address token, address to, uint256 amount) internal {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x14, to) // Store the `to` argument.\n            mstore(0x34, amount) // Store the `amount` argument.\n            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.\n            // Perform the approval, retrying upon failure.\n            if iszero(\n                and( // The arguments of `and` are evaluated from right to left.\n                    or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n                    call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\n                )\n            ) {\n                mstore(0x34, 0) // Store 0 for the `amount`.\n                mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.\n                pop(call(gas(), token, 0, 0x10, 0x44, codesize(), 0x00)) // Reset the approval.\n                mstore(0x34, amount) // Store back the original `amount`.\n                // Retry the approval, reverting upon failure.\n                if iszero(\n                    and(\n                        or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing.\n                        call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)\n                    )\n                ) {\n                    mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.\n                    revert(0x1c, 0x04)\n                }\n            }\n            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.\n        }\n    }\n\n    /// @dev Returns the amount of ERC20 `token` owned by `account`.\n    /// Returns zero if the `token` does not exist.\n    function balanceOf(address token, address account) internal view returns (uint256 amount) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            mstore(0x14, account) // Store the `account` argument.\n            mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.\n            amount :=\n                mul(\n                    mload(0x20),\n                    and( // The arguments of `and` are evaluated from right to left.\n                        gt(returndatasize(), 0x1f), // At least 32 bytes returned.\n                        staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)\n                    )\n                )\n        }\n    }\n}\n"
      },
      "lib/unlockdv2-wallet/src/interfaces/IAllowedControllers.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.19;\n\ninterface IAllowedControllers {\n    event Collections(address indexed collections, bool isAllowed);\n\n    event DelegationController(address indexed delegationController, bool isAllowed);\n\n    function isAllowedDelegationController(address _controller) external view returns (bool);\n\n    function isAllowedCollection(address _collection) external view returns (bool);\n}\n"
      },
      "lib/unlockdv2-wallet/src/interfaces/IDelegationWalletRegistry.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity 0.8.19;\n\ninterface IDelegationWalletRegistry {\n    struct Wallet {\n        address wallet;\n        address owner;\n        address guard;\n        address guardOwner;\n        address delegationOwner;\n        address protocolOwner;\n    }\n\n    function setFactory(address _delegationWalletFactory) external;\n\n    function setWallet(\n        address _wallet,\n        address _owner,\n        address _guard,\n        address _guardOwner,\n        address _delegationGuard,\n        address _protocolOwner\n    ) external;\n\n    function getWallet(address _wallet) external view returns (Wallet memory);\n\n    function getOwnerWalletAddresses(address _owner) external view returns (address[] memory);\n\n    function getOwnerWalletAt(address _owner, uint256 _index) external view returns (Wallet memory);\n}\n"
      },
      "lib/unlockdv2-wallet/src/interfaces/IProtocolOwner.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\ninterface IProtocolOwner {\n    ////////////////////////////////////////////////////////////////////////////////\n    // Events\n    ////////////////////////////////////////////////////////////////////////////////\n\n    event SetLockController(address indexed lockController, bool allowed);\n    event ChangeOwner(address indexed asset, uint256 indexed assetId, address newOwner);\n    event LockedAsset(\n        address indexed asset,\n        uint256 indexed assetId,\n        uint256 claimDate,\n        address indexed lockController\n    );\n\n    event UnlockedAsset(address indexed asset, uint256 indexed assetId, address indexed lockController);\n    event ClaimedAsset(address indexed asset, uint256 indexed assetId, address indexed receiver);\n    event TransferredAsset(address indexed asset, uint256 indexed assetId, address indexed receiver);\n\n    event SetLoanId(bytes32 index, bytes32 loanId);\n    event SetBatchLoanId(bytes32[] indexed assets, bytes32 indexed loanId);\n\n    ////////////////////////////////////////////////////////////////////////////////\n    // Functions\n    ////////////////////////////////////////////////////////////////////////////////\n\n    function approveSale(\n        address _collection,\n        uint256 _tokenId,\n        address _underlyingAsset,\n        uint256 _amount,\n        address _marketApproval,\n        bytes32 _loanId\n    ) external;\n\n    // Delegatee Functions\n    function execTransaction(\n        address _to,\n        uint256 _value,\n        bytes calldata _data,\n        uint256 _safeTxGas,\n        uint256 _baseGas,\n        uint256 _gasPrice,\n        address _gasToken,\n        address payable _refundReceiver\n    ) external returns (bool success);\n\n    function delegateOneExecution(address to, bool value) external;\n\n    function isDelegatedExecution(address to) external view returns (bool);\n\n    function isAssetLocked(bytes32 _id) external view returns (bool);\n\n    function batchSetLoanId(bytes32[] calldata _assets, bytes32 _loanId) external;\n\n    function batchSetToZeroLoanId(bytes32[] calldata _assets) external;\n\n    function changeOwner(address _asset, uint256 _id, address _newOwner) external;\n\n    function getLoanId(bytes32 _assetId) external view returns (bytes32);\n\n    function setLoanId(bytes32 _assetId, bytes32 _loanId) external;\n\n    function safeSetLoanId(address _asset, uint256 _id, bytes32 _loanId) external;\n}\n"
      },
      "lib/unlockdv2-wallet/src/libs/logic/AssetLogic.sol": {
        "content": "// SPDX-License-Identifier: agpl-3.0\npragma solidity 0.8.19;\n\nlibrary AssetLogic {\n    function assetId(address _asset, uint256 _id) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(_asset, _id));\n    }\n\n    function getSelector(bytes memory _data) internal pure returns (bytes4 selector) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            selector := mload(add(_data, 32))\n        }\n    }\n}\n"
      },
      "src/interfaces/IACLManager.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {IAccessControl} from '@openzeppelin/contracts/access/IAccessControl.sol';\n\n/**\n * @title IACLManager\n * @author Unlockd\n * @notice Defines the basic interface for the ACL Manager\n */\ninterface IACLManager is IAccessControl {\n  /**\n   * @notice Returns the identifier of the UtokenAdmin role\n   * @return The id of the UtokenAdmin role\n   */\n  function UTOKEN_ADMIN() external view returns (bytes32);\n\n  /**\n   * @notice Returns the identifier of the Protocol Admin role\n   * @return The id of the Protocol Admin role\n   */\n  function PROTOCOL_ADMIN() external view returns (bytes32);\n\n  /**\n   * @notice Returns the identifier of the PriceUpdater role\n   * @return The id of the PriceUpdater role\n   */\n  function PRICE_UPDATER() external view returns (bytes32);\n\n  /**\n   * @notice Returns the identifier of the EmergencyAdmin role\n   * @return The id of the EmergencyAdmin role\n   */\n  function AUCTION_ADMIN() external view returns (bytes32);\n\n  /**\n   * @notice Returns the identifier of the EmergencyAdmin role\n   * @return The id of the EmergencyAdmin role\n   */\n  function EMERGENCY_ADMIN() external view returns (bytes32);\n\n  /**\n   * @notice Returns the identifier of the Governance Admin role\n   * @return The id of the PriceUpdater role\n   */\n  function GOVERNANCE_ADMIN() external view returns (bytes32);\n\n  /**\n   * @notice Returns the identifier of the WRAPPER ADAPTER role\n   * @return The id of the PriceUpdater role\n   */\n  function WRAPPER_ADAPTER() external view returns (bytes32);\n\n  /**\n   * @notice Set the address of the protocol\n   * @dev Is the main address of the protocol.Only can be updated by the ADMIN.\n   * @param protocol address of the protocol\n   */\n  function setProtocol(address protocol) external;\n\n  /**\n   * @notice Returns true if the address is the protocol, false otherwise\n   * @param protocol The address to check\n   * @return True if the given address is the protocol, false otherwise\n   */\n  function isProtocol(address protocol) external view returns (bool);\n\n  /**\n   * @notice Set the role as admin of a specific role.\n   * @dev By default the admin role for all roles is `DEFAULT_ADMIN_ROLE`.\n   * @param role The role to be managed by the admin role\n   * @param adminRole The admin role\n   */\n  function setRoleAdmin(bytes32 role, bytes32 adminRole) external;\n\n  // UTOKEN\n  /**\n   * @notice Adds a new admin as  Utoken Admin\n   * @param admin The address of the new admin\n   */\n  function addUTokenAdmin(address admin) external;\n\n  /**\n   * @notice Removes an admin as  Utoken Admin\n   * @param admin The address of the admin to remove\n   */\n  function removeUTokenAdmin(address admin) external;\n\n  /**\n   * @notice Returns true if the address is Utoken Admin, false otherwise\n   * @param admin The address to check\n   * @return True if the given address is  Utoken Admin, false otherwise\n   */\n  function isUTokenAdmin(address admin) external view returns (bool);\n\n  // PROTOCOL\n  /**\n   * @notice Adds a new admin as  Protocol Admin\n   * @param admin The address of the new admin\n   */\n  function addProtocolAdmin(address admin) external;\n\n  /**\n   * @notice Removes an admin as  Protocol Admin\n   * @param admin The address of the admin to remove\n   */\n  function removeProtocolAdmin(address admin) external;\n\n  /**\n   * @notice Returns true if the address is Protocol Admin, false otherwise\n   * @param admin The address to check\n   * @return True if the given address is  Protocol Admin, false otherwise\n   */\n  function isProtocolAdmin(address admin) external view returns (bool);\n\n  // AUCTION ADMIN\n  /**\n   * @notice Adds a new admin as  Auction Admin\n   * @param admin The address of the new admin\n   */\n  function addAuctionAdmin(address admin) external;\n\n  /**\n   * @notice Removes an admin as  Auction Admin\n   * @param admin The address of the admin to remove\n   */\n  function removeAuctionAdmin(address admin) external;\n\n  /**\n   * @notice Returns true if the address is Auction Admin, false otherwise\n   * @param admin The address to check\n   * @return True if the given address is  Auction Admin, false otherwise\n   */\n  function isAuctionAdmin(address admin) external view returns (bool);\n\n  // EMERGENCY\n  /**\n   * @notice Adds a new admin as EmergencyAdmin\n   * @param admin The address of the new admin\n   */\n  function addEmergencyAdmin(address admin) external;\n\n  /**\n   * @notice Removes an admin as EmergencyAdmin\n   * @param admin The address of the admin to remove\n   */\n  function removeEmergencyAdmin(address admin) external;\n\n  /**\n   * @notice Returns true if the address is EmergencyAdmin, false otherwise\n   * @param admin The address to check\n   * @return True if the given address is EmergencyAdmin, false otherwise\n   */\n  function isEmergencyAdmin(address admin) external view returns (bool);\n\n  // PRICE UPDATER\n  /**\n   * @notice Adds a new admin as PriceUpdater\n   * @param admin The address of the new PriceUpdater\n   */\n  function addPriceUpdater(address admin) external;\n\n  /**\n   * @notice Removes an admin as PriceUpdater\n   * @param admin The address of the PriceUpdater to remove\n   */\n  function removePriceUpdater(address admin) external;\n\n  /**\n   * @notice Returns true if the address is PriceUpdater, false otherwise\n   * @param admin The address to check\n   * @return True if the given address is PriceUpdater, false otherwise\n   */\n  function isPriceUpdater(address admin) external view returns (bool);\n\n  // Governance admin\n  /**\n   * @notice Adds a new admin as Govnernance admin\n   * @param admin The address of the new Governance admin\n   */\n  function addGovernanceAdmin(address admin) external;\n\n  /**\n   * @notice Removes an admin as Governance Admin\n   * @param admin The address of the Governance Admin to remove\n   */\n  function removeGovernanceAdmin(address admin) external;\n\n  /**\n   * @notice Returns true if the address is Governance Admin, false otherwise\n   * @param admin The address to check\n   * @return True if the given address is Governance Admin, false otherwise\n   */\n  function isGovernanceAdmin(address admin) external view returns (bool);\n\n  // Wrapper ADAPTER\n  /**\n   * @notice Adds a new adapter as WRAPPER_ADAPTER\n   * @param adapter The address of the new adapter\n   */\n  function addWrapperAdapter(address adapter) external;\n\n  /**\n   * @notice Removes an adapter as WRAPPER_ADAPTER\n   * @param adapter The address of the WRAPPER_ADAPTER to remove\n   */\n  function removeWrapperAdapter(address adapter) external;\n\n  /**\n   * @notice Returns true if the address is WRAPPER_ADAPTER, false otherwise\n   * @param adapter The address to check\n   * @return True if the given address is WRAPPER_ADAPTER, false otherwise\n   */\n  function isWrapperAdapter(address adapter) external view returns (bool);\n}\n"
      },
      "src/interfaces/ICore.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\ninterface ICore {\n  event Genesis();\n\n  event ProxyCreated(address indexed proxy, uint256 moduleId);\n\n  event InstallerInstallModule(\n    uint256 indexed moduleId,\n    address indexed moduleImpl,\n    bytes32 moduleVersion\n  );\n}\n"
      },
      "src/interfaces/ISafeERC721.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\ninterface ISafeERC721 {\n  function ownerOf(address collection, uint256 tokenId) external view returns (address);\n}\n"
      },
      "src/interfaces/IUTokenVault.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {DataTypes} from '../types/DataTypes.sol';\nimport {Constants} from '../libraries/helpers/Constants.sol';\n\ninterface IUTokenVault {\n  //////////////////////////////////\n  // EVENS\n\n  event MarketCreated(\n    address indexed underlyingAsset,\n    address indexed interestRate,\n    address indexed strategy,\n    address sharesToken\n  );\n\n  event MarketInterestRateUpdated(address indexed underlyingAsset, address indexed interestRate);\n\n  event ReserveDataUpdated(\n    address indexed reserve,\n    uint256 liquidityRate,\n    uint256 variableBorrowRate,\n    uint256 liquidityIndex,\n    uint256 variableBorrowIndex\n  );\n\n  event Deposit(\n    address indexed user,\n    address indexed onBehalfOf,\n    address indexed underlyingAsset,\n    uint256 amount\n  );\n  event Withdraw(\n    address indexed user,\n    address indexed to,\n    address indexed underlyingAsset,\n    uint256 amount\n  );\n\n  event Borrow(\n    address indexed iniciator,\n    address indexed onBehalfOf,\n    address indexed underlyingAsset,\n    uint256 amount,\n    bytes32 loanId,\n    uint256 borrowRate\n  );\n\n  event Repay(\n    address indexed iniciator,\n    address indexed onBehalfOf,\n    address indexed underlyingAsset,\n    uint256 amount,\n    bytes32 loanId,\n    uint256 borrowRate\n  );\n\n  event UpdateReserveState(address indexed underlyingAsset, uint256 newState);\n\n  event DisableReserveStrategy(address indexed underlyingAsset);\n\n  event UpdateReserveStrategy(address indexed underlyingAsset, address indexed newStrategy);\n  /**\n   * @dev Emitted when the pause is triggered.\n   */\n  event Paused();\n\n  /**\n   * @dev Emitted when the pause is lifted.\n   */\n  event Unpaused();\n\n  event ActiveVault(address indexed underlyingAsset, bool isActive);\n  event FrozenVault(address indexed underlyingAsset, bool isFrozen);\n  event PausedVault(address indexed underlyingAsset, bool isPaused);\n\n  event UpdateCaps(\n    address indexed underlyingAsset,\n    uint256 minCap,\n    uint256 depositCap,\n    uint256 borrowCap\n  );\n  //////////////////////////////////\n  // STRUCTS\n\n  struct CreateMarketParams {\n    address interestRateAddress;\n    address strategyAddress;\n    uint16 reserveFactor;\n    address underlyingAsset;\n    Constants.ReserveType reserveType;\n    uint8 decimals;\n    string tokenName;\n    string tokenSymbol;\n  }\n\n  //////////////////////////////////\n  // ONLY ADMIN\n\n  function createMarket(CreateMarketParams calldata params) external;\n\n  //////////////////////////////////\n  // PUBLIC\n\n  function deposit(address underlyingAsset, uint256 amount, address onBehalf) external;\n\n  function withdraw(address underlyingAsset, uint256 amount, address onBehalf) external;\n\n  //////////////////////////////////\n  // ONLY PROTOCOL\n\n  function borrow(\n    address underlyingAsset,\n    bytes32 loanId,\n    uint256 amount,\n    address to,\n    address onBehalfOf\n  ) external;\n\n  function repay(\n    address underlyingAsset,\n    bytes32 loanId,\n    uint256 amount,\n    address from,\n    address onBehalfOf\n  ) external;\n\n  function updateState(address underlyingAsset) external;\n\n  //////////////////////////////////\n  // GETTERS\n\n  function validateReserveType(\n    Constants.ReserveType currentReserveType,\n    Constants.ReserveType reserveType\n  ) external view returns (bool);\n\n  function getReserveData(\n    address underlyingAsset\n  ) external view returns (DataTypes.ReserveData memory);\n\n  function getScaledToken(address underlyingAsset) external view returns (address);\n\n  function getCaps(address underlyingAsset) external view returns (uint256, uint256, uint256);\n\n  function getFlags(address underlyingAsset) external view returns (bool, bool, bool);\n\n  function getDecimals(address underlyingAsset) external view returns (uint256);\n\n  function getReserveType(address underlyingAsset) external view returns (Constants.ReserveType);\n\n  function getScaledTotalDebtMarket(address underlyingAsset) external view returns (uint256);\n\n  function getTotalDebtFromUser(\n    address underlyingAsset,\n    address user\n  ) external view returns (uint256);\n\n  function getScaledTotalDebtFromUser(\n    address underlyingAsset,\n    address user\n  ) external view returns (uint256);\n\n  function getDebtFromLoanId(\n    address underlyingAsset,\n    bytes32 loanId\n  ) external view returns (uint256);\n\n  function getScaledDebtFromLoanId(\n    address underlyingAsset,\n    bytes32 loanId\n  ) external view returns (uint256);\n\n  function getBalances(\n    address underlyingAsset\n  ) external view returns (DataTypes.MarketBalance memory);\n\n  function getBalanceByUser(address underlyingAsset, address user) external view returns (uint256);\n\n  function getScaledBalanceByUser(\n    address underlyingAsset,\n    address user\n  ) external view returns (uint256);\n\n  function totalSupply(address underlyingAsset) external view returns (uint256);\n\n  function totalAvailableSupply(address underlyingAsset) external view returns (uint256);\n\n  function totalSupplyNotInvested(address underlyingAsset) external view returns (uint256);\n}\n"
      },
      "src/interfaces/adapter/IMarketAdapter.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {DataTypes} from '../../types/DataTypes.sol';\n\ninterface IMarketAdapter {\n  ///////////////////////////////////////////////\n  // STRUCTS\n  ///////////////////////////////////////////////\n\n  struct PreSellParams {\n    bytes32 loanId;\n    address collection;\n    uint256 tokenId;\n    address underlyingAsset;\n    uint256 marketPrice;\n    address marketApproval;\n    address protocolOwner;\n  }\n\n  struct SellParams {\n    address collection;\n    uint256 tokenId;\n    address wallet;\n    address protocolOwner;\n    address underlyingAsset;\n    uint256 marketPrice;\n    address marketApproval;\n    address to;\n    uint256 value;\n    bytes data;\n  }\n\n  struct PreBuyParams {\n    bytes32 loanId;\n    address collection;\n    uint256 tokenId;\n    address underlyingAsset;\n    uint256 marketPrice;\n    address marketApproval;\n    address protocolOwner;\n  }\n\n  struct BuyParams {\n    address wallet;\n    address underlyingAsset;\n    uint256 marketPrice;\n    address marketApproval;\n    address to;\n    uint256 value;\n    bytes data;\n  }\n\n  function preBuy(PreBuyParams memory params) external payable;\n\n  function buy(BuyParams memory params) external payable returns (uint256);\n\n  function preSell(PreSellParams memory params) external payable;\n\n  function sell(SellParams memory params) external payable;\n}\n"
      },
      "src/interfaces/modules/IBuyNowModule.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {ILoan} from './ILoan.sol';\nimport '../../types/DataTypes.sol';\n\ninterface IBuyNowModule is ILoan {\n  // EVENTS\n  event BuyNowPayLater(\n    bytes32 loanId,\n    address asset,\n    uint256 tokenId,\n    uint256 price,\n    uint256 amount\n  );\n\n  struct CalculatedDataBuyNow {\n    bytes32 loanId;\n    uint256 userAmountApproved;\n    uint256 minAmount;\n    uint256 maxAmountToBorrow;\n    uint256 realCost;\n  }\n\n  function buy(\n    uint256 amount,\n    DataTypes.SignBuyNow calldata signBuyNow,\n    DataTypes.EIP712Signature calldata sig\n  ) external;\n\n  function getCalculations(\n    DataTypes.SignBuyNow calldata signBuyNow\n  ) external view returns (uint256, uint256);\n}\n"
      },
      "src/interfaces/modules/ILoan.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport '../../types/DataTypes.sol';\n\ninterface ILoan {\n  /**\n   * @dev Emitted when a loan is created\n   * @param user The address initiating the action\n   */\n  event LoanCreated(\n    address indexed user,\n    uint256 indexed loanId,\n    uint256 totalAssets,\n    uint256 amount,\n    uint256 borrowIndex\n  );\n}\n"
      },
      "src/interfaces/oracles/IReserveOracle.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\n/**\n *\n * @title IReserveOracle interface\n * @notice Interface for getting Reserve price oracle.\n */\ninterface IReserveOracle {\n  event AggregatorAdded(address currencyKey, address aggregator);\n  event AggregatorRemoved(address currencyKey, address aggregator);\n\n  /**\n   *\n   * @dev returns the asset price in the base CURRENCY\n   */\n  function getAssetPrice(address asset) external view returns (uint256);\n}\n"
      },
      "src/interfaces/tokens/IInterestRate.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\n/**\n * @title IInterestRate interface\n * @dev Interface for the calculation of the interest rates\n * @author Unlockd\n */\ninterface IInterestRate {\n  struct CalculateInterestRatesParams {\n    uint256 liquidityAdded;\n    uint256 liquidityTaken;\n    uint256 totalVariableDebt;\n    uint256 totalSupplyAssets;\n    uint256 reserveFactor;\n  }\n\n  /**\n   * @dev Get the variable borrow rate\n   * @return the base variable borrow rate\n   *\n   */\n  function baseVariableBorrowRate() external view returns (uint256);\n\n  /**\n   * @dev Get the maximum variable borrow rate\n   * @return the maximum variable borrow rate\n   *\n   */\n  function getMaxVariableBorrowRate() external view returns (uint256);\n\n  /**\n   * @dev Calculates the interest rates depending on the reserve's state and configurations\n   * @param params params needed to calculate the interest rate\n   */\n  function calculateInterestRates(\n    CalculateInterestRatesParams memory params\n  ) external view returns (uint256, uint256);\n\n  /**\n   * @dev Calculates the interest rates depending on the reserve's state and configurations\n   * @param availableLiquidity The available liquidity for the reserve\n   * @param totalVariableDebt The total borrowed from the reserve at a variable rate\n   * @param reserveFactor The reserve portion of the interest that goes to the treasury of the market\n   *\n   */\n  function calculateInterestRates(\n    uint256 availableLiquidity,\n    uint256 totalVariableDebt,\n    uint256 reserveFactor\n  ) external view returns (uint256 currentLiquidityRate, uint256 currentVariableBorrowRate);\n}\n"
      },
      "src/libraries/base/BaseCore.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {CoreStorage} from '../storage/CoreStorage.sol';\nimport {ICore} from '../../interfaces/ICore.sol';\nimport {UnlockdMinimalProxy} from '../proxy/UnlockdMinimalProxy.sol';\nimport {Constants} from '../helpers/Constants.sol';\nimport {Errors} from '../helpers/Errors.sol';\n\n/**\n * @title BaseCore\n * @notice Base logic for the proxy\n * @author Unlockd\n * @dev fork from https://github.com/euler-xyz/euler-contracts/blob/master/contracts/Base.sol\n */\ncontract BaseCore is CoreStorage, ICore {\n  function _createProxy(uint256 proxyModuleId) internal returns (address) {\n    if (proxyModuleId == 0) {\n      revert Errors.InvalidModule();\n    }\n    if (proxyModuleId > Constants.MAX_EXTERNAL_MODULEID) {\n      revert Errors.InvalidModule();\n    }\n\n    // If we've already created a proxy for a single-proxy module, just return it:\n    if (_proxyLookup[proxyModuleId] != address(0)) return _proxyLookup[proxyModuleId];\n\n    // Otherwise create a proxy:\n    address proxyAddr = address(new UnlockdMinimalProxy());\n\n    if (proxyModuleId <= Constants.MAX_EXTERNAL_SINGLE_PROXY_MODULEID) {\n      _proxyLookup[proxyModuleId] = proxyAddr;\n    }\n\n    TrustedSenderInfo storage trustedSenderInfo = _trustedSenders[proxyAddr];\n\n    trustedSenderInfo.moduleId = uint32(proxyModuleId);\n\n    emit ProxyCreated(proxyAddr, proxyModuleId);\n\n    return proxyAddr;\n  }\n\n  function callInternalModule(\n    uint256 moduleId,\n    bytes memory input\n  ) internal returns (bytes memory) {\n    (bool success, bytes memory result) = _moduleLookup[moduleId].delegatecall(input);\n    if (!success) revertBytes(result);\n    return result;\n  }\n\n  // Modifiers\n\n  modifier reentrantOK() {\n    // documentation only\n    _;\n  }\n\n  // Used to flag functions which do not modify storage, but do perform a delegate call\n  // to a view function, which prohibits a standard view modifier. The flag is used to\n  // patch state mutability in compiled ABIs and interfaces.\n  modifier staticDelegate() {\n    _;\n  }\n\n  // WARNING: Must be very careful with this modifier. It resets the free memory pointer\n  // to the value it was when the function started. This saves gas if more memory will\n  // be allocated in the future. However, if the memory will be later referenced\n  // (for example because the function has returned a pointer to it) then you cannot\n  // use this modifier.\n\n  modifier FREEMEM() {\n    uint256 origFreeMemPtr;\n    assembly {\n      origFreeMemPtr := mload(0x40)\n    }\n    _;\n    /*  \n        assembly { // DEV_MODE: overwrite the freed memory with garbage to detect bugs\n            let garbage := 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF\n            for { let i := origFreeMemPtr } lt(i, mload(0x40)) { i := add(i, 32) } { mstore(i, garbage) }\n        }\n        */\n\n    assembly {\n      mstore(0x40, origFreeMemPtr)\n    }\n  }\n\n  // Error handling\n  function revertBytes(bytes memory errMsg) internal pure {\n    if (errMsg.length > 0) {\n      assembly {\n        revert(add(32, errMsg), mload(errMsg))\n      }\n    }\n\n    revert Errors.RevertEmptyBytes();\n  }\n}\n"
      },
      "src/libraries/base/BaseCoreModule.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {IDelegationWalletRegistry} from '@unlockd-wallet/src/interfaces/IDelegationWalletRegistry.sol';\nimport {BaseCore} from './BaseCore.sol';\nimport {Errors} from '../helpers/Errors.sol';\nimport {IACLManager} from '../../interfaces/IACLManager.sol';\nimport {Constants} from '../helpers/Constants.sol';\n\n/**\n * @title BaseCoreModule\n * @notice Base logic on each module\n * @author Unlockd\n */\ncontract BaseCoreModule is BaseCore {\n  // public accessors common to all modules\n  uint256 public immutable moduleId;\n  bytes32 public immutable moduleVersion;\n\n  constructor(uint256 moduleId_, bytes32 moduleVersion_) {\n    moduleId = moduleId_;\n    moduleVersion = moduleVersion_;\n  }\n\n  /**\n   * @dev Modifier that checks if the sender has Protocol Admin ROLE\n   */\n  modifier onlyAdmin() {\n    if (!IACLManager(_aclManager).isProtocolAdmin(unpackTrailingParamMsgSender())) {\n      revert Errors.ProtocolAccessDenied();\n    }\n    _;\n  }\n\n  /**\n   * @dev Modifier that checks if the sender has Governance ROLE\n   */\n  modifier onlyGovernance() {\n    // We can create a new role for that\n    if (!IACLManager(_aclManager).isGovernanceAdmin(unpackTrailingParamMsgSender())) {\n      revert Errors.GovernanceAccessDenied();\n    }\n    _;\n  }\n\n  /**\n   * @dev Modifier that checks if the sender has Emergency ROLE\n   */\n  modifier onlyEmergency() {\n    if (!IACLManager(_aclManager).isEmergencyAdmin(unpackTrailingParamMsgSender())) {\n      revert Errors.EmergencyAccessDenied();\n    }\n    _;\n  }\n\n  /**\n   * @dev Modifier that checks if the sender has the defined ROLE, this allow us to not need to update the BaseCoreModule with each\n   * new functionality\n   * @param role Assigned role to check with the sender\n   */\n  modifier onlyRole(bytes32 role) {\n    if (!IACLManager(_aclManager).hasRole(role, unpackTrailingParamMsgSender())) {\n      revert Errors.RoleAccessDenied();\n    }\n    _;\n  }\n\n  // Accessing parameters\n\n  /**\n   * @dev Due we are using the router we need to do this thing in order to extract the real sender, by default msg.sender is the router\n   */\n  function unpackTrailingParamMsgSender() internal pure returns (address msgSender) {\n    /// @solidity memory-safe-assembly\n    assembly {\n      msgSender := shr(96, calldataload(sub(calldatasize(), 40)))\n    }\n  }\n\n  function unpackTrailingParams() internal pure returns (address msgSender, address proxyAddr) {\n    /// @solidity memory-safe-assembly\n    assembly {\n      msgSender := shr(96, calldataload(sub(calldatasize(), 40)))\n      proxyAddr := shr(96, calldataload(sub(calldatasize(), 20)))\n    }\n  }\n\n  /**\n   *  @dev Internal function that checks if the sender is an abstract wallet created by us\n   *  the protocol only allow on wallet x address\n   */\n  function _checkHasUnlockdWallet(address msgSender) internal view {\n    if (\n      IDelegationWalletRegistry(_walletRegistry).getOwnerWalletAt(msgSender, 0).owner != msgSender\n    ) {\n      revert Errors.UnlockdWalletNotFound();\n    }\n  }\n\n  function _checkUnderlyingAsset(address underlyingAsset) internal view {}\n}\n"
      },
      "src/libraries/base/BaseSignature.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.19;\n\nimport {ECDSA} from '@solady/utils/ECDSA.sol';\nimport {EIP712} from '../utils/EIP712.sol';\n\nimport {CoreStorage, DataTypes} from '../storage/CoreStorage.sol';\nimport {Errors} from '../../libraries/helpers/Errors.sol';\n\n/**\n * @title BaseSignature\n * @notice Base logic to implement EIP712\n * @author Unlockd\n */\nabstract contract BaseSignature is EIP712, CoreStorage {\n  using ECDSA for bytes32;\n\n  modifier validateDeadline(uint256 deadline) {\n    Errors.verifyNotExpiredTimestamp(deadline, block.timestamp);\n    _;\n  }\n\n  constructor(string memory name, string memory version) EIP712(name, version) {\n    // NOTHING TO DO\n  }\n\n  /**\n   * @dev Generates the domain separator\n   */\n  function DOMAIN_SEPARATOR() external view returns (bytes32) {\n    return _domainSeparatorV4();\n  }\n\n  /**\n   * @dev Validates that the signed message is signed by the expected Address\n   * @param digest message signature\n   * @param expectedAddress expected address to check\n   * @param deadline expired time of the message\n   */\n  function _validateRecoveredAddress(\n    bytes32 digest,\n    address expectedAddress,\n    uint256 deadline,\n    DataTypes.EIP712Signature memory sig\n  ) internal view returns (bool) {\n    if (sig.deadline != deadline) {\n      revert Errors.NotEqualDeadline();\n    }\n    Errors.verifyNotExpiredTimestamp(sig.deadline, block.timestamp);\n    address recoveredAddress = _getAddressRecover(digest, sig);\n\n    if (recoveredAddress != expectedAddress || recoveredAddress == address(0)) {\n      revert Errors.InvalidRecoveredAddress();\n    }\n    return true;\n  }\n\n  /**\n   * @dev Return the address of the signature\n   * @param digest message signature\n   * @param sig struct with the signed message\n   */\n  function _getAddressRecover(\n    bytes32 digest,\n    DataTypes.EIP712Signature memory sig\n  ) internal view returns (address) {\n    return digest.recover(sig.v, sig.r, sig.s);\n  }\n\n  /**\n   * @dev Hash with typed data\n   * @param structHash struct hash\n   */\n  function _hashTypedData(bytes32 structHash) internal view returns (bytes32) {\n    return _hashTypedDataV4(structHash);\n  }\n\n  /**\n   * @dev Return the nonce\n   * @param sender user to return the nonce\n   */\n  function getNonce(address sender) external view returns (uint256) {\n    return _signNonce[sender];\n  }\n}\n"
      },
      "src/libraries/configuration/ACLManager.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {AccessControl} from '@openzeppelin/contracts/access/AccessControl.sol';\nimport {IACLManager} from '../../interfaces/IACLManager.sol';\nimport {Errors} from '../helpers/Errors.sol';\n\n/**\n * @title ACLManager\n * @notice Access Control List Manager. Main registry of system roles and permissions.\n * @author Unlockd\n */\ncontract ACLManager is AccessControl, IACLManager {\n  // @dev address of the PROTOCOL\n  address public UNLOCK_PROTOCOL;\n\n  // @dev utoken admin in charge of updating the utoken\n  bytes32 public constant override UTOKEN_ADMIN = keccak256('UTOKEN_ADMIN');\n  // @dev protocol admin in charge of updating the protocol\n  bytes32 public constant override PROTOCOL_ADMIN = keccak256('PROTOCOL_ADMIN');\n  // @dev update the prices of the oracle\n  bytes32 public constant override PRICE_UPDATER = keccak256('PRICE_UPDATER');\n  // @dev check if the loans are healty and creates the auction\n  bytes32 public constant override AUCTION_ADMIN = keccak256('AUCTION_ADMIN');\n  // @dev block the pools and the protocol in case of a emergency\n  bytes32 public constant override EMERGENCY_ADMIN = keccak256('EMERGENCY_ADMIN');\n  // @dev modify the configuration of the protocol\n  bytes32 public constant override GOVERNANCE_ADMIN = keccak256('GOVERNANCE_ADMIN');\n  // @dev modify the configuration of the protocol\n  bytes32 public constant override WRAPPER_ADAPTER = keccak256('WRAPPER_ADAPTER');\n\n  /**\n   * @dev Constructor\n   * @dev The ACL admin should be initialized at the addressesProvider beforehand\n   * @param aclAdmin address of the general admin\n   */\n  constructor(address aclAdmin) {\n    if (aclAdmin == address(0)) {\n      revert Errors.ACLAdminZeroAddress();\n    }\n    _setupRole(DEFAULT_ADMIN_ROLE, aclAdmin);\n  }\n\n  /// @inheritdoc IACLManager\n  function setRoleAdmin(bytes32 role, bytes32 adminRole) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    _setRoleAdmin(role, adminRole);\n  }\n\n  /// @inheritdoc IACLManager\n  function setProtocol(address protocol) external onlyRole(DEFAULT_ADMIN_ROLE) {\n    Errors.verifyNotZero(protocol);\n    UNLOCK_PROTOCOL = protocol;\n  }\n\n  /// @inheritdoc IACLManager\n  function isProtocol(address protocol) external view returns (bool) {\n    return UNLOCK_PROTOCOL == protocol;\n  }\n\n  /// @inheritdoc IACLManager\n  function addUTokenAdmin(address admin) external {\n    grantRole(UTOKEN_ADMIN, admin);\n  }\n\n  /// @inheritdoc IACLManager\n  function removeUTokenAdmin(address admin) external {\n    revokeRole(UTOKEN_ADMIN, admin);\n  }\n\n  /// @inheritdoc IACLManager\n  function isUTokenAdmin(address admin) external view returns (bool) {\n    return hasRole(UTOKEN_ADMIN, admin);\n  }\n\n  /// @inheritdoc IACLManager\n  function addProtocolAdmin(address borrower) external {\n    grantRole(PROTOCOL_ADMIN, borrower);\n  }\n\n  /// @inheritdoc IACLManager\n  function removeProtocolAdmin(address borrower) external {\n    revokeRole(PROTOCOL_ADMIN, borrower);\n  }\n\n  /// @inheritdoc IACLManager\n  function isAuctionAdmin(address borrower) external view returns (bool) {\n    return hasRole(PROTOCOL_ADMIN, borrower);\n  }\n\n  /// @inheritdoc IACLManager\n  function addAuctionAdmin(address borrower) external {\n    grantRole(PROTOCOL_ADMIN, borrower);\n  }\n\n  /// @inheritdoc IACLManager\n  function removeAuctionAdmin(address borrower) external {\n    revokeRole(PROTOCOL_ADMIN, borrower);\n  }\n\n  /// @inheritdoc IACLManager\n  function isProtocolAdmin(address protocol) external view returns (bool) {\n    return hasRole(PROTOCOL_ADMIN, protocol);\n  }\n\n  /// @inheritdoc IACLManager\n  function addEmergencyAdmin(address admin) external {\n    grantRole(EMERGENCY_ADMIN, admin);\n  }\n\n  /// @inheritdoc IACLManager\n  function removeEmergencyAdmin(address admin) external {\n    revokeRole(EMERGENCY_ADMIN, admin);\n  }\n\n  /// @inheritdoc IACLManager\n  function isEmergencyAdmin(address admin) external view returns (bool) {\n    return hasRole(EMERGENCY_ADMIN, admin);\n  }\n\n  /// @inheritdoc IACLManager\n  function addPriceUpdater(address admin) external {\n    grantRole(PRICE_UPDATER, admin);\n  }\n\n  /// @inheritdoc IACLManager\n  function removePriceUpdater(address admin) external {\n    revokeRole(PRICE_UPDATER, admin);\n  }\n\n  /// @inheritdoc IACLManager\n  function isPriceUpdater(address admin) external view returns (bool) {\n    return hasRole(PRICE_UPDATER, admin);\n  }\n\n  /// @inheritdoc IACLManager\n  function addGovernanceAdmin(address admin) external {\n    grantRole(GOVERNANCE_ADMIN, admin);\n  }\n\n  /// @inheritdoc IACLManager\n  function removeGovernanceAdmin(address admin) external {\n    revokeRole(GOVERNANCE_ADMIN, admin);\n  }\n\n  /// @inheritdoc IACLManager\n  function isGovernanceAdmin(address admin) external view returns (bool) {\n    return hasRole(GOVERNANCE_ADMIN, admin);\n  }\n\n  /// @inheritdoc IACLManager\n  function addWrapperAdapter(address adapter) external {\n    grantRole(WRAPPER_ADAPTER, adapter);\n  }\n\n  /// @inheritdoc IACLManager\n  function removeWrapperAdapter(address adapter) external {\n    revokeRole(WRAPPER_ADAPTER, adapter);\n  }\n\n  /// @inheritdoc IACLManager\n  function isWrapperAdapter(address adapter) external view returns (bool) {\n    return hasRole(WRAPPER_ADAPTER, adapter);\n  }\n}\n"
      },
      "src/libraries/configuration/ReserveConfiguration.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport {DataTypes, Constants} from '../../types/DataTypes.sol';\nimport {Errors} from '../helpers/Errors.sol';\n\n/**\n * @title ReserveConfiguration library\n * @author Unlockd\n * @notice Implements the bitmap logic to handle the reserve configuration\n * @dev based on Aave ReserveConfiguration https://github.com/aave/aave-v3-core/blob/master/contracts/protocol/libraries/configuration/ReserveConfiguration.sol\n */\nlibrary ReserveConfiguration {\n  // @dev each F is x4\n  uint256 internal constant RESERVE_FACTOR_MASK =            0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000; // prettier-ignore\n  uint256 internal constant BORROW_CAP_MASK     =            0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000FFFF; // prettier-ignore\n  uint256 internal constant DEPOSIT_CAP_MASK    =            0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000FFFFFFFFFFFFF; // prettier-ignore\n  uint256 internal constant MIN_CAP_MASK        =            0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000FFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore\n  uint256 internal constant DECIMALS_MASK       =            0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore\n  uint256 internal constant ACTIVE_MASK         =            0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore\n  uint256 internal constant FROZEN_MASK         =            0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore\n  uint256 internal constant PAUSED_MASK         =            0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore\n  uint256 internal constant RESERVE_TYPE_MASK   =            0xFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore\n\n  ///////////////////////////////////////\n  // BIT POSITIONS\n  /// @dev For the RESERVE_FACTOR, the start bit is 0 (up to 15), hence no bitshifting is needed\n\n  uint256 internal constant BORROW_CAP_START_BIT_POSITION     = 16; // prettier-ignore\n  uint256 internal constant DEPOSIT_CAP_START_BIT_POSITION    = 52; // prettier-ignore\n  uint256 internal constant MIN_CAP_START_BIT_POSITION        = 88; // prettier-ignore\n\n  uint256 internal constant DECIMALS_START_BIT_POSITION       = 124; // prettier-ignore\n\n  uint256 internal constant IS_ACTIVE_START_BIT_POSITION      = 132; // prettier-ignore\n  uint256 internal constant IS_FROZEN_START_BIT_POSITION      = 133; // prettier-ignore\n  uint256 internal constant IS_PAUSED_START_BIT_POSITION      = 136; // prettier-ignore\n\n  uint256 internal constant RESERVE_TYPE_START_BIT_POSITION   = 140; // prettier-ignore\n\n  ///////////////////////////////////////\n  // VALIDATIONS\n\n  uint256 internal constant MAX_VALID_DECIMALS                = 255; // prettier-ignore\n  uint256 internal constant MAX_VALID_RESERVE_FACTOR          = 65535; // prettier-ignore\n  uint256 internal constant MAX_VALID_BORROW_CAP              = 68719476735; // prettier-ignore\n  uint256 internal constant MAX_VALID_DEPOSIT_CAP             = 68719476735; // prettier-ignore\n  uint256 internal constant MAX_VALID_MIN_CAP                 = 68719476735; // prettier-ignore\n\n  /**\n   * @notice Sets reserve factor\n   * @param self The reserve configuration\n   * @param reserveFactor value reserve factor\n   */\n  function setReserveFactor(\n    DataTypes.ReserveConfigurationMap memory self,\n    uint256 reserveFactor\n  ) internal pure {\n    if (reserveFactor > MAX_VALID_RESERVE_FACTOR) revert Errors.InvalidReserveFactor();\n    self.data = (self.data & RESERVE_FACTOR_MASK) | reserveFactor;\n  }\n\n  /**\n   * @notice Gets reserve factor\n   * @param self The reserve configuration\n   * @return The borrow cap\n   */\n  function getReserveFactor(\n    DataTypes.ReserveConfigurationMap memory self\n  ) internal pure returns (uint256) {\n    return self.data & ~RESERVE_FACTOR_MASK;\n  }\n\n  /**\n   * @notice Sets the borrow cap of the reserve\n   * @param self The reserve configuration\n   * @param borrowCap The borrow cap\n   */\n  function setBorrowCap(\n    DataTypes.ReserveConfigurationMap memory self,\n    uint256 borrowCap\n  ) internal pure {\n    if (borrowCap > MAX_VALID_BORROW_CAP) revert Errors.InvalidMaxBorrowCap();\n    self.data = (self.data & BORROW_CAP_MASK) | (borrowCap << BORROW_CAP_START_BIT_POSITION);\n  }\n\n  /**\n   * @notice Gets the borrow cap of the reserve\n   * @param self The reserve configuration\n   * @return The borrow cap\n   */\n  function getBorrowCap(\n    DataTypes.ReserveConfigurationMap memory self\n  ) internal pure returns (uint256) {\n    return (self.data & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION;\n  }\n\n  /**\n   * @notice Sets the supply cap of the reserve\n   * @param self The reserve configuration\n   * @param depositCap The supply cap\n   */\n  function setDepositCap(\n    DataTypes.ReserveConfigurationMap memory self,\n    uint256 depositCap\n  ) internal pure {\n    if (depositCap > MAX_VALID_DEPOSIT_CAP) revert Errors.InvalidMaxDepositCap();\n    self.data = (self.data & DEPOSIT_CAP_MASK) | (depositCap << DEPOSIT_CAP_START_BIT_POSITION);\n  }\n\n  /**\n   * @notice Gets the supply cap of the reserve\n   * @param self The reserve configuration\n   * @return The deposit cap\n   */\n  function getDepositCap(\n    DataTypes.ReserveConfigurationMap memory self\n  ) internal pure returns (uint256) {\n    return (self.data & ~DEPOSIT_CAP_MASK) >> DEPOSIT_CAP_START_BIT_POSITION;\n  }\n\n  /**\n   * @notice Sets the min cap of the reserve\n   * @param self The reserve configuration\n   * @param minCap The supply cap\n   */\n  function setMinCap(DataTypes.ReserveConfigurationMap memory self, uint256 minCap) internal pure {\n    if (minCap > MAX_VALID_MIN_CAP) revert Errors.InvalidMaxMinCap();\n    self.data = (self.data & MIN_CAP_MASK) | (minCap << MIN_CAP_START_BIT_POSITION);\n  }\n\n  /**\n   * @notice Gets the min cap of the reserve\n   * @param self The reserve configuration\n   * @return The supply cap\n   */\n  function getMinCap(\n    DataTypes.ReserveConfigurationMap memory self\n  ) internal pure returns (uint256) {\n    return (self.data & ~MIN_CAP_MASK) >> MIN_CAP_START_BIT_POSITION;\n  }\n\n  /**\n   * @notice Sets the decimals of the underlying asset of the reserve\n   * @param self The reserve configuration\n   * @param decimals The decimals\n   */\n  function setDecimals(\n    DataTypes.ReserveConfigurationMap memory self,\n    uint256 decimals\n  ) internal pure {\n    if (decimals > MAX_VALID_DECIMALS) revert Errors.InvalidMaxDecimals();\n    self.data = (self.data & DECIMALS_MASK) | (decimals << DECIMALS_START_BIT_POSITION);\n  }\n\n  /**\n   * @notice Gets the decimals of the underlying asset of the reserve\n   * @param self The reserve configuration\n   * @return The decimals of the asset\n   */\n  function getDecimals(\n    DataTypes.ReserveConfigurationMap memory self\n  ) internal pure returns (uint256) {\n    return (self.data & ~DECIMALS_MASK) >> DECIMALS_START_BIT_POSITION;\n  }\n\n  /**\n   * @notice Sets the active state of the reserve\n   * @param self The reserve configuration\n   * @param active The active state\n   */\n  function setActive(DataTypes.ReserveConfigurationMap memory self, bool active) internal pure {\n    self.data =\n      (self.data & ACTIVE_MASK) |\n      (uint256(active ? 1 : 0) << IS_ACTIVE_START_BIT_POSITION);\n  }\n\n  /**\n   * @notice Gets the active state of the reserve\n   * @param self The reserve configuration\n   * @return The active state\n   */\n  function getActive(DataTypes.ReserveConfigurationMap memory self) internal pure returns (bool) {\n    return (self.data & ~ACTIVE_MASK) != 0;\n  }\n\n  /**\n   * @notice Sets the frozen state of the reserve\n   * @param self The reserve configuration\n   * @param frozen The frozen state\n   */\n  function setFrozen(DataTypes.ReserveConfigurationMap memory self, bool frozen) internal pure {\n    self.data =\n      (self.data & FROZEN_MASK) |\n      (uint256(frozen ? 1 : 0) << IS_FROZEN_START_BIT_POSITION);\n  }\n\n  /**\n   * @notice Gets the frozen state of the reserve\n   * @param self The reserve configuration\n   * @return The frozen state\n   */\n  function getFrozen(DataTypes.ReserveConfigurationMap memory self) internal pure returns (bool) {\n    return (self.data & ~FROZEN_MASK) != 0;\n  }\n\n  /**\n   * @notice Sets the paused state of the reserve\n   * @param self The reserve configuration\n   * @param paused The paused state\n   */\n  function setPaused(DataTypes.ReserveConfigurationMap memory self, bool paused) internal pure {\n    self.data =\n      (self.data & PAUSED_MASK) |\n      (uint256(paused ? 1 : 0) << IS_PAUSED_START_BIT_POSITION);\n  }\n\n  /**\n   * @notice Gets the paused state of the reserve\n   * @param self The reserve configuration\n   * @return The paused state\n   */\n  function getPaused(DataTypes.ReserveConfigurationMap memory self) internal pure returns (bool) {\n    return (self.data & ~PAUSED_MASK) != 0;\n  }\n\n  /**\n   * @notice Sets the reserve type of the reserve\n   * @param self The reserve configuration\n   * @param reserveType type of the reserve\n   */\n  function setReserveType(\n    DataTypes.ReserveConfigurationMap memory self,\n    Constants.ReserveType reserveType\n  ) internal pure {\n    self.data =\n      (self.data & RESERVE_TYPE_MASK) |\n      (uint(reserveType) << RESERVE_TYPE_START_BIT_POSITION);\n  }\n\n  /**\n   * @notice Gets the decimals of the underlying asset of the reserve\n   * @param self The reserve configuration\n   * @return The decimals of the asset\n   */\n  function getReserveType(\n    DataTypes.ReserveConfigurationMap memory self\n  ) internal pure returns (Constants.ReserveType) {\n    return\n      Constants.ReserveType((self.data & ~RESERVE_TYPE_MASK) >> RESERVE_TYPE_START_BIT_POSITION);\n  }\n\n  /**\n   * @notice Gets the caps parameters of the reserve from storage\n   * @param self The reserve configuration\n   * @return borrowCap The state param representing borrow cap\n   * @return depositCap The state param representing supply cap.\n   * @return MinCap The state param representing min cap.\n   */\n  function getCaps(\n    DataTypes.ReserveConfigurationMap memory self\n  ) internal pure returns (uint256, uint256, uint256) {\n    uint256 dataLocal = self.data;\n\n    return (\n      (dataLocal & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION,\n      (dataLocal & ~DEPOSIT_CAP_MASK) >> DEPOSIT_CAP_START_BIT_POSITION,\n      (dataLocal & ~MIN_CAP_MASK) >> MIN_CAP_START_BIT_POSITION\n    );\n  }\n\n  /**\n   * @notice Gets the configuration flags of the reserve\n   * @param self The reserve configuration\n   * @return The state flag representing active\n   * @return The state flag representing frozen\n   * @return The state flag representing paused\n   */\n  function getFlags(\n    DataTypes.ReserveConfigurationMap memory self\n  ) internal pure returns (bool, bool, bool) {\n    uint256 dataLocal = self.data;\n\n    return (\n      (dataLocal & ~ACTIVE_MASK) != 0,\n      (dataLocal & ~FROZEN_MASK) != 0,\n      (dataLocal & ~PAUSED_MASK) != 0\n    );\n  }\n}\n"
      },
      "src/libraries/helpers/Constants.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nlibrary Constants {\n  ////////////////////////////////////////////\n  // Reentrancy Guard for modules\n  ////////////////////////////////////////////\n  uint256 internal constant REENTRANCYLOCK__UNLOCKED = 0; // prettier-ignore\n  uint256 internal constant REENTRANCYLOCK__LOCKED   = 2; // prettier-ignore\n\n  ////////////////////////////////////////////\n  // Modules Configuration\n  ////////////////////////////////////////////\n\n  uint256 internal constant MAX_EXTERNAL_SINGLE_PROXY_MODULEID = 499_999; // prettier-ignore\n  uint256 internal constant MAX_EXTERNAL_MODULEID              = 999_999; // prettier-ignore\n\n  ////////////////////////////////////////////\n  // List Modules\n  ////////////////////////////////////////////\n\n  // Public single-proxy modules\n  uint256 internal constant MODULEID__INSTALLER  = 1; // prettier-ignore\n  uint256 internal constant MODULEID__MANAGER    = 2; // prettier-ignore\n  uint256 internal constant MODULEID__ACTION     = 3; // prettier-ignore\n  uint256 internal constant MODULEID__AUCTION    = 4; // prettier-ignore\n  uint256 internal constant MODULEID__MARKET     = 5; // prettier-ignore\n  uint256 internal constant MODULEID__BUYNOW     = 6; // prettier-ignore\n  uint256 internal constant MODULEID__SELLNOW    = 7; // prettier-ignore\n\n  ////////////////////////////////////////////\n  // RESERVE STATE\n  ////////////////////////////////////////////\n\n  enum ReserveState {\n    STOPPED, // No supply, No borrow\n    FREEZED, // No supply, No withdraw , No borrow, No repay\n    ACTIVE // All OK\n  }\n\n  ////////////////////////////////////////////\n  // LOAN STATE\n  ////////////////////////////////////////////\n\n  enum LoanState {\n    BLOCKED,\n    ACTIVE,\n    FREEZE\n  }\n\n  ////////////////////////////////////////////\n  // GRUP RESERVE TYPE\n  ////////////////////////////////////////////\n\n  enum ReserveType {\n    DISABLED, // Disabled collection\n    ALL, // All the assets with the exception SPECIAL\n    STABLE, // For the stable coins\n    COMMON, // Common coins WETH etc ...\n    SPECIAL // Only if the collection is also isolated to one asset token\n  }\n\n  ////////////////////////////////////////////\n  // ORDER TYPE\n  ////////////////////////////////////////////\n\n  enum OrderType {\n    TYPE_LIQUIDATION_AUCTION,\n    //Auction with BIDs\n    TYPE_AUCTION,\n    // Fixed price only buynow function\n    TYPE_FIXED_PRICE,\n    // Fixed price and auction with bids\n    TYPE_FIXED_PRICE_AND_AUCTION\n  }\n}\n"
      },
      "src/libraries/helpers/Errors.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\n/**\n * @title Errors library\n * @author Unlockd\n * @notice Defines the error messages emitted by the different contracts of the Unlockd protocol\n */\nlibrary Errors {\n  ///////////////////////////////////////////\n  ///   GENERIC\n  ///////////////////////////////////////////\n\n  error AccessDenied();\n  //error ZeroAddress(string paramName);\n\n  error InvalidParam(string paramName);\n  error ArrayLengthMismatch(string details);\n  error InvalidArrayLength();\n  error Paused();\n  error Frozen();\n\n  error AddressesNotEquals();\n  error NumbersNotEquals();\n\n  error ZeroAddress();\n  error ZeroBytes();\n  error ZeroNumber();\n\n  error ACLAdminZeroAddress();\n\n  error UTokenNotAllowed();\n  error AdapterNotAllowed();\n  error TimestampExpired();\n  error TimestampNotExpired();\n  error NotImplemented();\n\n  error InvalidParams();\n  error InvalidModule();\n  error InvalidCurrentLtv();\n  error InvalidTotalAmount();\n  error InvalidCurrentLiquidationThreshold();\n  error InvalidUserCollateralBalance();\n  error InvalidOrderOwner();\n  error InvalidOrderBuyer();\n  error InvalidBidAmount();\n  error InvalidLoanOwner();\n  error InvalidUnderlyingAsset();\n  error InvalidAssets();\n  error InvalidEndAmount();\n  error InvalidStartAmount();\n  error InvalidEndTime();\n  error InvalidStartTime();\n\n  error InvalidPriceFeedKey();\n  error InvalidAggregator();\n  error InvalidLastRoundData();\n\n  error NotEnoughLiquidity();\n  error DebtExceedsAmount();\n  error AmountExceedsDebt();\n  error AmountExceedsBalance();\n  error AmountToLow();\n  error CollectionNotAllowed();\n  error NotAssetOwner();\n  error UnsuccessfulExecution();\n  error AssetsMismatch();\n  error InvalidRecoveredAddress();\n  error SenderZeroAddress();\n  error OrderActive();\n\n  error WrongNonce();\n\n  error NotEqualDeadline();\n  error NotEqualUnderlyingAsset();\n  error NotEqualTotalAssets();\n  error NotEqualOrderOwner();\n  error NotEqualSender();\n\n  error ProtocolAccessDenied();\n  error GovernanceAccessDenied();\n  error EmergencyAccessDenied();\n  error RoleAccessDenied();\n  error MarketPriceNotCoverDebt();\n  error StrategyNotEmpty();\n\n  error InvalidDepositCap();\n  error InvalidBorrowCap();\n  error PoolNotActive();\n  error PoolPaused();\n  error PoolFrozen();\n\n  ///////////////////////////////////////////\n  ///   RESERVE CONFIG\n  ///////////////////////////////////////////\n\n  error InvalidReserveFactor();\n  error InvalidMaxBorrowCap();\n  error InvalidMaxDepositCap();\n  error InvalidMaxMinCap();\n  error InvalidMaxDecimals();\n  ///////////////////////////////////////////\n  ///   UTOKEN\n  ///////////////////////////////////////////\n  error UnderlyingMarketNotExist();\n  error UnderlyingMarketAlreadyExist();\n  error UTokenAccessDenied();\n  error ReserveNotActive();\n  error NotValidReserve();\n  ///////////////////////////////////////////\n  ///   ROUTER\n  ///////////////////////////////////////////\n\n  error BaseInputToShort();\n  error ReentrancyLocked();\n  error RevertEmptyBytes();\n  ///////////////////////////////////////////\n  ///   WALLET\n  ///////////////////////////////////////////\n\n  error UnlockdWalletNotFound();\n  error InvalidWalletOwner();\n  error NotEqualWallet();\n  error ProtocolOwnerZeroAddress();\n\n  ///////////////////////////////////////////\n  ///   LOAN\n  ///////////////////////////////////////////\n\n  error HealtyLoan();\n  error UnhealtyLoan();\n  error UnableToBorrowMore();\n  error LoanNotActive();\n  error LowCollateral();\n  error InvalidLoanId();\n  error LoanNotUpdated();\n  error LoanBlocked();\n  error LoanWithDebtRepayed();\n  ///////////////////////////////////////////\n  ///   ORDER\n  ///////////////////////////////////////////\n\n  error OrderNotAllowed();\n  error InvalidOrderId();\n\n  ///////////////////////////////////////////\n  ///   ASSETS\n  ///////////////////////////////////////////\n\n  error InvalidAssetAmount();\n  error InvalidAmount();\n  error AssetLocked();\n  error AssetUnlocked();\n  error LiquidityRateOverflow();\n  error LiquidityIndexOverflow();\n  error BorrorRateOverflow();\n  error BorrowIndexOverflow();\n\n  ///////////////////////////////////////////\n  ///   WRAPPERS\n  ///////////////////////////////////////////\n\n  error TransferNotSupported();\n  error ApproveNotSupported();\n  error SetApprovalForAllNotSupported();\n  error StreamERC20NotSupported();\n  error CallerNotNFTOwner();\n  error StreamCancelable();\n  error StreamNotTransferable();\n  error BurnerNotApproved();\n  error ERC721ReceiverNotSupported();\n\n  error ERC1155AmountNotValid();\n  error ERC1155BatchNotAllowed();\n  error NotWrapperAdapter();\n  error SoldForASmallerAmount();\n\n  function verifyNotZero(address addr) internal pure {\n    if (addr == address(0)) {\n      revert ZeroAddress();\n    }\n  }\n\n  function verifyNotZero(bytes32 key) internal pure {\n    if (key == bytes32(0)) {\n      revert ZeroBytes();\n    }\n  }\n\n  function verifyNotZero(uint256 num) internal pure {\n    if (num == 0) {\n      revert ZeroNumber();\n    }\n  }\n\n  function verifyAreEquals(address ad1, address ad2) internal pure {\n    if (ad1 != ad2) {\n      revert AddressesNotEquals();\n    }\n  }\n\n  function verifyAreEquals(uint256 pa1, uint256 pa2) internal pure {\n    if (pa1 != pa2) {\n      revert NumbersNotEquals();\n    }\n  }\n\n  function verifyNotExpiredTimestamp(uint256 endTimestamp, uint256 nowTimestamp) internal pure {\n    assembly {\n      // if (endTimestamp <= nowTimestamp)\n      if iszero(gt(endTimestamp, nowTimestamp)) {\n        mstore(0x00, 0x26c69d1a) // TimestampExpired() selector\n        revert(0x1c, 0x04)\n      }\n    }\n  }\n\n  function verifyExpiredTimestamp(uint256 endTimestamp, uint256 nowTimestamp) internal pure {\n    assembly {\n      // if (endTimestamp > nowTimestamp)\n      if gt(endTimestamp, nowTimestamp) {\n        mstore(0x00, 0x2499486c) // TimestampNotExpired() selector\n        revert(0x1c, 0x04)\n      }\n    }\n  }\n}\n"
      },
      "src/libraries/logic/AssetLogic.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {DataTypes} from '../../types/DataTypes.sol';\nimport {GenericLogic} from './GenericLogic.sol';\n\n/**\n * @title AssetLogic library\n * @author Unlockd\n * @notice Implements the logic to sign the asset\n */\nlibrary AssetLogic {\n  bytes32 internal constant TYPEHASH =\n    0x952d72a21d7cc0fcc1bc09ed86fbffc8c63ecf57742377a17e9461f7a2d704fd;\n\n  /**\n   * @dev return the Asset struct hashed\n   * @param nonce nonce of the struct\n   * @param signAsset struct of the asset to hash\n   *\n   */\n  function getAssetStructHash(\n    uint256 nonce,\n    DataTypes.SignAsset calldata signAsset\n  ) internal pure returns (bytes32) {\n    return\n      keccak256(\n        abi.encode(\n          TYPEHASH,\n          signAsset.assetId,\n          signAsset.collection,\n          signAsset.tokenId,\n          signAsset.price,\n          nonce,\n          signAsset.deadline\n        )\n      );\n  }\n}\n"
      },
      "src/libraries/logic/BuyNowLogic.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\n// import {IUToken, DataTypes} from '../../interfaces/tokens/IUToken.sol';\nimport {Errors} from '../../libraries/helpers/Errors.sol';\nimport {GenericLogic, DataTypes} from './GenericLogic.sol';\n\n/**\n * @title BuyNowLogic library\n * @author Unlockd\n * @notice Implements the logic to execute the buynow module\n */\nlibrary BuyNowLogic {\n  /**\n   *  @dev In charge of the calculation to buy the asset to get the max Amount needed contributed by\n   *  the user and the max amount to borrow by the protocol to buy the asset.\n   *  @param buyData struct with the information needed to buy the asset\n   */\n  function calculations(\n    DataTypes.SignBuyNow calldata buyData\n  ) internal pure returns (uint256, uint256) {\n    uint256 maxAmountToBorrow;\n    // We calculate the max amount that the user can borrow based on the min price.\n    maxAmountToBorrow = GenericLogic.calculateAvailableBorrows(\n      buyData.marketPrice > buyData.asset.price ? buyData.asset.price : buyData.marketPrice,\n      0,\n      buyData.assetLtv\n    );\n    uint256 minAmount = buyData.marketPrice - maxAmountToBorrow;\n\n    return (minAmount, maxAmountToBorrow);\n  }\n}\n"
      },
      "src/libraries/logic/GenericLogic.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {IDelegationWalletRegistry} from '@unlockd-wallet/src/interfaces/IDelegationWalletRegistry.sol';\nimport {FixedPointMathLib} from '@solady/utils/FixedPointMathLib.sol';\n\nimport {IProtocolOwner} from '@unlockd-wallet/src/interfaces/IProtocolOwner.sol';\nimport {IReserveOracle} from '../../interfaces/oracles/IReserveOracle.sol';\nimport {IUTokenVault} from '../../interfaces/IUTokenVault.sol';\n\nimport {WadRayMath} from '../math/WadRayMath.sol';\nimport {PercentageMath} from '../math/PercentageMath.sol';\n\nimport {Errors} from '../helpers/Errors.sol';\nimport {DataTypes} from '../../types/DataTypes.sol';\n\n/**\n * @title GenericLogic library\n * @author Unlockd\n * @notice Implements protocol-level logic to calculate and validate the state of a user\n */\nlibrary GenericLogic {\n  using WadRayMath for uint256;\n  using PercentageMath for uint256;\n  using FixedPointMathLib for uint256;\n  // HEALTH FACTOR 1\n  uint256 internal constant HEALTH_FACTOR_LIQUIDATION_THRESHOLD = 1 ether;\n  uint256 internal constant FIRST_BID_INCREMENT = 250; // 2.5 %\n  uint256 internal constant NEXT_BID_INCREMENT = 100; // 1 %\n\n  struct CalculateLoanDataVars {\n    uint256 reserveUnitPrice;\n    uint256 reserveUnit;\n    uint256 healthFactor;\n    uint256 totalCollateralInReserve;\n    uint256 totalDebtInReserve;\n    uint256 amount;\n  }\n\n  /**\n   * @dev Calculates the current debt of a specific loand and asset\n   * @param loanId identifier of the loan\n   * @param uTokenVault Current vault\n   * @param underlyingAsset Underlying asset of the debt\n   * @return currentDebt the amount of debt\n   *\n   */\n  function calculateLoanDebt(\n    bytes32 loanId,\n    address uTokenVault,\n    address underlyingAsset\n  ) internal view returns (uint256) {\n    if (loanId == 0) return 0;\n    // fetching variable debt\n    uint256 userTotalDebt = IUTokenVault(uTokenVault).getScaledDebtFromLoanId(\n      underlyingAsset,\n      loanId\n    );\n    return userTotalDebt;\n  }\n\n  /**\n   * @dev Calculates the health factor from the corresponding balances\n   * @param totalCollateral The total collateral\n   * @param totalDebt The total debt\n   * @param liquidationThreshold The avg liquidation threshold\n   * @return healthFactor The health factor calculated from the balances provided\n   *\n   */\n  function calculateHealthFactorFromBalances(\n    uint256 totalCollateral,\n    uint256 totalDebt,\n    uint256 liquidationThreshold\n  ) internal pure returns (uint256 healthFactor) {\n    healthFactor = totalDebt == 0\n      ? type(uint256).max\n      : (totalCollateral.percentMul(liquidationThreshold)).wadDiv(totalDebt);\n  }\n\n  /**\n   * @dev Calculates the equivalent amount that an user can borrow, depending on the available collateral and the\n   * average Loan To Value\n   * @param totalCollateral The total collateral\n   * @param totalDebt The total borrow balance\n   * @param ltv The average loan to value\n   * @return availableBorrows the amount available to borrow for the user\n   *\n   */\n  function calculateAvailableBorrows(\n    uint256 totalCollateral,\n    uint256 totalDebt,\n    uint256 ltv\n  ) internal pure returns (uint256 availableBorrows) {\n    availableBorrows = totalCollateral.percentMul(ltv);\n\n    unchecked {\n      availableBorrows = availableBorrows < totalDebt ? 0 : availableBorrows - totalDebt;\n    }\n  }\n\n  /**\n   * @dev Calculates the amount needed to arrive the LTV, in case of a healty position returns 0\n   * @param totalCollateral The total collateral\n   * @param totalDebt The total borrow balance\n   * @param ltv The average loan to value\n   * @return amountToLtv the amount needed to arrive to LTV\n   */\n  function calculateAmountToArriveToLTV(\n    uint256 totalCollateral,\n    uint256 totalDebt,\n    uint256 ltv\n  ) internal pure returns (uint256 amountToLtv) {\n    uint256 availableBorrows = totalCollateral.percentMul(ltv);\n\n    unchecked {\n      amountToLtv = availableBorrows < totalDebt ? totalDebt - availableBorrows : 0;\n    }\n  }\n\n  /**\n   * @dev Get the abstract wallet information\n   * @param walletRegistry address of the wallet registry\n   * @param owner Owner of the wallet\n   * @return address wallet\n   * @return address protocol owner\n   */\n  function getMainWallet(\n    address walletRegistry,\n    address owner\n  ) internal view returns (address, address) {\n    IDelegationWalletRegistry.Wallet memory wallet = IDelegationWalletRegistry(walletRegistry)\n      .getOwnerWalletAt(owner, 0);\n    return (wallet.wallet, wallet.protocolOwner);\n  }\n\n  /**\n   * @dev Get the wallet adderess of the abstract wallet\n   * @param walletRegistry address of the wallet registry\n   * @param owner Owner of the wallet\n   * @return walletAddress wallet\n   */\n  function getMainWalletAddress(\n    address walletRegistry,\n    address owner\n  ) internal view returns (address walletAddress) {\n    IDelegationWalletRegistry.Wallet memory wallet = IDelegationWalletRegistry(walletRegistry)\n      .getOwnerWalletAt(owner, 0);\n    walletAddress = wallet.wallet;\n  }\n\n  /**\n   * @dev Get the owner adderess of the abstract wallet\n   * @param walletRegistry address of the wallet registry\n   * @param owner Owner of the wallet\n   * @return walletOwner owner\n   */\n  function getMainWalletOwner(\n    address walletRegistry,\n    address owner\n  ) internal view returns (address walletOwner) {\n    IDelegationWalletRegistry.Wallet memory wallet = IDelegationWalletRegistry(walletRegistry)\n      .getOwnerWalletAt(owner, 0);\n    walletOwner = wallet.owner;\n  }\n\n  /**\n   * @dev Get the protocol owner adderess of the abstract wallet\n   * @param walletRegistry address of the wallet registry\n   * @param owner Owner of the wallet\n   * @return walletProtocolOwner protocol owner\n   */\n  function getMainWalletProtocolOwner(\n    address walletRegistry,\n    address owner\n  ) internal view returns (address walletProtocolOwner) {\n    IDelegationWalletRegistry.Wallet memory wallet = IDelegationWalletRegistry(walletRegistry)\n      .getOwnerWalletAt(owner, 0);\n    walletProtocolOwner = wallet.protocolOwner;\n  }\n}\n"
      },
      "src/libraries/logic/LoanLogic.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {DataTypes} from '../../types/DataTypes.sol';\nimport {GenericLogic} from './GenericLogic.sol';\nimport {Constants} from '../helpers/Constants.sol';\nimport {Errors} from '../helpers/Errors.sol';\n\n/**\n * @title LoanLogic library\n * @author Unlockd\n * @notice Implements protocol-level logic to calculate and validate the state of a user\n */\nlibrary LoanLogic {\n  event LoanCreated(address indexed user, bytes32 indexed loanId, uint256 totalAssets);\n  event FreezeLoan(bytes32 loanId);\n  event ActivateLoan(bytes32 loanId);\n  event BlockLoan(bytes32 loanId);\n\n  bytes32 internal constant TYPEHASH =\n    0x4b24ba5d0861514e3889c8dcf89590916d297469584a6cf27d0e9d3750a33970;\n\n  struct ParamsCreateLoan {\n    address msgSender;\n    address underlyingAsset;\n    bytes32 loanId;\n    uint88 totalAssets;\n  }\n\n  /**\n   * @dev generate unique loanId, because the nonce is x address and is incremental it should be unique.\n   * @param msgSender address of the user\n   * @param nonce incremental number\n   * @param deadline timestamp\n   * */\n  function generateId(\n    address msgSender,\n    uint256 nonce,\n    uint256 deadline\n  ) internal pure returns (bytes32) {\n    return keccak256(abi.encodePacked(msgSender, abi.encodePacked(nonce, deadline)));\n  }\n\n  /**\n   * @dev creates a new Loan object on the storage\n   * @param loan storage of the loan\n   * @param params Parameters to create the new loan\n   */\n  function createLoan(DataTypes.Loan storage loan, ParamsCreateLoan memory params) internal {\n    unchecked {\n      loan.loanId = params.loanId;\n      loan.owner = params.msgSender;\n      loan.underlyingAsset = params.underlyingAsset;\n      loan.totalAssets = params.totalAssets;\n\n      loan.state = Constants.LoanState.ACTIVE;\n    }\n    emit LoanCreated(params.msgSender, loan.loanId, params.totalAssets);\n  }\n\n  /**\n   * @dev Freeze loan\n   */\n  function freeze(DataTypes.Loan storage loan) internal {\n    loan.state = Constants.LoanState.FREEZE;\n    emit FreezeLoan(loan.loanId);\n  }\n\n  /**\n   * @dev Activate loan\n   */\n  function activate(DataTypes.Loan storage loan) internal {\n    loan.state = Constants.LoanState.ACTIVE;\n    emit ActivateLoan(loan.loanId);\n  }\n\n  /**\n   * @dev Block loan\n   */\n  function blocked(DataTypes.Loan storage loan) internal {\n    loan.state = Constants.LoanState.BLOCKED;\n    emit BlockLoan(loan.loanId);\n  }\n\n  /**\n   * @dev return the loan struct hashed\n   * @param nonce Nonce of the signature\n   */\n  function getLoanStructHash(\n    uint256 nonce,\n    DataTypes.SignLoanConfig calldata signLoanConfig\n  ) internal pure returns (bytes32) {\n    return\n      keccak256(\n        abi.encode(\n          TYPEHASH,\n          signLoanConfig.loanId,\n          signLoanConfig.aggLoanPrice,\n          signLoanConfig.aggLtv,\n          signLoanConfig.aggLiquidationThreshold,\n          signLoanConfig.totalAssets,\n          nonce,\n          signLoanConfig.deadline\n        )\n      );\n  }\n}\n"
      },
      "src/libraries/logic/OrderLogic.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport {DataTypes} from '../../types/DataTypes.sol';\nimport {IUTokenVault} from '../../interfaces/IUTokenVault.sol';\nimport {GenericLogic, Errors} from './GenericLogic.sol';\nimport {PercentageMath} from '../math/PercentageMath.sol';\nimport {Constants} from '../helpers/Constants.sol';\nimport {MathUtils} from '../math/MathUtils.sol';\n\nlibrary OrderLogic {\n  using SafeERC20 for IERC20;\n  using PercentageMath for uint256;\n\n  event OrderCreated(\n    address indexed owner,\n    bytes32 indexed orderId,\n    bytes32 indexed loanId,\n    Constants.OrderType orderType\n  );\n\n  struct ParamsCreateOrder {\n    Constants.OrderType orderType;\n    address owner;\n    bytes32 orderId;\n    bytes32 loanId;\n    bytes32 assetId;\n    uint128 startAmount;\n    uint128 endAmount;\n    uint128 debtToSell;\n    uint40 startTime;\n    uint40 endTime;\n  }\n\n  /**\n   * @dev generate unique loanId, because the nonce is x address and is incremental it should be unique.\n   * */\n  function generateId(bytes32 assetId, bytes32 loanId) internal pure returns (bytes32) {\n    return keccak256(abi.encodePacked(loanId, assetId));\n  }\n\n  /**\n   * @dev creates a new order\n   * @param order storage of the order\n   * @param params struct with params\n   *  struct ParamsCreateOrder {\n   *    Constants.OrderType orderType;\n   *    address owner;\n   *    bytes32 orderId;\n   *    bytes32 loanId;\n   *    bytes32 assetId;\n   *    uint128 startAmount;\n   *    uint128 endAmount;\n   *    uint128 debtToSell;\n   *    uint40 startTime;\n   *    uint40 endTime;\n   *  }\n   */\n  function createOrder(DataTypes.Order storage order, ParamsCreateOrder memory params) internal {\n    unchecked {\n      order.orderId = params.orderId;\n      order.owner = params.owner;\n      order.orderType = params.orderType;\n      order.offer = DataTypes.OfferItem({\n        loanId: params.loanId,\n        assetId: params.assetId,\n        startAmount: params.startAmount,\n        endAmount: params.endAmount,\n        // debToSell is the % of the final bid or payed that is going to repay debt.\n        debtToSell: params.debtToSell\n      });\n\n      order.timeframe = DataTypes.Timeframe({startTime: params.startTime, endTime: params.endTime});\n    }\n    emit OrderCreated(params.owner, params.orderId, params.loanId, params.orderType);\n  }\n\n  struct ParamsUpdateOrder {\n    bytes32 loanId;\n    bytes32 assetId;\n    uint128 minBid;\n    uint40 endTime;\n  }\n\n  /**\n   * @dev Change the order type to LIQUIDATION_AUCTION\n   * @param order order previously created\n   * @param params data needed to migrate from one order type to other\n   *  struct ParamsUpdateOrder {\n   *     bytes32 loanId;\n   *     bytes32 assetId;\n   *     uint128 minBid;\n   *     uint40 endTime;\n   *  }\n   */\n  function updateToLiquidationOrder(\n    DataTypes.Order storage order,\n    ParamsUpdateOrder memory params\n  ) internal {\n    // Check if the Loan is Unhealty\n    order.orderType = Constants.OrderType.TYPE_LIQUIDATION_AUCTION;\n    // Overwrite offer\n    order.offer = DataTypes.OfferItem({\n      loanId: params.loanId,\n      assetId: params.assetId,\n      startAmount: params.minBid,\n      endAmount: 0,\n      // debToSell is the % of the final bid or payed that is going to repay debt.\n      debtToSell: 1e4\n    });\n\n    order.timeframe = DataTypes.Timeframe({startTime: 0, endTime: params.endTime});\n  }\n\n  struct BorrowByBidderParams {\n    bytes32 loanId;\n    address owner;\n    address to;\n    address underlyingAsset;\n    address uTokenVault;\n    uint256 amountOfDebt;\n    uint256 assetPrice;\n    uint256 assetLtv;\n  }\n\n  /**\n   * @dev Borrow function from bidder\n   * @param params data needed to migrate from one order type to other\n   *  struct BorrowByBidderParams {\n   *    bytes32 loanId;\n   *    address owner;\n   *    address to;\n   *    address underlyingAsset;\n   *    address uTokenVault;\n   *    uint256 amountOfDebt;\n   *    uint256 assetPrice;\n   *    uint256 assetLtv;\n   *  }\n   *\n   */\n  function borrowByBidder(BorrowByBidderParams memory params) internal {\n    if (params.loanId == 0) revert Errors.InvalidLoanId();\n    uint256 maxAmountToBorrow = GenericLogic.calculateAvailableBorrows(\n      params.assetPrice,\n      0,\n      params.assetLtv\n    );\n    if (params.amountOfDebt >= maxAmountToBorrow) {\n      revert Errors.AmountExceedsDebt();\n    }\n    // Borrow on the factory\n    IUTokenVault(params.uTokenVault).borrow(\n      params.underlyingAsset,\n      params.loanId,\n      params.amountOfDebt,\n      params.to,\n      params.owner\n    );\n  }\n\n  struct RepayDebtParams {\n    address owner;\n    address from;\n    address underlyingAsset;\n    address uTokenVault;\n    bytes32 loanId;\n    uint256 amount;\n  }\n\n  /**\n   * @dev Repay specified debt\n   * @param params data needed to migrate from one order type to other\n   *  struct RepayDebtParams {\n   *    address owner;\n   *    address from;\n   *    address underlyingAsset;\n   *    address uTokenVault;\n   *    bytes32 loanId;\n   *    uint256 amount;\n   *  }\n   *\n   */\n  function repayDebt(RepayDebtParams memory params) internal {\n    // Check if there is a loan asociated\n    // We repay the total debt\n    IERC20(params.underlyingAsset).approve(params.uTokenVault, params.amount);\n    // Repay the debt\n    IUTokenVault(params.uTokenVault).repay(\n      params.underlyingAsset,\n      params.loanId,\n      params.amount,\n      params.from,\n      params.owner\n    );\n  }\n\n  struct RefundBidderParams {\n    bytes32 loanId;\n    address owner;\n    address from;\n    address underlyingAsset;\n    address uTokenVault;\n    address reserveOracle;\n    uint256 amountToPay;\n    uint256 amountOfDebt;\n    DataTypes.ReserveData reserve;\n  }\n\n  /**\n   * @dev Refund bidder amount\n   * @param params data needed to migrate from one order type to other\n   *  struct RefundBidderParams {\n   *    bytes32 loanId;\n   *    address owner;\n   *    address from;\n   *    address underlyingAsset;\n   *    address uTokenVault;\n   *    address reserveOracle;\n   *    uint256 amountToPay;\n   *    uint256 amountOfDebt;\n   *    DataTypes.ReserveData reserve;\n   *  }\n   */\n  function refundBidder(RefundBidderParams memory params) internal {\n    uint256 totalAmount = params.amountToPay + params.amountOfDebt;\n    // Check if there is a loan asociated\n\n    if (params.amountOfDebt > 0 && params.loanId != 0) {\n      uint256 currentDebt = GenericLogic.calculateLoanDebt(\n        params.loanId,\n        params.uTokenVault,\n        params.reserve.underlyingAsset\n      );\n      // Check if this loan has currentDebt\n      if (currentDebt > 0) {\n        /**\n          WARNING : If the debt exceeds the total bid amount, we attempt to repay as much as possible. \n          However, in the rare instance where the utilization rate is exceptionally high and borrowing \n          is significantly increased, the debt could surpass the full amount.\n\n          That's why we calculate the total amount of debt that the user is capable of repaying. \n        **/\n        uint256 supportedDebt = MathUtils.minOf(currentDebt, totalAmount);\n        // We remove the current debt\n        totalAmount = totalAmount - supportedDebt;\n\n        repayDebt(\n          RepayDebtParams({\n            loanId: params.loanId,\n            owner: params.owner,\n            from: params.from,\n            amount: supportedDebt,\n            underlyingAsset: params.underlyingAsset,\n            uTokenVault: params.uTokenVault\n          })\n        );\n      }\n    }\n\n    if (totalAmount > 0) {\n      // Return the amount to the first bidder\n      IERC20(params.underlyingAsset).safeTransfer(\n        params.owner,\n        // We return the amount payed minus the interest of the debt\n        totalAmount\n      );\n    }\n  }\n\n  /**\n   * @dev Get the bigger amount between the amount needed to be healty or the amount provided\n   * @param loanId Id from the loan\n   * @param uTokenVault vault address\n   * @param defaultAmount default amount to compare with the debt\n   * @param totalCollateral total amount of collateral of the Loan provided\n   * @param ltv ltv of the asset\n   * @param reserveData reserve data\n   * @return amount Max amount calculated\n   */\n  function getMaxDebtOrDefault(\n    bytes32 loanId,\n    address uTokenVault,\n    uint256 defaultAmount,\n    uint256 totalCollateral,\n    uint256 ltv,\n    DataTypes.ReserveData memory reserveData\n  ) internal view returns (uint256) {\n    uint256 totalDebt = GenericLogic.calculateLoanDebt(\n      loanId,\n      uTokenVault,\n      reserveData.underlyingAsset\n    );\n    if (totalDebt == 0) return defaultAmount;\n    uint256 minAmountNeeded = GenericLogic.calculateAmountToArriveToLTV(\n      totalCollateral,\n      totalDebt,\n      ltv\n    );\n\n    return MathUtils.maxOf(minAmountNeeded, defaultAmount);\n  }\n\n  /**\n   * @dev Get the lower amount between the amount needed to be healty or the amount provided\n   * @param loanId Id from the loan\n   * @param uTokenVault vault address\n   * @param defaultAmount default amount to compare with the debt\n   * @param totalCollateral total amount of collateral of the Loan provided\n   * @param ltv ltv of the asset\n   * @param reserveData reserve data\n   * @return amount lower amount calculated\n   */\n  function getMinDebtOrDefault(\n    bytes32 loanId,\n    address uTokenVault,\n    uint256 defaultAmount,\n    uint256 totalCollateral,\n    uint256 ltv,\n    DataTypes.ReserveData memory reserveData\n  ) internal view returns (uint256) {\n    uint256 totalDebt = GenericLogic.calculateLoanDebt(\n      loanId,\n      uTokenVault,\n      reserveData.underlyingAsset\n    );\n    if (totalDebt < defaultAmount) return totalDebt;\n\n    uint256 minAmountNeeded = GenericLogic.calculateAmountToArriveToLTV(\n      totalCollateral,\n      totalDebt,\n      ltv\n    );\n    return MathUtils.minOf(minAmountNeeded, defaultAmount);\n  }\n\n  /**\n   * @dev Calculate the minimum bid based on the amount of debt to be healty or the startAmount\n   * 0 bids then debt or startAmoun\n   * 1 > bids then debt or lastBid + 1%\n   * @param order current order\n   * @param uTokenVault address of the vault\n   * @param totalCollateral total collateral of the loan\n   * @param ltv ltv of the loan\n   * @return amount Calculation of the min bid\n   * */\n  function getMinBid(\n    DataTypes.Order memory order,\n    address uTokenVault,\n    uint256 totalCollateral,\n    uint256 ltv,\n    DataTypes.ReserveData memory reserveData\n  ) internal view returns (uint256) {\n    if (order.countBids == 0) {\n      return\n        getMaxDebtOrDefault(\n          order.offer.loanId,\n          uTokenVault,\n          order.offer.startAmount,\n          totalCollateral,\n          ltv,\n          reserveData\n        );\n    }\n    uint256 lastBid = order.bid.amountOfDebt + order.bid.amountToPay;\n\n    return\n      getMaxDebtOrDefault(\n        order.offer.loanId,\n        uTokenVault,\n        calculateMinBid(lastBid, order.countBids),\n        totalCollateral,\n        ltv,\n        reserveData\n      );\n  }\n\n  function calculateMinBid(\n    uint256 lastBid,\n    uint256 countBids\n  ) internal pure returns (uint256 minBid) {\n    minBid = countBids == 1\n      ? lastBid + lastBid.percentMul(GenericLogic.FIRST_BID_INCREMENT) // At least 2.5% more than the last bid\n      : lastBid + lastBid.percentMul(GenericLogic.NEXT_BID_INCREMENT); // At least %1 more than the last bid\n  }\n\n  struct RepayDebtToSellParams {\n    address reserveOracle;\n    address underlyingAsset;\n    address uTokenVault;\n    address from;\n    uint256 totalAmount;\n    uint256 aggLoanPrice;\n    uint256 aggLtv;\n  }\n\n  function repayDebtToSell(\n    DataTypes.Order memory order,\n    RepayDebtToSellParams memory params,\n    DataTypes.ReserveData memory reserveData\n  ) internal returns (uint256 totalAmount) {\n    uint256 totalDebt = GenericLogic.calculateLoanDebt(\n      order.offer.loanId,\n      params.uTokenVault,\n      reserveData.underlyingAsset\n    );\n    totalAmount = params.totalAmount;\n\n    if (totalDebt > 0 && order.offer.debtToSell > 0) {\n      uint256 minAmountNeeded = GenericLogic.calculateAmountToArriveToLTV(\n        params.aggLoanPrice,\n        totalDebt,\n        params.aggLtv\n      );\n      // We need to choose between the debt or the % selected by the user to repay.\n      uint256 amounToRepay = MathUtils.maxOf(\n        totalDebt.percentMul(order.offer.debtToSell),\n        minAmountNeeded\n      );\n      if (amounToRepay > 0) {\n        if (amounToRepay > totalAmount) {\n          revert Errors.DebtExceedsAmount();\n        }\n        // Repay the debt\n        repayDebt(\n          RepayDebtParams({\n            loanId: order.offer.loanId,\n            owner: order.owner,\n            from: params.from,\n            amount: amounToRepay,\n            underlyingAsset: params.underlyingAsset,\n            uTokenVault: params.uTokenVault\n          })\n        );\n        // // We remove from the total amount the debt repayed\n        totalAmount = totalAmount - amounToRepay;\n      }\n    }\n  }\n}\n"
      },
      "src/libraries/logic/ValidationLogic.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {SafeERC20} from '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport {IDelegationWalletRegistry} from '@unlockd-wallet/src/interfaces/IDelegationWalletRegistry.sol';\nimport {IProtocolOwner} from '@unlockd-wallet/src/interfaces/IProtocolOwner.sol';\nimport {AssetLogic} from '@unlockd-wallet/src/libs/logic/AssetLogic.sol';\nimport {IAllowedControllers} from '@unlockd-wallet/src/interfaces/IAllowedControllers.sol';\nimport {Constants} from '../helpers/Constants.sol';\nimport {WadRayMath} from '../math/WadRayMath.sol';\nimport {PercentageMath} from '../math/PercentageMath.sol';\nimport {ReserveConfiguration} from '../configuration/ReserveConfiguration.sol';\nimport {GenericLogic} from './GenericLogic.sol';\nimport {OrderLogic} from './OrderLogic.sol';\n\nimport {Errors} from '../helpers/Errors.sol';\nimport {DataTypes} from '../../types/DataTypes.sol';\n\nimport {IInterestRate} from '../../interfaces/tokens/IInterestRate.sol';\n\n/**\n * @title ValidationLogic library\n * @author Unlockd\n * @notice Implements functions to validate the different actions of the protocol\n */\nlibrary ValidationLogic {\n  using WadRayMath for uint256;\n  using PercentageMath for uint256;\n  using ReserveConfiguration for DataTypes.ReserveConfigurationMap;\n\n  struct ValidateLoanStateParams {\n    uint256 amount;\n    uint256 price;\n    address reserveOracle;\n    address uTokenVault;\n    DataTypes.ReserveData reserve;\n    DataTypes.SignLoanConfig loanConfig;\n  }\n\n  function validateFutureLoanState(ValidateLoanStateParams memory params) internal view {\n    // We always need to define the LTV and the Liquidation threshold\n    if (params.loanConfig.aggLtv == 0 || params.loanConfig.aggLtv > 9999) {\n      revert Errors.InvalidCurrentLtv();\n    }\n    if (\n      params.loanConfig.aggLiquidationThreshold == 0 ||\n      params.loanConfig.aggLiquidationThreshold > 9999 ||\n      params.loanConfig.aggLtv > params.loanConfig.aggLiquidationThreshold\n    ) {\n      revert Errors.InvalidCurrentLiquidationThreshold();\n    }\n    uint256 currentDebt = GenericLogic.calculateLoanDebt(\n      params.loanConfig.loanId,\n      params.uTokenVault,\n      params.reserve.underlyingAsset\n    );\n\n    uint256 updatedDebt = currentDebt < params.amount ? 0 : currentDebt - params.amount;\n\n    // We calculate the current debt and the HF\n    uint256 healthFactor = GenericLogic.calculateHealthFactorFromBalances(\n      params.loanConfig.totalAssets == 0 ? params.price : params.loanConfig.aggLoanPrice,\n      updatedDebt,\n      params.loanConfig.aggLiquidationThreshold\n    );\n\n    if (healthFactor <= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD) {\n      revert Errors.UnhealtyLoan();\n    }\n\n    if (params.loanConfig.totalAssets == 0 && updatedDebt > 0) {\n      revert Errors.UnhealtyLoan();\n    }\n  }\n\n  function validateFutureUnhealtyLoanState(ValidateLoanStateParams memory params) internal view {\n    // We always need to define the LTV and the Liquidation threshold\n    if (params.loanConfig.aggLtv == 0 || params.loanConfig.aggLtv > 9999) {\n      revert Errors.InvalidCurrentLtv();\n    }\n    if (\n      params.loanConfig.aggLiquidationThreshold == 0 ||\n      params.loanConfig.aggLiquidationThreshold > 9999 ||\n      params.loanConfig.aggLtv > params.loanConfig.aggLiquidationThreshold\n    ) {\n      revert Errors.InvalidCurrentLiquidationThreshold();\n    }\n\n    uint256 currentDebt = GenericLogic.calculateLoanDebt(\n      params.loanConfig.loanId,\n      params.uTokenVault,\n      params.reserve.underlyingAsset\n    );\n\n    uint256 updatedDebt = currentDebt < params.amount ? 0 : currentDebt - params.amount;\n\n    uint256 healthFactor = GenericLogic.calculateHealthFactorFromBalances(\n      params.loanConfig.totalAssets == 0 ? params.price : params.loanConfig.aggLoanPrice,\n      updatedDebt,\n      params.loanConfig.aggLiquidationThreshold\n    );\n\n    if (healthFactor > GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD) {\n      revert Errors.HealtyLoan();\n    }\n\n    if (params.loanConfig.totalAssets == 0 && updatedDebt == 0) {\n      revert Errors.HealtyLoan();\n    }\n  }\n\n  function validateRepay(\n    bytes32 loanId,\n    address uTokenVault,\n    uint256 amount,\n    DataTypes.ReserveData memory reserve\n  ) internal view {\n    // Check allowance to perform the payment to the UToken\n    uint256 loanDebt = GenericLogic.calculateLoanDebt(loanId, uTokenVault, reserve.underlyingAsset);\n\n    if (amount > loanDebt) {\n      revert Errors.AmountExceedsDebt();\n    }\n  }\n\n  ///////////////////////////////////////////////////////\n  // Validation Market Orders\n  ///////////////////////////////////////////////////////\n\n  function validateOrderBid(\n    Constants.OrderType orderType,\n    uint40 orderTimeframeEndtime,\n    uint256 totalAssets,\n    uint88 loanTotalAssets,\n    Constants.LoanState loanState\n  ) internal view {\n    if (\n      orderType == Constants.OrderType.TYPE_FIXED_PRICE ||\n      orderType == Constants.OrderType.TYPE_LIQUIDATION_AUCTION\n    ) {\n      revert Errors.OrderNotAllowed();\n    }\n    if (loanState == Constants.LoanState.BLOCKED) {\n      revert Errors.LoanBlocked();\n    }\n    // Check if the starting time is not in the past\n    Errors.verifyNotExpiredTimestamp(orderTimeframeEndtime, block.timestamp);\n\n    // Check if it is a biddable order\n    if (loanTotalAssets != totalAssets + 1) revert Errors.LoanNotUpdated();\n  }\n\n  function validateBuyNow(\n    uint256 totalAssets,\n    DataTypes.Order memory order,\n    uint88 loanTotalAssets,\n    Constants.LoanState loanState\n  ) internal view {\n    if (\n      order.orderType == Constants.OrderType.TYPE_AUCTION ||\n      order.orderType == Constants.OrderType.TYPE_LIQUIDATION_AUCTION\n    ) {\n      revert Errors.OrderNotAllowed();\n    }\n    if (loanTotalAssets != totalAssets + 1) revert Errors.LoanNotUpdated();\n    if (order.owner == address(0)) revert Errors.InvalidOrderOwner();\n    if (loanState == Constants.LoanState.BLOCKED) {\n      revert Errors.LoanBlocked();\n    }\n    if (order.orderType == Constants.OrderType.TYPE_FIXED_PRICE_AND_AUCTION) {\n      // Check time only for typefixed price\n      Errors.verifyNotExpiredTimestamp(order.timeframe.endTime, block.timestamp);\n    }\n  }\n\n  function validateOrderClaim(\n    uint256 totalAssets,\n    DataTypes.Order memory order,\n    uint88 loanTotalAssets,\n    Constants.LoanState loanState\n  ) internal view {\n    if (\n      order.orderType == Constants.OrderType.TYPE_FIXED_PRICE ||\n      order.orderType == Constants.OrderType.TYPE_LIQUIDATION_AUCTION\n    ) {\n      revert Errors.OrderNotAllowed();\n    }\n    if (order.owner == address(0)) revert Errors.InvalidOrderOwner();\n    if (order.bid.buyer == address(0)) revert Errors.InvalidOrderBuyer();\n\n    // Check if is auction over\n    Errors.verifyExpiredTimestamp(order.timeframe.endTime, block.timestamp);\n    if (loanState == Constants.LoanState.BLOCKED) {\n      revert Errors.LoanBlocked();\n    }\n    if (loanTotalAssets != totalAssets + 1) revert Errors.LoanNotUpdated();\n  }\n\n  struct ValidateCreateOrderMarketParams {\n    Constants.OrderType orderType;\n    Constants.LoanState loanState;\n    uint256 endAmount;\n    uint256 startAmount;\n    uint256 endTime;\n    uint256 startTime;\n    uint256 debtToSell;\n    uint256 currentTimestamp;\n  }\n\n  function validateCreateOrderMarket(ValidateCreateOrderMarketParams memory params) internal pure {\n    if (params.loanState != Constants.LoanState.ACTIVE) {\n      revert Errors.LoanNotActive();\n    }\n    // Check order not liquidation\n    if (params.orderType == Constants.OrderType.TYPE_LIQUIDATION_AUCTION) {\n      revert Errors.OrderNotAllowed();\n    }\n    if (\n      params.orderType == Constants.OrderType.TYPE_FIXED_PRICE ||\n      params.orderType == Constants.OrderType.TYPE_FIXED_PRICE_AND_AUCTION\n    ) {\n      if (params.endAmount == 0) {\n        revert Errors.InvalidEndAmount();\n      }\n      if (params.startAmount == 0) {\n        revert Errors.InvalidStartAmount();\n      }\n      if (params.startAmount > params.endAmount) {\n        revert Errors.InvalidParams();\n      }\n    }\n\n    if (\n      params.orderType == Constants.OrderType.TYPE_AUCTION ||\n      params.orderType == Constants.OrderType.TYPE_FIXED_PRICE_AND_AUCTION\n    ) {\n      if (params.startTime == 0) {\n        revert Errors.InvalidEndTime();\n      }\n      if (params.endTime == 0) {\n        revert Errors.InvalidStartTime();\n      }\n      if (params.startTime > params.endTime || params.currentTimestamp > params.endTime) {\n        revert Errors.InvalidParams();\n      }\n    }\n\n    // Validate value percentage\n    if (params.debtToSell > PercentageMath.ONE_HUNDRED_PERCENT) {\n      revert Errors.InvalidParams();\n    }\n  }\n\n  function validateCancelOrderMarket(\n    address msgSender,\n    Constants.LoanState loanState,\n    address orderOwner,\n    Constants.OrderType orderType,\n    uint40 orderTimeframeEndTime,\n    DataTypes.Bid memory bidData\n  ) internal view {\n    // Only ORDER OWNER\n    if (msgSender != orderOwner) {\n      revert Errors.NotEqualOrderOwner();\n    }\n\n    if (loanState == Constants.LoanState.BLOCKED) {\n      revert Errors.LoanBlocked();\n    }\n\n    if (\n      orderType == Constants.OrderType.TYPE_FIXED_PRICE_AND_AUCTION ||\n      orderType == Constants.OrderType.TYPE_AUCTION\n    ) {\n      // If it's expired and has buyer\n      if (orderTimeframeEndTime < block.timestamp && bidData.buyer != address(0)) {\n        revert Errors.TimestampExpired();\n      }\n    }\n  }\n\n  ///////////////////////////////////////////////////////\n  // Validation Liquidation Order\n  ///////////////////////////////////////////////////////\n\n  function validateBid(\n    uint256 totalAmount,\n    uint256 totalAssets,\n    uint256 minBid,\n    DataTypes.Order memory order,\n    DataTypes.Loan memory loan\n  ) internal view {\n    if (loan.totalAssets != totalAssets + 1) revert Errors.LoanNotUpdated();\n    if (order.orderType != Constants.OrderType.TYPE_LIQUIDATION_AUCTION)\n      revert Errors.OrderNotAllowed();\n\n    Errors.verifyNotExpiredTimestamp(order.timeframe.endTime, block.timestamp);\n    if (totalAmount == 0) revert Errors.InvalidTotalAmount();\n    if (totalAmount < minBid) revert Errors.InvalidBidAmount();\n  }\n\n  ///////////////////////////////////////////////////////\n  // Validation Vault\n  ///////////////////////////////////////////////////////\n\n  function validateVaultDeposit(\n    DataTypes.ReserveData storage reserve,\n    uint256 amount\n  ) internal view {\n    if (reserve.lastUpdateTimestamp == 0) {\n      revert Errors.UnderlyingMarketNotExist();\n    }\n\n    (, uint256 depositCap, uint256 minCap) = reserve.config.getCaps();\n\n    if (depositCap != 0) {\n      uint256 decimals = reserve.config.getDecimals();\n      uint256 depositCap_ = depositCap + 10 ** decimals;\n\n      if (amount <= minCap || amount > depositCap_) {\n        revert Errors.InvalidDepositCap();\n      }\n    }\n\n    (bool isActive, bool isFrozen, ) = reserve.config.getFlags();\n\n    if (!isActive) revert Errors.PoolNotActive();\n    if (isFrozen) revert Errors.PoolFrozen();\n  }\n\n  function validateVaultWithdraw(DataTypes.ReserveData memory reserve) internal pure {\n    if (reserve.lastUpdateTimestamp == 0) {\n      revert Errors.UnderlyingMarketNotExist();\n    }\n\n    (bool isActive, , bool isPaused) = reserve.config.getFlags();\n\n    if (!isActive) revert Errors.PoolNotActive();\n    if (isPaused) revert Errors.PoolPaused();\n  }\n\n  function validateVaultRepay(DataTypes.ReserveData memory reserve) internal pure {\n    if (reserve.lastUpdateTimestamp == 0) {\n      revert Errors.UnderlyingMarketNotExist();\n    }\n\n    (bool isActive, , bool isPaused) = reserve.config.getFlags();\n\n    if (!isActive) revert Errors.PoolNotActive();\n    if (isPaused) revert Errors.PoolPaused();\n  }\n\n  function validateVaultBorrow(DataTypes.ReserveData memory reserve, uint256 amount) internal pure {\n    if (reserve.lastUpdateTimestamp == 0) {\n      revert Errors.UnderlyingMarketNotExist();\n    }\n\n    (uint256 borrowCap, , uint256 minCap) = reserve.config.getCaps();\n\n    if (borrowCap != 0) {\n      uint256 decimals = reserve.config.getDecimals();\n      uint256 borrowCap_ = borrowCap * 10 ** decimals;\n\n      if (amount <= minCap || amount > borrowCap_) {\n        revert Errors.InvalidBorrowCap();\n      }\n    }\n\n    (bool isActive, , bool isPaused) = reserve.config.getFlags();\n\n    if (!isActive) revert Errors.PoolNotActive();\n    if (isPaused) revert Errors.PoolPaused();\n  }\n}\n"
      },
      "src/libraries/math/MathUtils.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\nimport {FixedPointMathLib} from '@solady/utils/FixedPointMathLib.sol';\nimport {WadRayMath} from './WadRayMath.sol';\n\n/**\n * @title MathUtils library\n * @author Unlockd\n * @notice Provides functions to perform linear and compounded interest calculations\n * @dev fork from https://github.com/aave/aave-v3-core/blob/master/contracts/protocol/libraries/math/MathUtils.sol\n */\nlibrary MathUtils {\n  using WadRayMath for uint256;\n\n  /// @dev Ignoring leap years\n  uint256 internal constant SECONDS_PER_YEAR = 365 days;\n\n  /**\n   * @dev Function to calculate the interest accumulated using a linear interest rate formula\n   * @param rate The interest rate, in ray\n   * @param lastUpdateTimestamp The timestamp of the last update of the interest\n   * @return interest The interest rate linearly accumulated during the timeDelta, in ray\n   *\n   */\n\n  function calculateLinearInterest(\n    uint256 rate,\n    uint40 lastUpdateTimestamp\n  ) internal view returns (uint256) {\n    //solium-disable-next-line\n    uint256 result = rate * (block.timestamp - uint256(lastUpdateTimestamp));\n    unchecked {\n      result = result / SECONDS_PER_YEAR;\n    }\n\n    return WadRayMath.RAY + result;\n  }\n\n  /**\n   * @dev Function to calculate the interest using a compounded interest rate formula\n   * To avoid expensive exponentiation, the calculation is performed using a binomial approximation:\n   *\n   *  (1+x)^n = 1+n*x+[n/2*(n-1)]*x^2+[n/6*(n-1)*(n-2)*x^3...\n   *\n   * The approximation slightly underpays liquidity providers and undercharges borrowers, with the advantage of great gas cost reductions\n   * The whitepaper contains reference to the approximation and a table showing the margin of error per different time periods\n   *\n   * @param rate The interest rate, in ray\n   * @param lastUpdateTimestamp The timestamp of the last update of the interest\n   * @return compoundedInterest The interest rate compounded during the timeDelta, in ray\n   *\n   */\n  function calculateCompoundedInterest(\n    uint256 rate,\n    uint40 lastUpdateTimestamp,\n    uint256 currentTimestamp\n  ) internal pure returns (uint256) {\n    //solium-disable-next-line\n    uint256 exp = currentTimestamp - uint256(lastUpdateTimestamp);\n\n    if (exp == 0) {\n      return WadRayMath.RAY;\n    }\n\n    uint256 expMinusOne;\n    uint256 expMinusTwo;\n    uint256 basePowerTwo;\n    uint256 basePowerThree;\n    unchecked {\n      expMinusOne = exp - 1;\n\n      expMinusTwo = exp > 2 ? exp - 2 : 0;\n\n      basePowerTwo = rate.rayMul(rate) / (SECONDS_PER_YEAR * SECONDS_PER_YEAR);\n      basePowerThree = basePowerTwo.rayMul(rate) / SECONDS_PER_YEAR;\n    }\n\n    uint256 secondTerm = exp * expMinusOne * basePowerTwo;\n    unchecked {\n      secondTerm /= 2;\n    }\n    uint256 thirdTerm = exp * expMinusOne * expMinusTwo * basePowerThree;\n    unchecked {\n      thirdTerm /= 6;\n    }\n\n    return WadRayMath.RAY + (rate * exp) / SECONDS_PER_YEAR + secondTerm + thirdTerm;\n  }\n\n  /**\n   * @dev Calculates the compounded interest between the timestamp of the last update and the current block timestamp\n   * @param rate The interest rate (in ray)\n   * @param lastUpdateTimestamp The timestamp from which the interest accumulation needs to be calculated\n   *\n   */\n  function calculateCompoundedInterest(\n    uint256 rate,\n    uint40 lastUpdateTimestamp\n  ) internal view returns (uint256) {\n    return calculateCompoundedInterest(rate, lastUpdateTimestamp, block.timestamp);\n  }\n\n  /**\n   * @dev max between two numbers\n   * @param x number one\n   * @param y number two\n   */\n  function maxOf(uint256 x, uint256 y) internal pure returns (uint256 max) {\n    assembly {\n      max := xor(x, mul(xor(x, y), gt(y, x)))\n    }\n  }\n\n  /**\n   * @dev min between two numbers\n   * @param x number one\n   * @param y number two\n   */\n  function minOf(uint256 x, uint256 y) internal pure returns (uint256 min) {\n    /// @solidity memory-safe-assembly\n    assembly {\n      min := xor(x, mul(xor(x, y), lt(y, x)))\n    }\n  }\n}\n"
      },
      "src/libraries/math/PercentageMath.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n/**\n * @title PercentageMath library\n * @author Unlockd\n * @notice Provides functions to perform percentage calculations\n * @dev Percentages are defined by default with 2 decimals of precision (100.00). The precision is indicated by PERCENTAGE_FACTOR\n * @dev Operations are rounded. If a value is >=.5, will be rounded up, otherwise rounded down.\n * @dev fork from https://github.com/aave/aave-v3-core/blob/master/contracts/protocol/libraries/math/PercentageMath.sol\n */\nlibrary PercentageMath {\n  uint256 constant PERCENTAGE_FACTOR = 1e4; //percentage plus two decimals\n  uint256 constant ONE_HUNDRED_PERCENT = 1e4; //10000, 100%\n  uint256 internal constant HALF_PERCENTAGE_FACTOR = 0.5e4;\n\n  /**\n   * @notice Executes a percentage multiplication\n   * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328\n   * @param value The value of which the percentage needs to be calculated\n   * @param percentage The percentage of the value to be calculated\n   * @return result value percentmul percentage\n   */\n  function percentMul(uint256 value, uint256 percentage) internal pure returns (uint256 result) {\n    // to avoid overflow, value <= (type(uint256).max - HALF_PERCENTAGE_FACTOR) / percentage\n    assembly {\n      if iszero(\n        or(\n          iszero(percentage),\n          iszero(gt(value, div(sub(not(0), HALF_PERCENTAGE_FACTOR), percentage)))\n        )\n      ) {\n        revert(0, 0)\n      }\n\n      result := div(add(mul(value, percentage), HALF_PERCENTAGE_FACTOR), PERCENTAGE_FACTOR)\n    }\n  }\n\n  /**\n   * @notice Executes a percentage division\n   * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328\n   * @param value The value of which the percentage needs to be calculated\n   * @param percentage The percentage of the value to be calculated\n   * @return result value percentdiv percentage\n   */\n  function percentDiv(uint256 value, uint256 percentage) internal pure returns (uint256 result) {\n    // to avoid overflow, value <= (type(uint256).max - halfPercentage) / PERCENTAGE_FACTOR\n    assembly {\n      if or(\n        iszero(percentage),\n        iszero(iszero(gt(value, div(sub(not(0), div(percentage, 2)), PERCENTAGE_FACTOR))))\n      ) {\n        revert(0, 0)\n      }\n\n      result := div(add(mul(value, PERCENTAGE_FACTOR), div(percentage, 2)), percentage)\n    }\n  }\n}\n"
      },
      "src/libraries/math/WadRayMath.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n/**\n * @title WadRayMath library\n * @author Unlockd\n * @notice Provides functions to perform calculations with Wad and Ray units\n * @dev Provides mul and div function for wads (decimal numbers with 18 digits of precision) and rays (decimal numbers\n * with 27 digits of precision)\n * @dev Operations are rounded. If a value is >=.5, will be rounded up, otherwise rounded down.\n * @dev fork from https://github.com/aave/aave-v3-core/blob/master/contracts/protocol/libraries/math/WadRayMath.sol\n */\nlibrary WadRayMath {\n  // HALF_WAD and HALF_RAY expressed with extended notation as constant with operations are not supported in Yul assembly\n  uint256 internal constant WAD = 1e18;\n  uint256 internal constant HALF_WAD = 0.5e18; // 18\n\n  uint256 internal constant RAY = 1e27;\n  uint256 internal constant HALF_RAY = 0.5e27; // A Ray is a unit with 27 decimals of precision.\n\n  uint256 internal constant WAD_RAY_RATIO = 1e9;\n\n  /**\n   * @return One ray, 1e27\n   *\n   */\n  function ray() internal pure returns (uint256) {\n    return RAY;\n  }\n\n  /**\n   * @return One wad, 1e18\n   *\n   */\n\n  function wad() internal pure returns (uint256) {\n    return WAD;\n  }\n\n  /**\n   * @return Half ray, 1e27/2\n   *\n   */\n  function halfRay() internal pure returns (uint256) {\n    return HALF_RAY;\n  }\n\n  /**\n   * @return Half ray, 1e18/2\n   *\n   */\n  function halfWad() internal pure returns (uint256) {\n    return HALF_WAD;\n  }\n\n  /**\n   * @dev Solady FixedPointMathLib.sol mulWad (Equivalent to `(x * y) / WAD` rounded up.)\n   * @param x Wad\n   * @param y Wad\n   * @return z = x*y, in wad\n   */\n  function wadMul(uint256 x, uint256 y) internal pure returns (uint256 z) {\n    /// @solidity memory-safe-assembly\n    assembly {\n      // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`.\n      if mul(y, gt(x, div(not(0), y))) {\n        mstore(0x00, 0xbac65e5b) // `MulWadFailed()`.\n        revert(0x1c, 0x04)\n      }\n      z := div(mul(x, y), WAD)\n    }\n  }\n\n  /**\n   * @dev Solady FixedPointMathLib.sol divWad (Equivalent to `(x * WAD) / y` rounded down.)\n   * @param x Wad\n   * @param y Wad\n   * @return z = z/y, in wad\n   */\n  function wadDiv(uint256 x, uint256 y) internal pure returns (uint256 z) {\n    /// @solidity memory-safe-assembly\n    assembly {\n      // Equivalent to `require(y != 0 && (WAD == 0 || x <= type(uint256).max / WAD))`.\n      if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) {\n        mstore(0x00, 0x7c5f487d) // `DivWadFailed()`.\n        revert(0x1c, 0x04)\n      }\n      z := div(mul(x, WAD), y)\n    }\n  }\n\n  /**\n   * @notice Multiplies two ray, rounding half up to the nearest ray\n   * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328\n   * @param a Ray\n   * @param b Ray\n   * @return c = a raymul b\n   */\n  function rayMul(uint256 a, uint256 b) internal pure returns (uint256 c) {\n    // to avoid overflow, a <= (type(uint256).max - HALF_RAY) / b\n    assembly {\n      if iszero(or(iszero(b), iszero(gt(a, div(sub(not(0), HALF_RAY), b))))) {\n        revert(0, 0)\n      }\n\n      c := div(add(mul(a, b), HALF_RAY), RAY)\n    }\n  }\n\n  /**\n   * @notice Divides two ray, rounding half up to the nearest ray\n   * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328\n   * @param a Ray\n   * @param b Ray\n   * @return c = a raydiv b\n   */\n  function rayDiv(uint256 a, uint256 b) internal pure returns (uint256 c) {\n    // to avoid overflow, a <= (type(uint256).max - halfB) / RAY\n    assembly {\n      if or(iszero(b), iszero(iszero(gt(a, div(sub(not(0), div(b, 2)), RAY))))) {\n        revert(0, 0)\n      }\n\n      c := div(add(mul(a, RAY), div(b, 2)), b)\n    }\n  }\n\n  /**\n   * @dev Casts ray down to wad\n   * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328\n   * @param a Ray\n   * @return b = a converted to wad, rounded half up to the nearest wad\n   */\n  function rayToWad(uint256 a) internal pure returns (uint256 b) {\n    assembly {\n      b := div(a, WAD_RAY_RATIO)\n      let remainder := mod(a, WAD_RAY_RATIO)\n      if iszero(lt(remainder, div(WAD_RAY_RATIO, 2))) {\n        b := add(b, 1)\n      }\n    }\n  }\n\n  /**\n   * @dev Converts wad up to ray\n   * @dev assembly optimized for improved gas savings, see https://twitter.com/transmissions11/status/1451131036377571328\n   * @param a Wad\n   * @return b = a converted in ray\n   */\n  function wadToRay(uint256 a) internal pure returns (uint256 b) {\n    // to avoid overflow, b/WAD_RAY_RATIO == a\n    assembly {\n      b := mul(a, WAD_RAY_RATIO)\n\n      if iszero(eq(div(b, WAD_RAY_RATIO), a)) {\n        revert(0, 0)\n      }\n    }\n  }\n}\n"
      },
      "src/libraries/proxy/UnlockdMinimalProxy.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.19;\n\n/**\n * @title Unlockd Minimal Proxy\n * @author Unlockd\n * @notice Proxy for the modules\n * @dev fork from https://github.com/euler-xyz/euler-contracts/blob/master/contracts/Proxy.sol\n */\ncontract UnlockdMinimalProxy {\n  address immutable creator;\n\n  constructor() {\n    creator = msg.sender;\n  }\n\n  // External interface\n\n  fallback() external {\n    address creator_ = creator;\n    assembly {\n      mstore(0, 0xe9c4a3ac00000000000000000000000000000000000000000000000000000000) // dispatch() selector\n      calldatacopy(4, 0, calldatasize())\n      mstore(add(4, calldatasize()), shl(96, caller()))\n\n      let result := call(gas(), creator_, 0, 0, add(24, calldatasize()), 0, 0)\n      returndatacopy(0, 0, returndatasize())\n\n      switch result\n      case 0 {\n        revert(0, returndatasize())\n      }\n      default {\n        return(0, returndatasize())\n      }\n    }\n  }\n}\n"
      },
      "src/libraries/signatures/BuyNowSign.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.19;\n\nimport {Errors} from '../../libraries/helpers/Errors.sol';\nimport {BaseSignature} from '../../libraries/base/BaseSignature.sol';\nimport {CoreStorage} from '../storage/CoreStorage.sol';\nimport {DataTypes} from '../../types/DataTypes.sol';\nimport {AssetLogic} from '../../libraries/logic/AssetLogic.sol';\n\ncontract BuyNowSign is BaseSignature {\n  string internal constant NAME = 'SignBuyNow';\n  string internal constant VERSION = '1';\n\n  bytes32 internal constant TYPEHASH =\n    0x6b77050f9bf3df21b1bd19ccdbf03be95abec0c1da32ea40a2950af432b17e6f;\n\n  constructor() BaseSignature(NAME, VERSION) {\n    // NOTHINIG TO DO\n  }\n\n  function calculateDigest(\n    uint256 nonce,\n    DataTypes.SignBuyNow calldata signBuyNow\n  ) public view validateDeadline(signBuyNow.deadline) returns (bytes32 digest) {\n    unchecked {\n      digest = _hashTypedData(_getStructHash(nonce, signBuyNow));\n    }\n  }\n\n  function _validateSignature(\n    address msgSender,\n    DataTypes.SignBuyNow calldata signBuyNow,\n    DataTypes.EIP712Signature calldata sig\n  ) internal {\n    if (msgSender == address(0)) {\n      revert Errors.SenderZeroAddress();\n    }\n    if (_signNonce[msgSender] != signBuyNow.nonce) {\n      revert Errors.WrongNonce();\n    }\n    // Validate signature\n    _validateRecoveredAddress(\n      calculateDigest(_signNonce[msgSender]++, signBuyNow),\n      _signer,\n      signBuyNow.deadline,\n      sig\n    );\n  }\n\n  function _getStructHash(\n    uint256 nonce,\n    DataTypes.SignBuyNow calldata buyNowSign\n  ) internal pure returns (bytes32) {\n    bytes32 result;\n    {\n      result = keccak256(\n        abi.encode(\n          TYPEHASH,\n          AssetLogic.getAssetStructHash(nonce, buyNowSign.asset),\n          buyNowSign.marketAdapter,\n          buyNowSign.assetLtv,\n          buyNowSign.assetLiquidationThreshold,\n          buyNowSign.from,\n          buyNowSign.to,\n          keccak256(abi.encodePacked(buyNowSign.data)),\n          buyNowSign.value,\n          buyNowSign.marketApproval,\n          buyNowSign.marketPrice,\n          buyNowSign.underlyingAsset,\n          nonce,\n          buyNowSign.deadline\n        )\n      );\n    }\n    return result;\n  }\n}\n"
      },
      "src/libraries/storage/CoreStorage.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.19;\n\nimport {Constants} from '../helpers/Constants.sol';\nimport {DataTypes} from '../../types/DataTypes.sol';\nimport {ACLManager} from '../configuration/ACLManager.sol';\n\n/**\n * @title CoreStorage\n * @author Unlockd\n * @notice Storage of the route context for the modules\n */\ncontract CoreStorage {\n  /////////////////////////////////////////\n  //  Dispacher and Upgrades\n  /////////////////////////////////////////\n\n  mapping(uint256 => address) internal _moduleLookup; // moduleId => module implementation\n  mapping(uint256 => address) internal _proxyLookup; // moduleId => proxy address (only for single-proxy modules)\n  mapping(address => TrustedSenderInfo) internal _trustedSenders;\n  struct TrustedSenderInfo {\n    uint32 moduleId; // 0 = un-trusted\n    address moduleImpl; // only non-zero for external single-proxy modules\n  }\n\n  /////////////////////////////////////////\n  //  Configurations\n  /////////////////////////////////////////\n\n  // ACL MANAGER ADDRESS\n  address internal _aclManager;\n  // WALLET REGISTRY\n  address internal _walletRegistry;\n  // ALLOWED CONTROLLER\n  address internal _allowedControllers;\n  // ORACLE ADDRESS\n  address internal _reserveOracle;\n  // SIGNED ADDRESS\n  address internal _signer;\n  // UTOKEN Vault\n  address internal _uTokenVault;\n  /// @dev contract that\n  address internal _safeERC721;\n  /////////////////////////////////////////\n  //  Signature Logic\n  /////////////////////////////////////////\n  mapping(address => uint256) internal _signNonce;\n\n  /////////////////////////////////////////\n  //  Allowed NFTS\n  /////////////////////////////////////////\n\n  mapping(address => Constants.ReserveType) internal _allowedCollections;\n\n  /////////////////////////////////////////\n  //  Allowed addresses\n  /////////////////////////////////////////\n\n  // Mapping of markets adapter allowed\n  mapping(address => uint256) internal _allowedMarketAdapter; // address adapter true/false\n\n  /////////////////////////////////////////\n  //  Data Structs\n  /////////////////////////////////////////\n\n  mapping(bytes32 => DataTypes.Loan) internal _loans;\n  mapping(bytes32 => DataTypes.Order) internal _orders;\n\n  /////////////////////////////////////////\n}\n"
      },
      "src/libraries/utils/EIP712.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.19;\n\n/// @notice Contract for EIP-712 typed structured data hashing and signing.\n/// @author Turing Consulting\n/// @author Modified and simplified from Solady's EIP721.sol\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EIP712.sol)\n/// @author Modified from Solbase (https://github.com/Sol-DAO/solbase/blob/main/src/utils/EIP712.sol)\n/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/EIP712.sol)\n/// Note, this implementation:\n/// - Uses `address(this)` for the `verifyingContract` field.\n/// - Does NOT use the optional EIP-712 salt.\n/// - Does NOT use any EIP-712 extensions.\n/// This is for simplicity and to save gas.\nabstract contract EIP712 {\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                  CONSTANTS AND IMMUTABLES                  */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev `keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\")`.\n    bytes32 internal constant _DOMAIN_TYPEHASH =\n        0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;\n\n    address private immutable _cachedThis;\n    uint256 private immutable _cachedChainId;\n    bytes32 private immutable _cachedNameHash;\n    bytes32 private immutable _cachedVersionHash;\n    bytes32 private immutable _cachedDomainSeparator;\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                        CONSTRUCTOR                         */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Cache the hashes for cheaper runtime gas costs.\n    /// In the case of upgradeable contracts (i.e. proxies),\n    /// or if the chain id changes due to a hard fork,\n    /// the domain separator will be seamlessly calculated on-the-fly.\n    constructor(string memory name, string memory version) {\n        _cachedThis = address(this);\n        _cachedChainId = block.chainid;\n\n        bytes32 nameHash = keccak256(bytes(name));\n        bytes32 versionHash = keccak256(bytes(version));\n        _cachedNameHash = nameHash;\n        _cachedVersionHash = versionHash;\n\n        bytes32 separator;\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Load the free memory pointer.\n            mstore(m, _DOMAIN_TYPEHASH)\n            mstore(add(m, 0x20), nameHash)\n            mstore(add(m, 0x40), versionHash)\n            mstore(add(m, 0x60), chainid())\n            mstore(add(m, 0x80), address())\n            separator := keccak256(m, 0xa0)\n        }\n        _cachedDomainSeparator = separator;\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                     HASHING OPERATIONS                     */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns the EIP-712 domain separator.\n    function _domainSeparatorV4() internal view virtual returns (bytes32 separator) {\n        separator = _cachedDomainSeparator;\n        if (_cachedDomainSeparatorInvalidated()) {\n            separator = _buildDomainSeparatorV4();\n        }\n    }\n\n    /// @dev Returns the hash of the fully encoded EIP-712 message for this domain,\n    /// given `structHash`, as defined in\n    /// https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct.\n    ///\n    /// The hash can be used together with {ECDSA-recover} to obtain the signer of a message:\n    /// ```\n    ///     bytes32 digest = _hashTypedData(keccak256(abi.encode(\n    ///         keccak256(\"Mail(address to,string contents)\"),\n    ///         mailTo,\n    ///         keccak256(bytes(mailContents))\n    ///     )));\n    ///     address signer = ECDSA.recover(digest, signature);\n    /// ```\n    function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32 digest) {\n        bytes32 separator = _cachedDomainSeparator;\n        if (_cachedDomainSeparatorInvalidated()) {\n            separator = _buildDomainSeparatorV4();\n        }\n        /// @solidity memory-safe-assembly\n        assembly {\n            // Compute the digest.\n            mstore(0x00, 0x1901000000000000) // Store \"\\x19\\x01\".\n            mstore(0x1a, separator) // Store the domain separator.\n            mstore(0x3a, structHash) // Store the struct hash.\n            digest := keccak256(0x18, 0x42)\n            // Restore the part of the free memory slot that was overwritten.\n            mstore(0x3a, 0)\n        }\n    }\n\n    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n    /*                      PRIVATE HELPERS                       */\n    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n    /// @dev Returns the EIP-712 domain separator.\n    function _buildDomainSeparatorV4() private view returns (bytes32 separator) {\n        bytes32 nameHash = _cachedNameHash;\n        bytes32 versionHash = _cachedVersionHash;\n        /// @solidity memory-safe-assembly\n        assembly {\n            let m := mload(0x40) // Load the free memory pointer.\n            mstore(m, _DOMAIN_TYPEHASH)\n            mstore(add(m, 0x20), nameHash)\n            mstore(add(m, 0x40), versionHash)\n            mstore(add(m, 0x60), chainid())\n            mstore(add(m, 0x80), address())\n            separator := keccak256(m, 0xa0)\n        }\n    }\n\n    /// @dev Returns if the cached domain separator has been invalidated.\n    function _cachedDomainSeparatorInvalidated() private view returns (bool result) {\n        uint256 cachedChainId = _cachedChainId;\n        address cachedThis = _cachedThis;\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := iszero(and(eq(chainid(), cachedChainId), eq(address(), cachedThis)))\n        }\n    }\n}\n"
      },
      "src/protocol/modules/BuyNow.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport {SafeTransferLib} from '@solady/utils/SafeTransferLib.sol';\nimport {IProtocolOwner} from '@unlockd-wallet/src/interfaces/IProtocolOwner.sol';\nimport {IDelegationWalletRegistry} from '@unlockd-wallet/src/interfaces/IDelegationWalletRegistry.sol';\nimport {AssetLogic} from '@unlockd-wallet/src/libs/logic/AssetLogic.sol';\n\nimport {BaseCoreModule} from '../../libraries/base/BaseCoreModule.sol';\n\nimport {LoanLogic} from '../../libraries/logic/LoanLogic.sol';\nimport {ValidationLogic} from '../../libraries/logic/ValidationLogic.sol';\nimport {GenericLogic} from '../../libraries/logic/GenericLogic.sol';\nimport {BuyNowLogic} from '../../libraries/logic/BuyNowLogic.sol';\nimport {IUTokenVault} from '../../interfaces/IUTokenVault.sol';\nimport {ISafeERC721} from '../../interfaces/ISafeERC721.sol';\nimport {IBuyNowModule} from '../../interfaces/modules/IBuyNowModule.sol';\nimport {BuyNowSign} from '../../libraries/signatures/BuyNowSign.sol';\n\nimport {ReserveConfiguration} from '../../libraries/configuration/ReserveConfiguration.sol';\nimport {IMarketAdapter} from '../../interfaces/adapter/IMarketAdapter.sol';\nimport {Errors} from '../../libraries/helpers/Errors.sol';\nimport {DataTypes} from '../../types/DataTypes.sol';\n\ncontract BuyNow is BaseCoreModule, BuyNowSign, IBuyNowModule {\n  using SafeTransferLib for address;\n  using LoanLogic for DataTypes.Loan;\n  using ReserveConfiguration for DataTypes.ReserveConfigurationMap;\n\n  constructor(uint256 moduleId, bytes32 moduleVersion) BaseCoreModule(moduleId, moduleVersion) {\n    // NOTHING TO DO\n  }\n\n  /**\n   *  @dev Get the calculation\n   *  @param signBuyMarket struct with the information needed about the asset to realize the buy\n   *\n   */\n  function getCalculations(\n    DataTypes.SignBuyNow calldata signBuyMarket\n  ) external pure returns (uint256, uint256) {\n    return BuyNowLogic.calculations(signBuyMarket);\n  }\n\n  /**\n   * @dev BuyNowPayLater functionality, allow the user to buy a asset throw the adapter implementation\n   * and create a loan on belhalf of this new NFT to pay part of the final price.\n   * @param amount Amount that the user wan't to use to buy the asset\n   * @param signBuyMarket signed struct with the information needed to proceed the process\n   * @param sig validation of the signature\n   */\n  function buy(\n    uint256 amount,\n    DataTypes.SignBuyNow calldata signBuyMarket,\n    DataTypes.EIP712Signature calldata sig\n  ) external {\n    address msgSender = unpackTrailingParamMsgSender();\n    _checkHasUnlockdWallet(msgSender);\n\n    _validateSignature(msgSender, signBuyMarket, sig);\n\n    CalculatedDataBuyNow memory vars;\n\n    (address wallet, address protocolOwner) = GenericLogic.getMainWallet(\n      _walletRegistry,\n      msgSender\n    );\n    // Update pool liquidity\n    IUTokenVault(_uTokenVault).updateState(signBuyMarket.underlyingAsset);\n    DataTypes.ReserveData memory reserve = IUTokenVault(_uTokenVault).getReserveData(\n      signBuyMarket.underlyingAsset\n    );\n    // We move the funds from user to the Adapter\n    reserve.underlyingAsset.safeTransferFrom(msgSender, signBuyMarket.marketAdapter, amount);\n\n    // If the user don't pay the full amount we create a loan\n    if (amount < signBuyMarket.marketPrice) {\n      if (\n        IUTokenVault(_uTokenVault).validateReserveType(\n          reserve.config.getReserveType(),\n          _allowedCollections[signBuyMarket.asset.collection]\n        ) == false\n      ) {\n        revert Errors.NotValidReserve();\n      }\n      vars.loanId = _borrowLoan(msgSender, amount, protocolOwner, signBuyMarket);\n    }\n\n    {\n      Errors.verifyAreEquals(wallet, signBuyMarket.from);\n\n      // Buy the asset\n      vars.realCost = IMarketAdapter(signBuyMarket.marketAdapter).buy(\n        IMarketAdapter.BuyParams({\n          wallet: wallet,\n          underlyingAsset: signBuyMarket.underlyingAsset,\n          marketPrice: signBuyMarket.marketPrice,\n          marketApproval: signBuyMarket.marketApproval,\n          to: signBuyMarket.to,\n          value: signBuyMarket.value,\n          data: signBuyMarket.data\n        })\n      );\n\n      // Validate we recived the NFT.\n      Errors.verifyAreEquals(\n        ISafeERC721(_safeERC721).ownerOf(\n          signBuyMarket.asset.collection,\n          signBuyMarket.asset.tokenId\n        ),\n        wallet\n      );\n    }\n\n    emit BuyNowPayLater(\n      vars.loanId,\n      signBuyMarket.asset.collection,\n      signBuyMarket.asset.tokenId,\n      vars.realCost,\n      amount\n    );\n  }\n\n  function _borrowLoan(\n    address msgSender,\n    uint256 amount,\n    address protocolOwner,\n    DataTypes.SignBuyNow calldata signBuyMarket\n  ) internal returns (bytes32 loanId) {\n    (uint256 minAmount, ) = BuyNowLogic.calculations(signBuyMarket);\n\n    // We check that the amount is bigger or equal than the minimum\n    if (minAmount > amount) {\n      revert Errors.AmountToLow();\n    }\n    uint256 amountNeeded = signBuyMarket.marketPrice - amount;\n    // Create LOAN\n    loanId = LoanLogic.generateId(msgSender, signBuyMarket.nonce, signBuyMarket.deadline);\n\n    _loans[loanId].createLoan(\n      LoanLogic.ParamsCreateLoan({\n        msgSender: msgSender,\n        underlyingAsset: signBuyMarket.underlyingAsset,\n        totalAssets: 1,\n        loanId: loanId\n      })\n    );\n    // We borrow on belhalf of the user and sent the money to the Adapter.\n    IUTokenVault(_uTokenVault).borrow(\n      signBuyMarket.underlyingAsset,\n      loanId,\n      amountNeeded,\n      signBuyMarket.marketAdapter,\n      msgSender\n    );\n    // Set the new NFT assigned to the LoanId\n    IProtocolOwner(protocolOwner).setLoanId(signBuyMarket.asset.assetId, loanId);\n  }\n}\n"
      },
      "src/types/DataTypes.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {Constants} from '../libraries/helpers/Constants.sol';\n\n\nlibrary DataTypes {\n\n  ///////////////////////////////////////////////////////\n  // ASSET \n  ///////////////////////////////////////////////////////\n\n  struct MarketBalance {\n  // Total supply invested\n    uint128 totalSupplyScaledNotInvested;   \n    // Total supply\n    uint128 totalSupplyAssets;\n    uint128 totalSupplyScaled;\n    // Total supply borrowed\n    uint128 totalBorrowScaled;\n      // last update\n    uint40 lastUpdateTimestamp;\n  }\n\n  struct ReserveData {\n    ReserveConfigurationMap config;\n    //the liquidity index. Expressed in ray\n    uint128 liquidityIndex;\n    //variable borrow index. Expressed in ray\n    uint128 variableBorrowIndex;\n    //the current supply rate. Expressed in ray\n    uint128 currentLiquidityRate;\n    //the current variable borrow rate. Expressed in ray\n    uint128 currentVariableBorrowRate;\n    // address asset\n    address underlyingAsset;\n    // address scaled token\n    address scaledTokenAddress;\n    //address of the interest rate strategy\n    address interestRateAddress;\n    // address of the strategy\n    address strategyAddress;\n    // last update\n    uint40 lastUpdateTimestamp;\n  }\n  \n  struct ReserveConfigurationMap {\n    //bit 0-15: LTV\n    //bit 16-31: Liq. threshold\n    //bit 32-47: Liq. bonus\n    //bit 48-55: Decimals\n    //bit 56: reserve is active\n    //bit 57: reserve is frozen\n    //bit 58: borrowing is enabled\n    //bit 59: stable rate borrowing enabled\n    //bit 60: asset is paused\n    //bit 61: borrowing in isolation mode is enabled\n    //bit 62: siloed borrowing enabled\n    //bit 63: flashloaning enabled\n    //bit 64-79: reserve factor\n    //bit 80-115 borrow cap in whole tokens, borrowCap == 0 => no cap\n    //bit 116-151 supply cap in whole tokens, supplyCap == 0 => no cap\n    //bit 152-167 liquidation protocol fee\n    //bit 168-175 eMode category\n    //bit 176-211 unbacked mint cap in whole tokens, unbackedMintCap == 0 => minting disabled\n    //bit 212-251 debt ceiling for isolation mode with (ReserveConfiguration::DEBT_CEILING_DECIMALS) decimals\n    //bit 252-255 unused\n\n    uint256 data;\n  }\n\n   \n\n  ///////////////////////////////////////////////////////\n  // ORDER \n  ///////////////////////////////////////////////////////\n\n  struct OfferItem {\n    // Slot 0\n    bytes32 loanId;\n    // Slot 1\n    bytes32 assetId;\n    // Slot 2\n    uint128 startAmount;\n    uint128 endAmount; \n    // Slot 3\n    uint128 debtToSell;\n  }  \n\n  struct Timeframe {\n    // Slot 0\n    uint40 startTime;\n    uint40 endTime;\n  }\n\n  struct Bid {\n    // Slot 0\n    bytes32 loanId;\n    // Slot 1\n    address buyer;\n    // Slot 2\n    uint128 amountToPay;\n    uint128 amountOfDebt;\n  }\n\n  struct Order {\n    // Slot 0\n    bytes32 orderId;\n    // Slot 1\n    address owner;\n    Constants.OrderType orderType;\n    uint88 countBids;\n\n    uint256 bidderDebtPayed;\n    uint256 bidderBonus;\n    // Slot 2\n    OfferItem offer;\n    // Slot 3\n    Timeframe timeframe;\n    // Slot 4\n    Bid bid;\n  }\n\n  ///////////////////////////////////////////////////////\n  // LOAN \n  ///////////////////////////////////////////////////////\n\n  struct Loan {\n    // Slot 0\n    bytes32 loanId;\n    // Slot 1\n    uint88 totalAssets;\n    Constants.LoanState state;\n    // Slot 2\n    address underlyingAsset;\n    // Slot 3\n    address owner; \n  }\n\n\n  ///////////////////////////////////////////////////////\n  // Asset\n  ///////////////////////////////////////////////////////\n\n  struct Asset {\n    address collection;\n    uint256 tokenId;\n  }\n \n  ///////////////////////////////////////////////////////\n  // SIGNATURES \n  ///////////////////////////////////////////////////////\n\n  struct EIP712Signature {\n    uint8 v;\n    bytes32 r;\n    bytes32 s;\n    uint256 deadline;\n  }\n\n  struct SignLoanConfig {\n    bytes32 loanId;\n    uint256 aggLoanPrice;\n    uint256 aggLtv;\n    uint256 aggLiquidationThreshold;\n    uint88 totalAssets;\n    uint256 nonce;\n    uint256 deadline;\n  }\n\n  struct SignAsset {\n    bytes32 assetId;\n    address collection;\n    uint256 tokenId;\n    uint256 price;\n    uint256 nonce;\n    uint256 deadline;\n  }\n\n  struct SignBuyNow {\n    SignAsset asset;\n    uint256 assetLtv; // configuration asset\n    uint256 assetLiquidationThreshold; // configuration asset\n    // tx Data\n    address from;\n    address to;\n    bytes data;\n    uint256 value;\n    // Configuration\n    address marketAdapter;\n    address marketApproval; // Approval needed to make the buy\n    uint256 marketPrice; // Market Adapter Price (Reservoir, Opensea ...)\n    address underlyingAsset; // asset needed to buy\n    uint256 nonce;\n    uint256 deadline;\n  }\n\n  struct SignSellNow {\n    SignLoanConfig loan;\n    bytes32 assetId;\n    // approval\n    address marketAdapter;\n    address marketApproval;\n    uint256 marketPrice;\n    address underlyingAsset;\n    // sell data\n    address from;\n    address to;\n    bytes data;\n    uint256 value;\n  \n    // signature\n    uint256 nonce;\n    uint256 deadline;\n  }\n\n  struct SignAction {\n    SignLoanConfig loan;\n    bytes32[] assets;\n    address underlyingAsset;\n    uint256 nonce;\n    uint256 deadline;\n  }\n\n  struct SignMarket {\n    SignLoanConfig loan;\n    bytes32 assetId;\n    address collection;\n    uint256 tokenId;\n    uint256 assetPrice;\n    uint256 assetLtv;\n    uint256 nonce;\n    uint256 deadline;\n  }\n\n  struct SignAuction {\n    SignLoanConfig loan;\n    bytes32[] assets;\n    uint256 assetPrice;\n    uint256 assetLtv;\n    uint40 endTime; // @audit-info review this\n    uint256 nonce;\n    uint256 deadline;\n  }\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "forge-std/=lib/forge-std/src/",
        "solady/=lib/solady/src/",
        "@openzeppelin/=lib/openzeppelin-contracts/",
        "@openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
        "@chainlink/=lib/chainlink/",
        "@unlockd-wallet/=lib/unlockdv2-wallet/",
        "@solady/=lib/solady/src/",
        "@maxapy/=lib/maxapy/src/",
        "@gnosis.pm/safe-contracts/=lib/unlockdv2-wallet/lib/safe-contracts/",
        "chainlink/=lib/chainlink/",
        "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
        "maxapy/=lib/maxapy/",
        "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "openzeppelin/=lib/openzeppelin-contracts/contracts/",
        "safe-contracts/=lib/unlockdv2-wallet/lib/safe-contracts/contracts/",
        "unlockdv2-wallet/=lib/unlockdv2-wallet/src/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "libraries": {}
    },
    "language": "Solidity"
  }}