Moonbase Alpha Testnet

Contract Diff Checker

Contract Name:
ChainlinkFeedGetter

Contract Source Code:

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.4;

import "../oracle/interfaces/IPrimeOracle.sol";
import "../oracle/interfaces/IPrimeOracleGetter.sol";
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import "../../util/CommonErrors.sol";

contract ChainlinkFeedGetter is IPrimeOracleGetter, CommonErrors {

    // Map of asset price feeds (asset => priceSource)
    mapping(uint256 => mapping(address => AggregatorV3Interface)) private assetFeeds;

    //TODO: allow transfer of admin
    address public admin;

    uint8 public constant RATIO_DECIMALS = 18;

    /**
    * @dev Only the admin can call functions marked by this modifier.
    **/
    modifier onlyAdmin {
        if(msg.sender != admin) revert OnlyAdmin();
        _;
    }

    constructor() {
        admin = msg.sender;
    }

    /// @inheritdoc IPrimeOracleGetter

    function getAssetPrice(
        uint256 chainId,
        address asset,
        address /* denomToken */
    ) external view override returns (uint256 price, uint8 decimals) {
        AggregatorV3Interface feed = assetFeeds[chainId][asset];
        if (address(feed) != address(0)) {
            (
                /* uint80 roundId */,
                int256 answer,
                /* uint256 startedAt */,
                /* uint256 updatedAt */,
                /* uint80 answeredInRound */
            ) = feed.latestRoundData();

            if (answer < 0) return (0,0);

            price = uint256(answer);
            decimals = feed.decimals();
        }
    }

    function getAssetRatio(
        address overlyingAsset,
        address underlyingAsset,
        uint256 underlyingChainId
    ) external view override returns (uint256 ratio, uint8 decimals) {
        AggregatorV3Interface numFeed = assetFeeds[block.chainid][overlyingAsset];
        AggregatorV3Interface denFeed = assetFeeds[underlyingChainId][underlyingAsset];

        if (address(numFeed) != address(0) && address(denFeed) != address(0)) {
            (
                /* uint80 roundId */,
                int256 numAnswer,
                /* uint256 startedAt */,
                /* uint256 updatedAt */,
                /* uint80 answeredInRound */
            ) = numFeed.latestRoundData();

            (
                /* uint80 roundId */,
                int256 denAnswer,
                /* uint256 startedAt */,
                /* uint256 updatedAt */,
                /* uint80 answeredInRound */
            ) = denFeed.latestRoundData();

            if (numAnswer >= 0 && denAnswer >= 0) {
                ratio = uint256(numAnswer) * 10**(denFeed.decimals() + RATIO_DECIMALS) / uint256(denAnswer) / 10**numFeed.decimals();
                decimals = RATIO_DECIMALS;
            }
        }
    }

    function getPriceDecimals(uint256 chainId, address asset) external view override returns (uint256) {
        if (asset == address(0)) revert AddressExpected();

        AggregatorV3Interface feed = assetFeeds[chainId][asset];
        if (address(feed) != address(0)) {
            return feed.decimals();
        }
        return 0;
    }

    function _getAssetFeed(uint256 chainId, address asset) internal view returns (address) {
        if (asset == address(0)) revert AddressExpected();

        return address(assetFeeds[chainId][asset]);
    }

    function getAssetFeed(uint256 chainId, address asset) external view override returns (address) {
        if (asset == address(0)) revert AddressExpected();

        return _getAssetFeed(chainId, asset);
    }

    /// @inheritdoc IPrimeOracleGetter
    function setAssetFeed(
        uint256 chainId,
        address asset,
        address feed
    ) external override onlyAdmin() {
        assetFeeds[chainId][asset] = AggregatorV3Interface(feed);
        emit AssetFeedUpdated(chainId, asset, feed);
    }

}

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.4;

import "./IPrimeOracleGetter.sol";
import "./PrimeOracleStorage.sol";

/**
 * @title IPrimeOracle
 * @author Prime
 * @notice The core interface for the Prime Oracle
 */
abstract contract IPrimeOracle is PrimeOracleStorage {

    /**
     * @dev Emitted after the price data feed of an asset is set/updated
     * @param asset The address of the asset
     * @param chainId The chainId of the asset
     * @param feed The price feed of the asset
     */
    event SetPrimaryFeed(uint256 chainId, address indexed asset, address indexed feed);

    /**
     * @dev Emitted after the price data feed of an asset is set/updated
     * @param asset The address of the asset
     * @param feed The price feed of the asset
     */
    event SetSecondaryFeed(uint256 chainId, address indexed asset, address indexed feed);

    /**
     * @dev Emitted after the exchange rate data feed of a loan market asset is set/updated
     * @param asset The address of the asset
     * @param chainId The chainId of the asset
     * @param feed The price feed of the asset
     */
    event SetExchangRatePrimaryFeed(uint256 chainId, address indexed asset, address indexed feed);

    /**
     * @dev Emitted after the exchange rate data feed of a loan market asset is set/updated
     * @param asset The address of the asset
     * @param feed The price feed of the asset
     */
    event SetExchangeRateSecondaryFeed(uint256 chainId, address indexed asset, address indexed feed);

    /**
     * @notice Get the underlying price of a cToken asset
     * @param collateralMarketUnderlying The PToken collateral to get the sasset price of
     * @param chainId the chainId to get an asset price for
     * @return The underlying asset price.
     *  Zero means the price is unavailable.
     */
    function getUnderlyingPrice(uint256 chainId, address collateralMarketUnderlying) external view virtual returns (uint256, uint8);

    /**
     * @notice Get the underlying borrow price of loanMarketAsset
     * @return The underlying borrow price
     *  Zero means the price is unavailable.
     */
    function getUnderlyingPriceBorrow(
        uint256 chainId,
        address loanMarketUnderlying
    ) external view virtual returns (uint256, uint8);

    /**
     * @notice Get the exchange rate of loanMarketAsset to basis
     * @return The underlying exchange rate of loanMarketAsset to basis
     *  Zero means the price is unavailable.
     */
    function getBorrowAssetExchangeRate(
        address loanMarketOverlying,
        uint256 loanMarketUnderlyingChainId,
        address loanMarketUnderlying
    ) external view virtual returns (uint256 /* ratio */, uint8 /* decimals */);

    /*** Admin Functions ***/

    /**
     * @notice Sets or replaces price feeds of assets
     * @param asset The addresses of the assets
     * @param feed The addresses of the price feeds
     */
    function setPrimaryFeed(uint256 chainId, address asset, IPrimeOracleGetter feed) external virtual;

    /**
     * @notice Sets or replaces price feeds of assets
     * @param asset The addresses of the assets
     * @param feed The addresses of the price feeds
     */
    function setSecondaryFeed(uint256 chainId, address asset, IPrimeOracleGetter feed) external virtual;
}

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.4;

/**
 * @title IPrimeOracleGetter
 * @author Prime
 * @notice Interface for the Prime price oracle.
 **/
interface IPrimeOracleGetter {

    /**
     * @dev Emitted after the price data feed of an asset is updated
     * @param asset The address of the asset
     * @param feed The price feed of the asset
     */
    event AssetFeedUpdated(uint256 chainId, address indexed asset, address indexed feed);

    /**
     * @notice Gets the price feed of an asset
     * @param asset The addresses of the asset
     * @return address of asset feed
     */
    function getAssetFeed(uint256 chainId, address asset) external view returns (address);

    /**
     * @notice Sets or replaces price feeds of assets
     * @param asset The addresses of the assets
     * @param feed The addresses of the price feeds
     */
    function setAssetFeed(uint256 chainId, address asset, address feed) external;

    /**
     * @notice Returns the price data in the denom currency
     * @param quoteToken A token to return price data for
     * @param denomToken A token to price quoteToken against
     * @param price of the asset from the oracle
     * @param decimals of the asset from the oracle
     **/
    function getAssetPrice(
        uint256 chainId,
        address quoteToken,
        address denomToken
    ) external view returns (uint256 price, uint8 decimals);

    function getAssetRatio(
        address overlyingAsset,
        address underlyingAsset,
        uint256 underlyingChainId
    ) external view returns (uint256 ratio, uint8 decimals);

    /**
     * @notice Returns the price data in the denom currency
     * @param quoteToken A token to return price data for
     * @return return price of the asset from the oracle
     **/
    function getPriceDecimals(
        uint256 chainId,
        address quoteToken
    ) external view returns (uint256);

}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface AggregatorV3Interface {
  function decimals() external view returns (uint8);

  function description() external view returns (string memory);

  function version() external view returns (uint256);

  // getRoundData and latestRoundData should both raise "No data present"
  // if they do not have data to report, instead of returning unset values
  // which could be misinterpreted as actual reported values.
  function getRoundData(uint80 _roundId)
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );

  function latestRoundData()
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );
}

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.4;

abstract contract CommonErrors {
    error AccountNoAssets(address account);
    error AddressExpected();
    error AlreadyInitialized();
    error EccMessageAlreadyProcessed();
    error EccFailedToValidate();
    error ExpectedMintAmount();
    error ExpectedBridgeAmount();
    error ExpectedBorrowAmount();
    error ExpectedWithdrawAmount();
    error ExpectedRepayAmount();
    error ExpectedTradeAmount();
    error ExpectedDepositAmount();
    error ExpectedTransferAmount();
    error InsufficientReserves();
    error InvalidPayload();
    error InvalidPrice();
    error InvalidPrecision();
    error InvalidSelector();
    error MarketExists();
    error LoanMarketIsListed(bool status);
    error MarketIsPaused();
    error MarketNotListed();
    error MsgDataExpected();
    error NameExpected();
    error NothingToWithdraw();
    error NotInMarket(uint256 chainId, address token);
    error OnlyAdmin();
    error OnlyAuth();
    error OnlyGateway();
    error OnlyMiddleLayer();
    error OnlyMintAuth();
    error OnlyRoute();
    error OnlyRouter();
    error OnlyMasterState();
    error ParamOutOfBounds();
    error RouteExists();
    error Reentrancy();
    error EnterLoanMarketFailed();
    error EnterCollMarketFailed();
    error ExitLoanMarketFailed();
    error ExitCollMarketFailed();
    error RepayTooMuch(uint256 repayAmount, uint256 maxAmount);
    error WithdrawTooMuch();
    error NotEnoughBalance(address token, address who);
    error LiquidateDisallowed();
    error SeizeTooMuch();
    error SymbolExpected();
    error RouteNotSupported(address route);
    error MiddleLayerPaused();
    error PairNotSupported(address loanAsset, address tradeAsset);
    error TransferFailed(address from, address dest);
    error TransferPaused();
    error UnknownRevert();
    error UnexpectedValueDelta();
    error ExpectedValue();
    error UnexpectedDelta();
}

//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.4;

import "./IPrimeOracleGetter.sol";

/**
 * @title PrimeOracleStorage
 * @author Prime
 * @notice The core interface for the Prime Oracle storage variables
 */
abstract contract PrimeOracleStorage {
    address public pusdAddress;
    //TODO: allow transfer of ownership
    address public admin;
    // Map of asset price feeds (chainasset => priceSource)
    mapping(uint256 => mapping(address => IPrimeOracleGetter)) public primaryFeeds;
    mapping(uint256 => mapping(address => IPrimeOracleGetter)) public secondaryFeeds;
    mapping(uint256 => mapping(address => IPrimeOracleGetter)) public exchangeRatePrimaryFeeds;
    mapping(uint256 => mapping(address => IPrimeOracleGetter)) public exchangeRateSecondaryFeeds;
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):