> ## 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.

# Transfer USDC from HyperEVM to HyperCore

This guide shows how to transfer USDC from HyperEVM to HyperCore using the
`CoreDepositWallet` contract.

<Tip>
  **Tip:** The `CoreDepositWallet` contract provides `deposit`, `depositFor`,
  and `depositWithAuth` methods. This guide uses `deposit`. All methods accept a
  `destinationDex` parameter (`0` for perps, `4294967295` for spot). See the
  [CoreDepositWallet contract
  interface](/cctp/references/coredepositwallet-contract-interface) for detailed
  information.
</Tip>

## Prerequisites

Before you begin, ensure that you've:

* Installed [Node.js v22+](https://nodejs.org/)

* Prepared an EVM testnet wallet with the private key available

* Funded your wallet with HyperEVM testnet USDC from the
  [Circle Faucet](https://faucet.circle.com)

* Created a new Node project and installed dependencies:

  ```bash theme={null}
  npm install viem
  npm install -D tsx typescript @types/node
  ```

* Created a `.env` file with required environment variable:

  ```text theme={null}
  PRIVATE_KEY=0x...
  ```

## Steps

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

### Step 1. Approve the `CoreDepositWallet` to spend USDC

Approve the `CoreDepositWallet` contract to transfer USDC on your behalf:

```ts TypeScript theme={null}
const hash = await walletClient.writeContract({
  address: USDC_ADDRESS,
  abi: USDC_ABI,
  functionName: "approve",
  args: [CORE_DEPOSIT_WALLET, amount],
});

await publicClient.waitForTransactionReceipt({ hash });
```

### Step 2. Call the `deposit` function

Call the `deposit` function with your desired amount and destination:

```ts TypeScript theme={null}
const hash = await walletClient.writeContract({
  address: CORE_DEPOSIT_WALLET,
  abi: CORE_DEPOSIT_WALLET_ABI,
  functionName: "deposit",
  args: [amount, destinationDex], // 0 = perps, 4294967295 = spot
});

const receipt = await publicClient.waitForTransactionReceipt({ hash });
```

The `deposit` function transfers USDC from your account to the
`CoreDepositWallet` and credits your HyperCore balance.

## Full example code

The following is a complete example of how to transfer USDC from HyperEVM to
HyperCore.

```ts script.ts expandable theme={null}
/**
 * Script: Call CoreDepositWallet.deposit on HyperEVM
 * - Approves USDC spending
 * - Calls deposit(amount, destinationDex)
 */

import {
  createWalletClient,
  createPublicClient,
  http,
  parseUnits,
  formatUnits,
  type Address,
  type Hex,
} from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { hyperliquidEvmTestnet } from "viem/chains";

// -------- Configuration --------
const config = {
  privateKey: (process.env.PRIVATE_KEY || "0x") as Hex,

  // Contract addresses (HyperEVM Testnet)
  coreDepositWallet: "0x0B80659a4076E9E93C7DbE0f10675A16a3e5C206" as Address,
  usdcToken: "0x2B3370eE501B4a559b57D449569354196457D8Ab" as Address,

  // Transfer parameters
  amount: "2", // USDC amount to deposit

  // HyperCore destination (0 = perps, 4294967295 = spot)
  destinationDex: 0,
};

// -------- Main Function --------
async function main() {
  // Validate private key
  if (!config.privateKey || config.privateKey === "0x") {
    throw new Error("Set PRIVATE_KEY");
  }

  // Setup account and clients
  const account = privateKeyToAccount(config.privateKey);
  const publicClient = createPublicClient({
    chain: hyperliquidEvmTestnet,
    transport: http(),
  });
  const walletClient = createWalletClient({
    chain: hyperliquidEvmTestnet,
    transport: http(),
    account,
  });

  const amount = parseUnits(config.amount, 6);

  console.log("User:", account.address);
  console.log("CoreDepositWallet:", config.coreDepositWallet);
  console.log("USDC:", config.usdcToken);
  console.log("Amount (USDC):", config.amount);
  console.log(
    "Destination DEX:",
    config.destinationDex === 0 ? "perps" : "spot",
  );

  // Check USDC balance
  const balance = await publicClient.readContract({
    address: config.usdcToken,
    abi: [
      {
        name: "balanceOf",
        type: "function",
        stateMutability: "view",
        inputs: [{ name: "account", type: "address" }],
        outputs: [{ name: "", type: "uint256" }],
      },
    ],
    functionName: "balanceOf",
    args: [account.address],
  });

  if (balance < amount) {
    throw new Error(
      `Insufficient USDC: have ${formatUnits(balance, 6)}, need ${config.amount}`,
    );
  }

  // Check current allowance
  const currentAllowance = await publicClient.readContract({
    address: config.usdcToken,
    abi: [
      {
        name: "allowance",
        type: "function",
        stateMutability: "view",
        inputs: [
          { name: "owner", type: "address" },
          { name: "spender", type: "address" },
        ],
        outputs: [{ name: "", type: "uint256" }],
      },
    ],
    functionName: "allowance",
    args: [account.address, config.coreDepositWallet],
  });

  // Step 1: Approve if needed
  if (currentAllowance < amount) {
    console.log("\nApproving USDC spending...");
    const hash = await walletClient.writeContract({
      address: config.usdcToken,
      abi: [
        {
          name: "approve",
          type: "function",
          stateMutability: "nonpayable",
          inputs: [
            { name: "spender", type: "address" },
            { name: "amount", type: "uint256" },
          ],
          outputs: [{ name: "", type: "bool" }],
        },
      ],
      functionName: "approve",
      args: [config.coreDepositWallet, amount],
    });

    console.log("Approve tx hash:", hash);
    await publicClient.waitForTransactionReceipt({ hash });
    console.log("Approval confirmed");
  } else {
    console.log("\nSufficient allowance already exists");
  }

  // Step 2: Deposit
  console.log("\nDepositing USDC to HyperCore...");
  const hash = await walletClient.writeContract({
    address: config.coreDepositWallet,
    abi: [
      {
        name: "deposit",
        type: "function",
        stateMutability: "nonpayable",
        inputs: [
          { name: "amount", type: "uint256" },
          { name: "destinationDex", type: "uint32" },
        ],
        outputs: [],
      },
    ],
    functionName: "deposit",
    args: [amount, config.destinationDex],
  });

  console.log("Deposit tx hash:", hash);

  // Wait for transaction receipt
  const receipt = await publicClient.waitForTransactionReceipt({ hash });

  console.log("Status:", receipt.status === "success" ? "SUCCESS" : "FAILED");
  console.log(
    "Block:",
    receipt.blockNumber,
    "\nGas Used:",
    receipt.gasUsed.toString(),
  );
}

// Run
main().catch((error) => {
  console.error("Error:", error.message);
  process.exit(1);
});
```

Run the script:

```bash theme={null}
npx tsx --env-file=.env script.ts
```
