@@ -12,7 +12,23 @@ import "@pythnetwork/pyth-sdk-solidity/IPyth.sol";
1212
1313/// @title MorphoPythOracle 
1414/// @author Pyth Data Association 
15- /// @notice Morpho Blue oracle using Pyth Price Feeds. 
15+ /// @notice Morpho oracle implementation that combines Pyth price feeds with ERC-4626 vault pricing 
16+ /// @dev This oracle calculates prices by combining multiple data sources: 
17+ ///      - Up to 2 Pyth price feeds each for base and quote assets 
18+ ///      - Optional ERC-4626 vault share-to-asset conversion for base and quote 
19+ ///      - Configurable staleness checks for price feed age validation 
20+ /// 
21+ /// Price Calculation Formula: 
22+ /// price = SCALE_FACTOR * (baseVaultAssets * baseFeed1 * baseFeed2) / (quoteVaultAssets * quoteFeed1 * quoteFeed2) 
23+ /// 
24+ /// Security Considerations: 
25+ /// - Single priceFeedMaxAge used for all feeds may not suit different asset volatilities 
26+ /// - ERC-4626 vaults can be manipulated through donations, flash loans, or fee changes 
27+ /// - Pyth confidence intervals are not validated, potentially accepting uncertain prices 
28+ /// - Conversion samples must be large enough to avoid rounding to zero 
29+ /// 
30+ /// @dev This contract follows Morpho's design philosophy prioritizing flexibility over safety. 
31+ ///      Users must validate all configuration parameters and monitor oracle behavior. 
1632contract  MorphoPythOracle  is  IMorphoPythOracle  {
1733    using Math   for  uint256 ;
1834
@@ -50,8 +66,40 @@ contract MorphoPythOracle is IMorphoPythOracle {
5066    uint256  public  immutable  SCALE_FACTOR;
5167
5268    /// @inheritdoc IMorphoPythOracle 
69+     /// @dev WARNING: Single staleness threshold applied to all feeds regardless of asset characteristics. 
70+     ///      Fast-moving assets may need shorter max age (e.g., 15s) while stable assets could tolerate longer (e.g., 
71+     /// 60s). 
72+     ///      Using a universal value may reject valid stable prices or accept stale volatile prices. 
73+     ///      Consider asset-specific staleness checks for improved accuracy and reliability. 
5374    uint256  public  PRICE_FEED_MAX_AGE;
5475
76+     /// @notice Initializes a new MorphoPythOracle instance 
77+     /// @dev Constructor performs parameter validation but cannot prevent all misconfigurations. 
78+     ///      Users must ensure parameters are appropriate for their use case. 
79+     /// 
80+     /// @param pyth_ Address of the Pyth contract - must be the official Pyth contract for the chain 
81+     /// @param baseVault ERC-4626 vault for base asset, or address(0) to skip vault conversion 
82+     /// @param baseVaultConversionSample Sample shares amount for base vault conversion (must provide adequate 
83+     /// precision) 
84+     /// @param baseFeed1 First Pyth price feed ID for base asset, or bytes32(0) for price=1 
85+     /// @param baseFeed2 Second Pyth price feed ID for base asset, or bytes32(0) for price=1 
86+     /// @param baseTokenDecimals Decimal places for base token 
87+     /// @param quoteVault ERC-4626 vault for quote asset, or address(0) to skip vault conversion 
88+     /// @param quoteVaultConversionSample Sample shares amount for quote vault conversion (must provide adequate 
89+     /// precision) 
90+     /// @param quoteFeed1 First Pyth price feed ID for quote asset, or bytes32(0) for price=1 
91+     /// @param quoteFeed2 Second Pyth price feed ID for quote asset, or bytes32(0) for price=1 
92+     /// @param quoteTokenDecimals Decimal places for quote token 
93+     /// @param priceFeedMaxAge Maximum acceptable age in seconds for price feeds (applies to all feeds) 
94+     /// 
95+     /// @dev CRITICAL: Conversion samples must be large enough that convertToAssets() returns non-zero values. 
96+     ///      Small samples may round to zero, breaking price calculations. Test with actual vault implementations! 
97+     /// 
98+     /// @dev VAULT SECURITY: If using vaults, ensure they are trusted implementations resistant to: 
99+     ///      - Share price manipulation via direct token transfers 
100+     ///      - Flash loan attacks that temporarily affect asset/share ratios 
101+     ///      - Dynamic fee changes that alter convertToAssets() results 
102+     ///      - First depositor attacks setting malicious initial exchange rates 
55103    constructor (
56104        address  pyth_ ,
57105        IERC4626  baseVault ,
@@ -105,6 +153,21 @@ contract MorphoPythOracle is IMorphoPythOracle {
105153    /* PRICE */ 
106154
107155    /// @inheritdoc IOracle 
156+     /// @notice Calculates the current price by combining vault asset values and Pyth feed prices 
157+     /// @return The calculated price with 18 decimal precision 
158+     /// @dev Price calculation: SCALE_FACTOR * (baseAssets * baseFeeds) / (quoteAssets * quoteFeeds) 
159+     /// 
160+     /// SECURITY WARNINGS: 
161+     /// - Vault prices can be manipulated if vaults are not manipulation-resistant 
162+     /// - Single PRICE_FEED_MAX_AGE applied to all feeds regardless of asset volatility 
163+     /// - Pyth confidence intervals are ignored - uncertain prices may be accepted 
164+     /// - No per-block deviation caps - prices can change drastically within one block 
165+     /// 
166+     /// @dev This function will revert if: 
167+     ///      - Any Pyth feed returns a negative price 
168+     ///      - Any feed is older than PRICE_FEED_MAX_AGE 
169+     ///      - Vault convertToAssets calls fail 
170+     ///      - Arithmetic overflow in multiplication/division 
108171    function price  () external  view  returns  (uint256 ) {
109172        return  SCALE_FACTOR.mulDiv (
110173            BASE_VAULT.getAssets (BASE_VAULT_CONVERSION_SAMPLE)
0 commit comments