Goliath → 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:
ERC-20 withdraw (ETH, USDC) — one transaction on Goliath, calling
BridgeMint.burn(...).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
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
ETH
0x9253587505c3B7E7b9DEE118AE1AcB53eEC0E4b6
18
USDC
0xC8410270bb53f6c99A2EFe6eD3686a8630Efe22B
6
BridgeMint contract on Goliath: 0x1d14ae13ca030eb5e9e2857e911af515cf5ffff2
The burn Function
burn FunctionEmits:
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
BridgeMintStep 3 — Call burn
burnStep 4 — Poll status
Expect the status to progress CONFIRMING → AWAITING_RELAY (during the 1 h hold) → PROCESSING_DESTINATION → COMPLETED.
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:
Sign an EIP-712 withdrawal intent with your Goliath wallet.
Register the intent via
POST /bridge/xcn-withdraw-intent. The API returns arelayerWalletAddress.Send a plain native XCN transfer from your wallet to
relayerWalletAddresswithvalue = amount.Pair the resulting tx hash to the intent via
POST /bridge/xcn-withdraw-intent/bind-origin.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.
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
The EIP-712 domain must be GoliathBridge / version 1 / chainId = 327 (or 8901 on testnet). Signatures from a different domain are rejected with SIGNATURE_DOMAIN_REJECTED.
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
The to address must be the relayerWalletAddress returned by the API in the same flow. Sending XCN to the old relayer or to BridgeMint will not trigger a withdrawal — there is no automatic refund. Read relayerWalletAddress fresh for every transfer.
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:
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_TX → CONFIRMING → AWAITING_RELAY (during the hold) → PROCESSING_DESTINATION → COMPLETED. If the intent expires before the tx is bound, the status ends at EXPIRED.
Complete Example (viem)
Common Errors
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
REST API Reference — every endpoint used above.
Contracts & Events — full ABIs and testnet addresses.
Smart Account Integration — ERC-1271 / ERC-4337 variant of the native-XCN flow.
Ethereum → Goliath — the reverse direction.
Last updated