diff --git a/ethereum/contracts/Getters.sol b/ethereum/contracts/Getters.sol index 627b641509..24ce5c865f 100644 --- a/ethereum/contracts/Getters.sol +++ b/ethereum/contracts/Getters.sol @@ -5,51 +5,71 @@ pragma solidity ^0.8.0; import "./State.sol"; +/// @title Getters for Wormhole State +/// @notice Provides read-only access to the state variables of Wormhole stored in the State contract. contract Getters is State { + /// @notice Fetches the guardian set for the given index + /// @param index The index for the guardian set + /// @return guardianSet Returns a guardian set function getGuardianSet(uint32 index) public view returns (Structs.GuardianSet memory) { return _state.guardianSets[index]; } + /// @notice Retrieves the index of the current guardian set + /// @return index Returns the guardian set's index function getCurrentGuardianSetIndex() public view returns (uint32) { return _state.guardianSetIndex; } + /// @notice Returns the expiration time for the current guardian set function getGuardianSetExpiry() public view returns (uint32) { return _state.guardianSetExpiry; } + /// @notice Checks whether a governance action has already been consumed + /// @return consumed Returns true if consumed function governanceActionIsConsumed(bytes32 hash) public view returns (bool) { return _state.consumedGovernanceActions[hash]; } + /// @notice Determines if the given contract implementation has been initialized + /// @param impl The address of the contract implementation + /// @return initialized Returns true if initialized function isInitialized(address impl) public view returns (bool) { return _state.initializedImplementations[impl]; } + /// @notice Returns the chain ID function chainId() public view returns (uint16) { return _state.provider.chainId; } + /// @notice Returns the EVM chain ID function evmChainId() public view returns (uint256) { return _state.evmChainId; } + /// @notice Checks if the current chain is a fork function isFork() public view returns (bool) { return evmChainId() != block.chainid; } + /// @notice Returns the governance chain ID function governanceChainId() public view returns (uint16){ return _state.provider.governanceChainId; } + /// @notice Returns the address of the governance contract in bytes32 function governanceContract() public view returns (bytes32){ return _state.provider.governanceContract; } + /// @notice Gets the current message fee function messageFee() public view returns (uint256) { return _state.messageFee; } + /// @notice Fetches the next sequence number for a given emitter address function nextSequence(address emitter) public view returns (uint64) { return _state.sequences[emitter]; } diff --git a/ethereum/contracts/Governance.sol b/ethereum/contracts/Governance.sol index cc01fb473c..494fdebfe0 100644 --- a/ethereum/contracts/Governance.sol +++ b/ethereum/contracts/Governance.sol @@ -11,8 +11,9 @@ import "./Setters.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol"; /** - * @dev `Governance` defines a means to enacting changes to the core bridge contract, - * guardianSets, message fees, and transfer fees + * @title Wormhole Governance Abstract Contract + * @notice Provides functionality for governance actions such as contract upgrades, fee setting, and guardian set updates to the core bridge contract. + * @dev This abstract contract inherits from GovernanceStructs, Messages, Setters, and the standard ERC1967Upgrade. */ abstract contract Governance is GovernanceStructs, Messages, Setters, ERC1967Upgrade { event ContractUpgraded(address indexed oldContract, address indexed newContract); @@ -23,6 +24,7 @@ abstract contract Governance is GovernanceStructs, Messages, Setters, ERC1967Upg /** * @dev Upgrades a contract via Governance VAA/VM + * @param _vm The encoded VAA/VM data */ function submitContractUpgrade(bytes memory _vm) public { require(!isFork(), "invalid fork"); @@ -50,6 +52,7 @@ abstract contract Governance is GovernanceStructs, Messages, Setters, ERC1967Upg /** * @dev Sets a `messageFee` via Governance VAA/VM + * @param _vm The encoded VAA/VM data */ function submitSetMessageFee(bytes memory _vm) public { Structs.VM memory vm = parseVM(_vm); @@ -75,6 +78,7 @@ abstract contract Governance is GovernanceStructs, Messages, Setters, ERC1967Upg /** * @dev Deploys a new `guardianSet` via Governance VAA/VM + * @param _vm The encoded VAA/VM data */ function submitNewGuardianSet(bytes memory _vm) public { Structs.VM memory vm = parseVM(_vm); @@ -113,6 +117,7 @@ abstract contract Governance is GovernanceStructs, Messages, Setters, ERC1967Upg /** * @dev Submits transfer fees to the recipient via Governance VAA/VM + * @param _vm The encoded VAA/VM data */ function submitTransferFees(bytes memory _vm) public { Structs.VM memory vm = parseVM(_vm); @@ -142,6 +147,7 @@ abstract contract Governance is GovernanceStructs, Messages, Setters, ERC1967Upg /** * @dev Updates the `chainId` and `evmChainId` on a forked chain via Governance VAA/VM + * @param _vm The encoded VAA/VM data */ function submitRecoverChainId(bytes memory _vm) public { require(isFork(), "not a fork"); @@ -170,6 +176,7 @@ abstract contract Governance is GovernanceStructs, Messages, Setters, ERC1967Upg /** * @dev Upgrades the `currentImplementation` with a `newImplementation` + * @param newImplementation The address of the new contract implementation */ function upgradeImplementation(address newImplementation) internal { address currentImplementation = _getImplementation(); @@ -186,6 +193,9 @@ abstract contract Governance is GovernanceStructs, Messages, Setters, ERC1967Upg /** * @dev Verifies a Governance VAA/VM is valid + * @param vm The governance VAA/VM to verify + * @return isValid True if the VAA/VM is valid + * @return reason The reason string if the VAA/VM is not valid */ function verifyGovernanceVM(Structs.VM memory vm) internal view returns (bool, string memory){ // Verify the VAA is valid diff --git a/ethereum/contracts/GovernanceStructs.sol b/ethereum/contracts/GovernanceStructs.sol index 88d9be2f14..0143af4b27 100644 --- a/ethereum/contracts/GovernanceStructs.sol +++ b/ethereum/contracts/GovernanceStructs.sol @@ -6,18 +6,19 @@ pragma solidity ^0.8.0; import "./libraries/external/BytesLib.sol"; import "./Structs.sol"; -/** - * @dev `GovernanceStructs` defines a set of structs and parsing functions - * for minimal struct validation - */ + +/// @title Governance Structures for Wormhole +/// @notice Defines governance structs and parsing functions for minimal struct validation. contract GovernanceStructs { using BytesLib for bytes; + /// @dev Enum representing different types of governance actions. enum GovernanceAction { UpgradeContract, UpgradeGuardianset } + /// @dev Represents a contract upgrade action. struct ContractUpgrade { bytes32 module; uint8 action; @@ -26,6 +27,7 @@ contract GovernanceStructs { address newContract; } + /// @dev Represents a guardian set upgrade action. struct GuardianSetUpgrade { bytes32 module; uint8 action; @@ -35,6 +37,7 @@ contract GovernanceStructs { uint32 newGuardianSetIndex; } + /// @dev Represents an action to set a new message fee. struct SetMessageFee { bytes32 module; uint8 action; @@ -43,6 +46,7 @@ contract GovernanceStructs { uint256 messageFee; } + /// @dev Represents an action to transfer fees to a recipient. struct TransferFees { bytes32 module; uint8 action; @@ -52,6 +56,7 @@ contract GovernanceStructs { bytes32 recipient; } + /// @dev Represents an action to recover the chain ID. struct RecoverChainId { bytes32 module; uint8 action; @@ -60,7 +65,10 @@ contract GovernanceStructs { uint16 newChainId; } - /// @dev Parse a contract upgrade (action 1) with minimal validation + /// @notice Parse a ContractUpgrade (action 1) from bytes. + /// @dev Performs minimal validation. + /// @param encodedUpgrade The bytes containing the encoded ContractUpgrade. + /// @return cu The parsed ContractUpgrade struct. function parseContractUpgrade(bytes memory encodedUpgrade) public pure returns (ContractUpgrade memory cu) { uint index = 0; @@ -81,7 +89,10 @@ contract GovernanceStructs { require(encodedUpgrade.length == index, "invalid ContractUpgrade"); } - /// @dev Parse a guardianSet upgrade (action 2) with minimal validation + /// @notice Parses a GuardianSetUpgrade (action 2) from bytes. + /// @dev Performs minimal validation. + /// @param encodedUpgrade The bytes containing the encoded GuardianSetUpgrade. + /// @return gsu The parsed GuardianSetUpgrade struct. function parseGuardianSetUpgrade(bytes memory encodedUpgrade) public pure returns (GuardianSetUpgrade memory gsu) { uint index = 0; @@ -115,7 +126,10 @@ contract GovernanceStructs { require(encodedUpgrade.length == index, "invalid GuardianSetUpgrade"); } - /// @dev Parse a setMessageFee (action 3) with minimal validation + /// @notice Parses a setMessageFee (action 3) from bytes. + /// @dev Performs minimal validation. + /// @param encodedSetMessageFee The bytes containing the encoded SetMessageFee. + /// @return smf The parsed SetMessageFee struct. function parseSetMessageFee(bytes memory encodedSetMessageFee) public pure returns (SetMessageFee memory smf) { uint index = 0; @@ -136,7 +150,10 @@ contract GovernanceStructs { require(encodedSetMessageFee.length == index, "invalid SetMessageFee"); } - /// @dev Parse a transferFees (action 4) with minimal validation + /// @notice Parses a transferFees (action 4) from bytes. + /// @dev Performs minimal validation. + /// @param encodedTransferFees The bytes containing the encoded encodedTransferFees. + /// @return tf The parsed TransferFees struct. function parseTransferFees(bytes memory encodedTransferFees) public pure returns (TransferFees memory tf) { uint index = 0; @@ -160,7 +177,10 @@ contract GovernanceStructs { require(encodedTransferFees.length == index, "invalid TransferFees"); } - /// @dev Parse a recoverChainId (action 5) with minimal validation + /// @notice Parses a recoverChainId (action 5) from bytes. + /// @dev Performs minimal validation. + /// @param encodedRecoverChainId The bytes containing the encoded RecoverChainId. + /// @return rci The parsed RecoverChainId struct. function parseRecoverChainId(bytes memory encodedRecoverChainId) public pure returns (RecoverChainId memory rci) { uint index = 0; diff --git a/ethereum/contracts/Implementation.sol b/ethereum/contracts/Implementation.sol index 5bb98cf87b..b65fb01c53 100644 --- a/ethereum/contracts/Implementation.sol +++ b/ethereum/contracts/Implementation.sol @@ -8,10 +8,18 @@ import "./Governance.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol"; +/// @title Wormhole Governance Implementation Contract upgrades +/// @notice This contract is an implementation of Wormhole's Governance contract. contract Implementation is Governance { + + /// @notice Emitted when a message is published to the Wormhole network event LogMessagePublished(address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel); - // Publish a message to be attested by the Wormhole network + /// @notice Publish a message to be attested by the Wormhole network + /// @param nonce The nonce to ensure message uniqueness + /// @param payload The content of the emitted message to be published, an arbitrary byte array + /// @param consistencyLevel The level of finality to reach before the guardians will observe and attest the emitted event + /// @return sequence A number that is unique and increments for every message for a given emitter (and implicitly chain) function publishMessage( uint32 nonce, bytes memory payload, @@ -25,11 +33,15 @@ contract Implementation is Governance { emit LogMessagePublished(msg.sender, sequence, nonce, payload, consistencyLevel); } + /// @dev Update and fetch the current sequence for a given emitter + /// @param emitter The address that emits a message + /// @return sequence The next sequence for a given emitter function useSequence(address emitter) internal returns (uint64 sequence) { sequence = nextSequence(emitter); setNextSequence(emitter, sequence + 1); } + /// @notice Initializes the contract with the EVM chain ID mapping upon deployment or upgrade function initialize() initializer public virtual { // this function needs to be exposed for an upgrade to pass if (evmChainId() == 0) { @@ -61,6 +73,7 @@ contract Implementation is Governance { } } + /// @dev Modifier to ensure the contract is only initialized once modifier initializer() { address implementation = ERC1967Upgrade._getImplementation(); @@ -74,7 +87,9 @@ contract Implementation is Governance { _; } + /// @dev Fallback function that reverts all calls fallback() external payable {revert("unsupported");} + /// @dev Receive function that reverts all transactions with assets receive() external payable {revert("the Wormhole contract does not accept assets");} } diff --git a/ethereum/contracts/Messages.sol b/ethereum/contracts/Messages.sol index c70efbb6a1..4485157af2 100644 --- a/ethereum/contracts/Messages.sol +++ b/ethereum/contracts/Messages.sol @@ -12,7 +12,10 @@ import "./libraries/external/BytesLib.sol"; contract Messages is Getters { using BytesLib for bytes; - /// @dev parseAndVerifyVM serves to parse an encodedVM and wholy validate it for consumption + /// @notice parseAndVerifyVM serves to parse an encodedVM and wholy validate it for consumption + /// @return vm a decoded VM struct + /// @return valid if the VM is valid or not + /// @return reason if the VM is not valid, the reason is contained in this string function parseAndVerifyVM(bytes calldata encodedVM) public view returns (Structs.VM memory vm, bool valid, string memory reason) { vm = parseVM(encodedVM); /// setting checkHash to false as we can trust the hash field in this case given that parseVM computes and then sets the hash field above @@ -20,13 +23,16 @@ contract Messages is Getters { } /** - * @dev `verifyVM` serves to validate an arbitrary vm against a valid Guardian set + * @notice `verifyVM` serves to validate an arbitrary vm against a valid Guardian set * - it aims to make sure the VM is for a known guardianSet * - it aims to ensure the guardianSet is not expired * - it aims to ensure the VM has reached quorum * - it aims to verify the signatures provided against the guardianSet * - it aims to verify the hash field provided against the contents of the vm + * @return valid if the VM is valid or not + * @return reason if the VM is not valid, the reason is contained in this string */ + function verifyVM(Structs.VM memory vm) public view returns (bool valid, string memory reason) { (valid, reason) = verifyVMInternal(vm, true); } @@ -105,9 +111,12 @@ contract Messages is Getters { /** * @dev verifySignatures serves to validate arbitrary sigatures against an arbitrary guardianSet * - it intentionally does not solve for expectations within guardianSet (you should use verifyVM if you need these protections) - * - it intentioanlly does not solve for quorum (you should use verifyVM if you need these protections) + * - it intentionally does not solve for quorum (you should use verifyVM if you need these protections) * - it intentionally returns true when signatures is an empty set (you should use verifyVM if you need these protections) + * @return valid if the signatures are valid or not + * @return reason if the signatures are not valid, the reason is contained in this string */ + /// function verifySignatures(bytes32 hash, Structs.Signature[] memory signatures, Structs.GuardianSet memory guardianSet) public pure returns (bool valid, string memory reason) { uint8 lastIndex = 0; uint256 guardianCount = guardianSet.keys.length; @@ -143,6 +152,7 @@ contract Messages is Getters { /** * @dev parseVM serves to parse an encodedVM into a vm struct * - it intentionally performs no validation functions, it simply parses raw into a struct + * @return vm a decoded VM struct */ function parseVM(bytes memory encodedVM) public pure virtual returns (Structs.VM memory vm) { uint index = 0; @@ -208,7 +218,8 @@ contract Messages is Getters { } /** - * @dev quorum serves solely to determine the number of signatures required to acheive quorum + * @dev quorum serves solely to determine the number of signatures required to achieve quorum + * @return numSignaturesRequiredForQuorum The number of signatures required to achieve quorum */ function quorum(uint numGuardians) public pure virtual returns (uint numSignaturesRequiredForQuorum) { // The max number of guardians is 255 diff --git a/ethereum/contracts/Migrations.sol b/ethereum/contracts/Migrations.sol index 51afb19649..3fb4c83fbb 100644 --- a/ethereum/contracts/Migrations.sol +++ b/ethereum/contracts/Migrations.sol @@ -1,10 +1,14 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.4.22 <0.9.0; +/// @title Migrations Contract +/// @notice This contract is designed to facilitate and record migrations of contract states during upgrades. contract Migrations { + /// @notice The owner of the contract, set upon deployment to the address deploying the contract. address public owner = msg.sender; uint public last_completed_migration; + /// @dev Restricts function calls to only the owner of the contract. modifier restricted() { require( msg.sender == owner, @@ -13,6 +17,9 @@ contract Migrations { _; } + /// @notice Sets a given migration as complete. + /// @dev Callable only by the current owner due to the `restricted` modifier. + /// @param completed The identifier of the migration that has been completed. function setCompleted(uint completed) public restricted { last_completed_migration = completed; } diff --git a/ethereum/contracts/Setters.sol b/ethereum/contracts/Setters.sol index 17f8828278..4dcc1363b1 100644 --- a/ethereum/contracts/Setters.sol +++ b/ethereum/contracts/Setters.sol @@ -6,14 +6,21 @@ pragma solidity ^0.8.0; import "./State.sol"; contract Setters is State { + /// @notice updates the current guardian set index + /// @param newIndex the new guardian set index function updateGuardianSetIndex(uint32 newIndex) internal { _state.guardianSetIndex = newIndex; } + /// @notice sets a guardian set to expire 1 day from now + /// @param index the index for a given guardian set function expireGuardianSet(uint32 index) internal { _state.guardianSets[index].expirationTime = uint32(block.timestamp) + 86400; } + /// @notice stores a guardian set + /// @param set the guardian set + /// @param index the index to store the guardian set under function storeGuardianSet(Structs.GuardianSet memory set, uint32 index) internal { uint setLength = set.keys.length; for (uint i = 0; i < setLength; i++) { @@ -22,34 +29,48 @@ contract Setters is State { _state.guardianSets[index] = set; } + /// @notice sets the implemented contract as initialized + /// @dev https://github.com/wormhole-foundation/wormhole/issues/1930 + /// @param implementatiom the address of the implementation function setInitialized(address implementatiom) internal { _state.initializedImplementations[implementatiom] = true; } + /// @notice sets a governance action as consumed to prevent reentry + /// @param hash a hash from a governance VM function setGovernanceActionConsumed(bytes32 hash) internal { _state.consumedGovernanceActions[hash] = true; } + /// @notice sets the chain id + /// @param chainId the chain id function setChainId(uint16 chainId) internal { _state.provider.chainId = chainId; } + /// @notice sets the chain id of the governance + /// @param chainId the chain id of the governance function setGovernanceChainId(uint16 chainId) internal { _state.provider.governanceChainId = chainId; } + /// @notice sets the governance contract function setGovernanceContract(bytes32 governanceContract) internal { _state.provider.governanceContract = governanceContract; } + /// @notice sets the message fee + /// @param newFee the fee to set the message fee to function setMessageFee(uint256 newFee) internal { _state.messageFee = newFee; } + /// @notice updates the next sequence for a given emitter function setNextSequence(address emitter, uint64 sequence) internal { _state.sequences[emitter] = sequence; } + /// @notice sets the EVM chain id function setEvmChainId(uint256 evmChainId) internal { require(evmChainId == block.chainid, "invalid evmChainId"); _state.evmChainId = evmChainId; diff --git a/ethereum/contracts/Setup.sol b/ethereum/contracts/Setup.sol index abcd3a645f..026d6ac2e0 100644 --- a/ethereum/contracts/Setup.sol +++ b/ethereum/contracts/Setup.sol @@ -8,7 +8,19 @@ import "./Governance.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol"; +/** +@title Setup Contract +@dev This contract is used to setup a wormhole contract. + It inherits from the standard ERC1967Upgrade, as well as the Setters contract. +*/ contract Setup is Setters, ERC1967Upgrade { + /// @notice sets up a wormhole contract + /// @param implementation the address of the wormhole contract + /// @param initialGuardians the initial guardian set + /// @param chainId the chain id + /// @param governanceChainId the chain id of the governance + /// @param governanceContract the contract of the governance + /// @param evmChainId the EVM chain id function setup( address implementation, address[] memory initialGuardians, diff --git a/ethereum/contracts/State.sol b/ethereum/contracts/State.sol index 7fa5a5c7f0..743d89c86a 100644 --- a/ethereum/contracts/State.sol +++ b/ethereum/contracts/State.sol @@ -5,12 +5,21 @@ pragma solidity ^0.8.0; import "./Structs.sol"; +/// @title Events for Wormhole State contract +/// @notice Defines events related to changes in guardian sets and message publication contract Events { + /// @notice Event emitted when the guardian set changes + /// @param oldGuardianIndex Index of the guardian set before the change + /// @param newGuardianIndex Index of the guardian set after the change event LogGuardianSetChanged( uint32 oldGuardianIndex, uint32 newGuardianIndex ); + /// @notice Event emitted when a message is published + /// @param emitter_address The address from which the message is sent + /// @param nonce A nonce to ensure message uniqueness + /// @param payload The data payload of the message event LogMessagePublished( address emitter_address, uint32 nonce, @@ -18,35 +27,42 @@ contract Events { ); } +/// @title Storage for Wormhole State contract +/// @notice Contains the storage states used by the Wormhole protocol contract Storage { + /// @dev Internal structure for maintaining Wormhole's state struct WormholeState { Structs.Provider provider; - // Mapping of guardian_set_index => guardian set + /// @dev Mapping of guardian_set_index => guardian set mapping(uint32 => Structs.GuardianSet) guardianSets; - // Current active guardian set index + /// @dev Current active guardian set index uint32 guardianSetIndex; - // Period for which a guardian set stays active after it has been replaced + /// @dev Period for which a guardian set stays active after it has been replaced uint32 guardianSetExpiry; - // Sequence numbers per emitter + /// @dev Sequence numbers per emitter mapping(address => uint64) sequences; - // Mapping of consumed governance actions + /// @dev Mapping of consumed governance actions mapping(bytes32 => bool) consumedGovernanceActions; - // Mapping of initialized implementations + /// @dev Mapping of initialized implementations mapping(address => bool) initializedImplementations; + /// @dev Fee required to publish a message uint256 messageFee; - // EIP-155 Chain ID + /// @dev EIP-155 Chain ID uint256 evmChainId; } } +/// @title State contract for Wormhole +/// @notice Manages the state variables for the Wormhole protocol contract State { + /// @dev State variable containing all Wormhole state information Storage.WormholeState _state; } diff --git a/ethereum/contracts/Structs.sol b/ethereum/contracts/Structs.sol index d61155c551..220a5e74ff 100644 --- a/ethereum/contracts/Structs.sol +++ b/ethereum/contracts/Structs.sol @@ -3,18 +3,32 @@ pragma solidity ^0.8.0; +/// @title Wormhole Structs +/// @notice This interface declares several structs that are used in Wormhole . interface Structs { + /// @notice The Provider struct. + /// @param chainId The chain id. + /// @param governanceChainId The chain ID where the governance contract is deployed. + /// @param governanceContract The address in bytes of the governance contract. struct Provider { uint16 chainId; uint16 governanceChainId; bytes32 governanceContract; } + /// @notice The Guardian Set is a set of guardians that are responsible for validating a message emitted from the core contracts. + /// @param keys An array of addresses representing the public keys of the guardians. + /// @param expirationTime The timestamp at which this guardian set expires and can be replaced by a new set. struct GuardianSet { address[] keys; uint32 expirationTime; } + /// @notice Represents a signature produced by a guardian. + /// @param r The 'r' portion of the ECDSA signature. + /// @param s The 's' portion of the ECDSA signature. + /// @param v The recovery byte of the ECDSA signature. + /// @param guardianIndex The index of the guardian in the current guardian set that produced this signature. struct Signature { bytes32 r; bytes32 s; @@ -22,6 +36,18 @@ interface Structs { uint8 guardianIndex; } + /// @notice Describes a verifiable message (VM) in the Wormhole protocol. + /// @param version The version of the VM structure. + /// @param timestamp The timestamp when the VM was produced. + /// @param nonce A nonce to ensure uniqueness of the VM. + /// @param emitterChainId The chain ID from where the message originated. + /// @param emitterAddress The address in bytes from where the message originated. + /// @param sequence A number that increments with each message from a given emitter, ensuring ordered processing. + /// @param consistencyLevel The level of consistency required for the message before it is considered confirmed. + /// @param payload The actual data content of the message. + /// @param guardianSetIndex The index of the guardian set responsible for signing the VM. + /// @param signatures An array of signatures by the guardians. + /// @param hash The hash of the message contents. struct VM { uint8 version; uint32 timestamp; diff --git a/ethereum/contracts/interfaces/IWormhole.sol b/ethereum/contracts/interfaces/IWormhole.sol index eba9f6f2ea..08d5a91726 100644 --- a/ethereum/contracts/interfaces/IWormhole.sol +++ b/ethereum/contracts/interfaces/IWormhole.sol @@ -3,12 +3,16 @@ pragma solidity ^0.8.0; +/// @title Wormhole Interface +/// @notice This interface declares the necessary functions and events for interacting with the Wormhole network interface IWormhole { + /// @dev Represents a set of guardians with their associated keys and expiration time struct GuardianSet { address[] keys; uint32 expirationTime; } + /// @dev Represents a signature produced by a guardian struct Signature { bytes32 r; bytes32 s; @@ -16,6 +20,7 @@ interface IWormhole { uint8 guardianIndex; } + /// @dev Represents a Wormhole message with necessary metadata and signatures struct VM { uint8 version; uint32 timestamp; @@ -32,6 +37,7 @@ interface IWormhole { bytes32 hash; } + /// @dev A VAA that instructs an implementation on a specific chain to upgrade itself struct ContractUpgrade { bytes32 module; uint8 action; @@ -40,6 +46,7 @@ interface IWormhole { address newContract; } + /// @dev A VAA that upgrades a GuardianSet struct GuardianSetUpgrade { bytes32 module; uint8 action; @@ -49,6 +56,7 @@ interface IWormhole { uint32 newGuardianSetIndex; } + /// @dev Contains details for setting a new message fee struct SetMessageFee { bytes32 module; uint8 action; @@ -57,6 +65,7 @@ interface IWormhole { uint256 messageFee; } + /// @dev Contains details for transferring collected fees struct TransferFees { bytes32 module; uint8 action; @@ -66,6 +75,7 @@ interface IWormhole { bytes32 recipient; } + /// @dev Contains details for recovering a chain ID struct RecoverChainId { bytes32 module; uint8 action; @@ -74,69 +84,146 @@ interface IWormhole { uint16 newChainId; } + /// @notice Emitted when a message is published to the Wormhole network event LogMessagePublished(address indexed sender, uint64 sequence, uint32 nonce, bytes payload, uint8 consistencyLevel); + + /// @notice Emitted when a contract is upgraded on the Wormhole network event ContractUpgraded(address indexed oldContract, address indexed newContract); + + /// @notice Emitted when a new guardian set is added to the Wormhole network event GuardianSetAdded(uint32 indexed index); + /// @notice Publish a message to be attested by the Wormhole network + /// @param nonce A free integer field that can be used however the developer would like + /// @param payload The content of the emitted message, an arbitrary byte array + /// @param consistencyLevel The level of finality to reach before the guardians will observe and attest the emitted event + /// @return sequence number that is unique and increments for every message for a given emitter (and implicitly chain) function publishMessage( uint32 nonce, bytes memory payload, uint8 consistencyLevel ) external payable returns (uint64 sequence); + /// @notice Initializes the contract with the EVM chain ID mapping upon deployment or upgrade + /// @dev Should only be called once, upon contract deployment or upgrade function initialize() external; + /// @dev Parses and verifies a verifiable message (VM) + /// @param encodedVM An encoded VM in bytes + /// @return vm A decoded VM struct + /// @return valid True if the VM is valid and false if not + /// @return reason If the VM is not valid, the reason is contained in this string function parseAndVerifyVM(bytes calldata encodedVM) external view returns (VM memory vm, bool valid, string memory reason); + /// @dev Validates an arbitrary verifiable message (VM) against an arbitrary guardian set + /// @param vm A decoded VM struct + /// @return valid True if the VM is valid and false if not + /// @return reason If the VM is not valid, the reason is contained in this string function verifyVM(VM memory vm) external view returns (bool valid, string memory reason); + /// @dev Verifies signatures against an arbitrary guardian set + /// @param signatures An array of Signature + /// @param guardianSet A guardian set used to verify the signatures provided + /// @return valid True if the signatures are valid and false if not + /// @return reason If the signatures are not valid, the reason is contained in this string function verifySignatures(bytes32 hash, Signature[] memory signatures, GuardianSet memory guardianSet) external pure returns (bool valid, string memory reason); + /// @dev Parses an encoded VM to a decoded VM struct + /// @param encodedVM An encoded VM in bytes + /// @return vm A decoded VM struct function parseVM(bytes memory encodedVM) external pure returns (VM memory vm); + /// @dev Calculates the required quorum for a given number of guardians + /// @param numGuardians The number of guardians to calculate the quorum for + /// @return numSignaturesRequiredForQuorum The number of signatures required to achieve quorum function quorum(uint numGuardians) external pure returns (uint numSignaturesRequiredForQuorum); + /// @dev Fetches the guardian set for the given index + /// @param index The index for the guardian set + /// @return guardianSet Returns a guardian set function getGuardianSet(uint32 index) external view returns (GuardianSet memory); + /// @dev Retrieves the index of the current guardian set + /// @return index Returns the guardian set's index function getCurrentGuardianSetIndex() external view returns (uint32); + /// @dev Returns the expiration time for the current guardian set function getGuardianSetExpiry() external view returns (uint32); + /// @dev Checks whether a governance action has already been consumed + /// @return consumed Returns true if consumed function governanceActionIsConsumed(bytes32 hash) external view returns (bool); + /// @dev Determines if the given contract implementation has been initialized + /// @param impl The address of the contract implementation + /// @return initialized Returns true if initialized function isInitialized(address impl) external view returns (bool); + /// @dev Returns the chain ID function chainId() external view returns (uint16); + /// @dev Checks if the current chain is a fork function isFork() external view returns (bool); + /// @dev Returns the governance chain ID function governanceChainId() external view returns (uint16); + /// @dev Returns the address of the governance contract in bytes32 function governanceContract() external view returns (bytes32); + /// @dev Gets the current message fee function messageFee() external view returns (uint256); + /// @dev Gets the EVM chain ID function evmChainId() external view returns (uint256); + /// @dev Fetches the next sequence number for a given emitter address function nextSequence(address emitter) external view returns (uint64); + /// @dev Parses an encoded contract upgrade (action 1) to its structured representation + /// @param encodedUpgrade the encoded contract upgrade in bytes function parseContractUpgrade(bytes memory encodedUpgrade) external pure returns (ContractUpgrade memory cu); + /// @dev Parses an encoded guardian set upgrade (action 2) to its structured representation + /// @param encodedUpgrade the encoded guardian set upgrade in bytes function parseGuardianSetUpgrade(bytes memory encodedUpgrade) external pure returns (GuardianSetUpgrade memory gsu); + /// @dev Parses an encoded message fee update (action 3) to its structured representation function parseSetMessageFee(bytes memory encodedSetMessageFee) external pure returns (SetMessageFee memory smf); + /// @dev Parses an encoded transfer of fees (action 4) to its structured representation function parseTransferFees(bytes memory encodedTransferFees) external pure returns (TransferFees memory tf); + /// @dev Parses an encoded recover chain ID operation (action 5) to its structured representation function parseRecoverChainId(bytes memory encodedRecoverChainId) external pure returns (RecoverChainId memory rci); + /** + * @dev Upgrades a contract via Governance VAA/VM + * @param _vm The encoded VAA/VM data + */ function submitContractUpgrade(bytes memory _vm) external; + /** + * @dev Sets a `messageFee` via Governance VAA/VM + * @param _vm The encoded VAA/VM data + */ function submitSetMessageFee(bytes memory _vm) external; + /** + * @dev Deploys a new `guardianSet` via Governance VAA/VM + * @param _vm The encoded VAA/VM data + */ function submitNewGuardianSet(bytes memory _vm) external; + /** + * @dev Submits transfer fees to the recipient via Governance VAA/VM + * @param _vm The encoded VAA/VM data + */ function submitTransferFees(bytes memory _vm) external; + /** + * @dev Updates the `chainId` and `evmChainId` on a forked chain via Governance VAA/VM + * @param _vm The encoded VAA/VM data + */ function submitRecoverChainId(bytes memory _vm) external; }