ReverseMultiplicativePriceFeed

Description:

Smart contract deployed on Ethereum with Factory, Oracle features.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "contracts/IPriceFeed.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.15;

/**
 * @dev Interface for price feeds used by Comet
 * Note This is Chainlink's AggregatorV3Interface, but without the `getRoundData` function.
 */
interface IPriceFeed {
  function decimals() external view returns (uint8);

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

  function version() external view returns (uint256);

  function latestRoundData()
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );
}"
    },
    "contracts/pricefeeds/ReverseMultiplicativePriceFeed.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.15;

import "../vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import "../IPriceFeed.sol";

/**
 * @title Reverse multiplicative price feed
 * @notice A custom price feed that multiplies the price from one price feed and the inverse price from another price feed and returns the result
 * @dev for example if we need tokenX to eth, but there is only tokenX to usd, we can use this price feed to get tokenX to eth: tokenX to usd * reversed(eth to usd)
 * @author Compound
 */
contract ReverseMultiplicativePriceFeed is IPriceFeed {
    /** Custom errors **/
    error BadDecimals();
    error InvalidInt256();

    /// @notice Version of the price feed
    uint public constant VERSION = 1;

    /// @notice Description of the price feed
    string public override description;

    /// @notice Number of decimals for returned prices
    uint8 public immutable override decimals;

    /// @notice Chainlink price feed A
    address public immutable priceFeedA;

    /// @notice Chainlink price feed B
    address public immutable priceFeedB;

    /// @notice Price feed A scale
    int public immutable priceFeedAScale;

    /// @notice Price feed B scale
    int public immutable priceFeedBScale;

    /// @notice Scale of this price feed
    int public immutable priceFeedScale;

    /**
     * @notice Construct a new reverse multiplicative price feed
     * @param priceFeedA_ The address of the first price feed to fetch prices from
     * @param priceFeedB_ The address of the second price feed to fetch prices from that should be reversed
     * @param decimals_ The number of decimals for the returned prices
     * @param description_ The description of the price feed
     **/
    constructor(address priceFeedA_, address priceFeedB_, uint8 decimals_, string memory description_) {
        priceFeedA = priceFeedA_;
        priceFeedB = priceFeedB_;
        uint8 priceFeedADecimals = AggregatorV3Interface(priceFeedA_).decimals();
        uint8 priceFeedBDecimals = AggregatorV3Interface(priceFeedB_).decimals();
        priceFeedAScale = signed256(10 ** (priceFeedADecimals));
        priceFeedBScale = signed256(10 ** (priceFeedBDecimals));

        if (decimals_ > 18) revert BadDecimals();
        decimals = decimals_;
        description = description_;
        priceFeedScale = int256(10 ** decimals);
    }

    /**
     * @notice Calculates the latest round data using data from the two price feeds
     * @return roundId Round id from price feed B
     * @return answer Latest price
     * @return startedAt Timestamp when the round was started; passed on from price feed B
     * @return updatedAt Timestamp when the round was last updated; passed on from price feed B
     * @return answeredInRound Round id in which the answer was computed; passed on from price feed B
     * @dev Note: Only the `answer` really matters for downstream contracts that use this price feed (e.g. Comet)
     **/
    function latestRoundData() override external view returns (uint80, int256, uint256, uint256, uint80) {
        (, int256 priceA, , , ) = AggregatorV3Interface(priceFeedA).latestRoundData();
        (uint80 roundId_, int256 priceB, uint256 startedAt_, uint256 updatedAt_, uint80 answeredInRound_) = AggregatorV3Interface(priceFeedB).latestRoundData();

        if (priceA <= 0 || priceB <= 0) return (roundId_, 0, startedAt_, updatedAt_, answeredInRound_);

        // int256 price = priceA * (priceFeedBScale/priceB) * priceFeedScale / priceFeedAScale;
        int256 price = priceA * priceFeedBScale * priceFeedScale / priceB / priceFeedAScale;
        return (roundId_, price, startedAt_, updatedAt_, answeredInRound_);
    }

    function signed256(uint256 n) internal pure returns (int256) {
        if (n > uint256(type(int256).max)) revert InvalidInt256();
        return int256(n);
    }

    /**
     * @notice Price for the latest round
     * @return The version of the price feed contract
     **/
    function version() external pure returns (uint256) {
        return VERSION;
    }
}
"
    },
    "contracts/vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": {
      "content": "// 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
    );
}
"
    }
  },
  "settings": {
    "evmVersion": "london",
    "metadata": {
      "bytecodeHash": "ipfs"
    },
    "optimizer": {
      "details": {
        "constantOptimizer": true,
        "cse": true,
        "deduplicate": true,
        "inliner": true,
        "jumpdestRemover": true,
        "orderLiterals": true,
        "peephole": true,
        "yul": true,
        "yulDetails": {
          "optimizerSteps": "dhfoDgvulfnTUtnIf [xa[r]scLM cCTUtTOntnfDIul Lcul Vcul [j] Tpeul xa[rul] xa[r]cL gvif CTUca[r]LsTOtfDnca[r]Iulc] jmul[jul] VcTOcul jmul",
          "stackAllocation": true
        }
      },
      "runs": 1
    },
    "remappings": [],
    "viaIR": true,
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    }
  }
}}

Tags:
Factory, Oracle|addr:0xe51a17c21b4cd878cdae305df9bacc3477425282|verified:true|block:23733715|tx:0x51cea2a970b86470a6bf065b6c61bbd83f2b89910d1b5f018430d9cabd087029|first_check:1762353788

Submitted on: 2025-11-05 15:43:10

Comments

Log in to comment.

No comments yet.