more line edits, additions, etc

This commit is contained in:
chase-45 2022-09-19 21:04:13 -04:00
parent f8cc94e6c8
commit 9b8cc2b3cf
10 changed files with 101 additions and 64 deletions

View File

@ -61,8 +61,8 @@
- [Relayers](./technical/relayer/overview.md)
- [Plugin Relayer](./technical/relayer/pluginRelayers.md)
- [Guardian Network](./technical/relayer/guardianNetwork.md)
- [Generic Relayers](./technical/relayer/genericRelayer.md)
- [Specialized Relayers](./technical/relayer/pluginRelayers.md)
- [Wormhole Typescript SDK](./development/portal/overview.md)
- [EVM]()

View File

@ -8,14 +8,15 @@
Here's a succinct list of the pros and cons of the environment, so you can decide if it's the right fit for you.
- Pros
### Pros
- Lightweight, low system resource demand.
- Fast iteration times.
- Can be added into an existing blockchain development setup.
- Lightweight, low system resource demand.
- Fast iteration times.
- Can be added into an existing blockchain development setup.
- Cons
- You may end up reinventing the tilt/testnet environment as you add more components.
### Cons
- You may end up reinventing the tilt/testnet environment as you add more components.
## Setting up Wormhole Local Validator

View File

@ -6,7 +6,7 @@ This section will explain how to properly interact with the Wormhome Core Layer
[Here](https://github.com/wormhole-foundation/wormhole/blob/dev.v2/ethereum/contracts/interfaces/IWormhole.sol) is the interface for applications to interact with Wormhole's Core Contract to publish messages or verify and parse a received message.
Instantiating the interface will depend on your development ecosystem and blockchain. The Wormhole Core Layer contract address is usually stored in your contract address.
Instantiating the interface will depend on the contract address of your development ecosystem and blockchain.
Below is an example line of code to instantiate the interface for mainnet Ethereum:
@ -45,12 +45,16 @@ For either message type, remember to collect gas fees associated with submitting
To properly parse and verify a single VAA, always use `parseAndVerifyVM` which takes in one argument: `encodedVM` (bytes). This function will return three arguments:
1. `vm` (VM): Structured data that reflects the content of the VAA.
- A breakdown of this message format is described in the [VAA](../../wormhole/4_vaa.md) section. It is up to the receving contracting to properly parse this data structure for the necessary information.
- A breakdown of this message format is described in the [VAA](../../wormhole/4_vaa.md) section. Aside from the header information, which can be considered 'trusted', it is up to the recipient contract to properly parse the remaining payload, as this contains the verbatim message sent from the emitting contract.
2. `valid` (bool): Boolean that reflects whether or not the VAA was properly signed by the Guardian Network
3. `reason` (string): Explanatory error message if a VAA is invalid, or an empty string if it is valid.
<!--
TODO
everything about this
**Batch VAA**
To properly parse and verify a batch VAA, always use `parseAndVerifyBatchVM` which takes in two arguments: `encodedVM` (bytes) and `cache` (bool).
Batch VAAs are designed so that relayers can choose to submit any subset of the observations batched together. It is the receiving contract's responsiblity to verify that all VAAs contained in a batch are submitted.
@ -58,3 +62,5 @@ Batch VAAs are designed so that relayers can choose to submit any subset of the
---
Code recommendation, write the code which expects to receive a VAA to utilize parseAndVerifyVM(? unsure if this is the correct call). That way, your code will be able to handle either type 1 VAAs (single VAAs), or type 3 VAAs (headless VAAs). This allows it to utilize both single & batch VAAs and dramatically increases composeability. \*this only requires like two or three lines of code, so this would be a good candidate for a code example which shows how to properly use batch vaas without breaking composeability. Should note that the module code still ALWAYS needs to verify, but should do so with the 'single' message verifying and then expose that function publicly in order to enable composeability.
-->

View File

@ -4,10 +4,14 @@ This section will explain how to properly interact with the NFT Layer in an EVM
## Configuring the interface
[Here]() is the interface for applications to interact with Wormhole's NFT layer.
//TODO link to file in github so doesn't become stale
[Here](https://github.com/wormhole-foundation/wormhole/tree/dev.v2/ethereum/contracts/interfaces) is the interface for applications to interact with Wormhole's NFT layer.
Instantiating the interface will depend on your development ecosystem and blockchain. The Wormhole xAsset contract address is usually stored in your contract address.
<!---
TODO
merge down the interface PR and link to actual file
-->
Instantiating the interface will depend on the contract address of your development ecosystem and blockchain.
Below is an example line of code to instantiate the interface for mainnet Ethereum:
@ -18,21 +22,22 @@ INFTBridge NFT_bridge = INFTBridge(wormhole_nft_bridge_address);
## Transferring a NFT
The Wormhole NFT Bridge only supports tokens that support the ERC-721 interface and will create a wrapped NFT with identical metadata. How this is implemented varies by ecosystem.
The Wormhole NFT Bridge only supports tokens compliant with the ERC-721 interface, and functions by creating a 'wrapped NFT' with identical metadata. How this is implemented varies by ecosystem.
**Note**: Unlike xAssets, there is no attestation required for bridging NFTs.
To transfer a NFT, there are three steps:
1. Initiate the NFT transfer
- This function call will return a `sequence` (uint64) that is used in the VAA retrieval step
- This function call will return a `sequence` (uint64) that is used in the VAA retrieval step
```
transferNFT(tokenAddress, tokenID, recipientChain, recipient, nonce);
```
2. Retrieve the emitted VAA.
- _Note: NFT Transfer VAAs are retrieved from the Guardian Network by the `emitterChainID`, `emitterAddress`, and `sequence`_
2. Retrieve the emitted VAA from the Guardian Network. (Usually done by a relayer)
- _Note: NFT Transfer VAAs are retrieved from the Guardian Network by the `emitterChainID`, `emitterAddress`, and `sequence`_
```
const emitterAddr = getEmitterAddressEth(network.NFTBridgeAddress);
const seq = parseSequenceFromLogEth(tx, network.bridgeAddress);
@ -45,12 +50,14 @@ while (!vaaBytes.vaaBytes) {
}
```
3. Complete the NFT transfer
3. Complete the NFT transfer by submitting the resultant VAA to the target chain.
```
completeTransfer(VAA);
```
## Additional utility
<!---
TODO
//TODO NFT verification and perhaps some other common usecases
additional usecases, most specifically how to grab the origin address of the wrapped NFT
-->

View File

@ -2,13 +2,15 @@
**Disclaimer**: This section is written as a guide for how to use Wormhole for experienced EVM developers. If you are new to using the EVM ecosystem, it's recommended for you to get started with a tutorial like [this]().
For our purposes, EVM refers to any blockchain in the Wormhole ecosystem that utilizes EVM contracts of Wormhole -- this includes blockchains beyond Ethereum such as Polygon or Avalanche, as well as EVM+ evnrionments such as Acala.
For our purposes, EVM refers to any blockchain in the Wormhole ecosystem that utilizes EVM contracts of Wormhole -- this includes blockchains beyond Ethereum such as Polygon or Avalanche, as well as EVM+ environments such as Acala.
### Recommended Tooling for EVM
**Development**
- [Ethers](https://docs.ethers.io/v5/) library
**Frontend Development**
**Testing**
- [Foundry](https://github.com/foundry-rs/foundry) is preferred and increasingly used by the core repository
- [Truffle](https://trufflesuite.com/) and [Hardhat](https://hardhat.org/) are also options
- [Ethers](https://docs.ethers.io/v5/) an excellent, widely used library for using web-based wallets to interact with EVM blockchains.
**Contract Development and Testing**
- [Foundry](https://github.com/foundry-rs/foundry) is the preferred library for the Core Repository. It has tooling for development, testing, compilation, and even the ability to duplicate mainnet environments for development.
- [Truffle](https://trufflesuite.com/) and [Hardhat](https://hardhat.org/) are also viable alternatives.

View File

@ -20,34 +20,44 @@ ITokenBridge token_bridge = ITokenBridge(wormhole_token_bridge_address);
Attesting a token from EVM needs to happen once per token. If a token is not attested, it will not be claimable until so. However, there are no restrictions to reattesting a token; doing so will update the metadata.
It is not advised to attest tokens on-chain for most usecases. To attest a token by an off-chain process, you can either do it by hand through one of the Token Bridge UIs (for example [Portal](https://www.portalbridge.com/#/transfer)) or using the [JS SDK](https://www.npmjs.com/package/@certusone/wormhole-sdk).
It is not advised to attest tokens on-chain for most usecases. To attest a token by an off-chain process, you can either do it by hand through one of the Token Bridge UIs (for example [Portal](https://www.portalbridge.com/#/register)) or using the [JS SDK](https://www.npmjs.com/package/@certusone/wormhole-sdk).
<!--
TODO link to this code example from later in the guide
// If we want to show how to attest with JS SDK, have the example [here](https://book.wormhole.com/development/portal/evm/attestingToken.html)
-->
## Basic Transfer
Basic transfer should only be used if you are transferring messages to an end user wallet. If the end destination is a contract, you should only use Contract Controlled Transfers (described below).
Basic transfer should only be used if you are transferring messages to an end user wallet. If the end destination is a contract, you should only use Contract Controlled Transfers (described below).
It is important to note the transferring native currency is a special case of the Basic Transfer. As such, a different function call is provided as a QoL improvement when initiating and completing the transfer messaging when unwrapping the ETH is desired.
To transfer a token, there are four steps:
1. Approve the Token Bridge to spend that token on our behalf.
- _Note: Tokens in EVM usually denote up to 18 decimals places. However. Wormhole normalizes this to **8** decimals._
- _Note: Tokens in EVM usually denote up to 18 decimals places. However. Wormhole normalizes this to **8** decimals._
```
contractAddress.approve(token_bridge_address, amt);
```
2. Transfer the token to create the transfer VAA.
- This function call will return a `sequence` (uint64) that is used in the VAA retrieval step.
- _Note: Wormhole addresses are 32 bytes for standardization across the different blockchains within the Wormhole ecosystem._
- This function call will return a `sequence` (uint64) that is used in the VAA retrieval step.
- _Note: Wormhole addresses are 32 bytes for standardization across the different blockchains within the Wormhole ecosystem._
```
// To initiate transfer of normal ERC-20s
token_bridge.transferTokens(tokenAddress, amount, recipientChain, recipient, arbiterFee, nonce);
// To initiate transfer of native currency
token_bridge.wrapAndTransferETH(recipientChain, recipient, arbiterFee, nonce);
token_bridge.wrapAndTransferETH(recipientChain, recipient, arbiterFee, nonce);
```
3. Retrieve the emitted VAA.
- _Note: Basic Transfer VAAs are retrieved from the Guardian Network by the `emitterChainID`, `emitterAddress`, and `sequence`_
- _Note: Basic Transfer VAAs are retrieved from the Guardian Network by the `emitterChainID`, `emitterAddress`, and `sequence`_
```
const emitterAddr = getEmitterAddressEth(network.tokenBridgeAddress);
const seq = parseSequenceFromLogEth(tx, network.bridgeAddress);
@ -61,7 +71,8 @@ while (!vaaBytes.vaaBytes) {
```
4. Complete the transfer using the VAA.
- _Note: VAAs are retrieved from the
- \_Note: VAAs are retrieved from the
```
// To complete transfer of normal ERC-20s
token_bridge.completeTransfer(VAA);
@ -75,6 +86,7 @@ completeTransferAndUnwrapETH(VAA);
For any message transfers where the destination is a contract, you should always used Contract Controlled Transfers.
There are a few main differences between Contract Controlled Transfers and Basic Transfers:
- message contains both tokens and an arbitrary payload
- can only be redeemed by a specified contract address
- does not have a relayer fee field because of the redemption restriction above.
@ -82,23 +94,29 @@ There are a few main differences between Contract Controlled Transfers and Basic
As was the case with Basic Transfers, transferring native currency is a special case for Contract Controlled Transfers as well. As such, a different function call is provided as a QoL improvement when initiating and completing the transfer messaging when unwrapping the ETH is desired.
The process of sending a Contract Controlled Transfer is very similar to that of a Basic Transfer:
1. Approve the Token Bridge to spend that token on our behalf.
- _Note: Tokens in EVM usually denote up to 18 decimals places. However. Wormhole normalizes this to **8** decimals._
- _Note: Tokens in EVM usually denote up to 18 decimals places. However. Wormhole normalizes this to **8** decimals._
```
contractAddress.approve(token_bridge_address, amt);
```
2. Transfer the token to create the transfer VAA.
- This function call will return a `sequence` (uint64) that is used in the VAA retrieval step.
- _Note: Wormhole addresses are 32 bytes for standardization across the different blockchains within the Wormhole ecosystem._
- This function call will return a `sequence` (uint64) that is used in the VAA retrieval step.
- _Note: Wormhole addresses are 32 bytes for standardization across the different blockchains within the Wormhole ecosystem._
```
// To initiate transfer of normal ERC-20s
token_bridge.transferTokesWithPayload(tokenAddress, amount, recipientChain, recipient, nonce, payload);
// To initiate transfer of native currency
token_bridge.wrapAndTransferETHWithPayload(recipientChain, recipient, nonce, payload);
token_bridge.wrapAndTransferETHWithPayload(recipientChain, recipient, nonce, payload);
```
3. Retrieve the emitted VAA.
- _Note: Basic Transfer VAAs are retrieved from the Guardian Network by the `emitterChainID`, `emitterAddress`, and `sequence`_
- _Note: Basic Transfer VAAs are retrieved from the Guardian Network by the `emitterChainID`, `emitterAddress`, and `sequence`_
```
const emitterAddr = getEmitterAddressEth(network.tokenBridgeAddress);
const seq = parseSequenceFromLogEth(tx, network.bridgeAddress);
@ -112,7 +130,8 @@ while (!vaaBytes.vaaBytes) {
```
4. Complete the transfer using the VAA.
- _Note: VAAs are retrieved from the
- \_Note: VAAs are retrieved from the
```
// To complete transfer of normal ERC-20s
token_bridge.completeTransferWithPayload(VAA);

View File

View File

@ -1,9 +0,0 @@
# Guardian Network
If you're totally homerolling a relayer solution, you'll need to interact with the guardian network directly.
link to spydk. Use this to tie directly into the guardian network and receive events. If you're particularly ambitious, you can even join the guardian network as a 'spy' which is the term for a non-validating guardian.
VAAs can also be pulled directly from any public node on the guardian network using REST endpoints. This is a really simple way to grab known VAAs.
- provide the REST endpoints for this

View File

@ -1,15 +1 @@
- Link to Plugin relayer codebase
- Recommend plugin relayers as the starting point for anyone developing specialized relayers
- plugin relayers provide a kernel for relayer development. Handles management of all the necessary hotwallets, provides the necessary typescript interfaces for dealing with each ecosystems, and provides an easy integration point to connect to the guardian network
- Follow the instructions provided in the codebase in order to get it running
- to develop a plugin, simply implement the interface provided at [here]
- diagram explaining the flow
- Listener component listens to either incoming REST calls or the guardian network for relevant VAAs,
- When a relevant VAA is detected, your listener code is responsible for producing an action.
- This action is stored in a redis instance
- The executor portion of the interface is responsible for consuming interactions which are provided by the listener.
- The executor is handed an action and is responsible for consuming that action and (optionally) queuing up more actions
- additional configuration info can be found in the README of the codebase.
# Specialized Relayers

View File

@ -0,0 +1,25 @@
- Link to Plugin relayer codebase
- Recommend plugin relayers as the starting point for anyone developing specialized relayers
- plugin relayers provide a kernel for relayer development. Handles management of all the necessary hotwallets, provides the necessary typescript interfaces for dealing with each ecosystems, and provides an easy integration point to connect to the guardian network
- Follow the instructions provided in the codebase in order to get it running
- to develop a plugin, simply implement the interface provided at [here]
- diagram explaining the flow
- Listener component listens to either incoming REST calls or the guardian network for relevant VAAs,
- When a relevant VAA is detected, your listener code is responsible for producing an action.
- This action is stored in a redis instance
- The executor portion of the interface is responsible for consuming interactions which are provided by the listener.
- The executor is handed an action and is responsible for consuming that action and (optionally) queuing up more actions
- additional configuration info can be found in the README of the codebase.
# Homerolling a Relayer
If you're totally homerolling a relayer solution, you'll need to interact with the guardian network directly.
link to spydk. Use this to tie directly into the guardian network and receive events. If you're particularly ambitious, you can even join the guardian network as a 'spy' which is the term for a non-validating guardian.
VAAs can also be pulled directly from any public node on the guardian network using REST endpoints. This is a really simple way to grab known VAAs.
- provide the REST endpoints for this