Bridging
Moving USDC and other tokens between HyperEVM and HyperCore — including the unified-account edge case.
Hyperliquid runs two surfaces: HyperEVM (chain id 999) for ERC-20 balances and contract calls, and HyperCore (L1) where orderbook trading happens. Outcome markets live on HyperCore, but your USDC most likely starts on HyperEVM.
Hedgepit handles the bridge for you, but it helps to know what's actually happening on each path.
Deposit (HyperEVM → HyperCore)#
There are two flavours depending on the token:
- USDC → calls
CoreDepositWallet.deposit(amount, dest=0)after a standard ERC-20approve. Lands in the perps (or unified) balance. - Any other spot token → direct ERC-20
transfer(systemAddress, amount)wheresystemAddress = 0x20…<tokenIndex>. Lands in the spot balance. No approval needed.
Withdraw (HyperCore → HyperEVM)#
Withdrawal is more nuanced — Hyperliquid has two account modes and they take different paths.
Standard (non-unified) account#
usdClassTransferperps → spot, if you're withdrawing more USDC than already sits in spot.spotSendto the token's system address.
Unified / portfolio-margin account#
Unified accounts reject usdClassTransfer and spotSend to system address with "Action disabled when unified account is active". Use sendAsset instead:
{
sourceDex: "spot",
destinationDex: "spot",
destination: tokenSystemAddress(idx),
token: "Name:0x<tokenId>",
fromSubAccount: "",
}Decimal truncation#
Both paths require the amount truncated to evmDecimals = weiDecimals + evm_extra_wei_decimals. For most stables that's 8 + (-2) = 6. Pass weiDecimals and the bridge rejects with "Invalid number of decimals".
Token format#
spotSend and sendAsset want the colon-prefixed form: "USDH:0x<tokenId>". Bare names ("USDH") return "Unknown token".