Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developers.circle.com/llms.txt

Use this file to discover all available pages before exploring further.

This guide shows how to transfer USDC from Solana to HyperCore using the TokenMessengerV2 contract. Solana’s CCTP implementation does not have the depositForBurnWithAuth, and there is no CctpExtension contract for Solana. As such, transfers from Solana to HyperCore follow the standard CCTP flow, with the addition of hook data to call the CctpForwarder contract on HyperEVM. This guide does not provide full example code for the transfer to HyperCore from Solana.
Fast Transfers from Solana to HyperEVM incur a protocol fee and a dynamic forwarding fee for the HyperEVM chain relay transaction. Fast Transfer is the default for transfers from Solana to HyperCore.

Steps

Use the following steps to transfer USDC from Solana to HyperCore.

Step 1. Get CCTP fees from the API

Query the CCTP API for the fees for transferring USDC from Solana to HyperCore. This value is passed to the maxFee parameter in the depositForBurnWithHook transaction. The following is an example request to the CCTP using source domain 5 (Solana) and destination domain 19 (HyperEVM):
curl --request GET \
  --url 'https://iris-api-sandbox.circle.com/v2/burn/USDC/fees/5/19?forward=true&hyperCoreDeposit=true' \
  --header 'Content-Type: application/json'
Response:
[
  {
    "finalityThreshold": 1000, // fast transfer
    "minimumFee": 1, // in basis points
    "forwardFee": {
      "low": 211203,
      "med": 216109, // 0.216109 USDC
      "high": 221014
    }
  },
  {
    "finalityThreshold": 2000, // standard transfer
    "minimumFee": 0,
    "forwardFee": {
      "low": 211203,
      "med": 216109, // 0.216109 USDC
      "high": 221014
    }
  }
]

Step 2. Calculate the USDC amounts minus fees

There is a protocol fee to deposit USDC from Solana to HyperEVM and a dynamic forwarding fee for the HyperEVM chain relay transaction. The CCTP fast transfer fee is 1 basis point (0.01%) of the transfer amount. The forwarding fee is 0.20 USDC (0_200_000 subunits) plus a dynamic destination chain gas fee. For a 10 USDC transfer from Solana to HyperCore, the protocol fee is 0.001 USDC (10 USDC × 0.0001) and an example forwarding fee is 0.216109 USDC, for a total fee of 0.217109 USDC. Because the protocol fee scales with the transfer amount and the forwarding fee is dynamic, you must recalculate maxFee for each transfer. For a programmatic approach, see calculateMaxFee on the fees page.

Step 3. Sign and broadcast a depositForBurnWithHook transaction on the TokenMessengerV2 contract

Create a depositForBurnWithHook transaction for the TokenMessengerV2 contract with the following parameters:
  • amount: The amount of USDC to transfer
  • destinationDomain: 19 (HyperEVM)
  • mintRecipient: The address of the CctpForwarder contract on HyperEVM
  • destinationCaller: The address of the CctpForwarder contract on HyperEVM
  • maxFee: The protocol fee + forwarding fee calculated in Step 2
  • minFinalityThreshold: 1000 (Fast Transfer)
  • hookData: The hook data to call the CctpForwarder contract on HyperEVM
Always set both mintRecipient and destinationCaller to the CctpForwarder contract address on HyperEVM when you transfer USDC to HyperCore.
  • If destinationCaller is wrong, the forwarder cannot complete the transfer.
  • If mintRecipient is wrong, the minted USDC is not sent to the forwarder.
In either case, funds become permanently stuck and cannot be recovered.
The hookData is the data to execute the forwarder to HyperCore. The following is an example of the hook data:
TypeScript
/**
 * Generate CCTP forwarder hook data for HyperCore
 *
 * Hook Data Format:
 * Field                        Bytes      Type       Index
 * magicBytes                   24         bytes24    0     ASCII prefix "cctp-forward", followed by padding
 * version                      4          uint32     24
 * dataLength                   4          uint32     28
 * hyperCoreMintRecipient       20         address    32    EVM address - optional, included if requesting a deposit to HyperCore
 * hyperCoreDestinationDex      4          uint32     52    The destinationDexId on HyperCore (0 for perp and uint32.max for spot)
 */
function encodeForwardHookData(
  hyperCoreMintRecipient?: `0x${string}`,
  hyperCoreDestinationDex: number = 0,
): `0x${string}` {
  // Validate hex prefix if recipient provided
  if (hyperCoreMintRecipient && !hyperCoreMintRecipient.startsWith("0x")) {
    throw new Error("Address must start with 0x");
  }

  // Magic bytes: "cctp-forward" (12 chars) padded to 24 bytes with zeros
  const magic = "cctp-forward";
  const magicHex = Buffer.from(magic, "utf-8").toString("hex").padEnd(48, "0");

  // Version: uint32 = 0 (4 bytes, big-endian)
  const version = "00000000";

  if (!hyperCoreMintRecipient) {
    // No recipient: dataLength = 0, return header only (32 bytes)
    const dataLength = "00000000";
    return `0x${magicHex}${version}${dataLength}`;
  }

  // With recipient: dataLength = 24 (20 bytes address + 4 bytes dex)
  const dataLength = "00000018"; // 24 in hex

  // Address: 20 bytes (remove 0x prefix)
  const address = hyperCoreMintRecipient.slice(2).toLowerCase();

  // Destination DEX: uint32 big-endian
  // 0 = perps, 4294967295 (0xFFFFFFFF) = spot
  const dex = (hyperCoreDestinationDex >>> 0).toString(16).padStart(8, "0");

  return `0x${magicHex}${version}${dataLength}${address}${dex}`;
}
For full example code calling the depositForBurnWithHook function, see the Solana CCTP V2 example on GitHub. Once the deposit transaction is confirmed, the USDC is minted on HyperEVM and automatically forwarded to your address on HyperCore. By default (when hyperCoreDestinationDex is 0), deposits credit the perps balance on HyperCore. To deposit to the spot balance, set hyperCoreDestinationDex to 4294967295 (uint32 max value).