PreFundedEscrow smart contract. Your wallet retains beneficial ownership; PMXT operates the contract and submits orders to the venue on your behalf. This page walks through the full lifecycle: approve, deposit, trade, withdraw.
The escrow contract lives on Polygon for Polymarket trades and on BSC for Opinion’s cross-chain settlement.
Why escrow at all?
Polymarket’s CLOB exchange expects the submitter to be the operator of the user’s CLOB proxy wallet. That proxy is created by Polymarket’s USDC.e adapter and is non-trivial to operate from a third-party context. PMXT’sPreFundedEscrow solves this by acting as a pre-funded operator: the user deposits USDC once, PMXT routes orders against that balance, and the user can withdraw at any time. The user signs every order with EIP-712; the escrow contract can only spend USDC against signed orders, never unilaterally.
For Opinion, the escrow plays a different role — it’s the on-chain settlement leg of a dual-signature cross-chain flow. Same custody story, different mechanics.
The client.escrow namespace
Hosted exchange clients (Polymarket, Opinion) expose an escrow namespace. Every method builds an unsigned transaction. Your wallet — MetaMask, ethers Wallet, viem, web3.py, etc. — is responsible for signing and broadcasting it. PMXT never holds your private key.
| Method (Python / TypeScript) | Description |
|---|---|
escrow.approve_tx(token, amount_wei=None) / escrow.approveTx(token, amountWei?) | Build an unsigned ERC-20 approval for USDC or CTF. |
escrow.deposit_tx(amount) / escrow.depositTx(amount) | Build an unsigned USDC deposit into PreFundedEscrow. |
escrow.withdraw_tx(action, amount=None) / escrow.withdrawTx(action, amount?) | Build an unsigned request / claim / cancel withdrawal. |
escrow.withdrawals(include="pending,events") / escrow.withdrawals({ include }) | Read pending withdrawal state and historical events. |
sdks/python/pmxt/escrow.py and sdks/typescript/pmxt/escrow.ts.
1. Approve
Before the first deposit, the escrow contract needs permission to pull USDC (and, for some flows, the Polymarket CTF token) from your wallet. This is a standard ERC-20 approval.Approval is one-time per token + spender. If you ever rotate the escrow contract (rare, gated on a PMXT migration announcement), you’ll need to re-approve.
2. Deposit
Once approval is in place, deposit USDC. Amounts are in whole USDC (6 decimals); the SDK validates precision and rejects values like0.0000001.
3. Confirm the deposit
After the deposit transaction confirms on-chain, the balance shows up in escrow.fetch_balance is the canonical check.
On-chain confirmation usually takes 2–5 seconds on Polygon. If
fetch_balance still reads zero 30 seconds after broadcast, check the tx on Polygonscan — a failed deposit (e.g. due to missing approval) will not update escrow state.4. Trade
With escrow funded, you can trade.create_order and submit_order debit the escrow balance; cancel_order releases the reservation. No additional escrow calls are needed during normal trading — the balance just gets spent.
5. Withdraw
Withdrawals are a two-step timelock. You firstrequest a withdrawal; after a contract-enforced delay (~1 hour in production), you claim it. You can also cancel a pending request.
The timelock is a security feature — it gives the user a window to detect and abort an unauthorized withdrawal even if the operator key were compromised.
Request
Inspect pending withdrawals
Claim
Onceclaimable_at has passed, claim the funds — they move from escrow to your wallet.
claim does not take an amount. It claims all matured requests at once. The escrow tracks individual request maturities; only matured ones settle.Cancel
If you change your mind during the timelock window, cancel a pending request and the funds remain in escrow as free balance.Errors you might hit
MissingWalletAddress—client.escrow.*requireswallet_addresson the exchange constructor. Pass it explicitly.ValidationError: amount precision exceeds 6 decimals— round before passing.InsufficientEscrowBalance(during a trade) — deposit more before retrying, or wait for matured withdrawals to clear pending positions.HostedTradingError(5xx) — transient server error; retry with backoff. See Hosted errors.
Source references
- Python:
sdks/python/pmxt/escrow.py - TypeScript:
sdks/typescript/pmxt/escrow.ts

