Beyond Hello Wormhole
Last updated
Was this helpful?
Last updated
Was this helpful?
In Part 1 (), we wrote a fully functioning cross-chain application that allows users to request, from one contract, that a GreetingReceived
event to be emitted from one of the other contracts on a different chain.
In Part 2 (), we discussed how the Wormhole Relayer contract works behind the scenes. In summary, it works by publishing a wormhole message with delivery instructions, which alerts a delivery provider to call the deliver
endpoint of the Wormhole Relayer contract on the target chain, finally calling the designated targetAddress
with the correct inputs
HelloWormhole is a great example application, but has much room for improvement. Let's talk through some ways to improve both the security and features of the application!
Topics covered:
Restricting the sender
Refunds
Chained Deliveries
Delivering existing VAAs
A user doesn’t have to go through the HelloWormhole contract to request a greeting - they can call wormholeRelayer.sendPayloadToEvm{value: cost}(…)
themselves!
This is not ideal if, for example, you wanted to store some information in the source HelloWormhole contract every time a sendCrossChainGreeting
was requested.
Often, it is desirable that all of the requests go through your own source contract.
Solution: We can check, in our implementation of receiveWormholeMessages
, that sourceChain
and sourceAddress
are a valid HelloWormhole contract, and revert otherwise
You can add these helpers into your own project as such:
Often, you cannot predict exactly how much gas your contract will use. To avoid the chance of a 'Receiver Failure' (which occurs when your contract reverts - because, for example, it runs out of gas), you should request a reasonable upper bound for how much gas your contract will use.
However, this means if, e.g. we expect HelloWormhole to take somewhere (uniformly random) between 10000 and 50000 units of gas, we are losing on expectation the cost of 20000 units of gas if we request 50000 units of gas for every request!
If these are specified, then different logic is applied depending on the values of refundChain
and targetChain
If refundChain is equal to targetChain, a refund of
will be sent to address refundAddress
on the target chain.
gasUsed is the amount of gas your contract (at targetAddress
) uses in the call to receiveWormholeMessages
.
Note that this must be less than or equal to gasLimit.
targetChainRefundPerGasUnused is a constant quoted pre-delivery by the delivery provider - this is the second return value of the quoteEVMDeliveryPrice
function:
else (if refundChain is not equal to targetChain), then
The cost to perform a delivery with a gas limit and receiver value of 0 to the refund chain will be calculated (let’s call it BASE_COST)
if TARGET_CHAIN_REFUND = targetChainRefundPerGasUnused * (gasLimit - gasUsed)
is larger than BASE_COST, then a delivery will be performed, and the msg.value
that will be sent to refundAddress
on refundChain
will be
Note: deliveryProviderAddress here is equal to
targetChainWormholeRelayer.quoteDefaultDeliveryProvider
Suppose you wish to request a delivery from chain A to chain B, and then after the delivery has completed on chain B, you wish to deliver some information to chain C.
One way to do this is to call sendPayloadToEvm
within the implementation of receiveWormholeMessages
on chain B. Often in these scenarios, you only have currency on chain A, but you can still request the appropriate amount as your receiverValue
in your delivery request on chain A.
How do you know how much receiver value to request in your delivery on chain A? Unfortunately, the amount you need depends on a quote that the delivery provider on chain B can provide. Our best recommendation here is to expose this 'receiverValue' amount as a parameter on your contract's endpoint, and have the front-end of your application determine the correct value to pass here by querying the WormholeRelayer contract on chain B.
Often times, we wish to deliver a wormhole message that has already been published (by a different contract).
We provide a base class in the that includes the modifier shown above, makes it easy to add these functionalities as such
Included in the HelloWormhole repository is an (and ) that uses these helpers:
Fortunately, the IWormholeRelayer
interface for any gas you do not end up using in your target contract!
Included in the HelloWormhole repository is an (and ) that use this refund feature.
Included in the HelloWormhole repository is an (and ) that go from chain A to chain B to chain C, using the recommendation above.
To do this, use the function, which lets you specify additional published wormhole messages for which the corresponding signed VAAs will be pass in as a parameter in the call to targetAddress
For an example usage of this, see the Wormhole Solidity SDK’s implementation of , which use the TokenBridge wormhole module to send tokens!