@@ -179,8 +179,7 @@ contract PulseTest is Test, PulseEvents {
179
179
sequenceNumber = pulse.requestPriceUpdatesWithCallback {value: totalFee}(
180
180
publishTime,
181
181
priceIds,
182
- CALLBACK_GAS_LIMIT,
183
- provider
182
+ CALLBACK_GAS_LIMIT
184
183
);
185
184
186
185
return (sequenceNumber, priceIds, publishTime);
@@ -226,8 +225,7 @@ contract PulseTest is Test, PulseEvents {
226
225
pulse.requestPriceUpdatesWithCallback {value: totalFee}(
227
226
publishTime,
228
227
priceIds,
229
- CALLBACK_GAS_LIMIT,
230
- defaultProvider
228
+ CALLBACK_GAS_LIMIT
231
229
);
232
230
233
231
// Additional assertions to verify event data was stored correctly
@@ -260,8 +258,7 @@ contract PulseTest is Test, PulseEvents {
260
258
pulse.requestPriceUpdatesWithCallback {value: PYTH_FEE}( // Intentionally low fee
261
259
block .timestamp ,
262
260
priceIds,
263
- CALLBACK_GAS_LIMIT,
264
- defaultProvider
261
+ CALLBACK_GAS_LIMIT
265
262
);
266
263
}
267
264
@@ -277,7 +274,7 @@ contract PulseTest is Test, PulseEvents {
277
274
vm.prank (address (consumer));
278
275
uint64 sequenceNumber = pulse.requestPriceUpdatesWithCallback {
279
276
value: totalFee
280
- }(publishTime, priceIds, CALLBACK_GAS_LIMIT, defaultProvider );
277
+ }(publishTime, priceIds, CALLBACK_GAS_LIMIT);
281
278
282
279
// Step 2: Create mock price feeds and setup Pyth response
283
280
PythStructs.PriceFeed[] memory priceFeeds = createMockPriceFeeds (
@@ -432,7 +429,7 @@ contract PulseTest is Test, PulseEvents {
432
429
vm.prank (address (consumer));
433
430
uint64 sequenceNumber = pulse.requestPriceUpdatesWithCallback {
434
431
value: totalFee
435
- }(futureTime, priceIds, CALLBACK_GAS_LIMIT, defaultProvider );
432
+ }(futureTime, priceIds, CALLBACK_GAS_LIMIT);
436
433
437
434
// Try to execute callback before the requested timestamp
438
435
PythStructs.PriceFeed[] memory priceFeeds = createMockPriceFeeds (
@@ -470,8 +467,7 @@ contract PulseTest is Test, PulseEvents {
470
467
pulse.requestPriceUpdatesWithCallback {value: totalFee}(
471
468
farFutureTime,
472
469
priceIds,
473
- CALLBACK_GAS_LIMIT,
474
- defaultProvider
470
+ CALLBACK_GAS_LIMIT
475
471
);
476
472
}
477
473
@@ -536,7 +532,7 @@ contract PulseTest is Test, PulseEvents {
536
532
vm.prank (address (consumer));
537
533
pulse.requestPriceUpdatesWithCallback {
538
534
value: calculateTotalFee (defaultProvider)
539
- }(block .timestamp , priceIds, CALLBACK_GAS_LIMIT, defaultProvider );
535
+ }(block .timestamp , priceIds, CALLBACK_GAS_LIMIT);
540
536
541
537
// Get admin's balance before withdrawal
542
538
uint256 adminBalanceBefore = admin.balance;
@@ -584,7 +580,7 @@ contract PulseTest is Test, PulseEvents {
584
580
vm.prank (address (consumer));
585
581
pulse.requestPriceUpdatesWithCallback {
586
582
value: calculateTotalFee (defaultProvider)
587
- }(block .timestamp , priceIds, CALLBACK_GAS_LIMIT, defaultProvider );
583
+ }(block .timestamp , priceIds, CALLBACK_GAS_LIMIT);
588
584
589
585
// Get provider's accrued fees instead of total fees
590
586
PulseState.ProviderInfo memory providerInfo = pulse.getProviderInfo (
@@ -691,8 +687,7 @@ contract PulseTest is Test, PulseEvents {
691
687
pulse.requestPriceUpdatesWithCallback {value: totalFee}(
692
688
block .timestamp ,
693
689
priceIds,
694
- CALLBACK_GAS_LIMIT,
695
- defaultProvider
690
+ CALLBACK_GAS_LIMIT
696
691
);
697
692
}
698
693
@@ -755,9 +750,130 @@ contract PulseTest is Test, PulseEvents {
755
750
vm.prank (address (consumer));
756
751
uint64 sequenceNumber = pulse.requestPriceUpdatesWithCallback {
757
752
value: totalFee
758
- }(block .timestamp , priceIds, CALLBACK_GAS_LIMIT, provider );
753
+ }(block .timestamp , priceIds, CALLBACK_GAS_LIMIT);
759
754
760
755
PulseState.Request memory req = pulse.getRequest (sequenceNumber);
761
756
assertEq (req.provider, provider);
762
757
}
758
+
759
+ function testExclusivityPeriod () public {
760
+ // Test initial value
761
+ assertEq (
762
+ pulse.getExclusivityPeriod (),
763
+ 15 ,
764
+ "Initial exclusivity period should be 15 seconds "
765
+ );
766
+
767
+ // Test setting new value
768
+ vm.prank (admin);
769
+ vm.expectEmit ();
770
+ emit ExclusivityPeriodUpdated (15 , 30 );
771
+ pulse.setExclusivityPeriod (30 );
772
+
773
+ assertEq (
774
+ pulse.getExclusivityPeriod (),
775
+ 30 ,
776
+ "Exclusivity period should be updated "
777
+ );
778
+ }
779
+
780
+ function testSetExclusivityPeriodUnauthorized () public {
781
+ vm.prank (address (0xdead ));
782
+ vm.expectRevert ("Only admin can set exclusivity period " );
783
+ pulse.setExclusivityPeriod (30 );
784
+ }
785
+
786
+ function testExecuteCallbackDuringExclusivity () public {
787
+ // Register a second provider
788
+ address secondProvider = address (0x456 );
789
+ vm.prank (secondProvider);
790
+ pulse.registerProvider (DEFAULT_PROVIDER_FEE);
791
+
792
+ // Setup request
793
+ (
794
+ uint64 sequenceNumber ,
795
+ bytes32 [] memory priceIds ,
796
+ uint256 publishTime
797
+ ) = setupConsumerRequest (address (consumer), defaultProvider);
798
+
799
+ // Setup mock data
800
+ PythStructs.PriceFeed[] memory priceFeeds = createMockPriceFeeds (
801
+ publishTime
802
+ );
803
+ mockParsePriceFeedUpdates (priceFeeds);
804
+ bytes [] memory updateData = createMockUpdateData (priceFeeds);
805
+
806
+ // Try to execute with second provider during exclusivity period
807
+ vm.prank (secondProvider);
808
+ vm.expectRevert ("Only assigned provider during exclusivity period " );
809
+ pulse.executeCallback (sequenceNumber, updateData, priceIds);
810
+
811
+ // Original provider should succeed
812
+ vm.prank (defaultProvider);
813
+ pulse.executeCallback (sequenceNumber, updateData, priceIds);
814
+ }
815
+
816
+ function testExecuteCallbackAfterExclusivity () public {
817
+ // Register a second provider
818
+ address secondProvider = address (0x456 );
819
+ vm.prank (secondProvider);
820
+ pulse.registerProvider (DEFAULT_PROVIDER_FEE);
821
+
822
+ // Setup request
823
+ (
824
+ uint64 sequenceNumber ,
825
+ bytes32 [] memory priceIds ,
826
+ uint256 publishTime
827
+ ) = setupConsumerRequest (address (consumer), defaultProvider);
828
+
829
+ // Setup mock data
830
+ PythStructs.PriceFeed[] memory priceFeeds = createMockPriceFeeds (
831
+ publishTime
832
+ );
833
+ mockParsePriceFeedUpdates (priceFeeds);
834
+ bytes [] memory updateData = createMockUpdateData (priceFeeds);
835
+
836
+ // Wait for exclusivity period to end
837
+ vm.warp (block .timestamp + pulse.getExclusivityPeriod () + 1 );
838
+
839
+ // Second provider should now succeed
840
+ vm.prank (secondProvider);
841
+ pulse.executeCallback (sequenceNumber, updateData, priceIds);
842
+ }
843
+
844
+ function testExecuteCallbackWithCustomExclusivityPeriod () public {
845
+ // Register a second provider
846
+ address secondProvider = address (0x456 );
847
+ vm.prank (secondProvider);
848
+ pulse.registerProvider (DEFAULT_PROVIDER_FEE);
849
+
850
+ // Set custom exclusivity period
851
+ vm.prank (admin);
852
+ pulse.setExclusivityPeriod (30 );
853
+
854
+ // Setup request
855
+ (
856
+ uint64 sequenceNumber ,
857
+ bytes32 [] memory priceIds ,
858
+ uint256 publishTime
859
+ ) = setupConsumerRequest (address (consumer), defaultProvider);
860
+
861
+ // Setup mock data
862
+ PythStructs.PriceFeed[] memory priceFeeds = createMockPriceFeeds (
863
+ publishTime
864
+ );
865
+ mockParsePriceFeedUpdates (priceFeeds);
866
+ bytes [] memory updateData = createMockUpdateData (priceFeeds);
867
+
868
+ // Try at 29 seconds (should fail for second provider)
869
+ vm.warp (block .timestamp + 29 );
870
+ vm.prank (secondProvider);
871
+ vm.expectRevert ("Only assigned provider during exclusivity period " );
872
+ pulse.executeCallback (sequenceNumber, updateData, priceIds);
873
+
874
+ // Try at 31 seconds (should succeed for second provider)
875
+ vm.warp (block .timestamp + 2 );
876
+ vm.prank (secondProvider);
877
+ pulse.executeCallback (sequenceNumber, updateData, priceIds);
878
+ }
763
879
}
0 commit comments