Integating Canary Nest Oracle (PUSH Based)
PriceOracle Technical Specification
Overview
The PriceOracle contract is a Chainlink-compatible price oracle implementation that provides secure price data management with built-in deviation controls and curator oversight. It implements the AggregatorV3Interface standard while adding additional security mechanisms for price validation and approval workflows.
Contract Information
License: MIT
Solidity Version: 0.8.25
Contract Type: Upgradeable proxy pattern
Version: 1
Architecture
Inheritance Structure
PriceOracle
βββ AggregatorV3Interface (Chainlink standard)
βββ Initializable (OpenZeppelin upgradeable)
βββ AccessControlEnumerableUpgradeable (OpenZeppelin role-based access)Access Control Roles
Default Admin
DEFAULT_ADMIN_ROLE
Manages other roles, overall contract administration
Curator
CURATOR_ROLE
Approves/rejects pending prices, configures parameters
Updater
UPDATER_ROLE
Submits new price data
Data Structures
RoundData
Stores confirmed price round information:
PendingRoundData
Stores price data awaiting curator approval:
State Variables
VERSION
uint8
Contract version (constant: 1)
pendingRoundData
PendingRoundData
Current pending price data
s_description
string
Oracle description
s_decimals
uint8
Price decimal places
rounds
mapping(uint80 => RoundData)
Historical round data
latestRoundId
uint80
Most recent round identifier
maxPriceDeviation
uint256
Maximum allowed price change
timestampBuffer
uint256
Timestamp validation buffer (ms)
Core Functions
Initialisation
initialize(address defaultAdmin, address curator, address updater, uint256 _maxPriceDeviation, uint256 _timestampBuffer, uint8 _decimals, string memory _description)
Initialises the upgradeable contract with initial parameters and role assignments.
Parameters:
defaultAdmin: Address receiving admin privilegescurator: Address receiving curator privilegesupdater: Address receiving updater privileges_maxPriceDeviation: Maximum allowed price deviation between rounds_timestampBuffer: Timestamp validation buffer in milliseconds_decimals: Number of decimal places for prices_description: Human-readable oracle description
Requirements:
All addresses must be non-zero
Description must be non-empty
Decimals must be greater than zero
Price Management
addRoundData(uint256 recordedOffchainAt, int192 price, bytes32 sourceHash)
Submits new price data for validation and storage.
Access Control: UPDATER_ROLE
Parameters:
recordedOffchainAt: Offchain recording timestamp (milliseconds)price: Price value (must be non-zero)sourceHash: Source identification hash (must be non-zero)
Validation Rules:
Price must be non-zero
Source hash must be non-zero
No pending price data can exist
Timestamp must not be too far in the future (respects
timestampBuffer)Timestamp must be newer than the latest round
Price deviation from last round determines approval workflow
Behavior:
If price deviation β€
maxPriceDeviation: Automatically approved and storedIf price deviation >
maxPriceDeviation: Stored as pending, requires curator approval
resolvePendingPrice(bool isApproved)
Curator function to approve or reject pending price data.
Access Control: CURATOR_ROLE
Parameters:
isApproved:trueto approve and store the pending price,falseto reject
Requirements:
Pending price data must exist
Behavior:
If approved: Moves pending data to confirmed rounds
Always clears pending data regardless of approval decision
Configuration Management
setMaxPriceDeviation(uint256 _maxPriceDeviation)
Updates the maximum allowed price deviation threshold.
Access Control: CURATOR_ROLE
Parameters:
_maxPriceDeviation: New deviation threshold (must be non-zero and different from current)
setTimestampBuffer(uint256 _timestampBuffer)
Updates the timestamp validation buffer.
Access Control: CURATOR_ROLE
Parameters:
_timestampBuffer: New buffer duration in milliseconds (can be zero)
Chainlink Interface Implementation
decimals() β uint8
Returns the number of decimal places in price values.
description() β string
Returns the human-readable oracle description.
version() β uint256
Returns the contract version number.
getRoundData(uint80 _roundId) β (uint80, int256, uint256, uint256, uint80)
Retrieves historical round data by round ID.
Returns:
roundId: The requested round IDanswer: Price value (converted to int256)startedAt: Offchain recording timestampupdatedAt: Onchain recording timestampansweredInRound: Same as roundId
Requirements:
Round ID must be valid (1 β€ roundId β€ latestRoundId)
latestRoundData() β (uint80, int256, uint256, uint256, uint80)
Retrieves the most recent round data.
Returns: Same format as getRoundData
Requirements:
At least one round must exist
Events
RoundDataAdded(uint80 indexed roundId, uint256 recordedOffchainAt, uint256 recordedOnchainAt, int192 price, bytes32 indexed sourceHash)
RoundDataAdded(uint80 indexed roundId, uint256 recordedOffchainAt, uint256 recordedOnchainAt, int192 price, bytes32 indexed sourceHash)Emitted when price data is confirmed and stored.
PendingRoundDataAdded(uint256 recordedOffchainAt, uint256 recordedOnchainAt, int192 pendingPrice, bytes32 indexed sourceHash)
PendingRoundDataAdded(uint256 recordedOffchainAt, uint256 recordedOnchainAt, int192 pendingPrice, bytes32 indexed sourceHash)Emitted when price data requires curator approval.
SetMaxPriceDeviation(uint256 oldMaxPriceDeviation, uint256 newMaxPriceDeviation)
SetMaxPriceDeviation(uint256 oldMaxPriceDeviation, uint256 newMaxPriceDeviation)Emitted when price deviation threshold is updated.
SetTimestampBuffer(uint256 oldTimestampBuffer, uint256 newTimestampBuffer)
SetTimestampBuffer(uint256 oldTimestampBuffer, uint256 newTimestampBuffer)Emitted when timestamp buffer is updated.
Error Conditions
ZeroAddress()
Zero address provided in initialization
CantGeneratePrice()
No rounds available for latest data query
InvalidRoundId(uint80)
Round ID is zero or exceeds latest round
TimestampInvalid()
Timestamp validation failures
InvalidMaxPriceDeviation()
Invalid price deviation parameter
InvalidDescription()
Empty description in initialization
PriceZero()
Zero price value submitted
PriceNotPending()
No pending price to resolve
PriceAlreadyPending()
Attempting to add price when one is pending
InvalidDecimals()
Zero decimals in initialization
InvalidTimestampBuffer()
Invalid timestamp buffer parameter
InvalidSourceHash()
Zero source hash provided
Security Considerations
Price Validation
Deviation Control: Prices exceeding
maxPriceDeviationrequire curator approvalTimestamp Validation: Prevents future timestamps and ensures chronological ordering
Source Tracking: Each price includes a source hash for accountability
Access Control
Role Separation: Clear separation between data submission and approval
Upgradeable Pattern: Uses OpenZeppelin's secure upgrade pattern
Administrative Controls: Curators can adjust system parameters
Economic Security
Anti-Manipulation: Large price movements require human oversight
Historical Integrity: Immutable round data once confirmed
Operational Continuity: System continues operating during pending price periods
Integration Guidelines
For Consumers
Interface Requirements
Consumers must import and use the Chainlink AggregatorV3Interface to interact with the PriceOracle:
Reading Historical Price Data
Use getRoundData(uint80 _roundId) to retrieve specific historical rounds:
Essential Integration Patterns
Always validate price data before using it in calculations
Handle potential reversion when no data is available using try-catch blocks
Validate data freshness using the
updatedAttimestamp (in milliseconds)Account for decimal precision using
priceFeed.decimals()
For Operators
Updaters: Submit regular price updates with accurate timestamps and source hashes
Curators: Monitor pending prices and validate large deviations promptly
Administrators: Configure deviation thresholds and timestamp buffers appropriately
Deployment Considerations
Proxy Pattern: Deploy using upgradeable proxy for future improvements
Role Assignment: Carefully assign roles to appropriate addresses
Parameter Tuning: Set
maxPriceDeviationandtimestampBufferbased on asset volatilityMonitoring: Implement off-chain monitoring for pending prices and system health
Last updated