Blockchain / Global / Address

Contract

0x09ffBfF04D893bBd632A0823b0dC16d2ADf41f76

Balance
0 SOMI
Transactions sent
1
Type
Contract · 1,517 bytes of code

CLAggregatorAdapter Verified

Compiler
solc 0.8.28+commit.7893614a
Language
Solidity
Optimization
Yes, 200 runs
EVM version
paris
License
—
Verified
2026-10-12

contracts/cl-adapters/CLAggregatorAdapter.sol

and 3 more files

Solidity
// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: Copyright (c) 2024-2025 Schelling Point Labs Inc.
pragma solidity ^0.8.28;

import '../interfaces/ICLAggregatorAdapter.sol';
import {CLAdapterLib} from '../libraries/CLAdapterLib.sol';

/// @title CLAggregatorAdapter
/// @author Aneta Tsvetkova
/// @notice Contract that proxies calls to the dataFeedStore
/// @notice This contract is responsible for fetching data for one feed only
contract CLAggregatorAdapter is ICLAggregatorAdapter {
  /// @inheritdoc IChainlinkAggregator
  uint8 public immutable override decimals;
  /// @inheritdoc ICLAggregatorAdapter
  address public immutable override dataFeedStore;

  /// @notice The ID of the feed
  /// @dev The ID is shifted to the left by 120 bits to save gas
  uint256 internal immutable ID;

  /// @inheritdoc IChainlinkAggregator
  string public override description;

  /// @notice Constructor
  /// @param _description The description of the feed
  /// @param _decimals The decimals of the feed
  /// @param _id The ID of the feed
  /// @param _dataFeedStore The address of the data feed store
  constructor(
    string memory _description,
    uint8 _decimals,
    uint256 _id,
    address _dataFeedStore
  ) {
    description = _description;
    decimals = _decimals;
    ID = CLAdapterLib.shiftId(_id);
    dataFeedStore = _dataFeedStore;
  }

  /// @inheritdoc ICLAggregatorAdapter
  function id() external view override returns (uint256) {
    return ID >> 120;
  }

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

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

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

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

Other files

  • contracts/interfaces/ICLAggregatorAdapter.sol
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.28;
    
    import {IChainlinkAggregator} from './chainlink/IChainlinkAggregator.sol';
    
    interface ICLAggregatorAdapter is IChainlinkAggregator {
      /// @notice The feed data this contract is responsible for
      /// @dev This is the feed ID for the mapping in the dataFeedStore
      /// @return _id The ID for the feed
      function id() external view returns (uint256);
    
      /// @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);
    }
    
  • contracts/interfaces/chainlink/IChainlinkAggregator.sol
    /**
     * SPDX-FileCopyrightText: Copyright (c) 2021 SmartContract ChainLink Limited SEZC
     *
     * SPDX-License-Identifier: MIT
     */
    pragma solidity ^0.8.28;
    
    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
        );
    }
    
  • contracts/libraries/CLAdapterLib.sol
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.28;
    
    //    ___  __         __                           _  __    __                  __
    //   / _ )/ /__  ____/ /__ ___ ___ ___  ___ ___   / |/ /__ / /__    _____  ____/ /__
    //  / _  / / _ \/ __/  '_/(_-</ -_) _ \(_-</ -_) /    / -_) __/ |/|/ / _ \/ __/  '_/
    // /____/_/\___/\__/_/\_\/___/\__/_//_/___/\__/ /_/|_/\__/\__/|__,__/\___/_/ /_/\_\
    //    _____   ____  ___    ___   ___  ________
    //   / __/ | / /  |/  /   / _ | / _ \/ __/ __/
    //  / _/ | |/ / /|_/ /   / __ |/ // / _/_\ \
    // /___/ |___/_/  /_/   /_/ |_/____/_/ /___/
    //
    // Website:         https://blocksense.network/
    // Git Repository:  https://github.com/blocksense-network/blocksense
    
    /// @title CLAdapterLib
    /// @author Aneta Tsvetkova
    /// @notice Library for calling dataFeedStore functions for Chainlink adapters
    /// @dev Contains utility functions for calling gas efficiently dataFeedStore functions and decoding return data
    library CLAdapterLib {
      /// @notice Gets the latest answer from the dataFeedStore
      /// @param dataFeedStore The address of the dataFeedStore contract
      /// @param id The ID of the feed
      /// @return answer The latest stored value after being decoded
      function latestAnswer(
        uint256 id,
        address dataFeedStore
      ) internal view returns (int256) {
        return
          int256(
            uint256(
              uint192(
                bytes24(
                  // 1st byte is function selector
                  // after that are 16 bytes of the feed id
                  _callDataFeed(dataFeedStore, (uint256(0x82) << 248) | id)
                )
              )
            )
          );
      }
    
      /// @notice Gets the round data from the dataFeedStore
      /// @param _roundId The round ID to retrieve data for
      /// @param id The ID of 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,
        uint256 id,
        address dataFeedStore
      )
        internal
        view
        returns (uint80, int256 answer, uint256 startedAt, uint256, uint80)
      {
        (answer, startedAt) = _decodeData(
          _callDataFeed(
            dataFeedStore,
            // 1st byte is function selector
            // after that are 16 bytes of the feed id
            // after the feed id are 2 bytes of the round id
            (uint256(0x86) << 248) | id | (uint256(_roundId) << 104)
          )
        );
        return (_roundId, answer, startedAt, startedAt, _roundId);
      }
    
      /// @notice Gets the latest round ID for a given feed from the dataFeedStore
      /// @param id The ID of the feed
      /// @param dataFeedStore The address of the dataFeedStore contract
      /// @return roundId The latest round ID
      function latestRound(
        uint256 id,
        address dataFeedStore
      ) internal view returns (uint256) {
        return
          uint256(
            // 1st byte is function selector
            // after that are 16 bytes of the feed id
            _callDataFeed(dataFeedStore, (uint256(0x81) << 248) | id)
          );
      }
    
      /// @notice Gets the latest round data for a given feed from the dataFeedStore
      /// @dev Using assembly achieves lower gas costs
      /// @param id The ID of 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(
        uint256 id,
        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
          // 1st byte is function selector
          // after that are 16 bytes of the feed id
          mstore(
            0x00,
            or(
              0x8300000000000000000000000000000000000000000000000000000000000000,
              id
            )
          )
    
          // call dataFeedStore with selector and store return value (64 bytes) at memory location ptr
          let success := staticcall(gas(), dataFeedStore, 0x00, 17, 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 first 32 bytes of the returned 64 bytes
          roundId := mload(ptr)
    
          // value is stored in the second 32 bytes of the returned 64 bytes
          returnData := 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 selector The data to call the dataFeedStore with
      /// @return returnData The return value from the dataFeedStore
      function _callDataFeed(
        address dataFeedStore,
        uint256 selector
      ) internal view returns (bytes32 returnData) {
        // using assembly staticcall costs less gas than using a view function
        assembly {
          // store selector in memory at location 0
          mstore(0x00, selector)
    
          // call dataFeedStore with data and store return value (32 bytes) at memory location ptr
          let success := staticcall(
            gas(), // gas remaining
            dataFeedStore, // address to call
            0x00, // location of data to call
            19, // size of data to call - usually it is 17b but for _getRoundData it is 19b because of the 2 bytes of the roundId
            returnData, // 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 to returnData
          returnData := mload(returnData)
        }
      }
    
      /// @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)) / 1000 // timestamp is stored in milliseconds
        );
      }
    
      /// @notice Shifts the feed id to the left by 120 bits
      /// @dev This is used in the constructor to save gas when calling the dataFeedStore
      /// The dataFeedStore expects the feed id to be positioned in the calldata in a 16 bytes value starting from the 2nd byte
      /// @param id The feed id to shift
      function shiftId(uint256 id) internal pure returns (uint256) {
        return id << 120;
      }
    }
    
ABI · 9 entries
json
[
  {
    "type": "constructor",
    "inputs": [
      {
        "name": "_description",
        "type": "string",
        "internalType": "string"
      },
      {
        "name": "_decimals",
        "type": "uint8",
        "internalType": "uint8"
      },
      {
        "name": "_id",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "_dataFeedStore",
        "type": "address",
        "internalType": "address"
      }
    ],
    "stateMutability": "nonpayable"
  },
  {
    "name": "dataFeedStore",
    "type": "function",
    "inputs": [],
    "outputs": [
      {
        "name": "",
        "type": "address",
        "internalType": "address"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "decimals",
    "type": "function",
    "inputs": [],
    "outputs": [
      {
        "name": "",
        "type": "uint8",
        "internalType": "uint8"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "description",
    "type": "function",
    "inputs": [],
    "outputs": [
      {
        "name": "",
        "type": "string",
        "internalType": "string"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "getRoundData",
    "type": "function",
    "inputs": [
      {
        "name": "_roundId",
        "type": "uint80",
        "internalType": "uint80"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "uint80",
        "internalType": "uint80"
      },
      {
        "name": "",
        "type": "int256",
        "internalType": "int256"
      },
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "",
        "type": "uint80",
        "internalType": "uint80"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "id",
    "type": "function",
    "inputs": [],
    "outputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "latestAnswer",
    "type": "function",
    "inputs": [],
    "outputs": [
      {
        "name": "",
        "type": "int256",
        "internalType": "int256"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "latestRound",
    "type": "function",
    "inputs": [],
    "outputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "latestRoundData",
    "type": "function",
    "inputs": [],
    "outputs": [
      {
        "name": "",
        "type": "uint80",
        "internalType": "uint80"
      },
      {
        "name": "",
        "type": "int256",
        "internalType": "int256"
      },
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "",
        "type": "uint80",
        "internalType": "uint80"
      }
    ],
    "stateMutability": "view"
  }
]