fluid-contracts-public/contracts/oracle/implementations/fallbackOracleImpl.sol
2024-07-11 13:05:09 +00:00

81 lines
3.8 KiB
Solidity

// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.21;
import { ErrorTypes } from "../errorTypes.sol";
import { IRedstoneOracle } from "../interfaces/external/IRedstoneOracle.sol";
import { Error as OracleError } from "../error.sol";
import { ChainlinkOracleImpl } from "./chainlinkOracleImpl.sol";
import { RedstoneOracleImpl } from "./redstoneOracleImpl.sol";
/// @title Fallback Oracle implementation
/// @notice This contract is used to get the exchange rate from a main oracle feed and a fallback oracle feed.
//
// @dev inheriting contracts should implement a view method to expose `_FALLBACK_ORACLE_MAIN_SOURCE`
abstract contract FallbackOracleImpl is OracleError, RedstoneOracleImpl, ChainlinkOracleImpl {
/// @dev which oracle to use as main source:
/// - 1 = Chainlink ONLY (no fallback)
/// - 2 = Chainlink with Redstone Fallback
/// - 3 = Redstone with Chainlink Fallback
uint8 internal immutable _FALLBACK_ORACLE_MAIN_SOURCE;
/// @notice sets the main source, Chainlink Oracle and Redstone Oracle data.
/// @param mainSource_ which oracle to use as main source:
/// - 1 = Chainlink ONLY (no fallback)
/// - 2 = Chainlink with Redstone Fallback
/// - 3 = Redstone with Chainlink Fallback
/// @param chainlinkParams_ chainlink Oracle constructor params struct.
/// @param redstoneOracle_ Redstone Oracle data. (address can be set to zero address if using Chainlink only)
constructor(
uint8 mainSource_,
ChainlinkConstructorParams memory chainlinkParams_,
RedstoneOracleData memory redstoneOracle_
)
ChainlinkOracleImpl(chainlinkParams_)
RedstoneOracleImpl(
address(redstoneOracle_.oracle) == address(0)
? RedstoneOracleData(IRedstoneOracle(_REDSTONE_ORACLE_NOT_SET_ADDRESS), false, 1)
: redstoneOracle_
)
{
if (mainSource_ < 1 || mainSource_ > 3) {
revert FluidOracleError(ErrorTypes.FallbackOracle__InvalidParams);
}
_FALLBACK_ORACLE_MAIN_SOURCE = mainSource_;
}
/// @dev returns the exchange rate for the main oracle source, or the fallback source (if configured) if the main exchange rate
/// fails to be fetched. If returned rate is 0, fetching rate failed or something went wrong.
/// @return exchangeRate_ exchange rate
/// @return fallback_ whether fallback was necessary or not
function _getRateWithFallback() internal view returns (uint256 exchangeRate_, bool fallback_) {
if (_FALLBACK_ORACLE_MAIN_SOURCE == 1) {
// 1 = Chainlink ONLY (no fallback)
exchangeRate_ = _getChainlinkExchangeRate();
} else if (_FALLBACK_ORACLE_MAIN_SOURCE == 2) {
// 2 = Chainlink with Redstone Fallback
exchangeRate_ = _getChainlinkExchangeRate();
if (exchangeRate_ == 0) {
fallback_ = true;
exchangeRate_ = _getRedstoneExchangeRate();
}
} else {
// 3 = Redstone with Chainlink Fallback
exchangeRate_ = _getRedstoneExchangeRate();
if (exchangeRate_ == 0) {
fallback_ = true;
exchangeRate_ = _getChainlinkExchangeRate();
}
}
}
/// @dev returns the exchange rate for Chainlink, or Redstone if configured & Chainlink fails.
function _getChainlinkOrRedstoneAsFallback() internal view returns (uint256 exchangeRate_) {
exchangeRate_ = _getChainlinkExchangeRate();
if (exchangeRate_ == 0 && _FALLBACK_ORACLE_MAIN_SOURCE != 1) {
// Chainlink failed but Redstone is configured too -> try Redstone
exchangeRate_ = _getRedstoneExchangeRate();
}
}
}