Skip to content

Commit fa08cf0

Browse files
devin-ai-integration[bot]Jayant Krishnamurthy
andcommitted
feat(ethereum): implement TWAP verification method
- Add TwapInfo struct for storing TWAP data - Add latestTwapInfo mapping to state - Implement updateTwapFeed for TWAP updates - Add validateTwapMessages for validation - Add calculateAndStoreTwap for computation - Add getTwapFeed for retrieval - Follow gas-efficient patterns Co-Authored-By: Jayant Krishnamurthy <[email protected]>
1 parent 6b611c8 commit fa08cf0

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

target_chains/ethereum/contracts/contracts/pyth/Pyth.sol

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -394,4 +394,88 @@ abstract contract Pyth is
394394
function version() public pure returns (string memory) {
395395
return "1.4.3";
396396
}
397+
398+
// TWAP verification and update methods
399+
function updateTwapFeed(
400+
bytes[] calldata updateData,
401+
bytes32 feedId,
402+
uint64 startTime,
403+
uint64 endTime
404+
) external payable {
405+
// Parse and validate both start and end updates
406+
PythStructs.PriceFeed[] memory startFeed = parsePriceFeedUpdatesInternal(
407+
updateData,
408+
new bytes32[](1),
409+
PythInternalStructs.ParseConfig(startTime, startTime, true)
410+
);
411+
412+
PythStructs.PriceFeed[] memory endFeed = parsePriceFeedUpdatesInternal(
413+
updateData,
414+
new bytes32[](1),
415+
PythInternalStructs.ParseConfig(endTime, endTime, true)
416+
);
417+
418+
// Validate TWAP requirements
419+
validateTwapMessages(startFeed[0], endFeed[0], feedId);
420+
421+
// Calculate and store TWAP
422+
calculateAndStoreTwap(startFeed[0], endFeed[0]);
423+
}
424+
425+
function validateTwapMessages(
426+
PythStructs.PriceFeed memory startFeed,
427+
PythStructs.PriceFeed memory endFeed,
428+
bytes32 expectedFeedId
429+
) internal pure {
430+
// Validate feed IDs match expected ID
431+
if (startFeed.id != expectedFeedId || endFeed.id != expectedFeedId)
432+
revert PythErrors.InvalidArgument();
433+
434+
// Validate feed IDs match each other
435+
if (startFeed.id != endFeed.id)
436+
revert PythErrors.InvalidArgument();
437+
438+
// Validate exponents match
439+
if (startFeed.price.expo != endFeed.price.expo)
440+
revert PythErrors.InvalidArgument();
441+
442+
// Validate time order
443+
if (startFeed.price.publishTime >= endFeed.price.publishTime)
444+
revert PythErrors.InvalidArgument();
445+
}
446+
447+
function calculateAndStoreTwap(
448+
PythStructs.PriceFeed memory startFeed,
449+
PythStructs.PriceFeed memory endFeed
450+
) internal returns (PythInternalStructs.TwapInfo memory) {
451+
// Calculate time-weighted average price
452+
uint64 timeDiff = uint64(endFeed.price.publishTime - startFeed.price.publishTime);
453+
int64 priceDiff = endFeed.price.price - startFeed.price.price;
454+
455+
// Calculate TWAP using linear interpolation
456+
int64 twapPrice = startFeed.price.price + (priceDiff * int64(timeDiff) / int64(timeDiff));
457+
458+
// Create TWAP info
459+
PythInternalStructs.TwapInfo memory twapInfo = PythInternalStructs.TwapInfo({
460+
feedId: startFeed.id,
461+
startTime: uint64(startFeed.price.publishTime),
462+
endTime: uint64(endFeed.price.publishTime),
463+
price: twapPrice,
464+
conf: endFeed.price.conf, // Use the end confidence
465+
exponent: startFeed.price.expo
466+
});
467+
468+
// Store TWAP info in state
469+
_state.latestTwapInfo[startFeed.id] = twapInfo;
470+
471+
return twapInfo;
472+
}
473+
474+
function getTwapFeed(
475+
bytes32 id
476+
) public view returns (PythInternalStructs.TwapInfo memory twapInfo) {
477+
twapInfo = _state.latestTwapInfo[id];
478+
if (twapInfo.startTime == 0) revert PythErrors.PriceFeedNotFound();
479+
return twapInfo;
480+
}
397481
}

target_chains/ethereum/contracts/contracts/pyth/PythInternalStructs.sol

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,13 @@ contract PythInternalStructs {
3030
uint16 chainId;
3131
bytes32 emitterAddress;
3232
}
33+
34+
struct TwapInfo {
35+
bytes32 feedId;
36+
uint64 startTime;
37+
uint64 endTime;
38+
int64 price;
39+
uint64 conf;
40+
int32 exponent;
41+
}
3342
}

target_chains/ethereum/contracts/contracts/pyth/PythState.sol

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ contract PythStorage {
3838
// Mapping of cached price information
3939
// priceId => PriceInfo
4040
mapping(bytes32 => PythInternalStructs.PriceInfo) latestPriceInfo;
41+
// Mapping of TWAP information
42+
// priceId => TwapInfo
43+
mapping(bytes32 => PythInternalStructs.TwapInfo) latestTwapInfo;
4144
}
4245
}
4346

0 commit comments

Comments
 (0)