Inspiration

Wash trading is old. Selling stock to yourself to fake volume has been illegal in the US since the Exchange Act of 1934, up to 20 years in prison. NFTs never got that rulebook. They've never been confirmed as securities, so almost no federal rule covers manipulation in NFT marketplaces. With years of market surveillance experience, that gap was the obvious hook: there's a full trading floor's worth of data sitting completely in the open on the blockchain, so what would actually turn up if I looked?

The hackathon's theme sealed it. Surveillance teams already work this way after any confirmed incident: "what should we have caught sooner?" I wanted an agent that does that automatically, turning every confirmed case into a memory that helps it catch the next one faster.

What it does

It scans real Ethereum NFT trades (LooksRare, 2022, chosen because independent research estimated about 94.5% of that year's volume was wash trading, a rare answer key to test against) and finds closed loops of wallets trading the same NFTs back and forth to fake volume. Every detected ring becomes a case, with who's in it, how many self trades happened, and whether the exact same token literally came back to the group (the smoking gun).

Every day it scans fresh trades and ranks new rings by how closely they match cases already confirmed in memory, so an analyst opens an already triaged worklist. Ruling on a ring means a grounded checklist and precedent, not a bare button, and that verdict becomes permanent memory. Days later, the same scheme described in totally different words gets caught faster, because it's matched by meaning, not keywords. You can also just ask the memory questions in plain English, like which case had the most wallets, and it writes and runs the query itself, showing its work.

How we built it

Ingestion pulls real trades from Alchemy's NFT API and wallet funding history from Etherscan. A Python pipeline finds symmetric round trip pairs and, more importantly, matched order rings via graph cycle detection, a blind spot pairwise detection alone misses, then consolidates overlapping rings into distinct collusion cases.

CockroachDB is where evidence and memory live together: trades and cases sit in relational tables, with a distributed vector index over embedded case notes on top, so a new ring gets compared by meaning against every past verdict in one database, no separate vector store to keep in sync. The Cloud Managed MCP Server lets the agent answer plain English questions with a real, auditable, read only SQL query. AWS Bedrock, Titan Text Embeddings V2 plus an LLM for rationales, does the embedding and the explaining. It's a FastAPI app, deployed publicly on Vercel in a read only demo mode: no AWS keys, a database user with SELECT only, so the public deployment is structurally unable to spend money or alter the evidence.

Challenges we ran into

Most of the real challenges were about data, not code. Two candidate data sources shut down entirely mid project, and another needed a paid plan just to create a query, so ingestion got rebuilt around Alchemy's NFT API instead. Detecting an NFT collection's metadata reveal sounds simple until you find a collection that called setBaseURI three separate times, once for the real placeholder, once for the actual reveal, and once for a totally unrelated repin, and only checking the token metadata itself tells you which is which.

I also tried detecting individual insider traders statistically, and it honestly didn't work: even on a collection with a documented rarity sniping exploit, no wallet's rare acquisitions survived a proper multiple comparison correction. That taught me wash trading, high volume and easy to catch statistically, and surgical insider trading, one well timed trade and statistically invisible, need fundamentally different detection methods, so I scoped around that instead of forcing a false positive.

Accomplishments that we're proud of

The memory measurably works: a scheme confirmed once, then described in completely different words days later, went from a 0.51 to a 0.37 cosine distance, meaning the agent got sharper because it remembered, not because a threshold got tuned. Across 15 straight days of daily runs, all 110 freshly detected rings resembled a case already confirmed in memory, exactly the "catch it earlier next time" story this hackathon is about.

I'm just as proud of the honest negative results. When statistical insider detection came up empty on both a fair collection and one with a known exploit, I didn't force a false positive, I reported the limit and used it to draw an honest line between what public on chain data can prove and what it can't. And the whole thing runs live: a real CockroachDB cluster, a real vector index, real Bedrock calls, with a public demo anyone can click through safely.

What we learned

The biggest realization was structural: traditional market surveillance runs on order book data, every quote, cancel, and amendment, while public blockchains only expose executed trades and transfers. That single gap explains exactly which manipulation types public on chain data can catch outright, like wash trading rings, and which it fundamentally can't, like spoofing or layering, and it shaped nearly every scoping decision after that.

I also learned to be suspicious of my own results. It would have been easy to loosen a threshold until insider trading "worked," but running the correct statistical test and getting a null result was more valuable, because it proved the method has real specificity instead of just finding whatever it went looking for. And treating a memory database as one system for both evidence and vector search, instead of a relational store synced to a separate vector store, removes an entire category of consistency bugs.

What's next for NFT wash trading detector

The next real milestone is the second manipulation type this memory architecture was built for: insider trading around verifiable events like metadata reveals, where materiality and non public information can both be proven from public data, using transaction level tracing instead of population statistics. Training a proper model on AWS SageMaker over the precursor features already engineered here would let it rank which early signals predict a confirmed case before it becomes an obvious ring.

Longer term, the same memory engine that works on public data today is built to generalize: deployed inside a real exchange or regulator with order book and account level data, it could cover manipulation types that are structurally invisible from outside, like spoofing. And there's a lighter idea worth chasing too, a real time version giving everyday collectors a live per collection risk score, framed honestly as "this volume looks manufactured," never as trading advice.

Built With

Share this project:

Updates