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/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/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/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"
      },
      "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/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/modules/IManagerModule.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {Constants} from '../../libraries/helpers/Constants.sol';\n\ninterface IManagerModule {\n  ////////////////////////////////////\n  // SAFE ERC721\n  event SetSafeERC721(address indexed safeERC721);\n\n  function setSafeERC721(address safeERC721) external;\n\n  function getSafeERC721() external view returns (address);\n\n  ////////////////////////////////////\n  // RESERVE ORACLE\n  event SetReserveOracle(address indexed oracle);\n\n  function setReserveOracle(address oracle) external;\n\n  function getReserveOracle() external returns (address);\n\n  ////////////////////////////////////\n  // SIGNER\n  event SetSigner(address indexed signer);\n\n  function setSigner(address signer) external;\n\n  function getSigner() external view returns (address);\n\n  ////////////////////////////////////\n  // WALLET REGISTRY\n  event SetWalletRegistry(address indexed walletRegistry);\n\n  function setWalletRegistry(address walletRegistry) external;\n\n  function getWalletRegistry() external view returns (address);\n\n  ////////////////////////////////////\n  // ALLOWED CONTROLLERS\n\n  event SetAllowedControllers(address indexed allowedControllers);\n\n  function setAllowedControllers(address allowedControllers) external;\n\n  function getAllowedController() external view returns (address);\n\n  ////////////////////////////////////\n  // ALLOWED CONTROLLERS\n\n  event AllowCollectionReserveType(address indexed collection, uint256 indexed reserveType);\n\n  function allowCollectionReserveType(\n    address collection,\n    Constants.ReserveType reserveType\n  ) external;\n\n  function getCollectionReserveType(\n    address collection\n  ) external view returns (Constants.ReserveType);\n\n  ////////////////////////////////////\n  // UTokenVault\n  event SetUTokenVault(address indexed uToken);\n\n  function setUTokenVault(address uTokenVault) external;\n\n  function getUTokenVault() external view returns (address);\n\n  ////////////////////////////////////\n  // Adapters\n\n  event ActivateMarketAdapter(address indexed market);\n\n  event DisableMarketAdapter(address indexed market);\n\n  function addMarketAdapters(address adapter, bool active) external;\n\n  function isMarketAdapterActive(address adapter) external view returns (uint256);\n\n  ////////////////////////////////////\n  // EMERGENCY\n\n  event EmergencyFreezeLoan(bytes32 loanId);\n\n  function emergencyFreezeLoan(bytes32 loanId) external;\n\n  event EmergencyActivateLoan(bytes32 loanId);\n\n  function emergencyActivateLoan(bytes32 loanId) external;\n\n  event EmergencyBlockLoan(bytes32 loanId);\n\n  function emergencyBlockLoan(bytes32 loanId) external;\n\n  event EmergencyUpdateEndTimeAuction(bytes32 orderId, uint40 newEndTime);\n\n  function emergencyUpdateEndTimeAuction(bytes32 orderId, uint40 newEndTime) external;\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/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/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/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/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/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/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/protocol/modules/Manager.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {IManagerModule} from '../../interfaces/modules/IManagerModule.sol';\nimport {PercentageMath} from '../../libraries/math/PercentageMath.sol';\nimport {BaseCoreModule} from '../../libraries/base/BaseCoreModule.sol';\nimport {IACLManager} from '../../interfaces/IACLManager.sol';\nimport {Errors} from '../../libraries/helpers/Errors.sol';\nimport {DataTypes, Constants} from '../../types/DataTypes.sol';\nimport {LoanLogic} from '../../libraries/logic/LoanLogic.sol';\n\ncontract Manager is BaseCoreModule, IManagerModule {\n  using LoanLogic for DataTypes.Loan;\n\n  constructor(uint256 moduleId_, bytes32 moduleVersion_) BaseCoreModule(moduleId_, moduleVersion_) {\n    // NOTHING TO DO\n  }\n\n  /**\n   * @dev Is a helper where aggregate the function to be standard\n   * @param safeERC721 Address of the SafeERC721\n   */\n  function setSafeERC721(address safeERC721) external onlyAdmin {\n    if (safeERC721 == address(0)) revert Errors.ZeroAddress();\n    _safeERC721 = safeERC721;\n    emit SetSafeERC721(safeERC721);\n  }\n\n  /**\n   * @dev return the address of this helper\n   * @return address return address safeERC721\n   */\n  function getSafeERC721() external view returns (address) {\n    return _safeERC721;\n  }\n\n  /**\n   * @dev Oracle for the reserve\n   * @param oracle Address of the new Reserve Oracle\n   */\n  function setReserveOracle(address oracle) external onlyAdmin {\n    if (oracle == address(0)) revert Errors.ZeroAddress();\n    _reserveOracle = oracle;\n    emit SetReserveOracle(oracle);\n  }\n\n  function getReserveOracle() external view returns (address) {\n    return _reserveOracle;\n  }\n\n  /**\n   *  @dev Set the singer of the messages\n   *  @param signer Address of the signer\n   */\n  function setSigner(address signer) external onlyAdmin {\n    if (signer == address(0)) revert Errors.ZeroAddress();\n    _signer = signer;\n    emit SetSigner(signer);\n  }\n\n  /**\n   * @dev get address of the signer\n   * @return address Address of the signer\n   */\n  function getSigner() external view returns (address) {\n    return _signer;\n  }\n\n  /**\n   * @dev Set the Wallet registry to check the get the wallets created\n   * @param walletRegistry Address of the wallet registry where we can check the addresses\n   */\n  function setWalletRegistry(address walletRegistry) external onlyAdmin {\n    if (walletRegistry == address(0)) revert Errors.ZeroAddress();\n    _walletRegistry = walletRegistry;\n    emit SetWalletRegistry(walletRegistry);\n  }\n\n  /**\n   * @dev get wallet registry\n   * @return address of the wallet registry\n   */\n  function getWalletRegistry() external view returns (address) {\n    return _walletRegistry;\n  }\n\n  /**\n   * @dev Set the allowed controller\n   * @param allowedControllers Address of the allowed controller\n   */\n  function setAllowedControllers(address allowedControllers) external onlyAdmin {\n    if (allowedControllers == address(0)) revert Errors.ZeroAddress();\n    _allowedControllers = allowedControllers;\n    emit SetAllowedControllers(allowedControllers);\n  }\n\n  /**\n   * @dev return allowed controller\n   * @return allowedControllers Address of the allowed controller\n   */\n  function getAllowedController() external view returns (address) {\n    return _allowedControllers;\n  }\n\n  /**\n   * @dev Set the allowed controller\n   * @param collection Address of the allowed collection\n   * @param reserveType type of the reserve that we allow to borrow.\n   */\n  function allowCollectionReserveType(\n    address collection,\n    Constants.ReserveType reserveType\n  ) external onlyAdmin {\n    if (collection == address(0)) revert Errors.ZeroAddress();\n    _allowedCollections[collection] = reserveType;\n    emit AllowCollectionReserveType(collection, uint256(reserveType));\n  }\n\n  /**\n   * @dev Get the collection reserve type\n   * @param collection Address of the allowed collection\n   * @return reserveType return stuct Constants.ReserveType\n   */\n  function getCollectionReserveType(\n    address collection\n  ) external view returns (Constants.ReserveType) {\n    return _allowedCollections[collection];\n  }\n\n  /**\n   * @dev Update the UTokenVault from the protocol\n   * @param uTokenVault address of the uTokenVault\n   */\n  function setUTokenVault(address uTokenVault) external onlyAdmin {\n    if (uTokenVault == address(0)) revert Errors.ZeroAddress();\n    _uTokenVault = uTokenVault;\n    emit SetUTokenVault(uTokenVault);\n  }\n\n  /**\n   * @dev Get the configured UTokenVault on the protocol\n   * @return address return the address of the uTokenVault\n   */\n  function getUTokenVault() external view returns (address) {\n    return _uTokenVault;\n  }\n\n  /**\n   * @dev Allow Market adapter to interact with the protocol\n   * @param adapter Address of the adapter\n   * @param active Bolean to allow or disable the UToken on the protocol\n   */\n  function addMarketAdapters(address adapter, bool active) external onlyGovernance {\n    if (adapter == address(0)) revert Errors.ZeroAddress();\n    _allowedMarketAdapter[adapter] = active ? 1 : 0;\n    if (active) {\n      emit ActivateMarketAdapter(adapter);\n    } else {\n      emit DisableMarketAdapter(adapter);\n    }\n  }\n\n  /**\n   * @dev check is is a avtived Market Adapter\n   * @return isActive 1 active 0 disabled\n   */\n  function isMarketAdapterActive(address adapter) external view returns (uint256) {\n    return _allowedMarketAdapter[adapter];\n  }\n\n  /**\n   * @dev Allow freeze a loan, the current owner can't borrow or add more assets to this loan.\n   * @param loanId Loand Id\n   */\n  function emergencyFreezeLoan(bytes32 loanId) external onlyEmergency {\n    if (loanId == bytes32(0)) revert Errors.InvalidLoanId();\n    _loans[loanId].freeze();\n    emit EmergencyFreezeLoan(loanId);\n  }\n\n  /**\n   * @dev Allow to activate a loan\n   * @param loanId Loand Id\n   */\n  function emergencyActivateLoan(bytes32 loanId) external onlyEmergency {\n    if (loanId == bytes32(0)) revert Errors.InvalidLoanId();\n    _loans[loanId].activate();\n    emit EmergencyActivateLoan(loanId);\n  }\n\n  /**\n   * @dev Allow to block a loan\n   * @param loanId Loand Id\n   */\n  function emergencyBlockLoan(bytes32 loanId) external onlyEmergency {\n    if (loanId == bytes32(0)) revert Errors.InvalidLoanId();\n    _loans[loanId].blocked();\n    emit EmergencyBlockLoan(loanId);\n  }\n\n  /**\n   * @dev Allow to increase the timestamp of a current auction\n   * @param orderId order Id\n   * @param newEndTime timestamp to finalize the auction\n   */\n  function emergencyUpdateEndTimeAuction(\n    bytes32 orderId,\n    uint40 newEndTime\n  ) external onlyEmergency {\n    if (orderId == bytes32(0)) revert Errors.InvalidOrderId();\n    _orders[orderId].timeframe.endTime = newEndTime;\n    emit EmergencyUpdateEndTimeAuction(orderId, newEndTime);\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"
  }}