Skip to content

Commit

Permalink
feat: wormhole all chain verify
Browse files Browse the repository at this point in the history
  • Loading branch information
kidneyweakx committed Aug 24, 2023
1 parent 724deb8 commit bd85111
Show file tree
Hide file tree
Showing 5 changed files with 1,044 additions and 0 deletions.
57 changes: 57 additions & 0 deletions packages/zk-circuits/contracts/WormExample.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "./interface/IWormholeRelayer.sol";
import "./interface/IWormholeReceiver.sol";

contract HelloWormhole is IWormholeReceiver {
event GreetingReceived(string greeting, uint16 senderChain, address sender);

uint256 constant GAS_LIMIT = 50_000;

IWormholeRelayer public immutable wormholeRelayer;

string public latestGreeting;

constructor(address _wormholeRelayer) {
wormholeRelayer = IWormholeRelayer(_wormholeRelayer);
}

function quoteCrossChainGreeting(uint16 targetChain) public view returns (uint256 cost) {
(cost,) = wormholeRelayer.quoteEVMDeliveryPrice(targetChain, 0, GAS_LIMIT);
}

function sendCrossChainGreeting(uint16 targetChain, address targetAddress, string memory greeting) public payable {
uint256 cost = quoteCrossChainGreeting(targetChain);
require(msg.value == cost);
wormholeRelayer.sendPayloadToEvm{value: cost}(
targetChain,
targetAddress,
abi.encode(greeting, msg.sender), // payload
0, // no receiver value needed since we're just passing a message
GAS_LIMIT
);
}

mapping(bytes32 => bool) public seenDeliveryVaaHashes;

function receiveWormholeMessages(
bytes memory payload,
bytes[] memory, // additionalVaas
bytes32, // address that called 'sendPayloadToEvm' (HelloWormhole contract address)
uint16 sourceChain,
bytes32 deliveryHash // this can be stored in a mapping deliveryHash => bool to prevent duplicate deliveries
) public payable override {
require(msg.sender == address(wormholeRelayer), "Only relayer allowed");

// Ensure no duplicate deliveries
require(!seenDeliveryVaaHashes[deliveryHash], "Message already processed");
seenDeliveryVaaHashes[deliveryHash] = true;

// Parse the payload and do the corresponding actions!
(string memory greeting, address sender) = abi.decode(payload, (string, address));
latestGreeting = greeting;
emit GreetingReceived(latestGreeting, sourceChain, sender);
}

}
86 changes: 86 additions & 0 deletions packages/zk-circuits/contracts/WormKamuiField.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.7.0 <0.9.0;

import "./interface/ICircuitsVerifier.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract KamuiField is Ownable {
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;
}

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);
}

function registerUser(address user, uint proof) public onlyOwner {
users[user] = [proof];
}
}
148 changes: 148 additions & 0 deletions packages/zk-circuits/contracts/interface/IWormhole.sol
Original file line number Diff line number Diff line change
@@ -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;
}
49 changes: 49 additions & 0 deletions packages/zk-circuits/contracts/interface/IWormholeReceiver.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// SPDX-License-Identifier: Apache 2

pragma solidity ^0.8.0;

/**
* @notice Interface for a contract which can receive Wormhole messages.
*/
interface IWormholeReceiver {
/**
* @notice When a `send` is performed with this contract as the target, this function will be
* invoked by the WormholeRelayer contract
*
* NOTE: This function should be restricted such that only the Wormhole Relayer contract can call it.
*
* We also recommend that this function:
* - Stores all received `deliveryHash`s in a mapping `(bytes32 => bool)`, and
* on every call, checks that deliveryHash has not already been stored in the
* map (This is to prevent other users maliciously trying to relay the same message)
* - Checks that `sourceChain` and `sourceAddress` are indeed who
* you expect to have requested the calling of `send` or `forward` on the source chain
*
* The invocation of this function corresponding to the `send` request will have msg.value equal
* to the receiverValue specified in the send request.
*
* If the invocation of this function reverts or exceeds the gas limit
* specified by the send requester, this delivery will result in a `ReceiverFailure`.
*
* @param payload - an arbitrary message which was included in the delivery by the
* requester.
* @param additionalVaas - Additional VAAs which were requested to be included in this delivery.
* They are guaranteed to all be included and in the same order as was specified in the
* delivery request.
* @param sourceAddress - the (wormhole format) address on the sending chain which requested
* this delivery.
* @param sourceChain - the wormhole chain ID where this delivery was requested.
* @param deliveryHash - the VAA hash of the deliveryVAA.
*
* NOTE: These signedVaas are NOT verified by the Wormhole core contract prior to being provided
* to this call. Always make sure `parseAndVerify()` is called on the Wormhole core contract
* before trusting the content of a raw VAA, otherwise the VAA may be invalid or malicious.
*/
function receiveWormholeMessages(
bytes memory payload,
bytes[] memory additionalVaas,
bytes32 sourceAddress,
uint16 sourceChain,
bytes32 deliveryHash
) external payable;
}
Loading

0 comments on commit bd85111

Please sign in to comment.