Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

BasketOracle

Git Source

Inherits: AggregatorV3Interface, Ownable2Step

Title: BasketOracle

Aggregates multiple Chainlink feeds into a normalized weighted plDXY basket price.

Price = Sum(Weight_i * Price_i / BasePrice_i). Normalization preserves intended currency weights.

Note: security-contact: contact@plether.com

Constants

DECIMALS

Chainlink standard decimals for fiat/USD pairs.

uint8 public constant DECIMALS = 8

DESCRIPTION

Oracle description string.

string public constant DESCRIPTION = "plDXY Fixed Basket (Bounded)"

TIMELOCK_DELAY

Timelock delay for Curve pool updates (7 days).

uint256 public constant TIMELOCK_DELAY = 7 days

MAX_DEVIATION_BPS

Maximum allowed deviation from Curve spot (basis points).

uint256 public immutable MAX_DEVIATION_BPS

CAP

Protocol CAP price (8 decimals). Theoretical price is clamped to this before deviation check.

uint256 public immutable CAP

State Variables

components

Array of currency components (EUR, JPY, GBP, CAD, SEK, CHF).

Component[] public components

curvePool

Curve pool for deviation validation.

ICurvePool public curvePool

pendingCurvePool

Pending Curve pool for timelock-protected updates.

address public pendingCurvePool

hasPendingProposal

Whether a proposal is active (needed because address(0) is a valid proposal).

bool public hasPendingProposal

curvePoolActivationTime

Timestamp when pending Curve pool can be finalized.

uint256 public curvePoolActivationTime

Functions

constructor

Creates basket oracle with currency components.

constructor(
    address[] memory _feeds,
    uint256[] memory _quantities,
    uint256[] memory _basePrices,
    uint256 _maxDeviationBps,
    uint256 _cap,
    address _owner
) Ownable(_owner);

Parameters

NameTypeDescription
_feedsaddress[]Array of Chainlink feed addresses.
_quantitiesuint256[]Array of basket weights (1e18 precision).
_basePricesuint256[]Array of base prices for normalization (8 decimals).
_maxDeviationBpsuint256Maximum deviation from Curve (e.g., 200 = 2%).
_capuint256Protocol CAP price (8 decimals). Clamps theoretical price in deviation check.
_owneraddressAdmin address for Curve pool management.

setCurvePool

Sets the Curve pool for deviation validation (initial setup only).

function setCurvePool(
    address _curvePool
) external onlyOwner;

Parameters

NameTypeDescription
_curvePooladdressCurve USDC/plDXY-BEAR pool address.

proposeCurvePool

Proposes a new Curve pool (requires 7-day timelock).

function proposeCurvePool(
    address _newPool
) external onlyOwner;

Parameters

NameTypeDescription
_newPooladdressNew Curve pool address.

finalizeCurvePool

Finalizes the Curve pool update after timelock expires.

function finalizeCurvePool() external onlyOwner;

latestRoundData

Returns the aggregated basket price from all component feeds.

function latestRoundData() public view returns (uint80, int256, uint256, uint256, uint80);

Returns

NameTypeDescription
<none>uint80roundId Mock round ID (always 1).
<none>int256answer The calculated basket price in 8 decimals.
<none>uint256startedAt Oldest component updatedAt (no separate round start; same as updatedAt).
<none>uint256updatedAt Oldest component updatedAt (weakest link for staleness checks).
<none>uint80answeredInRound Mock answered round (always 1).

_checkDeviation

Validates basket price against Curve spot. Reverts on excessive deviation. Intentionally acts as a global circuit breaker: if Chainlink and Curve EMA diverge beyond MAX_DEVIATION_BPS, all consumers (SyntheticSplitter, MorphoOracle, StakedOracle) are frozen — including Morpho liquidations. This is the desired behavior: large divergence signals either a compromised feed or a manipulated pool, and freezing is safer than acting on potentially bad price data.

function _checkDeviation(
    uint256 theoreticalDxy8Dec
) internal view;

Parameters

NameTypeDescription
theoreticalDxy8Decuint256Computed basket price (8 decimals).

decimals

Returns oracle decimals (8).

function decimals() external pure returns (uint8);

description

Returns oracle description.

function description() external pure returns (string memory);

version

Returns oracle version (1).

function version() external pure returns (uint256);

getRoundData

Returns data for a specific round ID.

Only round ID 1 is supported (synthetic basket has no historical rounds).

function getRoundData(
    uint80 _roundId
) external view returns (uint80, int256, uint256, uint256, uint80);

Events

CurvePoolProposed

Emitted when a new Curve pool is proposed.

event CurvePoolProposed(address indexed newPool, uint256 activationTime);

CurvePoolUpdated

Emitted when Curve pool is updated.

event CurvePoolUpdated(address indexed oldPool, address indexed newPool);

Errors

BasketOracle__InvalidPrice

Thrown when a component feed returns invalid price.

error BasketOracle__InvalidPrice(address feed);

BasketOracle__LengthMismatch

Thrown when feeds and quantities arrays have different lengths.

error BasketOracle__LengthMismatch();

BasketOracle__PriceDeviation

Thrown when basket price deviates too far from Curve spot.

error BasketOracle__PriceDeviation(uint256 theoretical, uint256 spot);

BasketOracle__AlreadySet

Thrown when Curve pool is already configured.

error BasketOracle__AlreadySet();

BasketOracle__TimelockActive

Thrown when timelock period has not elapsed.

error BasketOracle__TimelockActive();

BasketOracle__InvalidProposal

Thrown when no pending proposal exists.

error BasketOracle__InvalidProposal();

BasketOracle__InvalidDeviation

Thrown when max deviation is zero.

error BasketOracle__InvalidDeviation();

BasketOracle__InvalidBasePrice

Thrown when a base price is zero.

error BasketOracle__InvalidBasePrice();

BasketOracle__InvalidWeights

Thrown when quantities don’t sum to 1e18.

error BasketOracle__InvalidWeights();

BasketOracle__InvalidRoundId

error BasketOracle__InvalidRoundId();

Structs

Component

Component feed with its basket weight and base price for normalization.

struct Component {
    AggregatorV3Interface feed;
    uint256 quantity;
    uint256 basePrice;
}