@@ -13,6 +13,11 @@ import {
13
13
PYTH_AUTHORIZE_GOVERNANCE_DATA_SOURCE_TRANSFER ,
14
14
PYTH_REQUEST_GOVERNANCE_DATA_SOURCE_TRANSFER ,
15
15
TEST_GUARDIAN_ADDRESS2 ,
16
+ ETH_PRICE_FEED_ID ,
17
+ HERMES_BTC_PRICE ,
18
+ HERMES_ETH_PRICE ,
19
+ HERMES_ETH_PUBLISH_TIME ,
20
+ HERMES_BTC_PUBLISH_TIME ,
16
21
} from "./utils/pyth" ;
17
22
import { GUARDIAN_SET_0 , MAINNET_UPGRADE_VAAS } from "./utils/wormhole" ;
18
23
import { DataSource } from "@pythnetwork/xc-admin-common" ;
@@ -235,6 +240,14 @@ describe("PythTest", () => {
235
240
236
241
await updateGuardianSets ( pythTest , deployer ) ;
237
242
243
+ // Check initial prices
244
+ const initialBtcPrice = await pythTest . getPriceUnsafe ( BTC_PRICE_FEED_ID ) ;
245
+ expect ( initialBtcPrice . price ) . not . toBe ( HERMES_BTC_PRICE ) ;
246
+ // Expect an error for ETH price feed as it doesn't exist initially
247
+ await expect ( pythTest . getPriceUnsafe ( ETH_PRICE_FEED_ID ) ) . rejects . toThrow (
248
+ "Unable to execute get method. Got exit_code: 1019"
249
+ ) ; // ERROR_PRICE_FEED_NOT_FOUND = 1019
250
+
238
251
const updateData = Buffer . from ( HERMES_BTC_ETH_UPDATE , "hex" ) ;
239
252
const updateFee = await pythTest . getUpdateFee ( updateData ) ;
240
253
@@ -250,10 +263,14 @@ describe("PythTest", () => {
250
263
success : true ,
251
264
} ) ;
252
265
253
- // Check if the price has been updated correctly
254
- const updatedPrice = await pythTest . getPriceUnsafe ( BTC_PRICE_FEED_ID ) ;
255
- expect ( updatedPrice . price ) . not . toBe ( Number ( PRICE . price ) ) ; // Since we updated the price, it should not be the same as the initial price
256
- expect ( updatedPrice . publishTime ) . toBeGreaterThan ( PRICE . publishTime ) ;
266
+ // Check if both BTC and ETH prices have been updated
267
+ const updatedBtcPrice = await pythTest . getPriceUnsafe ( BTC_PRICE_FEED_ID ) ;
268
+ expect ( updatedBtcPrice . price ) . toBe ( HERMES_BTC_PRICE ) ;
269
+ expect ( updatedBtcPrice . publishTime ) . toBe ( HERMES_BTC_PUBLISH_TIME ) ;
270
+
271
+ const updatedEthPrice = await pythTest . getPriceUnsafe ( ETH_PRICE_FEED_ID ) ;
272
+ expect ( updatedEthPrice . price ) . toBe ( HERMES_ETH_PRICE ) ;
273
+ expect ( updatedEthPrice . publishTime ) . toBe ( HERMES_ETH_PUBLISH_TIME ) ;
257
274
} ) ;
258
275
259
276
it ( "should fail to get update fee with invalid data" , async ( ) => {
@@ -339,6 +356,21 @@ describe("PythTest", () => {
339
356
} ) ;
340
357
} ) ;
341
358
359
+ it ( "should correctly handle stale prices" , async ( ) => {
360
+ const staleTime = Math . floor ( Date . now ( ) / 1000 ) - TIME_PERIOD - 10 ; // 10 seconds past the allowed period
361
+ const stalePrice = new Price ( {
362
+ price : "1" ,
363
+ conf : "2" ,
364
+ expo : 3 ,
365
+ publishTime : staleTime ,
366
+ } ) ;
367
+ await deployContract ( BTC_PRICE_FEED_ID , TIME_PERIOD , stalePrice , EMA_PRICE ) ;
368
+
369
+ await expect (
370
+ pythTest . getPriceNoOlderThan ( TIME_PERIOD , BTC_PRICE_FEED_ID )
371
+ ) . rejects . toThrow ( "Unable to execute get method. Got exit_code: 1020" ) ; // ERROR_OUTDATED_PRICE = 1020
372
+ } ) ;
373
+
342
374
it ( "should fail to update price feeds with insufficient gas" , async ( ) => {
343
375
await deployContract ( ) ;
344
376
await updateGuardianSets ( pythTest , deployer ) ;
@@ -385,7 +417,7 @@ describe("PythTest", () => {
385
417
} ) ;
386
418
} ) ;
387
419
388
- it ( "should fail to get price for non-existent price feed" , async ( ) => {
420
+ it ( "should fail to get prices for non-existent price feed" , async ( ) => {
389
421
await deployContract ( ) ;
390
422
391
423
const nonExistentPriceFeedId =
@@ -394,6 +426,14 @@ describe("PythTest", () => {
394
426
await expect (
395
427
pythTest . getPriceUnsafe ( nonExistentPriceFeedId )
396
428
) . rejects . toThrow ( "Unable to execute get method. Got exit_code: 1019" ) ; // ERROR_PRICE_FEED_NOT_FOUND = 1019
429
+
430
+ await expect (
431
+ pythTest . getPriceNoOlderThan ( TIME_PERIOD , nonExistentPriceFeedId )
432
+ ) . rejects . toThrow ( "Unable to execute get method. Got exit_code: 1019" ) ; // ERROR_PRICE_FEED_NOT_FOUND
433
+
434
+ await expect (
435
+ pythTest . getEmaPriceUnsafe ( nonExistentPriceFeedId )
436
+ ) . rejects . toThrow ( "Unable to execute get method. Got exit_code: 1019" ) ; // ERROR_PRICE_FEED_NOT_FOUND
397
437
} ) ;
398
438
399
439
it ( "should correctly get chain ID" , async ( ) => {
@@ -518,7 +558,7 @@ describe("PythTest", () => {
518
558
expect ( result ) . toBe ( SINGLE_UPDATE_FEE ) ;
519
559
} ) ;
520
560
521
- it ( "should execute set fee governance instruction" , async ( ) => {
561
+ it ( "should execute set data sources governance instruction" , async ( ) => {
522
562
await deployContract (
523
563
BTC_PRICE_FEED_ID ,
524
564
TIME_PERIOD ,
@@ -572,6 +612,47 @@ describe("PythTest", () => {
572
612
expect ( oldDataSourceIsValid ) . toBe ( false ) ;
573
613
} ) ;
574
614
615
+ it ( "should execute set fee governance instruction" , async ( ) => {
616
+ await deployContract (
617
+ BTC_PRICE_FEED_ID ,
618
+ TIME_PERIOD ,
619
+ PRICE ,
620
+ EMA_PRICE ,
621
+ SINGLE_UPDATE_FEE ,
622
+ DATA_SOURCES ,
623
+ 0 ,
624
+ [ TEST_GUARDIAN_ADDRESS1 ] ,
625
+ 60051 , // CHAIN_ID of starknet since we are using the test payload for starknet
626
+ 1 ,
627
+ "0000000000000000000000000000000000000000000000000000000000000004" ,
628
+ TEST_GOVERNANCE_DATA_SOURCES [ 0 ]
629
+ ) ;
630
+
631
+ // Get the initial fee
632
+ const initialFee = await pythTest . getSingleUpdateFee ( ) ;
633
+ expect ( initialFee ) . toBe ( SINGLE_UPDATE_FEE ) ;
634
+
635
+ // Execute the governance action
636
+ const result = await pythTest . sendExecuteGovernanceAction (
637
+ deployer . getSender ( ) ,
638
+ Buffer . from ( PYTH_SET_FEE , "hex" )
639
+ ) ;
640
+ expect ( result . transactions ) . toHaveTransaction ( {
641
+ from : deployer . address ,
642
+ to : pythTest . address ,
643
+ success : true ,
644
+ } ) ;
645
+
646
+ // Get the new fee
647
+ const newFee = await pythTest . getSingleUpdateFee ( ) ;
648
+ expect ( newFee ) . toBe ( 4200 ) ; // The new fee value is 4200 in the PYTH_SET_FEE payload
649
+
650
+ // Verify that the new fee is used for updates
651
+ const updateData = Buffer . from ( HERMES_BTC_ETH_UPDATE , "hex" ) ;
652
+ const updateFee = await pythTest . getUpdateFee ( updateData ) ;
653
+ expect ( updateFee ) . toBe ( 8400 ) ; // There are two price updates in HERMES_BTC_ETH_UPDATE
654
+ } ) ;
655
+
575
656
it ( "should execute authorize governance data source transfer" , async ( ) => {
576
657
await deployContract (
577
658
BTC_PRICE_FEED_ID ,
@@ -732,6 +813,36 @@ describe("PythTest", () => {
732
813
} ) ;
733
814
} ) ;
734
815
816
+ it ( "should fail to execute governance action with invalid chain ID" , async ( ) => {
817
+ const invalidChainId = 999 ;
818
+ await deployContract (
819
+ BTC_PRICE_FEED_ID ,
820
+ TIME_PERIOD ,
821
+ PRICE ,
822
+ EMA_PRICE ,
823
+ SINGLE_UPDATE_FEE ,
824
+ DATA_SOURCES ,
825
+ 0 ,
826
+ [ TEST_GUARDIAN_ADDRESS1 ] ,
827
+ invalidChainId ,
828
+ 1 ,
829
+ "0000000000000000000000000000000000000000000000000000000000000004" ,
830
+ TEST_GOVERNANCE_DATA_SOURCES [ 0 ]
831
+ ) ;
832
+
833
+ const result = await pythTest . sendExecuteGovernanceAction (
834
+ deployer . getSender ( ) ,
835
+ Buffer . from ( PYTH_SET_FEE , "hex" )
836
+ ) ;
837
+
838
+ expect ( result . transactions ) . toHaveTransaction ( {
839
+ from : deployer . address ,
840
+ to : pythTest . address ,
841
+ success : false ,
842
+ exitCode : 1034 , // ERROR_INVALID_GOVERNANCE_TARGET
843
+ } ) ;
844
+ } ) ;
845
+
735
846
it ( "should successfully upgrade the contract" , async ( ) => {
736
847
// Compile the upgraded contract
737
848
const upgradedCode = await compile ( "PythTestUpgraded" ) ;
0 commit comments