From c11882dedb93a64088ec8a01ae82c25e9a3c772e Mon Sep 17 00:00:00 2001 From: Ian Traas <108365619+itraas@users.noreply.github.com> Date: Tue, 9 Aug 2022 10:24:14 -0500 Subject: [PATCH 01/10] Update wormhole-local-validator.md Revised content for style, grammar and punctuation --- src/development/wormhole-local-validator.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/development/wormhole-local-validator.md b/src/development/wormhole-local-validator.md index 9a136f5..61db8d6 100644 --- a/src/development/wormhole-local-validator.md +++ b/src/development/wormhole-local-validator.md @@ -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. From cbadcab772e96ebb9a6e1cc014b6eac7a670826d Mon Sep 17 00:00:00 2001 From: Ian Traas <108365619+itraas@users.noreply.github.com> Date: Tue, 9 Aug 2022 10:26:10 -0500 Subject: [PATCH 02/10] Update evm.md Updated content for readability. --- src/development/messages/receiving/evm.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/development/messages/receiving/evm.md b/src/development/messages/receiving/evm.md index 0af4f47..a383f47 100644 --- a/src/development/messages/receiving/evm.md +++ b/src/development/messages/receiving/evm.md @@ -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. From ee861fc8ebb0b71a6f8c8c0afa792345f3b74d42 Mon Sep 17 00:00:00 2001 From: Ian Traas <108365619+itraas@users.noreply.github.com> Date: Tue, 9 Aug 2022 10:29:34 -0500 Subject: [PATCH 03/10] Update overview.md Adjusted content for grammar, style and readability. --- src/development/messages/receiving/overview.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/development/messages/receiving/overview.md b/src/development/messages/receiving/overview.md index d00ab1b..642663b 100644 --- a/src/development/messages/receiving/overview.md +++ b/src/development/messages/receiving/overview.md @@ -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. \ No newline at end of file +After we have ensured all those things are correct, we can process the message according to the business logic in our application. From 89ee802e7b1b7ee5974193f6eda5807c26d3941e Mon Sep 17 00:00:00 2001 From: Ian Traas <108365619+itraas@users.noreply.github.com> Date: Tue, 9 Aug 2022 10:32:31 -0500 Subject: [PATCH 04/10] Update overview.md Revised content for readability. --- src/development/messages/registration/overview.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/development/messages/registration/overview.md b/src/development/messages/registration/overview.md index 33e31bb..49dc9dc 100644 --- a/src/development/messages/registration/overview.md +++ b/src/development/messages/registration/overview.md @@ -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. From 320040ec87171ca457647f35ee675070fa9a7927 Mon Sep 17 00:00:00 2001 From: Ian Traas <108365619+itraas@users.noreply.github.com> Date: Tue, 9 Aug 2022 10:34:26 -0500 Subject: [PATCH 05/10] Update evm.md Updated content for readability. --- src/development/messages/registration/evm.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/development/messages/registration/evm.md b/src/development/messages/registration/evm.md index bb0c93c..365fb3e 100644 --- a/src/development/messages/registration/evm.md +++ b/src/development/messages/registration/evm.md @@ -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[]. \ No newline at end of file +If you have more than one address per chainId that you want to listen to, consider making the mapping into bytes32[]. From 1fcaff42a9cd5544fa0b791c5da99d07f205134a Mon Sep 17 00:00:00 2001 From: Ian Traas <108365619+itraas@users.noreply.github.com> Date: Tue, 9 Aug 2022 10:37:59 -0500 Subject: [PATCH 06/10] Update overview.md Edited content for readability. --- src/development/messages/relaying/overview.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/development/messages/relaying/overview.md b/src/development/messages/relaying/overview.md index 37694b9..ce3b5eb 100644 --- a/src/development/messages/relaying/overview.md +++ b/src/development/messages/relaying/overview.md @@ -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. \ No newline at end of file + 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. From f7247cbe887d71ba101685290efec50927fe8fa7 Mon Sep 17 00:00:00 2001 From: Ian Traas <108365619+itraas@users.noreply.github.com> Date: Tue, 9 Aug 2022 10:40:39 -0500 Subject: [PATCH 07/10] Update overview.md Edited formatting to fall in line with other pages. Revised content for readability. --- src/development/messages/sending/overview.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/development/messages/sending/overview.md b/src/development/messages/sending/overview.md index 4838538..22efcc6 100644 --- a/src/development/messages/sending/overview.md +++ b/src/development/messages/sending/overview.md @@ -1,12 +1,14 @@ # 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. From 7dbe4236265751ac08181d52745c88a629b0b255 Mon Sep 17 00:00:00 2001 From: Ian Traas <108365619+itraas@users.noreply.github.com> Date: Tue, 9 Aug 2022 10:41:03 -0500 Subject: [PATCH 08/10] Update overview.md --- src/development/messages/sending/overview.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/development/messages/sending/overview.md b/src/development/messages/sending/overview.md index 22efcc6..724f314 100644 --- a/src/development/messages/sending/overview.md +++ b/src/development/messages/sending/overview.md @@ -5,10 +5,13 @@ While the specific code varies chain by chain, sending a message always requires 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. 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. 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. From 2adc7ce0fe612ece0d53fa8dd77c059888e2410c Mon Sep 17 00:00:00 2001 From: Ian Traas <108365619+itraas@users.noreply.github.com> Date: Tue, 9 Aug 2022 10:43:30 -0500 Subject: [PATCH 09/10] Update evm.md Updated content for readability. --- src/development/messages/sending/evm.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/development/messages/sending/evm.md b/src/development/messages/sending/evm.md index dc0db55..cc694b1 100644 --- a/src/development/messages/sending/evm.md +++ b/src/development/messages/sending/evm.md @@ -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 From 6f1c1dd0a8d5958117ea6cf5b30d6b46b05c8a1b Mon Sep 17 00:00:00 2001 From: Ian Traas <108365619+itraas@users.noreply.github.com> Date: Tue, 9 Aug 2022 10:50:54 -0500 Subject: [PATCH 10/10] Update overview.md Updated content for readability, grammar and style. --- src/development/portal/overview.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/development/portal/overview.md b/src/development/portal/overview.md index a8f3dc5..86e64ba 100644 --- a/src/development/portal/overview.md +++ b/src/development/portal/overview.md @@ -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. \ No newline at end of file +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.