Skip to content
Back to skills

Gdex Perp Funding

ASecurity

Deposit and withdraw USDC to/from HyperLiquid for perpetual futures trading — constraints, amounts, and managed-custody flow

  • 4 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 3, 2026
ai-agentstypescriptapibackend

Works with

  • cli
  • api

Security analysis

A100/100

Scanned October 3, 2026

npx -y skills add GemachDAO/gdex-skill --skill gdex-perp-funding --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Gdex Perp Funding?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Gdex Perp Funding
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/gemachdao-gdex-perp-funding/badge)](https://www.skillsdirectory.com/skills/gemachdao-gdex-perp-funding)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: gdex-perp-funding
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

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

const skill = new GdexSkill();
skill.loginWithApiKey(GDEX_API_KEY_PRIMARY);

// Amount is human-readable USDC — SDK converts to smallest unit (6 decimals) internally
await skill.perpDeposit({ amount: '10' });   // deposit 10 USDC (minimum)
await skill.perpDeposit({ amount: '100' });  // deposit 100 USDC
```

### Managed-Custody Deposit (Explicit)

```typescript
await skill.perpDeposit({
  amount: '50',
  tokenAddress: '[REDACTED]', // 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: '5' });   // withdraw 5 USDC
```

### Managed-Custody Withdraw (Explicit)

```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
const balance = await skill.getHlUsdcBalance({ walletAddress: '0xYourAddress' });
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 outcome (HIP-3) trading or placing
an 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

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.