Aditya Arora 9 months ago
parent
commit
8c5eff5e81

+ 3 - 1
target_chains/cosmwasm/examples/cw-contract/Cargo.lock

@@ -485,7 +485,9 @@ dependencies = [
 
 [[package]]
 name = "pyth-sdk-cw"
-version = "0.1.0"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c04e9f2961bce1ef13b09afcdb5aee7d4ddde83669e5f9d2824ba422cb00de48"
 dependencies = [
  "cosmwasm-schema",
  "cosmwasm-std",

+ 82 - 0
target_chains/ethereum/contracts/contracts/pyth/Pyth.sol

@@ -304,6 +304,88 @@ abstract contract Pyth is
             );
     }
 
+    function parseTwapPriceFeedUpdates(
+        bytes[2][] calldata updateData,
+        bytes32[] calldata priceIds,
+        unit8 windowSize
+    )
+        external
+        payable
+        override
+        returns (PythStructs.TwapPriceFeed[] memory twapPriceFeeds)
+    {
+        {
+            revert(updateData.length != 2, PythErrors.InvalidUpdateData());
+            uint requiredFee = getUpdateFee(updateData[0]);
+
+            // Check if the two updateData contains the same number of priceUpdates
+            if (requiredFee != getUpdateFee(updateData[1])) {
+                revert PythErrors.InvalidUpdateData();
+            }
+            if (msg.value < requiredFee) revert PythErrors.InsufficientFee();
+        }
+
+        // Parse the updateData
+        twapPriceFeeds = new PythStructs.TwapPriceFeed[](priceIds.length);
+        for (uint i = 0; i < updateData[0].length; i++) {
+            if (
+                (updateData[0][i].length > 4 &&
+                    UnsafeCalldataBytesLib.toUint32(updateData[0][i], 0) ==
+                    ACCUMULATOR_MAGIC) &&
+                (updateData[1][i].length > 4 &&
+                    UnsafeCalldataBytesLib.toUint32(updateData[1][i], 0) ==
+                    ACCUMULATOR_MAGIC)
+            ) {
+                // Parse the accumulator update
+                uint offsetFirst;
+                uint offsetSecond;
+                {
+                    UpdateType updateType;
+                    (offsetFirst, updateType) = extractUpdateTypeFromAccumulatorHeader(updateData[0][i]);
+                    if (updateType != UpdateType.WormholeMerkle) {
+                        revert PythErrors.InvalidUpdateData();
+                    }
+                    (offsetSecond, updateType) = extractUpdateTypeFromAccumulatorHeader(updateData[1][i]);
+                    if (updateType != UpdateType.WormholeMerkle) {
+                        revert PythErrors.InvalidUpdateData();
+                    }
+                }
+
+                bytes20 digestFirst;
+                bytes20 digestSecond;
+                uint8 numUpdatesFirst;
+                uint8 numUpdatesSecond;
+                bytes calldata encodedFirst;
+                bytes calldata encodedSecond;
+                (
+                    offsetFirst,
+                    digestFirst,
+                    numUpdates,
+                    encodedFirst
+                ) = extractWormholeMerkleHeaderDigestAndNumUpdatesAndEncodedFromAccumulatorUpdate(
+                    updateData[0][i],
+                    offsetFirst
+                );
+                (
+                    offsetSecond,
+                    digestSecond,
+                    numUpdates,
+                    encodedSecond
+                ) = extractWormholeMerkleHeaderDigestAndNumUpdatesAndEncodedFromAccumulatorUpdate(
+                    updateData[1][i],
+                    offsetSecond);
+
+                if (numUpdatesFirst != numUpdatesSecond) {
+                    revert PythErrors.InvalidUpdateData();
+                }
+
+                
+            } else {
+                revert PythErrors.InvalidUpdateData();
+            }
+        }
+    }
+
     function parsePriceFeedUpdatesUnique(
         bytes[] calldata updateData,
         bytes32[] calldata priceIds,

+ 71 - 1
target_chains/ethereum/contracts/contracts/pyth/PythAccumulator.sol

@@ -25,7 +25,8 @@ abstract contract PythAccumulator is PythGetters, PythSetters, AbstractPyth {
     }
 
     enum MessageType {
-        PriceFeed
+        PriceFeed,
+        TwapPriceFeed
     }
 
     // This method is also used by batch attestation but moved here
@@ -262,6 +263,11 @@ abstract contract PythAccumulator is PythGetters, PythSetters, AbstractPyth {
                     encodedMessage,
                     1
                 );
+            } else if (messageType == MessageType.TwapPriceFeed) {
+                (twapPriceInfo, priceId) = parseTwapPriceFeedMessage(
+                    encodedMessage,
+                    1
+                );
             } else {
                 revert PythErrors.InvalidUpdateData();
             }
@@ -335,6 +341,70 @@ abstract contract PythAccumulator is PythGetters, PythSetters, AbstractPyth {
         }
     }
 
+    function parseTwapPriceFeedMessage(
+        bytes calldata encodedTwapPriceFeed,
+        uint offset
+    )
+        private
+        pure
+        returns (
+            PythInternalStructs.TwapPriceInfo memory twapPriceInfo,
+            bytes32 priceId
+        )
+    {
+        unchecked {
+            priceId = UnsafeCalldataBytesLib.toBytes32(
+                encodedPriceFeed,
+                offset
+            );
+            offset += 32;
+
+            twapPriceInfo.cumulativePrice = int128(
+                UnsafeCalldataBytesLib.toUint64(encodedPriceFeed, offset)
+            );
+            offset += 16;
+
+            twapPriceInfo.cumulativeConf = UnsafeCalldataBytesLib.toUint128(
+                encodedPriceFeed,
+                offset
+            );
+            offset += 16;
+
+            twapPriceInfo.numDownSlots = UnsafeCalldataBytesLib.toUint64(
+                encodedPriceFeed,
+                offset
+            );
+            offset += 8;
+
+            twapPriceInfo.publishSlot = UnsafeCalldataBytesLib.toUint64(
+                encodedPriceFeed,
+                offset
+            );
+            offset += 8;
+
+            twapPriceInfo.publishTime = UnsafeCalldataBytesLib.toUint64(
+                encodedPriceFeed,
+                offset
+            );
+            offset += 8;
+
+            twapPriceInfo.prevPublishTime = UnsafeCalldataBytesLib.toUint64(
+                encodedPriceFeed,
+                offset
+            );
+            offset += 8;
+
+            twapPriceInfo.expo = int32(
+                UnsafeCalldataBytesLib.toUint32(encodedPriceFeed, offset)
+            );
+            offset += 4;
+
+            if (offset > encodedPriceFeed.length)
+                revert PythErrors.InvalidUpdateData();
+        }
+    }
+
+
     function updatePriceInfosFromAccumulatorUpdate(
         bytes calldata accumulatorUpdate
     ) internal returns (uint8 numUpdates) {

+ 15 - 0
target_chains/ethereum/contracts/contracts/pyth/PythInternalStructs.sol

@@ -26,6 +26,21 @@ contract PythInternalStructs {
         uint64 emaConf;
     }
 
+    struct TwapPriceInfo {
+        // slot 1
+        int128 cumulativePrice;
+        uint128 cumulativeConf;
+        
+        // slot 2
+        uint64 numDownSlots;
+        uint64 publishSlot;
+        int64 publishTime;
+        int64 prevPublishTime;
+        // slot 3
+        
+        int32 expo;
+    }
+
     struct DataSource {
         uint16 chainId;
         bytes32 emitterAddress;

+ 14 - 1
target_chains/ethereum/sdk/solidity/PythStructs.sol

@@ -30,4 +30,17 @@ contract PythStructs {
         // Latest available exponentially-weighted moving average price
         Price emaPrice;
     }
-}
+
+    struct TwapPriceFeed {
+        // The price ID.
+        bytes32 id;
+        // Start time of the TWAP
+        uint startTime;
+        // End time of the TWAP
+        uint endTime;
+        // TWAP price
+        Price cumulativePrice;
+        // Down slot ratio
+        uint32 downSlotRatio;
+    }
+1}

+ 1 - 1
target_chains/fuel/contracts/Cargo.lock

@@ -4784,7 +4784,7 @@ dependencies = [
 
 [[package]]
 name = "pythnet-sdk"
-version = "2.3.0"
+version = "2.3.1"
 dependencies = [
  "bincode",
  "borsh",

File diff suppressed because it is too large
+ 322 - 304
target_chains/near/example/Cargo.lock


Some files were not shown because too many files changed in this diff