xdapp-book/src/technical/evm/xassetLayer.md

136 lines
6.1 KiB
Markdown
Raw Normal View History

2022-09-21 10:13:51 -07:00
# Token Bridge
2022-09-14 09:16:13 -07:00
2022-09-21 10:13:51 -07:00
This section will explain how to properly interact with the Wormhome Token Bridge Module in an EVM ecosystem.
2022-09-14 10:03:57 -07:00
2022-09-19 16:00:10 -07:00
## Configuring the interface
2022-09-14 10:03:57 -07:00
2022-09-21 10:13:51 -07:00
[Here]() is the interface for applications to interact with Wormhole's Token Bridge.
2022-09-16 08:45:16 -07:00
//TODO link to file in github so doesn't become stale
2022-09-14 09:16:13 -07:00
2022-09-21 10:13:51 -07:00
Instantiating the interface will depend on your development ecosystem and blockchain. The Wormhole Token Bridge contract address is usually stored in your contract address.
2022-09-14 09:16:13 -07:00
2022-09-16 08:45:16 -07:00
Below is an example line of code to instantiate the interface for mainnet Ethereum:
2022-09-14 09:16:13 -07:00
2022-09-16 08:45:16 -07:00
```
address private wormhole_token_bridge_address = address(0x3ee18B2214AFF97000D974cf647E7C347E8fa585);
ITokenBridge token_bridge = ITokenBridge(wormhole_token_bridge_address);
2022-09-14 10:03:57 -07:00
```
## Registering New Tokens
2022-09-16 08:45:16 -07:00
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.
2022-09-19 18:04:13 -07:00
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).
2022-09-16 08:45:16 -07:00
2022-09-21 10:13:51 -07:00
_[Here](../../development/portal/evm/attestingToken.md) is an example of how to attest a token using the JS SDK._
2022-09-19 18:04:13 -07:00
2022-09-14 10:03:57 -07:00
## Basic Transfer
2022-09-19 18:04:13 -07:00
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).
2022-09-16 08:45:16 -07:00
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:
2022-09-19 18:04:13 -07:00
2022-09-16 08:45:16 -07:00
1. Approve the Token Bridge to spend that token on our behalf.
2022-09-19 18:04:13 -07:00
- _Note: Tokens in EVM usually denote up to 18 decimals places. However. Wormhole normalizes this to **8** decimals._
2022-09-16 08:45:16 -07:00
```
contractAddress.approve(token_bridge_address, amt);
```
2022-09-19 18:04:13 -07:00
2022-09-16 08:45:16 -07:00
2. Transfer the token to create the transfer VAA.
2022-09-19 18:04:13 -07:00
- 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._
2022-09-16 08:45:16 -07:00
```
// To initiate transfer of normal ERC-20s
token_bridge.transferTokens(tokenAddress, amount, recipientChain, recipient, arbiterFee, nonce);
// To initiate transfer of native currency
2022-09-19 18:04:13 -07:00
token_bridge.wrapAndTransferETH(recipientChain, recipient, arbiterFee, nonce);
2022-09-16 08:45:16 -07:00
```
2022-09-19 18:04:13 -07:00
2022-09-16 08:45:16 -07:00
3. Retrieve the emitted VAA.
2022-09-19 18:04:13 -07:00
- _Note: Basic Transfer VAAs are retrieved from the Guardian Network by the `emitterChainID`, `emitterAddress`, and `sequence`_
2022-09-16 08:45:16 -07:00
```
const emitterAddr = getEmitterAddressEth(network.tokenBridgeAddress);
const seq = parseSequenceFromLogEth(tx, network.bridgeAddress);
const vaaURL = `${config.wormhole.restAddress}/v1/signed_vaa/${network.wormholeChainId}/${emitterAddr}/${seq}`;
let vaaBytes = await (await fetch(vaaURL)).json();
while (!vaaBytes.vaaBytes) {
console.log("VAA not found, retrying in 5s!");
await new Promise((r) => setTimeout(r, 5000)); //Timeout to let Guardiand pick up log and have VAA ready
vaaBytes = await (await fetch(vaaURL)).json();
}
```
4. Complete the transfer using the VAA.
2022-09-19 18:04:13 -07:00
2022-09-16 08:45:16 -07:00
```
// To complete transfer of normal ERC-20s
token_bridge.completeTransfer(VAA);
// To complete transfer of native currency
completeTransferAndUnwrapETH(VAA);
```
2022-09-14 10:03:57 -07:00
## Contract Controlled Transfer
2022-09-16 08:45:16 -07:00
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:
2022-09-19 18:04:13 -07:00
2022-09-16 08:45:16 -07:00
- 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.
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:
2022-09-19 18:04:13 -07:00
2022-09-16 08:45:16 -07:00
1. Approve the Token Bridge to spend that token on our behalf.
2022-09-19 18:04:13 -07:00
- _Note: Tokens in EVM usually denote up to 18 decimals places. However. Wormhole normalizes this to **8** decimals._
2022-09-16 08:45:16 -07:00
```
contractAddress.approve(token_bridge_address, amt);
```
2022-09-19 18:04:13 -07:00
2022-09-16 08:45:16 -07:00
2. Transfer the token to create the transfer VAA.
2022-09-19 18:04:13 -07:00
- 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._
2022-09-16 08:45:16 -07:00
```
// To initiate transfer of normal ERC-20s
token_bridge.transferTokesWithPayload(tokenAddress, amount, recipientChain, recipient, nonce, payload);
// To initiate transfer of native currency
2022-09-19 18:04:13 -07:00
token_bridge.wrapAndTransferETHWithPayload(recipientChain, recipient, nonce, payload);
2022-09-16 08:45:16 -07:00
```
2022-09-19 18:04:13 -07:00
2022-09-16 08:45:16 -07:00
3. Retrieve the emitted VAA.
2022-09-19 18:04:13 -07:00
- _Note: Basic Transfer VAAs are retrieved from the Guardian Network by the `emitterChainID`, `emitterAddress`, and `sequence`_
2022-09-16 08:45:16 -07:00
```
const emitterAddr = getEmitterAddressEth(network.tokenBridgeAddress);
const seq = parseSequenceFromLogEth(tx, network.bridgeAddress);
const vaaURL = `${config.wormhole.restAddress}/v1/signed_vaa/${network.wormholeChainId}/${emitterAddr}/${seq}`;
let vaaBytes = await (await fetch(vaaURL)).json();
while (!vaaBytes.vaaBytes) {
console.log("VAA not found, retrying in 5s!");
await new Promise((r) => setTimeout(r, 5000)); //Timeout to let Guardiand pick up log and have VAA ready
vaaBytes = await (await fetch(vaaURL)).json();
}
```
4. Complete the transfer using the VAA.
2022-09-19 18:04:13 -07:00
2022-09-16 08:45:16 -07:00
```
// To complete transfer of normal ERC-20s
token_bridge.completeTransferWithPayload(VAA);
// To complete transfer of native currency
completeTransferAndUnwrapETHWithPayload(VAA);
```