Blockchain / Global / Address
Contract
0x295982F5515fbbAF2EE6c361dc6d58162a129f3e
- 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"
}
]