Sonic Blaze Testnet

Contract Diff Checker

Contract Name:
ChainlinkProxy

Contract Source Code:

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

import '../interfaces/IAggregator.sol';
import {ProxyCall} from '../libraries/ProxyCall.sol';

/// @title ChainlinkProxy
/// @notice Contract that proxies calls to the dataFeedStore
/// @notice This contract is responsible for fetching data for one feed only
contract ChainlinkProxy is IAggregator {
  /// @inheritdoc IChainlinkAggregator
  uint8 public immutable override decimals;
  /// @inheritdoc IAggregator
  uint32 public immutable override key;
  /// @inheritdoc IAggregator
  address public immutable override dataFeedStore;

  /// @inheritdoc IChainlinkAggregator
  string public override description;

  /// @notice Constructor
  /// @param _description The description of the feed
  /// @param _decimals The decimals of the feed
  /// @param _key The key ID of the feed
  /// @param _dataFeedStore The address of the data feed store
  constructor(
    string memory _description,
    uint8 _decimals,
    uint32 _key,
    address _dataFeedStore
  ) {
    description = _description;
    decimals = _decimals;
    key = _key;
    dataFeedStore = _dataFeedStore;
  }

  /// @inheritdoc IChainlinkAggregator
  function latestAnswer() external view override returns (int256) {
    return ProxyCall._latestAnswer(key, dataFeedStore);
  }

  /// @inheritdoc IChainlinkAggregator
  function latestRound() external view override returns (uint256) {
    return ProxyCall._latestRound(key, dataFeedStore);
  }

  /// @inheritdoc IChainlinkAggregator
  function latestRoundData()
    external
    view
    override
    returns (uint80, int256, uint256, uint256, uint80)
  {
    return ProxyCall._latestRoundData(key, dataFeedStore);
  }

  /// @inheritdoc IChainlinkAggregator
  function getRoundData(
    uint80 _roundId
  ) external view override returns (uint80, int256, uint256, uint256, uint80) {
    return ProxyCall._getRoundData(_roundId, key, dataFeedStore);
  }
}

/**
 * SPDX-FileCopyrightText: Copyright (c) 2021 SmartContract ChainLink Limited SEZC
 *
 * SPDX-License-Identifier: MIT
 */
pragma solidity ^0.8.24;

interface IChainlinkAggregator {
  /// @notice Decimals for the feed data
  /// @return decimals The decimals of the feed
  function decimals() external view returns (uint8);

  /// @notice Description text for the feed data
  /// @return description The description of the feed
  function description() external view returns (string memory);

  /// @notice Get the latest answer for the feed
  /// @return answer The latest value stored
  function latestAnswer() external view returns (int256);

  /// @notice Get the latest round ID for the feed
  /// @return roundId The latest round ID
  function latestRound() external view returns (uint256);

  /// @notice Get the data for a round at a given round ID
  /// @param _roundId The round ID to retrieve the data for
  /// @return roundId The round ID
  /// @return answer The value stored for the round
  /// @return startedAt Timestamp of when the value was stored
  /// @return updatedAt Same as startedAt
  /// @return answeredInRound Same as roundId
  function getRoundData(
    uint80 _roundId
  )
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );

  /// @notice Get the latest round data available
  /// @return roundId The latest round ID for the feed
  /// @return answer The value stored for the round
  /// @return startedAt Timestamp of when the value was stored
  /// @return updatedAt Same as startedAt
  /// @return answeredInRound Same as roundId
  function latestRoundData()
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );
}

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

import {IChainlinkAggregator} from './chainlink/IChainlinkAggregator.sol';

interface IAggregator is IChainlinkAggregator {
  /// @notice The feed data this contract is responsible for
  /// @dev This is the key ID for the mapping in the dataFeedStore
  /// @return key The key ID for the feed
  function key() external view returns (uint32);

  /// @notice The dataFeedStore this contract is responsible for
  /// @dev The address of the underlying contract that stores the data
  /// @return dataFeedStore The address of the dataFeedStore
  function dataFeedStore() external view returns (address);
}

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

/// @title ProxyCall
/// @notice Library for calling dataFeedStore functions
/// @dev Contains utility functions for calling gas efficiently dataFeedStore functions and decoding return data
library ProxyCall {
  /// @notice Gets the latest answer from the dataFeedStore
  /// @param key The key ID for the feed
  /// @param dataFeedStore The address of the dataFeedStore contract
  /// @return answer The latest stored value after being decoded
  function _latestAnswer(
    uint32 key,
    address dataFeedStore
  ) internal view returns (int256) {
    return
      int256(
        uint256(
          uint192(
            bytes24(
              _callDataFeed(dataFeedStore, abi.encodePacked(0x80000000 | key))
            )
          )
        )
      );
  }

  /// @notice Gets the round data from the dataFeedStore
  /// @param _roundId The round ID to retrieve data for
  /// @param key The key ID for the feed
  /// @param dataFeedStore The address of the dataFeedStore contract
  /// @return roundId The round ID
  /// @return answer The value stored for the feed at the given round ID
  /// @return startedAt The timestamp when the value was stored
  /// @return updatedAt Same as startedAt
  /// @return answeredInRound Same as roundId
  function _getRoundData(
    uint80 _roundId,
    uint32 key,
    address dataFeedStore
  )
    internal
    view
    returns (uint80, int256 answer, uint256 startedAt, uint256, uint80)
  {
    (answer, startedAt) = _decodeData(
      _callDataFeed(
        dataFeedStore,
        abi.encodeWithSelector(bytes4(0x20000000 | key), _roundId)
      )
    );

    return (_roundId, answer, startedAt, startedAt, _roundId);
  }

  /// @notice Gets the latest round ID for a given feed from the dataFeedStore
  /// @dev Using assembly achieves lower gas costs
  /// @param key The key ID for the feed
  /// @param dataFeedStore The address of the dataFeedStore contract
  /// @return roundId The latest round ID
  function _latestRound(
    uint32 key,
    address dataFeedStore
  ) internal view returns (uint256 roundId) {
    // using assembly staticcall costs less gas than using a view function
    assembly {
      // get free memory pointer
      let ptr := mload(0x40)

      // store selector in memory at location 0
      mstore(0, shl(224, or(0x40000000, key)))

      // call dataFeedStore with selector 0xc0000000 | key (4 bytes) and store return value (64 bytes) at memory location ptr
      let success := staticcall(gas(), dataFeedStore, 0, 4, ptr, 64)

      // revert if call failed
      if iszero(success) {
        revert(0, 0)
      }

      // load return value from memory at location ptr
      // roundId is stored in the second 32 bytes of the return 64 bytes
      roundId := mload(add(ptr, 32))
    }
  }

  /// @notice Gets the latest round data for a given feed from the dataFeedStore
  /// @dev Using assembly achieves lower gas costs
  /// @param key The key ID for the feed
  /// @param dataFeedStore The address of the dataFeedStore contract
  /// @return roundId The latest round ID
  /// @return answer The latest stored value after being decoded
  /// @return startedAt The timestamp when the value was stored
  /// @return updatedAt Same as startedAt
  /// @return answeredInRound Same as roundId
  function _latestRoundData(
    uint32 key,
    address dataFeedStore
  )
    internal
    view
    returns (uint80 roundId, int256 answer, uint256 startedAt, uint256, uint80)
  {
    bytes32 returnData;

    // using assembly staticcall costs less gas than using a view function
    assembly {
      // get free memory pointer
      let ptr := mload(0x40)

      // store selector in memory at location 0
      mstore(0x00, shl(224, or(0xc0000000, key)))

      // call dataFeedStore with selector 0xc0000000 | key (4 bytes) and store return value (64 bytes) at memory location ptr
      let success := staticcall(gas(), dataFeedStore, 0x00, 4, ptr, 64)

      // revert if call failed
      if iszero(success) {
        revert(0, 0)
      }

      // assign return value to returnData
      returnData := mload(ptr)

      // load return value from memory at location ptr
      // roundId is stored in the second 32 bytes of the return 64 bytes
      roundId := mload(add(ptr, 32))
    }

    (answer, startedAt) = _decodeData(returnData);

    return (roundId, answer, startedAt, startedAt, roundId);
  }

  /// @notice Calls the dataFeedStore with the given data
  /// @dev Using assembly achieves lower gas costs
  /// Used as a call() function to dataFeedStore
  /// @param dataFeedStore The address of the dataFeedStore contract
  /// @param data The data to call the dataFeedStore with
  /// @return returnData The return value from the dataFeedStore
  function _callDataFeed(
    address dataFeedStore,
    bytes memory data
  ) internal view returns (bytes32 returnData) {
    // using assembly staticcall costs less gas than using a view function
    assembly {
      // get free memory pointer
      let ptr := mload(0x40)

      // call dataFeedStore with data and store return value (32 bytes) at memory location ptr
      let success := staticcall(
        gas(), // gas remaining
        dataFeedStore, // address to call
        add(data, 32), // location of data to call (skip first 32 bytes of data which is the length of data)
        mload(data), // size of data to call
        ptr, // where to store the return data
        32 // how much data to store
      )

      // revert if call failed
      if iszero(success) {
        revert(0, 0)
      }

      // assign loaded return value at memory location ptr to returnData
      returnData := mload(ptr)
    }
  }

  /// @notice Decodes the return data from the dataFeedStore
  /// @param data The data to decode
  /// @return answer The value stored for the feed at the given round ID
  /// @return timestamp The timestamp when the value was stored
  function _decodeData(bytes32 data) internal pure returns (int256, uint256) {
    return (int256(uint256(uint192(bytes24(data)))), uint64(uint256(data)));
  }
}

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

Context size (optional):