@@ -317,21 +317,16 @@ abstract contract Pyth is
317317 override
318318 returns (PythStructs.TwapPriceFeed[] memory twapPriceFeeds )
319319 {
320- {
321- if (updateData.length != 2 ) {
322- revert PythErrors.InvalidUpdateData ();
323- }
324- uint requiredFee = getUpdateFee (updateData[0 ]);
320+ if (updateData.length != 2 ) {
321+ revert PythErrors.InvalidUpdateData ();
322+ }
323+ uint requiredFee = getUpdateFee (updateData[0 ]);
325324
326- // Check if the two updateData contains the same number of priceUpdates
327- // by comparing fees since getUpdateFee parses the update data to count price feeds
328- if (requiredFee != getUpdateFee (updateData[1 ])) {
329- revert PythErrors.InvalidUpdateData ();
330- }
331- if (msg .value < requiredFee) revert PythErrors.InsufficientFee ();
325+ if (requiredFee != getUpdateFee (updateData[1 ])) {
326+ revert PythErrors.InvalidUpdateData ();
332327 }
328+ if (msg .value < requiredFee) revert PythErrors.InsufficientFee ();
333329
334- // Parse the updateData
335330 unchecked {
336331 twapPriceFeeds = new PythStructs.TwapPriceFeed [](priceIds.length );
337332 for (uint i = 0 ; i < updateData[0 ].length ; i++ ) {
@@ -343,123 +338,102 @@ abstract contract Pyth is
343338 UnsafeCalldataBytesLib.toUint32 (updateData[1 ][i], 0 ) ==
344339 ACCUMULATOR_MAGIC)
345340 ) {
346- uint offsetStart;
347- uint offsetEnd;
348- {
349- UpdateType updateType;
350- (
351- offsetStart,
352- updateType
353- ) = extractUpdateTypeFromAccumulatorHeader (
354- updateData[0 ][i]
355- );
356- if (updateType != UpdateType.WormholeMerkle) {
357- revert PythErrors.InvalidUpdateData ();
358- }
359- (
360- offsetEnd,
361- updateType
362- ) = extractUpdateTypeFromAccumulatorHeader (
363- updateData[1 ][i]
364- );
365- if (updateType != UpdateType.WormholeMerkle) {
366- revert PythErrors.InvalidUpdateData ();
367- }
341+ PythInternalStructs.TwapUpdateData memory twapData;
342+ UpdateType updateType;
343+ (
344+ twapData.offsetStart,
345+ updateType
346+ ) = extractUpdateTypeFromAccumulatorHeader (
347+ updateData[0 ][i]
348+ );
349+ if (updateType != UpdateType.WormholeMerkle) {
350+ revert PythErrors.InvalidUpdateData ();
351+ }
352+ (
353+ twapData.offsetEnd,
354+ updateType
355+ ) = extractUpdateTypeFromAccumulatorHeader (
356+ updateData[1 ][i]
357+ );
358+ if (updateType != UpdateType.WormholeMerkle) {
359+ revert PythErrors.InvalidUpdateData ();
368360 }
369361
370- bytes20 digestStart;
371- bytes20 digestEnd;
372- uint8 numUpdatesStart;
373- uint8 numUpdatesEnd;
374- bytes calldata encodedStart;
375- bytes calldata encodedEnd;
376362 (
377- offsetStart,
378- digestStart,
379- numUpdatesStart,
380- encodedStart
363+ twapData. offsetStart,
364+ twapData. digestStart,
365+ twapData. numUpdatesStart,
366+ twapData. encodedStart
381367 ) = extractWormholeMerkleHeaderDigestAndNumUpdatesAndEncodedFromAccumulatorUpdate (
382368 updateData[0 ][i],
383- offsetStart
369+ twapData. offsetStart
384370 );
385371 (
386- offsetEnd,
387- digestEnd,
388- numUpdatesEnd,
389- encodedEnd
372+ twapData. offsetEnd,
373+ twapData. digestEnd,
374+ twapData. numUpdatesEnd,
375+ twapData. encodedEnd
390376 ) = extractWormholeMerkleHeaderDigestAndNumUpdatesAndEncodedFromAccumulatorUpdate (
391377 updateData[1 ][i],
392- offsetEnd
378+ twapData. offsetEnd
393379 );
394380
395- // We have already validated the number of updates in the first and second updateData so we only use numUpdatesStart here
396- for (uint j = 0 ; j < numUpdatesStart; j++ ) {
397- PythInternalStructs.TwapPriceInfo
398- memory twapPriceInfoStart;
399- PythInternalStructs.TwapPriceInfo
400- memory twapPriceInfoEnd;
401- bytes32 priceIdStart;
402- bytes32 priceIdEnd;
381+ PythInternalStructs.TwapPriceInfo memory twapPriceInfoStart;
382+ PythInternalStructs.TwapPriceInfo memory twapPriceInfoEnd;
383+ bytes32 priceIdStart;
384+ bytes32 priceIdEnd;
403385
404- (
405- offsetStart,
406- twapPriceInfoStart,
407- priceIdStart
408- ) = extractTwapPriceInfoFromMerkleProof (
409- digestStart,
410- encodedStart,
411- offsetStart
412- );
413- (
414- offsetEnd,
415- twapPriceInfoEnd,
416- priceIdEnd
417- ) = extractTwapPriceInfoFromMerkleProof (
418- digestEnd,
419- encodedEnd,
420- offsetEnd
421- );
422-
423- if (priceIdStart != priceIdEnd)
424- revert PythErrors.InvalidTwapUpdateDataSet ();
386+ // Use original calldata directly in function calls
387+ (
388+ twapData.offsetStart,
389+ twapPriceInfoStart,
390+ priceIdStart
391+ ) = extractTwapPriceInfoFromMerkleProof (
392+ twapData.digestStart,
393+ updateData[0 ][i],
394+ twapData.offsetStart
395+ );
396+ (
397+ twapData.offsetEnd,
398+ twapPriceInfoEnd,
399+ priceIdEnd
400+ ) = extractTwapPriceInfoFromMerkleProof (
401+ twapData.digestEnd,
402+ updateData[1 ][i],
403+ twapData.offsetEnd
404+ );
425405
426- // Unlike parsePriceFeedUpdatesInternal, we don't call updateLatestPriceIfNecessary here.
427- // TWAP calculations are read-only operations that compute time-weighted averages
428- // without updating the contract's state, returning calculated values directly to the caller.
429- {
430- uint k = findIndexOfPriceId (priceIds, priceIdStart);
406+ if (priceIdStart != priceIdEnd)
407+ revert PythErrors.InvalidTwapUpdateDataSet ();
431408
432- // If priceFeed[k].id != 0 then it means that there was a valid
433- // update for priceIds[k] and we don't need to process this one.
434- if (
435- k == priceIds.length ||
436- twapPriceFeeds[k].id != 0
437- ) {
438- continue ;
439- }
409+ // Unlike parsePriceFeedUpdatesInternal, we don't call updateLatestPriceIfNecessary here.
410+ // TWAP calculations are read-only operations that compute time-weighted averages
411+ // without updating the contract's state, returning calculated values directly to the caller.
412+ uint k = findIndexOfPriceId (priceIds, priceIdStart);
440413
441- // Perform additional validation checks on the TWAP price data
442- // to ensure proper time ordering, consistent exponents, and timestamp integrity
443- // before using the data for calculations
444- validateTwapPriceInfo (
445- twapPriceInfoStart,
446- twapPriceInfoEnd
447- );
448-
449- twapPriceFeeds[k] = calculateTwap (
450- priceIdStart,
451- twapPriceInfoStart,
452- twapPriceInfoEnd
453- );
454- }
414+ // If priceFeed[k].id != 0 then it means that there was a valid
415+ // update for priceIds[k] and we don't need to process this one.
416+ if (k == priceIds.length || twapPriceFeeds[k].id != 0 ) {
417+ continue ;
455418 }
456- if (offsetStart != encodedStart.length ) {
419+
420+ // Perform additional validation checks on the TWAP price data
421+ // to ensure proper time ordering, consistent exponents, and timestamp integrity
422+ // before using the data for calculations
423+ validateTwapPriceInfo (twapPriceInfoStart, twapPriceInfoEnd);
424+
425+ twapPriceFeeds[k] = calculateTwap (
426+ priceIdStart,
427+ twapPriceInfoStart,
428+ twapPriceInfoEnd
429+ );
430+ if (twapData.offsetStart != twapData.encodedStart.length ) {
457431 revert PythErrors.InvalidTwapUpdateData ();
458432 }
459- if (offsetEnd != encodedEnd.length ) {
433+ if (twapData. offsetEnd != twapData. encodedEnd.length ) {
460434 revert PythErrors.InvalidTwapUpdateData ();
461435 }
462- if (offsetStart != offsetEnd) {
436+ if (twapData. offsetStart != twapData. offsetEnd) {
463437 revert PythErrors.InvalidTwapUpdateData ();
464438 }
465439 } else {
0 commit comments