This commit is contained in:
spacemandev 2022-08-10 05:15:30 -05:00
commit f426021989
9 changed files with 44 additions and 32 deletions

View File

@ -1,6 +1,6 @@
# Receving Messages on EVM
To receive messages in EVM we need to implement a function `receiveMsg`. The name of this function is arbitrary, any function name works as long as your relayer knows what to call on the application contract when submitting messages.
To receive messages in EVM, first we need to implement a function `receiveMsg`. The name of this function is arbitrary, so any function name will work as long as your relayer knows what to call on the application contract when submitting messages.
This function will take in an encoded set of `bytes` as the VAA and then call the `parseAndVerifyVM` function on the Core Bridge to validate the message.

View File

@ -1,9 +1,9 @@
# Overview of Receving Messages
The basic flow of receving messages requires you (or a relayer!) to submit the VAA to your application contract. This contract then calls the Core Bridge on the receving chain to check the message signatures against the stored guardian set signatures.
Receving messages requires you (or a relayer) to submit the VAA to your application contract. This contract then calls the Core Bridge on the receving chain to check the message signatures against the stored Guardian set signatures.
If those checks pass, then the application can check to see if it's a message that's already been processed before by checking it's sequence number against a store list of processed message sequence numbers.
If those checks pass, then the application can see if it's a message that's already been processed by checking its sequence number against a store list of processed message sequence numbers.
The final optional check is to make sure that the message came from an application from the source chain that we were expecting. Usually this is our own application, and should be registered during initialization steps (see [registration](../registration/overview.md)).
After we have ensured all those things are correct, we can go ahead and process the message according to the business logic in our application.
After we have ensured all those things are correct, we can process the message according to the business logic in our application.

View File

@ -1,6 +1,8 @@
# Registering Emitters: EVM
Specifying applications that our EVM application is allowed to listen to is a fairly simple process; We can create a mapping of chainId to bytes32 addresses of the relevant contracts on other chains. The chainId used here is the *wormhole* chainId, and the address used here is the address in *bytes*.
To specify applications that our EVM application is allowed to listen to, we can create a mapping of chainId to bytes32 addresses of the relevant contracts on other chains.
The chainId used here is the *wormhole* chainId, and the address used here is the address in *bytes*.
```solidity
@ -23,4 +25,4 @@ contract Messenger {
}
```
If you have more than one address per chainId that you want to listen to, consider making the mapping into bytes32[].
If you have more than one address per chainId that you want to listen to, consider making the mapping into bytes32[].

View File

@ -1,7 +1,7 @@
# Registering Emitters
This is not strictly required, but when writing xDapps, you want to listen for messages from *specific* apps on other chains, otherwise attacks could create fake applications that emit messages that *look* like what we expect, but have fake payloads.
While not strictly required, when writing xDapps it's important to listen for messages from *specific* apps on other chains, otherwise attacks could create fake applications that emit messages that *look* like what we expect, but have fake payloads.
To do this, we register the sending contract's addresses with the receiving contracts. Because each VAA has the contract address that asked the core bridge to *emit* the VAA, we call the sending contracts *emitters*. Also, the emitters you're listening to *do not* need to be your own contracts. You might want to listen to the emits of a different xDapp, in which case you'd register it's address in your code.
To do this, we register the sending contract's addresses with the receiving contracts. Because each VAA has the contract address that asked the core bridge to *emit* the VAA, we call the sending contracts *emitters*. Additionally, the emitters you're listening to *do not* need to be your own contracts. You might want to listen to the emits of a different xDapp, in which case you'd register its address in your code.
Then, when receiving messages, we can check the VAA being submitted, and make sure that the VAA being submitted came from one of the contracts we were expecting and *from the chain* we were expecting.
Then, when receiving messages, we can check the VAA being submitted to make sure it came from one of the contracts we were expecting and *from the chain* we were expecting.

View File

@ -4,12 +4,12 @@ Relaying Messages can be done one of three ways:
1. Manual Relaying
Manual Relaying is usally done on the front end, and has the front end fetch the VAA it just created and then submit on the target chain. This means the user ends up paying for the gas fee to submit the tx on the target chain and has to go through the additional step.
Manual Relaying is usally done on the front end. Manual relyaing requires the front end to fetch the VAA it just created and then submit on the target chain. This means the user ends up paying for the gas fee and has to go through the additional step to submit the tx on the target chain.
2. Protocol Specific Relayers
Protocols and Apps can run their own relayers, listening to messages as they are created by the Core Bridge and submitting them to their application on the target chain. This is the ideal user experience but means more work for the developer.
Protocols and Apps can run their own relayers, listening to messages as they are created by the Core Bridge and submitting them to their application on the target chain. This is the ideal user experience but requires more work from the developer.
3. Generic Relayers
Generic Relayers can pick up any app or protocol's messages and submit them to the target chain for a fee. This is the ideal developer and user experience, but still being developed.
Generic Relayers can pick up any app or protocol's messages and submit them to the target chain for a fee. This is the ideal developer and user experience, but is still being developed.

View File

@ -1,7 +1,8 @@
# Sending Messages: EVM
To send messages from EVM, first we have to download the Core Bridge interfaces. We need two interfaces, [IWormhole.sol](https://github.com/certusone/wormhole/raw/dev.v2/ethereum/contracts/interfaces/IWormhole.sol) and [Structs.sol](https://github.com/certusone/wormhole/raw/dev.v2/ethereum/contracts/Structs.sol)
To send messages from EVM, first we have to download the Core Bridge interfaces.
We need two interfaces, [IWormhole.sol](https://github.com/certusone/wormhole/raw/dev.v2/ethereum/contracts/interfaces/IWormhole.sol) and [Structs.sol](https://github.com/certusone/wormhole/raw/dev.v2/ethereum/contracts/Structs.sol)
In your xdapp-starter, place those files in
```
@ -13,7 +14,7 @@ In your xdapp-starter, place those files in
- Structs.sol
```
also, let's modify the IWormhole.sol file to update the import for Structs.sol.
Let's also modify the IWormhole.sol file to update the import for Structs.sol.
```solidity
// contracts/Messages.sol
@ -27,9 +28,9 @@ import "./Structs.sol";
```
Now, let's create a new contract in our src/ folder `Messenger.sol`. In this contract, we also create a uint32 nonce. You can think of this nonce like a message id, it's just a number that let's the receiving contract know if it's already processed a message.
Now, let's create a new contract in our src/ folder `Messenger.sol`. In this contract, we'll also create a uint32 nonce. You can think of this nonce like a message id--it's just a number that lets the receiving contract know if it has already processed a message.
Also we'll set the consistency level here to 1, because we're just testing and want the Guardians to sign this VAA as soon as they see it, but if we were deploying to production, we might want to match this level to the deployed chain's finality guarantees.
Also, we'll set the consistency level here to 1, because we're just testing and want the Guardians to sign this VAA as soon as they see it. If we were deploying to production, we might want to match this level to the deployed chain's finality guarantees.
```solidity

View File

@ -1,12 +1,17 @@
# Overview of Sending Messages
While the specific code varies chain by chain, the basic flow of sending a message requires your contract to interact with the Core Bridge contract deployed on each chain to emit a VAA.
While the specific code varies chain by chain, sending a message always requires your contract to interact with the Core Bridge contract deployed on each chain to emit a VAA.
To emit a VAA requires three pieces of information:
Emitting a VAA requires three pieces of information:
1. Nonce (u32)
- The nonce is a random number assigned to each message. This allows the receiving contract a way to make sure it doesn't double process messages.
The nonce is a random number assigned to each message. This allows the receiving contract a way to make sure it doesn't double process messages.
2. Consistency (u8)
- This is the number of blocks for Guardians to wait before they sign the message. Higher consistencies mean more security against blockchain reorgs. For example, if this is set too low, and the block you're emitting from reorgs, then it's possible that even though the message was emitted and signed by the Guardians and processed on the receiving chain, no record of it exists on the emitting chain. If you were sending tokens across, this would allow for double spend attacks.
This is the number of blocks for Guardians to wait before they sign the message. Higher consistencies mean more security against blockchain reorgs. For example, if this is set too low, and the block you're emitting from reorgs, then it's possible that even though the message was emitted and signed by the Guardians and processed on the receiving chain, no record of it exists on the emitting chain. If you were sending tokens across, this would allow for double spend attacks.
3. Payload (bytes[])
- This is a payload of raw bytes that you want to emit. It's up to the receiving contract to know how to parse it.
This is a payload of raw bytes that you want to emit. It's up to the receiving contract to know how to parse it.

View File

@ -1,18 +1,22 @@
# Portal Token Bridge Transfers
One of the biggest applications built on Wormhole is the Portal Token Bridge, which uses structured payloads to transfer tokens and NFTs from one wallet to another.
Portal Token Bridge is one of the biggest applications built on Wormhole. It uses structured payloads to transfer tokens and NFTs from one wallet to another.
## Attesting a Token
Before a token can be transferred, the token need to be *attested* to another chain. To attest a token, you first create a AssetMeta VAA by calling the `attest()` function on Token Bridge. Then you take the VAA over to the receipient chain, where you call `createWrapped()` which deploys a wrapped version of the Token.
This only needs to happen *once* per payload, and trying to attest a token a second time will simply result in the address of the already created Wrapped Token Address.
This only needs to happen *once* per payload, and trying to attest a token a second time will simply result in the address of the already-created Wrapped Token Address.
## Transfering Tokens
To transfer tokens, the payer of tokens first authorizes the Token Bridge contract to move the tokens on their behalf, then locks them up with the Token Bridge, which emits a VAA. This VAA can then be submitted on target chain's Token Bridge's `completeTransfer()` to mint the wrapped version of the Token.
If the token being transferred is native to the chain it's being transfered to, you'll receive the original token back, rather than a wrapped version.
When transfering tokens from Chain A to B to C, the token is only "wrapped" once, as every time it's attested, it's always from the chain the token is natively located on.
Usually there's two functions for transfer, `transfer()` and `transferNative()`. This is because native currencies of most blockchains (ETH on Ethereum, SOL on Solana, etc) don't follow the Token spec of that chain, so to transfer native currencies, we usually wrap them first into a tokenized version of them and then transfer.
To transfer tokens, the payer of tokens first authorizes the Token Bridge contract to move the tokens on their behalf, then locks them up with the Token Bridge, which then emits a VAA. This VAA can then be submitted on target chain's Token Bridge's `completeTransfer()` to mint the wrapped version of the Token.
When transfering tokens from Chain A to B and beyond, the token is only "wrapped" once, as every time it's attested, it's always from the chain the token is natively located on. If the token being transferred is native to the chain it's being transfered to, you'll receive the original token back instread of a wrapped version.
There are typically two functions for transfer: `transfer()` and `transferNative()`. This is because native currencies of most blockchains (ETH on Ethereum, SOL on Solana, etc) don't follow the Token spec of that chain, so to transfer native currencies, we wrap them first into a tokenized version and then transfer.
For transfers, there's also an arbiterFee you can set. If this fee is set, when `completeTransfer()` is called, that amount of tokens are withheld from the release of tokens on the target chain and instead given to the submitter of the message (for example, a relayer). This allows third party to submit transactions on your behalf, for a fee.
## Transfering with a Payload
Transfering with a Payload is much like transfering normal tokens, with two major differences. First, as the name implies, you can attach a bytes payload to the transfer message. Secondly, the `completeTransfer()` function for Transfer with Payload can *only* be called by the receipient of that VAA. This means the flow is slightly different, instead of the user calling the `completeTransfer()` function on the Token Bridge, they call a function on the application they are interacting with, which will check the payload, do what state changes it needs to make and then call `completeTransfer()` on Token Bridge to mint tokens to itself.
Transfering with a Payload is much like transfering normal tokens, with two major differences.
First, as the name implies, you can attach a bytes payload to the transfer message. Secondly, the `completeTransfer()` function for Transfer with Payload can *only* be called by the receipient of that VAA. This means the flow is slightly different; instead of the user calling the `completeTransfer()` function on the Token Bridge, they call a function on the application they are interacting with which will check the payload, do any state changes it needs to make and then call `completeTransfer()` on Token Bridge to mint tokens to itself.

View File

@ -1,14 +1,14 @@
# Wormhole Local Validator
The Wormhole Local Validator is available [here](https://github.com/certusone/xdapp-book/tree/main/projects/wormhole-local-validator). It contains the wormhole local validator, along with code to spin up EVM and Solana local validators, and deployment code to add Wormhole contracts to those new chains.
The Wormhole Local Validator is available [here](https://github.com/certusone/xdapp-book/tree/main/projects/wormhole-local-validator). Along with the Wormhole Local Validator, this also contains code to spin up EVM and Solana local validators, as well as deployment code to add Wormhole contracts to those new chains.
## Dependencies
You will also need Docker; you can get either [Docker Desktop](https://docs.docker.com/get-docker/) if you're developing on your computer or if you're in a headless VM, install [Docker Engine](https://docs.docker.com/engine/). Make sure to have Docker running before you run any of the following commands.
You will need Docker; if you're developing on your computer you should get [Docker Desktop](https://docs.docker.com/get-docker/), but if you're in a headless VM, install [Docker Engine](https://docs.docker.com/engine/). Make sure to have Docker running before you run any of the following commands.
To run EVM chains you will need [Ganache](https://github.com/trufflesuite/ganache#command-line-use).
To run Solana chains you will need [Solana](https://docs.solana.com/cli/install-solana-cli-tools) installed.
## Run EVM Chains
`npm run evm` will start up two EVM chains with Wormhole Chain ID 2 (like ETH) and Wormhole Chain ID 4 (like BSC) and deploy the Wormhole Core Bridge (`0xC89Ce4735882C9F0f0FE26686c53074E09B0D550`), Token Bridge (`0x0290FB167208Af455bB137780163b7B7a9a10C16`), and NFT Bridge (`0x26b4afb60d6c903165150c6f0aa14f8016be4aec`) contracts to them. They'll also deploy a Test Token (TKN at `0x2D8BE6BF0baA74e0A907016679CaE9190e80dD0A`), test NFT (`0x5b9b42d6e4B2e4Bf8d42Eba32D46918e10899B66`), and WETH Contract (`0xDDb64fE46a91D46ee29420539FC25FD07c5FEa3E`)
`npm run evm` will start up two EVM chains with Wormhole Chain ID 2 (like ETH) and Wormhole Chain ID 4 (like BSC) and deploy the Wormhole Core Bridge (`0xC89Ce4735882C9F0f0FE26686c53074E09B0D550`), Token Bridge (`0x0290FB167208Af455bB137780163b7B7a9a10C16`), and NFT Bridge (`0x26b4afb60d6c903165150c6f0aa14f8016be4aec`) contracts to them. They'll also deploy a Test Token (TKN at `0x2D8BE6BF0baA74e0A907016679CaE9190e80dD0A`), test NFT (`0x5b9b42d6e4B2e4Bf8d42Eba32D46918e10899B66`), and WETH Contract (`0xDDb64fE46a91D46ee29420539FC25FD07c5FEa3E`) as well.
They'll use the standard Wormhole test mnemonic (`myth like bonus scare over problem client lizard pioneer submit female collect`) and use the first key for deployment and payment (Public Key: `0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1`, Private Key: (`0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d`))
@ -23,4 +23,4 @@ Simply run `npm run wormhole`, which will pull and run the Wormhole Guardian doc
### FAQ & Common Problems
- Anvil isn't working
While we recommend Foundry's Forge tool for compiling and deploying code elsewhere in these docs, we *do not* at this time recommend using anvil for guardiand; this is because guardiand is spec'd against go-ethereum, and anvil is out of spec for how it reports block headers (non left padding to normalize length), which means go-ethereum freaks out and can't read anvil headers.
While we recommend Foundry's Forge tool for compiling and deploying code elsewhere in these docs, we *do not* at this time recommend using anvil for guardiand; this is because guardiand is spec'd against go-ethereum, and anvil is out of spec for how it reports block headers (non left padding to normalize length), which means go-ethereum reacts abnormally and can't read anvil headers.