소스 검색

feat(pulse): improve gas benchmark with variable feed ID counts

Co-Authored-By: Tejas Badadare <tejas@dourolabs.xyz>
Devin AI 8 달 전
부모
커밋
5a37de4c9a

+ 57 - 0
target_chains/ethereum/contracts/forge-test/PulseGasBenchmark.t.sol

@@ -66,6 +66,38 @@ contract PulseGasBenchmark is Test, PulseTestUtils {
         createMockUpdateData(priceFeeds);
     }
 
+    // Helper function to run the benchmark with a specified number of price feeds
+    function runBenchmarkWithFeedCount(uint8 feedCount) internal {
+        uint64 timestamp = SafeCast.toUint64(block.timestamp);
+        bytes32[] memory priceIds = createPriceIds(feedCount);
+
+        uint128 callbackGasLimit = 100000;
+        uint128 totalFee = pulse.getFee(
+            defaultProvider,
+            callbackGasLimit,
+            priceIds
+        );
+        vm.deal(address(consumer), 1 ether);
+        vm.prank(address(consumer));
+        uint64 sequenceNumber = pulse.requestPriceUpdatesWithCallback{
+            value: totalFee
+        }(defaultProvider, timestamp, priceIds, callbackGasLimit);
+
+        PythStructs.PriceFeed[] memory priceFeeds = createMockPriceFeeds(
+            timestamp,
+            priceIds
+        );
+        mockParsePriceFeedUpdates(pyth, priceFeeds);
+        bytes[] memory updateData = createMockUpdateData(priceFeeds);
+
+        pulse.executeCallback(
+            defaultProvider,
+            sequenceNumber,
+            updateData,
+            priceIds
+        );
+    }
+
     function testBasicFlow() public {
         uint64 timestamp = SafeCast.toUint64(block.timestamp);
         bytes32[] memory priceIds = createPriceIds();
@@ -95,6 +127,31 @@ contract PulseGasBenchmark is Test, PulseTestUtils {
             priceIds
         );
     }
+
+    // Benchmark with 1 price feed
+    function testBenchmarkWithOneFeed() public {
+        runBenchmarkWithFeedCount(1);
+    }
+
+    // Benchmark with 2 price feeds
+    function testBenchmarkWithTwoFeeds() public {
+        runBenchmarkWithFeedCount(2);
+    }
+
+    // Benchmark with 4 price feeds
+    function testBenchmarkWithFourFeeds() public {
+        runBenchmarkWithFeedCount(4);
+    }
+
+    // Benchmark with 8 price feeds
+    function testBenchmarkWithEightFeeds() public {
+        runBenchmarkWithFeedCount(8);
+    }
+
+    // Benchmark with 10 price feeds (maximum)
+    function testBenchmarkWithTenFeeds() public {
+        runBenchmarkWithFeedCount(10);
+    }
 }
 
 // A simple consumer that does nothing with the price updates.

+ 51 - 18
target_chains/ethereum/contracts/forge-test/utils/PulseTestUtils.t.sol

@@ -27,31 +27,63 @@ abstract contract PulseTestUtils is Test {
 
     // Helper function to create price IDs array
     function createPriceIds() internal pure returns (bytes32[] memory) {
-        bytes32[] memory priceIds = new bytes32[](2);
-        priceIds[0] = BTC_PRICE_FEED_ID;
-        priceIds[1] = ETH_PRICE_FEED_ID;
+        return createPriceIds(2);
+    }
+
+    // Helper function to create price IDs array with specified count
+    function createPriceIds(uint8 count) internal pure returns (bytes32[] memory) {
+        bytes32[] memory priceIds = new bytes32[](count);
+        
+        // Always use real price feed IDs for the first two if available
+        if (count >= 1) {
+            priceIds[0] = BTC_PRICE_FEED_ID;
+        }
+        if (count >= 2) {
+            priceIds[1] = ETH_PRICE_FEED_ID;
+        }
+        
+        // For additional IDs, generate synthetic ones based on the index
+        for (uint8 i = 2; i < count; i++) {
+            priceIds[i] = bytes32(uint256(keccak256(abi.encodePacked(i))));
+        }
+        
         return priceIds;
     }
 
     // Helper function to create mock price feeds
     function createMockPriceFeeds(
         uint256 publishTime
+    ) internal pure returns (PythStructs.PriceFeed[] memory) {
+        bytes32[] memory priceIds = createPriceIds();
+        return createMockPriceFeeds(publishTime, priceIds);
+    }
+
+    // Helper function to create mock price feeds for specific priceIds
+    function createMockPriceFeeds(
+        uint256 publishTime,
+        bytes32[] memory priceIds
     ) internal pure returns (PythStructs.PriceFeed[] memory) {
         PythStructs.PriceFeed[] memory priceFeeds = new PythStructs.PriceFeed[](
-            2
+            priceIds.length
         );
 
-        priceFeeds[0].id = BTC_PRICE_FEED_ID;
-        priceFeeds[0].price.price = MOCK_BTC_PRICE;
-        priceFeeds[0].price.conf = MOCK_BTC_CONF;
-        priceFeeds[0].price.expo = MOCK_PRICE_FEED_EXPO;
-        priceFeeds[0].price.publishTime = publishTime;
-
-        priceFeeds[1].id = ETH_PRICE_FEED_ID;
-        priceFeeds[1].price.price = MOCK_ETH_PRICE;
-        priceFeeds[1].price.conf = MOCK_ETH_CONF;
-        priceFeeds[1].price.expo = MOCK_PRICE_FEED_EXPO;
-        priceFeeds[1].price.publishTime = publishTime;
+        for (uint i = 0; i < priceIds.length; i++) {
+            priceFeeds[i].id = priceIds[i];
+            // Use BTC price for index 0, ETH price for index 1, and a synthetic price for others
+            if (i == 0) {
+                priceFeeds[i].price.price = MOCK_BTC_PRICE;
+                priceFeeds[i].price.conf = MOCK_BTC_CONF;
+            } else if (i == 1) {
+                priceFeeds[i].price.price = MOCK_ETH_PRICE;
+                priceFeeds[i].price.conf = MOCK_ETH_CONF;
+            } else {
+                // For additional feeds, use a price derived from the index
+                priceFeeds[i].price.price = int64(uint64(1_000_000_000_000 + (i * 100_000_000_000)));
+                priceFeeds[i].price.conf = uint64(1_000_000_000 + (i * 100_000_000));
+            }
+            priceFeeds[i].price.expo = MOCK_PRICE_FEED_EXPO;
+            priceFeeds[i].price.publishTime = publishTime;
+        }
 
         return priceFeeds;
     }
@@ -81,9 +113,10 @@ abstract contract PulseTestUtils is Test {
     function createMockUpdateData(
         PythStructs.PriceFeed[] memory priceFeeds
     ) internal pure returns (bytes[] memory) {
-        bytes[] memory updateData = new bytes[](2);
-        updateData[0] = abi.encode(priceFeeds[0]);
-        updateData[1] = abi.encode(priceFeeds[1]);
+        bytes[] memory updateData = new bytes[](priceFeeds.length);
+        for (uint i = 0; i < priceFeeds.length; i++) {
+            updateData[i] = abi.encode(priceFeeds[i]);
+        }
         return updateData;
     }