Skip to content

Commit

Permalink
update improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
derpy-duck committed Oct 26, 2023
1 parent 8db8a10 commit a11e814
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 95 deletions.
50 changes: 2 additions & 48 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,17 +228,13 @@ interface IWormholeReceiver {
*
* 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
* We also recommend that this function checks that `sourceChain` and `sourceAddress` are indeed who
* you expect to have requested the calling of `send` 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
* 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
Expand Down Expand Up @@ -276,48 +272,6 @@ So, in receiveWormholeMessages, we want to:
To provide certainty about the validity of the payload, we must restrict the msg.sender of this function to only be the Wormhole Relayer contract. Otherwise, anyone could call this receiveWormholeMessages endpoint with fake greetings, source chains, and source senders.

### One more step

You should store each delivery hash in a mapping from delivery hashes to booleans, to prevent duplicate processing of deliveries! This also gives you a way of tracking the completion of sent deliveries

```solidity
event GreetingReceived(string greeting, uint16 senderChain, address sender);
string public latestGreeting;
mapping(bytes32 => bool) public seenDeliveryVaaHashes;
/**
* @notice Endpoint that the Wormhole Relayer contract will call
* to deliver the greeting
*/
function receiveWormholeMessages(
bytes memory payload,
bytes[] memory, // additionalVaas
bytes32 sourceAddress,
uint16 sourceChain,
bytes32 // deliveryHash
) 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,
fromWormholeFormat(sourceAddress)
);
}
```

And voila, we have a full contract that can be deployed to many EVM chains, and in totality would form a full cross-chain application powered by Wormhole!

Users with any wallet can request greetings to be emitted on any chain that is part of the system.
Expand Down
50 changes: 21 additions & 29 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"clean": "rm -rf ts-scripts/ethers-contracts/; rm -rf out/;"
},
"dependencies": {
"@certusone/wormhole-sdk": "^0.9.20",
"@certusone/wormhole-sdk": "^0.10.5",
"@improbable-eng/grpc-web-node-http-transport": "^0.15.0",
"@typechain/ethers-v5": "^11.0.0",
"ethers": "^5",
Expand Down
30 changes: 18 additions & 12 deletions src/HelloWormhole.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,21 @@ contract HelloWormhole is IWormholeReceiver {
wormholeRelayer = IWormholeRelayer(_wormholeRelayer);
}

function quoteCrossChainGreeting(uint16 targetChain) public view returns (uint256 cost) {
(cost,) = wormholeRelayer.quoteEVMDeliveryPrice(targetChain, 0, GAS_LIMIT);
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 {
function sendCrossChainGreeting(
uint16 targetChain,
address targetAddress,
string memory greeting
) public payable {
uint256 cost = quoteCrossChainGreeting(targetChain);
require(msg.value == cost);
wormholeRelayer.sendPayloadToEvm{value: cost}(
Expand All @@ -33,8 +43,6 @@ contract HelloWormhole is IWormholeReceiver {
);
}

mapping(bytes32 => bool) public seenDeliveryVaaHashes;

function receiveWormholeMessages(
bytes memory payload,
bytes[] memory, // additionalVaas
Expand All @@ -44,14 +52,12 @@ contract HelloWormhole is IWormholeReceiver {
) 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));
(string memory greeting, address sender) = abi.decode(
payload,
(string, address)
);
latestGreeting = greeting;
emit GreetingReceived(latestGreeting, sourceChain, sender);
}

}
}
17 changes: 12 additions & 5 deletions ts-scripts/getStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@ import {
storeDeployedAddresses,
getChain,
loadDeployedAddresses,
} from "./utils"
import {relayer, ChainName} from "@certusone/wormhole-sdk"
} from "./utils";
import { relayer, ChainName } from "@certusone/wormhole-sdk";

export async function getStatus(sourceChain: ChainName, transactionHash: string): Promise<{status: string, info: string}> {
const info = await relayer.getWormholeRelayerInfo(sourceChain, transactionHash, {environment: "TESTNET"});
export async function getStatus(
sourceChain: ChainName,
transactionHash: string
): Promise<{ status: string; info: string }> {
const info = await relayer.getWormholeRelayerInfo(
sourceChain,
transactionHash,
{ environment: "TESTNET" }
);
const status = info.targetChainStatus.events[0].status;
return {status, info: relayer.stringifyWormholeRelayerInfo(info)};
return { status, info: info.stringified || "Info not obtained" };
}

0 comments on commit a11e814

Please sign in to comment.