@@ -159,6 +159,8 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils {
159
159
updateData[1 ] = endUpdateData;
160
160
161
161
// Calculate the update fee
162
+ // We only charge fee for 1 update even though we need 2 updates to derive TWAP.
163
+ // This is for better UX since user's intention is to get a single TWAP price.
162
164
updateFee = pyth.getUpdateFee (updateData[0 ]);
163
165
}
164
166
@@ -451,4 +453,164 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils {
451
453
// Validate the downSlotsRatio is 0 in our test implementation
452
454
assertEq (twapPriceFeeds[0 ].downSlotsRatio, uint32 (0 ));
453
455
}
456
+
457
+ function testParseTwapPriceFeedUpdatesRevertsWithInvalidUpdateDataLength ()
458
+ public
459
+ {
460
+ bytes32 [] memory priceIds = new bytes32 [](1 );
461
+ priceIds[0 ] = bytes32 (uint256 (1 ));
462
+
463
+ // Create invalid update data with wrong length
464
+ bytes [][] memory updateData = new bytes [][](1 ); // Should be 2
465
+ updateData[0 ] = new bytes [](1 );
466
+
467
+ vm.expectRevert (PythErrors.InvalidUpdateData.selector );
468
+ pyth.parseTwapPriceFeedUpdates {value: 0 }(updateData, priceIds);
469
+ }
470
+
471
+ function testParseTwapPriceFeedUpdatesRevertsWithMismatchedPriceIds ()
472
+ public
473
+ {
474
+ bytes32 [] memory priceIds = new bytes32 [](1 );
475
+ priceIds[0 ] = bytes32 (uint256 (1 ));
476
+
477
+ PriceFeedMessage[] memory messages = new PriceFeedMessage [](2 );
478
+
479
+ // Start message with priceId 1
480
+ messages[0 ].priceId = bytes32 (uint256 (1 ));
481
+ messages[0 ].price = 100 ;
482
+ messages[0 ].publishTime = 1000 ;
483
+ messages[0 ].prevPublishTime = 900 ;
484
+
485
+ // End message with different priceId 2
486
+ messages[1 ].priceId = bytes32 (uint256 (2 )); // Different priceId
487
+ messages[1 ].price = 110 ;
488
+ messages[1 ].publishTime = 1100 ;
489
+ messages[1 ].prevPublishTime = 1000 ;
490
+
491
+ (
492
+ bytes [][] memory updateData ,
493
+ uint updateFee
494
+ ) = createBatchedTwapUpdateDataFromMessages (messages);
495
+
496
+ vm.expectRevert (PythErrors.InvalidTwapUpdateDataSet.selector );
497
+ pyth.parseTwapPriceFeedUpdates {value: updateFee}(updateData, priceIds);
498
+ }
499
+
500
+ function testParseTwapPriceFeedUpdatesRevertsWithInvalidTimeOrdering ()
501
+ public
502
+ {
503
+ bytes32 [] memory priceIds = new bytes32 [](1 );
504
+ priceIds[0 ] = bytes32 (uint256 (1 ));
505
+
506
+ PriceFeedMessage[] memory messages = new PriceFeedMessage [](2 );
507
+
508
+ // Start message with later time
509
+ messages[0 ].priceId = priceIds[0 ];
510
+ messages[0 ].price = 100 ;
511
+ messages[0 ].publishTime = 1100 ; // Later time
512
+ messages[0 ].prevPublishTime = 1000 ;
513
+
514
+ // End message with earlier time
515
+ messages[1 ].priceId = priceIds[0 ];
516
+ messages[1 ].price = 110 ;
517
+ messages[1 ].publishTime = 1000 ; // Earlier time
518
+ messages[1 ].prevPublishTime = 900 ;
519
+
520
+ (
521
+ bytes [][] memory updateData ,
522
+ uint updateFee
523
+ ) = createBatchedTwapUpdateDataFromMessages (messages);
524
+
525
+ vm.expectRevert (PythErrors.InvalidTwapUpdateDataSet.selector );
526
+ pyth.parseTwapPriceFeedUpdates {value: updateFee}(updateData, priceIds);
527
+ }
528
+
529
+ function testParseTwapPriceFeedUpdatesRevertsWithMismatchedExponents ()
530
+ public
531
+ {
532
+ bytes32 [] memory priceIds = new bytes32 [](1 );
533
+ priceIds[0 ] = bytes32 (uint256 (1 ));
534
+
535
+ PriceFeedMessage[] memory messages = new PriceFeedMessage [](2 );
536
+
537
+ // Start message with expo -8
538
+ messages[0 ].priceId = priceIds[0 ];
539
+ messages[0 ].price = 100 ;
540
+ messages[0 ].expo = - 8 ;
541
+ messages[0 ].publishTime = 1000 ;
542
+ messages[0 ].prevPublishTime = 900 ;
543
+
544
+ // End message with different expo -6
545
+ messages[1 ].priceId = priceIds[0 ];
546
+ messages[1 ].price = 110 ;
547
+ messages[1 ].expo = - 6 ; // Different exponent
548
+ messages[1 ].publishTime = 1100 ;
549
+ messages[1 ].prevPublishTime = 1000 ;
550
+
551
+ (
552
+ bytes [][] memory updateData ,
553
+ uint updateFee
554
+ ) = createBatchedTwapUpdateDataFromMessages (messages);
555
+
556
+ vm.expectRevert (PythErrors.InvalidTwapUpdateDataSet.selector );
557
+ pyth.parseTwapPriceFeedUpdates {value: updateFee}(updateData, priceIds);
558
+ }
559
+
560
+ function testParseTwapPriceFeedUpdatesRevertsWithInvalidPrevPublishTime ()
561
+ public
562
+ {
563
+ bytes32 [] memory priceIds = new bytes32 [](1 );
564
+ priceIds[0 ] = bytes32 (uint256 (1 ));
565
+
566
+ PriceFeedMessage[] memory messages = new PriceFeedMessage [](2 );
567
+
568
+ // Start message with invalid prevPublishTime
569
+ messages[0 ].priceId = priceIds[0 ];
570
+ messages[0 ].price = 100 ;
571
+ messages[0 ].publishTime = 1000 ;
572
+ messages[0 ].prevPublishTime = 1100 ; // Invalid: prevPublishTime > publishTime
573
+
574
+ // End message
575
+ messages[1 ].priceId = priceIds[0 ];
576
+ messages[1 ].price = 110 ;
577
+ messages[1 ].publishTime = 1200 ;
578
+ messages[1 ].prevPublishTime = 1000 ;
579
+
580
+ (
581
+ bytes [][] memory updateData ,
582
+ uint updateFee
583
+ ) = createBatchedTwapUpdateDataFromMessages (messages);
584
+
585
+ vm.expectRevert (PythErrors.InvalidTwapUpdateData.selector );
586
+ pyth.parseTwapPriceFeedUpdates {value: updateFee}(updateData, priceIds);
587
+ }
588
+
589
+ function testParseTwapPriceFeedUpdatesRevertsWithInsufficientFee () public {
590
+ bytes32 [] memory priceIds = new bytes32 [](1 );
591
+ priceIds[0 ] = bytes32 (uint256 (1 ));
592
+
593
+ PriceFeedMessage[] memory messages = new PriceFeedMessage [](2 );
594
+
595
+ messages[0 ].priceId = priceIds[0 ];
596
+ messages[0 ].price = 100 ;
597
+ messages[0 ].publishTime = 1000 ;
598
+ messages[0 ].prevPublishTime = 900 ;
599
+
600
+ messages[1 ].priceId = priceIds[0 ];
601
+ messages[1 ].price = 110 ;
602
+ messages[1 ].publishTime = 1100 ;
603
+ messages[1 ].prevPublishTime = 1000 ;
604
+
605
+ (
606
+ bytes [][] memory updateData ,
607
+ uint updateFee
608
+ ) = createBatchedTwapUpdateDataFromMessages (messages);
609
+
610
+ vm.expectRevert (PythErrors.InsufficientFee.selector );
611
+ pyth.parseTwapPriceFeedUpdates {value: updateFee - 1 }(
612
+ updateData,
613
+ priceIds
614
+ ); // Send insufficient fee
615
+ }
454
616
}
0 commit comments