From 781639d5732e16d60ebae5ce8f282b069c6070a4 Mon Sep 17 00:00:00 2001 From: Daniel Chew Date: Fri, 11 Apr 2025 14:07:28 +0900 Subject: [PATCH 1/2] feat: add support for custom update fees --- .../ethereum/contracts/contracts/pyth/Pyth.sol | 12 ++++++++++-- .../contracts/contracts/pyth/PythGetters.sol | 4 ++++ .../contracts/contracts/pyth/PythGovernance.sol | 13 +++++++++++++ .../contracts/contracts/pyth/PythSetters.sol | 5 +++++ .../ethereum/contracts/contracts/pyth/PythState.sol | 2 ++ 5 files changed, 34 insertions(+), 2 deletions(-) diff --git a/target_chains/ethereum/contracts/contracts/pyth/Pyth.sol b/target_chains/ethereum/contracts/contracts/pyth/Pyth.sol index dbc2be966c..f7dcf12384 100644 --- a/target_chains/ethereum/contracts/contracts/pyth/Pyth.sol +++ b/target_chains/ethereum/contracts/contracts/pyth/Pyth.sol @@ -493,8 +493,11 @@ abstract contract Pyth is function getTotalFee( uint totalNumUpdates ) private view returns (uint requiredFee) { - return - (totalNumUpdates * singleUpdateFeeInWei()) + transactionFeeInWei(); + uint updateFee = customUpdateFeeInWei(msg.sender); + if (updateFee == 0) { + updateFee = singleUpdateFeeInWei(); + } + return (totalNumUpdates * updateFee) + transactionFeeInWei(); } function findIndexOfPriceId( @@ -559,6 +562,11 @@ abstract contract Pyth is return "1.4.4-alpha.2"; } + // @dev Only for testing gas benchmarks + function setCustomFeeForAddress(address addr, uint fee) public { + setCustomUpdateFeeInWei(addr, fee); + } + function calculateTwap( bytes32 priceId, PythStructs.TwapPriceInfo memory twapPriceInfoStart, diff --git a/target_chains/ethereum/contracts/contracts/pyth/PythGetters.sol b/target_chains/ethereum/contracts/contracts/pyth/PythGetters.sol index e0146da190..d7458326b2 100644 --- a/target_chains/ethereum/contracts/contracts/pyth/PythGetters.sol +++ b/target_chains/ethereum/contracts/contracts/pyth/PythGetters.sol @@ -95,4 +95,8 @@ contract PythGetters is PythState { function transactionFeeInWei() public view returns (uint) { return _state.transactionFeeInWei; } + + function customUpdateFeeInWei(address addr) public view returns (uint) { + return _state.customUpdateFeeInWei[addr]; + } } diff --git a/target_chains/ethereum/contracts/contracts/pyth/PythGovernance.sol b/target_chains/ethereum/contracts/contracts/pyth/PythGovernance.sol index 5bb1bd3265..13bc39f5e2 100644 --- a/target_chains/ethereum/contracts/contracts/pyth/PythGovernance.sol +++ b/target_chains/ethereum/contracts/contracts/pyth/PythGovernance.sol @@ -39,6 +39,12 @@ abstract contract PythGovernance is address newWormholeAddress ); event TransactionFeeSet(uint oldFee, uint newFee); + event CustomFeeSet(address indexed target, uint oldFee, uint newFee); + + struct SetCustomFeePayload { + address target; + uint newFee; + } function verifyGovernanceVM( bytes memory encodedVM @@ -255,4 +261,11 @@ abstract contract PythGovernance is emit TransactionFeeSet(oldFee, transactionFeeInWei()); } + + function setCustomFee(SetCustomFeePayload memory payload) internal { + uint oldFee = customUpdateFeeInWei(payload.target); + setCustomUpdateFeeInWei(payload.target, payload.newFee); + + emit CustomFeeSet(payload.target, oldFee, payload.newFee); + } } diff --git a/target_chains/ethereum/contracts/contracts/pyth/PythSetters.sol b/target_chains/ethereum/contracts/contracts/pyth/PythSetters.sol index 849fc7659f..4fbb0ea15f 100644 --- a/target_chains/ethereum/contracts/contracts/pyth/PythSetters.sol +++ b/target_chains/ethereum/contracts/contracts/pyth/PythSetters.sol @@ -5,6 +5,7 @@ pragma solidity ^0.8.0; import "./PythState.sol"; import "@pythnetwork/pyth-sdk-solidity/IPythEvents.sol"; +import "./PythInternalStructs.sol"; contract PythSetters is PythState, IPythEvents { function setWormhole(address wh) internal { @@ -52,4 +53,8 @@ contract PythSetters is PythState, IPythEvents { function setTransactionFeeInWei(uint fee) internal { _state.transactionFeeInWei = fee; } + + function setCustomUpdateFeeInWei(address addr, uint fee) internal { + _state.customUpdateFeeInWei[addr] = fee; + } } diff --git a/target_chains/ethereum/contracts/contracts/pyth/PythState.sol b/target_chains/ethereum/contracts/contracts/pyth/PythState.sol index a860a4341b..b5a197626d 100644 --- a/target_chains/ethereum/contracts/contracts/pyth/PythState.sol +++ b/target_chains/ethereum/contracts/contracts/pyth/PythState.sol @@ -40,6 +40,8 @@ contract PythStorage { mapping(bytes32 => PythInternalStructs.PriceInfo) latestPriceInfo; // Fee charged per transaction, in addition to per-update fees uint transactionFeeInWei; + // Mapping of address to custom fee per update (0 means use default fee) + mapping(address => uint) customUpdateFeeInWei; } } From 5f7ca651e587a95179f98f838d5cb41713c437e9 Mon Sep 17 00:00:00 2001 From: Daniel Chew Date: Fri, 11 Apr 2025 14:15:53 +0900 Subject: [PATCH 2/2] refactor: remove setCustomFeeForAddress function from Pyth contract --- target_chains/ethereum/contracts/contracts/pyth/Pyth.sol | 5 ----- 1 file changed, 5 deletions(-) diff --git a/target_chains/ethereum/contracts/contracts/pyth/Pyth.sol b/target_chains/ethereum/contracts/contracts/pyth/Pyth.sol index f7dcf12384..f97b7bda89 100644 --- a/target_chains/ethereum/contracts/contracts/pyth/Pyth.sol +++ b/target_chains/ethereum/contracts/contracts/pyth/Pyth.sol @@ -562,11 +562,6 @@ abstract contract Pyth is return "1.4.4-alpha.2"; } - // @dev Only for testing gas benchmarks - function setCustomFeeForAddress(address addr, uint fee) public { - setCustomUpdateFeeInWei(addr, fee); - } - function calculateTwap( bytes32 priceId, PythStructs.TwapPriceInfo memory twapPriceInfoStart,