Getting Started with Consumers Contracts
What You'll Learn
- How to develop smart contracts that consume Allora Network inferences
- Two main patterns for using inference data in your contracts
- Setting up consumer contracts with proper verification
Overview
Sample code snippets to help you get started using inferences from Allora topics
Consumer contracts are essential for bringing Allora Network prices on-chain. You can find the code repository containing example consumer contracts here (opens in a new tab). Consumer contracts verify that the data is correctly formatted, and signed by a valid signer.
Why Use Consumer Contracts?
Consumer contracts provide:
- Data verification: Ensures inference data is correctly formatted and signed
- On-chain integration: Brings Allora Network predictions directly into your smart contracts
- Security: Cryptographic verification of all inference data
Prerequisites
- Solidity development experience (version 0.8.13+)
- Understanding of smart contract interfaces
- Experience with OpenZeppelin contracts
Consuming Allora Inferences
Below is a complete example of a contract that brings inference data on-chain for use in a protocol, and verifies the data against an Allora Consumer contract. This example code can be found here (opens in a new tab).
Complete Contract Example
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {
IAlloraConsumer,
TopicValue,
AlloraConsumerNetworkInferenceData
} from '../interface/IAlloraConsumer.sol';
import { Ownable2Step } from "../../lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol";
import { EnumerableSet } from "../../lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol";
/**
* @title AlloraConsumerBringPredictionOnChainExample
* @notice Example contract for using the Allora consumer by bringing predictions on-chain
*/
contract AlloraConsumerBringPredictionOnChainExample is Ownable2Step {
// Sepolia consumer Address
IAlloraConsumer public alloraConsumer = IAlloraConsumer(0x4341a3F0a350C2428184a727BAb86e16D4ba7018);
// ***************************************************************
// * ================== USER INTERFACE ========================= *
// ***************************************************************
/**
* @notice Example for calling a protocol function with using an inference and confidence
* intervals already stored on the Allora Consumer, only if the value is not stale.
*
* @param protocolFunctionArgument An argument for the protocol function
* @param topicId The id of the topic to use the most recent stored value for
*/
function callProtocolFunctionWithExistingValue(
uint256 protocolFunctionArgument,
uint256 topicId
) external payable {
TopicValue memory topicValue = alloraConsumer.getTopicValue(topicId, '');
if (topicValue.recentValueTime + 1 hours < block.timestamp) {
revert('AlloraConsumerBringPredictionOnChainExample: stale value');
}
_protocolFunctionRequiringPredictionValue(
protocolFunctionArgument,
topicValue.recentValue,
topicValue.confidenceIntervalPercentiles,
topicValue.confidenceIntervalValues
);
}
/**
* @notice Example for calling a protocol function with an inference value from the Allora Consumer
*
* @param protocolFunctionArgument An argument for the protocol function
* @param alloraNetworkInferenceData The signed data from the Allora Consumer
*/
function callProtocolFunctionWithAlloraTopicInference(
uint256 protocolFunctionArgument,
AlloraConsumerNetworkInferenceData calldata alloraNetworkInferenceData
) external payable {
(
uint256 value,
uint256[] memory confidenceIntervalPercentiles,
uint256[] memory confidenceIntervalValues,
) = alloraConsumer.verifyNetworkInference(alloraNetworkInferenceData);
_protocolFunctionRequiringPredictionValue(
protocolFunctionArgument,
value,
confidenceIntervalPercentiles,
confidenceIntervalValues
);
}
function _protocolFunctionRequiringPredictionValue(
uint256 protocolFunctionArgument,
uint256 value,
uint256[] memory confidenceIntervalPercentiles,
uint256[] memory confidenceIntervalValues
) internal {
// use arguments and value
}
// ***************************************************************
// * ========================= ADMIN =========================== *
// ***************************************************************
/**
* @notice Set the AlloraConsumer contract address
*
* @param alloraConsumer_ The AlloraConsumer contract address
*/
function setAlloraConsumerContract(IAlloraConsumer alloraConsumer_) external onlyOwner {
alloraConsumer = alloraConsumer_;
}
}Understanding the Contract
Key Components
Contract Setup:
- Consumer Address: Points to Sepolia testnet consumer at
0x4341a3F0a350C2428184a727BAb86e16D4ba7018 - Inheritance: Uses
Ownable2Stepfor secure ownership management - Imports: Required interfaces for Allora consumer interaction
Two Usage Patterns:
-
Using Existing Stored Values (
callProtocolFunctionWithExistingValue):- Reads inference data already stored in the consumer contract
- Checks that data is not stale (less than 1 hour old)
- More gas efficient for repeated reads
-
Real-time Verification (
callProtocolFunctionWithAlloraTopicInference):- Verifies fresh inference data with cryptographic signatures
- Uses the latest available inference data
- More secure but higher gas cost
Function Breakdown
callProtocolFunctionWithExistingValue:
- Gets stored topic value from consumer contract
- Validates data freshness (1 hour limit)
- Passes verified data to your protocol logic
callProtocolFunctionWithAlloraTopicInference:
- Verifies signed inference data on-chain
- Extracts inference value and confidence intervals
- Passes verified data to your protocol logic
setAlloraConsumerContract:
- Admin function to update consumer contract address
- Uses
onlyOwnermodifier for security
Implementation Steps
- Deploy the Contract: Deploy with the correct consumer address for your network
- Configure Consumer: Set the consumer contract address if needed
- Choose Integration Pattern: Use stored values for efficiency or real-time verification for maximum freshness
- Implement Protocol Logic: Add your specific business logic in
_protocolFunctionRequiringPredictionValue