@@ -45,6 +45,19 @@ import {
45
45
HERMES_ETH_UNIQUE_EXPO ,
46
46
HERMES_ETH_UNIQUE_PRICE ,
47
47
HERMES_ETH_UNIQUE_PUBLISH_TIME ,
48
+ HERMES_SOL_TON_PYTH_USDT_UPDATE ,
49
+ PYTH_PRICE_FEED_ID ,
50
+ SOL_PRICE_FEED_ID ,
51
+ TON_PRICE_FEED_ID ,
52
+ USDT_PRICE_FEED_ID ,
53
+ HERMES_SOL_UNIQUE_PUBLISH_TIME ,
54
+ HERMES_SOL_UNIQUE_PRICE ,
55
+ HERMES_SOL_UNIQUE_CONF ,
56
+ HERMES_SOL_UNIQUE_EXPO ,
57
+ HERMES_USDT_UNIQUE_PRICE ,
58
+ HERMES_USDT_UNIQUE_EXPO ,
59
+ HERMES_USDT_UNIQUE_CONF ,
60
+ HERMES_USDT_UNIQUE_PUBLISH_TIME ,
48
61
} from "./utils/pyth" ;
49
62
import { GUARDIAN_SET_0 , MAINNET_UPGRADE_VAAS } from "./utils/wormhole" ;
50
63
import { DataSource } from "@pythnetwork/xc-admin-common" ;
@@ -1110,6 +1123,122 @@ describe("PythTest", () => {
1110
1123
) ;
1111
1124
} ) ;
1112
1125
1126
+ it ( "should successfully parse price feed updates with more than 3 price feed ids" , async ( ) => {
1127
+ await deployContract ( ) ;
1128
+ await updateGuardianSets ( pythTest , deployer ) ;
1129
+
1130
+ const sentValue = toNano ( "1" ) ;
1131
+ const result = await pythTest . sendParsePriceFeedUpdates (
1132
+ deployer . getSender ( ) ,
1133
+ Buffer . from ( HERMES_SOL_TON_PYTH_USDT_UPDATE , "hex" ) ,
1134
+ sentValue ,
1135
+ [
1136
+ SOL_PRICE_FEED_ID ,
1137
+ TON_PRICE_FEED_ID ,
1138
+ PYTH_PRICE_FEED_ID ,
1139
+ USDT_PRICE_FEED_ID ,
1140
+ ] ,
1141
+ HERMES_SOL_UNIQUE_PUBLISH_TIME ,
1142
+ HERMES_SOL_UNIQUE_PUBLISH_TIME ,
1143
+ deployer . address ,
1144
+ CUSTOM_PAYLOAD ,
1145
+ ) ;
1146
+
1147
+ // Verify transaction success and message count
1148
+ expect ( result . transactions ) . toHaveTransaction ( {
1149
+ from : deployer . address ,
1150
+ to : pythTest . address ,
1151
+ success : true ,
1152
+ outMessagesCount : 1 ,
1153
+ } ) ;
1154
+
1155
+ // Get the output message
1156
+ const outMessage = result . transactions [ 1 ] . outMessages . values ( ) [ 0 ] ;
1157
+
1158
+ // Verify excess value is returned
1159
+ expect (
1160
+ ( outMessage . info as CommonMessageInfoInternal ) . value . coins ,
1161
+ ) . toBeGreaterThan ( 0 ) ;
1162
+
1163
+ const cs = outMessage . body . beginParse ( ) ;
1164
+
1165
+ // Verify message header
1166
+ const op = cs . loadUint ( 32 ) ;
1167
+ expect ( op ) . toBe ( 5 ) ; // OP_PARSE_PRICE_FEED_UPDATES
1168
+
1169
+ // Verify number of price feeds
1170
+ const numPriceFeeds = cs . loadUint ( 8 ) ;
1171
+ expect ( numPriceFeeds ) . toBe ( 4 ) ; // We expect SOL, TON, PYTH and USDT price feeds
1172
+
1173
+ // Load and verify price feeds
1174
+ const priceFeedsCell = cs . loadRef ( ) ;
1175
+ let currentCell = priceFeedsCell ;
1176
+
1177
+ // First price feed (SOL)
1178
+ const solCs = currentCell . beginParse ( ) ;
1179
+ const solPriceId =
1180
+ "0x" + solCs . loadUintBig ( 256 ) . toString ( 16 ) . padStart ( 64 , "0" ) ;
1181
+ expect ( solPriceId ) . toBe ( SOL_PRICE_FEED_ID ) ;
1182
+
1183
+ const solPriceFeedCell = solCs . loadRef ( ) ;
1184
+ const solPriceFeedSlice = solPriceFeedCell . beginParse ( ) ;
1185
+
1186
+ // Verify SOL current price
1187
+ const solCurrentPriceCell = solPriceFeedSlice . loadRef ( ) ;
1188
+ const solCurrentPrice = solCurrentPriceCell . beginParse ( ) ;
1189
+ expect ( solCurrentPrice . loadInt ( 64 ) ) . toBe ( HERMES_SOL_UNIQUE_PRICE ) ;
1190
+ expect ( solCurrentPrice . loadUint ( 64 ) ) . toBe ( HERMES_SOL_UNIQUE_CONF ) ;
1191
+ expect ( solCurrentPrice . loadInt ( 32 ) ) . toBe ( HERMES_SOL_UNIQUE_EXPO ) ;
1192
+ expect ( solCurrentPrice . loadUint ( 64 ) ) . toBe ( HERMES_SOL_UNIQUE_PUBLISH_TIME ) ;
1193
+
1194
+ // Move through TON and PYTH price feeds to reach USDT
1195
+ currentCell = solCs . loadRef ( ) ; // Move to TON
1196
+ const tonCs = currentCell . beginParse ( ) ;
1197
+ tonCs . loadUintBig ( 256 ) ; // Skip TON price ID
1198
+ tonCs . loadRef ( ) ; // Skip TON price data
1199
+
1200
+ currentCell = tonCs . loadRef ( ) ; // Move to PYTH
1201
+ const pythCs = currentCell . beginParse ( ) ;
1202
+ pythCs . loadUintBig ( 256 ) ; // Skip PYTH price ID
1203
+ pythCs . loadRef ( ) ; // Skip PYTH price data
1204
+
1205
+ currentCell = pythCs . loadRef ( ) ; // Move to USDT
1206
+ const usdtCs = currentCell . beginParse ( ) ;
1207
+ const usdtPriceId =
1208
+ "0x" + usdtCs . loadUintBig ( 256 ) . toString ( 16 ) . padStart ( 64 , "0" ) ;
1209
+ expect ( usdtPriceId ) . toBe ( USDT_PRICE_FEED_ID ) ;
1210
+
1211
+ const usdtPriceFeedCell = usdtCs . loadRef ( ) ;
1212
+ const usdtPriceFeedSlice = usdtPriceFeedCell . beginParse ( ) ;
1213
+
1214
+ // Verify USDT current price
1215
+ const usdtCurrentPriceCell = usdtPriceFeedSlice . loadRef ( ) ;
1216
+ const usdtCurrentPrice = usdtCurrentPriceCell . beginParse ( ) ;
1217
+ expect ( usdtCurrentPrice . loadInt ( 64 ) ) . toBe ( HERMES_USDT_UNIQUE_PRICE ) ;
1218
+ expect ( usdtCurrentPrice . loadUint ( 64 ) ) . toBe ( HERMES_USDT_UNIQUE_CONF ) ;
1219
+ expect ( usdtCurrentPrice . loadInt ( 32 ) ) . toBe ( HERMES_USDT_UNIQUE_EXPO ) ;
1220
+ expect ( usdtCurrentPrice . loadUint ( 64 ) ) . toBe ( HERMES_USDT_UNIQUE_PUBLISH_TIME ) ;
1221
+
1222
+ // Verify this is the end of the chain
1223
+ expect ( usdtCs . remainingRefs ) . toBe ( 0 ) ;
1224
+
1225
+ // Verify sender address
1226
+ const senderAddress = cs . loadAddress ( ) ;
1227
+ expect ( senderAddress ?. toString ( ) ) . toBe (
1228
+ deployer . getSender ( ) . address . toString ( ) ,
1229
+ ) ;
1230
+
1231
+ // Verify custom payload
1232
+ const customPayloadCell = cs . loadRef ( ) ;
1233
+ const customPayloadSlice = customPayloadCell . beginParse ( ) ;
1234
+ const receivedPayload = Buffer . from (
1235
+ customPayloadSlice . loadBuffer ( CUSTOM_PAYLOAD . length ) ,
1236
+ ) ;
1237
+ expect ( receivedPayload . toString ( "hex" ) ) . toBe (
1238
+ CUSTOM_PAYLOAD . toString ( "hex" ) ,
1239
+ ) ;
1240
+ } ) ;
1241
+
1113
1242
it ( "should successfully parse unique price feed updates" , async ( ) => {
1114
1243
await deployContract ( ) ;
1115
1244
await updateGuardianSets ( pythTest , deployer ) ;
@@ -1229,6 +1358,122 @@ describe("PythTest", () => {
1229
1358
) ;
1230
1359
} ) ;
1231
1360
1361
+ it ( "should successfully parse unique price feed updates with more than 3 price feed ids" , async ( ) => {
1362
+ await deployContract ( ) ;
1363
+ await updateGuardianSets ( pythTest , deployer ) ;
1364
+
1365
+ const sentValue = toNano ( "1" ) ;
1366
+ const result = await pythTest . sendParseUniquePriceFeedUpdates (
1367
+ deployer . getSender ( ) ,
1368
+ Buffer . from ( HERMES_SOL_TON_PYTH_USDT_UPDATE , "hex" ) ,
1369
+ sentValue ,
1370
+ [
1371
+ SOL_PRICE_FEED_ID ,
1372
+ TON_PRICE_FEED_ID ,
1373
+ PYTH_PRICE_FEED_ID ,
1374
+ USDT_PRICE_FEED_ID ,
1375
+ ] ,
1376
+ HERMES_SOL_UNIQUE_PUBLISH_TIME ,
1377
+ 60 ,
1378
+ deployer . address ,
1379
+ CUSTOM_PAYLOAD ,
1380
+ ) ;
1381
+
1382
+ // Verify transaction success and message count
1383
+ expect ( result . transactions ) . toHaveTransaction ( {
1384
+ from : deployer . address ,
1385
+ to : pythTest . address ,
1386
+ success : true ,
1387
+ outMessagesCount : 1 ,
1388
+ } ) ;
1389
+
1390
+ // Get the output message
1391
+ const outMessage = result . transactions [ 1 ] . outMessages . values ( ) [ 0 ] ;
1392
+
1393
+ // Verify excess value is returned
1394
+ expect (
1395
+ ( outMessage . info as CommonMessageInfoInternal ) . value . coins ,
1396
+ ) . toBeGreaterThan ( 0 ) ;
1397
+
1398
+ const cs = outMessage . body . beginParse ( ) ;
1399
+
1400
+ // Verify message header
1401
+ const op = cs . loadUint ( 32 ) ;
1402
+ expect ( op ) . toBe ( 6 ) ; // OP_PARSE_UNIQUE_PRICE_FEED_UPDATES
1403
+
1404
+ // Verify number of price feeds
1405
+ const numPriceFeeds = cs . loadUint ( 8 ) ;
1406
+ expect ( numPriceFeeds ) . toBe ( 4 ) ; // We expect SOL, TON, PYTH and USDT price feeds
1407
+
1408
+ // Load and verify price feeds
1409
+ const priceFeedsCell = cs . loadRef ( ) ;
1410
+ let currentCell = priceFeedsCell ;
1411
+
1412
+ // First price feed (SOL)
1413
+ const solCs = currentCell . beginParse ( ) ;
1414
+ const solPriceId =
1415
+ "0x" + solCs . loadUintBig ( 256 ) . toString ( 16 ) . padStart ( 64 , "0" ) ;
1416
+ expect ( solPriceId ) . toBe ( SOL_PRICE_FEED_ID ) ;
1417
+
1418
+ const solPriceFeedCell = solCs . loadRef ( ) ;
1419
+ const solPriceFeedSlice = solPriceFeedCell . beginParse ( ) ;
1420
+
1421
+ // Verify SOL current price
1422
+ const solCurrentPriceCell = solPriceFeedSlice . loadRef ( ) ;
1423
+ const solCurrentPrice = solCurrentPriceCell . beginParse ( ) ;
1424
+ expect ( solCurrentPrice . loadInt ( 64 ) ) . toBe ( HERMES_SOL_UNIQUE_PRICE ) ;
1425
+ expect ( solCurrentPrice . loadUint ( 64 ) ) . toBe ( HERMES_SOL_UNIQUE_CONF ) ;
1426
+ expect ( solCurrentPrice . loadInt ( 32 ) ) . toBe ( HERMES_SOL_UNIQUE_EXPO ) ;
1427
+ expect ( solCurrentPrice . loadUint ( 64 ) ) . toBe ( HERMES_SOL_UNIQUE_PUBLISH_TIME ) ;
1428
+
1429
+ // Move through TON and PYTH price feeds to reach USDT
1430
+ currentCell = solCs . loadRef ( ) ; // Move to TON
1431
+ const tonCs = currentCell . beginParse ( ) ;
1432
+ tonCs . loadUintBig ( 256 ) ; // Skip TON price ID
1433
+ tonCs . loadRef ( ) ; // Skip TON price data
1434
+
1435
+ currentCell = tonCs . loadRef ( ) ; // Move to PYTH
1436
+ const pythCs = currentCell . beginParse ( ) ;
1437
+ pythCs . loadUintBig ( 256 ) ; // Skip PYTH price ID
1438
+ pythCs . loadRef ( ) ; // Skip PYTH price data
1439
+
1440
+ currentCell = pythCs . loadRef ( ) ; // Move to USDT
1441
+ const usdtCs = currentCell . beginParse ( ) ;
1442
+ const usdtPriceId =
1443
+ "0x" + usdtCs . loadUintBig ( 256 ) . toString ( 16 ) . padStart ( 64 , "0" ) ;
1444
+ expect ( usdtPriceId ) . toBe ( USDT_PRICE_FEED_ID ) ;
1445
+
1446
+ const usdtPriceFeedCell = usdtCs . loadRef ( ) ;
1447
+ const usdtPriceFeedSlice = usdtPriceFeedCell . beginParse ( ) ;
1448
+
1449
+ // Verify USDT current price
1450
+ const usdtCurrentPriceCell = usdtPriceFeedSlice . loadRef ( ) ;
1451
+ const usdtCurrentPrice = usdtCurrentPriceCell . beginParse ( ) ;
1452
+ expect ( usdtCurrentPrice . loadInt ( 64 ) ) . toBe ( HERMES_USDT_UNIQUE_PRICE ) ;
1453
+ expect ( usdtCurrentPrice . loadUint ( 64 ) ) . toBe ( HERMES_USDT_UNIQUE_CONF ) ;
1454
+ expect ( usdtCurrentPrice . loadInt ( 32 ) ) . toBe ( HERMES_USDT_UNIQUE_EXPO ) ;
1455
+ expect ( usdtCurrentPrice . loadUint ( 64 ) ) . toBe ( HERMES_USDT_UNIQUE_PUBLISH_TIME ) ;
1456
+
1457
+ // Verify this is the end of the chain
1458
+ expect ( usdtCs . remainingRefs ) . toBe ( 0 ) ;
1459
+
1460
+ // Verify sender address
1461
+ const senderAddress = cs . loadAddress ( ) ;
1462
+ expect ( senderAddress ?. toString ( ) ) . toBe (
1463
+ deployer . getSender ( ) . address . toString ( ) ,
1464
+ ) ;
1465
+
1466
+ // Verify custom payload
1467
+ const customPayloadCell = cs . loadRef ( ) ;
1468
+ const customPayloadSlice = customPayloadCell . beginParse ( ) ;
1469
+ const receivedPayload = Buffer . from (
1470
+ customPayloadSlice . loadBuffer ( CUSTOM_PAYLOAD . length ) ,
1471
+ ) ;
1472
+ expect ( receivedPayload . toString ( "hex" ) ) . toBe (
1473
+ CUSTOM_PAYLOAD . toString ( "hex" ) ,
1474
+ ) ;
1475
+ } ) ;
1476
+
1232
1477
it ( "should fail to parse invalid price feed updates" , async ( ) => {
1233
1478
await deployContract ( ) ;
1234
1479
await updateGuardianSets ( pythTest , deployer ) ;
0 commit comments