creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@openzeppelin/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"
      },
      "@openzeppelin/contracts/utils/math/SafeCast.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint248 from uint256, reverting on\n     * overflow (when the input is greater than largest uint248).\n     *\n     * Counterpart to Solidity's `uint248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint248(uint256 value) internal pure returns (uint248) {\n        require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n        return uint248(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint240 from uint256, reverting on\n     * overflow (when the input is greater than largest uint240).\n     *\n     * Counterpart to Solidity's `uint240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint240(uint256 value) internal pure returns (uint240) {\n        require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n        return uint240(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint232 from uint256, reverting on\n     * overflow (when the input is greater than largest uint232).\n     *\n     * Counterpart to Solidity's `uint232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint232(uint256 value) internal pure returns (uint232) {\n        require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n        return uint232(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint216 from uint256, reverting on\n     * overflow (when the input is greater than largest uint216).\n     *\n     * Counterpart to Solidity's `uint216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint216(uint256 value) internal pure returns (uint216) {\n        require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n        return uint216(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint208 from uint256, reverting on\n     * overflow (when the input is greater than largest uint208).\n     *\n     * Counterpart to Solidity's `uint208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint208(uint256 value) internal pure returns (uint208) {\n        require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n        return uint208(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint200 from uint256, reverting on\n     * overflow (when the input is greater than largest uint200).\n     *\n     * Counterpart to Solidity's `uint200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint200(uint256 value) internal pure returns (uint200) {\n        require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n        return uint200(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint192 from uint256, reverting on\n     * overflow (when the input is greater than largest uint192).\n     *\n     * Counterpart to Solidity's `uint192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint192(uint256 value) internal pure returns (uint192) {\n        require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n        return uint192(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint184 from uint256, reverting on\n     * overflow (when the input is greater than largest uint184).\n     *\n     * Counterpart to Solidity's `uint184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint184(uint256 value) internal pure returns (uint184) {\n        require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n        return uint184(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint176 from uint256, reverting on\n     * overflow (when the input is greater than largest uint176).\n     *\n     * Counterpart to Solidity's `uint176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint176(uint256 value) internal pure returns (uint176) {\n        require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n        return uint176(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint168 from uint256, reverting on\n     * overflow (when the input is greater than largest uint168).\n     *\n     * Counterpart to Solidity's `uint168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint168(uint256 value) internal pure returns (uint168) {\n        require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n        return uint168(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint160 from uint256, reverting on\n     * overflow (when the input is greater than largest uint160).\n     *\n     * Counterpart to Solidity's `uint160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint160(uint256 value) internal pure returns (uint160) {\n        require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n        return uint160(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint152 from uint256, reverting on\n     * overflow (when the input is greater than largest uint152).\n     *\n     * Counterpart to Solidity's `uint152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint152(uint256 value) internal pure returns (uint152) {\n        require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n        return uint152(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint144 from uint256, reverting on\n     * overflow (when the input is greater than largest uint144).\n     *\n     * Counterpart to Solidity's `uint144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint144(uint256 value) internal pure returns (uint144) {\n        require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n        return uint144(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint136 from uint256, reverting on\n     * overflow (when the input is greater than largest uint136).\n     *\n     * Counterpart to Solidity's `uint136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint136(uint256 value) internal pure returns (uint136) {\n        require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n        return uint136(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint120 from uint256, reverting on\n     * overflow (when the input is greater than largest uint120).\n     *\n     * Counterpart to Solidity's `uint120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint120(uint256 value) internal pure returns (uint120) {\n        require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n        return uint120(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint112 from uint256, reverting on\n     * overflow (when the input is greater than largest uint112).\n     *\n     * Counterpart to Solidity's `uint112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint112(uint256 value) internal pure returns (uint112) {\n        require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n        return uint112(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint104 from uint256, reverting on\n     * overflow (when the input is greater than largest uint104).\n     *\n     * Counterpart to Solidity's `uint104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint104(uint256 value) internal pure returns (uint104) {\n        require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n        return uint104(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.2._\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint88 from uint256, reverting on\n     * overflow (when the input is greater than largest uint88).\n     *\n     * Counterpart to Solidity's `uint88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint88(uint256 value) internal pure returns (uint88) {\n        require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n        return uint88(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint80 from uint256, reverting on\n     * overflow (when the input is greater than largest uint80).\n     *\n     * Counterpart to Solidity's `uint80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint80(uint256 value) internal pure returns (uint80) {\n        require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n        return uint80(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint72 from uint256, reverting on\n     * overflow (when the input is greater than largest uint72).\n     *\n     * Counterpart to Solidity's `uint72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint72(uint256 value) internal pure returns (uint72) {\n        require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n        return uint72(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint56 from uint256, reverting on\n     * overflow (when the input is greater than largest uint56).\n     *\n     * Counterpart to Solidity's `uint56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint56(uint256 value) internal pure returns (uint56) {\n        require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n        return uint56(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint48 from uint256, reverting on\n     * overflow (when the input is greater than largest uint48).\n     *\n     * Counterpart to Solidity's `uint48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint48(uint256 value) internal pure returns (uint48) {\n        require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n        return uint48(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint40 from uint256, reverting on\n     * overflow (when the input is greater than largest uint40).\n     *\n     * Counterpart to Solidity's `uint40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint40(uint256 value) internal pure returns (uint40) {\n        require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n        return uint40(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint24 from uint256, reverting on\n     * overflow (when the input is greater than largest uint24).\n     *\n     * Counterpart to Solidity's `uint24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toUint24(uint256 value) internal pure returns (uint24) {\n        require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n        return uint24(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v2.5._\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     *\n     * _Available since v3.0._\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value >= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int248 from int256, reverting on\n     * overflow (when the input is less than smallest int248 or\n     * greater than largest int248).\n     *\n     * Counterpart to Solidity's `int248` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 248 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt248(int256 value) internal pure returns (int248 downcasted) {\n        downcasted = int248(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int240 from int256, reverting on\n     * overflow (when the input is less than smallest int240 or\n     * greater than largest int240).\n     *\n     * Counterpart to Solidity's `int240` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 240 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt240(int256 value) internal pure returns (int240 downcasted) {\n        downcasted = int240(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int232 from int256, reverting on\n     * overflow (when the input is less than smallest int232 or\n     * greater than largest int232).\n     *\n     * Counterpart to Solidity's `int232` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 232 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt232(int256 value) internal pure returns (int232 downcasted) {\n        downcasted = int232(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int224 from int256, reverting on\n     * overflow (when the input is less than smallest int224 or\n     * greater than largest int224).\n     *\n     * Counterpart to Solidity's `int224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt224(int256 value) internal pure returns (int224 downcasted) {\n        downcasted = int224(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int216 from int256, reverting on\n     * overflow (when the input is less than smallest int216 or\n     * greater than largest int216).\n     *\n     * Counterpart to Solidity's `int216` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 216 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt216(int256 value) internal pure returns (int216 downcasted) {\n        downcasted = int216(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int208 from int256, reverting on\n     * overflow (when the input is less than smallest int208 or\n     * greater than largest int208).\n     *\n     * Counterpart to Solidity's `int208` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 208 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt208(int256 value) internal pure returns (int208 downcasted) {\n        downcasted = int208(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int200 from int256, reverting on\n     * overflow (when the input is less than smallest int200 or\n     * greater than largest int200).\n     *\n     * Counterpart to Solidity's `int200` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 200 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt200(int256 value) internal pure returns (int200 downcasted) {\n        downcasted = int200(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int192 from int256, reverting on\n     * overflow (when the input is less than smallest int192 or\n     * greater than largest int192).\n     *\n     * Counterpart to Solidity's `int192` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 192 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt192(int256 value) internal pure returns (int192 downcasted) {\n        downcasted = int192(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int184 from int256, reverting on\n     * overflow (when the input is less than smallest int184 or\n     * greater than largest int184).\n     *\n     * Counterpart to Solidity's `int184` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 184 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt184(int256 value) internal pure returns (int184 downcasted) {\n        downcasted = int184(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int176 from int256, reverting on\n     * overflow (when the input is less than smallest int176 or\n     * greater than largest int176).\n     *\n     * Counterpart to Solidity's `int176` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 176 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt176(int256 value) internal pure returns (int176 downcasted) {\n        downcasted = int176(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int168 from int256, reverting on\n     * overflow (when the input is less than smallest int168 or\n     * greater than largest int168).\n     *\n     * Counterpart to Solidity's `int168` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 168 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt168(int256 value) internal pure returns (int168 downcasted) {\n        downcasted = int168(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int160 from int256, reverting on\n     * overflow (when the input is less than smallest int160 or\n     * greater than largest int160).\n     *\n     * Counterpart to Solidity's `int160` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 160 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt160(int256 value) internal pure returns (int160 downcasted) {\n        downcasted = int160(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int152 from int256, reverting on\n     * overflow (when the input is less than smallest int152 or\n     * greater than largest int152).\n     *\n     * Counterpart to Solidity's `int152` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 152 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt152(int256 value) internal pure returns (int152 downcasted) {\n        downcasted = int152(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int144 from int256, reverting on\n     * overflow (when the input is less than smallest int144 or\n     * greater than largest int144).\n     *\n     * Counterpart to Solidity's `int144` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 144 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt144(int256 value) internal pure returns (int144 downcasted) {\n        downcasted = int144(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int136 from int256, reverting on\n     * overflow (when the input is less than smallest int136 or\n     * greater than largest int136).\n     *\n     * Counterpart to Solidity's `int136` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 136 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt136(int256 value) internal pure returns (int136 downcasted) {\n        downcasted = int136(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128 downcasted) {\n        downcasted = int128(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int120 from int256, reverting on\n     * overflow (when the input is less than smallest int120 or\n     * greater than largest int120).\n     *\n     * Counterpart to Solidity's `int120` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 120 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt120(int256 value) internal pure returns (int120 downcasted) {\n        downcasted = int120(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int112 from int256, reverting on\n     * overflow (when the input is less than smallest int112 or\n     * greater than largest int112).\n     *\n     * Counterpart to Solidity's `int112` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 112 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt112(int256 value) internal pure returns (int112 downcasted) {\n        downcasted = int112(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int104 from int256, reverting on\n     * overflow (when the input is less than smallest int104 or\n     * greater than largest int104).\n     *\n     * Counterpart to Solidity's `int104` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 104 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt104(int256 value) internal pure returns (int104 downcasted) {\n        downcasted = int104(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int96 from int256, reverting on\n     * overflow (when the input is less than smallest int96 or\n     * greater than largest int96).\n     *\n     * Counterpart to Solidity's `int96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt96(int256 value) internal pure returns (int96 downcasted) {\n        downcasted = int96(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int88 from int256, reverting on\n     * overflow (when the input is less than smallest int88 or\n     * greater than largest int88).\n     *\n     * Counterpart to Solidity's `int88` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 88 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt88(int256 value) internal pure returns (int88 downcasted) {\n        downcasted = int88(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int80 from int256, reverting on\n     * overflow (when the input is less than smallest int80 or\n     * greater than largest int80).\n     *\n     * Counterpart to Solidity's `int80` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 80 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt80(int256 value) internal pure returns (int80 downcasted) {\n        downcasted = int80(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int72 from int256, reverting on\n     * overflow (when the input is less than smallest int72 or\n     * greater than largest int72).\n     *\n     * Counterpart to Solidity's `int72` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 72 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt72(int256 value) internal pure returns (int72 downcasted) {\n        downcasted = int72(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64 downcasted) {\n        downcasted = int64(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int56 from int256, reverting on\n     * overflow (when the input is less than smallest int56 or\n     * greater than largest int56).\n     *\n     * Counterpart to Solidity's `int56` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 56 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt56(int256 value) internal pure returns (int56 downcasted) {\n        downcasted = int56(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int48 from int256, reverting on\n     * overflow (when the input is less than smallest int48 or\n     * greater than largest int48).\n     *\n     * Counterpart to Solidity's `int48` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 48 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt48(int256 value) internal pure returns (int48 downcasted) {\n        downcasted = int48(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int40 from int256, reverting on\n     * overflow (when the input is less than smallest int40 or\n     * greater than largest int40).\n     *\n     * Counterpart to Solidity's `int40` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 40 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt40(int256 value) internal pure returns (int40 downcasted) {\n        downcasted = int40(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32 downcasted) {\n        downcasted = int32(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int24 from int256, reverting on\n     * overflow (when the input is less than smallest int24 or\n     * greater than largest int24).\n     *\n     * Counterpart to Solidity's `int24` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 24 bits\n     *\n     * _Available since v4.7._\n     */\n    function toInt24(int256 value) internal pure returns (int24 downcasted) {\n        downcasted = int24(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16 downcasted) {\n        downcasted = int16(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8 downcasted) {\n        downcasted = int8(value);\n        require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     *\n     * _Available since v3.0._\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n"
      },
      "contracts/interfaces/ILiquidity.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/**\n * @title Interface to Liquidity state\n */\ninterface ILiquidity {\n    /**************************************************************************/\n    /* Errors */\n    /**************************************************************************/\n\n    /**\n     * @notice Insufficient liquidity\n     */\n    error InsufficientLiquidity();\n\n    /**\n     * @notice Inactive liquidity\n     */\n    error InactiveLiquidity();\n\n    /**\n     * @notice Insufficient tick spacing\n     */\n    error InsufficientTickSpacing();\n\n    /**************************************************************************/\n    /* Structures */\n    /**************************************************************************/\n\n    /**\n     * @notice Flattened liquidity node returned by getter\n     * @param tick Tick\n     * @param value Liquidity value\n     * @param shares Liquidity shares outstanding\n     * @param available Liquidity available\n     * @param pending Liquidity pending (with interest)\n     * @param redemptions Total pending redemptions\n     * @param prev Previous liquidity node\n     * @param next Next liquidity node\n     */\n    struct NodeInfo {\n        uint128 tick;\n        uint128 value;\n        uint128 shares;\n        uint128 available;\n        uint128 pending;\n        uint128 redemptions;\n        uint128 prev;\n        uint128 next;\n    }\n\n    /**\n     * @notice Accrual info returned by getter\n     * @param accrued Accrued interest\n     * @param rate Accrual rate\n     * @param timestamp Accrual timestamp\n     */\n    struct AccrualInfo {\n        uint128 accrued;\n        uint64 rate;\n        uint64 timestamp;\n    }\n\n    /**************************************************************************/\n    /* API */\n    /**************************************************************************/\n\n    /**\n     * Get liquidity nodes spanning [startTick, endTick] range\n     * @param startTick Start tick\n     * @param endTick End tick\n     * @return Liquidity nodes\n     */\n    function liquidityNodes(uint128 startTick, uint128 endTick) external view returns (NodeInfo[] memory);\n\n    /**\n     * Get liquidity node at tick\n     * @param tick Tick\n     * @return Liquidity node\n     */\n    function liquidityNode(uint128 tick) external view returns (NodeInfo memory);\n\n    /**\n     * Get liquidity node with accrual info at tick\n     * @param tick Tick\n     * @return Liquidity node, Accrual info\n     */\n    function liquidityNodeWithAccrual(uint128 tick) external view returns (NodeInfo memory, AccrualInfo memory);\n\n    /**\n     * @notice Get deposit share price\n     * @param tick Tick\n     * @return Deposit share price\n     */\n    function depositSharePrice(uint128 tick) external view returns (uint256);\n\n    /**\n     * @notice Get redemption share price\n     * @param tick Tick\n     * @return Redemption share price\n     */\n    function redemptionSharePrice(uint128 tick) external view returns (uint256);\n}\n"
      },
      "contracts/LiquidityLogic.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.20;\n\nimport \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\n\nimport \"./interfaces/ILiquidity.sol\";\nimport \"./Tick.sol\";\n\n/**\n * @title Liquidity Logic\n * @author MetaStreet Labs\n */\nlibrary LiquidityLogic {\n    /*\n     * Liquidity nodes are arranged in a linked-list that starts with a zero\n     * sentinel and ends with an end sentinel. There are two types of ticks, namely,\n     * ratio ticks and absolute ticks (see more in Tick.sol). In the linked-list,\n     * ratio ticks are ordered before absolute ticks. Within the types, they are\n     * ordered in ascending order of their tick values.\n     *\n     * +--------------------------------------------------------------------+\n     * |                         Linked-List Layout                         |\n     * +----------------------------------|------------------|--------------+\n     * |       0       | (Limit Type = 1) | (Limit Type = 0) | Max. uint128 |\n     * | Zero Sentinel |   Ratio Ticks    |  Absolute Ticks  | End Sentinel |\n     * +--------------------------------------------------------------------+\n     *\n     */\n\n    using SafeCast for uint256;\n\n    /**************************************************************************/\n    /* Constants */\n    /**************************************************************************/\n\n    /**\n     * @notice Tick limit spacing basis points for absolute type (10%)\n     */\n    uint256 internal constant ABSOLUTE_TICK_LIMIT_SPACING_BASIS_POINTS = 1000;\n\n    /**\n     * @notice Tick limit spacing basis points for ratio type (5%)\n     */\n    uint256 internal constant RATIO_TICK_LIMIT_SPACING_BASIS_POINTS = 500;\n\n    /**\n     * @notice Fixed point scale\n     */\n    uint256 internal constant FIXED_POINT_SCALE = 1e18;\n\n    /**\n     * @notice Basis points scale\n     */\n    uint256 internal constant BASIS_POINTS_SCALE = 10_000;\n\n    /**\n     * @notice Impaired price threshold (5%)\n     */\n    uint256 internal constant IMPAIRED_PRICE_THRESHOLD = 0.05 * 1e18;\n\n    /**\n     * @notice Max ticks used count\n     */\n    uint256 private constant MAX_TICKS_USED_COUNT = 32;\n\n    /**\n     * @notice Max redemption queue scan count\n     */\n    uint256 private constant MAX_REDEMPTION_QUEUE_SCAN_COUNT = 150;\n\n    /**\n     * @notice Amount of shares to lock for initial deposit\n     */\n    uint128 private constant LOCKED_SHARES = 1e6;\n\n    /**************************************************************************/\n    /* Structures */\n    /**************************************************************************/\n\n    /**\n     * @notice Node source\n     * @param tick Tick\n     * @param used Amount used\n     * @param pending Amount pending\n     */\n    struct NodeSource {\n        uint128 tick;\n        uint128 used;\n        uint128 pending;\n    }\n\n    /**\n     * @notice Fulfilled redemption\n     * @param shares Shares redeemed\n     * @param amount Amount redeemed\n     */\n    struct FulfilledRedemption {\n        uint128 shares;\n        uint128 amount;\n    }\n\n    /**\n     * @notice Redemption state\n     * @param pending Pending shares\n     * @param index Current index\n     * @param fulfilled Fulfilled redemptions\n     */\n    struct Redemptions {\n        uint128 pending;\n        uint128 index;\n        mapping(uint128 => FulfilledRedemption) fulfilled;\n    }\n\n    /**\n     * @notice Accrual state\n     * @param accrued Accrued interest\n     * @param rate Accrual rate\n     * @param timestamp Last accrual timestamp\n     */\n    struct Accrual {\n        uint128 accrued;\n        uint64 rate;\n        uint64 timestamp;\n    }\n\n    /**\n     * @notice Liquidity node\n     * @param value Liquidity value\n     * @param shares Liquidity shares outstanding\n     * @param available Liquidity available\n     * @param pending Liquidity pending (with interest)\n     * @param prev Previous liquidity node\n     * @param next Next liquidity node\n     * @param redemption Redemption state\n     * @param accrual Accrual state\n     */\n    struct Node {\n        uint128 value;\n        uint128 shares;\n        uint128 available;\n        uint128 pending;\n        uint128 prev;\n        uint128 next;\n        Redemptions redemptions;\n        Accrual accrual;\n    }\n\n    /**\n     * @notice Liquidity state\n     * @param nodes Liquidity nodes\n     */\n    struct Liquidity {\n        mapping(uint256 => Node) nodes;\n    }\n\n    /**************************************************************************/\n    /* Getters */\n    /**************************************************************************/\n\n    /**\n     * Get liquidity node at tick\n     * @param liquidity Liquidity state\n     * @param tick Tick\n     * @return Liquidity node\n     */\n    function liquidityNode(Liquidity storage liquidity, uint128 tick) public view returns (ILiquidity.NodeInfo memory) {\n        Node storage node = liquidity.nodes[tick];\n\n        return\n            ILiquidity.NodeInfo({\n                tick: tick,\n                value: node.value,\n                shares: node.shares,\n                available: node.available,\n                pending: node.pending,\n                redemptions: node.redemptions.pending,\n                prev: node.prev,\n                next: node.next\n            });\n    }\n\n    /**\n     * @notice Count liquidity nodes spanning [startTick, endTick] range, where\n     * startTick is 0 or an instantiated tick\n     * @param liquidity Liquidity state\n     * @param startTick Start tick\n     * @param endTick End tick\n     * @return count Liquidity nodes count\n     */\n    function liquidityNodesCount(\n        Liquidity storage liquidity,\n        uint128 startTick,\n        uint128 endTick\n    ) public view returns (uint256 count) {\n        /* Validate start tick has active liquidity */\n        if (liquidity.nodes[startTick].next == 0) revert ILiquidity.InactiveLiquidity();\n\n        /* Count nodes */\n        uint256 t = startTick;\n        while (t != type(uint128).max && t <= endTick) {\n            t = liquidity.nodes[t].next;\n            count++;\n        }\n    }\n\n    /**\n     * @notice Get liquidity nodes spanning [startTick, endTick] range, where\n     * startTick is 0 or an instantiated tick\n     * @param liquidity Liquidity state\n     * @param startTick Start tick\n     * @param endTick End tick\n     * @return Liquidity nodes\n     */\n    function liquidityNodes(\n        Liquidity storage liquidity,\n        uint128 startTick,\n        uint128 endTick\n    ) external view returns (ILiquidity.NodeInfo[] memory) {\n        ILiquidity.NodeInfo[] memory nodes = new ILiquidity.NodeInfo[](\n            liquidityNodesCount(liquidity, startTick, endTick)\n        );\n\n        /* Populate nodes */\n        uint256 i;\n        uint128 t = startTick;\n        while (t != type(uint128).max && t <= endTick) {\n            nodes[i] = liquidityNode(liquidity, t);\n            t = nodes[i++].next;\n        }\n\n        return nodes;\n    }\n\n    /**\n     * @notice Get liquidity node with accrual info at tick\n     * @param liquidity Liquidity state\n     * @param tick Tick\n     * @return Liquidity node, Accrual info\n     */\n    function liquidityNodeWithAccrual(\n        Liquidity storage liquidity,\n        uint128 tick\n    ) external view returns (ILiquidity.NodeInfo memory, ILiquidity.AccrualInfo memory) {\n        Node storage node = liquidity.nodes[tick];\n\n        return (\n            ILiquidity.NodeInfo({\n                tick: tick,\n                value: node.value,\n                shares: node.shares,\n                available: node.available,\n                pending: node.pending,\n                redemptions: node.redemptions.pending,\n                prev: node.prev,\n                next: node.next\n            }),\n            ILiquidity.AccrualInfo({\n                accrued: node.accrual.accrued,\n                rate: node.accrual.rate,\n                timestamp: node.accrual.timestamp\n            })\n        );\n    }\n\n    /**\n     * @notice Get redemption available amount\n     * @param liquidity Liquidity state\n     * @param tick Tick\n     * @param pending Redemption pending\n     * @param index Redemption index\n     * @param target Redemption target\n     * @return redeemedShares Redeemed shares\n     * @return redeemedAmount Redeemed amount\n     * @return processedIndices Processed indices\n     * @return processedShares Processed shares\n     */\n    function redemptionAvailable(\n        Liquidity storage liquidity,\n        uint128 tick,\n        uint128 pending,\n        uint128 index,\n        uint128 target\n    )\n        internal\n        view\n        returns (uint128 redeemedShares, uint128 redeemedAmount, uint128 processedIndices, uint128 processedShares)\n    {\n        Node storage node = liquidity.nodes[tick];\n\n        uint256 stopIndex = index + MAX_REDEMPTION_QUEUE_SCAN_COUNT;\n\n        for (; processedShares < target + pending && index < stopIndex; index++) {\n            if (index == node.redemptions.index) {\n                /* Reached pending unfulfilled redemption */\n                break;\n            }\n\n            /* Look up the next fulfilled redemption */\n            FulfilledRedemption storage redemption = node.redemptions.fulfilled[index];\n\n            /* Update processed count */\n            processedIndices += 1;\n            processedShares += redemption.shares;\n\n            if (processedShares <= target) {\n                /* Have not reached the redemption queue position yet */\n                continue;\n            } else {\n                /* Compute number of shares to redeem in range of this\n                 * redemption batch */\n                uint128 shares = (((processedShares > target + pending) ? pending : (processedShares - target))) -\n                    redeemedShares;\n                /* Compute price of shares in this redemption batch */\n                uint256 price = (redemption.amount * FIXED_POINT_SCALE) / redemption.shares;\n\n                /* Accumulate redeemed shares and corresponding amount */\n                redeemedShares += shares;\n                redeemedAmount += Math.mulDiv(shares, price, FIXED_POINT_SCALE).toUint128();\n            }\n        }\n    }\n\n    /**\n     * @notice Get deposit share price\n     * @param liquidity Liquidity state\n     * @param tick Tick\n     * @return Deposit share price\n     */\n    function depositSharePrice(Liquidity storage liquidity, uint128 tick) external view returns (uint256) {\n        Node storage node = liquidity.nodes[tick];\n\n        /* Simulate accrual */\n        uint128 accrued = node.accrual.accrued + node.accrual.rate * uint128(block.timestamp - node.accrual.timestamp);\n\n        /* Return deposit price */\n        return\n            node.shares == 0\n                ? FIXED_POINT_SCALE\n                : (Math.min(node.value + accrued, node.available + node.pending) * FIXED_POINT_SCALE) / node.shares;\n    }\n\n    /**\n     * @notice Get redemption share price\n     * @param liquidity Liquidity state\n     * @param tick Tick\n     * @return Redemption share price\n     */\n    function redemptionSharePrice(Liquidity storage liquidity, uint128 tick) external view returns (uint256) {\n        Node storage node = liquidity.nodes[tick];\n\n        /* Revert if node is empty */\n        if (node.value == 0 || node.shares == 0) revert ILiquidity.InactiveLiquidity();\n\n        /* Return redemption price */\n        return (node.value * FIXED_POINT_SCALE) / node.shares;\n    }\n\n    /**************************************************************************/\n    /* Internal Helpers */\n    /**************************************************************************/\n\n    /**\n     * @dev Check if tick is reserved\n     * @param tick Tick\n     * @return True if reserved, otherwise false\n     */\n    function _isReserved(uint128 tick) internal pure returns (bool) {\n        return tick == 0 || tick == type(uint128).max;\n    }\n\n    /**\n     * @dev Check if liquidity node is empty\n     * @param node Liquidity node\n     * @return True if empty, otherwise false\n     */\n    function _isEmpty(Node storage node) internal view returns (bool) {\n        return node.shares <= LOCKED_SHARES && node.pending == 0;\n    }\n\n    /**\n     * @dev Check if liquidity node is active\n     * @param node Liquidity node\n     * @return True if active, otherwise false\n     */\n    function _isActive(Node storage node) internal view returns (bool) {\n        return node.prev != 0 || node.next != 0;\n    }\n\n    /**\n     * @dev Check if liquidity node is impaired\n     * @param node Liquidity node\n     * @return True if impaired, otherwise false\n     */\n    function _isImpaired(Node storage node) internal view returns (bool) {\n        /* If there's shares, but insufficient value for a stable share price */\n        return node.shares != 0 && node.value * FIXED_POINT_SCALE < node.shares * IMPAIRED_PRICE_THRESHOLD;\n    }\n\n    /**\n     * @notice Instantiate liquidity\n     * @param liquidity Liquidity state\n     * @param node Liquidity node\n     * @param tick Tick\n     */\n    function _instantiate(Liquidity storage liquidity, Node storage node, uint128 tick) internal {\n        /* If node is active, do nothing */\n        if (_isActive(node)) return;\n        /* If node is inactive and not empty, revert */\n        if (!_isEmpty(node)) revert ILiquidity.InactiveLiquidity();\n\n        /* Instantiate previous tick and previous node */\n        uint128 prevTick;\n        Node storage prevNode = liquidity.nodes[prevTick];\n\n        /* Decode limit and limit type from new tick and next tick */\n        (uint256 newLimit, , , Tick.LimitType newLimitType) = Tick.decode(tick, BASIS_POINTS_SCALE);\n        (uint256 nextLimit, , , Tick.LimitType nextLimitType) = Tick.decode(prevNode.next, BASIS_POINTS_SCALE);\n\n        /* Find prior node to new tick */\n        bool isAbsoluteType = newLimitType == Tick.LimitType.Absolute;\n        while (nextLimitType == newLimitType ? nextLimit < newLimit : isAbsoluteType) {\n            prevTick = prevNode.next;\n            prevNode = liquidity.nodes[prevTick];\n\n            /* Decode limit and limit type from next tick */\n            (nextLimit, , , nextLimitType) = Tick.decode(prevNode.next, BASIS_POINTS_SCALE);\n        }\n\n        /* Decode limit and limit type from prev tick */\n        (uint256 prevLimit, , , Tick.LimitType prevLimitType) = Tick.decode(prevTick, BASIS_POINTS_SCALE);\n\n        /* Validate tick limit spacing */\n        if (isAbsoluteType) {\n            /* Validate new absolute limit */\n            if (\n                newLimit != prevLimit &&\n                prevLimitType == Tick.LimitType.Absolute &&\n                newLimit <\n                (prevLimit * (BASIS_POINTS_SCALE + ABSOLUTE_TICK_LIMIT_SPACING_BASIS_POINTS)) / BASIS_POINTS_SCALE\n            ) revert ILiquidity.InsufficientTickSpacing();\n            if (\n                newLimit != nextLimit &&\n                nextLimitType == Tick.LimitType.Absolute &&\n                nextLimit <\n                (newLimit * (BASIS_POINTS_SCALE + ABSOLUTE_TICK_LIMIT_SPACING_BASIS_POINTS)) / BASIS_POINTS_SCALE\n            ) revert ILiquidity.InsufficientTickSpacing();\n        } else {\n            /* Validate new ratio limit */\n            if (\n                newLimit != prevLimit &&\n                prevLimitType == Tick.LimitType.Ratio &&\n                newLimit < (prevLimit + RATIO_TICK_LIMIT_SPACING_BASIS_POINTS)\n            ) revert ILiquidity.InsufficientTickSpacing();\n            if (\n                newLimit != nextLimit &&\n                nextLimitType == Tick.LimitType.Ratio &&\n                nextLimit < (newLimit + RATIO_TICK_LIMIT_SPACING_BASIS_POINTS)\n            ) revert ILiquidity.InsufficientTickSpacing();\n        }\n\n        /* Link new node */\n        node.prev = prevTick;\n        node.next = prevNode.next;\n        liquidity.nodes[prevNode.next].prev = tick;\n        prevNode.next = tick;\n    }\n\n    /**\n     * @dev Garbage collect an impaired or empty node, unlinking it from active\n     * liquidity\n     * @param liquidity Liquidity state\n     * @param node Liquidity node\n     */\n    function _garbageCollect(Liquidity storage liquidity, Node storage node) internal {\n        /* If node is not impaired and not empty, or already inactive, do nothing */\n        if ((!_isImpaired(node) && !_isEmpty(node)) || !_isActive(node)) return;\n\n        /* Make node inactive by unlinking it */\n        liquidity.nodes[node.prev].next = node.next;\n        liquidity.nodes[node.next].prev = node.prev;\n        node.next = 0;\n        node.prev = 0;\n    }\n\n    /**\n     * @notice Process redemptions from available liquidity\n     * @param liquidity Liquidity state\n     * @param node Liquidity node\n     */\n    function _processRedemptions(Liquidity storage liquidity, Node storage node) internal {\n        /* If there's no pending shares to redeem */\n        if (node.redemptions.pending == 0) return;\n\n        /* Compute redemption price */\n        uint256 price = (node.value * FIXED_POINT_SCALE) / node.shares;\n\n        if (price == 0) {\n            /* If node has pending interest */\n            if (node.pending != 0) return;\n\n            /* If node is insolvent, redeem all shares for zero amount */\n            uint128 shares = node.redemptions.pending;\n\n            /* Record fulfilled redemption */\n            node.redemptions.fulfilled[node.redemptions.index++] = FulfilledRedemption({shares: shares, amount: 0});\n\n            /* Update node state */\n            node.shares -= shares;\n            node.value = 0;\n            node.available = 0;\n            node.redemptions.pending = 0;\n\n            return;\n        } else {\n            /* Node is solvent */\n\n            /* If there's no cash to redeem from */\n            if (node.available == 0) return;\n\n            /* Redeem as many shares as possible and pending from available cash */\n            uint128 shares = uint128(Math.min((node.available * FIXED_POINT_SCALE) / price, node.redemptions.pending));\n            uint128 amount = Math.mulDiv(shares, price, FIXED_POINT_SCALE).toUint128();\n\n            /* If there's insufficient cash to redeem non-zero pending shares\n             * at current price */\n            if (shares == 0) return;\n\n            /* Record fulfilled redemption */\n            node.redemptions.fulfilled[node.redemptions.index++] = FulfilledRedemption({\n                shares: shares,\n                amount: amount\n            });\n\n            /* Update node state */\n            node.shares -= shares;\n            node.value -= amount;\n            node.available -= amount;\n            node.redemptions.pending -= shares;\n\n            /* Garbage collect node if it is now empty */\n            _garbageCollect(liquidity, node);\n\n            return;\n        }\n    }\n\n    /**\n     * @notice Process accrued value from accrual rate and timestamp\n     * @param node Liquidity node\n     */\n    function _accrue(Node storage node) internal {\n        node.accrual.accrued += node.accrual.rate * uint128(block.timestamp - node.accrual.timestamp);\n        node.accrual.timestamp = uint64(block.timestamp);\n    }\n\n    /**************************************************************************/\n    /* Primary API */\n    /**************************************************************************/\n\n    /**\n     * @notice Initialize liquidity state\n     * @param liquidity Liquidity state\n     */\n    function initialize(Liquidity storage liquidity) internal {\n        /* Liquidity state defaults to zero, but need to make head and tail nodes */\n        liquidity.nodes[0].next = type(uint128).max;\n        /* liquidity.nodes[type(uint128).max].prev = 0 by default */\n    }\n\n    /**\n     * @notice Deposit liquidity\n     * @param liquidity Liquidity state\n     * @param tick Tick\n     * @param amount Amount\n     * @return Number of shares\n     */\n    function deposit(Liquidity storage liquidity, uint128 tick, uint128 amount) internal returns (uint128) {\n        Node storage node = liquidity.nodes[tick];\n\n        /* If tick is reserved */\n        if (_isReserved(tick)) revert ILiquidity.InactiveLiquidity();\n\n        /* Instantiate node, if necessary */\n        _instantiate(liquidity, node, tick);\n\n        /* Process accrual */\n        _accrue(node);\n\n        /* Compute deposit price */\n        uint256 price = node.shares == 0\n            ? FIXED_POINT_SCALE\n            : (Math.min(node.value + node.accrual.accrued, node.available + node.pending) * FIXED_POINT_SCALE) /\n                node.shares;\n\n        /* Compute shares and depositor's shares */\n        uint128 shares = ((amount * FIXED_POINT_SCALE) / price).toUint128();\n\n        /* If this is the initial deposit, lock subset of shares */\n        bool initialDeposit = node.shares < LOCKED_SHARES;\n\n        node.value += amount;\n        node.shares += shares;\n        node.available += amount;\n\n        /* Process any pending redemptions from available cash */\n        _processRedemptions(liquidity, node);\n\n        return initialDeposit ? shares - LOCKED_SHARES : shares;\n    }\n\n    /**\n     * @notice Use liquidity from node\n     * @param liquidity Liquidity state\n     * @param tick Tick\n     * @param used Used amount\n     * @param pending Pending amount\n     * @param duration Duration\n     */\n    function use(Liquidity storage liquidity, uint128 tick, uint128 used, uint128 pending, uint64 duration) internal {\n        Node storage node = liquidity.nodes[tick];\n\n        node.available -= used;\n        node.pending += pending;\n\n        /* Process accrual */\n        _accrue(node);\n        /* Increment accrual rate */\n        uint256 rate = uint256(pending - used) / duration;\n        node.accrual.rate += rate.toUint64();\n    }\n\n    /**\n     * @notice Restore liquidity and process pending redemptions\n     * @param liquidity Liquidity state\n     * @param tick Tick\n     * @param used Used amount\n     * @param pending Pending amount\n     * @param restored Restored amount\n     * @param duration Duration\n     * @param elapsed Elapsed time since loan origination\n     */\n    function restore(\n        Liquidity storage liquidity,\n        uint128 tick,\n        uint128 used,\n        uint128 pending,\n        uint128 restored,\n        uint64 duration,\n        uint64 elapsed\n    ) internal {\n        Node storage node = liquidity.nodes[tick];\n\n        node.value = node.value - used + restored;\n        node.available += restored;\n        node.pending -= pending;\n\n        /* Garbage collect node if it is now impaired */\n        _garbageCollect(liquidity, node);\n\n        /* Process any pending redemptions */\n        _processRedemptions(liquidity, node);\n\n        /* Process accrual */\n        _accrue(node);\n        /* Decrement accrual rate and accrued */\n        uint256 rate = uint256(pending - used) / duration;\n        node.accrual.rate -= rate.toUint64();\n        node.accrual.accrued -= uint128(rate * elapsed);\n    }\n\n    /**\n     * @notice Redeem liquidity\n     * @param liquidity Liquidity state\n     * @param tick Tick\n     * @param shares Shares\n     * @return Redemption index, Redemption target\n     */\n    function redeem(Liquidity storage liquidity, uint128 tick, uint128 shares) internal returns (uint128, uint128) {\n        Node storage node = liquidity.nodes[tick];\n\n        /* Redemption from inactive liquidity nodes is allowed to facilitate\n         * restoring garbage collected nodes */\n\n        /* Snapshot redemption target */\n        uint128 redemptionIndex = node.redemptions.index;\n        uint128 redemptionTarget = node.redemptions.pending;\n\n        /* Add shares to pending redemptions */\n        node.redemptions.pending += shares;\n\n        /* Initialize redemption record to save gas in loan callbacks */\n        if (node.redemptions.fulfilled[redemptionIndex].shares != type(uint128).max) {\n            node.redemptions.fulfilled[redemptionIndex] = FulfilledRedemption({shares: type(uint128).max, amount: 0});\n        }\n\n        /* Process any pending redemptions from available cash */\n        _processRedemptions(liquidity, node);\n\n        return (redemptionIndex, redemptionTarget);\n    }\n\n    /**\n     * @notice Source liquidity from nodes\n     * @param liquidity Liquidity state\n     * @param amount Amount\n     * @param ticks Ticks to source from\n     * @param multiplier Multiplier for amount\n     * @param durationIndex Duration index for amount\n     * @param oraclePrice Collateral token price from price oracle, if any\n     * @return Sourced liquidity nodes, count of nodes\n     */\n    function source(\n        Liquidity storage liquidity,\n        uint256 amount,\n        uint128[] calldata ticks,\n        uint256 multiplier,\n        uint256 durationIndex,\n        uint256 oraclePrice\n    ) internal view returns (NodeSource[] memory, uint16) {\n        NodeSource[] memory sources = new NodeSource[](ticks.length);\n\n        uint128 prevTick;\n        uint256 taken;\n        uint256 count;\n        for (; count < ticks.length && taken != amount; count++) {\n            uint128 tick = ticks[count];\n\n            /* Validate tick and decode limit */\n            uint256 limit = Tick.validate(tick, prevTick, durationIndex, oraclePrice);\n\n            /* Look up liquidity node */\n            Node storage node = liquidity.nodes[tick];\n\n            /* Consume as much as possible up to the tick limit, amount available, and amount remaining */\n            uint128 take = uint128(Math.min(Math.min(limit * multiplier - taken, node.available), amount - taken));\n\n            /* Record the liquidity allocation in our sources list */\n            sources[count] = NodeSource({tick: tick, used: take, pending: 0});\n\n            taken += take;\n            prevTick = tick;\n        }\n\n        /* If unable to source required liquidity amount from provided ticks */\n        if (taken < amount) revert ILiquidity.InsufficientLiquidity();\n\n        /* If count exceeds max number of ticks */\n        if (count > MAX_TICKS_USED_COUNT) revert ILiquidity.InsufficientLiquidity();\n\n        return (sources, count.toUint16());\n    }\n}\n"
      },
      "contracts/Tick.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.20;\n\nimport \"@openzeppelin/contracts/utils/math/Math.sol\";\n\n/**\n * @title Tick\n * @author MetaStreet Labs\n */\nlibrary Tick {\n    /*\n     * A tick encodes three conditions on liquidity: limit, duration, rate, and type.\n     * Limit is the maximum depth that liquidity sourced from the node can be\n     * used in. Duration is the maximum allowed duration for that liquidity.\n     * Rate is the interest rate associated with that liquidity. Duration and\n     * rates are encoded as indexes into predetermined, discrete tiers. Type is the\n     * type of limit, which could either be absolute or ratio-based.\n     *\n     * +---------------------------------------------------------------------+\n     * |                                 128                                 |\n     * +--------------------------------------|----------|----------|--------+\n     * |                  120                 |    3     |     3    |    2   |\n     * |                 Limit                | Dur. Idx | Rate Idx |  Type  |\n     * +---------------------------------------------------------------------+\n     *\n     * Duration Index is ordered from longest duration to shortest, e.g. 30\n     * days, 14 days, 7 days.\n     *\n     * Rate Index is ordered from lowest rate to highest rate, e.g. 10%, 30%,\n     * 50%.\n     */\n\n    /**************************************************************************/\n    /* Structures */\n    /**************************************************************************/\n\n    /**\n     * @notice Limit type\n     */\n    enum LimitType {\n        Absolute,\n        Ratio\n    }\n\n    /**************************************************************************/\n    /* Constants */\n    /**************************************************************************/\n\n    /**\n     * @notice Tick limit mask\n     */\n    uint256 internal constant TICK_LIMIT_MASK = 0xffffffffffffffffffffffffffffff;\n\n    /**\n     * @notice Tick limit shift\n     */\n    uint256 internal constant TICK_LIMIT_SHIFT = 8;\n\n    /**\n     * @notice Tick duration index mask\n     */\n    uint256 internal constant TICK_DURATION_MASK = 0x7;\n\n    /**\n     * @notice Tick duration index shift\n     */\n    uint256 internal constant TICK_DURATION_SHIFT = 5;\n\n    /**\n     * @notice Tick rate index mask\n     */\n    uint256 internal constant TICK_RATE_MASK = 0x7;\n\n    /**\n     * @notice Tick rate index shift\n     */\n    uint256 internal constant TICK_RATE_SHIFT = 2;\n\n    /**\n     * @notice Tick limit type mask\n     */\n    uint256 internal constant TICK_LIMIT_TYPE_MASK = 0x3;\n\n    /**\n     * @notice Maximum number of durations supported\n     */\n    uint256 internal constant MAX_NUM_DURATIONS = TICK_DURATION_MASK + 1;\n\n    /**\n     * @notice Maximum number of rates supported\n     */\n    uint256 internal constant MAX_NUM_RATES = TICK_RATE_MASK + 1;\n\n    /**\n     * @notice Basis points scale\n     */\n    uint256 internal constant BASIS_POINTS_SCALE = 10_000;\n\n    /**************************************************************************/\n    /* Errors */\n    /**************************************************************************/\n\n    /**\n     * @notice Invalid tick\n     */\n    error InvalidTick();\n\n    /**************************************************************************/\n    /* Helper Functions */\n    /**************************************************************************/\n\n    /**\n     * @dev Decode a Tick\n     * @param tick Tick\n     * @param oraclePrice Oracle price\n     * @return limit Limit field\n     * @return duration Duration field\n     * @return rate Rate field\n     * @return limitType Limit type field\n     */\n    function decode(\n        uint128 tick,\n        uint256 oraclePrice\n    ) internal pure returns (uint256 limit, uint256 duration, uint256 rate, LimitType limitType) {\n        limit = ((tick >> TICK_LIMIT_SHIFT) & TICK_LIMIT_MASK);\n        duration = ((tick >> TICK_DURATION_SHIFT) & TICK_DURATION_MASK);\n        rate = ((tick >> TICK_RATE_SHIFT) & TICK_RATE_MASK);\n        limitType = tick == type(uint128).max ? LimitType.Absolute : LimitType(tick & TICK_LIMIT_TYPE_MASK);\n        limit = limitType == LimitType.Ratio ? Math.mulDiv(oraclePrice, limit, BASIS_POINTS_SCALE) : limit;\n    }\n\n    /**\n     * @dev Validate a Tick (fast)\n     * @param tick Tick\n     * @param prevTick Previous tick\n     * @param maxDurationIndex Maximum Duration Index (inclusive)\n     * @param oraclePrice Oracle price\n     * @return Limit field\n     */\n    function validate(\n        uint128 tick,\n        uint128 prevTick,\n        uint256 maxDurationIndex,\n        uint256 oraclePrice\n    ) internal pure returns (uint256) {\n        (uint256 prevLimit, uint256 prevDuration, uint256 prevRate, ) = decode(prevTick, oraclePrice);\n        (uint256 limit, uint256 duration, uint256 rate, ) = decode(tick, oraclePrice);\n        if (limit < prevLimit) revert InvalidTick();\n        if (limit == prevLimit && duration < prevDuration) revert InvalidTick();\n        if (limit == prevLimit && duration == prevDuration && rate <= prevRate) revert InvalidTick();\n        if (duration > maxDurationIndex) revert InvalidTick();\n        return limit;\n    }\n\n    /**\n     * @dev Validate a Tick (slow)\n     * @param tick Tick\n     * @param minLimit Minimum Limit (exclusive)\n     * @param minDurationIndex Minimum Duration Index (inclusive)\n     * @param maxDurationIndex Maximum Duration Index (inclusive)\n     * @param minRateIndex Minimum Rate Index (inclusive)\n     * @param maxRateIndex Maximum Rate Index (inclusive)\n     */\n    function validate(\n        uint128 tick,\n        uint256 minLimit,\n        uint256 minDurationIndex,\n        uint256 maxDurationIndex,\n        uint256 minRateIndex,\n        uint256 maxRateIndex\n    ) internal pure {\n        (uint256 limit, uint256 duration, uint256 rate, LimitType limitType) = decode(tick, BASIS_POINTS_SCALE);\n        if (limit <= minLimit) revert InvalidTick();\n        if (duration < minDurationIndex) revert InvalidTick();\n        if (duration > maxDurationIndex) revert InvalidTick();\n        if (rate < minRateIndex) revert InvalidTick();\n        if (rate > maxRateIndex) revert InvalidTick();\n        if (limitType == LimitType.Ratio && limit > BASIS_POINTS_SCALE) revert InvalidTick();\n    }\n}\n"
      }
    },
    "settings": {
      "viaIR": true,
      "optimizer": {
        "enabled": true,
        "runs": 800
      },
      "evmVersion": "shanghai",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}