Skip to content

Commit a0a205b

Browse files
committed
feat(pyth): update getTwapUpdateFee to accept updateData and calculate fees based on the number of updates
1 parent 4891ad2 commit a0a205b

File tree

7 files changed

+68
-21
lines changed

7 files changed

+68
-21
lines changed

target_chains/ethereum/contracts/contracts/pyth/Pyth.sol

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,35 @@ abstract contract Pyth is
120120
return getTotalFee(totalNumUpdates);
121121
}
122122

123-
function getTwapUpdateFee() public view override returns (uint feeAmount) {
124-
// In the accumulator update data a single update can contain
125-
// up to 255 messages and we charge a singleUpdateFee per each
126-
// message
127-
return singleUpdateFeeInWei() + transactionFeeInWei();
123+
function getTwapUpdateFee(
124+
bytes[] calldata updateData
125+
) public view override returns (uint feeAmount) {
126+
uint totalNumUpdates = 0;
127+
// For TWAP updates, updateData is always length 2 (start and end points),
128+
// but each VAA can contain multiple price feeds. We only need to count
129+
// the number of updates in the first VAA since both VAAs will have the
130+
// same number of price feeds.
131+
if (
132+
updateData[0].length > 4 &&
133+
UnsafeCalldataBytesLib.toUint32(updateData[0], 0) ==
134+
ACCUMULATOR_MAGIC
135+
) {
136+
(
137+
uint offset,
138+
UpdateType updateType
139+
) = extractUpdateTypeFromAccumulatorHeader(updateData[0]);
140+
if (updateType != UpdateType.WormholeMerkle) {
141+
revert PythErrors.InvalidUpdateData();
142+
}
143+
totalNumUpdates += parseWormholeMerkleHeaderNumUpdates(
144+
updateData[0],
145+
offset
146+
);
147+
} else {
148+
revert PythErrors.InvalidUpdateData();
149+
}
150+
151+
return getTotalFee(totalNumUpdates);
128152
}
129153

130154
// This is an overwrite of the same method in AbstractPyth.sol
@@ -461,7 +485,7 @@ abstract contract Pyth is
461485
revert PythErrors.InvalidUpdateData();
462486
}
463487

464-
uint requiredFee = getTwapUpdateFee();
488+
uint requiredFee = getTwapUpdateFee(updateData);
465489
if (msg.value < requiredFee) revert PythErrors.InsufficientFee();
466490

467491
// Process start update data

target_chains/ethereum/contracts/forge-test/Pyth.t.sol

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils {
533533
)
534534
);
535535

536-
uint updateFee = pyth.getTwapUpdateFee();
536+
uint updateFee = pyth.getTwapUpdateFee(updateData);
537537

538538
// Parse the TWAP updates
539539
PythStructs.TwapPriceFeed[] memory twapPriceFeeds = pyth
@@ -613,7 +613,7 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils {
613613
)
614614
);
615615

616-
uint updateFee = pyth.getTwapUpdateFee();
616+
uint updateFee = pyth.getTwapUpdateFee(updateData);
617617

618618
vm.expectRevert(PythErrors.InvalidTwapUpdateDataSet.selector);
619619
pyth.parseTwapPriceFeedUpdates{value: updateFee}(updateData, priceIds);
@@ -664,7 +664,7 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils {
664664
)
665665
);
666666

667-
uint updateFee = pyth.getTwapUpdateFee();
667+
uint updateFee = pyth.getTwapUpdateFee(updateData);
668668

669669
vm.expectRevert(PythErrors.InvalidTwapUpdateDataSet.selector);
670670
pyth.parseTwapPriceFeedUpdates{value: updateFee}(updateData, priceIds);
@@ -711,7 +711,7 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils {
711711
)
712712
);
713713

714-
uint updateFee = pyth.getTwapUpdateFee();
714+
uint updateFee = pyth.getTwapUpdateFee(updateData);
715715

716716
vm.expectRevert(PythErrors.InvalidTwapUpdateDataSet.selector);
717717
pyth.parseTwapPriceFeedUpdates{value: updateFee}(updateData, priceIds);
@@ -758,7 +758,7 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils {
758758
)
759759
);
760760

761-
uint updateFee = pyth.getTwapUpdateFee();
761+
uint updateFee = pyth.getTwapUpdateFee(updateData);
762762

763763
vm.expectRevert(PythErrors.InvalidTwapUpdateData.selector);
764764
pyth.parseTwapPriceFeedUpdates{value: updateFee}(updateData, priceIds);
@@ -800,7 +800,7 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils {
800800
)
801801
);
802802

803-
uint updateFee = pyth.getTwapUpdateFee();
803+
uint updateFee = pyth.getTwapUpdateFee(updateData);
804804

805805
vm.expectRevert(PythErrors.InsufficientFee.selector);
806806
pyth.parseTwapPriceFeedUpdates{value: updateFee - 1}(
@@ -849,7 +849,7 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils {
849849
config
850850
);
851851

852-
uint updateFee = pyth.getTwapUpdateFee();
852+
uint updateFee = pyth.getTwapUpdateFee(updateData);
853853

854854
// Parse the TWAP updates
855855
PythStructs.TwapPriceFeed[] memory twapPriceFeeds = pyth
@@ -924,7 +924,7 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils {
924924
config
925925
);
926926

927-
uint updateFee = pyth.getTwapUpdateFee();
927+
uint updateFee = pyth.getTwapUpdateFee(updateData);
928928

929929
vm.expectRevert(PythErrors.InvalidUpdateData.selector);
930930
pyth.parseTwapPriceFeedUpdates{value: updateFee}(updateData, priceIds);
@@ -976,7 +976,7 @@ contract PythTest is Test, WormholeTestUtils, PythTestUtils {
976976
config
977977
);
978978

979-
uint updateFee = pyth.getTwapUpdateFee();
979+
uint updateFee = pyth.getTwapUpdateFee(updateData);
980980

981981
// Should revert because one of the requested price IDs is not found in the updates
982982
vm.expectRevert(PythErrors.PriceFeedNotFoundWithinRange.selector);

target_chains/ethereum/sdk/solidity/IPyth.sol

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,11 @@ interface IPyth is IPythEvents {
9595
) external view returns (uint feeAmount);
9696

9797
/// @notice Returns the required fee to update a TWAP price.
98+
/// @param updateData Array of price update data.
9899
/// @return feeAmount The required fee in Wei.
99-
function getTwapUpdateFee() external view returns (uint feeAmount);
100+
function getTwapUpdateFee(
101+
bytes[] calldata updateData
102+
) external view returns (uint feeAmount);
100103

101104
/// @notice Parse `updateData` and return price feeds of the given `priceIds` if they are all published
102105
/// within `minPublishTime` and `maxPublishTime`.

target_chains/ethereum/sdk/solidity/MockPyth.sol

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,10 @@ contract MockPyth is AbstractPyth {
8080
return singleUpdateFeeInWei * updateData.length;
8181
}
8282

83-
function getTwapUpdateFee() public view override returns (uint feeAmount) {
84-
return singleUpdateFeeInWei;
83+
function getTwapUpdateFee(
84+
bytes[] calldata updateData
85+
) public view override returns (uint feeAmount) {
86+
return singleUpdateFeeInWei * updateData.length;
8587
}
8688

8789
function parsePriceFeedUpdatesInternal(

target_chains/ethereum/sdk/solidity/abis/AbstractPyth.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,13 @@
345345
"type": "function"
346346
},
347347
{
348-
"inputs": [],
348+
"inputs": [
349+
{
350+
"internalType": "bytes[]",
351+
"name": "updateData",
352+
"type": "bytes[]"
353+
}
354+
],
349355
"name": "getTwapUpdateFee",
350356
"outputs": [
351357
{

target_chains/ethereum/sdk/solidity/abis/IPyth.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,13 @@
248248
"type": "function"
249249
},
250250
{
251-
"inputs": [],
251+
"inputs": [
252+
{
253+
"internalType": "bytes[]",
254+
"name": "updateData",
255+
"type": "bytes[]"
256+
}
257+
],
252258
"name": "getTwapUpdateFee",
253259
"outputs": [
254260
{

target_chains/ethereum/sdk/solidity/abis/MockPyth.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,13 @@
484484
"type": "function"
485485
},
486486
{
487-
"inputs": [],
487+
"inputs": [
488+
{
489+
"internalType": "bytes[]",
490+
"name": "updateData",
491+
"type": "bytes[]"
492+
}
493+
],
488494
"name": "getTwapUpdateFee",
489495
"outputs": [
490496
{

0 commit comments

Comments
 (0)