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, orlegacy_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 withbullpen 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, ordiagnostic_incompleteJSON states also stop at support. Runbullpen supportfirst 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-interactiveand--yesas separate controls. Non-interactive mode does not approve money-moving commands.
Safe First Commands¶
For most recovery questions, run:
For backend-owned wallet-selection or maker-address failures, run:
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.
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.
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.
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.
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.
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.
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.
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:
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.