This release includes 1 security fix for security teams reviewing exposed deployments.
Topics
Affected surfaces
Summary
AI summaryWithdraw retry logic now prevents double‑spending and withdrawals can sweep legacy USDC.e.
Full changelog
Closes the external-review backlog: all 8 findings from the Kimi K3 review
(#72) and both unabsorbed pieces of @KillerQueen-Z's #59/#66 (#71).
fix(polymarket)— the withdraw retry double-spend window is closed
(#72.1). The relayer SDK'swait()polls 200s and returnsundefinedfor
BOTH an on-chain failure and a timeout, while the signed batch stays
executable until its 300s deadline — and our error text said "re-run",
an instruction that could double-send a partial withdrawal. Now:
sendWalletBatchasks the relayer which case it is and says so (a failure
is retry-safe; a pending batch gets "Do NOT retry" + the remaining window);
every withdrawal batch is tracked in the state file while in flight, and
action:"withdraw"refuses to sign a second transfer until the previous one
resolves or its deadline passes (unreachable relayer counts as pending —
the conservative side). Per-operation guidance replaces the hardcoded
"re-run setup" advice everywhere (#72.5).feat(polymarket)— withdrawals sweep legacy USDC.e (#71). Withdrawable
balance is now pUSD + USDC.e; any shortfall beyond the pUSD on hand is
wrapped through the collateral onramp first (wrap(asset, to, amount)
signature verified against the onramp's Sourcify exact-match source).
Sweep design from #59/#66, with the wrap preview in the dry-run and the
post-wrap balance re-read before bridging.fix(polymarket)—amount_usdparsing no longer truncates through float
noise.BigInt(Math.floor(usd * 1e6))sent $19.989999 for a $19.99
request; amounts now round to the exact micro-dollar and over-precision /
non-positive values are rejected. (The #66 draft's absolute 1e-7 tolerance
sat below the float-noise floor and rejected honest amounts like $1234.56;
0.01 micro separates noise from genuine violations.)fix(polymarket)— redeem refuses to guess the adapter (#72.3). A
missingneg_riskfield now falls back to the order book and errors out if
both sources are silent, instead of silently treating "missing" as
"standard market" — the wrong adapter is the no-op redeem class. The
confirm path also now refuses unresolved markets up front (#72.6) instead
of submitting a batch that reverts on-chain.fix(polymarket)— setup verifies the deploy landed at the DERIVED
address (#72.4) by reading contract code on-chain (3×750ms) before
recordingdeployed:true, so a relayer factory/salt divergence can never
point approvals and funding at a nonexistent wallet.fix(polymarket)— ClobClient cache key includes the deposit wallet
(#72.2), so a wallet change within the process lifetime can't keep
building orders against the oldfunderAddress.fix(polymarket)—roundToTickabsorbs float-division noise (#72.7).
0.58/0.001 = 579.9999…floored a buy to 0.579 (one tick under the stated
limit); on-grid prices now survive unchanged, off-grid still rounds
conservatively by side.fix— creds/state writes are atomic (#72.8) (tmp + rename), so a
crash mid-write can't corrupt the credentials or deposit-wallet mapping
that reads then silently swallow to null.- Bounded e2e scripts from #66 are in-tree (#71):
npm run e2e:polymarket:{readonly,approvals,approve,withdraw,live}— readonly and
approvals verified live against the local wallet today. - 250 tests (17 new: batch-state disambiguation, double-spend guard
lifecycle, sweep preview + calldata pinning, amount parsing, tick
rounding), typecheck, build green.
Security Fixes
- Withdraw retry double‑spend window closed: sendWalletBatch now distinguishes timeout vs. failure and blocks unsafe retries (#72.1)
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About blockrunai/blockrun-mcp
Live data for AI agents — search, research, markets, crypto, X/Twitter. Pay-per-call via x402 micropayments.
Related context
Beta — feedback welcome: [email protected]