creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 amount\n    ) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    function safeTransfer(\n        IERC20 token,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    function safeIncreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n        }\n    }\n\n    function safePermit(\n        IERC20Permit token,\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal {\n        uint256 nonceBefore = token.nonces(owner);\n        token.permit(owner, spender, value, deadline, v, r, s);\n        uint256 nonceAfter = token.nonces(owner);\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        if (returndata.length > 0) {\n            // Return data is optional\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"
      },
      "contracts/infiniteProxy/interfaces/iProxy.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface IProxy {\n    function setAdmin(address newAdmin_) external;\n\n    function setDummyImplementation(address newDummyImplementation_) external;\n\n    function addImplementation(address implementation_, bytes4[] calldata sigs_) external;\n\n    function removeImplementation(address implementation_) external;\n\n    function getAdmin() external view returns (address);\n\n    function getDummyImplementation() external view returns (address);\n\n    function getImplementationSigs(address impl_) external view returns (bytes4[] memory);\n\n    function getSigsImplementation(bytes4 sig_) external view returns (address);\n\n    function readFromStorage(bytes32 slot_) external view returns (uint256 result_);\n}\n"
      },
      "contracts/libraries/bigMathMinified.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @title library that represents a number in BigNumber(coefficient and exponent) format to store in smaller bits.\n/// @notice the number is divided into two parts: a coefficient and an exponent. This comes at a cost of losing some precision\n/// at the end of the number because the exponent simply fills it with zeroes. This precision is oftentimes negligible and can\n/// result in significant gas cost reduction due to storage space reduction.\n/// Also note, a valid big number is as follows: if the exponent is > 0, then coefficient last bits should be occupied to have max precision.\n/// @dev roundUp is more like a increase 1, which happens everytime for the same number.\n/// roundDown simply sets trailing digits after coefficientSize to zero (floor), only once for the same number.\nlibrary BigMathMinified {\n    /// @dev constants to use for `roundUp` input param to increase readability\n    bool internal constant ROUND_DOWN = false;\n    bool internal constant ROUND_UP = true;\n\n    /// @dev converts `normal` number to BigNumber with `exponent` and `coefficient` (or precision).\n    /// e.g.:\n    /// 5035703444687813576399599 (normal) = (coefficient[32bits], exponent[8bits])[40bits]\n    /// 5035703444687813576399599 (decimal) => 10000101010010110100000011111011110010100110100000000011100101001101001101011101111 (binary)\n    ///                                     => 10000101010010110100000011111011000000000000000000000000000000000000000000000000000\n    ///                                                                        ^-------------------- 51(exponent) -------------- ^\n    /// coefficient = 1000,0101,0100,1011,0100,0000,1111,1011               (2236301563)\n    /// exponent =                                            0011,0011     (51)\n    /// bigNumber =   1000,0101,0100,1011,0100,0000,1111,1011,0011,0011     (572493200179)\n    ///\n    /// @param normal number which needs to be converted into Big Number\n    /// @param coefficientSize at max how many bits of precision there should be (64 = uint64 (64 bits precision))\n    /// @param exponentSize at max how many bits of exponent there should be (8 = uint8 (8 bits exponent))\n    /// @param roundUp signals if result should be rounded down or up\n    /// @return bigNumber converted bigNumber (coefficient << exponent)\n    function toBigNumber(\n        uint256 normal,\n        uint256 coefficientSize,\n        uint256 exponentSize,\n        bool roundUp\n    ) internal pure returns (uint256 bigNumber) {\n        assembly {\n            let lastBit_\n            let number_ := normal\n            if gt(number_, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {\n                number_ := shr(0x80, number_)\n                lastBit_ := 0x80\n            }\n            if gt(number_, 0xFFFFFFFFFFFFFFFF) {\n                number_ := shr(0x40, number_)\n                lastBit_ := add(lastBit_, 0x40)\n            }\n            if gt(number_, 0xFFFFFFFF) {\n                number_ := shr(0x20, number_)\n                lastBit_ := add(lastBit_, 0x20)\n            }\n            if gt(number_, 0xFFFF) {\n                number_ := shr(0x10, number_)\n                lastBit_ := add(lastBit_, 0x10)\n            }\n            if gt(number_, 0xFF) {\n                number_ := shr(0x8, number_)\n                lastBit_ := add(lastBit_, 0x8)\n            }\n            if gt(number_, 0xF) {\n                number_ := shr(0x4, number_)\n                lastBit_ := add(lastBit_, 0x4)\n            }\n            if gt(number_, 0x3) {\n                number_ := shr(0x2, number_)\n                lastBit_ := add(lastBit_, 0x2)\n            }\n            if gt(number_, 0x1) {\n                lastBit_ := add(lastBit_, 1)\n            }\n            if gt(number_, 0) {\n                lastBit_ := add(lastBit_, 1)\n            }\n            if lt(lastBit_, coefficientSize) {\n                // for throw exception\n                lastBit_ := coefficientSize\n            }\n            let exponent := sub(lastBit_, coefficientSize)\n            let coefficient := shr(exponent, normal)\n            if and(roundUp, gt(exponent, 0)) {\n                // rounding up is only needed if exponent is > 0, as otherwise the coefficient fully holds the original number\n                coefficient := add(coefficient, 1)\n                if eq(shl(coefficientSize, 1), coefficient) {\n                    // case were coefficient was e.g. 111, with adding 1 it became 1000 (in binary) and coefficientSize 3 bits\n                    // final coefficient would exceed it's size. -> reduce coefficent to 100 and increase exponent by 1.\n                    coefficient := shl(sub(coefficientSize, 1), 1)\n                    exponent := add(exponent, 1)\n                }\n            }\n            if iszero(lt(exponent, shl(exponentSize, 1))) {\n                // if exponent is >= exponentSize, the normal number is too big to fit within\n                // BigNumber with too small sizes for coefficient and exponent\n                revert(0, 0)\n            }\n            bigNumber := shl(exponentSize, coefficient)\n            bigNumber := add(bigNumber, exponent)\n        }\n    }\n\n    /// @dev get `normal` number from `bigNumber`, `exponentSize` and `exponentMask`\n    function fromBigNumber(\n        uint256 bigNumber,\n        uint256 exponentSize,\n        uint256 exponentMask\n    ) internal pure returns (uint256 normal) {\n        assembly {\n            let coefficient := shr(exponentSize, bigNumber)\n            let exponent := and(bigNumber, exponentMask)\n            normal := shl(exponent, coefficient)\n        }\n    }\n\n    /// @dev gets the most significant bit `lastBit` of a `normal` number (length of given number of binary format).\n    /// e.g.\n    /// 5035703444687813576399599 = 10000101010010110100000011111011110010100110100000000011100101001101001101011101111\n    /// lastBit =                   ^---------------------------------   83   ----------------------------------------^\n    function mostSignificantBit(uint256 normal) internal pure returns (uint lastBit) {\n        assembly {\n            let number_ := normal\n            if gt(normal, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) {\n                number_ := shr(0x80, number_)\n                lastBit := 0x80\n            }\n            if gt(number_, 0xFFFFFFFFFFFFFFFF) {\n                number_ := shr(0x40, number_)\n                lastBit := add(lastBit, 0x40)\n            }\n            if gt(number_, 0xFFFFFFFF) {\n                number_ := shr(0x20, number_)\n                lastBit := add(lastBit, 0x20)\n            }\n            if gt(number_, 0xFFFF) {\n                number_ := shr(0x10, number_)\n                lastBit := add(lastBit, 0x10)\n            }\n            if gt(number_, 0xFF) {\n                number_ := shr(0x8, number_)\n                lastBit := add(lastBit, 0x8)\n            }\n            if gt(number_, 0xF) {\n                number_ := shr(0x4, number_)\n                lastBit := add(lastBit, 0x4)\n            }\n            if gt(number_, 0x3) {\n                number_ := shr(0x2, number_)\n                lastBit := add(lastBit, 0x2)\n            }\n            if gt(number_, 0x1) {\n                lastBit := add(lastBit, 1)\n            }\n            if gt(number_, 0) {\n                lastBit := add(lastBit, 1)\n            }\n        }\n    }\n}\n"
      },
      "contracts/libraries/liquiditySlotsLink.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @notice library that helps in reading / working with storage slot data of Fluid Liquidity.\n/// @dev as all data for Fluid Liquidity is internal, any data must be fetched directly through manual\n/// slot reading through this library or, if gas usage is less important, through the FluidLiquidityResolver.\nlibrary LiquiditySlotsLink {\n    /// @dev storage slot for status at Liquidity\n    uint256 internal constant LIQUIDITY_STATUS_SLOT = 1;\n    /// @dev storage slot for auths mapping at Liquidity\n    uint256 internal constant LIQUIDITY_AUTHS_MAPPING_SLOT = 2;\n    /// @dev storage slot for guardians mapping at Liquidity\n    uint256 internal constant LIQUIDITY_GUARDIANS_MAPPING_SLOT = 3;\n    /// @dev storage slot for user class mapping at Liquidity\n    uint256 internal constant LIQUIDITY_USER_CLASS_MAPPING_SLOT = 4;\n    /// @dev storage slot for exchangePricesAndConfig mapping at Liquidity\n    uint256 internal constant LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT = 5;\n    /// @dev storage slot for rateData mapping at Liquidity\n    uint256 internal constant LIQUIDITY_RATE_DATA_MAPPING_SLOT = 6;\n    /// @dev storage slot for totalAmounts mapping at Liquidity\n    uint256 internal constant LIQUIDITY_TOTAL_AMOUNTS_MAPPING_SLOT = 7;\n    /// @dev storage slot for user supply double mapping at Liquidity\n    uint256 internal constant LIQUIDITY_USER_SUPPLY_DOUBLE_MAPPING_SLOT = 8;\n    /// @dev storage slot for user borrow double mapping at Liquidity\n    uint256 internal constant LIQUIDITY_USER_BORROW_DOUBLE_MAPPING_SLOT = 9;\n    /// @dev storage slot for listed tokens array at Liquidity\n    uint256 internal constant LIQUIDITY_LISTED_TOKENS_ARRAY_SLOT = 10;\n    /// @dev storage slot for listed tokens array at Liquidity\n    uint256 internal constant LIQUIDITY_CONFIGS2_MAPPING_SLOT = 11;\n\n    // --------------------------------\n    // @dev stacked uint256 storage slots bits position data for each:\n\n    // ExchangePricesAndConfig\n    uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_RATE = 0;\n    uint256 internal constant BITS_EXCHANGE_PRICES_FEE = 16;\n    uint256 internal constant BITS_EXCHANGE_PRICES_UTILIZATION = 30;\n    uint256 internal constant BITS_EXCHANGE_PRICES_UPDATE_THRESHOLD = 44;\n    uint256 internal constant BITS_EXCHANGE_PRICES_LAST_TIMESTAMP = 58;\n    uint256 internal constant BITS_EXCHANGE_PRICES_SUPPLY_EXCHANGE_PRICE = 91;\n    uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_EXCHANGE_PRICE = 155;\n    uint256 internal constant BITS_EXCHANGE_PRICES_SUPPLY_RATIO = 219;\n    uint256 internal constant BITS_EXCHANGE_PRICES_BORROW_RATIO = 234;\n    uint256 internal constant BITS_EXCHANGE_PRICES_USES_CONFIGS2 = 249;\n\n    // RateData:\n    uint256 internal constant BITS_RATE_DATA_VERSION = 0;\n    // RateData: V1\n    uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_ZERO = 4;\n    uint256 internal constant BITS_RATE_DATA_V1_UTILIZATION_AT_KINK = 20;\n    uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_KINK = 36;\n    uint256 internal constant BITS_RATE_DATA_V1_RATE_AT_UTILIZATION_MAX = 52;\n    // RateData: V2\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_ZERO = 4;\n    uint256 internal constant BITS_RATE_DATA_V2_UTILIZATION_AT_KINK1 = 20;\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK1 = 36;\n    uint256 internal constant BITS_RATE_DATA_V2_UTILIZATION_AT_KINK2 = 52;\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_KINK2 = 68;\n    uint256 internal constant BITS_RATE_DATA_V2_RATE_AT_UTILIZATION_MAX = 84;\n\n    // TotalAmounts\n    uint256 internal constant BITS_TOTAL_AMOUNTS_SUPPLY_WITH_INTEREST = 0;\n    uint256 internal constant BITS_TOTAL_AMOUNTS_SUPPLY_INTEREST_FREE = 64;\n    uint256 internal constant BITS_TOTAL_AMOUNTS_BORROW_WITH_INTEREST = 128;\n    uint256 internal constant BITS_TOTAL_AMOUNTS_BORROW_INTEREST_FREE = 192;\n\n    // UserSupplyData\n    uint256 internal constant BITS_USER_SUPPLY_MODE = 0;\n    uint256 internal constant BITS_USER_SUPPLY_AMOUNT = 1;\n    uint256 internal constant BITS_USER_SUPPLY_PREVIOUS_WITHDRAWAL_LIMIT = 65;\n    uint256 internal constant BITS_USER_SUPPLY_LAST_UPDATE_TIMESTAMP = 129;\n    uint256 internal constant BITS_USER_SUPPLY_EXPAND_PERCENT = 162;\n    uint256 internal constant BITS_USER_SUPPLY_EXPAND_DURATION = 176;\n    uint256 internal constant BITS_USER_SUPPLY_BASE_WITHDRAWAL_LIMIT = 200;\n    uint256 internal constant BITS_USER_SUPPLY_IS_PAUSED = 255;\n\n    // UserBorrowData\n    uint256 internal constant BITS_USER_BORROW_MODE = 0;\n    uint256 internal constant BITS_USER_BORROW_AMOUNT = 1;\n    uint256 internal constant BITS_USER_BORROW_PREVIOUS_BORROW_LIMIT = 65;\n    uint256 internal constant BITS_USER_BORROW_LAST_UPDATE_TIMESTAMP = 129;\n    uint256 internal constant BITS_USER_BORROW_EXPAND_PERCENT = 162;\n    uint256 internal constant BITS_USER_BORROW_EXPAND_DURATION = 176;\n    uint256 internal constant BITS_USER_BORROW_BASE_BORROW_LIMIT = 200;\n    uint256 internal constant BITS_USER_BORROW_MAX_BORROW_LIMIT = 218;\n    uint256 internal constant BITS_USER_BORROW_IS_PAUSED = 255;\n\n    // Configs2\n    uint256 internal constant BITS_CONFIGS2_MAX_UTILIZATION = 0;\n\n    // --------------------------------\n\n    /// @notice Calculating the slot ID for Liquidity contract for single mapping at `slot_` for `key_`\n    function calculateMappingStorageSlot(uint256 slot_, address key_) internal pure returns (bytes32) {\n        return keccak256(abi.encode(key_, slot_));\n    }\n\n    /// @notice Calculating the slot ID for Liquidity contract for double mapping at `slot_` for `key1_` and `key2_`\n    function calculateDoubleMappingStorageSlot(\n        uint256 slot_,\n        address key1_,\n        address key2_\n    ) internal pure returns (bytes32) {\n        bytes32 intermediateSlot_ = keccak256(abi.encode(key1_, slot_));\n        return keccak256(abi.encode(key2_, intermediateSlot_));\n    }\n}\n"
      },
      "contracts/libraries/tickMath.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @title library that calculates number \"tick\" and \"ratioX96\" from this: ratioX96 = (1.0015^tick) * 2^96\n/// @notice this library is used in Fluid Vault protocol for optimiziation.\n/// @dev \"tick\" supports between -32767 and 32767. \"ratioX96\" supports between 37075072 and 169307877264527972847801929085841449095838922544595\nlibrary TickMath {\n    /// The minimum tick that can be passed in getRatioAtTick. 1.0015**-32767\n    int24 internal constant MIN_TICK = -32767;\n    /// The maximum tick that can be passed in getRatioAtTick. 1.0015**32767\n    int24 internal constant MAX_TICK = 32767;\n\n    uint256 internal constant FACTOR00 = 0x100000000000000000000000000000000;\n    uint256 internal constant FACTOR01 = 0xff9dd7de423466c20352b1246ce4856f; // 2^128/1.0015**1 = 339772707859149738855091969477551883631\n    uint256 internal constant FACTOR02 = 0xff3bd55f4488ad277531fa1c725a66d0; // 2^128/1.0015**2 = 339263812140938331358054887146831636176\n    uint256 internal constant FACTOR03 = 0xfe78410fd6498b73cb96a6917f853259; // 2^128/1.0015**4 = 338248306163758188337119769319392490073\n    uint256 internal constant FACTOR04 = 0xfcf2d9987c9be178ad5bfeffaa123273; // 2^128/1.0015**8 = 336226404141693512316971918999264834163\n    uint256 internal constant FACTOR05 = 0xf9ef02c4529258b057769680fc6601b3; // 2^128/1.0015**16 = 332218786018727629051611634067491389875\n    uint256 internal constant FACTOR06 = 0xf402d288133a85a17784a411f7aba082; // 2^128/1.0015**32 = 324346285652234375371948336458280706178\n    uint256 internal constant FACTOR07 = 0xe895615b5beb6386553757b0352bda90; // 2^128/1.0015**64 = 309156521885964218294057947947195947664\n    uint256 internal constant FACTOR08 = 0xd34f17a00ffa00a8309940a15930391a; // 2^128/1.0015**128 = 280877777739312896540849703637713172762 \n    uint256 internal constant FACTOR09 = 0xae6b7961714e20548d88ea5123f9a0ff; // 2^128/1.0015**256 = 231843708922198649176471782639349113087\n    uint256 internal constant FACTOR10 = 0x76d6461f27082d74e0feed3b388c0ca1; // 2^128/1.0015**512 = 157961477267171621126394973980180876449\n    uint256 internal constant FACTOR11 = 0x372a3bfe0745d8b6b19d985d9a8b85bb; // 2^128/1.0015**1024 = 73326833024599564193373530205717235131\n    uint256 internal constant FACTOR12 = 0x0be32cbee48979763cf7247dd7bb539d; // 2^128/1.0015**2048 = 15801066890623697521348224657638773661\n    uint256 internal constant FACTOR13 = 0x8d4f70c9ff4924dac37612d1e2921e;   // 2^128/1.0015**4096 = 733725103481409245883800626999235102\n    uint256 internal constant FACTOR14 = 0x4e009ae5519380809a02ca7aec77;     // 2^128/1.0015**8192 = 1582075887005588088019997442108535\n    uint256 internal constant FACTOR15 = 0x17c45e641b6e95dee056ff10;         // 2^128/1.0015**16384 = 7355550435635883087458926352\n\n    /// The minimum value that can be returned from getRatioAtTick. Equivalent to getRatioAtTick(MIN_TICK). ~ Equivalent to `(1 << 96) * (1.0015**-32767)`\n    uint256 internal constant MIN_RATIOX96 = 37075072;\n    /// The maximum value that can be returned from getRatioAtTick. Equivalent to getRatioAtTick(MAX_TICK).\n    /// ~ Equivalent to `(1 << 96) * (1.0015**32767)`, rounding etc. leading to minor difference\n    uint256 internal constant MAX_RATIOX96 = 169307877264527972847801929085841449095838922544595;\n\n    uint256 internal constant ZERO_TICK_SCALED_RATIO = 0x1000000000000000000000000; // 1 << 96 // 79228162514264337593543950336\n    uint256 internal constant _1E26 = 1e26;\n\n    /// @notice ratioX96 = (1.0015^tick) * 2^96\n    /// @dev Throws if |tick| > max tick\n    /// @param tick The input tick for the above formula\n    /// @return ratioX96 ratio = (debt amount/collateral amount)\n    function getRatioAtTick(int tick) internal pure returns (uint256 ratioX96) {\n        assembly {\n            let absTick_ := sub(xor(tick, sar(255, tick)), sar(255, tick))\n\n            if gt(absTick_, MAX_TICK) {\n                revert(0, 0)\n            }\n            let factor_ := FACTOR00\n            if and(absTick_, 0x1) {\n                factor_ := FACTOR01\n            }\n            if and(absTick_, 0x2) {\n                factor_ := shr(128, mul(factor_, FACTOR02))\n            }\n            if and(absTick_, 0x4) {\n                factor_ := shr(128, mul(factor_, FACTOR03))\n            }\n            if and(absTick_, 0x8) {\n                factor_ := shr(128, mul(factor_, FACTOR04))\n            }\n            if and(absTick_, 0x10) {\n                factor_ := shr(128, mul(factor_, FACTOR05))\n            }\n            if and(absTick_, 0x20) {\n                factor_ := shr(128, mul(factor_, FACTOR06))\n            }\n            if and(absTick_, 0x40) {\n                factor_ := shr(128, mul(factor_, FACTOR07))\n            }\n            if and(absTick_, 0x80) {\n                factor_ := shr(128, mul(factor_, FACTOR08))\n            }\n            if and(absTick_, 0x100) {\n                factor_ := shr(128, mul(factor_, FACTOR09))\n            }\n            if and(absTick_, 0x200) {\n                factor_ := shr(128, mul(factor_, FACTOR10))\n            }\n            if and(absTick_, 0x400) {\n                factor_ := shr(128, mul(factor_, FACTOR11))\n            }\n            if and(absTick_, 0x800) {\n                factor_ := shr(128, mul(factor_, FACTOR12))\n            }\n            if and(absTick_, 0x1000) {\n                factor_ := shr(128, mul(factor_, FACTOR13))\n            }\n            if and(absTick_, 0x2000) {\n                factor_ := shr(128, mul(factor_, FACTOR14))\n            }\n            if and(absTick_, 0x4000) {\n                factor_ := shr(128, mul(factor_, FACTOR15))\n            }\n\n            let precision_ := 0\n            if iszero(and(tick, 0x8000000000000000000000000000000000000000000000000000000000000000)) {\n                factor_ := div(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, factor_)\n                // we round up in the division so getTickAtRatio of the output price is always consistent\n                if mod(factor_, 0x100000000) {\n                    precision_ := 1\n                }\n            }\n            ratioX96 := add(shr(32, factor_), precision_)\n        }\n    }\n\n    /// @notice ratioX96 = (1.0015^tick) * 2^96\n    /// @dev Throws if ratioX96 > max ratio || ratioX96 < min ratio\n    /// @param ratioX96 The input ratio; ratio = (debt amount/collateral amount)\n    /// @return tick The output tick for the above formula. Returns in round down form. if tick is 123.23 then 123, if tick is -123.23 then returns -124\n    /// @return perfectRatioX96 perfect ratio for the above tick\n    function getTickAtRatio(uint256 ratioX96) internal pure returns (int tick, uint perfectRatioX96) {\n        assembly {\n            if or(gt(ratioX96, MAX_RATIOX96), lt(ratioX96, MIN_RATIOX96)) {\n                revert(0, 0)\n            }\n\n            let cond := lt(ratioX96, ZERO_TICK_SCALED_RATIO)\n            let factor_\n\n            if iszero(cond) {\n                // if ratioX96 >= ZERO_TICK_SCALED_RATIO\n                factor_ := div(mul(ratioX96, _1E26), ZERO_TICK_SCALED_RATIO)\n            }\n            if cond {\n                // ratioX96 < ZERO_TICK_SCALED_RATIO\n                factor_ := div(mul(ZERO_TICK_SCALED_RATIO, _1E26), ratioX96)\n            }\n\n            // put in https://www.wolframalpha.com/ whole equation: (1.0015^tick) * 2^96 * 10^26 / 79228162514264337593543950336\n\n            // for tick = 16384\n            // ratioX96 = (1.0015^16384) * 2^96 = 3665252098134783297721995888537077351735\n            // 3665252098134783297721995888537077351735 * 10^26 / 79228162514264337593543950336 =\n            // 4626198540796508716348404308345255985.06131964639489434655721\n            if iszero(lt(factor_, 4626198540796508716348404308345255985)) {\n                tick := or(tick, 0x4000)\n                factor_ := div(mul(factor_, _1E26), 4626198540796508716348404308345255985)\n            }\n            // for tick = 8192\n            // ratioX96 = (1.0015^8192) * 2^96 = 17040868196391020479062776466509865\n            // 17040868196391020479062776466509865 * 10^26 / 79228162514264337593543950336 =\n            // 21508599537851153911767490449162.3037648642153898377655505172\n            if iszero(lt(factor_, 21508599537851153911767490449162)) {\n                tick := or(tick, 0x2000)\n                factor_ := div(mul(factor_, _1E26), 21508599537851153911767490449162)\n            }\n            // for tick = 4096\n            // ratioX96 = (1.0015^4096) * 2^96 = 36743933851015821532611831851150\n            // 36743933851015821532611831851150 * 10^26 / 79228162514264337593543950336 =\n            // 46377364670549310883002866648.9777607649742626173648716941385\n            if iszero(lt(factor_, 46377364670549310883002866649)) {\n                tick := or(tick, 0x1000)\n                factor_ := div(mul(factor_, _1E26), 46377364670549310883002866649)\n            }\n            // for tick = 2048\n            // ratioX96 = (1.0015^2048) * 2^96 = 1706210527034005899209104452335\n            // 1706210527034005899209104452335 * 10^26 / 79228162514264337593543950336 =\n            // 2153540449365864845468344760.06357108484096046743300420319322\n            if iszero(lt(factor_, 2153540449365864845468344760)) {\n                tick := or(tick, 0x800)\n                factor_ := div(mul(factor_, _1E26), 2153540449365864845468344760)\n            }\n            // for tick = 1024\n            // ratioX96 = (1.0015^1024) * 2^96 = 367668226692760093024536487236\n            // 367668226692760093024536487236 * 10^26 / 79228162514264337593543950336 =\n            // 464062544207767844008185024.950588990554136265212906454481127\n            if iszero(lt(factor_, 464062544207767844008185025)) {\n                tick := or(tick, 0x400)\n                factor_ := div(mul(factor_, _1E26), 464062544207767844008185025)\n            }\n            // for tick = 512\n            // ratioX96 = (1.0015^512) * 2^96 = 170674186729409605620119663668\n            // 170674186729409605620119663668 * 10^26 / 79228162514264337593543950336 =\n            // 215421109505955298802281577.031879604792139232258508172947569\n            if iszero(lt(factor_, 215421109505955298802281577)) {\n                tick := or(tick, 0x200)\n                factor_ := div(mul(factor_, _1E26), 215421109505955298802281577)\n            }\n            // for tick = 256\n            // ratioX96 = (1.0015^256) * 2^96 = 116285004205991934861656513301\n            // 116285004205991934861656513301 * 10^26 / 79228162514264337593543950336 =\n            // 146772309890508740607270614.667650899656438875541505058062410\n            if iszero(lt(factor_, 146772309890508740607270615)) {\n                tick := or(tick, 0x100)\n                factor_ := div(mul(factor_, _1E26), 146772309890508740607270615)\n            }\n            // for tick = 128\n            // ratioX96 = (1.0015^128) * 2^96 = 95984619659632141743747099590\n            // 95984619659632141743747099590 * 10^26 / 79228162514264337593543950336 =\n            // 121149622323187099817270416.157248837742741760456796835775887\n            if iszero(lt(factor_, 121149622323187099817270416)) {\n                tick := or(tick, 0x80)\n                factor_ := div(mul(factor_, _1E26), 121149622323187099817270416)\n            }\n            // for tick = 64\n            // ratioX96 = (1.0015^64) * 2^96 = 87204845308406958006717891124\n            // 87204845308406958006717891124 * 10^26 / 79228162514264337593543950336 =\n            // 110067989135437147685980801.568068573422377364214113968609839\n            if iszero(lt(factor_, 110067989135437147685980801)) {\n                tick := or(tick, 0x40)\n                factor_ := div(mul(factor_, _1E26), 110067989135437147685980801)\n            }\n            // for tick = 32\n            // ratioX96 = (1.0015^32) * 2^96 = 83120873769022354029916374475\n            // 83120873769022354029916374475 * 10^26 / 79228162514264337593543950336 =\n            // 104913292358707887270979599.831816586773651266562785765558183\n            if iszero(lt(factor_, 104913292358707887270979600)) {\n                tick := or(tick, 0x20)\n                factor_ := div(mul(factor_, _1E26), 104913292358707887270979600)\n            }\n            // for tick = 16\n            // ratioX96 = (1.0015^16) * 2^96 = 81151180492336368327184716176\n            // 81151180492336368327184716176 * 10^26 / 79228162514264337593543950336 =\n            // 102427189924701091191840927.762844039579442328381455567932128\n            if iszero(lt(factor_, 102427189924701091191840928)) {\n                tick := or(tick, 0x10)\n                factor_ := div(mul(factor_, _1E26), 102427189924701091191840928)\n            }\n            // for tick = 8\n            // ratioX96 = (1.0015^8) * 2^96 = 80183906840906820640659903620\n            // 80183906840906820640659903620 * 10^26 / 79228162514264337593543950336 =\n            // 101206318935480056907421312.890625\n            if iszero(lt(factor_, 101206318935480056907421313)) {\n                tick := or(tick, 0x8)\n                factor_ := div(mul(factor_, _1E26), 101206318935480056907421313)\n            }\n            // for tick = 4\n            // ratioX96 = (1.0015^4) * 2^96 = 79704602139525152702959747603\n            // 79704602139525152702959747603 * 10^26 / 79228162514264337593543950336 =\n            // 100601351350506250000000000\n            if iszero(lt(factor_, 100601351350506250000000000)) {\n                tick := or(tick, 0x4)\n                factor_ := div(mul(factor_, _1E26), 100601351350506250000000000)\n            }\n            // for tick = 2\n            // ratioX96 = (1.0015^2) * 2^96 = 79466025265172787701084167660\n            // 79466025265172787701084167660 * 10^26 / 79228162514264337593543950336 =\n            // 100300225000000000000000000\n            if iszero(lt(factor_, 100300225000000000000000000)) {\n                tick := or(tick, 0x2)\n                factor_ := div(mul(factor_, _1E26), 100300225000000000000000000)\n            }\n            // for tick = 1\n            // ratioX96 = (1.0015^1) * 2^96 = 79347004758035734099934266261\n            // 79347004758035734099934266261 * 10^26 / 79228162514264337593543950336 =\n            // 100150000000000000000000000\n            if iszero(lt(factor_, 100150000000000000000000000)) {\n                tick := or(tick, 0x1)\n                factor_ := div(mul(factor_, _1E26), 100150000000000000000000000)\n            }\n            if iszero(cond) {\n                // if ratioX96 >= ZERO_TICK_SCALED_RATIO\n                perfectRatioX96 := div(mul(ratioX96, _1E26), factor_)\n            }\n            if cond {\n                // ratioX96 < ZERO_TICK_SCALED_RATIO\n                tick := not(tick)\n                perfectRatioX96 := div(mul(ratioX96, factor_), 100150000000000000000000000)\n            }\n            // perfect ratio should always be <= ratioX96\n            // not sure if it can ever be bigger but better to have extra checks\n            if gt(perfectRatioX96, ratioX96) {\n                revert(0, 0)\n            }\n        }\n    }\n}\n"
      },
      "contracts/liquidity/adminModule/structs.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Structs {\n    struct AddressBool {\n        address addr;\n        bool value;\n    }\n\n    struct AddressUint256 {\n        address addr;\n        uint256 value;\n    }\n\n    /// @notice struct to set borrow rate data for version 1\n    struct RateDataV1Params {\n        ///\n        /// @param token for rate data\n        address token;\n        ///\n        /// @param kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\n        /// utilization below kink usually means slow increase in rate, once utilization is above kink borrow rate increases fast\n        uint256 kink;\n        ///\n        /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100\n        /// i.e. constant minimum borrow rate\n        /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then)\n        uint256 rateAtUtilizationZero;\n        ///\n        /// @param rateAtUtilizationKink borrow rate when utilization is at kink. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 7% at kink then rateAtUtilizationKink would be 700\n        uint256 rateAtUtilizationKink;\n        ///\n        /// @param rateAtUtilizationMax borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500\n        uint256 rateAtUtilizationMax;\n    }\n\n    /// @notice struct to set borrow rate data for version 2\n    struct RateDataV2Params {\n        ///\n        /// @param token for rate data\n        address token;\n        ///\n        /// @param kink1 first kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\n        /// utilization below kink 1 usually means slow increase in rate, once utilization is above kink 1 borrow rate increases faster\n        uint256 kink1;\n        ///\n        /// @param kink2 second kink in borrow rate. in 1e2: 100% = 10_000; 1% = 100\n        /// utilization below kink 2 usually means slow / medium increase in rate, once utilization is above kink 2 borrow rate increases fast\n        uint256 kink2;\n        ///\n        /// @param rateAtUtilizationZero desired borrow rate when utilization is zero. in 1e2: 100% = 10_000; 1% = 100\n        /// i.e. constant minimum borrow rate\n        /// e.g. at utilization = 0.01% rate could still be at least 4% (rateAtUtilizationZero would be 400 then)\n        uint256 rateAtUtilizationZero;\n        ///\n        /// @param rateAtUtilizationKink1 desired borrow rate when utilization is at first kink. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 7% at first kink then rateAtUtilizationKink would be 700\n        uint256 rateAtUtilizationKink1;\n        ///\n        /// @param rateAtUtilizationKink2 desired borrow rate when utilization is at second kink. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 7% at second kink then rateAtUtilizationKink would be 1_200\n        uint256 rateAtUtilizationKink2;\n        ///\n        /// @param rateAtUtilizationMax desired borrow rate when utilization is maximum at 100%. in 1e2: 100% = 10_000; 1% = 100\n        /// e.g. when rate should be 125% at 100% then rateAtUtilizationMax would be 12_500\n        uint256 rateAtUtilizationMax;\n    }\n\n    /// @notice struct to set token config\n    struct TokenConfig {\n        ///\n        /// @param token address\n        address token;\n        ///\n        /// @param fee charges on borrower's interest. in 1e2: 100% = 10_000; 1% = 100\n        uint256 fee;\n        ///\n        /// @param threshold on when to update the storage slot. in 1e2: 100% = 10_000; 1% = 100\n        uint256 threshold;\n        ///\n        /// @param maxUtilization maximum allowed utilization. in 1e2: 100% = 10_000; 1% = 100\n        ///                       set to 100% to disable and have default limit of 100% (avoiding SLOAD).\n        uint256 maxUtilization;\n    }\n\n    /// @notice struct to set user supply & withdrawal config\n    struct UserSupplyConfig {\n        ///\n        /// @param user address\n        address user;\n        ///\n        /// @param token address\n        address token;\n        ///\n        /// @param mode: 0 = without interest. 1 = with interest\n        uint8 mode;\n        ///\n        /// @param expandPercent withdrawal limit expand percent. in 1e2: 100% = 10_000; 1% = 100\n        /// Also used to calculate rate at which withdrawal limit should decrease (instant).\n        uint256 expandPercent;\n        ///\n        /// @param expandDuration withdrawal limit expand duration in seconds.\n        /// used to calculate rate together with expandPercent\n        uint256 expandDuration;\n        ///\n        /// @param baseWithdrawalLimit base limit, below this, user can withdraw the entire amount.\n        /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:\n        /// with interest -> raw, without interest -> normal\n        uint256 baseWithdrawalLimit;\n    }\n\n    /// @notice struct to set user borrow & payback config\n    struct UserBorrowConfig {\n        ///\n        /// @param user address\n        address user;\n        ///\n        /// @param token address\n        address token;\n        ///\n        /// @param mode: 0 = without interest. 1 = with interest\n        uint8 mode;\n        ///\n        /// @param expandPercent debt limit expand percent. in 1e2: 100% = 10_000; 1% = 100\n        /// Also used to calculate rate at which debt limit should decrease (instant).\n        uint256 expandPercent;\n        ///\n        /// @param expandDuration debt limit expand duration in seconds.\n        /// used to calculate rate together with expandPercent\n        uint256 expandDuration;\n        ///\n        /// @param baseDebtCeiling base borrow limit. until here, borrow limit remains as baseDebtCeiling\n        /// (user can borrow until this point at once without stepped expansion). Above this, automated limit comes in place.\n        /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:\n        /// with interest -> raw, without interest -> normal\n        uint256 baseDebtCeiling;\n        ///\n        /// @param maxDebtCeiling max borrow ceiling, maximum amount the user can borrow.\n        /// amount in raw (to be multiplied with exchange price) or normal depends on configured mode in user config for the token:\n        /// with interest -> raw, without interest -> normal\n        uint256 maxDebtCeiling;\n    }\n}\n"
      },
      "contracts/liquidity/interfaces/iLiquidity.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\nimport { IProxy } from \"../../infiniteProxy/interfaces/iProxy.sol\";\nimport { Structs as AdminModuleStructs } from \"../adminModule/structs.sol\";\n\ninterface IFluidLiquidityAdmin {\n    /// @notice adds/removes auths. Auths generally could be contracts which can have restricted actions defined on contract.\n    ///         auths can be helpful in reducing governance overhead where it's not needed.\n    /// @param authsStatus_ array of structs setting allowed status for an address.\n    ///                     status true => add auth, false => remove auth\n    function updateAuths(AdminModuleStructs.AddressBool[] calldata authsStatus_) external;\n\n    /// @notice adds/removes guardians. Only callable by Governance.\n    /// @param guardiansStatus_ array of structs setting allowed status for an address.\n    ///                         status true => add guardian, false => remove guardian\n    function updateGuardians(AdminModuleStructs.AddressBool[] calldata guardiansStatus_) external;\n\n    /// @notice changes the revenue collector address (contract that is sent revenue). Only callable by Governance.\n    /// @param revenueCollector_  new revenue collector address\n    function updateRevenueCollector(address revenueCollector_) external;\n\n    /// @notice changes current status, e.g. for pausing or unpausing all user operations. Only callable by Auths.\n    /// @param newStatus_ new status\n    ///        status = 2 -> pause, status = 1 -> resume.\n    function changeStatus(uint256 newStatus_) external;\n\n    /// @notice                  update tokens rate data version 1. Only callable by Auths.\n    /// @param tokensRateData_   array of RateDataV1Params with rate data to set for each token\n    function updateRateDataV1s(AdminModuleStructs.RateDataV1Params[] calldata tokensRateData_) external;\n\n    /// @notice                  update tokens rate data version 2. Only callable by Auths.\n    /// @param tokensRateData_   array of RateDataV2Params with rate data to set for each token\n    function updateRateDataV2s(AdminModuleStructs.RateDataV2Params[] calldata tokensRateData_) external;\n\n    /// @notice updates token configs: fee charge on borrowers interest & storage update utilization threshold.\n    ///         Only callable by Auths.\n    /// @param tokenConfigs_ contains token address, fee & utilization threshold\n    function updateTokenConfigs(AdminModuleStructs.TokenConfig[] calldata tokenConfigs_) external;\n\n    /// @notice updates user classes: 0 is for new protocols, 1 is for established protocols.\n    ///         Only callable by Auths.\n    /// @param userClasses_ struct array of uint256 value to assign for each user address\n    function updateUserClasses(AdminModuleStructs.AddressUint256[] calldata userClasses_) external;\n\n    /// @notice sets user supply configs per token basis. Eg: with interest or interest-free and automated limits.\n    ///         Only callable by Auths.\n    /// @param userSupplyConfigs_ struct array containing user supply config, see `UserSupplyConfig` struct for more info\n    function updateUserSupplyConfigs(AdminModuleStructs.UserSupplyConfig[] memory userSupplyConfigs_) external;\n\n    /// @notice setting user borrow configs per token basis. Eg: with interest or interest-free and automated limits.\n    ///         Only callable by Auths.\n    /// @param userBorrowConfigs_ struct array containing user borrow config, see `UserBorrowConfig` struct for more info\n    function updateUserBorrowConfigs(AdminModuleStructs.UserBorrowConfig[] memory userBorrowConfigs_) external;\n\n    /// @notice pause operations for a particular user in class 0 (class 1 users can't be paused by guardians).\n    /// Only callable by Guardians.\n    /// @param user_          address of user to pause operations for\n    /// @param supplyTokens_  token addresses to pause withdrawals for\n    /// @param borrowTokens_  token addresses to pause borrowings for\n    function pauseUser(address user_, address[] calldata supplyTokens_, address[] calldata borrowTokens_) external;\n\n    /// @notice unpause operations for a particular user in class 0 (class 1 users can't be paused by guardians).\n    /// Only callable by Guardians.\n    /// @param user_          address of user to unpause operations for\n    /// @param supplyTokens_  token addresses to unpause withdrawals for\n    /// @param borrowTokens_  token addresses to unpause borrowings for\n    function unpauseUser(address user_, address[] calldata supplyTokens_, address[] calldata borrowTokens_) external;\n\n    /// @notice         collects revenue for tokens to configured revenueCollector address.\n    /// @param tokens_  array of tokens to collect revenue for\n    /// @dev            Note that this can revert if token balance is < revenueAmount (utilization > 100%)\n    function collectRevenue(address[] calldata tokens_) external;\n\n    /// @notice gets the current updated exchange prices for n tokens and updates all prices, rates related data in storage.\n    /// @param tokens_ tokens to update exchange prices for\n    /// @return supplyExchangePrices_ new supply rates of overall system for each token\n    /// @return borrowExchangePrices_ new borrow rates of overall system for each token\n    function updateExchangePrices(\n        address[] calldata tokens_\n    ) external returns (uint256[] memory supplyExchangePrices_, uint256[] memory borrowExchangePrices_);\n}\n\ninterface IFluidLiquidityLogic is IFluidLiquidityAdmin {\n    /// @notice Single function which handles supply, withdraw, borrow & payback\n    /// @param token_ address of token (0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for native)\n    /// @param supplyAmount_ if +ve then supply, if -ve then withdraw, if 0 then nothing\n    /// @param borrowAmount_ if +ve then borrow, if -ve then payback, if 0 then nothing\n    /// @param withdrawTo_ if withdrawal then to which address\n    /// @param borrowTo_ if borrow then to which address\n    /// @param callbackData_ callback data passed to `liquidityCallback` method of protocol\n    /// @return memVar3_ updated supplyExchangePrice\n    /// @return memVar4_ updated borrowExchangePrice\n    /// @dev to trigger skipping in / out transfers when in&out amounts balance themselves out (gas optimization):\n    /// -   supply(+) == borrow(+), withdraw(-) == payback(-).\n    /// -   `withdrawTo_` / `borrowTo_` must be msg.sender (protocol)\n    /// -   `callbackData_` MUST be encoded so that \"from\" address is at last 20 bytes (if this optimization is desired),\n    ///     also for native token operations where liquidityCallback is not triggered!\n    ///     from address must come at last position if there is more data. I.e. encode like:\n    ///     abi.encode(otherVar1, otherVar2, FROM_ADDRESS). Note dynamic types used with abi.encode come at the end\n    ///     so if dynamic types are needed, you must use abi.encodePacked to ensure the from address is at the end.\n    function operate(\n        address token_,\n        int256 supplyAmount_,\n        int256 borrowAmount_,\n        address withdrawTo_,\n        address borrowTo_,\n        bytes calldata callbackData_\n    ) external payable returns (uint256 memVar3_, uint256 memVar4_);\n}\n\ninterface IFluidLiquidity is IProxy, IFluidLiquidityLogic {}\n"
      },
      "contracts/protocols/vault/error.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ncontract Error {\n    error FluidVaultError(uint256 errorId_);\n\n    /// @notice used to simulate liquidation to find the maximum liquidatable amounts\n    error FluidLiquidateResult(uint256 colLiquidated, uint256 debtLiquidated);\n}\n"
      },
      "contracts/protocols/vault/errorTypes.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nlibrary ErrorTypes {\n    /***********************************|\n    |           Vault Factory           | \n    |__________________________________*/\n\n    uint256 internal constant VaultFactory__InvalidOperation = 30001;\n    uint256 internal constant VaultFactory__Unauthorized = 30002;\n    uint256 internal constant VaultFactory__SameTokenNotAllowed = 30003;\n    uint256 internal constant VaultFactory__InvalidParams = 30004;\n    uint256 internal constant VaultFactory__InvalidVault = 30005;\n    uint256 internal constant VaultFactory__InvalidVaultAddress = 30006;\n    uint256 internal constant VaultFactory__OnlyDelegateCallAllowed = 30007;\n\n    /***********************************|\n    |            VaultT1                | \n    |__________________________________*/\n\n    /// @notice thrown at reentrancy\n    uint256 internal constant VaultT1__AlreadyEntered = 31001;\n\n    /// @notice thrown when user sends deposit & borrow amount as 0\n    uint256 internal constant VaultT1__InvalidOperateAmount = 31002;\n\n    /// @notice thrown when msg.value is not in sync with native token deposit or payback\n    uint256 internal constant VaultT1__InvalidMsgValueOperate = 31003;\n\n    /// @notice thrown when msg.sender is not the owner of the vault\n    uint256 internal constant VaultT1__NotAnOwner = 31004;\n\n    /// @notice thrown when user's position does not exist. Sending the wrong index from the frontend\n    uint256 internal constant VaultT1__TickIsEmpty = 31005;\n\n    /// @notice thrown when the user's position is above CF and the user tries to make it more risky by trying to withdraw or borrow\n    uint256 internal constant VaultT1__PositionAboveCF = 31006;\n\n    /// @notice thrown when the top tick is not initialized. Happens if the vault is totally new or all the user's left\n    uint256 internal constant VaultT1__TopTickDoesNotExist = 31007;\n\n    /// @notice thrown when msg.value in liquidate is not in sync payback\n    uint256 internal constant VaultT1__InvalidMsgValueLiquidate = 31008;\n\n    /// @notice thrown when slippage is more on liquidation than what the liquidator sent\n    uint256 internal constant VaultT1__ExcessSlippageLiquidation = 31009;\n\n    /// @notice thrown when msg.sender is not the rebalancer/reserve contract\n    uint256 internal constant VaultT1__NotRebalancer = 31010;\n\n    /// @notice thrown when NFT of one vault interacts with the NFT of other vault\n    uint256 internal constant VaultT1__NftNotOfThisVault = 31011;\n\n    /// @notice thrown when the token is not initialized on the liquidity contract\n    uint256 internal constant VaultT1__TokenNotInitialized = 31012;\n\n    /// @notice thrown when admin updates fallback if a non-auth calls vault\n    uint256 internal constant VaultT1__NotAnAuth = 31013;\n\n    /// @notice thrown in operate when user tries to witdhraw more collateral than deposited\n    uint256 internal constant VaultT1__ExcessCollateralWithdrawal = 31014;\n\n    /// @notice thrown in operate when user tries to payback more debt than borrowed\n    uint256 internal constant VaultT1__ExcessDebtPayback = 31015;\n\n    /// @notice thrown when user try to withdrawal more than operate's withdrawal limit\n    uint256 internal constant VaultT1__WithdrawMoreThanOperateLimit = 31016;\n\n    /// @notice thrown when caller of liquidityCallback is not Liquidity\n    uint256 internal constant VaultT1__InvalidLiquidityCallbackAddress = 31017;\n\n    /// @notice thrown when reentrancy is not already on\n    uint256 internal constant VaultT1__NotEntered = 31018;\n\n    /// @notice thrown when someone directly calls secondary implementation contract\n    uint256 internal constant VaultT1__OnlyDelegateCallAllowed = 31019;\n\n    /// @notice thrown when the safeTransferFrom for a token amount failed\n    uint256 internal constant VaultT1__TransferFromFailed = 31020;\n\n    /// @notice thrown when exchange price overflows while updating on storage\n    uint256 internal constant VaultT1__ExchangePriceOverFlow = 31021;\n\n    /// @notice thrown when debt to liquidate amt is sent wrong\n    uint256 internal constant VaultT1__InvalidLiquidationAmt = 31022;\n\n    /// @notice thrown when user debt or collateral goes above 2**128 or below -2**128\n    uint256 internal constant VaultT1__UserCollateralDebtExceed = 31023;\n\n    /// @notice thrown if on liquidation branch debt becomes lower than 100\n    uint256 internal constant VaultT1__BranchDebtTooLow = 31024;\n\n    /// @notice thrown when tick's debt is less than 10000\n    uint256 internal constant VaultT1__TickDebtTooLow = 31025;\n\n    /// @notice thrown when the received new liquidity exchange price is of unexpected value (< than the old one)\n    uint256 internal constant VaultT1__LiquidityExchangePriceUnexpected = 31026;\n\n    /// @notice thrown when user's debt is less than 10000\n    uint256 internal constant VaultT1__UserDebtTooLow = 31027;\n\n    /// @notice thrown when on only payback and only deposit the ratio of position increases\n    uint256 internal constant VaultT1__InvalidPaybackOrDeposit = 31028;\n\n    /// @notice thrown when liquidation just happens of a single partial or when there's nothing to liquidate\n    uint256 internal constant VaultT1__InvalidLiquidation = 31029;\n\n    /// @notice thrown when msg.value is sent wrong in rebalance\n    uint256 internal constant VaultT1__InvalidMsgValueInRebalance = 31030;\n\n    /// @notice thrown when nothing rebalanced\n    uint256 internal constant VaultT1__NothingToRebalance = 31031;\n\n    /// @notice thrown on unforseen liquidation scenarios. Might never come in use.\n    uint256 internal constant VaultT1__LiquidationReverts = 31032;\n\n    /// @notice thrown when oracle price is > 1e54\n    uint256 internal constant VaultT1__InvalidOraclePrice = 31033;\n\n    /***********************************|\n    |              ERC721               | \n    |__________________________________*/\n\n    uint256 internal constant ERC721__InvalidParams = 32001;\n    uint256 internal constant ERC721__Unauthorized = 32002;\n    uint256 internal constant ERC721__InvalidOperation = 32003;\n    uint256 internal constant ERC721__UnsafeRecipient = 32004;\n    uint256 internal constant ERC721__OutOfBoundsIndex = 32005;\n\n    /***********************************|\n    |            Vault Admin            | \n    |__________________________________*/\n\n    /// @notice thrown when admin tries to setup invalid value which are crossing limits\n    uint256 internal constant VaultT1Admin__ValueAboveLimit = 33001;\n\n    /// @notice when someone directly calls admin implementation contract\n    uint256 internal constant VaultT1Admin__OnlyDelegateCallAllowed = 33002;\n\n    /// @notice thrown when auth sends NFT ID as 0 while collecting dust debt\n    uint256 internal constant VaultT1Admin__NftIdShouldBeNonZero = 33003;\n\n    /// @notice thrown when trying to collect dust debt of NFT which is not of this vault\n    uint256 internal constant VaultT1Admin__NftNotOfThisVault = 33004;\n\n    /// @notice thrown when dust debt of NFT is 0, meaning nothing to collect\n    uint256 internal constant VaultT1Admin__DustDebtIsZero = 33005;\n\n    /// @notice thrown when final debt after liquidation is not 0, meaning position 100% liquidated\n    uint256 internal constant VaultT1Admin__FinalDebtShouldBeZero = 33006;\n\n    /// @notice thrown when NFT is not liquidated state\n    uint256 internal constant VaultT1Admin__NftNotLiquidated = 33007;\n\n    /// @notice thrown when total absorbed dust debt is 0\n    uint256 internal constant VaultT1Admin__AbsorbedDustDebtIsZero = 33008;\n\n    /// @notice thrown when address is set as 0\n    uint256 internal constant VaultT1Admin__AddressZeroNotAllowed = 33009;\n\n    /***********************************|\n    |            Vault Rewards          | \n    |__________________________________*/\n\n    uint256 internal constant VaultRewards__Unauthorized = 34001;\n    uint256 internal constant VaultRewards__AddressZero = 34002;\n    uint256 internal constant VaultRewards__InvalidParams = 34003;\n    uint256 internal constant VaultRewards__NewMagnifierSameAsOldMagnifier = 34004;\n    uint256 internal constant VaultRewards__NotTheInitiator = 34005;\n    uint256 internal constant VaultRewards__AlreadyStarted = 34006;\n    uint256 internal constant VaultRewards__RewardsNotStartedOrEnded = 34007;\n}\n"
      },
      "contracts/protocols/vault/interfaces/iVaultT1.sol": {
        "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface IFluidVaultT1 {\n    /// @notice returns the vault id\n    function VAULT_ID() external view returns (uint256);\n\n    /// @notice reads uint256 data `result_` from storage at a bytes32 storage `slot_` key.\n    function readFromStorage(bytes32 slot_) external view returns (uint256 result_);\n\n    struct ConstantViews {\n        address liquidity;\n        address factory;\n        address adminImplementation;\n        address secondaryImplementation;\n        address supplyToken;\n        address borrowToken;\n        uint8 supplyDecimals;\n        uint8 borrowDecimals;\n        uint vaultId;\n        bytes32 liquiditySupplyExchangePriceSlot;\n        bytes32 liquidityBorrowExchangePriceSlot;\n        bytes32 liquidityUserSupplySlot;\n        bytes32 liquidityUserBorrowSlot;\n    }\n\n    /// @notice returns all Vault constants\n    function constantsView() external view returns (ConstantViews memory constantsView_);\n\n    /// @notice fetches the latest user position after a liquidation\n    function fetchLatestPosition(\n        int256 positionTick_,\n        uint256 positionTickId_,\n        uint256 positionRawDebt_,\n        uint256 tickData_\n    )\n        external\n        view\n        returns (\n            int256, // tick\n            uint256, // raw debt\n            uint256, // raw collateral\n            uint256, // branchID_\n            uint256 // branchData_\n        );\n\n    /// @notice calculates the updated vault exchange prices\n    function updateExchangePrices(\n        uint256 vaultVariables2_\n    )\n        external\n        view\n        returns (\n            uint256 liqSupplyExPrice_,\n            uint256 liqBorrowExPrice_,\n            uint256 vaultSupplyExPrice_,\n            uint256 vaultBorrowExPrice_\n        );\n\n    /// @notice calculates the updated vault exchange prices and writes them to storage\n    function updateExchangePricesOnStorage()\n        external\n        returns (\n            uint256 liqSupplyExPrice_,\n            uint256 liqBorrowExPrice_,\n            uint256 vaultSupplyExPrice_,\n            uint256 vaultBorrowExPrice_\n        );\n\n    /// @notice returns the liquidity contract address\n    function LIQUIDITY() external view returns (address);\n\n    function operate(\n        uint256 nftId_, // if 0 then new position\n        int256 newCol_, // if negative then withdraw\n        int256 newDebt_, // if negative then payback\n        address to_ // address at which the borrow & withdraw amount should go to. If address(0) then it'll go to msg.sender\n    )\n        external\n        payable\n        returns (\n            uint256, // nftId_\n            int256, // final supply amount. if - then withdraw\n            int256 // final borrow amount. if - then payback\n        );\n    \n    function liquidate(\n        uint256 debtAmt_,\n        uint256 colPerUnitDebt_, // min collateral needed per unit of debt in 1e18\n        address to_,\n        bool absorb_\n    ) external payable returns (uint actualDebtAmt_, uint actualColAmt_);\n\n    function absorb() external;\n\n    function rebalance() external payable returns (int supplyAmt_, int borrowAmt_);\n\n    error FluidLiquidateResult(uint256 colLiquidated, uint256 debtLiquidated);\n}\n"
      },
      "contracts/protocols/vault/rewards/events.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nabstract contract Events {\n    /// @notice Emitted when magnifier is updated\n    event LogUpdateMagnifier(address indexed vault, uint256 newMagnifier);\n\n    /// @notice Emitted when rewards are started\n    event LogRewardsStarted(uint256 startTime, uint256 endTime);\n}\n"
      },
      "contracts/protocols/vault/rewards/main.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { FluidVaultT1Admin } from \"../vaultT1/adminModule/main.sol\";\nimport { IFluidVaultT1 } from \"../interfaces/iVaultT1.sol\";\nimport { IFluidReserveContract } from \"../../../reserve/interfaces/iReserveContract.sol\";\nimport { LiquiditySlotsLink } from \"../../../libraries/liquiditySlotsLink.sol\";\nimport { Events } from \"./events.sol\";\nimport { Variables } from \"./variables.sol\";\nimport { ErrorTypes } from \"../errorTypes.sol\";\nimport { Error } from \"../error.sol\";\nimport { IFluidLiquidity } from \"../../../liquidity/interfaces/iLiquidity.sol\";\n\n/// @title VaultRewards\n/// @notice This contract is designed to adjust the supply rate magnifier for a vault based on the current collateral supply & supply rate.\n/// The adjustment aims to dynamically scale the rewards given to lenders as the TVL in the vault changes.\n///\n/// The magnifier is adjusted based on a regular most used reward type where rewardRate = totalRewardsAnnually / totalSupply.\n/// Reward rate is applied by adjusting the supply magnifier on vault.\n/// Adjustments are made via the rebalance function, which is restricted to be called by designated rebalancers only.\ncontract FluidVaultRewards is Variables, Events, Error {\n    /// @dev Validates that an address is not the zero address\n    modifier validAddress(address value_) {\n        if (value_ == address(0)) {\n            revert FluidVaultError(ErrorTypes.VaultRewards__AddressZero);\n        }\n        _;\n    }\n\n    /// @dev Validates that an address is a rebalancer (taken from reserve contract)\n    modifier onlyRebalancer() {\n        if (!RESERVE_CONTRACT.isRebalancer(msg.sender)) {\n            revert FluidVaultError(ErrorTypes.VaultRewards__Unauthorized);\n        }\n        _;\n    }\n\n    /// @notice Constructs the FluidVaultRewards contract.\n    /// @param reserveContract_ The address of the reserve contract where rebalancers are defined.\n    /// @param vault_ The vault to which this contract will apply new magnifier parameter.\n    /// @param liquidity_ Fluid liquidity address\n    /// @param rewardsAmt_ Amounts of rewards to distribute\n    /// @param duration_ rewards duration\n    /// @param initiator_ address that can start rewards with `start()`\n    /// @param collateralToken_ vault collateral token address\n    constructor(\n        IFluidReserveContract reserveContract_,\n        IFluidVaultT1 vault_,\n        IFluidLiquidity liquidity_,\n        uint256 rewardsAmt_,\n        uint256 duration_,\n        address initiator_,\n        address collateralToken_\n    ) validAddress(address(reserveContract_)) validAddress(address(liquidity_))  validAddress(address(vault_)) validAddress(initiator_)  validAddress(address(collateralToken_)){\n        if (rewardsAmt_ == 0 || duration_ == 0) {\n            revert FluidVaultError(ErrorTypes.VaultRewards__InvalidParams);\n        }\n        RESERVE_CONTRACT = reserveContract_;\n        VAULT = vault_;\n        REWARDS_AMOUNT = rewardsAmt_;\n        REWARDS_AMOUNT_PER_YEAR = rewardsAmt_ * SECONDS_PER_YEAR / duration_;\n        DURATION = duration_;\n        INITIATOR = initiator_;\n        LIQUIDITY = liquidity_;\n        VAULT_COLLATERAL_TOKEN = collateralToken_;\n\n        LIQUIDITY_TOTAL_AMOUNTS_COLLATERAL_TOKEN_SLOT = LiquiditySlotsLink.calculateMappingStorageSlot(\n            LiquiditySlotsLink.LIQUIDITY_TOTAL_AMOUNTS_MAPPING_SLOT,\n            collateralToken_\n        );\n        LIQUIDITY_EXCHANGE_PRICE_COLLATERAL_TOKEN_SLOT = LiquiditySlotsLink.calculateMappingStorageSlot(\n            LiquiditySlotsLink.LIQUIDITY_EXCHANGE_PRICES_MAPPING_SLOT,\n            collateralToken_\n        );\n    }\n\n    /// @notice Rebalances the supply rate magnifier based on the current collateral supply.\n    /// Can only be called by an authorized rebalancer.\n    function rebalance() external onlyRebalancer {\n        (uint256 newMagnifier_, bool ended_) = calculateMagnifier();\n        if (ended_) {\n            ended = true;\n        }\n        if (newMagnifier_ == currentMagnifier()) {\n            revert FluidVaultError(ErrorTypes.VaultRewards__NewMagnifierSameAsOldMagnifier);\n        }\n\n        FluidVaultT1Admin(address(VAULT)).updateSupplyRateMagnifier(newMagnifier_);\n        emit LogUpdateMagnifier(address(VAULT), newMagnifier_);\n    }\n\n    /// @notice Calculates the new supply rate magnifier based on the current collateral supply (`vaultTVL()`).\n    /// @return magnifier_ The calculated magnifier value.\n    function calculateMagnifier() public view returns (uint256 magnifier_, bool ended_) {\n        uint256 currentTVL_ = vaultTVL();\n        uint256 startTime_ = uint256(startTime);\n        uint256 endTime_ = uint256(endTime);\n\n        if (startTime_ == 0 || endTime_ == 0 || ended) {\n            revert FluidVaultError(ErrorTypes.VaultRewards__RewardsNotStartedOrEnded);\n        }\n\n        if (block.timestamp > endTime_) {\n            return (FOUR_DECIMALS, true);\n        }\n\n        uint supplyRate_ = getSupplyRate();\n        uint rewardsRate_ = (REWARDS_AMOUNT_PER_YEAR * FOUR_DECIMALS) / currentTVL_;\n\n        magnifier_ = FOUR_DECIMALS + (supplyRate_ == 0 ? rewardsRate_ : ((rewardsRate_ * FOUR_DECIMALS) / supplyRate_));\n        if (magnifier_ > X16) {\n            magnifier_ = X16;\n        }\n    }\n\n    /// @notice returns the currently configured supply magnifier at the `VAULT`.\n    function currentMagnifier() public view returns (uint256) {\n        // read supply rate magnifier from Vault `vaultVariables2` located in storage slot 1, first 16 bits\n        return VAULT.readFromStorage(bytes32(uint256(1))) & X16;\n    }\n\n    /// @notice returns the current total value locked as collateral (TVL) in the `VAULT`.\n    function vaultTVL() public view returns (uint256 tvl_) {\n        // read total supply raw in vault from storage slot 0 `vaultVariables`, 64 bits 82-145\n        tvl_ = (VAULT.readFromStorage(bytes32(0)) >> 82) & 0xFFFFFFFFFFFFFFFF;\n\n        // Converting bignumber into normal number\n        tvl_ = (tvl_ >> 8) << (tvl_ & 0xFF);\n\n        // get updated supply exchange price, which takes slot 1 `vaultVariables2` as input param\n        (, , uint256 vaultSupplyExPrice_, ) = VAULT.updateExchangePrices(VAULT.readFromStorage(bytes32(uint256(1))));\n\n        // converting raw total supply into normal amount\n        tvl_ = (tvl_ * vaultSupplyExPrice_) / 1e12;\n    }\n\n    function getSupplyRate() public view returns (uint supplyRate_) {\n        uint256 exchangePriceAndConfig_ = LIQUIDITY.readFromStorage(LIQUIDITY_EXCHANGE_PRICE_COLLATERAL_TOKEN_SLOT);\n        uint256 totalAmounts_ = LIQUIDITY.readFromStorage(LIQUIDITY_TOTAL_AMOUNTS_COLLATERAL_TOKEN_SLOT);\n\n        uint borrowRate_ = exchangePriceAndConfig_ & X16;\n        uint fee_ = (exchangePriceAndConfig_ >> LiquiditySlotsLink.BITS_EXCHANGE_PRICES_FEE) & X14;\n        uint supplyExchangePrice_ = ((exchangePriceAndConfig_ >>\n            LiquiditySlotsLink.BITS_EXCHANGE_PRICES_SUPPLY_EXCHANGE_PRICE) & X64);\n        uint borrowExchangePrice_ = ((exchangePriceAndConfig_ >>\n            LiquiditySlotsLink.BITS_EXCHANGE_PRICES_BORROW_EXCHANGE_PRICE) & X64);\n\n        // Extract supply raw interest\n        uint256 supplyWithInterest_ = totalAmounts_ & X64;\n        supplyWithInterest_ =\n            (supplyWithInterest_ >> DEFAULT_EXPONENT_SIZE) <<\n            (supplyWithInterest_ & DEFAULT_EXPONENT_MASK);\n\n        // Extract borrow raw interest\n        uint256 borrowWithInterest_ = (totalAmounts_ >> LiquiditySlotsLink.BITS_TOTAL_AMOUNTS_BORROW_WITH_INTEREST) &\n            X64;\n        borrowWithInterest_ =\n            (borrowWithInterest_ >> DEFAULT_EXPONENT_SIZE) <<\n            (borrowWithInterest_ & DEFAULT_EXPONENT_MASK);\n\n        if (supplyWithInterest_ > 0) {\n            // use old exchange prices for supply rate to be at same level as borrow rate from storage.\n            // Note the rate here can be a tiny bit with higher precision because we use borrowWithInterest_ / supplyWithInterest_\n            // which has higher precision than the utilization used from storage in LiquidityCalcs\n            supplyWithInterest_ = (supplyWithInterest_ * supplyExchangePrice_) / EXCHANGE_PRICES_PRECISION; // normalized from raw\n            borrowWithInterest_ = (borrowWithInterest_ * borrowExchangePrice_) / EXCHANGE_PRICES_PRECISION; // normalized from raw\n\n            supplyRate_ =\n                (borrowRate_ * (FOUR_DECIMALS - fee_) * borrowWithInterest_) /\n                (supplyWithInterest_ * FOUR_DECIMALS);\n        }\n    }\n\n    function start() external {\n        if (msg.sender != INITIATOR) {\n            revert FluidVaultError(ErrorTypes.VaultRewards__NotTheInitiator);\n        }\n        if (startTime > 0 || endTime > 0) {\n            revert FluidVaultError(ErrorTypes.VaultRewards__AlreadyStarted);\n        }\n        startTime = uint96(block.timestamp);\n        endTime = uint96(block.timestamp + DURATION);\n\n        emit LogRewardsStarted(startTime, endTime);\n    }\n}\n"
      },
      "contracts/protocols/vault/rewards/variables.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidReserveContract } from \"../../../reserve/interfaces/iReserveContract.sol\";\nimport { IFluidVaultT1 } from \"../interfaces/iVaultT1.sol\";\nimport { IFluidLiquidity } from \"../../../liquidity/interfaces/iLiquidity.sol\";\n\nabstract contract Constants {\n    IFluidLiquidity public immutable LIQUIDITY;\n    IFluidReserveContract public immutable RESERVE_CONTRACT;\n    IFluidVaultT1 public immutable VAULT;\n    uint256 public immutable REWARDS_AMOUNT;\n    uint256 public immutable REWARDS_AMOUNT_PER_YEAR;\n    uint256 public immutable DURATION;\n    address public immutable INITIATOR;\n    address public immutable VAULT_COLLATERAL_TOKEN;\n\n    bytes32 internal immutable LIQUIDITY_TOTAL_AMOUNTS_COLLATERAL_TOKEN_SLOT;\n    bytes32 internal immutable LIQUIDITY_EXCHANGE_PRICE_COLLATERAL_TOKEN_SLOT;\n    uint256 internal constant FOUR_DECIMALS = 10000;\n    uint256 internal constant SECONDS_PER_YEAR = 365 days;\n    uint256 internal constant DEFAULT_EXPONENT_SIZE = 8;\n    uint256 internal constant DEFAULT_EXPONENT_MASK = 0xff;\n    uint256 internal constant EXCHANGE_PRICES_PRECISION = 1e12;\n    uint256 internal constant X14 = 0x3fff;\n    uint256 internal constant X16 = 0xffff;\n    uint256 internal constant X64 = 0xffffffffffffffff;\n}\n\nabstract contract Variables is Constants {\n    bool public ended; // when rewards are ended\n    uint96 public startTime;\n    uint96 public endTime;\n}\n"
      },
      "contracts/protocols/vault/vaultT1/adminModule/events.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ncontract Events {\n    /// @notice emitted when the supply rate magnifier config is updated\n    event LogUpdateSupplyRateMagnifier(uint supplyRateMagnifier_);\n\n    /// @notice emitted when the borrow rate magnifier config is updated\n    event LogUpdateBorrowRateMagnifier(uint borrowRateMagnifier_);\n\n    /// @notice emitted when the collateral factor config is updated\n    event LogUpdateCollateralFactor(uint collateralFactor_);\n\n    /// @notice emitted when the liquidation threshold config is updated\n    event LogUpdateLiquidationThreshold(uint liquidationThreshold_);\n\n    /// @notice emitted when the liquidation max limit config is updated\n    event LogUpdateLiquidationMaxLimit(uint liquidationMaxLimit_);\n\n    /// @notice emitted when the withdrawal gap config is updated\n    event LogUpdateWithdrawGap(uint withdrawGap_);\n\n    /// @notice emitted when the liquidation penalty config is updated\n    event LogUpdateLiquidationPenalty(uint liquidationPenalty_);\n\n    /// @notice emitted when the borrow fee config is updated\n    event LogUpdateBorrowFee(uint borrowFee_);\n\n    /// @notice emitted when the core setting configs are updated\n    event LogUpdateCoreSettings(\n        uint supplyRateMagnifier_,\n        uint borrowRateMagnifier_,\n        uint collateralFactor_,\n        uint liquidationThreshold_,\n        uint liquidationMaxLimit_,\n        uint withdrawGap_,\n        uint liquidationPenalty_,\n        uint borrowFee_\n    );\n\n    /// @notice emitted when the oracle is updated\n    event LogUpdateOracle(address indexed newOracle_);\n\n    /// @notice emitted when the allowed rebalancer is updated\n    event LogUpdateRebalancer(address indexed newRebalancer_);\n\n    /// @notice emitted when funds are rescued\n    event LogRescueFunds(address indexed token_);\n\n    /// @notice emitted when dust debt is absorbed for `nftIds_`\n    event LogAbsorbDustDebt(uint256[] nftIds_, uint256 absorbedDustDebt_);\n}\n"
      },
      "contracts/protocols/vault/vaultT1/adminModule/main.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\nimport { Variables } from \"../common/variables.sol\";\nimport { Events } from \"./events.sol\";\nimport { ErrorTypes } from \"../../errorTypes.sol\";\nimport { Error } from \"../../error.sol\";\nimport { IFluidVaultT1 } from \"../../interfaces/iVaultT1.sol\";\nimport { BigMathMinified } from \"../../../../libraries/bigMathMinified.sol\";\nimport { TickMath } from \"../../../../libraries/tickMath.sol\";\n\n/// @notice Fluid Vault protocol Admin Module contract.\n///         Implements admin related methods to set configs such as liquidation params, rates\n///         oracle address etc.\n///         Methods are limited to be called via delegateCall only. Vault CoreModule (\"VaultT1\" contract)\n///         is expected to call the methods implemented here after checking the msg.sender is authorized.\n///         All methods update the exchange prices in storage before changing configs.\ncontract FluidVaultT1Admin is Variables, Events, Error {\n    uint private constant X8 = 0xff;\n    uint private constant X10 = 0x3ff;\n    uint private constant X16 = 0xffff;\n    uint private constant X19 = 0x7ffff;\n    uint private constant X24 = 0xffffff;\n    uint internal constant X64 = 0xffffffffffffffff;\n    uint private constant X96 = 0xffffffffffffffffffffffff;\n    address private constant NATIVE_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n    address private immutable addressThis;\n\n    constructor() {\n        addressThis = address(this);\n    }\n\n    modifier _verifyCaller() {\n        if (address(this) == addressThis) {\n            revert FluidVaultError(ErrorTypes.VaultT1Admin__OnlyDelegateCallAllowed);\n        }\n        _;\n    }\n\n    /// @dev updates exchange price on storage, called on all admin methods in combination with _verifyCaller modifier so\n    /// only called by authorized delegatecall\n    modifier _updateExchangePrice() {\n        IFluidVaultT1(address(this)).updateExchangePricesOnStorage();\n        _;\n    }\n\n    function _checkLiquidationMaxLimitAndPenalty(uint liquidationMaxLimit_, uint liquidationPenalty_) private pure {\n        // liquidation max limit with penalty should not go above 99.7%\n        // As liquidation with penalty can happen from liquidation Threshold to max limit\n        // If it goes above 100% than that means liquidator is getting more collateral than user's available\n        if ((liquidationMaxLimit_ + liquidationPenalty_) > 9970) {\n            revert FluidVaultError(ErrorTypes.VaultT1Admin__ValueAboveLimit);\n        }\n    }\n\n    /// @notice updates the supply rate magnifier to `supplyRateMagnifier_`. Input in 1e2 (1% = 100, 100% = 10_000).\n    function updateSupplyRateMagnifier(uint supplyRateMagnifier_) public _updateExchangePrice _verifyCaller {\n        emit LogUpdateSupplyRateMagnifier(supplyRateMagnifier_);\n\n        if (supplyRateMagnifier_ > X16) revert FluidVaultError(ErrorTypes.VaultT1Admin__ValueAboveLimit);\n\n        vaultVariables2 =\n            (vaultVariables2 & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000) |\n            supplyRateMagnifier_;\n    }\n\n    /// @notice updates the borrow rate magnifier to `borrowRateMagnifier_`. Input in 1e2 (1% = 100, 100% = 10_000).\n    function updateBorrowRateMagnifier(uint borrowRateMagnifier_) public _updateExchangePrice _verifyCaller {\n        emit LogUpdateBorrowRateMagnifier(borrowRateMagnifier_);\n\n        if (borrowRateMagnifier_ > X16) revert FluidVaultError(ErrorTypes.VaultT1Admin__ValueAboveLimit);\n\n        vaultVariables2 =\n            (vaultVariables2 & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffff) |\n            (borrowRateMagnifier_ << 16);\n    }\n\n    /// @notice updates the collateral factor to `collateralFactor_`. Input in 1e2 (1% = 100, 100% = 10_000).\n    function updateCollateralFactor(uint collateralFactor_) public _updateExchangePrice _verifyCaller {\n        emit LogUpdateCollateralFactor(collateralFactor_);\n\n        uint vaultVariables2_ = vaultVariables2;\n        uint liquidationThreshold_ = ((vaultVariables2_ >> 42) & X10);\n\n        collateralFactor_ = collateralFactor_ / 10;\n\n        if (collateralFactor_ >= liquidationThreshold_)\n            revert FluidVaultError(ErrorTypes.VaultT1Admin__ValueAboveLimit);\n\n        vaultVariables2 =\n            (vaultVariables2_ & 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffc00ffffffff) |\n            (collateralFactor_ << 32);\n    }\n\n    /// @notice updates the liquidation threshold to `liquidationThreshold_`. Input in 1e2 (1% = 100, 100% = 10_000).\n    function updateLiquidationThreshold(uint liquidationThreshold_) public _updateExchangePrice _verifyCaller {\n        emit LogUpdateLiquidationThreshold(liquidationThreshold_);\n\n        uint vaultVariables2_ = vaultVariables2;\n        uint collateralFactor_ = ((vaultVariables2_ >> 32) & X10);\n        uint liquidationMaxLimit_ = ((vaultVariables2_ >> 52) & X10);\n\n        liquidationThreshold_ = liquidationThreshold_ / 10;\n\n        if ((collateralFactor_ >= liquidationThreshold_) || (liquidationThreshold_ >= liquidationMaxLimit_))\n            revert FluidVaultError(ErrorTypes.VaultT1Admin__ValueAboveLimit);\n\n        vaultVariables2 =\n            (vaultVariables2_ & 0xfffffffffffffffffffffffffffffffffffffffffffffffffff003ffffffffff) |\n            (liquidationThreshold_ << 42);\n    }\n\n    /// @notice updates the liquidation max limit to `liquidationMaxLimit_`. Input in 1e2 (1% = 100, 100% = 10_000).\n    function updateLiquidationMaxLimit(uint liquidationMaxLimit_) public _updateExchangePrice _verifyCaller {\n        emit LogUpdateLiquidationMaxLimit(liquidationMaxLimit_);\n\n        uint vaultVariables2_ = vaultVariables2;\n        uint liquidationThreshold_ = ((vaultVariables2_ >> 42) & X10);\n        uint liquidationPenalty_ = ((vaultVariables2_ >> 72) & X10);\n\n        // both are in 1e2 decimals (1e2 = 1%)\n        _checkLiquidationMaxLimitAndPenalty(liquidationMaxLimit_, liquidationPenalty_);\n\n        liquidationMaxLimit_ = liquidationMaxLimit_ / 10;\n\n        if (liquidationThreshold_ >= liquidationMaxLimit_)\n            revert FluidVaultError(ErrorTypes.VaultT1Admin__ValueAboveLimit);\n\n        vaultVariables2 =\n            (vaultVariables2_ & 0xffffffffffffffffffffffffffffffffffffffffffffffffc00fffffffffffff) |\n            (liquidationMaxLimit_ << 52);\n    }\n\n    /// @notice updates the withdrawal gap to `withdrawGap_`. Input in 1e2 (1% = 100, 100% = 10_000).\n    function updateWithdrawGap(uint withdrawGap_) public _updateExchangePrice _verifyCaller {\n        emit LogUpdateWithdrawGap(withdrawGap_);\n\n        withdrawGap_ = withdrawGap_ / 10;\n\n        // withdrawGap must not be > 100%\n        if (withdrawGap_ > 1000) revert FluidVaultError(ErrorTypes.VaultT1Admin__ValueAboveLimit);\n\n        vaultVariables2 =\n            (vaultVariables2 & 0xffffffffffffffffffffffffffffffffffffffffffffff003fffffffffffffff) |\n            (withdrawGap_ << 62);\n    }\n\n    /// @notice updates the liquidation penalty to `liquidationPenalty_`. Input in 1e2 (1% = 100, 100% = 10_000).\n    function updateLiquidationPenalty(uint liquidationPenalty_) public _updateExchangePrice _verifyCaller {\n        emit LogUpdateLiquidationPenalty(liquidationPenalty_);\n\n        uint vaultVariables2_ = vaultVariables2;\n        uint liquidationMaxLimit_ = ((vaultVariables2_ >> 52) & X10);\n\n        // Converting liquidationMaxLimit_ in 1e2 decimals (1e2 = 1%)\n        _checkLiquidationMaxLimitAndPenalty((liquidationMaxLimit_ * 10), liquidationPenalty_);\n\n        if (liquidationPenalty_ > X10) revert FluidVaultError(ErrorTypes.VaultT1Admin__ValueAboveLimit);\n\n        vaultVariables2 =\n            (vaultVariables2_ & 0xfffffffffffffffffffffffffffffffffffffffffffc00ffffffffffffffffff) |\n            (liquidationPenalty_ << 72);\n    }\n\n    /// @notice updates the borrow fee to `borrowFee_`. Input in 1e2 (1% = 100, 100% = 10_000).\n    function updateBorrowFee(uint borrowFee_) public _updateExchangePrice _verifyCaller {\n        emit LogUpdateBorrowFee(borrowFee_);\n\n        if (borrowFee_ > X10) revert FluidVaultError(ErrorTypes.VaultT1Admin__ValueAboveLimit);\n\n        vaultVariables2 =\n            (vaultVariables2 & 0xfffffffffffffffffffffffffffffffffffffffff003ffffffffffffffffffff) |\n            (borrowFee_ << 82);\n    }\n\n    /// @notice updates the all Vault core settings according to input params.\n    /// All input values are expected in 1e2 (1% = 100, 100% = 10_000).\n    function updateCoreSettings(\n        uint256 supplyRateMagnifier_,\n        uint256 borrowRateMagnifier_,\n        uint256 collateralFactor_,\n        uint256 liquidationThreshold_,\n        uint256 liquidationMaxLimit_,\n        uint256 withdrawGap_,\n        uint256 liquidationPenalty_,\n        uint256 borrowFee_\n    ) public _updateExchangePrice _verifyCaller {\n        // emitting the event at the start as then we are updating numbers to store in a more optimized way\n        emit LogUpdateCoreSettings(\n            supplyRateMagnifier_,\n            borrowRateMagnifier_,\n            collateralFactor_,\n            liquidationThreshold_,\n            liquidationMaxLimit_,\n            withdrawGap_,\n            liquidationPenalty_,\n            borrowFee_\n        );\n\n        _checkLiquidationMaxLimitAndPenalty(liquidationMaxLimit_, liquidationPenalty_);\n\n        collateralFactor_ = collateralFactor_ / 10;\n        liquidationThreshold_ = liquidationThreshold_ / 10;\n        liquidationMaxLimit_ = liquidationMaxLimit_ / 10;\n        withdrawGap_ = withdrawGap_ / 10;\n\n        if (\n            (supplyRateMagnifier_ > X16) ||\n            (borrowRateMagnifier_ > X16) ||\n            (collateralFactor_ >= liquidationThreshold_) ||\n            (liquidationThreshold_ >= liquidationMaxLimit_) ||\n            (withdrawGap_ > X10) ||\n            (liquidationPenalty_ > X10) ||\n            (borrowFee_ > X10)\n        ) {\n            revert FluidVaultError(ErrorTypes.VaultT1Admin__ValueAboveLimit);\n        }\n\n        vaultVariables2 =\n            (vaultVariables2 & 0xfffffffffffffffffffffffffffffffffffffffff00000000000000000000000) |\n            supplyRateMagnifier_ |\n            (borrowRateMagnifier_ << 16) |\n            (collateralFactor_ << 32) |\n            (liquidationThreshold_ << 42) |\n            (liquidationMaxLimit_ << 52) |\n            (withdrawGap_ << 62) |\n            (liquidationPenalty_ << 72) |\n            (borrowFee_ << 82);\n    }\n\n    /// @notice updates the Vault oracle to `newOracle_`. Must implement the FluidOracle interface.\n    function updateOracle(address newOracle_) public _updateExchangePrice _verifyCaller {\n        if (newOracle_ == address(0)) revert FluidVaultError(ErrorTypes.VaultT1Admin__AddressZeroNotAllowed);\n\n        // Removing current oracle by masking only first 96 bits then inserting new oracle as bits\n        vaultVariables2 = (vaultVariables2 & X96) | (uint256(uint160(newOracle_)) << 96);\n\n        emit LogUpdateOracle(newOracle_);\n    }\n\n    /// @notice updates the allowed rebalancer to `newRebalancer_`.\n    function updateRebalancer(address newRebalancer_) public _updateExchangePrice _verifyCaller {\n        if (newRebalancer_ == address(0)) revert FluidVaultError(ErrorTypes.VaultT1Admin__AddressZeroNotAllowed);\n\n        rebalancer = newRebalancer_;\n\n        emit LogUpdateRebalancer(newRebalancer_);\n    }\n\n    /// @notice sends any potentially stuck funds to Liquidity contract.\n    /// @dev this contract never holds any funds as all operations send / receive funds from user <-> Liquidity.\n    function rescueFunds(address token_) external _verifyCaller {\n        if (token_ == NATIVE_TOKEN) {\n            Address.sendValue(payable(IFluidVaultT1(address(this)).LIQUIDITY()), address(this).balance);\n        } else {\n            SafeERC20.safeTransfer(\n                IERC20(token_),\n                IFluidVaultT1(address(this)).LIQUIDITY(),\n                IERC20(token_).balanceOf(address(this))\n            );\n        }\n\n        emit LogRescueFunds(token_);\n    }\n\n    /// @notice absorbs accumulated dust debt\n    /// @dev in decades if a lot of positions are 100% liquidated (aka absorbed) then dust debt can mount up\n    /// which is basically sort of an extra revenue for the protocol.\n    //\n    // this function might never come in use that's why adding it in admin module\n    function absorbDustDebt(uint[] memory nftIds_) public _verifyCaller {\n        uint256 vaultVariables_ = vaultVariables;\n        // re-entrancy check\n        if (vaultVariables_ & 1 == 0) {\n            // Updating on storage\n            vaultVariables = vaultVariables_ | 1;\n        } else {\n            revert FluidVaultError(ErrorTypes.VaultT1__AlreadyEntered);\n        }\n\n        uint nftId_;\n        uint posData_;\n        int posTick_;\n        uint tickId_;\n        uint posCol_;\n        uint posDebt_;\n        uint posDustDebt_;\n        uint tickData_;\n\n        uint absorbedDustDebt_ = absorbedDustDebt;\n\n        for (uint i = 0; i < nftIds_.length; ) {\n            nftId_ = nftIds_[i];\n            if (nftId_ == 0) {\n                revert FluidVaultError(ErrorTypes.VaultT1Admin__NftIdShouldBeNonZero);\n            }\n\n            // user's position data\n            posData_ = positionData[nftId_];\n\n            if (posData_ == 0) {\n                revert FluidVaultError(ErrorTypes.VaultT1Admin__NftNotOfThisVault);\n            }\n\n            posCol_ = (posData_ >> 45) & X64;\n            // Converting big number into normal number\n            posCol_ = (posCol_ >> 8) << (posCol_ & X8);\n\n            posDustDebt_ = (posData_ >> 109) & X64;\n            // Converting big number into normal number\n            posDustDebt_ = (posDustDebt_ >> 8) << (posDustDebt_ & X8);\n\n            if (posDustDebt_ == 0) {\n                revert FluidVaultError(ErrorTypes.VaultT1Admin__DustDebtIsZero);\n            }\n\n            // borrow position (has collateral & debt)\n            posTick_ = posData_ & 2 == 2 ? int((posData_ >> 2) & X19) : -int((posData_ >> 2) & X19);\n            tickId_ = (posData_ >> 21) & X24;\n\n            posDebt_ = (TickMath.getRatioAtTick(int24(posTick_)) * posCol_) >> 96;\n\n            // Tick data from user's tick\n            tickData_ = tickData[posTick_];\n\n            // Checking if tick is liquidated OR if the total IDs of tick is greater than user's tick ID\n            if (((tickData_ & 1) == 1) || (((tickData_ >> 1) & X24) > tickId_)) {\n                // User got liquidated\n                (, posDebt_, , , ) = IFluidVaultT1(address(this)).fetchLatestPosition(\n                    posTick_,\n                    tickId_,\n                    posDebt_,\n                    tickData_\n                );\n                if (posDebt_ > 0) {\n                    revert FluidVaultError(ErrorTypes.VaultT1Admin__FinalDebtShouldBeZero);\n                }\n                // absorbing user's debt as it's 100% or almost 100% liquidated\n                absorbedDustDebt_ = absorbedDustDebt_ + posDustDebt_;\n                // making position as supply only\n                positionData[nftId_] = 1;\n            } else {\n                revert FluidVaultError(ErrorTypes.VaultT1Admin__NftNotLiquidated);\n            }\n\n            unchecked {\n                i++;\n            }\n        }\n\n        if (absorbedDustDebt_ == 0) {\n            revert FluidVaultError(ErrorTypes.VaultT1Admin__AbsorbedDustDebtIsZero);\n        }\n\n        uint totalBorrow_ = (vaultVariables_ >> 146) & X64;\n        // Converting big number into normal number\n        totalBorrow_ = (totalBorrow_ >> 8) << (totalBorrow_ & X8);\n        // note: by default dust debt is not added into total borrow but on 100% liquidation (aka absorb) dust debt equivalent\n        // is removed from total borrow so adding it back again here\n        totalBorrow_ = totalBorrow_ + absorbedDustDebt_;\n        totalBorrow_ = BigMathMinified.toBigNumber(totalBorrow_, 56, 8, BigMathMinified.ROUND_UP);\n\n        // adding absorbed dust debt to total borrow so it will get included in the next rebalancing.\n        // there is some fuzziness here as when the position got fully liquidated (aka absorbed) the exchange price was different\n        // than what it'll be now. The fuzziness which will be extremely small so we can ignore it\n        // updating on storage\n        vaultVariables =\n            (vaultVariables_ & 0xfffffffffffc0000000000000003ffffffffffffffffffffffffffffffffffff) |\n            (totalBorrow_ << 146);\n\n        // updating on storage\n        absorbedDustDebt = 0;\n\n        emit LogAbsorbDustDebt(nftIds_, absorbedDustDebt_);\n    }\n}\n"
      },
      "contracts/protocols/vault/vaultT1/common/variables.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ncontract Variables {\n    /***********************************|\n    |         Storage Variables         |\n    |__________________________________*/\n\n    /// note: in all variables. For tick >= 0 are represented with bit as 1, tick < 0 are represented with bit as 0\n    /// note: read all the variables through storageRead.sol\n\n    /// note: vaultVariables contains vault variables which need regular updates through transactions\n    /// First 1 bit => 0 => re-entrancy. If 0 then allow transaction to go, else throw.\n    /// Next 1 bit => 1 => Is the current active branch liquidated? If true then check the branch's minima tick before creating a new position\n    /// If the new tick is greater than minima tick then initialize a new branch, make that as current branch & do proper linking\n    /// Next 1 bit => 2 => sign of topmost tick (0 -> negative; 1 -> positive)\n    /// Next 19 bits => 3-21 => absolute value of topmost tick\n    /// Next 30 bits => 22-51 => current branch ID\n    /// Next 30 bits => 52-81 => total branch ID\n    /// Next 64 bits => 82-145 => Total supply\n    /// Next 64 bits => 146-209 => Total borrow\n    /// Next 32 bits => 210-241 => Total positions\n    uint256 internal vaultVariables;\n\n    /// note: vaultVariables2 contains variables which do not update on every transaction. So mainly admin/auth set amount\n    /// First 16 bits => 0-15 => supply rate magnifier; 10000 = 1x (Here 16 bits should be more than enough)\n    /// Next 16 bits => 16-31 => borrow rate magnifier; 10000 = 1x (Here 16 bits should be more than enough)\n    /// Next 10 bits => 32-41 => collateral factor. 800 = 0.8 = 80% (max precision of 0.1%)\n    /// Next 10 bits => 42-51 => liquidation Threshold. 900 = 0.9 = 90% (max precision of 0.1%)\n    /// Next 10 bits => 52-61 => liquidation Max Limit. 950 = 0.95 = 95% (max precision of 0.1%) (above this 100% liquidation can happen)\n    /// Next 10 bits => 62-71 => withdraw gap. 100 = 0.1 = 10%. (max precision of 0.1%) (max 7 bits can also suffice for the requirement here of 0.1% to 10%). Needed to save some limits on withdrawals so liquidate can work seamlessly.\n    /// Next 10 bits => 72-81 => liquidation penalty. 100 = 0.01 = 1%. (max precision of 0.01%) (max liquidation penantly can be 10.23%). Applies when tick is in between liquidation Threshold & liquidation Max Limit.\n    /// Next 10 bits => 82-91 => borrow fee. 100 = 0.01 = 1%. (max precision of 0.01%) (max borrow fee can be 10.23%). Fees on borrow.\n    /// Next 4  bits => 92-95 => empty\n    /// Next 160 bits => 96-255 => Oracle address\n    uint256 internal vaultVariables2;\n\n    /// note: stores absorbed liquidity\n    /// First 128 bits raw debt amount\n    /// last 128 bits raw col amount\n    uint256 internal absorbedLiquidity;\n\n    /// position index => position data uint\n    /// if the entire variable is 0 (meaning not initialized) at the start that means no position at all\n    /// First 1 bit => 0 => position type (0 => borrow position; 1 => supply position)\n    /// Next 1 bit => 1 => sign of user's tick (0 => negative; 1 => positive)\n    /// Next 19 bits => 2-20 => absolute value of user's tick\n    /// Next 24 bits => 21-44 => user's tick's id\n    /// Below we are storing user's collateral & not debt, because the position can also be only collateral with no tick but it can never be only debt\n    /// Next 64 bits => 45-108 => user's supply amount. Debt will be calculated through supply & ratio.\n    /// Next 64 bits => 109-172 => user's dust debt amount. User's net debt = total debt - dust amount. Total debt is calculated through supply & ratio\n    /// User won't pay any extra interest on dust debt & hence we will not show it as a debt on UI. For user's there's no dust.\n    mapping(uint256 => uint256) internal positionData;\n\n    /// Tick has debt only keeps data of non liquidated positions. liquidated tick's data stays in branch itself\n    /// tick parent => uint (represents bool for 256 children)\n    /// parent of (i)th tick:-\n    /// if (i>=0) (i / 256);\n    /// else ((i + 1) / 256) - 1\n    /// first bit of the variable is the smallest tick & last bit is the biggest tick of that slot\n    mapping(int256 => uint256) internal tickHasDebt;\n\n    /// mapping tickId => tickData\n    /// Tick related data. Total debt & other things\n    /// First bit => 0 => If 1 then liquidated else not liquidated\n    /// Next 24 bits => 1-24 => Total IDs. ID should start from 1.\n    /// If not liquidated:\n    /// Next 64 bits => 25-88 => raw debt\n    /// If liquidated\n    /// The below 3 things are of last ID. This is to be updated when user creates a new position\n    /// Next 1 bit => 25 => Is 100% liquidated? If this is 1 meaning it was above max tick when it got liquidated (100% liquidated)\n    /// Next 30 bits => 26-55 => branch ID where this tick got liquidated\n    /// Next 50 bits => 56-105 => debt factor 50 bits (35 bits coefficient | 15 bits expansion)\n    mapping(int256 => uint256) internal tickData;\n\n    /// tick id => previous tick id liquidation data. ID starts from 1\n    /// One tick ID contains 3 IDs of 80 bits in it, holding liquidation data of previously active but liquidated ticks\n    /// 81 bits data below\n    /// #### First 85 bits ####\n    /// 1st bit => 0 => Is 100% liquidated? If this is 1 meaning it was above max tick when it got liquidated\n    /// Next 30 bits => 1-30 => branch ID where this tick got liquidated\n    /// Next 50 bits => 31-80 => debt factor 50 bits (35 bits coefficient | 15 bits expansion)\n    /// #### Second 85 bits ####\n    /// 85th bit => 85 => Is 100% liquidated? If this is 1 meaning it was above max tick when it got liquidated\n    /// Next 30 bits => 86-115 => branch ID where this tick got liquidated\n    /// Next 50 bits => 116-165 => debt factor 50 bits (35 bits coefficient | 15 bits expansion)\n    /// #### Third 85 bits ####\n    /// 170th bit => 170 => Is 100% liquidated? If this is 1 meaning it was above max tick when it got liquidated\n    /// Next 30 bits => 171-200 => branch ID where this tick got liquidated\n    /// Next 50 bits => 201-250 => debt factor 50 bits (35 bits coefficient | 15 bits expansion)\n    mapping(int256 => mapping(uint256 => uint256)) internal tickId;\n\n    /// mapping branchId => branchData\n    /// First 2 bits => 0-1 => if 0 then not liquidated, if 1 then liquidated, if 2 then merged, if 3 then closed\n    /// merged means the branch is merged into it's base branch\n    /// closed means all the users are 100% liquidated\n    /// Next 1 bit => 2 => minima tick sign of this branch. Will only be there if any liquidation happened.\n    /// Next 19 bits => 3-21 => minima tick of this branch. Will only be there if any liquidation happened.\n    /// Next 30 bits => 22-51 => Partials of minima tick of branch this is connected to. 0 if master branch.\n    /// Next 64 bits => 52-115 Debt liquidity at this branch. Similar to last's top tick data. Remaining debt will move here from tickData after first liquidation\n    /// If not merged\n    /// Next 50 bits => 116-165 => Debt factor or of this branch. (35 bits coefficient | 15 bits expansion)\n    /// If merged\n    /// Next 50 bits => 116-165 => Connection/adjustment debt factor of this branch with the next branch.\n    /// If closed\n    /// Next 50 bits => 116-165 => Debt factor as 0. As all the user's positions are now fully gone\n    /// following values are present always again (merged / not merged / closed)\n    /// Next 30 bits => 166-195 => Branch's ID with which this branch is connected. If 0 then that means this is the master branch\n    /// Next 1 bit => 196 => sign of minima tick of branch this is connected to. 0 if master branch.\n    /// Next 19 bits => 197-215 => minima tick of branch this is connected to. 0 if master branch.\n    mapping(uint256 => uint256) internal branchData;\n\n    /// Exchange prices are in 1e12\n    /// First 64 bits => 0-63 => Liquidity's collateral token supply exchange price\n    /// First 64 bits => 64-127 => Liquidity's debt token borrow exchange price\n    /// First 64 bits => 128-191 => Vault's collateral token supply exchange price\n    /// First 64 bits => 192-255 => Vault's debt token borrow exchange price\n    uint256 internal rates;\n\n    /// address of rebalancer\n    address internal rebalancer;\n\n    uint256 internal absorbedDustDebt;\n}\n"
      },
      "contracts/reserve/interfaces/iReserveContract.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidLiquidity } from \"../../liquidity/interfaces/iLiquidity.sol\";\n\ninterface IFluidReserveContract {\n    function isRebalancer(address user) external returns (bool);\n\n    function initialize(\n        address[] memory _auths,\n        address[] memory _rebalancers,\n        IFluidLiquidity liquidity_,\n        address owner_\n    ) external;\n\n    function rebalanceFToken(address protocol_) external;\n\n    function rebalanceVault(address protocol_) external;\n\n    function transferFunds(address token_) external;\n\n    function getProtocolTokens(address protocol_) external;\n\n    function updateAuth(address auth_, bool isAuth_) external;\n\n    function updateRebalancer(address rebalancer_, bool isRebalancer_) external;\n\n    function approve(address[] memory protocols_, address[] memory tokens_, uint256[] memory amounts_) external;\n\n    function revoke(address[] memory protocols_, address[] memory tokens_) external;\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 10000000
      },
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}