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

# CoreDepositWallet contract interface

The `CoreDepositWallet` contract on HyperEVM allows you to deposit USDC from
HyperEVM to HyperCore. This topic describes the contract interface and the
available deposit functions.

<Warning>
  To move USDC from HyperEVM to HyperCore, always call one of the
  `CoreDepositWallet` deposit functions (`deposit`, `depositFor`, or
  `depositWithAuth`). Only USDC is supported.

  Sending USDC or any tokens directly to the `CoreDepositWallet` contract address
  doesn't trigger a deposit on HyperCore. The funds are permanently stuck.
</Warning>

## Deposit functions

The `CoreDepositWallet` provides three entry points for depositing USDC from
HyperEVM into HyperCore. All deposits credit a user's balance on HyperCore, on
either the perps or spot DEX.

### `deposit` function

The `deposit` function transfers USDC from the caller's address and credits the
same address on HyperCore, after the caller has approved the `CoreDepositWallet`
to spend their tokens.

**Signature:**

```solidity theme={null}
deposit(uint256 amount, uint32 destinationDex);
```

**Parameters:**

| Parameter        | Value                                                                                                                           |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `amount`         | The USDC amount being deposited from HyperEVM to HyperCore                                                                      |
| `destinationDex` | The HyperCore destination `dex` index. Accepted values are:<br />- `0` → default perps DEX<br />- `type(uint32).max` → spot DEX |

**Token pull:** Uses `transferFrom(msg.sender, address(this), amount)` →
requires prior ERC-20 approve from the `msg.sender` to the core deposit wallet.

**Who is credited:** The `msg.sender` of the transaction on HyperEVM is credited
on HyperCore.

**Examples:**

ERC-20 Approval:

```shell theme={null}
# approve the CoreDepositWallet to spend 100 USDC from the sender
cast send <USDC_ADDRESS> "approve(address,uint256)" <CORE_DEPOSIT_WALLET_ADDRESS> 100000000 \
  --private-key $PRIVATE_KEY \
  --rpc-url $RPC_URL
```

Depositing to the perps DEX:

```shell theme={null}
# Deposit 100 USDC to the perps DEX (destinationDex = 0)
cast send <CORE_DEPOSIT_WALLET_ADDRESS> "deposit(uint256,uint32)" 100000000 0 \
  --private-key $PRIVATE_KEY \
  --rpc-url $RPC_URL
```

Depositing to the spot DEX:

```shell theme={null}
# Deposit 100 USDC to the spot DEX (destinationDex = uint32.max)
cast send <CORE_DEPOSIT_WALLET_ADDRESS> "deposit(uint256,uint32)" 100000000 4294967295 \
  --private-key $PRIVATE_KEY \
  --rpc-url $RPC_URL
```

<Note>
  **Note:** If the destination DEX value is not supported (spot or perps), the
  deposit is credited to the sender's spot balance.
</Note>

### `depositFor` function

The `depositFor` function transfers USDC from the caller but credits a specified
recipient address on HyperCore. This allows deposits on behalf of another user.

**Signature:**

```solidity theme={null}
depositFor(address recipient, uint256 amount, uint32 destinationId);
```

**Parameters:**

| Parameter       | Value                                                                                                                           |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `recipient`     | The recipient address on HyperCore                                                                                              |
| `amount`        | The USDC amount being deposited from HyperEVM to HyperCore                                                                      |
| `destinationId` | The HyperCore destination `dex` index. Accepted values are:<br />- `0` → default perps DEX<br />- `type(uint32).max` → spot DEX |

**Token pull:** Uses `transferFrom(msg.sender, address(this), amount)` →
requires prior ERC-20 approve from the `msg.sender` to the core deposit wallet.

**Who is credited:** The recipient address passed to the function is credited on
HyperCore.

**Examples:**

ERC-20 Approval:

```shell theme={null}
# approve the CoreDepositWallet to spend 100 USDC from the sender
cast send <USDC_ADDRESS> "approve(address,uint256)" <CORE_DEPOSIT_WALLET_ADDRESS> 100000000 \
  --private-key $PRIVATE_KEY \
  --rpc-url $RPC_URL
```

Depositing to the perps DEX:

```shell theme={null}
# Deposit 100 USDC to the perps DEX (destinationDex = 0)
cast send <CORE_DEPOSIT_WALLET_ADDRESS> "depositFor(address,uint256,uint32)" <RECIPIENT_ADDRESS> 100000000 0 \
  --private-key $PRIVATE_KEY \
  --rpc-url $RPC_URL
```

Depositing to the spot DEX:

```shell theme={null}
# Deposit 100 USDC to the spot DEX (destinationDex = uint32.max)
cast send <CORE_DEPOSIT_WALLET_ADDRESS> "depositFor(address,uint256,uint32)" <RECIPIENT_ADDRESS> 100000000 4294967295 \
  --private-key $PRIVATE_KEY \
  --rpc-url $RPC_URL
```

<Note>
  **Note:** If the destination DEX value is not supported (spot or perps), the
  deposit is credited to the recipient's spot balance.
</Note>

### `depositWithAuth` function

The `depositWithAuth` function allows depositing USDC using a pre-signed
ERC-3009 authorization. This enables a deposit where the token transfer is
authorized offchain and executed onchain without requiring a prior approve call.

**Signature:**

```solidity theme={null}
depositWithAuth(uint256 amount, uint256 authValidAfter, uint256 authValidBefore, bytes32 authNonce, uint8 v, bytes32 r, bytes32 s, uint32 destinationDex);
```

**Parameters:**

* `amount`: The USDC amount being deposited from HyperEVM to HyperCore
* `authValidAfter`, `authValidBefore`, `authNonce`, `v`, `r`, `s`:
  EIP-3009-style authorization fields for `receiveWithAuthorization`
* `destinationDex`: The HyperCore destination `dex` index. Accepted values are:
  * `0` → default perps DEX
  * `type(uint32).max` → spot DEX

**Token pull:** Calls `token.receiveWithAuthorization(...)`, no prior approve
needed.

**Who is credited:** The `msg.sender` which has to match the `from` address from
the `receiveWithAuthorization` is credited on HyperCore.

**receiveWithAuthorization details:**

* **ERC:** ERC-3009
* **Function Signature:** `ReceiveWithAuthorization`
* **Parameters:**

| Parameter     | Value                                                                                              |
| ------------- | -------------------------------------------------------------------------------------------------- |
| `from`        | The payer's address (`authorizer`) has to match the `msg.sender` of the `depositWithAuth` function |
| `to`          | The `CoreDepositWallet` address (payee)                                                            |
| `value`       | The auth amount                                                                                    |
| `validAfter`  | The time after which this is valid (Unix time)                                                     |
| `validBefore` | The time before which this is valid (Unix time)                                                    |
| `nonce`       | Unique nonce                                                                                       |
| `v`           | v of the signature                                                                                 |
| `r`           | r of the signature                                                                                 |
| `s`           | s of the signature                                                                                 |

**Example:**

The example below illustrates how to generate an ERC-3009 authorization:

```javascript theme={null}
#!/usr/bin/env node

const ethers = require("ethers");
const PRIVATE_KEY = process.env.PRIVATE_KEY;
const wallet = new ethers.Wallet(PRIVATE_KEY);
const provider = new ethers.JsonRpcProvider(
  process.env.RPC_URL || "https://rpc.hyperliquid-testnet.xyz/evm",
);

const usdcAddress = "<USDC_CONTRACT_ADDRESS>";
const coreDepositWallet = "<CORE_DEPOSIT_WALLET_ADDRESS>";

const EIP712_PREFIX = "0x1901";

const amount = ethers.parseUnits("100", 6); // 100 USDC
const nonce = ethers.hexlify(ethers.randomBytes(32));
const validAfter = 0;
const validBefore = Math.floor(Date.now() / 1000) + 3600; // valid for 1 hour

// Minimal ABI for DOMAIN_SEPARATOR
const USDC_ABI = [
  {
    inputs: [],
    name: "DOMAIN_SEPARATOR",
    outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }],
    stateMutability: "view",
    type: "function",
  },
];

async function getDomainSeparator(usdc) {
  try {
    return await usdc.DOMAIN_SEPARATOR();
  } catch {
    const domain = {
      name: "USD Coin",
      version: "2",
      chainId: await provider.getNetwork().then((n) => n.chainId),
      verifyingContract: await usdc.getAddress(),
    };
    return ethers.TypedDataEncoder.hashDomain(domain);
  }
}

async function main() {
  const usdc = new ethers.Contract(usdcAddress, USDC_ABI, provider);
  const domainSeparator = await getDomainSeparator(usdc);

  const structHash = ethers.keccak256(
    ethers.AbiCoder.defaultAbiCoder().encode(
      [
        "bytes32",
        "address",
        "address",
        "uint256",
        "uint256",
        "uint256",
        "bytes32",
      ],
      [
        ethers.keccak256(
          ethers.toUtf8Bytes(
            "ReceiveWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)",
          ),
        ),
        wallet.address,
        coreDepositWallet,
        amount,
        validAfter,
        validBefore,
        nonce,
      ],
    ),
  );

  const digest = ethers.keccak256(
    ethers.concat([EIP712_PREFIX, domainSeparator, structHash]),
  );
  const signer = new ethers.SigningKey(PRIVATE_KEY);
  const sig = signer.sign(digest);

  console.log("Authorization parameters:");
  console.log({
    amount: amount.toString(),
    validAfter,
    validBefore,
    nonce,
    v: sig.v,
    r: sig.r,
    s: sig.s,
  });
}

main().catch(console.error);
```

The example below illustrates how to call the `depositWithAuth` function with
the authorization data:

```shell theme={null}
cast send <CORE_DEPOSIT_WALLET_ADDRESS> \
  "depositWithAuth(uint256,uint256,uint256,bytes32,uint8,bytes32,bytes32,uint32)" \
  <AMOUNT> 0 1735660000 0x<NONCE> <V> 0x<R> 0x<S> <DEST_DEX_ID> \
  --private-key $PRIVATE_KEY \
  --rpc-url $RPC_URL
```

<Note>
  **Note:** If the destination DEX value is not supported (spot or `perp`), the
  deposit is credited to the `authorizer's` spot balance.
</Note>
