|
|
@@ -7,7 +7,6 @@ import "@pythnetwork/pyth-sdk-solidity/AbstractPyth.sol";
|
|
|
import "@pythnetwork/pyth-sdk-solidity/PythStructs.sol";
|
|
|
|
|
|
import "@pythnetwork/pyth-sdk-solidity/PythErrors.sol";
|
|
|
-import "@pythnetwork/pyth-sdk-solidity/PythUtils.sol";
|
|
|
import "./PythAccumulator.sol";
|
|
|
import "./PythGetters.sol";
|
|
|
import "./PythSetters.sol";
|
|
|
@@ -628,16 +627,53 @@ abstract contract Pyth is
|
|
|
return "1.4.4-alpha.5";
|
|
|
}
|
|
|
|
|
|
+ /// @notice Calculates TWAP from two price points
|
|
|
+ /// @dev The calculation is done by taking the difference of cumulative values and dividing by the time difference
|
|
|
+ /// @param priceId The price feed ID
|
|
|
+ /// @param twapPriceInfoStart The starting price point
|
|
|
+ /// @param twapPriceInfoEnd The ending price point
|
|
|
+ /// @return twapPriceFeed The calculated TWAP price feed
|
|
|
function calculateTwap(
|
|
|
bytes32 priceId,
|
|
|
PythStructs.TwapPriceInfo memory twapPriceInfoStart,
|
|
|
PythStructs.TwapPriceInfo memory twapPriceInfoEnd
|
|
|
- ) private pure returns (PythStructs.TwapPriceFeed memory) {
|
|
|
- return
|
|
|
- PythUtils.calculateTwap(
|
|
|
- priceId,
|
|
|
- twapPriceInfoStart,
|
|
|
- twapPriceInfoEnd
|
|
|
- );
|
|
|
+ ) private pure returns (PythStructs.TwapPriceFeed memory twapPriceFeed) {
|
|
|
+ twapPriceFeed.id = priceId;
|
|
|
+ twapPriceFeed.startTime = twapPriceInfoStart.publishTime;
|
|
|
+ twapPriceFeed.endTime = twapPriceInfoEnd.publishTime;
|
|
|
+
|
|
|
+ // Calculate differences between start and end points for slots and cumulative values
|
|
|
+ uint64 slotDiff = twapPriceInfoEnd.publishSlot -
|
|
|
+ twapPriceInfoStart.publishSlot;
|
|
|
+ int128 priceDiff = twapPriceInfoEnd.cumulativePrice -
|
|
|
+ twapPriceInfoStart.cumulativePrice;
|
|
|
+ uint128 confDiff = twapPriceInfoEnd.cumulativeConf -
|
|
|
+ twapPriceInfoStart.cumulativeConf;
|
|
|
+
|
|
|
+ // Calculate time-weighted average price (TWAP) and confidence by dividing
|
|
|
+ // the difference in cumulative values by the number of slots between data points
|
|
|
+ int128 twapPrice = priceDiff / int128(uint128(slotDiff));
|
|
|
+ uint128 twapConf = confDiff / uint128(slotDiff);
|
|
|
+
|
|
|
+ // The conversion from int128 to int64 is safe because:
|
|
|
+ // 1. Individual prices fit within int64 by protocol design
|
|
|
+ // 2. TWAP is essentially an average price over time (cumulativePrice₂-cumulativePrice₁)/slotDiff
|
|
|
+ // 3. This average must be within the range of individual prices that went into the calculation
|
|
|
+ // We use int128 only as an intermediate type to safely handle cumulative sums
|
|
|
+ twapPriceFeed.twap.price = int64(twapPrice);
|
|
|
+ twapPriceFeed.twap.conf = uint64(twapConf);
|
|
|
+ twapPriceFeed.twap.expo = twapPriceInfoStart.expo;
|
|
|
+ twapPriceFeed.twap.publishTime = twapPriceInfoEnd.publishTime;
|
|
|
+
|
|
|
+ // Calculate downSlotsRatio as a value between 0 and 1,000,000
|
|
|
+ // 0 means no slots were missed, 1,000,000 means all slots were missed
|
|
|
+ uint64 totalDownSlots = twapPriceInfoEnd.numDownSlots -
|
|
|
+ twapPriceInfoStart.numDownSlots;
|
|
|
+ uint64 downSlotsRatio = (totalDownSlots * 1_000_000) / slotDiff;
|
|
|
+
|
|
|
+ // Safely downcast to uint32 (sufficient for value range 0-1,000,000)
|
|
|
+ twapPriceFeed.downSlotsRatio = uint32(downSlotsRatio);
|
|
|
+
|
|
|
+ return twapPriceFeed;
|
|
|
}
|
|
|
}
|