diff --git a/.gitignore b/.gitignore index ca86849..4b95cc7 100644 --- a/.gitignore +++ b/.gitignore @@ -39,4 +39,5 @@ artifacts/ temp #zk-circuits -typechain/ \ No newline at end of file +typechain/ +cache/ \ No newline at end of file diff --git a/packages/zk-circuits/cache/solidity-files-cache.json b/packages/zk-circuits/cache/solidity-files-cache.json deleted file mode 100644 index 4c8ba9a..0000000 --- a/packages/zk-circuits/cache/solidity-files-cache.json +++ /dev/null @@ -1,186 +0,0 @@ -{ - "_format": "hh-sol-cache-2", - "files": { - "/Users/cfh00890942/Workspace/hackathon/tobi/tobi/packages/zk-circuits/contracts/CircuitsVerifier.sol": { - "lastModificationDate": 1692676198788, - "contentHash": "a1cd466008240a0102cf704daf699062", - "sourceName": "contracts/CircuitsVerifier.sol", - "solcConfig": { - "version": "0.6.11", - "settings": { - "optimizer": { - "enabled": false, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "imports": [], - "versionPragmas": [ - "^0.6.11" - ], - "artifacts": [ - "Pairing", - "Verifier" - ] - }, - "/Users/cfh00890942/Workspace/hackathon/tobi/tobi/packages/zk-circuits/contracts/KamuiField.sol": { - "lastModificationDate": 1692839634797, - "contentHash": "2623c233915cd7f0088dc81ee90882fd", - "sourceName": "contracts/KamuiField.sol", - "solcConfig": { - "version": "0.8.18", - "settings": { - "optimizer": { - "enabled": false, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "imports": [ - "./interface/ICircuitsVerifier.sol", - "@openzeppelin/contracts/access/Ownable.sol" - ], - "versionPragmas": [ - ">=0.7.0 <0.9.0" - ], - "artifacts": [ - "KamuiField" - ] - }, - "/Users/cfh00890942/Workspace/hackathon/tobi/tobi/packages/zk-circuits/contracts/interface/ICircuitsVerifier.sol": { - "lastModificationDate": 1692839634798, - "contentHash": "8414b18f6719c8db16c5484ac9265015", - "sourceName": "contracts/interface/ICircuitsVerifier.sol", - "solcConfig": { - "version": "0.8.18", - "settings": { - "optimizer": { - "enabled": false, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "imports": [], - "versionPragmas": [ - "^0.8.0" - ], - "artifacts": [ - "ICircuitsVerifier" - ] - }, - "/Users/cfh00890942/Workspace/hackathon/tobi/tobi/node_modules/.pnpm/@openzeppelin+contracts@4.9.3/node_modules/@openzeppelin/contracts/access/Ownable.sol": { - "lastModificationDate": 1692672501304, - "contentHash": "5a20b2cad87ddb61c7a3a6af21289e28", - "sourceName": "@openzeppelin/contracts/access/Ownable.sol", - "solcConfig": { - "version": "0.8.18", - "settings": { - "optimizer": { - "enabled": false, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "imports": [ - "../utils/Context.sol" - ], - "versionPragmas": [ - "^0.8.0" - ], - "artifacts": [ - "Ownable" - ] - }, - "/Users/cfh00890942/Workspace/hackathon/tobi/tobi/node_modules/.pnpm/@openzeppelin+contracts@4.9.3/node_modules/@openzeppelin/contracts/utils/Context.sol": { - "lastModificationDate": 1692672501254, - "contentHash": "5f2c5c4b6af2dd4551027144797bc8be", - "sourceName": "@openzeppelin/contracts/utils/Context.sol", - "solcConfig": { - "version": "0.8.18", - "settings": { - "optimizer": { - "enabled": false, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata" - ], - "": [ - "ast" - ] - } - } - } - }, - "imports": [], - "versionPragmas": [ - "^0.8.0" - ], - "artifacts": [ - "Context" - ] - } - } -} diff --git a/packages/zk-circuits/contracts/WormKamuiDst.sol b/packages/zk-circuits/contracts/WormKamuiDst.sol new file mode 100644 index 0000000..b9f90fe --- /dev/null +++ b/packages/zk-circuits/contracts/WormKamuiDst.sol @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.7.0 <0.9.0; + +import "./interface/IWormhole.sol"; +import "./interface/IWormholeReceiver.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +contract WormKamuiDst is Ownable, IWormholeReceiver { + struct Voter { + bool voted; + } + + struct Proposal { + string name; + address creator; + uint acceptCount; + uint denyCount; + uint256 endTime; + } + + struct MyMessage { + address recipient; + string message; + } + + event Voted(address indexed from, uint256 proposal, bool accept); + + // goerli core bridge: https://book.wormhole.com/reference/contracts.html#testnet + address private whAddr = 0x706abc4E45D419950511e474C7B9Ed348A4a716c; + IWormhole public immutable wormhole = IWormhole(whAddr); + + + mapping(uint16 => bytes32) public registeredContracts; + mapping(bytes32 => bool) public hasProcessedMessage; + string[] public messageHistory; + + + mapping(address => mapping(uint256 => Voter)) public voters; + + mapping(uint256 => Proposal) public proposals; + + mapping(address => uint[1]) public users; + + uint public totalProposals = 0; + + function createProposals(string calldata name, uint256 continueSec) public { + Proposal storage poll = proposals[totalProposals]; + poll.creator = msg.sender; + poll.name = name; + poll.endTime = block.timestamp + continueSec; + totalProposals += 1; + } + + function vote( + uint256 proposal, + bool accept + ) public { + Voter storage sender = voters[msg.sender][proposal]; + require(block.timestamp < proposals[proposal].endTime, "Vote End"); + require(!sender.voted, "Already voted."); + sender.voted = true; + if (accept) proposals[proposal].acceptCount += 1; + else proposals[proposal].denyCount += 1; + emit Voted(msg.sender, proposal, accept); + } + + function getResult(uint256 proposal) public view returns (bool) { + require(block.timestamp > proposals[proposal].endTime, "Vote Not End"); + if (proposals[proposal].acceptCount > proposals[proposal].denyCount) + return true; + else return false; + } + + function getBlockTime() public view returns (uint256) { + return block.timestamp; + } + + function registerEmitter(uint16 chainId, bytes32 emitterAddress) public { + // require(msg.sender == owner); + registeredContracts[chainId] = emitterAddress; + } + + function receiveWormholeMessages( + bytes[] memory signedVaas, + bytes[] memory + ) public payable override { + (IWormhole.VM memory parsed, bool valid, string memory reason) + = wormhole.parseAndVerifyVM(signedVaas[0]); + + require(valid, reason); + require( + registeredContracts[parsed.emitterChainId] == parsed.emitterAddress, + "Emitter address not valid" + ); + + require(!hasProcessedMessage[parsed.hash]); + + MyMessage memory message = abi.decode(parsed.payload, (MyMessage)); + require(message.recipient == address(this)); + + hasProcessedMessage[parsed.hash] = true; + messageHistory.push(message.message); + } + + function getFullMessageHistory() public view returns (string[] memory) { + return messageHistory; + } +} diff --git a/packages/zk-circuits/contracts/WormKamuiSrc.sol b/packages/zk-circuits/contracts/WormKamuiSrc.sol new file mode 100644 index 0000000..60c8fca --- /dev/null +++ b/packages/zk-circuits/contracts/WormKamuiSrc.sol @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.7.0 <0.9.0; + +import "./interface/IWormhole.sol"; +import "./interface/ICircuitsVerifier.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +contract WormKamuiSrc is Ownable { + struct MyMessage { + address recipient; + string message; + } + + // sepoloa core bridge: https://book.wormhole.com/reference/contracts.html#testnet + address private whAddr = 0x4a8bc80Ed5a4067f1CCf107057b8270E0cC11A78; + IWormhole public immutable wormhole = IWormhole(whAddr); + + uint256 public lastMessageSequence; + + struct Voter { + bool voted; + } + + struct Proposal { + string name; + address creator; + uint acceptCount; + uint denyCount; + uint256 endTime; + } + + struct ProofData { + uint[2] a; + uint[2][2] b; + uint[2] c; + uint[1] input; + } + + event Voted(address indexed from, uint256 proposal, bool accept); + + ICircuitsVerifier public verifier; + + constructor(address _verifierAddress) { + verifier = ICircuitsVerifier(_verifierAddress); + } + + mapping(address => mapping(uint256 => Voter)) public voters; + + mapping(uint256 => Proposal) public proposals; + + mapping(address => uint[1]) public users; + + uint public totalProposals = 0; + + function createProposals(string calldata name, uint256 continueSec) public { + Proposal storage poll = proposals[totalProposals]; + poll.creator = msg.sender; + poll.name = name; + poll.endTime = block.timestamp + continueSec; + totalProposals += 1; + } + + function vote( + uint256 proposal, + bool accept, + ProofData memory proofData + ) public { + require(verifyProof(proofData), "Verification Failed"); + Voter storage sender = voters[msg.sender][proposal]; + require(block.timestamp < proposals[proposal].endTime, "Vote End"); + require(!sender.voted, "Already voted."); + sender.voted = true; + if (accept) proposals[proposal].acceptCount += 1; + else proposals[proposal].denyCount += 1; + emit Voted(msg.sender, proposal, accept); + } + + function getResult(uint256 proposal) public view returns (bool) { + require(block.timestamp > proposals[proposal].endTime, "Vote Not End"); + if (proposals[proposal].acceptCount > proposals[proposal].denyCount) + return true; + else return false; + } + + function getBlockTime() public view returns (uint256) { + return block.timestamp; + } + + function verifyProof( + ProofData memory proofData + ) public view returns (bool) { + return + verifier.verifyProof( + proofData.a, + proofData.b, + proofData.c, + proofData.input + ); + } + + // wormhole + function getMessageForAddress(address recipient, string calldata message) external pure returns (bytes memory) { + return abi.encode(MyMessage(recipient, message)); + } + + function sendKYCMessage( + bytes memory fullMessage, + ProofData memory proofData + ) public payable { + require(verifyProof(proofData), "Verification Failed"); + lastMessageSequence = wormhole.publishMessage{ + value: wormhole.messageFee() + }(1, fullMessage, 200); + } + + function emitterAddress() public view returns (bytes32) { + return bytes32(uint256(uint160(address(this)))); + } +} diff --git a/packages/zk-circuits/contracts/interface/IWormhole.sol b/packages/zk-circuits/contracts/interface/IWormhole.sol new file mode 100644 index 0000000..a2becdf --- /dev/null +++ b/packages/zk-circuits/contracts/interface/IWormhole.sol @@ -0,0 +1,148 @@ +// 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(uint256 numGuardians) external pure returns (uint256 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; +} \ No newline at end of file diff --git a/packages/zk-circuits/contracts/interface/IWormholeReceiver.sol b/packages/zk-circuits/contracts/interface/IWormholeReceiver.sol new file mode 100644 index 0000000..98a7790 --- /dev/null +++ b/packages/zk-circuits/contracts/interface/IWormholeReceiver.sol @@ -0,0 +1,8 @@ +// contracts/Messages.sol +// SPDX-License-Identifier: Apache 2 + +pragma solidity ^0.8.0; + +interface IWormholeReceiver { + function receiveWormholeMessages(bytes[] memory vaas, bytes[] memory additionalData) external payable; +} \ No newline at end of file diff --git a/packages/zk-circuits/contracts/interface/IWormholeRelayer.sol b/packages/zk-circuits/contracts/interface/IWormholeRelayer.sol new file mode 100644 index 0000000..fbc5ffc --- /dev/null +++ b/packages/zk-circuits/contracts/interface/IWormholeRelayer.sol @@ -0,0 +1,704 @@ +// SPDX-License-Identifier: Apache 2 + +pragma solidity ^0.8.0; + +/** + * @title WormholeRelayer + * @author + * @notice This project allows developers to build cross-chain applications powered by Wormhole without needing to + * write and run their own relaying infrastructure + * + * We implement the IWormholeRelayer interface that allows users to request a delivery provider to relay a payload (and/or additional VAAs) + * to a chain and address of their choice. + */ + +/** + * @notice VaaKey identifies a wormhole message + * + * @custom:member chainId Wormhole chain ID of the chain where this VAA was emitted from + * @custom:member emitterAddress Address of the emitter of the VAA, in Wormhole bytes32 format + * @custom:member sequence Sequence number of the VAA + */ +struct VaaKey { + uint16 chainId; + bytes32 emitterAddress; + uint64 sequence; +} + +interface IWormholeRelayerBase { + event SendEvent(uint64 indexed sequence, uint256 deliveryQuote, uint256 paymentForExtraReceiverValue); + + function getRegisteredWormholeRelayerContract(uint16 chainId) external view returns (bytes32); +} + +/** + * @title IWormholeRelayerSend + * @notice The interface to request deliveries + */ +interface IWormholeRelayerSend is IWormholeRelayerBase { + /** + * @notice Publishes an instruction for the default delivery provider + * to relay a payload to the address `targetAddress` on chain `targetChain` + * with gas limit `gasLimit` and `msg.value` equal to `receiverValue` + * + * `targetAddress` must implement the IWormholeReceiver interface + * + * This function must be called with `msg.value` equal to `quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit)` + * + * Any refunds (from leftover gas) will be paid to the delivery provider. In order to receive the refunds, use the `sendPayloadToEvm` function + * with `refundChain` and `refundAddress` as parameters + * + * @param targetChain in Wormhole Chain ID format + * @param targetAddress address to call on targetChain (that implements IWormholeReceiver) + * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress` + * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) + * @param gasLimit gas limit with which to call `targetAddress`. + * @return sequence sequence number of published VAA containing delivery instructions + */ + function sendPayloadToEvm( + uint16 targetChain, + address targetAddress, + bytes memory payload, + uint256 receiverValue, + uint256 gasLimit + ) external payable returns (uint64 sequence); + + /** + * @notice Publishes an instruction for the default delivery provider + * to relay a payload to the address `targetAddress` on chain `targetChain` + * with gas limit `gasLimit` and `msg.value` equal to `receiverValue` + * + * Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain` + * `targetAddress` must implement the IWormholeReceiver interface + * + * This function must be called with `msg.value` equal to `quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit)` + * + * @param targetChain in Wormhole Chain ID format + * @param targetAddress address to call on targetChain (that implements IWormholeReceiver) + * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress` + * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) + * @param gasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the + * `targetChainRefundPerGasUnused` rate quoted by the delivery provider + * @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format + * @param refundAddress The address on `refundChain` to deliver any refund to + * @return sequence sequence number of published VAA containing delivery instructions + */ + function sendPayloadToEvm( + uint16 targetChain, + address targetAddress, + bytes memory payload, + uint256 receiverValue, + uint256 gasLimit, + uint16 refundChain, + address refundAddress + ) external payable returns (uint64 sequence); + + /** + * @notice Publishes an instruction for the default delivery provider + * to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain` + * with gas limit `gasLimit` and `msg.value` equal to `receiverValue` + * + * `targetAddress` must implement the IWormholeReceiver interface + * + * This function must be called with `msg.value` equal to `quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit)` + * + * Any refunds (from leftover gas) will be paid to the delivery provider. In order to receive the refunds, use the `sendVaasToEvm` function + * with `refundChain` and `refundAddress` as parameters + * + * @param targetChain in Wormhole Chain ID format + * @param targetAddress address to call on targetChain (that implements IWormholeReceiver) + * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress` + * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) + * @param gasLimit gas limit with which to call `targetAddress`. + * @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress` + * @return sequence sequence number of published VAA containing delivery instructions + */ + function sendVaasToEvm( + uint16 targetChain, + address targetAddress, + bytes memory payload, + uint256 receiverValue, + uint256 gasLimit, + VaaKey[] memory vaaKeys + ) external payable returns (uint64 sequence); + + /** + * @notice Publishes an instruction for the default delivery provider + * to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain` + * with gas limit `gasLimit` and `msg.value` equal to `receiverValue` + * + * Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain` + * `targetAddress` must implement the IWormholeReceiver interface + * + * This function must be called with `msg.value` equal to `quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit)` + * + * @param targetChain in Wormhole Chain ID format + * @param targetAddress address to call on targetChain (that implements IWormholeReceiver) + * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress` + * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) + * @param gasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the + * `targetChainRefundPerGasUnused` rate quoted by the delivery provider + * @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress` + * @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format + * @param refundAddress The address on `refundChain` to deliver any refund to + * @return sequence sequence number of published VAA containing delivery instructions + */ + function sendVaasToEvm( + uint16 targetChain, + address targetAddress, + bytes memory payload, + uint256 receiverValue, + uint256 gasLimit, + VaaKey[] memory vaaKeys, + uint16 refundChain, + address refundAddress + ) external payable returns (uint64 sequence); + + /** + * @notice Publishes an instruction for the delivery provider at `deliveryProviderAddress` + * to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain` + * with gas limit `gasLimit` and `msg.value` equal to + * receiverValue + (arbitrary amount that is paid for by paymentForExtraReceiverValue of this chain's wei) in targetChain wei. + * + * Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain` + * `targetAddress` must implement the IWormholeReceiver interface + * + * This function must be called with `msg.value` equal to + * quoteEVMDeliveryPrice(targetChain, receiverValue, gasLimit, deliveryProviderAddress) + paymentForExtraReceiverValue + * + * @param targetChain in Wormhole Chain ID format + * @param targetAddress address to call on targetChain (that implements IWormholeReceiver) + * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress` + * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) + * @param paymentForExtraReceiverValue amount (in current chain currency units) to spend on extra receiverValue + * (in addition to the `receiverValue` specified) + * @param gasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the + * `targetChainRefundPerGasUnused` rate quoted by the delivery provider + * @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format + * @param refundAddress The address on `refundChain` to deliver any refund to + * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider + * @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress` + * @param consistencyLevel Consistency level with which to publish the delivery instructions - see + * https://book.wormhole.com/wormhole/3_coreLayerContracts.html?highlight=consistency#consistency-levels + * @return sequence sequence number of published VAA containing delivery instructions + */ + function sendToEvm( + uint16 targetChain, + address targetAddress, + bytes memory payload, + uint256 receiverValue, + uint256 paymentForExtraReceiverValue, + uint256 gasLimit, + uint16 refundChain, + address refundAddress, + address deliveryProviderAddress, + VaaKey[] memory vaaKeys, + uint8 consistencyLevel + ) external payable returns (uint64 sequence); + + /** + * @notice Publishes an instruction for the delivery provider at `deliveryProviderAddress` + * to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain` + * with `msg.value` equal to + * receiverValue + (arbitrary amount that is paid for by paymentForExtraReceiverValue of this chain's wei) in targetChain wei. + * + * Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain` + * `targetAddress` must implement the IWormholeReceiver interface + * + * This function must be called with `msg.value` equal to + * quoteDeliveryPrice(targetChain, receiverValue, encodedExecutionParameters, deliveryProviderAddress) + paymentForExtraReceiverValue + * + * @param targetChain in Wormhole Chain ID format + * @param targetAddress address to call on targetChain (that implements IWormholeReceiver), in Wormhole bytes32 format + * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress` + * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) + * @param paymentForExtraReceiverValue amount (in current chain currency units) to spend on extra receiverValue + * (in addition to the `receiverValue` specified) + * @param encodedExecutionParameters encoded information on how to execute delivery that may impact pricing + * e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` with which to call `targetAddress` + * @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format + * @param refundAddress The address on `refundChain` to deliver any refund to, in Wormhole bytes32 format + * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider + * @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress` + * @param consistencyLevel Consistency level with which to publish the delivery instructions - see + * https://book.wormhole.com/wormhole/3_coreLayerContracts.html?highlight=consistency#consistency-levels + * @return sequence sequence number of published VAA containing delivery instructions + */ + function send( + uint16 targetChain, + bytes32 targetAddress, + bytes memory payload, + uint256 receiverValue, + uint256 paymentForExtraReceiverValue, + bytes memory encodedExecutionParameters, + uint16 refundChain, + bytes32 refundAddress, + address deliveryProviderAddress, + VaaKey[] memory vaaKeys, + uint8 consistencyLevel + ) external payable returns (uint64 sequence); + + /** + * @notice Performs the same function as a `send`, except: + * 1) Can only be used during a delivery (i.e. in execution of `receiveWormholeMessages`) + * 2) Is paid for (along with any other calls to forward) by (any msg.value passed in) + (refund leftover from current delivery) + * 3) Only executes after `receiveWormholeMessages` is completed (and thus does not return a sequence number) + * + * The refund from the delivery currently in progress will not be sent to the user; it will instead + * be paid to the delivery provider to perform the instruction specified here + * + * Publishes an instruction for the same delivery provider (or default, if the same one doesn't support the new target chain) + * to relay a payload to the address `targetAddress` on chain `targetChain` + * with gas limit `gasLimit` and with `msg.value` equal to `receiverValue` + * + * The following equation must be satisfied (sum_f indicates summing over all forwards requested in `receiveWormholeMessages`): + * (refund amount from current execution of receiveWormholeMessages) + sum_f [msg.value_f] + * >= sum_f [quoteEVMDeliveryPrice(targetChain_f, receiverValue_f, gasLimit_f)] + * + * The difference between the two sides of the above inequality will be added to `paymentForExtraReceiverValue` of the first forward requested + * + * Any refunds (from leftover gas) from this forward will be paid to the same refundChain and refundAddress specified for the current delivery. + * + * @param targetChain in Wormhole Chain ID format + * @param targetAddress address to call on targetChain (that implements IWormholeReceiver), in Wormhole bytes32 format + * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress` + * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) + * @param gasLimit gas limit with which to call `targetAddress`. + */ + function forwardPayloadToEvm( + uint16 targetChain, + address targetAddress, + bytes memory payload, + uint256 receiverValue, + uint256 gasLimit + ) external payable; + + /** + * @notice Performs the same function as a `send`, except: + * 1) Can only be used during a delivery (i.e. in execution of `receiveWormholeMessages`) + * 2) Is paid for (along with any other calls to forward) by (any msg.value passed in) + (refund leftover from current delivery) + * 3) Only executes after `receiveWormholeMessages` is completed (and thus does not return a sequence number) + * + * The refund from the delivery currently in progress will not be sent to the user; it will instead + * be paid to the delivery provider to perform the instruction specified here + * + * Publishes an instruction for the same delivery provider (or default, if the same one doesn't support the new target chain) + * to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain` + * with gas limit `gasLimit` and with `msg.value` equal to `receiverValue` + * + * The following equation must be satisfied (sum_f indicates summing over all forwards requested in `receiveWormholeMessages`): + * (refund amount from current execution of receiveWormholeMessages) + sum_f [msg.value_f] + * >= sum_f [quoteEVMDeliveryPrice(targetChain_f, receiverValue_f, gasLimit_f)] + * + * The difference between the two sides of the above inequality will be added to `paymentForExtraReceiverValue` of the first forward requested + * + * Any refunds (from leftover gas) from this forward will be paid to the same refundChain and refundAddress specified for the current delivery. + * + * @param targetChain in Wormhole Chain ID format + * @param targetAddress address to call on targetChain (that implements IWormholeReceiver), in Wormhole bytes32 format + * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress` + * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) + * @param gasLimit gas limit with which to call `targetAddress`. + * @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress` + */ + function forwardVaasToEvm( + uint16 targetChain, + address targetAddress, + bytes memory payload, + uint256 receiverValue, + uint256 gasLimit, + VaaKey[] memory vaaKeys + ) external payable; + + /** + * @notice Performs the same function as a `send`, except: + * 1) Can only be used during a delivery (i.e. in execution of `receiveWormholeMessages`) + * 2) Is paid for (along with any other calls to forward) by (any msg.value passed in) + (refund leftover from current delivery) + * 3) Only executes after `receiveWormholeMessages` is completed (and thus does not return a sequence number) + * + * The refund from the delivery currently in progress will not be sent to the user; it will instead + * be paid to the delivery provider to perform the instruction specified here + * + * Publishes an instruction for the delivery provider at `deliveryProviderAddress` + * to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain` + * with gas limit `gasLimit` and with `msg.value` equal to + * receiverValue + (arbitrary amount that is paid for by paymentForExtraReceiverValue of this chain's wei) in targetChain wei. + * + * Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain` + * `targetAddress` must implement the IWormholeReceiver interface + * + * The following equation must be satisfied (sum_f indicates summing over all forwards requested in `receiveWormholeMessages`): + * (refund amount from current execution of receiveWormholeMessages) + sum_f [msg.value_f] + * >= sum_f [quoteEVMDeliveryPrice(targetChain_f, receiverValue_f, gasLimit_f, deliveryProviderAddress_f) + paymentForExtraReceiverValue_f] + * + * The difference between the two sides of the above inequality will be added to `paymentForExtraReceiverValue` of the first forward requested + * + * @param targetChain in Wormhole Chain ID format + * @param targetAddress address to call on targetChain (that implements IWormholeReceiver), in Wormhole bytes32 format + * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress` + * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) + * @param paymentForExtraReceiverValue amount (in current chain currency units) to spend on extra receiverValue + * (in addition to the `receiverValue` specified) + * @param gasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the + * `targetChainRefundPerGasUnused` rate quoted by the delivery provider + * @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format + * @param refundAddress The address on `refundChain` to deliver any refund to, in Wormhole bytes32 format + * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider + * @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress` + * @param consistencyLevel Consistency level with which to publish the delivery instructions - see + * https://book.wormhole.com/wormhole/3_coreLayerContracts.html?highlight=consistency#consistency-levels + */ + function forwardToEvm( + uint16 targetChain, + address targetAddress, + bytes memory payload, + uint256 receiverValue, + uint256 paymentForExtraReceiverValue, + uint256 gasLimit, + uint16 refundChain, + address refundAddress, + address deliveryProviderAddress, + VaaKey[] memory vaaKeys, + uint8 consistencyLevel + ) external payable; + + /** + * @notice Performs the same function as a `send`, except: + * 1) Can only be used during a delivery (i.e. in execution of `receiveWormholeMessages`) + * 2) Is paid for (along with any other calls to forward) by (any msg.value passed in) + (refund leftover from current delivery) + * 3) Only executes after `receiveWormholeMessages` is completed (and thus does not return a sequence number) + * + * The refund from the delivery currently in progress will not be sent to the user; it will instead + * be paid to the delivery provider to perform the instruction specified here + * + * Publishes an instruction for the delivery provider at `deliveryProviderAddress` + * to relay a payload and VAAs specified by `vaaKeys` to the address `targetAddress` on chain `targetChain` + * with `msg.value` equal to + * receiverValue + (arbitrary amount that is paid for by paymentForExtraReceiverValue of this chain's wei) in targetChain wei. + * + * Any refunds (from leftover gas) will be sent to `refundAddress` on chain `refundChain` + * `targetAddress` must implement the IWormholeReceiver interface + * + * The following equation must be satisfied (sum_f indicates summing over all forwards requested in `receiveWormholeMessages`): + * (refund amount from current execution of receiveWormholeMessages) + sum_f [msg.value_f] + * >= sum_f [quoteDeliveryPrice(targetChain_f, receiverValue_f, encodedExecutionParameters_f, deliveryProviderAddress_f) + paymentForExtraReceiverValue_f] + * + * The difference between the two sides of the above inequality will be added to `paymentForExtraReceiverValue` of the first forward requested + * + * @param targetChain in Wormhole Chain ID format + * @param targetAddress address to call on targetChain (that implements IWormholeReceiver), in Wormhole bytes32 format + * @param payload arbitrary bytes to pass in as parameter in call to `targetAddress` + * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) + * @param paymentForExtraReceiverValue amount (in current chain currency units) to spend on extra receiverValue + * (in addition to the `receiverValue` specified) + * @param encodedExecutionParameters encoded information on how to execute delivery that may impact pricing + * e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` with which to call `targetAddress` + * @param refundChain The chain to deliver any refund to, in Wormhole Chain ID format + * @param refundAddress The address on `refundChain` to deliver any refund to, in Wormhole bytes32 format + * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider + * @param vaaKeys Additional VAAs to pass in as parameter in call to `targetAddress` + * @param consistencyLevel Consistency level with which to publish the delivery instructions - see + * https://book.wormhole.com/wormhole/3_coreLayerContracts.html?highlight=consistency#consistency-levels + */ + function forward( + uint16 targetChain, + bytes32 targetAddress, + bytes memory payload, + uint256 receiverValue, + uint256 paymentForExtraReceiverValue, + bytes memory encodedExecutionParameters, + uint16 refundChain, + bytes32 refundAddress, + address deliveryProviderAddress, + VaaKey[] memory vaaKeys, + uint8 consistencyLevel + ) external payable; + + /** + * @notice Requests a previously published delivery instruction to be redelivered + * (e.g. with a different delivery provider) + * + * This function must be called with `msg.value` equal to + * quoteEVMDeliveryPrice(targetChain, newReceiverValue, newGasLimit, newDeliveryProviderAddress) + * + * @notice *** This will only be able to succeed if the following is true ** + * - newGasLimit >= gas limit of the old instruction + * - newReceiverValue >= receiver value of the old instruction + * - newDeliveryProvider's `targetChainRefundPerGasUnused` >= old relay provider's `targetChainRefundPerGasUnused` + * + * @param deliveryVaaKey VaaKey identifying the wormhole message containing the + * previously published delivery instructions + * @param targetChain The target chain that the original delivery targeted. Must match targetChain from original delivery instructions + * @param newReceiverValue new msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) + * @param newGasLimit gas limit with which to call `targetAddress`. Any units of gas unused will be refunded according to the + * `targetChainRefundPerGasUnused` rate quoted by the delivery provider, to the refund chain and address specified in the original request + * @param newDeliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider + * @return sequence sequence number of published VAA containing redelivery instructions + * + * @notice *** This will only be able to succeed if the following is true ** + * - newGasLimit >= gas limit of the old instruction + * - newReceiverValue >= receiver value of the old instruction + * - newDeliveryProvider's `targetChainRefundPerGasUnused` >= old relay provider's `targetChainRefundPerGasUnused` + */ + function resendToEvm( + VaaKey memory deliveryVaaKey, + uint16 targetChain, + uint256 newReceiverValue, + uint256 newGasLimit, + address newDeliveryProviderAddress + ) external payable returns (uint64 sequence); + + /** + * @notice Requests a previously published delivery instruction to be redelivered + * + * + * This function must be called with `msg.value` equal to + * quoteDeliveryPrice(targetChain, newReceiverValue, newEncodedExecutionParameters, newDeliveryProviderAddress) + * + * @param deliveryVaaKey VaaKey identifying the wormhole message containing the + * previously published delivery instructions + * @param targetChain The target chain that the original delivery targeted. Must match targetChain from original delivery instructions + * @param newReceiverValue new msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) + * @param newEncodedExecutionParameters new encoded information on how to execute delivery that may impact pricing + * e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` with which to call `targetAddress` + * @param newDeliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider + * @return sequence sequence number of published VAA containing redelivery instructions + * + * @notice *** This will only be able to succeed if the following is true ** + * - (For EVM_V1) newGasLimit >= gas limit of the old instruction + * - newReceiverValue >= receiver value of the old instruction + * - (For EVM_V1) newDeliveryProvider's `targetChainRefundPerGasUnused` >= old relay provider's `targetChainRefundPerGasUnused` + */ + function resend( + VaaKey memory deliveryVaaKey, + uint16 targetChain, + uint256 newReceiverValue, + bytes memory newEncodedExecutionParameters, + address newDeliveryProviderAddress + ) external payable returns (uint64 sequence); + + /** + * @notice Returns the price to request a relay to chain `targetChain`, using the default delivery provider + * + * @param targetChain in Wormhole Chain ID format + * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) + * @param gasLimit gas limit with which to call `targetAddress`. + * @return nativePriceQuote Price, in units of current chain currency, that the delivery provider charges to perform the relay + * @return targetChainRefundPerGasUnused amount of target chain currency that will be refunded per unit of gas unused, + * if a refundAddress is specified + */ + function quoteEVMDeliveryPrice(uint16 targetChain, uint256 receiverValue, uint256 gasLimit) + external + view + returns (uint256 nativePriceQuote, uint256 targetChainRefundPerGasUnused); + + /** + * @notice Returns the price to request a relay to chain `targetChain`, using delivery provider `deliveryProviderAddress` + * + * @param targetChain in Wormhole Chain ID format + * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) + * @param gasLimit gas limit with which to call `targetAddress`. + * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider + * @return nativePriceQuote Price, in units of current chain currency, that the delivery provider charges to perform the relay + * @return targetChainRefundPerGasUnused amount of target chain currency that will be refunded per unit of gas unused, + * if a refundAddress is specified + */ + function quoteEVMDeliveryPrice( + uint16 targetChain, + uint256 receiverValue, + uint256 gasLimit, + address deliveryProviderAddress + ) external view returns (uint256 nativePriceQuote, uint256 targetChainRefundPerGasUnused); + + /** + * @notice Returns the price to request a relay to chain `targetChain`, using delivery provider `deliveryProviderAddress` + * + * @param targetChain in Wormhole Chain ID format + * @param receiverValue msg.value that delivery provider should pass in for call to `targetAddress` (in targetChain currency units) + * @param encodedExecutionParameters encoded information on how to execute delivery that may impact pricing + * e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` with which to call `targetAddress` + * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider + * @return nativePriceQuote Price, in units of current chain currency, that the delivery provider charges to perform the relay + * @return encodedExecutionInfo encoded information on how the delivery will be executed + * e.g. for version EVM_V1, this is a struct that encodes the `gasLimit` and `targetChainRefundPerGasUnused` + * (which is the amount of target chain currency that will be refunded per unit of gas unused, + * if a refundAddress is specified) + */ + function quoteDeliveryPrice( + uint16 targetChain, + uint256 receiverValue, + bytes memory encodedExecutionParameters, + address deliveryProviderAddress + ) external view returns (uint256 nativePriceQuote, bytes memory encodedExecutionInfo); + + /** + * @notice Returns the (extra) amount of target chain currency that `targetAddress` + * will be called with, if the `paymentForExtraReceiverValue` field is set to `currentChainAmount` + * + * @param targetChain in Wormhole Chain ID format + * @param currentChainAmount The value that `paymentForExtraReceiverValue` will be set to + * @param deliveryProviderAddress The address of the desired delivery provider's implementation of IDeliveryProvider + * @return targetChainAmount The amount such that if `targetAddress` will be called with `msg.value` equal to + * receiverValue + targetChainAmount + */ + function quoteNativeForChain(uint16 targetChain, uint256 currentChainAmount, address deliveryProviderAddress) + external + view + returns (uint256 targetChainAmount); + + /** + * @notice Returns the address of the current default delivery provider + * @return deliveryProvider The address of (the default delivery provider)'s contract on this source + * chain. This must be a contract that implements IDeliveryProvider. + */ + function getDefaultDeliveryProvider() external view returns (address deliveryProvider); +} + +/** + * @title IWormholeRelayerDelivery + * @notice The interface to execute deliveries. Only relevant for Delivery Providers + */ +interface IWormholeRelayerDelivery is IWormholeRelayerBase { + enum DeliveryStatus { + SUCCESS, + RECEIVER_FAILURE, + FORWARD_REQUEST_FAILURE, + FORWARD_REQUEST_SUCCESS + } + + enum RefundStatus { + REFUND_SENT, + REFUND_FAIL, + CROSS_CHAIN_REFUND_SENT, + CROSS_CHAIN_REFUND_FAIL_PROVIDER_NOT_SUPPORTED, + CROSS_CHAIN_REFUND_FAIL_NOT_ENOUGH + } + + /** + * @custom:member recipientContract - The target contract address + * @custom:member sourceChain - The chain which this delivery was requested from (in wormhole + * ChainID format) + * @custom:member sequence - The wormhole sequence number of the delivery VAA on the source chain + * corresponding to this delivery request + * @custom:member deliveryVaaHash - The hash of the delivery VAA corresponding to this delivery + * request + * @custom:member gasUsed - The amount of gas that was used to call your target contract + * @custom:member status: + * - RECEIVER_FAILURE, if the target contract reverts + * - SUCCESS, if the target contract doesn't revert and no forwards were requested + * - FORWARD_REQUEST_FAILURE, if the target contract doesn't revert, forwards were requested, + * but provided/leftover funds were not sufficient to cover them all + * - FORWARD_REQUEST_SUCCESS, if the target contract doesn't revert and all forwards are covered + * @custom:member additionalStatusInfo: + * - If status is SUCCESS or FORWARD_REQUEST_SUCCESS, then this is empty. + * - If status is RECEIVER_FAILURE, this is `RETURNDATA_TRUNCATION_THRESHOLD` bytes of the + * return data (i.e. potentially truncated revert reason information). + * - If status is FORWARD_REQUEST_FAILURE, this is also the revert data - the reason the forward failed. + * This will be either an encoded Cancelled, DeliveryProviderReverted, or DeliveryProviderPaymentFailed error + * @custom:member refundStatus - Result of the refund. REFUND_SUCCESS or REFUND_FAIL are for + * refunds where targetChain=refundChain; the others are for targetChain!=refundChain, + * where a cross chain refund is necessary + * @custom:member overridesInfo: + * - If not an override: empty bytes array + * - Otherwise: An encoded `DeliveryOverride` + */ + event Delivery( + address indexed recipientContract, + uint16 indexed sourceChain, + uint64 indexed sequence, + bytes32 deliveryVaaHash, + DeliveryStatus status, + uint256 gasUsed, + RefundStatus refundStatus, + bytes additionalStatusInfo, + bytes overridesInfo + ); + + /** + * @notice The delivery provider calls `deliver` to relay messages as described by one delivery instruction + * + * The delivery provider must pass in the specified (by VaaKeys[]) signed wormhole messages (VAAs) from the source chain + * as well as the signed wormhole message with the delivery instructions (the delivery VAA) + * + * The messages will be relayed to the target address (with the specified gas limit and receiver value) iff the following checks are met: + * - the delivery VAA has a valid signature + * - the delivery VAA's emitter is one of these WormholeRelayer contracts + * - the delivery provider passed in at least enough of this chain's currency as msg.value (enough meaning the maximum possible refund) + * - the instruction's target chain is this chain + * - the relayed signed VAAs match the descriptions in container.messages (the VAA hashes match, or the emitter address, sequence number pair matches, depending on the description given) + * + * @param encodedVMs - An array of signed wormhole messages (all from the same source chain + * transaction) + * @param encodedDeliveryVAA - Signed wormhole message from the source chain's WormholeRelayer + * contract with payload being the encoded delivery instruction container + * @param relayerRefundAddress - The address to which any refunds to the delivery provider + * should be sent + * @param deliveryOverrides - Optional overrides field which must be either an empty bytes array or + * an encoded DeliveryOverride struct + */ + function deliver( + bytes[] memory encodedVMs, + bytes memory encodedDeliveryVAA, + address payable relayerRefundAddress, + bytes memory deliveryOverrides + ) external payable; +} + +interface IWormholeRelayer is IWormholeRelayerDelivery, IWormholeRelayerSend {} + +/* + * Errors thrown by IWormholeRelayer contract + */ + +// Bound chosen by the following formula: `memoryWord * 4 + selectorSize`. +// This means that an error identifier plus four fixed size arguments should be available to developers. +// In the case of a `require` revert with error message, this should provide 2 memory word's worth of data. +uint256 constant RETURNDATA_TRUNCATION_THRESHOLD = 132; + +//When msg.value was not equal to `delivery provider's quoted delivery price` + `paymentForExtraReceiverValue` +error InvalidMsgValue(uint256 msgValue, uint256 totalFee); + +error RequestedGasLimitTooLow(); + +error DeliveryProviderDoesNotSupportTargetChain(address relayer, uint16 chainId); +error DeliveryProviderCannotReceivePayment(); + +//When calling `forward()` on the WormholeRelayer if no delivery is in progress +error NoDeliveryInProgress(); +//When calling `delivery()` a second time even though a delivery is already in progress +error ReentrantDelivery(address msgSender, address lockedBy); +//When any other contract but the delivery target calls `forward()` on the WormholeRelayer while a +// delivery is in progress +error ForwardRequestFromWrongAddress(address msgSender, address deliveryTarget); + +error InvalidPayloadId(uint8 parsed, uint8 expected); +error InvalidPayloadLength(uint256 received, uint256 expected); +error InvalidVaaKeyType(uint8 parsed); + +error InvalidDeliveryVaa(string reason); +//When the delivery VAA (signed wormhole message with delivery instructions) was not emitted by the +// registered WormholeRelayer contract +error InvalidEmitter(bytes32 emitter, bytes32 registered, uint16 chainId); +error VaaKeysLengthDoesNotMatchVaasLength(uint256 keys, uint256 vaas); +error VaaKeysDoNotMatchVaas(uint8 index); +//When someone tries to call an external function of the WormholeRelayer that is only intended to be +// called by the WormholeRelayer itself (to allow retroactive reverts for atomicity) +error RequesterNotWormholeRelayer(); + +//When trying to relay a `DeliveryInstruction` to any other chain but the one it was specified for +error TargetChainIsNotThisChain(uint16 targetChain); +error ForwardNotSufficientlyFunded(uint256 amountOfFunds, uint256 amountOfFundsNeeded); +//When a `DeliveryOverride` contains a gas limit that's less than the original +error InvalidOverrideGasLimit(); +//When a `DeliveryOverride` contains a receiver value that's less than the original +error InvalidOverrideReceiverValue(); +//When a `DeliveryOverride` contains a 'refund per unit of gas unused' that's less than the original +error InvalidOverrideRefundPerGasUnused(); + +//When the delivery provider doesn't pass in sufficient funds (i.e. msg.value does not cover the +// maximum possible refund to the user) +error InsufficientRelayerFunds(uint256 msgValue, uint256 minimum); + +//When a bytes32 field can't be converted into a 20 byte EVM address, because the 12 padding bytes +// are non-zero (duplicated from Utils.sol) +error NotAnEvmAddress(bytes32); \ No newline at end of file diff --git a/packages/zk-circuits/package.json b/packages/zk-circuits/package.json index 192986f..a82565b 100644 --- a/packages/zk-circuits/package.json +++ b/packages/zk-circuits/package.json @@ -3,8 +3,11 @@ "version": "0.1.0", "main": "index.js", "scripts": { + "compile": "hardhat compile", "deploy": "hardhat deploy:kamui --network sepolia --verify", "deploy:zk": "hardhat deploy:verifier --network sepolia --verify", + "deploy:wormsrc": "hardhat deploy:wormsrc --network sepolia --verify", + "deploy:wormdst": "hardhat deploy:wormdst --network goerli --verify", "circom:dev": "hardhat circom --deterministic --debug --verbose", "zk": "ts-node scripts/zk/verify.ts", "test": "echo \"Error: no test specified\" && exit 1" diff --git a/packages/zk-circuits/scripts/address/goerli/WormKamuiDst.json b/packages/zk-circuits/scripts/address/goerli/WormKamuiDst.json new file mode 100644 index 0000000..3304920 --- /dev/null +++ b/packages/zk-circuits/scripts/address/goerli/WormKamuiDst.json @@ -0,0 +1 @@ +{"main":"0xd09A679e9FDdffaD016a4fB24597499B0154B189"} \ No newline at end of file diff --git a/packages/zk-circuits/scripts/address/sepolia/WormKamuiSrc.json b/packages/zk-circuits/scripts/address/sepolia/WormKamuiSrc.json new file mode 100644 index 0000000..93fd1c0 --- /dev/null +++ b/packages/zk-circuits/scripts/address/sepolia/WormKamuiSrc.json @@ -0,0 +1 @@ +{"main":"0x585Cd0096cEceB30A8a9698C73Ec19EB4E36e6b1"} \ No newline at end of file diff --git a/packages/zk-circuits/scripts/tasks/deployProcess.ts b/packages/zk-circuits/scripts/tasks/deployProcess.ts index 8377992..6a5a0db 100644 --- a/packages/zk-circuits/scripts/tasks/deployProcess.ts +++ b/packages/zk-circuits/scripts/tasks/deployProcess.ts @@ -105,3 +105,86 @@ task('deploy:kamui', 'Deploy contract') } }, ) + + task('deploy:wormsrc', 'Deploy contract verifier') + .addFlag('verify', 'Validate contract after deploy') + .setAction(async ({verify}, hre) => { + await hre.run('compile') + const [signer] = await hre.ethers.getSigners() + const contractFactory = await hre.ethers.getContractFactory('contracts/WormKamuiSrc.sol:WormKamuiSrc') + + const contractAddress = fs.readFileSync(`scripts/address/${hre.network.name}/CircuitsVerifier.json`) + const himitsuAddress = JSON.parse(contractAddress.toString()) + + const feeData = await hre.ethers.provider.getFeeData() + const deployContract = await contractFactory.connect(signer).deploy(himitsuAddress.main,{ + maxPriorityFeePerGas: feeData.maxPriorityFeePerGas, + maxFeePerGas: feeData.maxFeePerGas, + gasLimit: 4000000, + }) + console.log(`WormKamuiSrc.sol deployed to ${deployContract.address}`) + + const address = { + main: deployContract.address, + } + const addressData = JSON.stringify(address) + writeFileSync(`scripts/address/${hre.network.name}/`, 'WormKamuiSrc.json', addressData) + + await deployContract.deployed() + + if (verify) { + console.log('verifying contract...') + await deployContract.deployTransaction.wait(5) + + try { + await hre.run('verify:verify', { + address: deployContract.address, + constructorArguments: [himitsuAddress.main], + contract: 'contracts/WormKamuiSrc.sol:WormKamuiSrc', + }) + } catch (e) { + console.log(e) + } + } + }, + ) + + task('deploy:wormdst', 'Deploy contract verifier') + .addFlag('verify', 'Validate contract after deploy') + .setAction(async ({verify}, hre) => { + await hre.run('compile') + const [signer] = await hre.ethers.getSigners() + const contractFactory = await hre.ethers.getContractFactory('contracts/WormKamuiDst.sol:WormKamuiDst') + + const feeData = await hre.ethers.provider.getFeeData() + const deployContract = await contractFactory.connect(signer).deploy({ + maxPriorityFeePerGas: feeData.maxPriorityFeePerGas, + maxFeePerGas: feeData.maxFeePerGas, + gasLimit: 4000000, + }) + console.log(`WormKamuiDst.sol deployed to ${deployContract.address}`) + + const address = { + main: deployContract.address, + } + const addressData = JSON.stringify(address) + writeFileSync(`scripts/address/${hre.network.name}/`, 'WormKamuiDst.json', addressData) + + await deployContract.deployed() + + if (verify) { + console.log('verifying contract...') + await deployContract.deployTransaction.wait(5) + + try { + await hre.run('verify:verify', { + address: deployContract.address, + constructorArguments: [], + contract: 'contracts/WormKamuiDst.sol:WormKamuiDst', + }) + } catch (e) { + console.log(e) + } + } + }, + ) \ No newline at end of file