Every token transfer that touches the wallet is grouped by transaction. Inside one transaction:
| What happened | What it is | What is recorded |
|---|---|---|
| You received a token and paid ETH, WETH, USDG, or a stock token | A buy | A lot: quantity and cost in USD |
| You sent a token and received ETH, WETH, USDG, or a stock token | A sell | Proceeds in USD, matched against lots |
| You received a token and paid nothing | An airdrop or a transfer in | A lot with zero cost |
| You sent a token and received nothing | A transfer out | Lots removed. No sale, no loss. |
| You sent one memecoin and received another | Token for token | Not counted. There is no dollar anchor and guessing one would be a lie. The count of skipped swaps is shown. |
| Several tokens moved at once: a batch, a liquidity add, a multi-token claim | No single subject | Not counted. There is no honest way to split one payment across several tokens. Counted separately as "no single subject" so the total adds up. |
A stock token is the payment asset when a memecoin is on the other side of the trade, and the thing being traded when only ETH or USDG is on the other side. Losing money on NVDA is still losing money.
Most buys on this chain are paid in plain ETH, not WETH, and most sells hand plain ETH back. Neither appears as a token transfer, so a naive method would show every buy as free and every sell as pure profit. That is the single biggest way a tool like this gets it wrong, and it is handled in two places:
Native legs are only attached to transactions that already move a token, so sending ETH to a friend is never mistaken for a trade.
An earlier version of this page described a different method, and it was wrong. It read Withdrawal events off the WETH contract out of each transaction receipt, on the theory that a router unwraps WETH and hands ETH back. Measured against a real active wallet: across its 300 most recent transactions, zero receipts contained a Withdrawal, while the internal-transaction list showed 291 real ETH arrivals over the same span. That method cost 2,034 RPC calls and four minutes to find nothing, and every sale it missed would have made a loss look bigger than it was, which is the one direction this page promises not to err in. It is recorded here rather than quietly deleted, because a method page that only lists the things it got right is a marketing page.
First in, first out. When you sell, the oldest lots are consumed first, and the loss on that sale is proceeds minus the cost of exactly the lots it consumed. A partial sale consumes a partial lot. This is the same method a tax office uses, and it means the number is not sensitive to how you would prefer to think about it.
| Asset | Valued at |
|---|---|
| ETH and WETH | That day's close, from data/eth-usd.json (CoinGecko, daily). A loss taken in July is valued in July's ETH, not today's. |
| USDG | 1.00 |
| Stock tokens as payment | Today's price. No daily history is available for them without an indexer, and this is flagged in the data as todayOnly. It is the one known approximation. |
| Anything still held | Today's price from DexScreener, deepest pool. Unrealized is a separate tab and is never mixed into a realized figure. |
The single sale with the most negative loss. Not the worst token, not your total, one transaction. It is linked on every row so you can open it and see the sale, the proceeds, and the date. The "by token" tab adds up every sale of one token instead. The total on the sidebar is realized losses across scanned wallets that are net down, and it excludes anyone who is net up.
The front page is a roster. Each wallet on it was added deliberately, by whoever runs the site, under a name they chose, and the page says "added by the mods, not submitted" at the top so nobody mistakes it for a queue of volunteers. With nothing in the roster the page says nobody has posted.
An earlier version was a leaderboard built by harvesting wallets out of the busiest pools and ranking whatever the script found. Every loss on it was real and every one was linked to its transaction, but nobody had posted any of them and each row said "submitted 2 days ago". A site whose entire argument is that its numbers can be checked does not get to describe a scrape as a submission, so that board came down. This is the same page on honest terms.
Being on it or not says nothing about you. There is no ranking against it either: a lookup tells you what you lost and links the sale, not where you place.
todayOnly in the data.Every one of these errs in one direction: it makes a loss smaller or missing. Nothing here can make a loss bigger than it was.
You can pick a username, react to a row, and argue underneath it. None of that is verified and none of it is meant to be, so it is worth being exact about which half of this site is which:
| The losses | The comments | |
|---|---|---|
| Where it comes from | The chain | Somebody typing |
| Can it be faked | No. A transfer is not a sale, and the transaction is linked so you can check | Yes, trivially |
| Is the name real | No name is involved | No. There is no password and nothing to sign in to |
| Can two people be u/same | n/a | Yes |
A username here is a display name. It is kept in your browser next to a random id, and that id is only there so you can delete your own comment and so a vote can be taken back. No figure depends on it and no number changes because of it. Comment votes move comments, never losses. That separation is the point: the reason this site is worth reading is that the losses cannot be faked, and a comment section is not allowed to quietly become part of the evidence.
If this copy of the site has no comment server configured, every thread says so and your comments are visible only to you. That is stated rather than hidden, because a comment box that looks like a room full of people and is not is its own kind of lie.
The block explorer offers the same data through two APIs, rate limited in opposite ways, and the response headers say so outright:
| API | Allowance | Rows per request |
|---|---|---|
/api?module=account | 10 per window, and the window is long | up to 10,000 |
/api/v2/… | 180 per ~50 seconds | 50 |
The long window has been measured anywhere between ten minutes and an hour, so nothing here assumes a number for it. The lookup page reads how many requests you have left and how long until they refill straight out of the response headers, and shows you both.
The obvious reading is that the second one is eighteen times more generous. For reading one wallet that reading is wrong, because the cost here is round trips rather than permission. Measured on the same real wallet, the same day:
| Method | Time | What came back |
|---|---|---|
| Paged, 50 rows at a time | 582 seconds | 1,000 of 4,169 transfers, capped |
| Three whole-history requests | 13.5 seconds | all 4,169 transfers |
Forty times faster and complete instead of truncated. The ten-minute read finished with 173 of its 180 requests unspent, so the allowance was never the constraint at all. A lookup therefore spends three of your ten whole-history requests, and only falls back to paging if you run out, which makes the slow path the floor and never the ceiling. That matters for accuracy and not just for patience: truncation is the main thing that makes this site understate a loss, and the fast path is the one that avoids it.
The build script does the opposite, because it reads hundreds of wallets and ten requests per ten minutes cannot do that. It pages, it is slow, and it runs offline where slow is free.
node data/test.mjs # the rules on this page, as tests node data/build.mjs --wallet 0x… # one wallet, printed node data/build.mjs --wallet 0x… # the same path the site takes
Same wallet, same price table, same output. --wallet takes the same whole-history path the lookup takes, so the terminal and the card agree by construction. The hashes of the engine, the price table, and the snapshot are pinned on verify.
Every claim on this page that can be turned into a test is one: that a transfer out records no sale, that native ETH paid counts as cost, that lots are consumed oldest first, that a stock token is the subject when only ETH is opposite, that a sub-cent bag is not a bag, and that no malformed row anywhere in real chain data can turn a figure into NaN. node data/test.mjs runs them with no network in under a second.