---
name: gdex-perp-funding-6624a047463e
description: Deposit and withdraw USDC to/from HyperLiquid for perpetual futures trading — constraints, amounts, and managed-custody flow
---

# GDEX: HyperLiquid Funding (Deposit / Withdraw)

Manage USDC deposits and withdrawals between your managed wallet and HyperLiquid perp account.

## When to Use

- Depositing USDC to HyperLiquid before trading perps
- Withdrawing USDC from HyperLiquid back to managed wallet
- Understanding deposit constraints and delivery times

## Prerequisites

- `@gemachdao/gdex-skill` installed
- Authenticated via managed-custody sign-in — see **gdex-authentication**

## Deposit USDC to HyperLiquid

Every deposit needs the managed-custody credentials from sign-in (sign in with
`chainId: 1`). MCP users pass `accountRef` from `gdex_connect` to `perp_deposit` instead.

```typescript
import { GdexSkill, GDEX_API_KEY_PRIMARY } from '@gemachdao/gdex-skill';

const skill = new GdexSkill();
skill.loginWithApiKey(GDEX_API_KEY_PRIMARY);
// ... managed sign-in (see gdex-authentication) → apiKey, walletAddress (control), sessionPrivateKey

// Amount is human-readable USDC — SDK converts to smallest unit (6 decimals) internally. Min 10 USDC.
await skill.perpDeposit({
  amount: '50',
  tokenAddress: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', // USDC on Arbitrum
  chainId: 42161,     // Arbitrum
  apiKey,
  walletAddress,      // MUST be the CONTROL wallet address (from sign-in), NOT the managed address
  sessionPrivateKey,
});
```

> **CRITICAL:** `walletAddress` must be the **control wallet address** used during sign-in — NOT the managed-custody address returned by `/v1/user`. Passing the managed address causes `400 Unauthorized (code 103)`. See **gdex-authentication** for details.

## Withdraw USDC from HyperLiquid

```typescript
await skill.perpWithdraw({
  amount: '25',
  apiKey,
  walletAddress,
  sessionPrivateKey,
});
```

## Deposit Constraints

| Constraint | Value |
|------------|-------|
| **Chain** | Arbitrum only (chainId `42161`) |
| **Token** | USDC only (`0xaf88d065e77c8cC2239327C5EDb3A432268e5831`) |
| **Min deposit** | 10 USDC |
| **Amount format** | Human-readable (e.g., `'10'` for 10 USDC); SDK converts to 6 decimal smallest unit internally |
| **Fee buffer** | Managed wallet must hold `amount × 1.01` (1% fee) |
| **Delivery time** | ~10 minutes after Arbitrum tx confirms |
| **On-chain amount** | 10 USDC = `10000000` (6 decimals) in the ABI encoding |

## Check USDC Balance on HyperLiquid

```typescript
// HL funds sit on the managed EVM wallet (getManagedUser with chainId 1)
const balance = await skill.getHlUsdcBalance(managedEvmAddress);
console.log('Available USDC:', balance);
```

## ABI Encoding Details

The deposit uses a specific ABI schema with `uint64` for chainId:

| Field | ABI Type | Example |
|-------|----------|---------|
| `chainId` | `uint64` | `42161` |
| `tokenAddress` | `address` | `0xaf88d065e77c8cC2239327C5EDb3A432268e5831` |
| `amount` | `uint256` | `10000000` (10 USDC) |
| `nonce` | `string` | Client-generated timestamp + random |

**CRITICAL:** `chainId` is `uint64`, NOT `uint256`. Using `uint256` causes `400 Unauthorized (code 103)`.

Withdraw ABI schema:

| Field | ABI Type | Example |
|-------|----------|---------|
| `amount` | `string` | `'5000000'` (5 USDC in smallest unit) |
| `nonce` | `string` | Client-generated |

## Common Issues

### "Insufficient balance" on deposit
- Managed wallet needs `amount × 1.01` USDC on Arbitrum (1% fee buffer)
- Check managed wallet balance, not HL perp balance

### Deposit doesn't appear on HL
- Normal delivery time is ~10 minutes after Arbitrum tx confirmation
- Use `getHlUsdcBalance()` or `getHlAccountState()` to check

### ⚠️ Deposit may return an error even when it succeeded (verify before retrying)
The backend can return an error (HTTP 400, "Transaction has been reverted…")
**even though the on-chain USDC transfer to the HL bridge succeeded** and the
funds are en route. **Do not blindly retry** — a retry spends gas and can move
funds twice. On any deposit error, first check the managed wallet's USDC
balance on Arbitrum and `getHlAccountState()` / `getHlUsdcBalance()`; only
retry if the balance is unchanged after a few minutes.

### Deposited funds show under the managed address (and may move to spot)
HyperLiquid credits the depositing wallet (the **managed** address), so check
`getHlAccountState(managedAddress)`. Enabling HL trading or placing
a HIP-4 outcome order can move USDC from the perp account to the **spot** balance —
check `getHlSpotState(managedAddress)` if the perp balance reads `$0`.

### 400 Unauthorized (code 103)
- **Most common cause:** Passing the managed address as `walletAddress` instead of the control wallet address — see **gdex-authentication**
- Second cause: `uint256` vs `uint64` encoding mismatch for chainId — see **gdex-perp-trading** for full ABI details

## Autonomous Agent Notes (Live-Tested)

1. **Deposit of 10 USDC was E2E verified.** Takes ~10 minutes for USDC to appear on HyperLiquid after Arbitrum tx confirms.
2. **After deposit, check balance with `getHlAccountState()`** — `getGbotUsdcBalance` returns 404.
3. **Amount is human-readable for high-level methods** (`perpDeposit({ amount: '10' })`), but the ABI encoding internally converts to 6-decimal smallest unit (10 USDC = 10000000).
4. **Sign-in must use `chainId: 1`** (EVM) for HL deposit/withdraw operations.
5. **`walletAddress` MUST be control wallet** — passing managed address → 400 Unauthorized (code 103).

## Related Skills

- **gdex-authentication** — Managed-custody auth required for deposits/withdrawals
- **gdex-perp-trading** — Trade perps after funding your HL account
- **gdex-portfolio** — Check overall portfolio including HL positions


---
Source attribution: GemachDAO
Original project: https://github.com/GemachDAO/gdex-skill/blob/7e51b52977be7ada679d2cbe58107d14db83cd83/skills/gdex-perp-funding/SKILL.md
License: MIT
License information: https://opensource.org/license/mit
Original upstream instructions; downloaded from Mega AI Hub.

## Upstream license notice

MIT License

Copyright (c) 2026 GemachDAO

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.



# Mega AI Hub resource metadata

Creator / publisher: GemachDAO
Original project: https://github.com/GemachDAO/gdex-skill/blob/7e51b52977be7ada679d2cbe58107d14db83cd83/skills/gdex-perp-funding/SKILL.md
Attribution basis: Source repository record

Fields of work: Finance & Accounting, Marketing
Roles: Financial Analyst, Growth Marketer, Product Marketer
Specialties: API, Backend, Frontend, Playwright, Testing
Tools: @Gdexsdk/Gdex Skill
Country applicability: Country not specified
Classification basis: Source catalog labels
Instruction SHA-256: 6b3d6414eacbe8d856679c5cf1eaefec6ca811e2563cab138a609ec69fa96eb1
