|
|
@@ -133,75 +133,6 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- function testParsePriceFeedUpdatesWorksWithRandomDistinctUpdatesInput(
|
|
|
- uint seed
|
|
|
- ) public {
|
|
|
- setRandSeed(seed);
|
|
|
- uint numMessages = 1 + (getRandUint() % 30);
|
|
|
- (
|
|
|
- bytes32[] memory priceIds,
|
|
|
- PriceFeedMessage[] memory messages
|
|
|
- ) = generateRandomPriceMessages(numMessages);
|
|
|
-
|
|
|
- (
|
|
|
- bytes[] memory updateData,
|
|
|
- uint updateFee
|
|
|
- ) = createBatchedUpdateDataFromMessages(messages);
|
|
|
-
|
|
|
- // Shuffle the messages
|
|
|
- for (uint i = 1; i < numMessages; i++) {
|
|
|
- uint swapWith = getRandUint() % (i + 1);
|
|
|
- (messages[i], messages[swapWith]) = (
|
|
|
- messages[swapWith],
|
|
|
- messages[i]
|
|
|
- );
|
|
|
- (priceIds[i], priceIds[swapWith]) = (
|
|
|
- priceIds[swapWith],
|
|
|
- priceIds[i]
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- // Select only first numSelectedMessages. numSelectedMessages will be in [0, numMessages]
|
|
|
- uint numSelectedMessages = getRandUint() % (numMessages + 1);
|
|
|
-
|
|
|
- PriceFeedMessage[] memory selectedMessages = new PriceFeedMessage[](
|
|
|
- numSelectedMessages
|
|
|
- );
|
|
|
- bytes32[] memory selectedPriceIds = new bytes32[](numSelectedMessages);
|
|
|
-
|
|
|
- for (uint i = 0; i < numSelectedMessages; i++) {
|
|
|
- selectedMessages[i] = messages[i];
|
|
|
- selectedPriceIds[i] = priceIds[i];
|
|
|
- }
|
|
|
-
|
|
|
- // Only parse selected messages
|
|
|
- PythStructs.PriceFeed[] memory priceFeeds = pyth.parsePriceFeedUpdates{
|
|
|
- value: updateFee
|
|
|
- }(updateData, selectedPriceIds, 0, MAX_UINT64);
|
|
|
-
|
|
|
- for (uint i = 0; i < numSelectedMessages; i++) {
|
|
|
- assertEq(priceFeeds[i].id, selectedPriceIds[i]);
|
|
|
- assertEq(priceFeeds[i].price.expo, selectedMessages[i].expo);
|
|
|
- assertEq(
|
|
|
- priceFeeds[i].emaPrice.price,
|
|
|
- selectedMessages[i].emaPrice
|
|
|
- );
|
|
|
- assertEq(priceFeeds[i].emaPrice.conf, selectedMessages[i].emaConf);
|
|
|
- assertEq(priceFeeds[i].emaPrice.expo, selectedMessages[i].expo);
|
|
|
-
|
|
|
- assertEq(priceFeeds[i].price.price, selectedMessages[i].price);
|
|
|
- assertEq(priceFeeds[i].price.conf, selectedMessages[i].conf);
|
|
|
- assertEq(
|
|
|
- priceFeeds[i].price.publishTime,
|
|
|
- selectedMessages[i].publishTime
|
|
|
- );
|
|
|
- assertEq(
|
|
|
- priceFeeds[i].emaPrice.publishTime,
|
|
|
- selectedMessages[i].publishTime
|
|
|
- );
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
function testParsePriceFeedUpdatesWorksWithOverlappingWithinTimeRangeUpdates()
|
|
|
public
|
|
|
{
|
|
|
@@ -281,31 +212,6 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils {
|
|
|
assertEq(priceFeeds[0].price.publishTime, 20);
|
|
|
}
|
|
|
|
|
|
- function testParsePriceFeedUpdatesRevertsIfUpdateFeeIsNotPaid() public {
|
|
|
- uint numMessages = 10;
|
|
|
- (
|
|
|
- bytes32[] memory priceIds,
|
|
|
- PriceFeedMessage[] memory messages
|
|
|
- ) = generateRandomPriceMessages(numMessages);
|
|
|
-
|
|
|
- (
|
|
|
- bytes[] memory updateData,
|
|
|
- uint updateFee
|
|
|
- ) = createBatchedUpdateDataFromMessages(messages);
|
|
|
-
|
|
|
- // Since messages are not empty the fee should be at least 1
|
|
|
- assertGe(updateFee, 1);
|
|
|
-
|
|
|
- vm.expectRevert(PythErrors.InsufficientFee.selector);
|
|
|
-
|
|
|
- pyth.parsePriceFeedUpdates{value: updateFee - 1}(
|
|
|
- updateData,
|
|
|
- priceIds,
|
|
|
- 0,
|
|
|
- MAX_UINT64
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
function testParsePriceFeedUpdatesRevertsIfUpdateVAAIsInvalid(
|
|
|
uint seed
|
|
|
) public {
|
|
|
@@ -400,131 +306,4 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils {
|
|
|
MAX_UINT64
|
|
|
);
|
|
|
}
|
|
|
-
|
|
|
- function testParsePriceFeedUpdatesRevertsIfPriceIdNotIncluded() public {
|
|
|
- PriceFeedMessage[] memory messages = new PriceFeedMessage[](1);
|
|
|
-
|
|
|
- messages[0].priceId = bytes32(uint(1));
|
|
|
- messages[0].price = 1000;
|
|
|
- messages[0].publishTime = 10;
|
|
|
-
|
|
|
- (
|
|
|
- bytes[] memory updateData,
|
|
|
- uint updateFee
|
|
|
- ) = createBatchedUpdateDataFromMessages(messages);
|
|
|
-
|
|
|
- bytes32[] memory priceIds = new bytes32[](1);
|
|
|
- priceIds[0] = bytes32(uint(2));
|
|
|
-
|
|
|
- vm.expectRevert(PythErrors.PriceFeedNotFoundWithinRange.selector);
|
|
|
- pyth.parsePriceFeedUpdates{value: updateFee}(
|
|
|
- updateData,
|
|
|
- priceIds,
|
|
|
- 0,
|
|
|
- MAX_UINT64
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- function testParsePriceFeedUpdateRevertsIfPricesOutOfTimeRange() public {
|
|
|
- uint numMessages = 10;
|
|
|
- (
|
|
|
- bytes32[] memory priceIds,
|
|
|
- PriceFeedMessage[] memory messages
|
|
|
- ) = generateRandomPriceMessages(numMessages);
|
|
|
-
|
|
|
- for (uint i = 0; i < numMessages; i++) {
|
|
|
- messages[i].publishTime = uint64(100 + (getRandUint() % 101)); // All between [100, 200]
|
|
|
- }
|
|
|
-
|
|
|
- (
|
|
|
- bytes[] memory updateData,
|
|
|
- uint updateFee
|
|
|
- ) = createBatchedUpdateDataFromMessages(messages);
|
|
|
-
|
|
|
- // Request for parse within the given time range should work
|
|
|
- pyth.parsePriceFeedUpdates{value: updateFee}(
|
|
|
- updateData,
|
|
|
- priceIds,
|
|
|
- 100,
|
|
|
- 200
|
|
|
- );
|
|
|
-
|
|
|
- // Request for parse after the time range should revert.
|
|
|
- vm.expectRevert(PythErrors.PriceFeedNotFoundWithinRange.selector);
|
|
|
- pyth.parsePriceFeedUpdates{value: updateFee}(
|
|
|
- updateData,
|
|
|
- priceIds,
|
|
|
- 300,
|
|
|
- MAX_UINT64
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- function testParsePriceFeedUpdatesLatestPriceIfNecessary() public {
|
|
|
- uint numMessages = 10;
|
|
|
- (
|
|
|
- bytes32[] memory priceIds,
|
|
|
- PriceFeedMessage[] memory messages
|
|
|
- ) = generateRandomPriceMessages(numMessages);
|
|
|
-
|
|
|
- for (uint i = 0; i < numMessages; i++) {
|
|
|
- messages[i].publishTime = uint64((getRandUint() % 101)); // All between [0, 100]
|
|
|
- }
|
|
|
-
|
|
|
- (
|
|
|
- bytes[] memory updateData,
|
|
|
- uint updateFee
|
|
|
- ) = createBatchedUpdateDataFromMessages(messages);
|
|
|
-
|
|
|
- // Request for parse within the given time range should work and update the latest price
|
|
|
- pyth.parsePriceFeedUpdates{value: updateFee}(
|
|
|
- updateData,
|
|
|
- priceIds,
|
|
|
- 0,
|
|
|
- 100
|
|
|
- );
|
|
|
-
|
|
|
- // Check if the latest price is updated
|
|
|
- for (uint i = 0; i < numMessages; i++) {
|
|
|
- assertEq(
|
|
|
- pyth.getPriceUnsafe(priceIds[i]).publishTime,
|
|
|
- messages[i].publishTime
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- for (uint i = 0; i < numMessages; i++) {
|
|
|
- messages[i].publishTime = uint64(100 + (getRandUint() % 101)); // All between [100, 200]
|
|
|
- }
|
|
|
-
|
|
|
- (updateData, updateFee) = createBatchedUpdateDataFromMessages(messages);
|
|
|
-
|
|
|
- // Request for parse after the time range should revert.
|
|
|
- vm.expectRevert(PythErrors.PriceFeedNotFoundWithinRange.selector);
|
|
|
- pyth.parsePriceFeedUpdates{value: updateFee}(
|
|
|
- updateData,
|
|
|
- priceIds,
|
|
|
- 300,
|
|
|
- 400
|
|
|
- );
|
|
|
-
|
|
|
- // parse function reverted so publishTimes should remain less than or equal to 100
|
|
|
- for (uint i = 0; i < numMessages; i++) {
|
|
|
- assertGe(100, pyth.getPriceUnsafe(priceIds[i]).publishTime);
|
|
|
- }
|
|
|
-
|
|
|
- // Time range is now fixed, so parse should work and update the latest price
|
|
|
- pyth.parsePriceFeedUpdates{value: updateFee}(
|
|
|
- updateData,
|
|
|
- priceIds,
|
|
|
- 100,
|
|
|
- 200
|
|
|
- );
|
|
|
-
|
|
|
- // Check if the latest price is updated
|
|
|
- for (uint i = 0; i < numMessages; i++) {
|
|
|
- assertEq(
|
|
|
- pyth.getPriceUnsafe(priceIds[i]).publishTime,
|
|
|
- messages[i].publishTime
|
|
|
- );
|
|
|
- }
|
|
|
- }
|
|
|
}
|