/>
/>
avalanchego/vms/platformvm/vm.go#322: initializing last accepted block as 2FUFPVPxbTpKNn39moGSzsmGroYES4NZRdw3mJgNvMkMiMHJ9e Jan 05 10:38:45 ip-172-31-30-64 avalanchego[2142]: INFO [01-05|10:38:45]
avalanchego/snow/engine/snowman/transitive.go#58: initializing consensus engine Jan 05 10:38:45 ip-172-31-30-64 avalanchego[2142]: INFO [01-05|10:38:45] avalanchego/api/server.go#143: adding route /ext/bc/11111111111111111111111111111111LpoYY Jan 05 10:38:45 ip-172-31-30-64 avalanchego[2142]: INFO [01-05|10:38:45] avalanchego/api/server.go#88: HTTP API server listening on ":9650" Jan 05 10:38:58 ip-172-31-30-64 avalanchego[2142]: INFO [01-05|10:38:58]
avalanchego/snow/engine/common/bootstrapper.go#185: Bootstrapping started syncing with 1 vertices in the accepted frontier Jan 05 10:39:02 ip-172-31-30-64 avalanchego[2142]: INFO [01-05|10:39:02]
avalanchego/snow/engine/snowman/bootstrap/bootstrapper.go#210: fetched 2500 blocks Jan 05 10:39:04 ip-172-31-30-64 avalanchego[2142]: INFO [01-05|10:39:04]
avalanchego/snow/engine/snowman/bootstrap/bootstrapper.go#210: fetched 5000 blocks Jan 05 10:39:06 ip-172-31-30-64 avalanchego[2142]: INFO [01-05|10:39:06]
avalanchego/snow/engine/snowman/bootstrap/bootstrapper.go#210: fetched 7500 blocks Jan 05 10:39:09 ip-172-31-30-64 avalanchego[2142]: INFO [01-05|10:39:09]
avalanchego/snow/engine/snowman/bootstrap/bootstrapper.go#210: fetched 10000 blocks Jan 05 10:39:11 ip-172-31-30-64 avalanchego[2142]: INFO [01-05|10:39:11]
avalanchego/snow/engine/snowman/bootstrap/bootstrapper.go#210: fetched 12500 blocks ```
bootstrap/bootstrapper.go:494 fetching blocks {"numFetchedBlocks": 5000, "numTotalBlocks": 101357, "eta": "2m52s"} [02-16|17:31:58.110] INFO
bootstrap/bootstrapper.go:494 fetching blocks {"numFetchedBlocks": 10000, "numTotalBlocks": 101357, "eta": "3m40s"} [02-16|17:32:04.554] INFO
bootstrap/bootstrapper.go:494 fetching blocks {"numFetchedBlocks": 15000, "numTotalBlocks": 101357, "eta": "2m56s"} ... [02-16|17:36:52.404] INFO
queue/jobs.go:203 executing operations {"numExecuted": 17881, "numToExecute": 101357, "eta": "2m20s"} [02-16|17:37:22.467] INFO
queue/jobs.go:203 executing operations {"numExecuted": 35009, "numToExecute": 101357, "eta": "1m54s"} [02-16|17:37:52.468] INFO
queue/jobs.go:203 executing operations {"numExecuted": 52713, "numToExecute": 101357, "eta": "1m23s"}
```
Similar logs are emitted for X and C chains and any chain in explicitly tracked Avalanche L1s.
### Why Chain Bootstrap ETA Keeps On Changing?[](#why-chain-bootstrap-eta-keeps-on-changing "Direct link to heading")
As you saw in the [bootstrap completion section](#when-does-bootstrapping-finish), an Avalanche L1 like the Primary Network completes once all of its chains finish bootstrapping. Some Avalanche L1 chains may have to wait for the slowest to finish. They'll restart bootstrapping in the meantime, to make sure they won't fall back too much with respect to the network accepted frontier.
## What Order Do The Chains Bootstrap?[](#what-order-do-the-chains-bootstrap "Direct link to heading")
The 3 chains will bootstrap in the following order: P-chain, X-chain, C-chain.
### Why Are AvalancheGo APIs Disabled During Bootstrapping?[](#why-are-avalanchego-apis-disabled-during-bootstrapping "Direct link to heading")
AvalancheGo APIs are [explicitly disabled](https://github.com/ava-labs/avalanchego/blob/master/api/server/server.go#L367:L379) during bootstrapping. The reason is that if the node has not fully rebuilt its Avalanche L1s state, it can't provide accurate information. AvalancheGo APIs are activated once bootstrap completes and node transition into its normal operating mode, accepting and validating transactions.
# Enroll in Avalanche Notify
URL: /docs/primary-network/maintain/enroll-in-avalanche-notify
To receive email alerts if a validator becomes unresponsive or out-of-date, sign up with the Avalanche Notify tool: [http://notify.avax.network](http://notify.avax.network/).
Avalanche Notify is an active monitoring system that checks a validator's responsiveness each minute.
An email alert is sent if a validator is down for 5 consecutive checks and when a validator recovers (is responsive for 5 checks in a row).
snow/engine/snowman/bootstrap/bootstrapper.go#445: waiting for the remaining chains in this subnet to finish syncing
INFO [02-09|00:59:34] api/server/server.go#203: adding route /ext/bc/2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM/wallet
INFO [02-09|00:59:34] api/server/server.go#203: adding route /ext/bc/2oYMBNV4eNHyqk2fjjV5nVQLDbtmNJzq5s3qs3Lo6ftnC6FByM/events
INFO [02-09|00:59:34] snow/engine/common/bootstrapper.go#235: Bootstrapping started syncing with 1 vertices in the accepted frontier
INFO [02-09|00:59:46] snowman/transitive.go:392 consensus starting {"lastAcceptedBlock": "2ofmPJuWZbdroCPEMv6aHGvZ45oa8SBp2reEm9gNxvFjnfSGFP"}
[09-09|17:01:51.628] INFO snowman/transitive.go:392 consensus starting {"lastAcceptedBlock": "2ofmPJuWZbdroCPEMv6aHGvZ45oa8SBp2reEm9gNxvFjnfSGFP"}
[09-09|17:01:51.628] INFO >
>
"
}
}
}
```
## Testing
### Unit Tests
Unit tests can be ran locally by running the command in the root of the project:
```bash
./scripts/test.sh
```
If your temporary directory is not writable, the unit tests may fail with messages like `fork/exec /tmp/go-build2296620589/b247/config.test: permission denied`. To fix this, set the `TMPDIR` environment variable to something writable, for example `export TMPDIR=~/tmp`.
### E2E Tests
To run the E2E tests locally, you'll need to install Gingko following the instructions [here](https://onsi.github.io/ginkgo/#installing-ginkgo). Run the tests using the dedicated script:
```bash
./scripts/e2e_test.sh
```
To run a specific E2E test, specify the environment variable `GINKGO_FOCUS`, which will then look for [test descriptions](https://github.com/ava-labs/icm-services/blob/main/relayer/tests/e2e_test.go#L68) that match the provided input. For example, to run the `Basic Relay` test:
```bash
GINKGO_FOCUS="Basic" ./scripts/e2e_test.sh
```
The E2E tests use the `TeleporterMessenger` contract deployment transaction specified in the following files:
* `tests/utils/UniversalTeleporterDeployerAddress.txt`
* `tests/utils/UniversalTeleporterDeployerTransaction.txt`
* `tests/utils/UniversalTeleporterMessagerContractAddress.txt`
To update the version of Teleporter used by the E2E tests, update these values with the latest contract deployment information. For more information on how to deploy the Teleporter contract, see the [Teleporter documentation](https://github.com/ava-labs/icm-contracts/tree/main/utils/contract-deployment).
### Generate Mocks
[Gomock](https://pkg.go.dev/go.uber.org/mock/gomock) is used to generate mocks for testing. To generate mocks, run the following command at the root of the project:
```bash
go generate ./...
```
### Generate Protobuf Files
[buf](https://github.com/bufbuild/buf/) is used to generate protobuf definitions for communication with the [Decider service](https://github.com/ava-labs/icm-services/blob/main/proto/decider/decider.proto). If you change any of the protobuf definitions you will have to regenerate the `.go` files. To generate these files, run the following command at the root of the project:
```bash
./scripts/protobuf_codegen.sh
```
### Generate Abi Bindings
[subnet-evm](https://github.com/ava-labs/subnet-evm/tree/6e67777132dd7d0d556e1e34d68ad8e27b22ebef/cmd/abigen) is used to generate abi binding `.go` files for solidity contracts. If you change any of the smart contracts, you will have to update the abi bindings. To generate these files, run the following command at the root of the project:
```bash
./scripts/abi_bindings.sh
```
# Avalanche Interchain Token Transfer (ICTT)
URL: /docs/cross-chain/interchain-token-transfer/overview
This page describes the Avalanche Interchain Token Transfer (ICTT)
# Avalanche Interchain Token Transfer (ICTT)
## Overview
Avalanche Interchain Token Transfer (ICTT) is an application that allows users to transfer tokens between L1s. The implementation is a set of smart contracts that are deployed across multiple L1s, and leverages [ICM](https://github.com/ava-labs/icm-contracts) for cross-chain communication.
Each token transferrer instance consists of one "home" contract and at least one but possibly many "remote" contracts. Each home contract instance manages one asset to be transferred out to `TokenRemote` instances. The home contract lives on the L1 where the asset to be transferred exists. A transfer consists of locking the asset as collateral on the home L1 and minting a representation of the asset on the remote L1. The remote contracts, each of which has a single specified home contract, live on other L1s that want to import the asset transferred by their specified home. The token transferrers are designed to be permissionless: anyone can register compatible `TokenRemote` instances to allow for transferring tokens from the `TokenHome` instance to that new `TokenRemote` instance. The home contract keeps track of token balances transferred to each `TokenRemote` instance, and handles returning the original tokens back to the user when assets are transferred back to the `TokenHome` instance. `TokenRemote` instances are registered with their home contract via an ICM message upon creation.
Home contract instances specify the asset to be transferred as either an ERC20 token or the native token, and they allow for transferring the token to any registered `TokenRemote` instances. The token representation on the remote chain can also either be an ERC20 or native token, allowing users to have any combination of ERC20 and native tokens between home and remote chains:
* `ERC20` -> `ERC20`
* `ERC20` -> `Native`
* `Native` -> `ERC20`
* `Native` -> `Native`
The remote tokens are designed to have compatibility with the token transferrer on the home chain by default, and they allow custom logic to be implemented in addition. For example, developers can inherit and extend the `ERC20TokenRemote` contract to add additional functionality, such as a custom minting, burning, or transfer logic.
The token transferrer also supports "multi-hop" transfers, where tokens can be transferred between remote chains. To illustrate, consider two remotes *Ra* and *Rb* that are both connected to the same home *H*. A multi-hop transfer from *Ra* to *Rb* first gets routed from *Ra* to *H*, where remote balances are updated, and then *H* automatically routes the transfer on to *Rb*.
In addition to supporting basic token transfers, the token transferrer contracts offer a `sendAndCall` interface for transferring tokens and using them in a smart contract interaction all within a single ICM message. If the call to the recipient smart contract fails, the transferred tokens are sent to a fallback recipient address on the destination chain of the transfer. The `sendAndCall` interface enables the direct use of transferred tokens in dApps on other chains, such as performing swaps, using the tokens to pay for fees when invoking services, etc.
## Upgradability
The token transferrer contracts implement both upgradeable and non-upgradeable versions. The non-upgradeable versions are extensions of their respective upgradeable token transferrer contract, and has a `constructor` that calls the `initialize` function of the upgradeable version. The upgradeable contracts are ERC7201 compliant, and use namespace storage to store the state of the contract.
## `ITokenTransferrer`
Interface that defines the events token transfer contract implementations must emit. Also defines the message types and formats of messages between all implementations.
## `IERC20TokenTransferrer` and `INativeTokenTransferrer`
Interfaces that define the external functions for interacting with token transfer contract implementations of each type. ERC20 and native token transferrer interfaces vary from each other in that the native token transferrer functions are `payable` and do not take an explicit amount parameter (it is implied by `msg.value`), while the ERC20 token transferrer functions are not `payable` and require the explicit amount parameter. Otherwise, they include the same functions.
## `TokenHome`
An abstract implementation of `ITokenTransferrer` for a token transfer contract on the "home" chain with the asset to be transferred. Each `TokenHome` instance supports transferring exactly one token type (ERC20 or native) on its chain to arbitrarily many "remote" instances on other chains. It handles locking tokens to be sent to `TokenRemote` instances, as well as receiving token transfer messages to either redeem tokens it holds as collateral (i.e. unlock), or route them to other `TokenRemote` instances (i.e. "multi-hop"). In the case of a multi-hop transfer, the `TokenHome` already has the collateral locked from when the tokens were originally transferred to the first `TokenRemote` instance, so it simply updates the accounting of the transferred balances to each respective `TokenRemote` instance. Remote contracts must first be registered with a `TokenHome` instance before the home contract will allow for sending tokens to them. This is to prevent tokens from being transferred to invalid remote addresses. Anyone is able to deploy and register remote contracts, which may have been modified from this repository. It is the responsibility of the users of the home contract to independently evaluate each remote for its security and correctness.
## `ERC20TokenHome`
A concrete implementation of `TokenHome` and `IERC20TokenTransferrer` that handles the locking and releasing of an ERC20 token.
## `NativeTokenHome`
A concrete implementation of `TokenHome` and `INativeTokenTransferrer` that handles the locking and release of the native EVM asset.
## `TokenRemote`
An abstract implementation of `ITokenTransferrer` for a token transfer contract on a "remote" chain that receives transferred assets from a specific `TokenHome` instance. Each `TokenRemote` instance has a single `TokenHome` instance that it receives token transfers from to mint tokens. It also handles sending messages (and correspondingly burning tokens) to route tokens back to other chains (either its `TokenHome`, or other `TokenRemote` instances). Once deployed, a `TokenRemote` instance must be registered with its specified `TokenHome` contract. This is done by calling `registerWithHome` on the remote contract, which will send an ICM message to the home contract with the information to register.
All messages sent by `TokenRemote` instances are sent to the specified `TokenHome` contract, whether they are to redeem the collateral from the `TokenHome` instance or route the tokens to another `TokenRemote` instance. Routing tokens from one `TokenRemote` instance to another is referred to as a "multi-hop", where the tokens are first sent back to their `TokenHome` contract to update its accounting, and then automatically routed on to their intended destination `TokenRemote` instance.
TokenRemote contracts allow for scaling token amounts, which should be used when the remote asset has a higher or lower denomination than the home asset, such as allowing for a ERC20 home asset with a denomination of 6 to be used as the native EVM asset on a remote chain (with a denomination of 18).
## `ERC20TokenRemote`
A concrete implementation of `TokenRemote`, `IERC20TokenTransferrer`, and `IERC20` that handles the minting and burning of an ERC20 asset. Note that the `ERC20TokenRemote` contract is an ERC20 implementation itself, which is why it takes the `tokenName`, `tokenSymbol`, and `tokenDecimals` in its constructor. All of the ERC20 interface implementations are inherited from the standard OpenZeppelin ERC20 implementation, and can be overriden in other implementations if desired.
## `NativeTokenRemote`
A concrete implementation of `TokenRemote`, `INativeTokenTransferrer`, and `IWrappedNativeToken` that handles the minting and burning of the native EVM asset on its chain using the native minter precompile. Deployments of this contract must be given the permission to mint native coins in the chain's configuration. Note that the `NativeTokenRemote` is also an implementation of `IWrappedNativeToken` itself, which is why the `nativeAssetSymbol` must be provided in its constructor. `NativeTokenRemote` instances always have a denomination of 18, which is the denomination of the native asset of EVM chains.
The [native minter precompile](https://build.avax.network/docs/virtual-machines/custom-precompiles#minting-native-coins) must be configured to allow the contract address of the `NativeTokenRemote` instance to call `mintNativeCoin`. The correctness of a native token transferrer implemented using `NativeTokenRemote` relies on no other accounts being allowed to call `mintNativeCoin`, which could result in the token transferrer becoming undercollateralized. Example initialization steps for a `NativeTokenRemote` instance are shown below.
Since the native minter precompile does not provide an interface for burning the native EVM asset, the "burn" functionality is implemented by transferring the native coins to an unowned address. The contract also provides a `reportBurnedTxFees` interface in order to burn the collateral in the `TokenHome` instance that should be made unredeemable to account for native tokens burnt on the chain with the `NativeTokenRemote` instance to pay for transaction fees.
To account for the need to bootstrap the chain using a transferred asset as its native token, the `NativeTokenRemote` takes the `initialReserveImbalance` in its constructor. Once registered with its `TokenHome`, the `TokenHome` will require the `initialReserveImbalance` to be accounted for before sending token amounts to be minted on the given remote chain. The following example demonstrates the intended initialization flow:
1. Create a new blockchain with 100 native tokens allocated in its genesis block, and set the pre-derived `NativeTokenRemote` contract address (based on the deployer nonce) to have the permission to mint native tokens using the native minter precompile. Note that the deployer account will need to be funded in order to deploy the `NativeTokenRemote` contract, and an account used to relay messages into this chain must also be funded to relay the first messages.
2. Deploy the `NativeTokenRemote` contract to the pre-derived address set in the blockchain configuration of step 1. The `initialReserveImbalance` should be 100, matching the number of tokens allocated in the genesis block that were not initially backed by collateral in the `TokenHome` instance.
3. Call the `registerWithHome` function on the `NativeTokenRemote` instance to send an ICM message registering this remote with its `TokenHome`. This message should be relayed and delivered to the `TokenHome` instance.
4. Once registered on the `TokenHome` contract, add 100 tokens as collateral for the new `NativeTokenRemote` instance by calling the `addCollateral` function on the `TokenHome` contract. A `CollateralAdded` event will be emitted by the `TokenHome` contract with a `remaining` amount of 0 once the `NativeTokenRemote` is fully collateralized.
5. Now that the `NativeTokenRemote` contract is fully collateralized, tokens can be moved normally in both directions across the token transfer contracts by calling their `send` functions.
The `totalNativeAssetSupply` implementation of `NativeTokenRemote` takes into account:
* the initial reserve imbalance
* the number of native tokens that it has minted
* the number of native tokens that have been burned to pay for transaction fees
* the number of native tokens "burned" to be transferred to other chains, which are sent to a pre-defined `BURNED_FOR_TRANSFER_ADDRESS`.
Note that the value returned by `totalNativeAssetSupply` is an upper bound on the circulating supply of the native asset on the chain using the `NativeTokenRemote` instance since tokens could be burned in other ways that it does not account for.
## ICM Message Fees
Fees can be optionally added to ICM messages in order to incentivize relayers to deliver them, as documented [here](https://github.com/ava-labs/icm-contracts/tree/main/contracts/teleporter#fees). The token transfer contracts in this repository allow for specifying any ERC20 token and amount to be used as the ICM message fee for single-hop transfers in either direction between `TokenHome` and `TokenRemote` instances. Fee amounts must be pre-approved to be spent by the token transfer contract before initiating a transfer.
Multi-hop transfers between two `TokenRemote` instances involve two ICM messages: the first from the initiating `TokenRemote` instance to its home, and the second from its home to the destination `TokenRemote` instance. In the multi-hop case, the first message fee can be paid in any ERC20 token and amount (similar to the single-hop case), but the second message fee must be paid in-kind of the asset being transferred and is deducted from the amount being transferred. This restriction on the secondary message fee is necessary because the transaction on the intermediate chain routing the funds to the destination `TokenRemote` instance is not sent by the wallet performing the transfer. Because of this, it can not directly spend an arbitrary ERC20 token from that wallet. Using the asset being transferred for the optional secondary fee allows users to perform an incentivized multi-hop transfer without needing to make any interaction with the home themselves. If there is a need for the second message from the home to the destination `TokenRemote` instance to pay a fee in another asset, it is recommended to perform two single-hop transfers, which allows for specifying an arbitrary ERC20 token to be used for the fee of each.
# Teleporter Addresses
URL: /docs/cross-chain/teleporter/addresses
## Deployed Addresses
| Contract | Address | Chain |
| --------------------- | ---------------------------------------------- | ------------------------ |
| `TeleporterMessenger` | **0x253b2784c75e510dD0fF1da844684a1aC0aa5fcf** | All chains, all networks |
| `TeleporterRegistry` | **0x7C43605E14F391720e1b37E49C78C4b03A488d98** | Mainnet C-Chain |
| `TeleporterRegistry` | **0xF86Cb19Ad8405AEFa7d09C778215D2Cb6eBfB228** | Fuji C-Chain |
1. Using [Nick's method](https://yamenmerhi.medium.com/nicks-method-ethereum-keyless-execution-168a6659479c#), `TeleporterMessenger` deploys at a universal address across all chains, varying with each `teleporter` Major release. **Compatibility exists only between same versions of `TeleporterMessenger` instances.** See [Teleporter Contract Deployment](https://github.com/ava-labs/teleporter/blob/main/utils/contract-deployment/README.md) and [Deploy Teleporter to a Subnet](https://github.com/ava-labs/teleporter/tree/main?tab=readme-ov-file#deploy-teleporter-to-a-subnet) for more details.
2. `TeleporterRegistry` can be deployed to any address. See [Deploy TeleporterRegistry to a Subnet](https://github.com/ava-labs/teleporter/blob/main/README.md#deploy-teleporter-to-a-subnet) for details. The table above enumerates the canonical registry addresses on the Mainnet and Fuji C-Chains.
## A Note on Versioning
Release versions follow the [semver](https://semver.org/) convention of incompatible Major releases. A new Major version is released whenever the `TeleporterMessenger` bytecode is changed, and a new version of `TeleporterMessenger` is meant to be deployed.
Due to the use of Nick's method to deploy the contract to the same address on all chains (see [Teleporter Contract Deployment](https://github.com/ava-labs/teleporter/blob/main/utils/contract-deployment/README.md) for details), this also means that new release versions would result in different Teleporter contract addresses. Minor and Patch versions may pertain to contract changes that do not change the `TeleporterMessenger` bytecode, or to changes in the test frameworks, and will only be included in tags.
# Teleporter CLI
URL: /docs/cross-chain/teleporter/cli
The CLI is a command line interface for interacting with the Teleporter contracts.
# Teleporter CLI
This directory contains the source code for the Teleporter CLI. The CLI is a command line interface for interacting with the Teleporter contracts. It is written with [cobra](https://github.com/spf13/cobra) commands as a Go application.
## Build
To build the CLI, run `go build` from this directory. This will create a binary called `teleporter-cli` in the current directory.
## Usage
The CLI has a number of subcommands. To see the list of subcommands, run `./teleporter-cli help`. To see the help for a specific subcommand, run `./teleporter-cli help
/>
alt="Upgrade UML diagram"/>