arrow-rightEthereum → Goliath

Step-by-step integration guide for bridging ETH, USDC, or XCN from Ethereum Mainnet to Goliath Mainnet — with ethers.js, viem, and status-polling examples.

Bridging from Ethereum Mainnet (1) to Goliath Mainnet (327) is a single transaction on Ethereum — no signed intent, no post-transfer API call. The relayer observes the Deposit event on Ethereum and mints the corresponding asset on Goliath automatically.

Typical completion time: ~5 minutes. No bridge fee (Ethereum gas only).

Prerequisites

  • A wallet connected to Ethereum Mainnet (Chain ID 1).

  • Enough ETH for gas.

  • For ERC-20 deposits (USDC, XCN): enough token balance + ETH for gas + approval (see Step 2).

Supported Tokens

Token
Ethereum-side asset
Address on Ethereum

ETH

Native ETH

n/a — pass msg.value

USDC

ERC-20

0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48

XCN

ERC-20

0xA2cd3D43c775978A96BdBf12d733D5A1ED94fb18

Destination (mint) addresses on Goliath are listed in Contracts & Events.

The BridgeLock Contract

Ethereum Mainnet BridgeLock: 0xa9fd64b5095d626f5a3a67e6db7fb766345f8092

Two user-facing functions:

// Native ETH
function depositNative(address destinationAddress)
    external payable
    returns (bytes32 depositId);

// ERC-20 tokens
function deposit(address token, uint256 amount, address destinationAddress)
    external
    returns (bytes32 depositId);

Both emit:

Full ABI in Contracts & Events.

Step 1 — (Optional) Quote the transfer

Deposits have no fee, but calling GET /bridge/fee-quote confirms the token is supported and returns the same canonical inputAmount / outputAmount shape you will see later in status responses.

Skip this step if you already know the amount.

Step 2 — Approve ERC-20 allowance (USDC and XCN only)

Skip for native ETH.

circle-info

Approving maxUint256 is the default in the Onyx App — users pay gas for approve only once per token. Switch to an exact amount if your policy forbids unbounded allowances.

Step 3 — Submit the deposit

Native ETH

USDC (6 decimals)

XCN (ERC-20 on Ethereum, 18 decimals)

circle-exclamation

Step 4 — Extract the depositId (optional)

The Deposit event includes a depositId — a bytes32 identifier you can use in place of the tx hash when polling status. It's emitted as an indexed topic so you can parse it directly from the receipt logs:

You can also skip this step entirely and just poll by originTxHash — both identifiers resolve to the same operation.

Step 5 — Poll the bridge API

Once the tx is included on Ethereum, poll GET /bridge/status until the operation reaches COMPLETED.

Response shape:

Poll every 5–10 seconds. See API Reference — /bridge/status for all fields.

circle-info

A 404 response is expected for the first few seconds after you submit the tx — the relayer indexes the event asynchronously. Treat 404 as "keep polling" until your own timeout (e.g. 15 minutes) elapses.

Step 6 — Verify on Goliath

Once status === "COMPLETED":

  • destinationTxHash is the Goliath transaction that credited the recipient.

  • settlement.tokenAddress is the bridged ERC-20 contract on Goliath (or null if the asset is native XCN).

  • settlement.amountFormatted is the delivered amount (equal to amount for deposits, since there's no deposit fee).

You can render the explorer link as https://explorer.goliath.net/tx/{destinationTxHash}.

Putting It All Together

A minimal viem end-to-end example for USDC:

Common Errors

Symptom
Cause
Fix

ERC20: insufficient allowance

Skipped Step 2.

Run approve first.

Tx reverts with BridgeLock: amount must be greater than 0

Passed amount = 0 / msg.value = 0.

Send a non-zero amount.

/bridge/status returns 404 for several minutes

Event still being indexed.

Keep polling. Usually resolves inside 30 s.

Deposit included but mint never lands

Destination address is a contract that cannot receive the bridged ERC-20.

Unblock the recipient or contact support.

Next

Last updated