arrow-leftGoliath → Ethereum

Step-by-step integration guide for bridging ETH, USDC, or XCN from Goliath Mainnet back to Ethereum Mainnet — burn flow for ERC-20s and signed-intent flow for native XCN.

Bridging from Goliath Mainnet (327) to Ethereum Mainnet (1) splits into two flows depending on the asset:

  1. ERC-20 withdraw (ETH, USDC) — one transaction on Goliath, calling BridgeMint.burn(...).

  2. Native-XCN withdraw — a signed EIP-712 intent plus a native XCN transfer. Required because XCN is the gas token on Goliath and cannot be "burned" as an ERC-20.

Both flows take ~1 hour total because of the one-hour security hold before the relayer releases funds on Ethereum, and both charge a withdrawal fee.

Fee Summary

Token
Fee rate
Minimum fee
Minimum bridge amount

ETH

0.25%

0.003 ETH

0.01 ETH

USDC

0.25%

5 USDC

10 USDC

XCN

0.25%

1,000 XCN

5,000 XCN

fee = max(amount * 25 / 10000, minFee[token]). Transfers below the minimum bridge amount are rejected by the API and should be blocked client-side.

Always call GET /bridge/fee-quote to render the user-facing breakdown — the canonical numbers come from the API.


ERC-20 Withdraw (ETH, USDC)

For assets that exist as ERC-20 tokens on Goliath (bridged ETH, bridged USDC), you call BridgeMint.burn(...).

Prerequisites

  • Wallet on Goliath Mainnet (Chain ID 327).

  • Enough native XCN for gas.

  • Enough of the token you're bridging.

  • One-time ERC-20 allowance granted to BridgeMint.

Goliath Bridged Token Addresses

Token
Goliath address
Decimals

ETH

0x9253587505c3B7E7b9DEE118AE1AcB53eEC0E4b6

18

USDC

0xC8410270bb53f6c99A2EFe6eD3686a8630Efe22B

6

BridgeMint contract on Goliath: 0x1d14ae13ca030eb5e9e2857e911af515cf5ffff2

The burn Function

Emits:

Full ABI in Contracts & Events.

Step 1 — Quote the fee

If the amount is below the minimum, the endpoint returns 400 BELOW_MINIMUM — surface that error to the user before they sign.

Step 2 — Approve BridgeMint

Step 3 — Call burn

Step 4 — Poll status

Expect the status to progress CONFIRMINGAWAITING_RELAY (during the 1 h hold) → PROCESSING_DESTINATIONCOMPLETED.

The response includes:

  • holdUntil — ISO timestamp when the relayer becomes eligible to release. Render as a countdown.

  • fee — the fee deducted (atomic + formatted).

  • outputAmount / outputAmountFormatted — what the recipient receives after fee.

  • destinationTxHash — the Ethereum tx that delivered the funds.

Complete Example (viem)


Native-XCN Withdraw

XCN is the native gas token on Goliath, so there is no ERC-20 to burn. The protocol uses a signed-intent flow instead:

  1. Sign an EIP-712 withdrawal intent with your Goliath wallet.

  2. Register the intent via POST /bridge/xcn-withdraw-intent. The API returns a relayerWalletAddress.

  3. Send a plain native XCN transfer from your wallet to relayerWalletAddress with value = amount.

  4. Pair the resulting tx hash to the intent via POST /bridge/xcn-withdraw-intent/bind-origin.

  5. After the hold, the relayer releases XCN (as ERC-20) on Ethereum to recipientAddress.

All five steps happen inside a single user flow. If the wallet disconnects between steps 3 and 4, the client must retry step 4 (the binding) when it reconnects — the bridge keeps the intent alive for 30 minutes.

circle-info

Using an ERC-4337 / smart-account wallet (Safe, Coinbase Smart Wallet, Biconomy, Alchemy AA, ZeroDev, thirdweb, …)? The endpoints, typed-data shape, and status flow below are identical, but senderAddress is the smart-account contract address, the signature is verified via ERC-1271 (isValidSignature(bytes32,bytes) returning 0x1626ba7e), and originTxHash is the final execution tx hash — not the userOpHash. See Smart Account Integration for the full list of hard rules and worked examples (viem + permissionless.js, ethers v6 + @safe-global/protocol-kit).

Prerequisites

  • Wallet on Goliath Mainnet (Chain ID 327).

  • Enough native XCN for amount + gas.

  • Client able to produce EIP-712 signatures (every mainstream wallet SDK supports this).

Step 1 — Build and sign the EIP-712 intent

circle-exclamation
circle-info

amountAtomic for XCN is an 18-decimal wei string — the same scale the Goliath JSON-RPC uses for eth_getBalance and value in eth_sendTransaction. You do not apply the 8-decimal tinyxcn conversion when composing the intent. See XCN Decimal Handling for context.

Step 2 — Register the intent

Store intentId locally — you will need it in Step 4 and for recovery if the user reopens the app.

Step 3 — Send native XCN to the relayer

triangle-exclamation

Step 4 — Bind the origin tx hash

Implement retries with exponential backoff. The onyx-new-frontend reference client uses 5 attempts with a 2 s base delay (2, 4, 8, 16, 32 s). The intent remains valid until expiresAt, so binding can succeed any time inside that window.

Error codes you may need to handle:

HTTP
Error code
Meaning

404

INTENT_NOT_FOUND

Wrong intentId or expired and garbage-collected.

409

INTENT_ALREADY_BOUND

You already bound this intent — stop retrying.

410

INTENT_EXPIRED

Missed the 30 min window. The user will need to restart the flow.

403

SENDER_MISMATCH

senderAddress does not match the intent signer.

Step 5 — Poll status

Same as the ERC-20 flow: GET /bridge/status?originTxHash=<txHash>. Polling returns the same shape whether the underlying mechanism was a burn or a native XCN transfer.

The status sequence is PENDING_ORIGIN_TXCONFIRMINGAWAITING_RELAY (during the hold) → PROCESSING_DESTINATIONCOMPLETED. If the intent expires before the tx is bound, the status ends at EXPIRED.

Complete Example (viem)

Common Errors

Symptom
Cause
Fix

BELOW_MINIMUM on /fee-quote

Transfer under the per-token minimum.

Increase the amount.

SIGNATURE_DOMAIN_REJECTED on intent registration

Signed with wrong chainId.

Use 327 (mainnet) or 8901 (testnet).

SIGNATURE_MISMATCH

senderAddress in body ≠ signer recovered from signature.

Re-sign with the connected account. For smart-account wallets, confirm senderAddress is the contract address and see Smart Account Integration.

SIGNATURE_VERIFICATION_UNAVAILABLE (503)

Transient RPC error, or a smart-account senderAddress is not yet deployed on Goliath.

Back off 1–5 s and retry. If you're using a counterfactual smart account, deploy it first — ERC-6492 pre-deploy signatures are not supported.

DEADLINE_EXPIRED

deadline in past.

Re-sign with a future deadline.

INTENT_EXPIRED with a smart-account wallet

Bound a userOpHash instead of the execution tx hash; intent never paired.

Resolve eth_getUserOperationReceipt(userOpHash).receipt.transactionHash before calling /bind-origin. See Smart Account Integration.

Burn reverts with BridgeMint: insufficient allowance

No approve step.

Approve the token before calling burn.

Status stuck at AWAITING_RELAY for >1 hour

Hold period not elapsed.

Wait until holdUntil; it's not an error.

Next

Last updated