batchWithdraw call burns your vault shares and returns the underlying Polymarket outcome tokens plus the organic yield those shares accrued. It works identically for both Polymarket wallet kinds.
batchWithdraw
A side may be zero (withdraw only YES or only NO), but each row must burn at least one share. The
Side enum is YES=0, NO=1.
Getting share balances
Read the shares you can burn — and what they are currently worth in outcome tokens — fromRobinLens.batchGetUserSharesAndAssets. The yesAssets / noAssets are loss-adjusted token amounts, so they reflect any impermanent loss already booked against the position.
UNDERLYING_DECIMALS=6). See Reading on-chain state for the full RobinLens surface.
TWAP first
The vault rejects a withdrawal for a market whose TWAP is not fresh, because
the TWAP determines how yield is split between the YES and NO sides. Refresh
the relevant markets and, when needed, prepend
RobinTwapOracle.submitTwap(...) to the same batch as batchWithdraw. See
Keeping TWAP fresh.Bonus payout is separate
The on-chain
batchWithdraw returns only the organic yield (paid via the
vault’s lossIndex + yieldPerShare accounting). The yield guarantee,
matching bonus, and Robin Points are an off-chain programme: Robin computes
them at withdrawal and sends them in a separate USDC transaction from its
operator wallet shortly after. Your withdraw transaction will not contain that
bonus — do not expect it in the Withdrawn event or the returned yield.Withdrawn(...) event carries a protocolFee — Robin may take a protocol fee on the organic yield only, never on principal.
Transport
batchWithdraw is identical for both wallet kinds; only how you submit it differs. Resolve the wallet once and submit through its transport.
1
Resolve the wallet
Determine whether the user’s Polymarket account is a
DepositWallet or a
legacy Gnosis Safe proxy, and key all reads and writes on that resolved
address. See Wallets.2
Build the batch
Sort by
conditionId, then assemble the call array — optionally
submitTwap first, then batchWithdraw.3
Submit through the wallet's transport
Safe proxy →
Safe.execTransaction. DepositWallet → the Polymarket
relayer. Unlike deposits, there is no pull/push distinction for withdrawals
— the vault already holds the shares.withdraw.ts in the integration example repo wires all of this together — wallet resolution, TWAP refresh, the multi-market batch, and transport dispatch.
Next steps
Reading on-chain state
Read shares, assets, and pending yield from
RobinLens.Keeping TWAP fresh
Refresh a market’s TWAP before withdrawing.