🐸
maxAPY for Devs
  • maxAPY ERC7540
    • MetaVault
      • Introduction
      • Architecture
      • Core Operations
      • State Management & Operations
      • Asset Management
      • Settlement Mechanics
      • Withdrawal Queue Mechanics
      • Deployed Addresses
  • Periphery
    • Hurdle Rate Oracle
    • SharePriceOracle
    • Deployed Addresses
  • maxAPY ERC4626
    • Introduction
    • Architecture
    • Vault
      • MaxApyFactory
      • MaxApyRouter
      • MaxApyVault
    • Periphery
      • MaxApyHarvester
    • Base Strategies
      • BaseStrategy
      • BaseSommelierStrategy
      • BaseYearnV3Strategy
      • BaseYearnV2Strategy
      • BaseConvexStrategy
      • BaseConvexStrategyPolygon
      • BaseBeefyStrategy
      • BaseHopStrategy
      • BaseBeefyCurveStrategy
    • Strategies
      • Ethereum - WETH
        • Convex
          • ConvexdETHFrxETHStrategy
        • Sommelier
          • SommelierMorphoEthMaximizerStrategy
          • SommelierStEthDepositTurboStEthStrategy
          • SommelierTurboDivEthStrategy
          • SommelierTurboEEthV2Strategy
          • SommelierTurboEthXStrategy
          • SommelierTurboEzEthStrategy
          • SommelierTurboRsEthStrategy
          • SommelierTurboStEthStrategy
          • SommelierTurboSwEthStrategy
        • Yearn
          • YearnAaveV3WETHLenderStrategy
          • YearnAjnaWETHStakingStrategy
          • YearnCompoundV3WETHLenderStrategy
          • YearnV3WETH2Strategy
          • YearnV3WETHStrategy
          • YearnWETHStrategy
      • Ethereum - USDC
        • Convex
          • ConvexCrvUSDWethCollateralStrategy
        • Sommelier
          • SommelierTurboGHOStrategy
        • Yearn
          • YearnAjnaDAIStakingStrategy
          • YearnDAIStrategy
          • YearnLUSDStrategy
          • YearnUSDCStrategy
          • YearnUSDTStrategy
      • Polygon - WETH
        • Hop
          • HopETHStrategy
      • Polygon - USDC.e
        • Convex
          • ConvexUSDCCrvUSDStrategy
          • ConvexUSDTCrvUSDStrategy
        • Beefy
          • BeefyCrvUSDUSDCeStrategy
          • BeefyMaiUSDCeStrategy
          • BeefyUSDCeDAIStrategy
        • Yearn
          • YearnAaveV3USDTLenderStrategy
          • YearnAjnaUSDCStrategy
          • YearnCompoundUSDCeLenderStrategy
          • YearnDAILenderStrategy
          • YearnDAIStrategy
          • YearnMaticUSDCStakingStrategy
          • YearnUSDCeLenderStrategy
          • YearnUSDCeStrategy
          • YearnUSDTStrategy
    • Subgraph
      • Overview
      • Schema
      • Query Guide
Powered by GitBook
On this page
  • Cross-Chain ERC4626 Vault Share Price Oracle
  • Overview
  • Key Features
  • System Architecture
  • Core Contracts
  • Oracle Adapters
  • Key Data Structures
  • Security Considerations
  • Common Workflows
  • Error Handling
  • Glossary
  1. Periphery

SharePriceOracle

Cross-Chain ERC4626 Vault Share Price Oracle

Overview

SharePriceOracle is a multi-adapter oracle system designed for cross-chain ERC4626 vault share price propagation. The system enables protocols to access and share vault share prices across different blockchains using LayerZero as a messaging layer. It provides a unified interface for fetching accurate price data from various sources and serves as a critical infrastructure for cross-chain vault strategies, yield aggregators, and DeFi protocols.

Key Features

  • Multi-adapter architecture: Supports multiple price feed providers (Chainlink, Pyth, API3, Redstone, AMMs)

  • Cross-chain compatibility: Propagates vault share prices across different blockchains via LayerZero

  • Price normalization: Converts prices to standardized 18-decimal precision (WAD)

  • Fallback mechanisms: Implements priority-based fallback for price sources

  • Price validation: Enforces bounds checking and staleness prevention

  • L2 sequencer awareness: Handles L2 sequencer downtime gracefully

System Architecture

The SharePriceOracle system consists of three main components:

  1. SharePriceOracle: The core contract that serves as the router and price aggregator

  2. Oracle Adapters: Specialized contracts for interfacing with different price feed providers

  3. MaxLzEndpoint: LayerZero endpoint for cross-chain communication

Data Flow

┌───────────────────┐          ┌───────────────────┐
│  SharePriceOracle │          │  SharePriceOracle │
│    (Chain A)      │◄─────────┤    (Chain B)      │
└─────────┬─────────┘          └─────────┬─────────┘
          │                              │
          ▼                              ▼
┌─────────────────────┐      ┌─────────────────────┐
│ Oracle Adapters     │      │ Oracle Adapters     │
│ (Chainlink, Pyth,   │      │ (Chainlink, Pyth,   │
│  UniswapV3, etc.)   │      │  UniswapV3, etc.)   │
└─────────────────────┘      └─────────────────────┘

Core Contracts

SharePriceOracle

The SharePriceOracle is the central contract that:

  1. Manages a registry of price adapters

  2. Handles cross-chain asset mappings

  3. Stores and updates share prices

  4. Provides normalized price conversion

  5. Enforces access control for different operations

contract SharePriceOracle is ISharePriceOracle, OwnableRoles {
    // Roles
    uint256 public constant ADMIN_ROLE = _ROLE_0;
    uint256 public constant ENDPOINT_ROLE = _ROLE_1;
    uint256 public constant ADAPTER_ROLE = _ROLE_2;
    
    // Mappings
    mapping(address => mapping(uint8 => LocalAssetConfig)) public localAssetConfigs;
    mapping(address => StoredSharePrice) public storedSharePrices;
    mapping(bytes32 => address) public crossChainAssetMap;
    mapping(bytes32 => VaultReport) public sharePrices;
}

Key functions:

  • getSharePrices: Fetches current share prices for multiple vaults

  • updateSharePrices: Updates share prices received from other chains

  • getLatestSharePrice: Gets the latest share price for a specific vault

  • getPrice: Gets the price of an asset from available adapters

  • setLocalAssetConfig: Configures a price feed for a local asset

  • setCrossChainAssetMapping: Maps cross-chain assets to local equivalents

MaxLzEndpoint

The MaxLzEndpoint contract handles cross-chain messaging via LayerZero:

  1. Sends vault share prices to other chains

  2. Receives and processes share price updates

  3. Manages messaging options and peers

  4. Implements request-response patterns for price updates

contract MaxLzEndpoint is ILayerZeroReceiver, Ownable {
    // Message pattern identifiers
    uint8 private constant AB_TYPE = 1;  // Simple send-receive
    uint8 private constant ABA_TYPE = 2; // Request-response pattern
    
    // Mappings
    mapping(uint32 eid => bytes32 peer) public peers;
}

Key functions:

  • sendSharePrices: Sends share prices to a destination chain

  • requestSharePrices: Requests share prices from a destination chain

  • lzReceive: Processes incoming messages from LayerZero

Oracle Adapters

The system supports multiple oracle adapters, each specialized for a different price feed provider:

1. Chainlink Adapter

Fetches price data from Chainlink price feeds with heartbeat validation and price bounds checking.

contract ChainlinkAdapter is BaseOracleAdapter {
    function getPrice(address asset, bool inUSD) 
        external view override returns (ISharePriceOracle.PriceReturnData memory);
}

2. Pyth Adapter

Integrates with Pyth Network for high-frequency, decentralized price updates.

contract PythAdapter is BaseOracleAdapter {
    function getPrice(address asset, bool inUSD) 
        external view override returns (ISharePriceOracle.PriceReturnData memory);
    
    function updateAndGetPrice(address asset, bool inUSD, bytes[] calldata updateData) 
        external payable returns (ISharePriceOracle.PriceReturnData memory);
}

3. API3 Adapter

Uses API3's dAPI (data feed) system for price data.

contract Api3Adapter is BaseOracleAdapter {
    function getPrice(address asset, bool inUSD) 
        external view override returns (ISharePriceOracle.PriceReturnData memory);
}

4. Redstone Adapter

Integrates with Redstone's oracle network for price data.

contract RedStoneAdapter is BaseOracleAdapter {
    function getPrice(address asset, bool inUSD) 
        external view override returns (ISharePriceOracle.PriceReturnData memory);
}

5. AMM-based Adapters

Several adapters for extracting prices from AMM pools:

  • UniswapV3Adapter: Uses TWAP (Time-Weighted Average Price) from Uniswap V3 pools

  • BalancerAdapter: Extracts prices from Balancer weighted pools

  • AerodromeV1Adapter/AerodromeV2Adapter: Works with Aerodrome pools (Base-specific)

  • Curve2PoolAssetAdapter: Extracts prices from Curve pools with reentrancy protection

Key Data Structures

VaultReport

Contains vault share price information and metadata for cross-chain communication:

struct VaultReport {
    uint256 sharePrice;
    uint64 lastUpdate;
    uint32 chainId;
    address rewardsDelegate;
    address vaultAddress;
    address asset;
    uint256 assetDecimals;
}

PriceReturnData

Standardized structure for price data returned by adapters:

struct PriceReturnData {
    uint240 price;     // Price normalized to WAD (1e18)
    bool hadError;     // Error flag
    bool inUSD;        // Price denomination
}

LocalAssetConfig

Configuration for local assets (e.g., USDC, WETH):

struct LocalAssetConfig {
    address priceFeed; // Priority-ordered price feeds
    bool inUSD;        // Whether price should be in USD
    address adaptor;   // Adapter address
}

Security Considerations

The SharePriceOracle implements several security mechanisms:

  1. Access control: Role-based permissions for administrative and update operations

  2. Price validation: Minimum and maximum bounds for prices to prevent manipulation

  3. Staleness prevention: Timestamp-based checks to ensure price freshness

  4. Sequencer awareness: Checks for L2 sequencer status before using prices

  5. Multiple price sources: Fallback mechanism to increase resilience

Common Workflows

Adding a New Vault to Monitor

To start monitoring a new vault's share price:

  1. Ensure the vault's underlying asset has a price feed configured

  2. Call getSharePrices() with the vault address to get its current share price

  3. Use sendSharePrices() on the MaxLzEndpoint to propagate the price to other chains

Configuring a New Price Feed

To add a new price feed for an asset:

  1. Deploy and configure the appropriate adapter contract

  2. Grant the adapter the ADAPTER_ROLE

  3. Call setLocalAssetConfig() to register the asset with the adapter

Cross-Chain Asset Mapping

To enable price conversion for cross-chain assets:

  1. Identify the local equivalent of the cross-chain asset

  2. Call setCrossChainAssetMapping() with the source chain ID, source asset, and local asset

Error Handling

The system uses custom errors to provide clear failure reasons:

  • InvalidAsset: Asset not supported or not properly configured

  • NoValidPrice: Unable to get a valid price

  • StalePrice: Price is too old to be considered valid

  • SequencerUnavailable: L2 sequencer is down or in grace period

  • MessageAlreadyProcessed: Prevents duplicate processing of cross-chain messages

Glossary

  • WAD: Standard unit representing 1 with 18 decimal places (10^18)

  • EID: Endpoint ID in LayerZero, representing a specific blockchain

  • TWAP: Time-Weighted Average Price, used by DEX-based oracles

  • ERC4626: Token standard for tokenized vaults

  • Share Price: The price of one vault share expressed in terms of the underlying asset

PreviousHurdle Rate OracleNextDeployed Addresses

Last updated 2 months ago