creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/oracle/error.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ncontract Error {\n    error FluidOracleError(uint256 errorId_);\n}\n"
      },
      "contracts/oracle/errorTypes.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nlibrary ErrorTypes {\n    /***********************************|\n    |           FluidOracleL2           | \n    |__________________________________*/\n\n    /// @notice thrown when sequencer on a L2 has an outage and grace period has not yet passed.\n    uint256 internal constant FluidOracleL2__SequencerOutage = 60000;\n\n    /***********************************|\n    |     UniV3CheckCLRSOracle          | \n    |__________________________________*/\n\n    /// @notice thrown when the delta between main price source and check rate source is exceeding the allowed delta\n    uint256 internal constant UniV3CheckCLRSOracle__InvalidPrice = 60001;\n\n    /// @notice thrown when an invalid parameter is passed to a method\n    uint256 internal constant UniV3CheckCLRSOracle__InvalidParams = 60002;\n\n    /// @notice thrown when the exchange rate is zero, even after all possible fallbacks depending on config\n    uint256 internal constant UniV3CheckCLRSOracle__ExchangeRateZero = 60003;\n\n    /***********************************|\n    |            sUSDe Oracle           | \n    |__________________________________*/\n\n    /// @notice thrown when an invalid parameter is passed to a method\n    uint256 internal constant SUSDeOracle__InvalidParams = 60102;\n\n    /***********************************|\n    |           Pendle Oracle           | \n    |__________________________________*/\n\n    /// @notice thrown when an invalid parameter is passed to a method\n    uint256 internal constant PendleOracle__InvalidParams = 60201;\n\n    /// @notice thrown when the Pendle market Oracle has not been initialized yet\n    uint256 internal constant PendleOracle__MarketNotInitialized = 60202;\n\n    /// @notice thrown when the Pendle market does not have 18 decimals\n    uint256 internal constant PendleOracle__MarketInvalidDecimals = 60203;\n\n    /// @notice thrown when the Pendle market returns an unexpected price\n    uint256 internal constant PendleOracle__InvalidPrice = 60204;\n\n    /***********************************|\n    |          Chainlink Oracle         | \n    |__________________________________*/\n\n    /// @notice thrown when an invalid parameter is passed to a method\n    uint256 internal constant ChainlinkOracle__InvalidParams = 61001;\n\n    /***********************************|\n    |          UniswapV3 Oracle         | \n    |__________________________________*/\n\n    /// @notice thrown when an invalid parameter is passed to a method\n    uint256 internal constant UniV3Oracle__InvalidParams = 62001;\n\n    /// @notice thrown when constructor is called with invalid ordered seconds agos values\n    uint256 internal constant UniV3Oracle__InvalidSecondsAgos = 62002;\n\n    /// @notice thrown when constructor is called with invalid delta values > 100%\n    uint256 internal constant UniV3Oracle__InvalidDeltas = 62003;\n\n    /***********************************|\n    |            WstETh Oracle          | \n    |__________________________________*/\n\n    /// @notice thrown when an invalid parameter is passed to a method\n    uint256 internal constant WstETHOracle__InvalidParams = 63001;\n\n    /***********************************|\n    |           Redstone Oracle         | \n    |__________________________________*/\n\n    /// @notice thrown when an invalid parameter is passed to a method\n    uint256 internal constant RedstoneOracle__InvalidParams = 64001;\n\n    /***********************************|\n    |          Fallback Oracle          | \n    |__________________________________*/\n\n    /// @notice thrown when an invalid parameter is passed to a method\n    uint256 internal constant FallbackOracle__InvalidParams = 65001;\n\n    /***********************************|\n    |       FallbackCLRSOracle          | \n    |__________________________________*/\n\n    /// @notice thrown when the exchange rate is zero, even for the fallback oracle source (if enabled)\n    uint256 internal constant FallbackCLRSOracle__ExchangeRateZero = 66001;\n\n    /***********************************|\n    |         WstETHCLRSOracle          | \n    |__________________________________*/\n\n    /// @notice thrown when the exchange rate is zero, even for the fallback oracle source (if enabled)\n    uint256 internal constant WstETHCLRSOracle__ExchangeRateZero = 67001;\n\n    /***********************************|\n    |        CLFallbackUniV3Oracle      | \n    |__________________________________*/\n\n    /// @notice thrown when the exchange rate is zero, even for the uniV3 rate\n    uint256 internal constant CLFallbackUniV3Oracle__ExchangeRateZero = 68001;\n\n    /***********************************|\n    |  WstETHCLRS2UniV3CheckCLRSOracle  | \n    |__________________________________*/\n\n    /// @notice thrown when the exchange rate is zero, even for the uniV3 rate\n    uint256 internal constant WstETHCLRS2UniV3CheckCLRSOracle__ExchangeRateZero = 69001;\n\n    /***********************************|\n    |             WeETh Oracle          | \n    |__________________________________*/\n\n    /// @notice thrown when an invalid parameter is passed to a method\n    uint256 internal constant WeETHOracle__InvalidParams = 70001;\n}\n"
      },
      "contracts/oracle/fluidOracle.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IFluidOracle } from \"./interfaces/iFluidOracle.sol\";\n\n/// @title   FluidOracle\n/// @notice  Base contract that any Fluid Oracle must implement\nabstract contract FluidOracle is IFluidOracle {\n    /// @inheritdoc IFluidOracle\n    function getExchangeRate() external view virtual returns (uint256 exchangeRate_);\n\n    /// @inheritdoc IFluidOracle\n    function getExchangeRateOperate() external view virtual returns (uint256 exchangeRate_);\n\n    /// @inheritdoc IFluidOracle\n    function getExchangeRateLiquidate() external view virtual returns (uint256 exchangeRate_);\n}\n"
      },
      "contracts/oracle/implementations/chainlinkOracleImpl.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { ErrorTypes } from \"../errorTypes.sol\";\nimport { IChainlinkAggregatorV3 } from \"../interfaces/external/IChainlinkAggregatorV3.sol\";\nimport { Error as OracleError } from \"../error.sol\";\nimport { OracleUtils } from \"../libraries/oracleUtils.sol\";\nimport { ChainlinkStructs } from \"./structs.sol\";\n\n/// @title   Chainlink Oracle implementation\n/// @notice  This contract is used to get the exchange rate via up to 3 hops at Chainlink price feeds.\n///          The rate is multiplied with the previous rate at each hop.\n///          E.g. to go from wBTC to USDC (assuming rates for example):\n///          1. wBTC -> BTC https://data.chain.link/ethereum/mainnet/crypto-other/wbtc-btc, rate: 0.92.\n///          2. BTC -> USD https://data.chain.link/ethereum/mainnet/crypto-usd/btc-usd rate: 30,000.\n///          3. USD -> USDC https://data.chain.link/ethereum/mainnet/stablecoins/usdc-usd rate: 0.98. Must invert feed: 1.02\n///          finale rate would be: 0.92 * 30,000 * 1.02 = 28,152\nabstract contract ChainlinkOracleImpl is OracleError, ChainlinkStructs {\n    /// @notice Chainlink price feed 1 to check for the exchange rate\n    IChainlinkAggregatorV3 internal immutable _CHAINLINK_FEED1;\n    /// @notice Chainlink price feed 2 to check for the exchange rate\n    IChainlinkAggregatorV3 internal immutable _CHAINLINK_FEED2;\n    /// @notice Chainlink price feed 3 to check for the exchange rate\n    IChainlinkAggregatorV3 internal immutable _CHAINLINK_FEED3;\n\n    /// @notice Flag to invert the price or not for feed 1 (to e.g. for WETH/USDC pool return prive of USDC per 1 WETH)\n    bool internal immutable _CHAINLINK_INVERT_RATE1;\n    /// @notice Flag to invert the price or not for feed 2 (to e.g. for WETH/USDC pool return prive of USDC per 1 WETH)\n    bool internal immutable _CHAINLINK_INVERT_RATE2;\n    /// @notice Flag to invert the price or not for feed 3 (to e.g. for WETH/USDC pool return prive of USDC per 1 WETH)\n    bool internal immutable _CHAINLINK_INVERT_RATE3;\n\n    /// @notice constant value for price scaling to reduce gas usage for feed 1\n    uint256 internal immutable _CHAINLINK_PRICE_SCALER_MULTIPLIER1;\n    /// @notice constant value for inverting price to reduce gas usage for feed 1\n    uint256 internal immutable _CHAINLINK_INVERT_PRICE_DIVIDEND1;\n\n    /// @notice constant value for price scaling to reduce gas usage for feed 2\n    uint256 internal immutable _CHAINLINK_PRICE_SCALER_MULTIPLIER2;\n    /// @notice constant value for inverting price to reduce gas usage for feed 2\n    uint256 internal immutable _CHAINLINK_INVERT_PRICE_DIVIDEND2;\n\n    /// @notice constant value for price scaling to reduce gas usage for feed 3\n    uint256 internal immutable _CHAINLINK_PRICE_SCALER_MULTIPLIER3;\n    /// @notice constant value for inverting price to reduce gas usage for feed 3\n    uint256 internal immutable _CHAINLINK_INVERT_PRICE_DIVIDEND3;\n\n    /// @notice constructor sets the Chainlink price feed and invertRate flag for each hop.\n    /// E.g. `invertRate_` should be true if for the USDC/ETH pool it's expected that the oracle returns USDC per 1 ETH\n    constructor(ChainlinkConstructorParams memory params_) {\n        if (\n            (params_.hops < 1 || params_.hops > 3) || // hops must be 1, 2 or 3\n            (address(params_.feed1.feed) == address(0) || params_.feed1.token0Decimals == 0) || // first feed must always be defined\n            (params_.hops > 1 && (address(params_.feed2.feed) == address(0) || params_.feed2.token0Decimals == 0)) || // if hops > 1, feed 2 must be defined\n            (params_.hops > 2 && (address(params_.feed3.feed) == address(0) || params_.feed3.token0Decimals == 0)) // if hops > 2, feed 3 must be defined\n        ) {\n            revert FluidOracleError(ErrorTypes.ChainlinkOracle__InvalidParams);\n        }\n\n        _CHAINLINK_FEED1 = params_.feed1.feed;\n        _CHAINLINK_FEED2 = params_.feed2.feed;\n        _CHAINLINK_FEED3 = params_.feed3.feed;\n\n        _CHAINLINK_INVERT_RATE1 = params_.feed1.invertRate;\n        _CHAINLINK_INVERT_RATE2 = params_.feed2.invertRate;\n        _CHAINLINK_INVERT_RATE3 = params_.feed3.invertRate;\n\n        // Actual desired output rate example USDC/ETH (6 decimals / 18 decimals).\n        // Note ETH has 12 decimals more than USDC.\n        //    0.000515525322211842331991619857165357691 // 39 decimals.  ETH for 1 USDC\n        // 1954.190000000000433             // 15 decimals. USDC for 1 ETH\n\n        // to get to PRICE_SCLAER_MULTIPLIER and INVERT_PRICE_DIVIDEND:\n        // fetched Chainlink price is in token1Decimals per 1 token0Decimals.\n        // E.g. for an USDC/ETH price feed it's in ETH 18 decimals.\n        //      for an  BTC/USD price feed it's in USD  8 decimals.\n        // So to scale to 1e27 we need to multiply by 1e27 - token0Decimals.\n        // E.g. for USDC/ETH it would be: fetchedPrice * 1e21\n        //\n        // or for inverted (x token0 per 1 token1), formula would be:\n        //    = 1e27 * 10**token0Decimals / fetchedPrice\n        // E.g. for USDC/ETH it would be: 1e33 / fetchedPrice\n\n        // no support for token1Decimals with more than OracleUtils.RATE_OUTPUT_DECIMALS decimals for now as extremely unlikely case\n        _CHAINLINK_PRICE_SCALER_MULTIPLIER1 = 10 ** (OracleUtils.RATE_OUTPUT_DECIMALS - params_.feed1.token0Decimals);\n        _CHAINLINK_INVERT_PRICE_DIVIDEND1 = 10 ** (OracleUtils.RATE_OUTPUT_DECIMALS + params_.feed1.token0Decimals);\n\n        _CHAINLINK_PRICE_SCALER_MULTIPLIER2 = params_.hops > 1\n            ? 10 ** (OracleUtils.RATE_OUTPUT_DECIMALS - params_.feed2.token0Decimals)\n            : 1;\n        _CHAINLINK_INVERT_PRICE_DIVIDEND2 = params_.hops > 1\n            ? 10 ** (OracleUtils.RATE_OUTPUT_DECIMALS + params_.feed2.token0Decimals)\n            : 1;\n\n        _CHAINLINK_PRICE_SCALER_MULTIPLIER3 = params_.hops > 2\n            ? 10 ** (OracleUtils.RATE_OUTPUT_DECIMALS - params_.feed3.token0Decimals)\n            : 1;\n        _CHAINLINK_INVERT_PRICE_DIVIDEND3 = params_.hops > 2\n            ? 10 ** (OracleUtils.RATE_OUTPUT_DECIMALS + params_.feed3.token0Decimals)\n            : 1;\n    }\n\n    /// @dev            Get the exchange rate from Chainlike oracle price feed(s)\n    /// @return rate_   The exchange rate in `OracleUtils.RATE_OUTPUT_DECIMALS`\n    function _getChainlinkExchangeRate() internal view returns (uint256 rate_) {\n        rate_ = _readFeedRate(\n            _CHAINLINK_FEED1,\n            _CHAINLINK_INVERT_RATE1,\n            _CHAINLINK_PRICE_SCALER_MULTIPLIER1,\n            _CHAINLINK_INVERT_PRICE_DIVIDEND1\n        );\n        if (rate_ == 0 || address(_CHAINLINK_FEED2) == address(0)) {\n            // rate 0 or only 1 hop -> return rate of price feed 1\n            return rate_;\n        }\n        rate_ =\n            (rate_ *\n                _readFeedRate(\n                    _CHAINLINK_FEED2,\n                    _CHAINLINK_INVERT_RATE2,\n                    _CHAINLINK_PRICE_SCALER_MULTIPLIER2,\n                    _CHAINLINK_INVERT_PRICE_DIVIDEND2\n                )) /\n            (10 ** OracleUtils.RATE_OUTPUT_DECIMALS);\n\n        if (rate_ == 0 || address(_CHAINLINK_FEED3) == address(0)) {\n            // rate 0 or 2 hops -> return rate of feed 1 combined with feed 2\n            return rate_;\n        }\n\n        // 3 hops -> return rate of feed 1 combined with feed 2 & feed 3\n        rate_ =\n            (rate_ *\n                _readFeedRate(\n                    _CHAINLINK_FEED3,\n                    _CHAINLINK_INVERT_RATE3,\n                    _CHAINLINK_PRICE_SCALER_MULTIPLIER3,\n                    _CHAINLINK_INVERT_PRICE_DIVIDEND3\n                )) /\n            (10 ** OracleUtils.RATE_OUTPUT_DECIMALS);\n    }\n\n    /// @dev reads the exchange `rate_` from a Chainlink price `feed_` taking into account scaling and `invertRate_`\n    function _readFeedRate(\n        IChainlinkAggregatorV3 feed_,\n        bool invertRate_,\n        uint256 priceMultiplier_,\n        uint256 invertDividend_\n    ) private view returns (uint256 rate_) {\n        try feed_.latestRoundData() returns (uint80, int256 exchangeRate_, uint256, uint256, uint80) {\n            // Return the price in `OracleUtils.RATE_OUTPUT_DECIMALS`\n            if (invertRate_) {\n                return invertDividend_ / uint256(exchangeRate_);\n            } else {\n                return uint256(exchangeRate_) * priceMultiplier_;\n            }\n        } catch {\n            return 0;\n        }\n    }\n\n    /// @notice returns all Chainlink oracle related data as utility for easy off-chain use / block explorer in a single view method\n    function chainlinkOracleData()\n        public\n        view\n        returns (\n            uint256 chainlinkExchangeRate_,\n            IChainlinkAggregatorV3 chainlinkFeed1_,\n            bool chainlinkInvertRate1_,\n            uint256 chainlinkExchangeRate1_,\n            IChainlinkAggregatorV3 chainlinkFeed2_,\n            bool chainlinkInvertRate2_,\n            uint256 chainlinkExchangeRate2_,\n            IChainlinkAggregatorV3 chainlinkFeed3_,\n            bool chainlinkInvertRate3_,\n            uint256 chainlinkExchangeRate3_\n        )\n    {\n        return (\n            _getChainlinkExchangeRate(),\n            _CHAINLINK_FEED1,\n            _CHAINLINK_INVERT_RATE1,\n            _readFeedRate(\n                _CHAINLINK_FEED1,\n                _CHAINLINK_INVERT_RATE1,\n                _CHAINLINK_PRICE_SCALER_MULTIPLIER1,\n                _CHAINLINK_INVERT_PRICE_DIVIDEND1\n            ),\n            _CHAINLINK_FEED2,\n            _CHAINLINK_INVERT_RATE2,\n            address(_CHAINLINK_FEED2) == address(0)\n                ? 0\n                : _readFeedRate(\n                    _CHAINLINK_FEED2,\n                    _CHAINLINK_INVERT_RATE2,\n                    _CHAINLINK_PRICE_SCALER_MULTIPLIER2,\n                    _CHAINLINK_INVERT_PRICE_DIVIDEND2\n                ),\n            _CHAINLINK_FEED3,\n            _CHAINLINK_INVERT_RATE3,\n            address(_CHAINLINK_FEED3) == address(0)\n                ? 0\n                : _readFeedRate(\n                    _CHAINLINK_FEED3,\n                    _CHAINLINK_INVERT_RATE3,\n                    _CHAINLINK_PRICE_SCALER_MULTIPLIER3,\n                    _CHAINLINK_INVERT_PRICE_DIVIDEND3\n                )\n        );\n    }\n}\n"
      },
      "contracts/oracle/implementations/fallbackOracleImpl.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { ErrorTypes } from \"../errorTypes.sol\";\nimport { IRedstoneOracle } from \"../interfaces/external/IRedstoneOracle.sol\";\nimport { Error as OracleError } from \"../error.sol\";\nimport { ChainlinkOracleImpl } from \"./chainlinkOracleImpl.sol\";\nimport { RedstoneOracleImpl } from \"./redstoneOracleImpl.sol\";\n\n/// @title   Fallback Oracle implementation\n/// @notice  This contract is used to get the exchange rate from a main oracle feed and a fallback oracle feed.\n//\n// @dev     inheriting contracts should implement a view method to expose `_FALLBACK_ORACLE_MAIN_SOURCE`\nabstract contract FallbackOracleImpl is OracleError, RedstoneOracleImpl, ChainlinkOracleImpl {\n    /// @dev which oracle to use as main source:\n    /// - 1 = Chainlink ONLY (no fallback)\n    /// - 2 = Chainlink with Redstone Fallback\n    /// - 3 = Redstone with Chainlink Fallback\n    uint8 internal immutable _FALLBACK_ORACLE_MAIN_SOURCE;\n\n    /// @notice                     sets the main source, Chainlink Oracle and Redstone Oracle data.\n    /// @param mainSource_          which oracle to use as main source:\n    ///                                  - 1 = Chainlink ONLY (no fallback)\n    ///                                  - 2 = Chainlink with Redstone Fallback\n    ///                                  - 3 = Redstone with Chainlink Fallback\n    /// @param chainlinkParams_     chainlink Oracle constructor params struct.\n    /// @param redstoneOracle_      Redstone Oracle data. (address can be set to zero address if using Chainlink only)\n    constructor(\n        uint8 mainSource_,\n        ChainlinkConstructorParams memory chainlinkParams_,\n        RedstoneOracleData memory redstoneOracle_\n    )\n        ChainlinkOracleImpl(chainlinkParams_)\n        RedstoneOracleImpl(\n            address(redstoneOracle_.oracle) == address(0)\n                ? RedstoneOracleData(IRedstoneOracle(_REDSTONE_ORACLE_NOT_SET_ADDRESS), false, 1)\n                : redstoneOracle_\n        )\n    {\n        if (mainSource_ < 1 || mainSource_ > 3) {\n            revert FluidOracleError(ErrorTypes.FallbackOracle__InvalidParams);\n        }\n        _FALLBACK_ORACLE_MAIN_SOURCE = mainSource_;\n    }\n\n    /// @dev returns the exchange rate for the main oracle source, or the fallback source (if configured) if the main exchange rate\n    /// fails to be fetched. If returned rate is 0, fetching rate failed or something went wrong.\n    /// @return exchangeRate_ exchange rate\n    /// @return fallback_ whether fallback was necessary or not\n    function _getRateWithFallback() internal view returns (uint256 exchangeRate_, bool fallback_) {\n        if (_FALLBACK_ORACLE_MAIN_SOURCE == 1) {\n            // 1 = Chainlink ONLY (no fallback)\n            exchangeRate_ = _getChainlinkExchangeRate();\n        } else if (_FALLBACK_ORACLE_MAIN_SOURCE == 2) {\n            // 2 = Chainlink with Redstone Fallback\n            exchangeRate_ = _getChainlinkExchangeRate();\n            if (exchangeRate_ == 0) {\n                fallback_ = true;\n                exchangeRate_ = _getRedstoneExchangeRate();\n            }\n        } else {\n            // 3 = Redstone with Chainlink Fallback\n            exchangeRate_ = _getRedstoneExchangeRate();\n            if (exchangeRate_ == 0) {\n                fallback_ = true;\n                exchangeRate_ = _getChainlinkExchangeRate();\n            }\n        }\n    }\n\n    /// @dev returns the exchange rate for Chainlink, or Redstone if configured & Chainlink fails.\n    function _getChainlinkOrRedstoneAsFallback() internal view returns (uint256 exchangeRate_) {\n        exchangeRate_ = _getChainlinkExchangeRate();\n\n        if (exchangeRate_ == 0 && _FALLBACK_ORACLE_MAIN_SOURCE != 1) {\n            // Chainlink failed but Redstone is configured too -> try Redstone\n            exchangeRate_ = _getRedstoneExchangeRate();\n        }\n    }\n}\n"
      },
      "contracts/oracle/implementations/redstoneOracleImpl.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { ErrorTypes } from \"../errorTypes.sol\";\nimport { IRedstoneOracle } from \"../interfaces/external/IRedstoneOracle.sol\";\nimport { Error as OracleError } from \"../error.sol\";\nimport { OracleUtils } from \"../libraries/oracleUtils.sol\";\nimport { RedstoneStructs } from \"./structs.sol\";\n\n/// @title   Redstone Oracle implementation\n/// @notice  This contract is used to get the exchange rate from a Redstone Oracle\nabstract contract RedstoneOracleImpl is OracleError, RedstoneStructs {\n    /// @notice Redstone price oracle to check for the exchange rate\n    IRedstoneOracle internal immutable _REDSTONE_ORACLE;\n    /// @notice Flag to invert the price or not (to e.g. for WETH/USDC pool return prive of USDC per 1 WETH)\n    bool internal immutable _REDSTONE_INVERT_RATE;\n\n    /// @notice constant value for price scaling to reduce gas usage\n    uint256 internal immutable _REDSTONE_PRICE_SCALER_MULTIPLIER;\n    /// @notice constant value for inverting price to reduce gas usage\n    uint256 internal immutable _REDSTONE_INVERT_PRICE_DIVIDEND;\n\n    address internal immutable _REDSTONE_ORACLE_NOT_SET_ADDRESS = 0x000000000000000000000000000000000000dEaD;\n\n    /// @notice constructor sets the Redstone oracle data\n    constructor(RedstoneOracleData memory oracleData_) {\n        if (address(oracleData_.oracle) == address(0) || oracleData_.token0Decimals == 0) {\n            revert FluidOracleError(ErrorTypes.RedstoneOracle__InvalidParams);\n        }\n\n        _REDSTONE_ORACLE = oracleData_.oracle;\n        _REDSTONE_INVERT_RATE = oracleData_.invertRate;\n\n        // for explanation on how to get to scaler multiplier and dividend see `chainlinkOracleImpl.sol`.\n        // no support for token1Decimals with more than OracleUtils.RATE_OUTPUT_DECIMALS decimals for now as extremely unlikely case\n        _REDSTONE_PRICE_SCALER_MULTIPLIER = address(oracleData_.oracle) == _REDSTONE_ORACLE_NOT_SET_ADDRESS\n            ? 1\n            : 10 ** (OracleUtils.RATE_OUTPUT_DECIMALS - oracleData_.token0Decimals);\n        _REDSTONE_INVERT_PRICE_DIVIDEND = address(oracleData_.oracle) == _REDSTONE_ORACLE_NOT_SET_ADDRESS\n            ? 1\n            : 10 ** (OracleUtils.RATE_OUTPUT_DECIMALS + oracleData_.token0Decimals);\n    }\n\n    /// @dev           Get the exchange rate from Redstone oracle\n    /// @param rate_   The exchange rate in `OracleUtils.RATE_OUTPUT_DECIMALS`\n    function _getRedstoneExchangeRate() internal view returns (uint256 rate_) {\n        try _REDSTONE_ORACLE.getExchangeRate() returns (uint256 exchangeRate_) {\n            if (_REDSTONE_INVERT_RATE) {\n                // invert the price\n                return _REDSTONE_INVERT_PRICE_DIVIDEND / exchangeRate_;\n            } else {\n                return exchangeRate_ * _REDSTONE_PRICE_SCALER_MULTIPLIER;\n            }\n        } catch {\n            return 0;\n        }\n    }\n\n    /// @notice returns all Redstone oracle related data as utility for easy off-chain use / block explorer in a single view method\n    function redstoneOracleData()\n        public\n        view\n        returns (uint256 redstoneExchangeRate_, IRedstoneOracle redstoneOracle_, bool redstoneInvertRate_)\n    {\n        return (\n            address(_REDSTONE_ORACLE) == _REDSTONE_ORACLE_NOT_SET_ADDRESS ? 0 : _getRedstoneExchangeRate(),\n            _REDSTONE_ORACLE,\n            _REDSTONE_INVERT_RATE\n        );\n    }\n}\n"
      },
      "contracts/oracle/implementations/structs.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IChainlinkAggregatorV3 } from \"../interfaces/external/IChainlinkAggregatorV3.sol\";\nimport { IRedstoneOracle } from \"../interfaces/external/IRedstoneOracle.sol\";\n\nabstract contract ChainlinkStructs {\n    struct ChainlinkFeedData {\n        /// @param feed           address of Chainlink feed.\n        IChainlinkAggregatorV3 feed;\n        /// @param invertRate     true if rate read from price feed must be inverted.\n        bool invertRate;\n        /// @param token0Decimals decimals of asset 0. E.g. for a USDC/ETH feed, USDC is token0 and has 6 decimals.\n        ///                       (token1Decimals are available directly via Chainlink `FEED.decimals()`)\n        uint256 token0Decimals;\n    }\n\n    struct ChainlinkConstructorParams {\n        /// @param param        hops count of hops, used for sanity checks. Must be 1, 2 or 3.\n        uint8 hops;\n        /// @param feed1        Chainlink feed 1 data. Required.\n        ChainlinkFeedData feed1;\n        /// @param feed2        Chainlink feed 2 data. Required if hops > 1.\n        ChainlinkFeedData feed2;\n        /// @param feed3        Chainlink feed 3 data. Required if hops > 2.\n        ChainlinkFeedData feed3;\n    }\n}\n\nabstract contract RedstoneStructs {\n    struct RedstoneOracleData {\n        /// @param oracle         address of Redstone oracle.\n        IRedstoneOracle oracle;\n        /// @param invertRate     true if rate read from price feed must be inverted.\n        bool invertRate;\n        /// @param token0Decimals decimals of asset 0. E.g. for a USDC/ETH feed, USDC is token0 and has 6 decimals.\n        ///                       (token1Decimals are available directly via Redstone `Oracle.decimals()`)\n        uint256 token0Decimals;\n    }\n}\n"
      },
      "contracts/oracle/interfaces/external/IChainlinkAggregatorV3.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\n/// from https://github.com/smartcontractkit/chainlink/blob/master/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\n/// Copyright (c) 2018 SmartContract ChainLink, Ltd.\n\ninterface IChainlinkAggregatorV3 {\n    /// @notice represents the number of decimals the aggregator responses represent.\n    function decimals() external view returns (uint8);\n\n    function description() external view returns (string memory);\n\n    function version() external view returns (uint256);\n\n    function getRoundData(\n        uint80 _roundId\n    )\n        external\n        view\n        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n\n    function latestRoundData()\n        external\n        view\n        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n}\n"
      },
      "contracts/oracle/interfaces/external/IRedstoneOracle.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface IRedstoneOracle {\n    /// @notice Get the `exchangeRate_` between the underlying asset and the peg asset\n    // @dev custom Redstone adapter for Instadapp implementation\n    function getExchangeRate() external view returns (uint256 exchangeRate_);\n\n    /**\n     * @notice Returns the number of decimals for the price feed\n     * @dev By default, RedStone uses 8 decimals for data feeds\n     * @return decimals The number of decimals in the price feed values\n     */\n    // see https://github.com/redstone-finance/redstone-oracles-monorepo/blob/main/packages/on-chain-relayer/contracts/price-feeds/PriceFeedBase.sol#L51C12-L51C20\n    function decimals() external view returns (uint8);\n}\n"
      },
      "contracts/oracle/interfaces/iFluidOracle.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.21;\n\ninterface IFluidOracle {\n    /// @dev Deprecated. Use `getExchangeRateOperate()` and `getExchangeRateLiquidate()` instead. Only implemented for\n    ///      backwards compatibility.\n    function getExchangeRate() external view returns (uint256 exchangeRate_);\n\n    /// @notice Get the `exchangeRate_` between the underlying asset and the peg asset in 1e27 for operates\n    function getExchangeRateOperate() external view returns (uint256 exchangeRate_);\n\n    /// @notice Get the `exchangeRate_` between the underlying asset and the peg asset in 1e27 for liquidations\n    function getExchangeRateLiquidate() external view returns (uint256 exchangeRate_);\n}\n"
      },
      "contracts/oracle/libraries/oracleUtils.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @title Oracle utils library\n/// @notice implements common utility methods for Fluid Oracles\nlibrary OracleUtils {\n    /// @dev The scaler for max delta point math (100%)\n    uint256 internal constant HUNDRED_PERCENT_DELTA_SCALER = 10_000;\n    /// @dev output precision of rates\n    uint256 internal constant RATE_OUTPUT_DECIMALS = 27;\n\n    /// @dev checks if `mainSourceRate_` is within a `maxDeltaPercent_` of `checkSourceRate_`. Returns true if so.\n    function isRateOutsideDelta(\n        uint256 mainSourceRate_,\n        uint256 checkSourceRate_,\n        uint256 maxDeltaPercent_\n    ) internal pure returns (bool) {\n        uint256 offset_ = (checkSourceRate_ * maxDeltaPercent_) / HUNDRED_PERCENT_DELTA_SCALER;\n        return (mainSourceRate_ > (checkSourceRate_ + offset_) || mainSourceRate_ < (checkSourceRate_ - offset_));\n    }\n}\n"
      },
      "contracts/oracle/oracles/fallbackCLRSOracle.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { FluidOracle } from \"../fluidOracle.sol\";\nimport { FallbackOracleImpl } from \"../implementations/fallbackOracleImpl.sol\";\nimport { ErrorTypes } from \"../errorTypes.sol\";\n\n/// @title   Chainlink / Redstone Oracle (with fallback)\n/// @notice  Gets the exchange rate between the underlying asset and the peg asset by using:\n///          the price from a Chainlink price feed or a Redstone Oracle with one of them being used as main source and\n///          the other one acting as a fallback if the main source fails for any reason. Reverts if fetched rate is 0.\ncontract FallbackCLRSOracle is FluidOracle, FallbackOracleImpl {\n    /// @notice                     sets the main source, Chainlink Oracle and Redstone Oracle data.\n    /// @param mainSource_          which oracle to use as main source: 1 = Chainlink, 2 = Redstone (other one is fallback).\n    /// @param chainlinkParams_     chainlink Oracle constructor params struct.\n    /// @param redstoneOracle_      Redstone Oracle data. (address can be set to zero address if using Chainlink only)\n    constructor(\n        uint8 mainSource_,\n        ChainlinkConstructorParams memory chainlinkParams_,\n        RedstoneOracleData memory redstoneOracle_\n    ) FallbackOracleImpl(mainSource_, chainlinkParams_, redstoneOracle_) {}\n\n    /// @inheritdoc FluidOracle\n    function getExchangeRateOperate() public view virtual override returns (uint256 exchangeRate_) {\n        (exchangeRate_, ) = _getRateWithFallback();\n\n        if (exchangeRate_ == 0) {\n            revert FluidOracleError(ErrorTypes.FallbackCLRSOracle__ExchangeRateZero);\n        }\n    }\n\n    /// @inheritdoc FluidOracle\n    function getExchangeRateLiquidate() public view virtual override returns (uint256 exchangeRate_) {\n        return getExchangeRateOperate();\n    }\n\n    /// @inheritdoc FluidOracle\n    function getExchangeRate() public view virtual override returns (uint256 exchangeRate_) {\n        return getExchangeRateOperate();\n    }\n\n    /// @notice which oracle to use as main source:\n    ///          - 1 = Chainlink ONLY (no fallback)\n    ///          - 2 = Chainlink with Redstone Fallback\n    ///          - 3 = Redstone with Chainlink Fallback\n    function FALLBACK_ORACLE_MAIN_SOURCE() public view returns (uint8) {\n        return _FALLBACK_ORACLE_MAIN_SOURCE;\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 10000000
      },
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}