Skip to Content
DocsContractsIntegration GuideUsing data feedsAggregated Data Feed Store

Aggregated Data Feed Store (ADFS)

Aggregated 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.

The examples below show how to call the contract to fetch data. We have the following types of calls:

  • selector 0x86: getDataAtIndex(uint128 feedId, uint16 index, uint32 startSlot?, uint32 slots?) returns (bytes)
  • selector 0x81: getLatestIndex(uint128 feedId) returns (uint16)
  • selector 0x82: getLatestSingleData(uint128 feedId) returns (bytes)
  • selector 0x84: getLatestData(uint128 feedId, uint32 startSlot?, uint32 slots?) returns (bytes)

The Aggregated Data Feed Store (ADFS) maintains historical data for feeds of varying sizes. Each feed’s size is determined by its slot count, where 1 slot equals 32 bytes. Supported sizes follow powers of 2, ranging from 0 to 31: [2^0; 2^31] (1 slot, 2 slots, 4 slots, 8 slots, 16 slots, 32 slots, etc.).

Data is stored using a ring buffer architecture with a maximum capacity of 8,192 indices (2^13). When the buffer reaches capacity, new data overwrites the oldest entries beginning at index 0, ensuring continuous operation while maintaining the most recent historical data.

Code Examples

Solidity

Here is a complete working example. After that, there are more details on how to perform a raw call.

ADFSConsumer.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import {ADFS} from `libraries/ADFS.sol'; /** * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE. * DO NOT USE THIS CODE IN PRODUCTION. */ contract ADFSConsumer { address public immutable adfs; constructor(address _adfs) { adfs = _adfs; } function getLatestSingleData(uint256 id) external view returns (bytes32) { return ADFS.getLatestSingleData(adfs, id); } function getLatestData(uint256 id) external view returns (bytes32[] memory) { return ADFS.getLatestData(adfs, id); } function getLatestDataSlice( uint256 id, uint256 startSlot, uint256 slotsCount ) external view returns (bytes32[] memory) { return ADFS.getLatestDataSlice(adfs, id, startSlot, slotsCount); } function getLatestIndex(uint256 id) external view returns (uint256 index) { return ADFS.getLatestIndex(adfs, id); } function getSingleDataAtIndex( uint256 id, uint256 index ) external view returns (bytes32) { return ADFS.getSingleDataAtIndex(adfs, id, index); } function getDataAtIndex( uint256 id, uint256 index ) external view returns (bytes32[] memory) { return ADFS.getDataAtIndex(adfs, id, index); } function getDataSliceAtIndex( uint256 id, uint256 index, uint256 startSlot, uint256 slotsCount ) external view returns (bytes32[] memory) { return ADFS.getDataSliceAtIndex(adfs, id, index, startSlot, slotsCount); } function getLatestSingleDataAndIndex( uint256 id ) external view returns (bytes32 data, uint256 index) { return ADFS.getLatestSingleDataAndIndex(adfs, id); } function getLatestDataAndIndex( uint256 id ) external view returns (bytes32[] memory data, uint256 index) { return ADFS.getLatestDataAndIndex(adfs, id); } function getLatestDataSliceAndIndex( uint256 id, uint256 startSlot, uint256 slotsCount ) external view returns (bytes32[] memory data, uint256 index) { return ADFS.getLatestDataSliceAndIndex(adfs, id, startSlot, slotsCount); } function getEpochSeconds(uint256 id) external view returns (uint64) { return ADFS.getEpochSeconds(ADFS.getLatestSingleData(adfs, id)); } function getEpochMilliseconds(uint256 id) external view returns (uint64) { return ADFS.getEpochMilliseconds(ADFS.getLatestSingleData(adfs, id)); } }

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

  • To read the latest data stored in a feed stored in up to 32 bytes:
solidity
function getLatestSingleData(uint256 id) external view returns (bytes32) { return ADFS.getLatestSingleData(adfs, id); }
  • To read the latest data stored in a feed stored in more than 32 bytes:
solidity
function getLatestData(uint256 id) external view returns (bytes32[] memory) { return ADFS.getLatestData(adfs, id); }
  • To read a slice of the latest data stored in a feed stored in more than 32 bytes:
solidity
function getLatestDataSlice( uint256 id, uint256 startSlot, uint256 slotsCount ) external view returns (bytes32[] memory) { return ADFS.getLatestDataSlice(adfs, id, startSlot, slotsCount); }
  • To get the latest ring buffer index:
solidity
function getLatestIndex(uint256 id) external view returns (uint256 index) { return ADFS.getLatestIndex(adfs, id); }
  • To read historical data stored in a feed stored in up to 32 bytes:
solidity
function getSingleDataAtIndex( uint256 id, uint256 index ) external view returns (bytes32) { return ADFS.getSingleDataAtIndex(adfs, id, index); }
  • To read historical data stored in a feed stored in more than 32 bytes:
solidity
function getDataAtIndex( uint256 id, uint256 index ) external view returns (bytes32[] memory) { return ADFS.getDataAtIndex(adfs, id, index); }
  • To read a slice of the historical data stored in a feed stored in more than 32 bytes:
solidity
function getDataSliceAtIndex( uint256 id, uint256 index, uint256 startSlot, uint256 slotsCount ) external view returns (bytes32[] memory) { return ADFS.getDataSliceAtIndex(adfs, id, index, startSlot, slotsCount); }
  • To read the latest data stored in a feed stored in up to 32 bytes with its ring buffer index:
solidity
function getLatestSingleDataAndIndex( uint256 id ) external view returns (bytes32 data, uint256 index) { return ADFS.getLatestSingleDataAndIndex(adfs, id); }
  • To read the latest data stored in a feed stored in more than 32 bytes with its ring buffer index:
solidity
function getLatestDataAndIndex( uint256 id ) external view returns (bytes32[] memory data, uint256 index) { return ADFS.getLatestDataAndIndex(adfs, id); }
  • To read a slice of the latest data of a feed stored in more than 32 bytes with its ring buffer index:
solidity
function getLatestDataSliceAndIndex( uint256 id, uint256 startSlot, uint256 slotsCount ) external view returns (bytes32[] memory data, uint256 index) { return ADFS.getLatestDataSliceAndIndex(adfs, id, startSlot, slotsCount); }

Solidity Hardhat Example

Ethers.js v6.x

To read the latest data stored in a feed stored in up to 32 bytes:

javascript
// inputs: id const adfs = new ethers.Contract( contractAddress, abiJson, provider, ); const data = ethers.solidityPacked(['bytes1', 'uint128'], ['0x82', id]); const res = await network.provider.send('eth_call', [ { to: adfs.target, data, }, 'latest', ]); const value = Number(res.slice(0, 50)); const timestamp = Number('0x' + res.slice(50, 66));

To read the latest data stored in a feed stored in more than 32 bytes:

javascript
// inputs: id const adfs = new ethers.Contract( contractAddress, abiJson, provider, ); const data = ethers.solidityPacked(['bytes1', 'uint128'], ['0x82', id]); const res = await network.provider.send('eth_call', [ { to: adfs.target, data, }, 'latest', ]); const value = splitInto32bChunks(res);

To read a slice of the latest data stored in a feed stored in more than 32 bytes:

javascript
// inputs: id, startSlot, slots const adfs = new ethers.Contract( contractAddress, abiJson, provider, ); const data = ethers.solidityPacked( ['bytes1', 'uint128', 'uint32', 'uint32'], ['0x84', id, startSlot, slots], ); const res = await network.provider.send('eth_call', [ { to: adfs.target, data, }, 'latest', ]); const value = splitInto32bChunks(res);

To get the latest ring buffer index:

javascript
// inputs: id const adfs = new ethers.Contract( contractAddress, abiJson, provider, ); const data = ethers.solidityPacked(['bytes1', 'uint128'], ['0x81', id]); const res = await network.provider.send('eth_call', [ { to: adfs.target, data, }, 'latest', ]); const index = Number(res)

To read historical data stored in a feed stored in up to 32 bytes:

javascript
// inputs: id, indexId const adfs = new ethers.Contract( contractAddress, abiJson, provider, ); const data = ethers.solidityPacked( ['bytes1', 'uint128', 'uint16'], ['0x86', id, indexId], ); const res = await network.provider.send('eth_call', [ { to: adfs.target, data, }, 'latest', ]); const value = Number(res.slice(0, 50)); const timestamp = Number('0x' + res.slice(50, 66));

To read historical data stored in a feed stored in more than 32 bytes:

javascript
// inputs: id, indexId const adfs = new ethers.Contract( contractAddress, abiJson, provider, ); const data = ethers.solidityPacked( ['bytes1', 'uint128', 'uint16'], ['0x86', id, indexId], ); const res = await network.provider.send('eth_call', [ { to: adfs.target, data, }, 'latest', ]); const value = splitInto32bChunks(res);

To read a slice of the historical data stored in a feed stored in more than 32 bytes:

javascript
// inputs: id, indexId, startSlot, slots const adfs = new ethers.Contract( contractAddress, abiJson, provider, ); const data = ethers.solidityPacked( ['bytes1', 'uint128', 'uint16', 'uint32', 'uint32'], ['0x86', id, indexId, startSlot, slots], ); const res = await network.provider.send('eth_call', [ { to: adfs.target, data, }, 'latest', ]); const value = splitInto32bChunks(res);

To read the latest data stored in a feed stored in up to 32 bytes with its ring buffer index:

javascript
// inputs: id const adfs = new ethers.Contract( contractAddress, abiJson, provider, ); const data = ethers.solidityPacked(['bytes1', 'uint128'], ['0x83', id]); const res = await network.provider.send('eth_call', [ { to: adfs.target, data, }, 'latest', ]); const feedData = '0x' + res.slice(66); const index = Number(res.slice(0, 66)); const value = Number(feedData.slice(0, 50)); const timestamp = Number('0x' + feedData.slice(50, 66));

To read the latest data stored in a feed stored in more than 32 bytes with its ring buffer index:

javascript
// inputs: id const adfs = new ethers.Contract( contractAddress, abiJson, provider, ); const data = ethers.solidityPacked(['bytes1', 'uint128'], ['0x85', id]); const res = await network.provider.send('eth_call', [ { to: adfs.target, data, }, 'latest', ]); const value = splitInto32bChunks(res);

To read a slice of the latest data stored in a feed stored in more than 32 bytes with its ring buffer index:

javascript
// inputs: id, startSlot, slots const adfs = new ethers.Contract( contractAddress, abiJson, provider, ); const data = ethers.solidityPacked( ['bytes1', 'uint128', 'uint32', 'uint32'], ['0x85', id, startSlot, slots], ); const res = await network.provider.send('eth_call', [ { to: adfs.target, data, }, 'latest', ]); const value = splitInto32bChunks(res);
Last updated on