> ## Documentation Index
> Fetch the complete documentation index at: https://docs.adipredictstreet.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Deposits overview

> How USDC moves from your associated EOA into your on-chain vault, and how long the platform takes to credit available balance.

A **deposit** moves USDC from your associated EOA into your on-chain
vault, where it becomes spendable as `available` balance and is
required collateral for placing BUY orders. It is always a
**user-initiated on-chain transaction** — neither the platform nor a
partner API key can pull funds out of an EOA without the owner's
authorisation.

## Prerequisites

| Requirement                 | How to satisfy                                                                                                                               |
| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| Vault deployed for your EOA | Auto-deployed by the platform — see [Backend auto-deploy](/concepts/vaults/auto-deploy). Verify with `GET /api/me/vault` (`deployed: true`). |
| USDC in the EOA             | Buy / bridge on-chain per your partner runbook.                                                                                              |
| ERC-20 allowance            | Your EOA must have called `USDC.approve(vault, X)` for at least `X = depositAmount`. `MaxUint256` is the standard one-time pattern.          |
| Within deposit limits       | The platform pre-initialises per-EOA daily / weekly / monthly caps — see [Deposit limits](/concepts/deposits/limits).                        |

## End-to-end flow

```mermaid theme={null}
sequenceDiagram
    participant E as EOA
    participant V as Vault contract
    participant USDC as USDC ERC-20
    participant CORE as core-api

    E->>USDC: approve(vault, MaxUint256)        (one-time)
    Note over E: skip if already approved
    E->>V: depositERC20(USDC, amount)
    V->>USDC: transferFrom(eoa → vault, amount)
    V-->>V: ledger += amount; cap-check passes
    V-->>CORE: DepositedERC20 event indexed
    Note over CORE: ~1 block lag
    CORE-->>E: GET /api/me/balances → available += amount
```

## Step 1 — `approve` (once per vault)

```typescript theme={null}
import { Contract, MaxUint256 } from 'ethers';

const usdc = new Contract(
  '0x9cb8142aEBBcdc60AF7c97Af897A67A8f3CA71C2',
  ['function approve(address,uint256) returns (bool)'],
  eoa,
);

await (await usdc.approve(vault, MaxUint256, { gasLimit: 100_000n })).wait();
```

`MaxUint256` saves gas on every future deposit. Tighten to a per-deposit
allowance if your security model requires it — the trade-off is one
extra `approve` per deposit.

## Step 2 — `depositERC20`

```typescript theme={null}
import { Contract, parseUnits } from 'ethers';

const v = new Contract(
  vault,
  ['function depositERC20(address token, uint256 amount)'],
  eoa,
);

await (await v.depositERC20(
  '0x9cb8142aEBBcdc60AF7c97Af897A67A8f3CA71C2',
  parseUnits('500', 6),                          // 500 USDC (6 decimals)
  { gasLimit: 600_000n },
)).wait();
```

Inside the tx the vault calls `transferFrom(eoa → vault)`, increments
its internal collateral ledger by `amount`, and checks the deposit-cap
windows in `DepositLimitRegistry` before settling. If the cap would be
exceeded, the tx reverts with `DepositCapExceeded()` — see
[Deposit limits](/concepts/deposits/limits).

## Step 3 — wait for the platform to credit

After the deposit tx mines, the platform indexes the on-chain event
and credits `exchange.balances.available` for your associated EOA.
End-to-end latency from mined tx to credited balance is typically
**well under 1 second** in production (chain-watcher streams events
sub-second) and **a few seconds** on mainnet (indexer batches
confirmations into the ledger). Plan UI for the mainnet ceiling — the
production path is faster than partners typically expect, so build for
the slower target and treat the production behaviour as the optimistic
case.

Two ways to observe it:

<CodeGroup>
  ```typescript Polling theme={null}
  async function waitForDeposit(amountUsdc: string, timeoutMs = 30_000) {
    const start = Date.now();
    while (Date.now() - start < timeoutMs) {
      const r = await fetch(`${BASE}/api/me/balances`, {
        headers: { 'X-Api-Key': process.env.PS_API_KEY! },
      });
      const balances = await r.json();
      const usdc = balances.find((b: any) => b.token === 'USDC');
      if (usdc && Number(usdc.available) >= Number(amountUsdc)) return usdc;
      await new Promise(r => setTimeout(r, 1000));
    }
    throw new Error('deposit not credited within timeout');
  }
  ```

  ```text Polling fallback theme={null}
  // Deposit confirmation isn't currently surfaced on the typed WS
  // channels — poll GET /api/me/balances until `available` reflects
  // the deposited amount, or watch `vault_positions` for the inflow
  // `vault_position_balance_changed` event keyed to your vault.
  ```
</CodeGroup>

## Idempotency and replays

Deposits are uniquely keyed by their on-chain `(txHash, logIndex)`.
If you receive the same `vault.deposit_confirmed` event twice (network
retry, WS reconnect with replay), the platform credits the deposit
exactly once — replays are cheap no-ops. Safe to handle naively.

## Withdrawing later

Funds in the vault stay liquid — withdraw any time via the dual-signed
flow documented in [Withdrawals overview](/concepts/withdrawals/overview).
The vault also exposes a 7-day-timelocked emergency withdraw for
recovery if the platform is unavailable; see [Vault contract
reference](/concepts/contracts/vaults).

## Common failures

| Symptom                                                                | Cause                                                                                                                                                                              | Fix                                                                                                    |
| ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `ERC20InsufficientAllowance`                                           | Step 1 skipped or insufficient cap                                                                                                                                                 | Run `usdc.approve(vault, MaxUint256)` first                                                            |
| Revert with selector `0x87138d5c`                                      | `NotInitialized()` — DepositLimitRegistry init lags vault deploy (separate platform job; observed lag 30 s – 4 min). Gating on `GET /api/me/vault.deployed` alone is insufficient. | Poll `GET /api/me/deposit-limits` until `initialized: true` *before* calling `depositERC20`.           |
| Revert with `DepositCapExceeded`                                       | The deposit would exceed your daily / weekly / monthly cap                                                                                                                         | See [Deposit limits](/concepts/deposits/limits) — wait for the rolling window or request a higher tier |
| Tx mined but `available` still 0 in `/api/me/balances` after >1 minute | Indexer lag or transient incident                                                                                                                                                  | Check [status page](https://status.predictstreet.com); if persistent, contact support with `txHash`    |

## Next

<CardGroup cols={2}>
  <Card title="Deposit limits" icon="gauge" href="/concepts/deposits/limits">
    Daily / weekly / monthly caps and how rolling windows are applied.
  </Card>

  <Card title="Withdrawals overview" icon="arrow-up-from-bracket" href="/concepts/withdrawals/overview">
    Dual-signature flow, AML review, state machine.
  </Card>

  <Card title="Place your first order" icon="plus" href="/concepts/trading/placing-orders">
    Sign + POST a vault-backed order against any open market.
  </Card>

  <Card title="Vault contract reference" icon="file-code" href="/concepts/contracts/vaults">
    Full ABI for the vault, including the deposit entry point.
  </Card>
</CardGroup>
