Skip to main content
Status: live. Every vault is deployed by the platform’s back-office wallet. Partners do not call deployVault themselves — the backend deploys the vault as soon as the wallet has a platform account (single_wallet, or multi_wallet with requirePerWalletKyc=true) or on first-request auto-onboarding (multi_wallet with requirePerWalletKyc=false), without waiting for KYC. Poll GET /api/me/vault until the vault address resolves.

What triggers it

There are two trigger paths, picked automatically based on the partner record:
  1. Account creation — single_wallet partners, and multi_wallet partners with requirePerWalletKyc=true. A deploy job is enqueued on the wallet’s first sign-in and again when its KYC is approved, and a catch-up job enqueues one every minute for any account that still has no vault (closed or blocked accounts are skipped). Vault deploy is not gated on KYC — KYC gates deposits and trading. See Partner kinds for the per-flag enforcement matrix.
  2. First request auto-onboarding — multi_wallet partners with requirePerWalletKyc=false (KYB-onboarded prime brokerage model). The first authenticated request from the partner key that names a previously-unseen sub-account in X-User-Wallet creates the sub-account and enqueues an auto-deploy job right then — without retail KYC for the sub-account.
Either way, the on-chain VaultFactory.deployVault call comes from the back-office submitter, gas is paid by the platform, and the result is identical: a fully-initialised Vault contract owned by your EOA. Deposit limits are set separately — see Limits initialisation.

Sequence

Typical end-to-end timing on testnet: under 15 seconds from trigger to deployed=true. Mainnet target is similar; expect spikes during periods of high block latency.

Reading deployment status

deployStatus values

On /ws/user, the user_activity channel pushes vault_created when the vault is deployed; otherwise poll GET /api/me/vault until deployed: true.

What stays the same

  • The on-chain artefact is identical to a manually-deployed vault — same Vault bytecode, same ABI, same vaultOf(eoa) lookup. The vault address is assigned at deploy time and cannot be computed from your EOA; always read it from vaultOf(eoa) or GET /api/me/vault.
  • Vault ownership stays with your associated EOA. The back-office wallet pays gas to deploy but never holds keys to the vault.
  • Emergency withdraw, dual-signature withdrawal, splits, merges, and redeems — all unchanged. Auto-deploy only saves the on-chain bootstrap, not custody.
  • Order.maker is your vault address; Order.signer is your EOA — the EIP-712 domain and signature flow are identical to manual deploy.

What stays your responsibility

  • Authorising each deposit. Auto-deploy stops at the vault contract; only the EOA that holds the USDC can move it in — either approve + depositERC20 sent from the EOA (you pay gas), or an EIP-2612 USDC.permit signed by the EOA and submitted to POST /api/deposits/relay (the platform broadcasts it: no gas, no approve). The platform cannot bypass that. See Deposits overview.
  • Custody of the EOA private key — never reaches our infrastructure.
  • Gas for any vault transaction you broadcast yourself (for example a split / merge / convert you send to the vault directly). Withdrawals are broadcast by the platform, and co-signed split / merge / convert ops can be relayed without gas via POST /api/me/positions/op-submit.

Limits initialisation

Per-EOA deposit caps in DepositLimitRegistry (per-deposit, rolling 30-day, rolling 12-month) are set by separate platform transactions driven by the wallet’s KYC level — or, for partner-backed sub-accounts (multi_wallet with requirePerWalletKyc=false), at the VIP tier on the first request. Vault deploy does not set them.
The two lifecycles are independent. /api/me/vault flipping to deployed: true does not mean the wallet can deposit. Until the wallet’s tier is set in the registry, vault.depositERC20(...) reverts with KycRequired() (selector 0x709ea86e).Bootstrap clients should poll /api/me/deposit-limits until tier is non-zero and restrictions.depositBlocked is false (not just /api/me/vault.deployed) before attempting the on-chain deposit. See Deposit limits for the cap shape and how usage windows roll.

Verifying

What if auto-deploy does not fire

For a partner-issued API key, auto-deploy is the only path — operations issues orders:write / vault:write keys only after the prerequisite KYC (or partner-level KYB) lands, so by the time your code runs the trigger is already in flight. If GET /api/me/vault keeps returning deployed: false with deployStatus: 'not_started' for more than a couple of minutes, the most common causes are:
  • The wallet has no platform account yet — it has never signed in, or (multi_wallet with requirePerWalletKyc=false) no authenticated request has named it in X-User-Wallet.
  • The account is closed or blocked — the catch-up job skips such accounts. Call your integration manager.
If deployStatus keeps returning to failed_permanent, every deploy attempt is failing — contact support. VaultFactory.deployVault(eoa) is permissionless: any address can call it, and the vault’s owner is always eoa no matter who pays gas. So in a true emergency a partner can deploy the vault themselves and pay gas — but operations should be the first call. The call is not idempotent: check VaultFactory.vaultOf(eoa) first, because it reverts with VaultAlreadyExists(eoa) (selector 0x4293864f) if a vault is already registered, including one the platform auto-deploy created a moment earlier. The contract reference at Vault contracts → VaultFactory documents the function signature.