-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
200 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity ^0.8.0; | ||
|
||
import "./IWormhole.sol"; | ||
|
||
/// @title Consume prices from the Pyth Network (https://pyth.network/). | ||
/// @dev Please refer to the guidance at https://docs.pyth.network/documentation/pythnet-price-feeds/best-practices for how to consume prices safely. | ||
/// @author Pyth Data Association | ||
interface IPyth { | ||
function wormhole() external view returns (IWormhole); | ||
|
||
function singleUpdateFeeInWei() external view returns (uint); | ||
|
||
/// @notice Update price feeds with given update messages. | ||
/// This method requires the caller to pay a fee in wei; the required fee can be computed by calling | ||
/// `getUpdateFee` with the length of the `updateData` array. | ||
/// Prices will be updated if they are more recent than the current stored prices. | ||
/// The call will succeed even if the update is not the most recent. | ||
/// @dev Reverts if the transferred fee is not sufficient or the updateData is invalid. | ||
/// @param updateData Array of price update data. | ||
function updatePriceFeeds(bytes[] calldata updateData) external payable; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
// contracts/Messages.sol | ||
// SPDX-License-Identifier: Apache 2 | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
interface IWormhole { | ||
struct GuardianSet { | ||
address[] keys; | ||
uint32 expirationTime; | ||
} | ||
|
||
struct Signature { | ||
bytes32 r; | ||
bytes32 s; | ||
uint8 v; | ||
uint8 guardianIndex; | ||
} | ||
|
||
struct VM { | ||
uint8 version; | ||
uint32 timestamp; | ||
uint32 nonce; | ||
uint16 emitterChainId; | ||
bytes32 emitterAddress; | ||
uint64 sequence; | ||
uint8 consistencyLevel; | ||
bytes payload; | ||
|
||
uint32 guardianSetIndex; | ||
Signature[] signatures; | ||
|
||
bytes32 hash; | ||
} | ||
|
||
struct ContractUpgrade { | ||
bytes32 module; | ||
uint8 action; | ||
uint16 chain; | ||
|
||
address newContract; | ||
} | ||
|
||
struct GuardianSetUpgrade { | ||
bytes32 module; | ||
uint8 action; | ||
uint16 chain; | ||
|
||
GuardianSet newGuardianSet; | ||
uint32 newGuardianSetIndex; | ||
} | ||
|
||
struct SetMessageFee { | ||
bytes32 module; | ||
uint8 action; | ||
uint16 chain; | ||
|
||
uint256 messageFee; | ||
} | ||
|
||
struct TransferFees { | ||
bytes32 module; | ||
uint8 action; | ||
uint16 chain; | ||
|
||
uint256 amount; | ||
bytes32 recipient; | ||
} | ||
|
||
struct RecoverChainId { | ||
bytes32 module; | ||
uint8 action; | ||
|
||
uint256 evmChainId; | ||
uint16 newChainId; | ||
} | ||
|
||
event LogMessagePublished(address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel); | ||
event ContractUpgraded(address indexed oldContract, address indexed newContract); | ||
event GuardianSetAdded(uint32 indexed index); | ||
|
||
function publishMessage( | ||
uint32 nonce, | ||
bytes memory payload, | ||
uint8 consistencyLevel | ||
) external payable returns (uint64 sequence); | ||
|
||
function initialize() external; | ||
|
||
function parseAndVerifyVM(bytes calldata encodedVM) external view returns (VM memory vm, bool valid, string memory reason); | ||
|
||
function verifyVM(VM memory vm) external view returns (bool valid, string memory reason); | ||
|
||
function verifySignatures(bytes32 hash, Signature[] memory signatures, GuardianSet memory guardianSet) external pure returns (bool valid, string memory reason); | ||
|
||
function parseVM(bytes memory encodedVM) external pure returns (VM memory vm); | ||
|
||
function quorum(uint numGuardians) external pure returns (uint numSignaturesRequiredForQuorum); | ||
|
||
function getGuardianSet(uint32 index) external view returns (GuardianSet memory); | ||
|
||
function getCurrentGuardianSetIndex() external view returns (uint32); | ||
|
||
function getGuardianSetExpiry() external view returns (uint32); | ||
|
||
function governanceActionIsConsumed(bytes32 hash) external view returns (bool); | ||
|
||
function isInitialized(address impl) external view returns (bool); | ||
|
||
function chainId() external view returns (uint16); | ||
|
||
function isFork() external view returns (bool); | ||
|
||
function governanceChainId() external view returns (uint16); | ||
|
||
function governanceContract() external view returns (bytes32); | ||
|
||
function messageFee() external view returns (uint256); | ||
|
||
function evmChainId() external view returns (uint256); | ||
|
||
function nextSequence(address emitter) external view returns (uint64); | ||
|
||
function parseContractUpgrade(bytes memory encodedUpgrade) external pure returns (ContractUpgrade memory cu); | ||
|
||
function parseGuardianSetUpgrade(bytes memory encodedUpgrade) external pure returns (GuardianSetUpgrade memory gsu); | ||
|
||
function parseSetMessageFee(bytes memory encodedSetMessageFee) external pure returns (SetMessageFee memory smf); | ||
|
||
function parseTransferFees(bytes memory encodedTransferFees) external pure returns (TransferFees memory tf); | ||
|
||
function parseRecoverChainId(bytes memory encodedRecoverChainId) external pure returns (RecoverChainId memory rci); | ||
|
||
function submitContractUpgrade(bytes memory _vm) external; | ||
|
||
function submitSetMessageFee(bytes memory _vm) external; | ||
|
||
function submitNewGuardianSet(bytes memory _vm) external; | ||
|
||
function submitTransferFees(bytes memory _vm) external; | ||
|
||
function submitRecoverChainId(bytes memory _vm) external; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// SPDX-License-Identifier: MIT OR Apache-2.0 | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
import "./IPyth.sol"; | ||
|
||
/// @title Verify oracle committed data for pyth | ||
/// @author zk.link | ||
contract PythVerifier { | ||
|
||
/// @notice The pyth contract | ||
IPyth public immutable pyth; | ||
|
||
constructor(IPyth _pyth) { | ||
pyth = _pyth; | ||
} | ||
|
||
function verify(uint32 guardianSetIndex, bytes32 guardianSetAddressHash, uint256 totalNumUpdates) external { | ||
// verify guardian set | ||
IWormhole wormhole = pyth.wormhole(); | ||
IWormhole.GuardianSet memory guardianSet = wormhole.getGuardianSet(guardianSetIndex); | ||
require(guardianSet.keys.length > 0, "Invalid guardian set index"); | ||
require(guardianSetIndex == wormhole.getCurrentGuardianSetIndex() || guardianSet.expirationTime >= block.timestamp, "Guardian set has expired"); | ||
|
||
// check the address set used to verify signature offchain is valid | ||
bytes memory addressHashContent; | ||
for (uint256 i = 0; i < guardianSet.keys.length; ++i) { | ||
addressHashContent = abi.encodePacked(addressHashContent, guardianSet.keys[i]); | ||
} | ||
require(keccak256(addressHashContent) == guardianSetAddressHash, "Invalid guardian set address hash"); | ||
|
||
// calculate fee that need to pay for pyth | ||
uint256 requiredFee = pyth.singleUpdateFeeInWei() * totalNumUpdates; | ||
pyth.updatePriceFeeds{value: requiredFee}(new bytes[](0)); | ||
} | ||
} |