Docs
Contracts
Integration Guide
Using data feeds
Historic Data Feed Store

Historical Data Feed Store

Historical Data Feed Store contract is where all data is stored and where all contracts read from. It is written in Solidity assembly and contains only one function: fallback.

⚠️

This contract serves as the core logic that dictates how the UpgradeableProxy contract manages its own storage, handling both data writing and reading operations. It's crucial to understand that all data is exclusively stored within the UpgradeableProxy contract. To access this data, users must interact with the fallback function of the UpgradeableProxy contract which underneath calls the fallback function of the HistoricDataFeedStore contract.

Code Examples

Solidity

💡

Use ProxyCall library for easy and gas optimised interaction with the contract.

In order to retrieve data from the contract, the client must call the fallback function as follows:

  • To read the latest price and timestamp:
solidity
function getDataById(
  uint32 key
) external view returns (uint256 value, uint64 timestamp) {
  bytes32 data = ProxyCall._callDataFeed(
    dataFeedStore,
    abi.encodePacked(0x80000000 | key)
  );
 
  return (uint256(uint192(bytes24(data))), uint64(uint256(data)));
}
  • To read historical data for a specific round:
solidity
function getFeedAtCounter(
  uint32 key,
  uint32 counter
) external view returns (uint256 value, uint64 timestamp) {
  bytes32 data = ProxyCall._callDataFeed(
    dataFeedStore,
    abi.encodeWithSelector(bytes4(0x20000000 | key), counter)
  );
 
  return (uint256(uint192(bytes24(data))), uint64(uint256(data)));
}
  • To get the latest round:
solidity
function getLatestCounter(uint32 key) external view returns (uint32 counter) {
  return uint32(ProxyCall._latestRound(key, dataFeedStore));
}
  • To get the latest round data:
solidity
function getDataById(
  uint32 key
) external view returns (int256 value, uint256 timestamp, uint80 counter) {
  (counter, value, timestamp, , ) = ProxyCall
    ._latestRoundData(key, dataFeedStore);
}

Solidity Hardhat Example

💡

You can find a working Hardhat project here. Clone the repo and follow the setup instructions to run the example locally.

Ethers.js v6.x

To read the latest value and timestamp:

javascript
const historicDataFeedStore = new ethers.Contract(
  contractAddress,
  abiJson,
  provider,
);
const data = '0x' + ((key | 0x80000000) >>> 0).toString(16).padStart(8, '0');
 
const res = await network.provider.send('eth_call', [
  {
    to: historicDataFeedStore.target,
    data,
  },
  'latest',
]);
 
const value = Number(res.slice(0, 50));
const timestamp = Number('0x' + res.slice(50, 66));

To read historical data for a specific round:

javascript
const historicDataFeedStore = new ethers.Contract(
  contractAddress,
  abiJson,
  provider,
);
const round = 1;
const data = '0x' + ((key | 0x20000000) >>> 0).toString(16).padStart(8, '0');
 
const res = await network.provider.send('eth_call', [
  {
    to: historicDataFeedStore.target,
    data: ethers.solidityPacked(['bytes4', 'uint256'], [data, round]),
  },
  'latest',
]);
 
const value = Number(res.slice(0, 50));
const timestamp = Number('0x' + res.slice(50, 66));

To get the latest round:

javascript
const historicDataFeedStore = new ethers.Contract(
  contractAddress,
  abiJson,
  provider,
);
const data = '0x' + ((key | 0x40000000) >>> 0).toString(16).padStart(8, '0');
 
const res = await network.provider.send('eth_call', [
  {
    to: historicDataFeedStore.target,
    data,
  },
  'latest',
]);
const round = Number('0x' + res.slice(66));

To get the latest round data:

javascript
const historicDataFeedStore = new ethers.Contract(
  contractAddress,
  abiJson,
  provider,
);
const data = '0x' + ((key | 0xc0000000) >>> 0).toString(16).padStart(8, '0');
 
const res = await network.provider.send('eth_call', [
  {
    to: historicDataFeedStore.target,
    data,
  },
  'latest',
]);
 
const value = Number(res.slice(0, 50));
const timestamp = Number('0x' + res.slice(50, 66));
const round = Number('0x' + res.slice(66));