Skip to main content
Withdrawals move USDC out of the user’s on-chain vault to an external destination. Every withdrawal is:
  1. EIP-712 signed by the user against the vault’s WithdrawERC20 typed-data struct.
  2. Compliance-screened (banned list, account restrictions, AML screening of your wallet and the destination, amount). A banned or AML-blocked destination, or a restriction that blocks withdrawals, is refused on the spot: the response carries status: "rejected" with a code (wallet_banned, aml_blocked, restriction_active) and no withdrawal is created. Other flags, and amounts above the auto-approve threshold, put the withdrawal in MLRO_REVIEW for human compliance review. See what sends a withdrawal to review.
  3. Backend co-signed with a second EIP-712 signature. Dual signatures are both required on-chain; neither party can move funds alone.
  4. Submitted on-chain by PredictStreet’s backend submitter (PredictStreet pays gas).
  5. Confirmed when the on-chain tx receipt is observed.

State machine

See State machine detail.

Withdrawal security

Two opt-in, per-wallet controls gate a withdrawal request before it enters the flow above (enforced when the platform enables withdrawal-security; SSO partners are exempt):
  • Address whitelist — once a wallet has any whitelisted address, withdrawals are allowed only to listed destinations (403 withdrawal_address_not_whitelisted otherwise). No entries = unrestricted.
  • 2FA (TOTP) — once active, every withdrawal must carry a totpCode (403 totp_required / totp_invalid otherwise). Manage both under /api/me/withdrawal-security/*.
The two are independent and stack. The existing AML / sanctions screen and high-value review run regardless.

Typical timeline

  • Happy path (no flag): under 10s from request to CONFIRMED on testnet; target < 60s on mainnet.
  • MLRO review path: a compliance decision, typically within 1 business day. If your signed deadline passes before the withdrawal executes, it ends EXPIRED and the amount is refunded.

User-visible balance effects

Partner & MM notes

Market makers running high withdrawal cadence should:
  • Withdrawals are not restricted to addresses that deposited before (see Deposit sources). To lock withdrawals to known destinations, use the address whitelist.
  • Poll GET /api/me/withdrawals/{id} for state transitions, or subscribe to user_activity on /ws/user (portfolio:read, no ids), which pushes a withdrawal_<state> frame (for example withdrawal_requested, withdrawal_approved, withdrawal_flagged_for_review, withdrawal_submitted, withdrawal_rejected, withdrawal_cancelled) as the request moves through review and submission. The on-chain success is not a user_activity frame: it arrives as withdrawal_confirmed on vault_activity (ids: [<your vault address>]).

Next

Dual-sig flow

Why two signatures, how the co-sign works.

EIP-712 struct

WithdrawERC20 struct + signing.

State machine

All states + transitions.

Deposit sources

Read-only list of the addresses that funded your vault.

Withdrawal 2FA

TOTP second factor on withdrawals.

Address whitelist

Restrict withdrawals to approved destinations.