Chains and contracts
The two chain families, how minting differs, and the exact contract on every network.
The bridge understands two kinds of chain. They burn and mint through different contracts, so it helps to know which is which.
EVM
EVM covers Ethereum and every EVM chain the SDK ships (Base, Arbitrum, Optimism, Polygon, Avalanche, Unichain, Linea, Codex, Sonic, World Chain, Sei, HyperEVM). USDC here is an ERC20 token with 6 decimals. Two contracts do the work.
TokenMessengerV2burns USDC and emits the message on the source chain.MessageTransmitterV2verifies the attestation and mints on the destination chain.
Both contracts live at the same addresses on every EVM chain. See Contracts.
Stellar
Stellar is a separate network with its own smart contract runtime, Soroban. USDC here is a Stellar Asset Contract with 7 decimals. Stellar also requires an account to hold a trustline before it can receive an asset. See Trustlines.
Stellar mirrors the EVM roles and adds one contract.
TokenMessengerandMessageTransmitterplay the same burn and mint roles inside Soroban.CctpForwarderexists because a mint on Stellar must be initiated by a caller. When you bridge to Stellar, the mint recipient in the burn message is the forwarder, not your account. The forwarder mints to itself, then forwards the USDC to the real recipient encoded in the message hook.
The three routes
| Route | Source burn | Destination mint |
|---|---|---|
| EVM to EVM | TokenMessengerV2.depositForBurn | MessageTransmitterV2.receiveMessage |
| EVM to Stellar | TokenMessengerV2.depositForBurnWithHook | CctpForwarder.mint_and_forward |
| Stellar to EVM | TokenMessenger.deposit_for_burn (Soroban) | MessageTransmitterV2.receiveMessage |
Read them in code
Every network in the SDK already carries these addresses. You never enter them.
import { NetworkId, AssetSymbol, ZetHubBridge } from "@zethub/bridge";
const sdk = new ZetHubBridge();
const chains = await sdk.chainDetailsMap();
const base = chains[NetworkId.BASE].network;
base.tokenMessenger; // burn contract
base.messageTransmitter; // mint contract
base.token(AssetSymbol.USDC).address; // the USDC token
const stellar = chains[NetworkId.STELLAR].network;
stellar.cctpForwarder; // used to mint on Stellar