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"
      },
      "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/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/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/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/Unlockd.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.19;\n\nimport {BaseCore} from '../libraries/base/BaseCore.sol';\nimport {ICore} from '../interfaces/ICore.sol';\nimport {Constants} from '../libraries/helpers/Constants.sol';\nimport {ACLManager} from '../libraries/configuration/ACLManager.sol';\nimport {Errors} from '../libraries/helpers/Errors.sol';\n\n/**\n * @title Unlockd Protocol\n * @author Unlockd\n * @notice Router\n * @dev fork from https://github.com/euler-xyz/euler-contracts/blob/master/contracts/Euler.sol\n */\ncontract Unlockd is ICore, BaseCore {\n  constructor(address aclManager, address installerModule) {\n    Errors.verifyNotZero(aclManager);\n    Errors.verifyNotZero(installerModule);\n\n    emit Genesis();\n\n    _aclManager = aclManager;\n\n    // Installer\n    _moduleLookup[Constants.MODULEID__INSTALLER] = installerModule;\n    address installerProxy = _createProxy(Constants.MODULEID__INSTALLER);\n    _trustedSenders[installerProxy].moduleImpl = installerModule;\n  }\n\n  string public constant NAME = 'Unlockd Protocol V2';\n\n  function moduleIdToImplementation(uint256 moduleId) external view returns (address) {\n    return _moduleLookup[moduleId];\n  }\n\n  function moduleIdToProxy(uint256 moduleId) external view returns (address) {\n    return _proxyLookup[moduleId];\n  }\n\n  function dispatch() external reentrantOK {\n    assembly {\n      // get moduleId and moduleImpl slot from trustedSenders mapping\n      mstore(0x00, caller())\n      mstore(0x20, _trustedSenders.slot)\n      let slot := sload(keccak256(0x00, 0x40))\n\n      // moduleId is the first 32 bits of the slot\n      let moduleId := and(slot, 0xFFFFFFFF)\n      // moduleImpl is the 160 bits after the first 32 bits\n      let moduleImpl := shr(96, shl(64, slot))\n\n      // if (moduleId == 0) revert Errors.InvalidParams();\n      if iszero(moduleId) {\n        mstore(0x00, 0xa86b6512)\n        revert(0x1c, 0x04)\n      }\n\n      // if (moduleImpl == address(0)) moduleImpl = _moduleLookup[moduleId];\n      if iszero(moduleImpl) {\n        mstore(0x00, moduleId)\n        mstore(0x20, _moduleLookup.slot)\n        moduleImpl := sload(keccak256(0x00, 0x40))\n      }\n\n      // if (msg.data.length < (4 + 4 + 20)) revert Errors.BaseInputToShort();\n      if lt(calldatasize(), 28) {\n        mstore(0x00, 0xa18d5bdc)\n        revert(0x1c, 0x04)\n      }\n\n      let payloadSize := sub(calldatasize(), 4)\n      calldatacopy(0, 4, payloadSize)\n      mstore(payloadSize, shl(96, caller()))\n\n      let result := delegatecall(gas(), moduleImpl, 0, add(payloadSize, 20), 0, 0)\n\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/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"
  }}