@zethub/bridge
How it works

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.

  • TokenMessengerV2 burns USDC and emits the message on the source chain.
  • MessageTransmitterV2 verifies 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.

  • TokenMessenger and MessageTransmitter play the same burn and mint roles inside Soroban.
  • CctpForwarder exists 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

RouteSource burnDestination mint
EVM to EVMTokenMessengerV2.depositForBurnMessageTransmitterV2.receiveMessage
EVM to StellarTokenMessengerV2.depositForBurnWithHookCctpForwarder.mint_and_forward
Stellar to EVMTokenMessenger.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

On this page