Skip to content

Wallet Routing And Funds Recovery

Purpose

Use this guide when Polymarket funds or positions appear on the wrong wallet, a Deposit Wallet or Safe route looks inconsistent, or a deposit did not arrive where you expected. Start with the simple recovery commands, then use the advanced diagnostics only when the CLI or support asks for them.

This guide helps you collect evidence and choose the next safe command. It does not prove that an affected account has been recovered.

Key Terms

These terms appear throughout this guide.

  • Owner EOA — one of your Bullpen-managed signing keys (an Ethereum 0x… address). An account can have more than one. The owner EOA signs transactions, but it is usually not where your Polymarket funds live.
  • Server-selected wallet — for each owner EOA, the Bullpen server chooses which Polymarket contract wallet (Deposit Wallet, Safe, or Proxy) is the active trading wallet. The CLI follows that choice; you do not pick it by hand during normal trading.
  • Split-brain / stranded assets — funds or positions sitting on a Polymarket wallet that is not the server-selected one. They are not lost, but the active trading flow cannot use them until they are consolidated.
  • Deposit Wallet derivation — the proof path used to compute the expected Deposit Wallet address. JSON may show beacon_proxy, legacy_uups, or legacy_uups_fallback_rpc_unavailable. Treat fallback provenance as degraded evidence and retry diagnostics when Polygon RPC is healthy before using it for a support decision.
  • Legacy pre-beacon Deposit Wallet — an address derived by Polymarket's older Deposit Wallet factory before the June 2026 beacon migration. If funds landed there after the migration, the funds are safe on-chain, but the address may need Polymarket/Bullpen recovery before it can be used for trading.

Start Here: Symptom → Command

Match your symptom, run the first command, then follow the linked section below. Preview and support commands are read-only; live recovery commands still require explicit confirmation.

Symptom Run this first Then
"My Polymarket balance shows $0 but I deposited" bullpen recover polymarket Recovery plan shown → Preview Recovery Workflows. No plan or support-required state → bullpen support.
"My deposit never arrived" bullpen funds diagnose-deposit --tx <TX_HASH> --chain <CHAIN> --token <TOKEN> --address <RECIPIENT_ADDRESS> --output json Wrong chain / wrong token / exchange address → attach the JSON to support.
"Funds are on the wrong wallet" bullpen recover polymarket Stranded assets reported → Preview Recovery Workflows.
"I moved funds to my Safe and can't trade them" bullpen recover funds --dry-run --output json Execute only when the preview says resolution_owner: "user" and shows the exact assets it will move.
"I can't trade / maker address not allowed" bullpen support Attach the generated artifact to support. Do not switch wallet kind unless support, or a CLI repair verdict, gives the exact kind.
"I can't redeem / STATE_FAILED" bullpen recover redeem --dry-run --output json Capture the dry-run JSON; see Trading → Redeem.
"L2_WALLET_DISAGREEMENT / exit code 13" bullpen support Do not force a wallet kind, relogin repeatedly, or retry money movement. Attach the generated support artifact to support.
"PM_LEGACY_DEPOSIT_WALLET_PENDING_RECOVERY" bullpen support Funds are safe on-chain at a legacy pre-beacon Deposit Wallet. Do not repeatedly retry approve, activate, or trading for that wallet.
"Cache, server, and on-chain disagree" bullpen doctor wallet --output json Attach the JSON to support.

You are done when bullpen fix --refresh reports no blocking action and your original command (trade, redeem, or withdraw) succeeds.

Self-Serve Versus Escalate

  • Self-serve: a clean "assets on a non-selected wallet" result is normal only when the preview says resolution_owner: "user" and lists a concrete action. Preview with bullpen recover funds --dry-run --output json, then execute only if the JSON plan is correct. See Preview Recovery Workflows.
  • Escalate to support: wrong-chain or wrong-token deposits, exchange/imported wallet destinations, L2_WALLET_DISAGREEMENT (exit code 13), maker-address CLOB rejections on the server-selected wallet, PM_LEGACY_DEPOSIT_WALLET_PENDING_RECOVERY, and cache/server/on-chain disagreements are not self-serve. support_required, diagnostic_required, or diagnostic_incomplete JSON states also stop at support. Run bullpen support first and contact support; do not force a wallet kind to "fix" them.

Before You Start

  • Run diagnostics from the same Bullpen account, machine, and environment that saw the issue.
  • Do not delete ~/.bullpen, export private keys, bridge manually, or force a wallet kind as the first recovery step.
  • Do not share private keys, seed phrases, JWTs, API tokens, full config files, or unredacted logs with support.
  • Treat --non-interactive and --yes as separate controls. Non-interactive mode does not approve money-moving commands.

Safe First Commands

For most recovery questions, run:

bullpen recover polymarket

For backend-owned wallet-selection or maker-address failures, run:

bullpen support

Use the advanced wallet audit only when the recovery output or support asks for wallet evidence. It is read-only and support-safe by default.

bullpen polymarket wallet-audit --refresh --output json

The split-brain pattern to look for is an asset balance on a wallet whose is_server_selected is false. Addresses and amounts below are redacted and illustrative; your exact fields will differ.

Example output — stranded assets on a non-selected wallet
{
  "schema_version": 1,
  "owners": [
    {
      "owner_eoa": "0xOWNER…1234",
      "server_selected": { "kind": "deposit_wallet", "address": "0xDEP…aaaa" },
      "wallets": [
        {
          "kind": "deposit_wallet",
          "address": "0xDEP…aaaa",
          "status": "active",
          "is_server_selected": true,
          "pusd": "0.00",
          "usdce": "0.00",
          "positions": 0
        },
        {
          "kind": "safe",
          "address": "0xSAFE…bbbb",
          "status": "inactive_legacy",
          "is_server_selected": false,
          "pusd": "42.10",
          "usdce": "0.00",
          "positions": 1,
          "stranded": true
        }
      ]
    }
  ],
  "summary": { "stranded_assets_found": true }
}

The audit enumerates owner EOAs, checks server-selected Polymarket routing, and probes Safe, Proxy, Deposit Wallet, and signer-EOA state without submitting a transaction. See the generated wallet-audit reference for the full flag list, including --owner and --include-order-credit.

If the audit reports PM_LEGACY_DEPOSIT_WALLET_PENDING_RECOVERY, the CLI found funds at a legacy pre-beacon Deposit Wallet address that is not the current server-selected Deposit Wallet derivation. This is not a normal stranded-assets case and it is not fixed by approve, activate, reregister-deposit-wallet, or repeated login. The funds are safe on-chain. Capture the support artifact and wait for Polymarket/Bullpen recovery status.

If the report is about a missing or wrong-chain deposit, run the deposit diagnostic next. It is read-only and does not attempt recovery.

bullpen funds diagnose-deposit --tx <TX_HASH> --chain <CHAIN> --token <TOKEN> --address <RECIPIENT_ADDRESS> --output json

Use the generated funds diagnose-deposit reference for accepted chain and token values. If you only know the recipient, the reference also documents the address-only diagnostic shape.

Read The Result

Use the JSON output as evidence, not as permission to run a repair command.

Result class Next safe action
Wallet route is consistent and no stranded assets are reported Continue with the original failed command's preview or diagnostic path.
Assets or positions appear on a non-selected Polymarket wallet Preview consolidation before any execution.
PM_LEGACY_DEPOSIT_WALLET_PENDING_RECOVERY appears Do not retry money movement. Attach status, doctor wallet, and wallet-audit JSON to support and wait for recovery status.
Deposit was sent to an unsupported chain, unsupported token, exchange address, imported wallet, signer EOA, or bot Safe Attach diagnose-deposit JSON and wallet-audit JSON to support.
Local wallet cache, server registry, or on-chain bytecode disagree Run the broader wallet diagnostic and attach JSON output to support.

Run the broader wallet diagnostic when the issue is account inventory or cache disagreement rather than stranded Polymarket assets.

bullpen doctor wallet --output json

A healthy result reports status: "ok". A status: "disagreement" (or a residual/inconclusive variant) means the local cache, the server registry, and on-chain bytecode do not agree for at least one owner EOA — escalate with the JSON attached. The safety block confirms the command performed no writes.

Example output — wallet disagreement (illustrative, redacted)
{
  "schema_version": 2,
  "status": "disagreement",
  "total_owners": 1,
  "entries": [
    {
      "owner_eoa": "0xOWNER…1234",
      "cache_kind": "legacy_safe",
      "server_kind": "safe",
      "onchain_deposit_wallet_deployed": true,
      "disagreement": "server_safe_but_dw_funded",
      "hint": "Deposit Wallet is funded on-chain but server selects the Safe. Attach this JSON to support; do not force a wallet kind."
    }
  ],
  "safety": {
    "signer_creation": false,
    "token_refresh": false,
    "wallet_cache_mutation": false
  }
}

See the generated doctor wallet reference.

Check Off-Chain Order Credit

Default wallet-audit and consolidation dry-runs skip signer-backed CLOB credit authentication for each wallet row. If funds still look missing after the read-only audit, or if consolidate --dry-run --output json reports non_closable_status values such as clob_credit_probe_skipped or clob_credit_probe_incomplete, run the explicit credit probe before choosing an asset-movement command.

bullpen polymarket wallet-audit --refresh --include-order-credit --output json

Label: read-only, support-gated. Inspect summary.clob_credit_checked, summary.clob_credit_status, and each wallet row's clob_credit_status. Off-chain order credit cannot be moved on-chain; when credit exists on a non-server-selected wallet, support may route the case through a web-app withdrawal or backend review instead of consolidate.

Preview Recovery Workflows

Preview consolidation when wallet-audit reports assets or positions on a non-selected Polymarket wallet.

bullpen polymarket consolidate --dry-run --output json

Label: preview. The dry-run prints a plan without executing it. Review the plan and generated consolidate reference before running any write command.

Example output — consolidation dry-run plan (illustrative, redacted)
{
  "dry_run": true,
  "destination": { "kind": "deposit_wallet", "address": "0xDEP…aaaa" },
  "steps": [
    { "action": "cancel_open_orders", "wallet": "0xSAFE…bbbb", "count": 0 },
    { "action": "transfer_positions", "wallet": "0xSAFE…bbbb", "positions": 1 },
    { "action": "sweep_balance", "token": "pUSD", "from": "0xSAFE…bbbb", "amount": "42.10" }
  ],
  "non_closable": [],
  "non_closable_status": null
}

If support asks you to inspect only one owner EOA, use the generated reference for the exact --owner form. Do not force --wallet-kind unless support explicitly directs it.

Mutating Commands

The commands in this section can submit transactions, change account metadata, or move funds. Run them only after diagnostics and plan review.

Execute consolidation only after the dry-run routes assets to the intended server-selected wallet.

bullpen polymarket consolidate --yes

Label: write, support-gated, fixture-gated. This can cancel orders, transfer positions, and sweep balances according to the plan. A successful command on one fixture or account does not prove another affected account is recovered.

Sweep stranded ERC-20 funds only when diagnostics and support identify a supported Polygon ERC-20 balance held by a Bullpen-owned Safe, Proxy, or Deposit Wallet.

bullpen polymarket sweep-stranded --token <TOKEN> --amount <AMOUNT>

Label: destructive, support-gated, fixture-gated. This is a one-way relayer transfer. Review the generated sweep-stranded reference before confirming, especially recipient rules and the --unsafe-recipient boundary.

Deploy or re-register a Deposit Wallet only when diagnostics show that the server-selected route is Deposit Wallet and the generated command output says that action is appropriate.

bullpen polymarket deploy-deposit-wallet
bullpen polymarket reregister-deposit-wallet
bullpen polymarket reregister-deposit-wallet --force-relayer-refresh --yes --output json

Label: write, support-gated. These commands do not override normal wallet routing. Use --force-relayer-refresh only when Polymarket returns POLYMARKET_RELAYER_WALLET_NOT_REGISTERED or "wallet registry validation failed" even though Bullpen already reports the Deposit Wallet as deployed. Do not use this command for PM_LEGACY_DEPOSIT_WALLET_PENDING_RECOVERY; that state means funds are at a legacy pre-beacon address pending recovery, not that the current Deposit Wallet merely needs a relayer refresh. If the forced refresh does not return status: registered, Bullpen support must repair the relayer registry row. See the generated deploy-deposit-wallet reference and reregister-deposit-wallet reference.

Select a Bullpen owner EOA only when you intend to change the primary owner wallet for a chain.

bullpen wallet select --chain evm <OWNER_EOA>

Label: write. This selects an owner EOA; it does not directly choose the server-selected Polymarket contract wallet. See the generated wallet select reference.

Support Capture

Create one redacted support artifact:

bullpen support

The command collects the CLI version, session health, selected-wallet evidence, and a support-safe summary without exposing credentials. Include the failed command's short error message in the ticket. Run individual JSON diagnostics only when support asks for a specific follow-up.

Do not attach secrets or full unredacted logs.

See Also