@@ -21,12 +21,23 @@ contract GasBenchmark is Test, WormholeTestUtils, PythTestUtils {
21
21
// We use 5 prices to form a batch of 5 prices, close to our mainnet transactions.
22
22
uint8 constant NUM_PRICES = 5 ;
23
23
24
- uint constant BENCHMARK_ITERATIONS = 1000 ;
25
-
26
24
IPyth public pyth;
27
25
28
26
bytes32 [] priceIds;
29
- PythStructs.Price[] prices;
27
+
28
+ // Cached prices are populated in the setUp
29
+ PythStructs.Price[] cachedPrices;
30
+ bytes [] cachedPricesUpdateData;
31
+ uint cachedPricesUpdateFee;
32
+ uint64 [] cachedPricesPublishTimes;
33
+
34
+ // Fresh prices are different prices that can be used
35
+ // as a fresh price to update the prices
36
+ PythStructs.Price[] freshPrices;
37
+ bytes [] freshPricesUpdateData;
38
+ uint freshPricesUpdateFee;
39
+ uint64 [] freshPricesPublishTimes;
40
+
30
41
uint64 sequence;
31
42
uint randSeed;
32
43
@@ -40,29 +51,40 @@ contract GasBenchmark is Test, WormholeTestUtils, PythTestUtils {
40
51
}
41
52
42
53
for (uint i = 0 ; i < NUM_PRICES; ++ i) {
43
- prices.push (PythStructs.Price (
54
+
55
+ uint64 publishTime = uint64 (getRand () % 10 );
56
+
57
+ cachedPrices.push (PythStructs.Price (
58
+ int64 (uint64 (getRand () % 1000 )), // Price
59
+ uint64 (getRand () % 100 ), // Confidence
60
+ - 5 , // Expo
61
+ publishTime
62
+ ));
63
+ cachedPricesPublishTimes.push (publishTime);
64
+
65
+ publishTime += uint64 (getRand () % 10 );
66
+ freshPrices.push (PythStructs.Price (
44
67
int64 (uint64 (getRand () % 1000 )), // Price
45
68
uint64 (getRand () % 100 ), // Confidence
46
69
- 5 , // Expo
47
- getRand () % 10 // publishTime
70
+ publishTime
48
71
));
72
+ freshPricesPublishTimes.push (publishTime);
49
73
}
74
+
75
+ // Populate the contract with the initial prices
76
+ (cachedPricesUpdateData, cachedPricesUpdateFee) = generateUpdateDataAndFee (cachedPrices);
77
+ pyth.updatePriceFeeds {value: cachedPricesUpdateFee}(cachedPricesUpdateData);
78
+
79
+ (freshPricesUpdateData, freshPricesUpdateFee) = generateUpdateDataAndFee (freshPrices);
50
80
}
51
81
52
82
function getRand () internal returns (uint val ) {
53
83
++ randSeed;
54
84
val = uint (keccak256 (abi.encode (randSeed)));
55
85
}
56
86
57
- function advancePrices () internal {
58
- for (uint i = 0 ; i < NUM_PRICES; ++ i) {
59
- prices[i].price = int64 (uint64 (getRand () % 1000 ));
60
- prices[i].conf = uint64 (getRand () % 100 );
61
- prices[i].publishTime += getRand () % 10 ;
62
- }
63
- }
64
-
65
- function generateUpdateDataAndFee () internal returns (bytes [] memory updateData , uint updateFee ) {
87
+ function generateUpdateDataAndFee (PythStructs.Price[] memory prices ) internal returns (bytes [] memory updateData , uint updateFee ) {
66
88
bytes memory vaa = generatePriceFeedUpdateVAA (
67
89
priceIds,
68
90
prices,
@@ -79,68 +101,36 @@ contract GasBenchmark is Test, WormholeTestUtils, PythTestUtils {
79
101
}
80
102
81
103
function testBenchmarkUpdatePriceFeedsFresh () public {
82
- for (uint i = 0 ; i < BENCHMARK_ITERATIONS; ++ i) {
83
- advancePrices ();
84
-
85
- (bytes [] memory updateData , uint updateFee ) = generateUpdateDataAndFee ();
86
- pyth.updatePriceFeeds {value: updateFee}(updateData);
87
- }
104
+ pyth.updatePriceFeeds {value: freshPricesUpdateFee}(freshPricesUpdateData);
88
105
}
89
106
90
107
function testBenchmarkUpdatePriceFeedsNotFresh () public {
91
- for (uint i = 0 ; i < BENCHMARK_ITERATIONS; ++ i) {
92
- (bytes [] memory updateData , uint updateFee ) = generateUpdateDataAndFee ();
93
- pyth.updatePriceFeeds {value: updateFee}(updateData);
94
- }
108
+ pyth.updatePriceFeeds {value: cachedPricesUpdateFee}(cachedPricesUpdateData);
95
109
}
96
110
97
111
function testBenchmarkUpdatePriceFeedsIfNecessaryFresh () public {
98
- for (uint i = 0 ; i < BENCHMARK_ITERATIONS; ++ i) {
99
- advancePrices ();
100
-
101
- uint64 [] memory publishTimes = new uint64 [](NUM_PRICES);
102
-
103
- for (uint j = 0 ; j < NUM_PRICES; ++ j) {
104
- publishTimes[j] = uint64 (prices[j].publishTime);
105
- }
106
-
107
- (bytes [] memory updateData , uint updateFee ) = generateUpdateDataAndFee ();
108
-
109
- // Since the prices have advanced, the publishTimes are newer than one in
110
- // the contract and hence, the call should succeed.
111
- pyth.updatePriceFeedsIfNecessary {value: updateFee}(updateData, priceIds, publishTimes);
112
- }
112
+ // Since the prices have advanced, the publishTimes are newer than one in
113
+ // the contract and hence, the call should succeed.
114
+ pyth.updatePriceFeedsIfNecessary {value: freshPricesUpdateFee}(freshPricesUpdateData, priceIds, freshPricesPublishTimes);
113
115
}
114
116
115
117
function testBenchmarkUpdatePriceFeedsIfNecessaryNotFresh () public {
116
- for (uint i = 0 ; i < BENCHMARK_ITERATIONS; ++ i) {
117
- uint64 [] memory publishTimes = new uint64 [](NUM_PRICES);
118
-
119
- for (uint j = 0 ; j < NUM_PRICES; ++ j) {
120
- publishTimes[j] = uint64 (prices[j].publishTime);
121
- }
118
+ // Since the price is not advanced, the publishTimes are the same as the
119
+ // ones in the contract.
120
+ vm.expectRevert (bytes ("no prices in the submitted batch have fresh prices, so this update will have no effect " ));
122
121
123
- (bytes [] memory updateData , uint updateFee ) = generateUpdateDataAndFee ();
124
-
125
- // Since the price is not advanced, the publishTimes are the same as the
126
- // ones in the contract except the first update.
127
- if (i > 0 ) {
128
- vm.expectRevert (bytes ("no prices in the submitted batch have fresh prices, so this update will have no effect " ));
129
- }
130
-
131
- pyth.updatePriceFeedsIfNecessary {value: updateFee}(updateData, priceIds, publishTimes);
132
- }
122
+ pyth.updatePriceFeedsIfNecessary {value: cachedPricesUpdateFee}(cachedPricesUpdateData, priceIds, cachedPricesPublishTimes);
133
123
}
134
124
135
125
function testBenchmarkGetPrice () public {
136
- (bytes [] memory updateData , uint updateFee ) = generateUpdateDataAndFee ();
137
- pyth.updatePriceFeeds {value: updateFee}(updateData);
126
+ // Set the block timestamp to 0. As prices have < 10 timestamp and staleness
127
+ // is set to 60 seconds, the getPrice should work as expected.
128
+ vm.warp (0 );
138
129
139
- // Set the block timestamp to the publish time, so getPrice work as expected.
140
- vm. warp (prices[ 0 ].publishTime);
130
+ pyth. getPrice (priceIds[ 0 ]);
131
+ }
141
132
142
- for (uint i = 0 ; i < BENCHMARK_ITERATIONS; ++ i) {
143
- pyth.getPrice (priceIds[getRand () % NUM_PRICES]);
144
- }
133
+ function testBenchmarkGetUpdateFee () public view {
134
+ pyth.getUpdateFee (freshPricesUpdateData);
145
135
}
146
136
}
0 commit comments