Skip to main content
This guide shows how to transfer USDC from HyperEVM to HyperCore using the CoreDepositWallet contract. The CoreDepositWallet contract provides three deposit functions: deposit, depositFor, and depositWithAuth. See the CoreDepositWallet contract interface for detailed information about these functions.
Tip: You can also use the depositFor method to deposit on behalf of another user, or the depositWithAuth method to use ERC-3009 authorization instead of a separate approve transaction. All methods accept a destinationDex parameter (0 for perps, 4294967295 for spot).
Review the full CoreDepositWallet contract interface for detailed information about these functions.

Prerequisites

Before you start, you should have:
  • Installed Node.js (version 16 or higher) and npm on your development machine
  • Created a testnet wallet on HyperEVM and have the private key available
  • Funded your testnet wallet with testnet USDC
  • Installed the ethers package (version 6):
    npm install ethers
    

Steps

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

Step 1. Set up your environment

Set up your wallet and contract instances:
const { ethers } = require("ethers");

// Configuration
const RPC_URL = "https://rpc.hyperliquid-testnet.xyz/evm";
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const USDC_ADDRESS = "0x2B3370eE501B4a559b57D449569354196457D8Ab";
const CORE_DEPOSIT_WALLET = "0x0B80659a4076E9E93C7DbE0f10675A16a3e5C206";

// Connect to HyperEVM
const provider = new ethers.JsonRpcProvider(RPC_URL);
const wallet = new ethers.Wallet(PRIVATE_KEY, provider);

// Contract instances
const usdc = new ethers.Contract(
  USDC_ADDRESS,
  [
    "function approve(address spender, uint256 amount) returns (bool)",
    "function allowance(address owner, address spender) view returns (uint256)",
  ],
  wallet,
);

const coreDepositWallet = new ethers.Contract(
  CORE_DEPOSIT_WALLET,
  ["function deposit(uint256 amount, uint32 destinationDex)"],
  wallet,
);

Step 2. Approve the CoreDepositWallet to spend USDC

Check the current allowance and approve if needed:
const amount = ethers.parseUnits("10", 6); // 10 USDC

// Check current allowance
const currentAllowance = await usdc.allowance(
  wallet.address,
  CORE_DEPOSIT_WALLET,
);

// Approve if needed
if (currentAllowance < amount) {
  const approveTx = await usdc.approve(CORE_DEPOSIT_WALLET, amount);
  console.log("Approve tx:", approveTx.hash);
  await approveTx.wait();
  console.log("Approval confirmed");
}

Step 3. Call the deposit function

Call the deposit function with your desired amount and destination:
// 0 = perps, 4294967295 = spot
const destinationDex = 0;

const depositTx = await coreDepositWallet.deposit(amount, destinationDex);
console.log("Deposit tx:", depositTx.hash);

const receipt = await depositTx.wait();
console.log("Deposit confirmed in block:", receipt.blockNumber);
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.
#!/usr/bin/env node

/**
 * Script: Call CoreDepositWallet.deposit on HyperEVM
 * - Approves USDC spending
 * - Calls deposit(amount, destinationDex)
 *
 * Requires: npm i ethers (v6)
 */

const { ethers } = require("ethers");

// -------- Configuration --------
const CONFIG = {
  // HyperEVM Testnet RPC (override via RPC_URL env)
  RPC_URL: process.env.RPC_URL || "https://rpc.hyperliquid-testnet.xyz/evm",

  // Keys & Contracts (override via env)
  PRIVATE_KEY: process.env.PRIVATE_KEY || "<PRIVATE_KEY>",
  CORE_DEPOSIT_WALLET:
    process.env.CORE_DEPOSIT_WALLET ||
    "0x0B80659a4076E9E93C7DbE0f10675A16a3e5C206",
  USDC_TOKEN:
    process.env.USDC_TOKEN || "0x2B3370eE501B4a559b57D449569354196457D8Ab",

  // Amount (USDC decimals = 6)
  AMOUNT_USDC: process.env.AMOUNT_USDC || "10",

  // Destination DEX (0 = perps, 4294967295 = spot)
  DESTINATION_DEX: Number(process.env.DESTINATION_DEX || 0),
};

// -------- ABIs --------
const CORE_DEPOSIT_WALLET_ABI = [
  "function deposit(uint256 amount, uint32 destinationDex)",
];

const USDC_ABI = [
  "function approve(address spender, uint256 amount) returns (bool)",
  "function balanceOf(address) view returns (uint256)",
  "function allowance(address owner, address spender) view returns (uint256)",
];

// -------- Helpers --------
function toUSDC(amountStr) {
  return ethers.parseUnits(amountStr, 6);
}

// -------- Main --------
async function main() {
  const {
    RPC_URL,
    PRIVATE_KEY,
    CORE_DEPOSIT_WALLET,
    USDC_TOKEN,
    AMOUNT_USDC,
    DESTINATION_DEX,
  } = CONFIG;

  if (!PRIVATE_KEY || PRIVATE_KEY === "<PRIVATE_KEY>")
    throw new Error("Set PRIVATE_KEY");
  if (!ethers.isAddress(CORE_DEPOSIT_WALLET))
    throw new Error("Invalid CORE_DEPOSIT_WALLET");
  if (!ethers.isAddress(USDC_TOKEN)) throw new Error("Invalid USDC_TOKEN");

  const provider = new ethers.JsonRpcProvider(RPC_URL);
  const wallet = new ethers.Wallet(PRIVATE_KEY, provider);
  const from = wallet.address;

  const coreDepositWallet = new ethers.Contract(
    CORE_DEPOSIT_WALLET,
    CORE_DEPOSIT_WALLET_ABI,
    wallet,
  );
  const usdc = new ethers.Contract(USDC_TOKEN, USDC_ABI, wallet);

  console.log("User:", from);
  console.log("CoreDepositWallet:", CORE_DEPOSIT_WALLET);
  console.log("USDC:", USDC_TOKEN);
  console.log("Amount (USDC):", AMOUNT_USDC);
  console.log("Destination DEX:", DESTINATION_DEX === 0 ? "perps" : "spot");

  const amount = toUSDC(AMOUNT_USDC);

  // Check USDC balance
  const balance = await usdc.balanceOf(from);
  console.log("USDC Balance:", ethers.formatUnits(balance, 6));
  if (balance < amount) {
    throw new Error(
      `Insufficient USDC: have ${ethers.formatUnits(
        balance,
        6,
      )}, need ${AMOUNT_USDC}`,
    );
  }

  // Check current allowance
  const currentAllowance = await usdc.allowance(from, CORE_DEPOSIT_WALLET);
  console.log(
    "Current Allowance:",
    ethers.formatUnits(currentAllowance, 6),
    "USDC",
  );

  // Step 1: Approve if needed
  if (currentAllowance < amount) {
    console.log("\nStep 1: Approving USDC spending...");
    const approveTx = await usdc.approve(CORE_DEPOSIT_WALLET, amount);
    console.log("Approve tx hash:", approveTx.hash);
    await approveTx.wait();
    console.log("Approval confirmed");
  } else {
    console.log("\nStep 1: Sufficient allowance already exists");
  }

  // Step 2: Deposit
  console.log("\nStep 2: Depositing USDC to HyperCore...");
  const depositTx = await coreDepositWallet.deposit(amount, DESTINATION_DEX);
  console.log("Deposit tx hash:", depositTx.hash);

  const receipt = await depositTx.wait();
  console.log("Status:", receipt.status === 1 ? "SUCCESS" : "FAILED");
  console.log(
    "Block:",
    receipt.blockNumber,
    "Gas Used:",
    receipt.gasUsed.toString(),
  );
  console.log(
    `\n✅ Successfully deposited ${AMOUNT_USDC} USDC to HyperCore ${
      DESTINATION_DEX === 0 ? "perps" : "spot"
    } balance`,
  );
}

if (require.main === module) {
  main().catch((e) => {
    console.error("Error:", e.message);
    process.exit(1);
  });
}