> For the complete documentation index, see [llms.txt](https://devs.maxapy.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://devs.maxapy.io/periphery/sharepriceoracle.md).

# 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

```solidity
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

```solidity
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.

```solidity
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.

```solidity
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.

```solidity
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.

```solidity
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:

```solidity
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:

```solidity
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):

```solidity
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
