The default that breaks wallet forensics.
MSR FINDING RECORD — the citable finding, scope, and limits
- Finding
- Polymarket’s
/tradesendpoint defaults to a taker-only view of a wallet’s fills. Read as a complete trade history, that default flagged ordinary trading across three wallets as unbacked leaderboard profit. - Test
- Re-fetched the 50 largest flagged markets per wallet — 150 of 4,725 flagged in total, chosen by size of excess within each wallet, not a pooled ranking or random sample — using
takerOnly=falseand/activity, scoped to the redeemed outcome token. Re-fetched 2026-07-25. - Result
- 150 of 150 reconciled: every flagged redemption was paid for by the wallet’s own purchases. In the flagship market the default view showed 1 purchase; the fuller history showed 80. That exemplar was independently confirmed on Polygon.
- Limit
- Not a random sample — the right test for whether the method works, the wrong one for a population rate. Only the exemplar received full on-chain reconstruction; the other 149 rest on API-level reconciliation. Does not establish the three wallets’ overall profitability — flagged markets are selected for large redemptions, so losing markets are excluded by construction.
- Reproduce & contact
- Per-market reconciliation: JSON · CSV. Full calls and method in Method and limits. Cite as MSR Decode, “The default that breaks wallet forensics”,
msrdecode.com/cases/trades-endpoint.html. Chris Park · ceo@msrdecode.com · For journalists.
Contents
The false-positive signal
Polymarket outcome shares are ERC-1155 tokens on Polygon. They can be bought on the order book, minted by splitting collateral, or simply sent from one wallet to another — and a plain token transfer carries no cost basis to the receiving side. A wallet could, in principle, receive winning shares from a second wallet the same person controls, redeem them at $1.00, and book the value as profit it never earned.
Our original screen compared the inventory a wallet appeared to acquire, from its trade history, with the amount it later redeemed. A redemption that exceeded what the visible trade history could explain was flagged for transfer review — on the theory that the unexplained excess had arrived from a second wallet. The share counts behind that comparison came from Polymarket’s public /trades endpoint.
Run across a set of wallets our own method had flagged, the results were dramatic: across the three wallets in this report it flagged 4,725 markets carrying $4,772,218.83 of apparently unbacked redemptions. The screen’s logic was sound. The trade history feeding it was not.
One market, four answers
Take the single largest flagged market in the worst-looking wallet: 0x8c901f67…a904, in “Bitcoin Up or Down — April 27, 9:35PM–9:40PM ET” (0x2981bbd7…89bb). A market that existed for five minutes.
| Source | Buy fills reported | Shares | Cost |
|---|---|---|---|
| /trades, default — as the filter read it in April 2026 | 1 | 21.19 | $16.74 |
| /trades, default — re-fetched 2026-07-25 | 1 | 20.87 | $16.49 |
| /trades?takerOnly=false — re-fetched 2026-07-25 | 80 | 12,759.03 | $9,978.37 |
| /activity — re-fetched 2026-07-25 | 80 | 12,759.68 | $9,978.88 |
At resolution the wallet burned 12,759.355696 shares and was paid $12,759.355696 — a figure Polymarket’s own records and the chain agree on to six decimals.
So the filter saw $16.74 of buying against a $12,759.36 redemption and concluded that roughly $12,738 of winning shares had been gifted in from a sister wallet. What actually happened is that the wallet bought 12,759.68 shares for $9,978.88 across 80 fills and made an ordinary $2,780.48 profit. Adding one query parameter — takerOnly=false — returns 79 of the 80 fills the default view withholds.
The April and July /trades rows differ slightly (21.19 vs 20.87 shares); we publish both rather than reconcile them away. The one-fill count — the part that matters — reproduces exactly.
The two fuller histories differ by $0.51 on one of the 80 fills; we traced it to the chain rather than rounding past it, and the discrepancy is reported rather than forced into agreement — derivation in Method and limits.
The chain independently reconciles it
An API disagreeing with itself does not settle who is right, so we went to Polygon. We took the redemption transaction, decoded which token was burned and in what quantity, then scanned the blocks before it for every inbound transfer of that exact token and resolved each sender.
| Sender | Identity | Transfers | Shares |
|---|---|---|---|
| 0x4bfb41d5…8982e | CTFExchange — Polymarket’s order-matching contract | 80 | 12,398.622139 |
| 0xe3f18acc…ab7b0 | FeeModule — Polymarket’s fee contract | 80 | 360.733557 |
| any ordinary wallet | — | 0 | 0.000000 |
| Total | ties to the burned quantity exactly | 160 | 12,759.355696 |
Every share came through Polymarket’s own contracts. Not one arrived from another user’s wallet. Both sender addresses are verified under those names on Blockscout, and the two calls in Section 06 reproduce this.
There is a trap here that is the mirror image of the first one. An ordinary purchase also arrives in your wallet as an inbound ERC-1155 transfer — the exchange contract is the sender. A raw count of “inbound transfers” is therefore not evidence of anything either. The sender has to be resolved before the number means what it appears to mean.
The 150-market test
One market could be a fluke. We re-fetched the 50 largest flagged markets by excess within each of the three wallets — 150 in total — and asked the same question of each: is the “excess” explained by buying that the default /trades view failed to report?
| Wallet | Markets | Called unbacked | Actually paid | Sale proceeds | Redeemed | Net | Explained |
|---|---|---|---|---|---|---|---|
| 0x8c901f67…a904 | 50 | $403,775.97 | $314,444.35 | $0.00 | $461,844.46 | +$147,400.11 | 50 / 50 |
| 0xd0d6053c…93aa | 50 | $82,311.53 | $129,580.46 | $5,377.05 | $218,392.51 | +$94,189.10 | 50 / 50 |
| 0x1d003413…0313 | 50 | $440,375.08 | $503,687.13 | $0.00 | $854,027.96 | +$350,340.83 | 50 / 50 |
| Total | 150 | $926,462.58 | $947,711.94 | $5,377.05 | $1,534,264.93 | +$591,930.04 | 150 / 150 |
Result. 150 of 150. The $926,462.58 the method called unbacked was backed by real buying of the specific shares each wallet went on to redeem.
Robustness. 108 of these 150 markets show the wallet trading both outcome tokens, not only the one that redeemed (the other 42 traded just the winning side). Re-splitting every row’s buying and selling by outcomeIndex and re-running the check against the redeemed token alone changes the classification on zero rows. It does change the dollar total: $947,711.94 above is money spent on the shares that were actually redeemed, not both outcomes of the market summed together, which is what an earlier pass of this table showed and which put the number $414,187.03 higher — real money the same wallets spent on the losing side of these same markets and mostly never recovered. Precision derivation in Method and limits.
Scope. These are the 50 largest flagged markets within each of the three wallets, 150 of 4,725 in total — chosen by size of excess inside each wallet, not a pooled ranking and not a random sample. That is the right sample for testing whether the method works, and the wrong one for estimating a rate. What it establishes is narrow: these redemptions were paid for by the wallets’ own purchases of the shares being redeemed — not that the wallets are profitable overall (flagged markets are selected for large redemptions, so losing markets are excluded by construction), and not that wallet-to-wallet transfers never happen, since a transfer traded out on the order book is paid for too and this method cannot see it.
The API default
takerOnly=true
The /trades endpoint defaults to takerOnly=true — it returns only the fills where the wallet crossed the spread. Passing takerOnly=false returns the rest. In the exemplar that is the difference between 1 fill and 80.
Not incidental
Not a rounding effect confined to the exemplar. Across all 150 markets we re-fetched — not a sample of them — the default view retained well under half of buy-side dollars and just over half of sell-side dollars.
Across all 150 markets, the default view retained 40.4% of buy-side dollars and 59.7% of sell-side dollars, leaving $811,984.53 of buying and $7,829.50 of selling omitted from the default response. Hidden buying dollar-dominates hidden selling here — more than 100 to 1 — because these are redemption-flagged markets by construction: the wallet held to resolution rather than trading out. That skew is a property of this sample’s selection, not a claim about every wallet or strategy: a wallet that sold down a transferred-in position before redemption could see the opposite bias.
Exemplar market — buy-side spend recovered
All 150 re-fetched markets — buy-side dollars
All 150 re-fetched markets — sell-side dollars
How to verify correctly
If you run wallet forensics on Polymarket — copy-trading products, leaderboard screens, academic work using displayed profit as a skill proxy — this failure is worth checking for in your own pipeline. It produces confident, specific, technical output that happens to be wrong.
Polymarket’s /activity feed enumerates twelve event types — TRADE, SPLIT, MERGE, REDEEM, REWARD, CONVERSION, DEPOSIT, WITHDRAWAL, YIELD, MAKER_REBATE, TAKER_REBATE, REFERRAL_REWARD — and none of them is a token transfer. A wallet-to-wallet share transfer does not appear as its own event in either /trades or /activity, and displayed profit does not net it out. It is not invisible outright: it is a plain ERC-1155 transfer, visible on Polygon to anyone willing to do what Section 03 did.
Ask for the other side of the book
Pass takerOnly=false, or reconcile against /activity scoped to a single market. Either way, page it: /activity caps every response at 500 records regardless of the limit you request, and 21 of these 150 markets needed more than one page.
Resolve senders on-chain
Measure the unambiguous quantity: inbound ERC-1155 transfers whose sender is not recognized Polymarket settlement infrastructure. Resolve sender identity on-chain (Section 03) rather than trusting a raw inbound-transfer count.
The calls behind Sections 02 and 03, in full:
| What | Call |
|---|---|
| Wallet | 0x8c901f67b036b5eebab4e1f2f904b8676743a904 |
| Market (condition ID) | 0x2981bbd76157280d6161a7cded2a141af40d8d2f94a2014c4561488079bd89bb |
| Outcome token (asset ID) | 85612635244646347265208933815991747551122064386068179565554647222358877800034 |
| 1 fill | data-api.polymarket.com/trades?user=0x8c901f67b036b5eebab4e1f2f904b8676743a904&market=0x2981bbd76157280d6161a7cded2a141af40d8d2f94a2014c4561488079bd89bb |
| 80 fills | …the same call with &takerOnly=false |
| Full activity incl. the redemption | data-api.polymarket.com/activity?user=0x8c901f67b036b5eebab4e1f2f904b8676743a904&market=0x2981bbd76157280d6161a7cded2a141af40d8d2f94a2014c4561488079bd89bb |
| The redemption | eth_getTransactionReceipt 0xbde3495edd20cf329cb5b12262be4191907f3e6261f124994870b4e3731c4ee8 |
| The senders | polygon.blockscout.com/api/v2/addresses/0x4bfb41d5b3570defd03c39a9a4d8de6bd8b8982e |
| The other sender | polygon.blockscout.com/api/v2/addresses/0xe3f18acc55091e2c48d883fc8c8413319d4ab7b0 |
| Full reconciliation, all 150 markets | /trades-endpoint-reconciliation.json · .csv |
Method and limits
Precision note. The two fuller histories behind the exemplar (takerOnly=false and /activity) differ by $0.51 on one of the 80 fills — transaction 0xba5167ca…28c9c, where both endpoints agree on price, timestamp and outcome but report different sizes (20.86924 vs 21.52 shares). The other 71 transactions behind those 80 fills match exactly. On-chain, this fill’s settlement moved 21.19462 shares to the wallet across two transfers (20.94795 from CTFExchange, 0.24667 from FeeModule) — a third figure, close to the midpoint of the two APIs’. The gap is real and confined to this one fill; which endpoint’s rounding or fee treatment produces it is not determinable from what is published, so both figures are reported as measured rather than reconciled to match.
Sender resolution. An inbound ERC-1155 transfer is not automatically evidence of a wallet-to-wallet gift — an ordinary purchase also arrives as an inbound transfer, from the exchange contract. We resolve each inbound transfer by sender and distinguish recognized Polymarket settlement infrastructure from ordinary external wallets before treating an inventory gap as externally funded; Section 03 names the two senders behind the exemplar specifically. A raw inbound-transfer count is not evidence on its own — sender identity is what the classification turns on.
Provenance. These figures came out of our own private research between April and May 2026. None were ever published, and this page is the reason they will not be: the false positives were demonstrated here, not before. One caveat runs the other way and stays open — this shows the method produces false positives at scale, not that wallet-to-wallet share transfers never happen; the behaviour is possible and is not exposed as a standalone event in Polymarket’s /trades or /activity feeds. An earlier internal reconstruction also failed to paginate 18 of the 110 markets in this report’s first draft at the /activity endpoint’s 500-record cap, understating real buying by roughly $72,000; the issue was caught before publication, corrected, and is now covered by the automated build check described above. A post-resolution enable_order_book field was initially considered as a possible explanation for the omission pattern, but historical testing showed the field could not establish trade-time market structure, so no causal claim is made from it.
Limits. The chain-level sender confirmation was run on one market, not all 150 — free Polygon archive endpoints refuse or rate-limit log queries at this depth, so the other 149 rest on the API reconciliation alone. The 150 markets are the 50 largest by excess within each of the three wallets, drawn from 4,725 flagged — not a pooled top-150 and not a random sample. The three wallets are the ones our own method flagged hardest, which is the right sample for testing the method and the wrong one for any population estimate. We make no claim about how common wallet-to-wallet transfers are on Polymarket — only that this way of detecting them does not work. Of the $414,187.03 disclosed in Section 04 as spent on the outcome that did not redeem, these wallets recovered only $14,067.73 before resolution — direct evidence that flagged markets exclude losing ones by construction. On some flagged markets the original filter’s own arithmetic produced negative net holdings — one record held −577.29 shares of a side it then redeemed, which a wallet cannot do; that self-refuting input should have stopped the pipeline and did not. Two figures cited in passing (that example and the April /trades row in Section 02) come from the original private pipeline’s stored output rather than from a published artifact.
Artifacts. Full reconciliation: JSON · CSV. Reproduction calls and on-chain lookups are above, in Section 06. MSR keeps a public log of its own corrections — the register and the record. Method questions, on the record: ceo@msrdecode.com.