---
name: trenchbuy
description: trenchbuy, the Chrome extension that turns a row on robinhoodtrenches.com into a loaded fomo buy panel in about one second. Read before touching Ben's buy flow, before any fomo.family UI automation, and before proposing any auto-buy or key-holding bot.
sources: [cowork]
aliases: [trench-buy, robinhoodtrenches, trenches-tape, fast-buy]
---

# trenchbuy

Built 5 Sep 2026. Lives on Ben's Mac at **/Users/bk/trenchbuy** (manifest.json, background.js, trenches.js, fomo.js, trenchbuy.css, INSTALL.txt). Loaded once via chrome://extensions > Developer mode > Load unpacked. Companion to [[rugscan]].

[stated] Ben found https://robinhoodtrenches.com/ ("live action on best traders on FOMO") and said his buy flow takes about 10 seconds: click the DexScreener link, wait for it to open, copy the contract, paste into fomo on desktop, wait for it to load. He asked for one click to buy a predefined amount, and clicking three times to buy three times that amount.

## What was built
- Content script on robinhoodtrenches.com adds a lightning button and a copy button to every tape row, plus a bottom-right bar where the unit amount is set (stored in chrome.storage).
- Click the lightning button: the pinned fomo tab jumps to that token and the buy amount is pre-filled with the unit. Click again within 6 seconds and the amount steps up 1x, 2x, 3x. `alt+1` to `alt+9` fire the top rows from the keyboard.
- The fomo tab is opened pinned and warmed the moment the tape loads, so the first click is as fast as the rest.
- **It fills the amount. It does NOT press Buy, and it never touches a private key.** That boundary is deliberate and was explained to Ben; do not remove it in a later session, and do not build a server-side signer holding his key.

## Measured facts about these two sites (5 Sep 2026, verified in his browser)
- **robinhoodtrenches.com** is a websocket tape. DOM is `<tbody id="tape">` with `<tr class="buy sz2">`, ticker in `.sym`, size in `.size`, trader in `.who`. **The contract address is already in each row's dexscreener href**, so opening DexScreener at all was pure waste, roughly 8 of his 10 seconds.
- **Jumping tokens inside fomo must go through fomo's own search box.** Set the search input with the native value setter, wait for the result link whose href contains the CA, click it: client-side route change, about 0.6s, NO reload. Verified.
- **A plain injected `<a href="/tokens/robinhood/CA">` that is clicked triggers a FULL page reload on fomo (3 to 4s).** It looks like it should soft-route and it does not. This is the trap; the code keeps it only as a fallback.
- fomo's buy panel already has preset buttons **$10, $100, $500, $1000** plus a free-text amount input (`placeholder="0"`). React accepts a value written through the native setter plus an `input` event; verified by writing 750 and reading it back.
- fomo has no `/portfolio` route and its API needs a bearer token, so UI automation is the way in.

## Installing it: Chrome is READ-ONLY to computer control, this is settled
[stated] Ben asked "install it for me, do the whole thing." It could not be fully done, for a structural reason worth never rediscovering:
- `computer_resolve_access` returns tier **"read"** for com.google.Chrome and every browser. The grant response says plainly: visible in screenshots only, no clicks or typing, and **"never use AppleScript, System Events, shell commands, or any other method to send clicks or keystrokes to this app."**
- `computer_request_full_control` refuses until an app is granted, and the browser grant is still read-only. So chrome://extensions cannot be clicked by anything on this side. The Claude-in-Chrome extension also cannot open `chrome://` URLs ("Can't interact with browser-internal or unparseable URLs").
- Therefore **Load unpacked is a four-click step only Ben can do**, and asking him is correct, not laziness. Do not try to route around it with osascript, and do not relaunch Chrome with `--load-extension` (kills his session, kills the Claude-in-Chrome link, and modern Chrome ignores the flag).

## The live-injection fallback, which DOES work with no install
Injected into his open tape tab with `mcp__claude-in-chrome__javascript_tool` and verified on screen, 150 rows decorated:
- Same lightning and copy buttons, same bottom-right unit bar (`localStorage` key `tb_unit`), same alt+1..9.
- Without extension privileges a page on robinhoodtrenches cannot script fomo.family, so the amount cannot be auto-filled. Instead the click does `window.open(url,'tbFomo')` (a NAMED window, so it reuses one fomo tab) and writes the amount to the clipboard for a paste.
- **Put the buttons in the FIRST cell, not appended.** The first attempt appended a `<td>` and the tape is wide enough that the whole column sat off-screen; it looked broken. `tr.insertBefore(td, tr.firstChild)`.
- This dies on page reload. It is the stopgap, not the product.

## The injected version CANNOT pre-fill the amount, and this was tested to destruction
[stated] Ben, 5 Sep 2026: "that button works, but it's not pre-filling the $500... and when I just reloaded Robinhood Trenches, the button disappeared, so there needs to be some easy way for me to turn it back on."
Pre-fill needs code running ON fomo.family. A script injected into robinhoodtrenches cannot reach it. Every workaround was tried and each failed for a different reason:
- **`window.open` from injected JS with no user gesture is popup-blocked** (returns null). It only succeeds inside Ben's own click handler.
- After a real click opened the named window, **`window.__tbW.closed` reported `true` immediately**, so a postMessage bridge cannot be relied on. robinhoodtrenches sends NO COOP and NO CSP header (checked by fetching its own URL), so the cause is not COOP; it was not worth chasing further.
- `window.open('', 'tbFomo')` only reaches a window THIS page opened, so it can never adopt a fomo tab Ben opened himself.
- Any hard navigation of the fomo tab kills an injected listener, so even a working bridge would need re-arming on every first click of a session.
**Conclusion: one-click open, correct token, hotkeys and amount-on-clipboard work injected. Pre-fill and the 0.6s soft nav require the extension. Do not re-litigate this.**

Also: the injected version dies on every page reload. There is no way to make it survive without the extension, and re-injecting requires a live session. The extension is the answer to "turn it back on", not a bookmarklet.

## First live test of the loaded extension, 5 Sep 2026
Ben loaded it via Load unpacked. On reload of the tape the content script ran (bar present, 150 buttons, `window.__TB__` false so it was the extension, not an injection). Then:
- **Buttons rendered at x=1900 on a 1919px viewport**, half off the edge, because `trenches.js` used `tr.appendChild(td)`. Fixed to `tr.insertBefore(td, tr.firstChild)` plus a matching `<th>`.
- **Editing an unpacked extension's files does NOT hot-reload.** The page was reloaded and still served the cached content script (cellIndex still 11). The extension card's reload arrow in chrome://extensions must be clicked, which is Ben's click. Budget for that on every code change.
- **Clicking a button fired the handler (toast appeared) but the fomo tab never moved.** Root cause: fomo.family was already open BEFORE the extension was installed, so it had no content script, and the fallback path was not reached cleanly. Fixed in background.js: `chrome.scripting.executeScript({files:["fomo.js"]})` on demand, then retry, then hard navigate. Required adding **"scripting"** to manifest permissions, which itself forces an extension reload.
- background.js now logs `[trenchbuy]` on every step and wraps the handler in try/catch, because a silent MV3 service worker is undebuggable from this side (chrome://extensions is unreachable).
- **`alt+1` did not fire** in testing; not yet diagnosed, the mouse path is the one that matters.

## CONFIRMED WORKING end to end, 5 Sep 2026
Screenshot of Chrome showed fomo on `/tokens/robinhood/0x7e687223d4df3c601a38d17f5b453348a18abe0b` (OTER, the exact row clicked) with **$500 typed into the buy amount** and "Buy OTER" ready. So the extension's full path works: content script -> background -> fomo content script -> soft route -> amount fill.
- **The earlier "nothing happened" was entirely the pre-existing fomo tab.** Once that tab was closed and the extension opened a fresh one, the content script was there and it worked first time. Injecting into old tabs (the `scripting` fix) is still the right permanent answer.
- Verifying this needs `computer_app_screenshot` on com.google.Chrome. `tabs_context_mcp` only lists tabs in the Claude-in-Chrome tab GROUP, so a tab the extension opens is invisible to it. Do not conclude "no tab was created" from tabs_context alone.
- **A page reload does NOT pick up edited extension files, and neither does reloading the extension without then reloading the page.** Both are needed, and the extension reload is Ben's click. Symptom to check: the `.tb-head` `<th>` is absent and `cellIndex` is still 11, which means the old cached script is running.
- Stopgap that needs no extension reload: inject a MutationObserver that moves each existing `.tb-cell` to `tr.firstChild`. Took the buttons from x=1900 to x=8 immediately.

## Coordinate trap for `computer` clicks in Chrome
The click tool's frame was **1568x675** while the page reported `innerWidth` 1919 (Ben moved Chrome to the AW3225QF external display). A click computed from `getBoundingClientRect()` was rejected as out of frame. **Scale page coordinates by frameWidth/innerWidth before clicking, or avoid coordinates entirely.** For an extension button, `element.click()` from `javascript_tool` is enough because the extension uses `chrome.tabs`, not `window.open`, so no user gesture is needed. A gesture IS needed for the injected version.

## Speed extras worth shipping
- `<link rel="preconnect">` and `dns-prefetch` to https://fomo.family are injected on the tape page. Cheap, removes DNS and TLS setup from the first hop.
- Real workflow win, no code: keep fomo in a SECOND Chrome window beside the tape. The lightning click updates it in place, so there is no tab switch at all.
- The tape prepends rows constantly, so screen coordinates for a given row go stale within a second. Always re-read `getBoundingClientRect()` immediately before clicking, never reuse a coordinate from a screenshot.

## TAIL mode, 5 Sep 2026 (real-time tailing unipcs)
[stated] Ben: "if the trader unipcs makes a first buy over $1,000, then automatically buy $500 ASAP in real time. This is a race for speed." And: the tape marks "first buy" in pink and sometimes "not a real buy", because people spoof buys or airdrop him tokens, so it has to be a REAL first buy.
- **Ben's tape is already filtered to unipcs alone** (only one `.who` value on screen), so he is watching this one trader live.
- **The exact markup, read off his page, is the whole spec:**
  - first buy: `<span class="newpos"> FIRST BUY</span>`
  - disqualifier: `<span class="flag"> · not a real buy (spoofed)</span>`
  - **estimated size: the `.size` cell text starts with `~`**, with `title="estimated from a price feed - this transaction had no readable cash leg"`. No readable cash leg means airdrop or spoof, so a `~` size is rejected even when there is no flag span. On the sample seen, 11 of 14 unipcs rows were flagged and the real ones were the minority.
- `isTailHit()` requires: side BUY, `.newpos` present, `.flag` ABSENT, size NOT estimated, USD >= threshold, and `.who` equal to the configured trader. A `ready` flag set 2.5s after load stops the 150-row backfill from firing on page load, and a `fired` Set stops repeats per contract.
- On a hit it opens fomo on that token with the tail amount pre-filled, sounds a triple 880Hz WebAudio beep, drops a full-width blue banner with the trader, the size, the ticker and the full contract, and outlines the row. **It does not press Buy.**
- The bar now carries: unit, a "tail" checkbox that glows the bar blue when armed, trader name, minimum size, and the buy amount. All in `chrome.storage.local` under `tail`.

## v1.1, the on-chain verifier: the tape's own spoof flag is NOT enough
[stated] Ben, 5 Sep 2026: the tape missed a spoof, so "propose a different way to make sure that he actually bought."
**From first principles the only proof of a buy is: the token landed in HIS wallet AND money left in the same transaction.** Every label on the tape is a claim about that; the receipt is the fact. Each row already carries its tx hash in the last cell, so the proof is one `eth_getTransactionReceipt` away.
`verify.js` does exactly that against **unipcs `0x0a6ebed0155edb4b21d92ad02897a626cd90119e`** (see [[unipcs-worldview]] for how that address was proved):
1. token Transfer with `to` == his wallet, else "went to a different wallet" or "his wallet received nothing"
2. a USDG (**/1e6**) or WETH cash leg in the same tx, else "no money moved, this is an airdrop"
3. the cash leg IS the true size, so the size threshold is applied to the chain number, never to the tape's, which can be a `~` estimate
**Measured RPC latency 0.38s to 1.43s** on the free public endpoint. So fomo is opened immediately (opening spends nothing) and the banner runs amber CHECKING -> green REAL / red NOT A REAL BUY / amber REAL BUT SMALL / grey COULD NOT PROVE IT. Nothing is lost to verification, and he only presses Buy on green.
Manifest 1.1.0 adds host permission for `https://rpc.mainnet.chain.robinhood.com/*` and loads `verify.js` before `trenches.js`.

## LIVE TEST OF THE VERIFIER, 5 Sep 2026, 10 rows across many traders
Run in the page against live tape rows. The check is independent of the tape's own labels and it agreed with them every time, plus it priced every trade correctly.
| trader | token | tape says | chain says | verdict | ms |
|---|---|---|---|---|---|
| DumbCrayonEater | Retail | ~$119.42 | $0 | FAKE (airdrop) | 502 |
| frankdegods | Retail | ~$125.98 | $0 | FAKE (airdrop) | 322 |
| ether_monk | Retail | ~$112.50 | $0 | FAKE (airdrop) | 342 |
| unipcs | Retail | ~$117.58 | $0 | FAKE (airdrop) | 387 |
| unipcs | ROBO | $199.87 | $200 | REAL, first buy | 318 |
| unipcs | BEE | $22.96 | $23 | REAL, first buy | 320 |
| ResellCalendar | BEE | $13.39 | $13 | REAL, first buy | 407 |
| frankdegods | BEE | $23.12 | $23 | REAL, first buy | 422 |
| 0xleo | FATCOIN | $4,991.86 | $4,992 | REAL | 389 |
| econoar | ROBINCAT | $14,910.75 | matched | REAL | ~330 |
- **Latency 318ms to 502ms** on the free public RPC. The 0.4s claim holds.
- **The "Retail" token `0xef56660c740996578fd71a05bf5398db42405cb6` was a mass spoof hitting at least four different traders at once**, all as fake FIRST BUYs around $110-130. That is the attack shape to expect: one token, many famous names, all in one window.
- The chain USD matched the tape USD to the dollar on every real row, which validates using the cash leg as the true size.
- unipcs is currently making genuinely tiny buys ($13 to $200). His small size is real behaviour, not a data artefact.

## v1.2, any-trader test mode
`verifyBuy(tx, wallet, token)` now accepts `wallet = null`: it still requires a token delivery and a real cash leg, but does not pin the identity. `TAIL.who` set to `*`, `any` or blank turns this on, so the tail can be tested against the whole tape before narrowing back to unipcs. [stated] Ben also asked that "real but small" be GREEN, not amber; only fakes are red.

## fomo's holder list is NOT evidence of anything. Settled 5 Sep 2026 on Shoppy.
[stated] Ben: kyle, frankdegods and unipcs all showed as Shoppy buys on the tape, "but they're not showing on fomo as holders. I don't understand what's going on here."
- Token `0x98520d059db48f65e956da51f8f64673589e1701` (Shoppy, o1 Launchpad). Chain truth: **57 wallets with a non-zero balance**; fomo's own stat block said **"Holders 69"**; fomo's named holder table said **"Holders (7)"**. The table is a fraction of the token, and fomo knows it.
- All three buys verified real by receipt: kyle `0x39b337121494b10cffe3e581ab3281b2d62c5b08` paid $11.35 and $11.36 and holds 6,269,222; frankdegods `0x696d1265c8fc4f14797abebfae3c43ebfa9d8e28` paid $15.95 and holds 6,948,144; unipcs `0x0a6ebed0155edb4b21d92ad02897a626cd90119e` holds 2,650,276. Ben `0x01c2E8cA848486166e3D08fa987d69b65df0D00F` holds 7,784,338. All four bought inside two minutes, 06:07:22 to 06:09:14 UTC. Only Ben's appeared.
- **It is not a dust filter.** The named table listed a $12.91 position, and unipcs's own profile lists 132 positions down to $2.02. Their Shoppy stakes ($37 to $96) are far above both floors.
- **It is not a wrong wallet either.** 0x0a6ebed0's PONS 10,957,901 and DELTA 15,980,266 match his fomo book exactly, so that IS the profile's wallet, and fomo still does not show his Shoppy.
- The tell: **the newest swap on unipcs's fomo feed was 6 hours old while his Shoppy buy was 13 minutes old.** fomo's position index simply lags for wallets that did not trade in the fomo app; Ben's own position appears instantly because it is his account.
- **Rule: absence from fomo's holder list or a trader's fomo profile is NEVER evidence that a buy did not happen.** This is the second time it has misled him (BUNNY was the first, hidden under "Show dust"). The receipt is the only proof, which is exactly what `verify.js` reads.

## Latency fixes to the lightning button, 5 Sep 2026 (v1.3.0)
[stated] Ben: "it takes too long, sometimes the button doesn't do it, it needs two clicks, it took 1 or 2 seconds for the modal to even load."
Three causes, all real, all fixed:
- **A hidden tab has its timers clamped to ~1s by Chrome.** fomo was doing all its polling while backgrounded, so 150ms polls really cost a second each. background.js now ACTIVATES the fomo tab BEFORE sending "goto".
- **fomo.js only answered after the amount was filled**, which could exceed the background's 6,000ms `sendToTab` timeout; the background then concluded "no content script", re-injected, retried, and finally hard-navigated (a 3-4s reload). That is exactly the "needs two clicks". It now ACKs immediately and does the work after, and falls back to a hard navigation from inside fomo.js rather than making the background wait to decide.
- **The MV3 service worker sleeps after 30s idle** and a message into a sleeping worker can be dropped. The content script now pings every 20s and retries `sendMessage` on `chrome.runtime.lastError`.
- Plus: the ⚡ fires on `pointerdown` not `click`, hovering a row pre-types the CA into fomo's search box (`prefetch`), waits are MutationObserver-driven instead of fixed polls, and a re-injection guard (`window.__tbFomo`) stops duplicate listeners fighting over the search box.
- verify.js now prefers the USDG leg over the WETH leg whenever both exist, because WETH has to be priced at a constant and a stale constant silently inflates the size the tail gate reads.

## v1.4.0, TWO-TIER TAIL on unipcs, 5 Sep 2026
[stated] Ben: "if he buys under $500, then buy $50, and if he buys above $500, then buy $500."
- `TAIL` is now `{on, who:"unipcs", wallet, split:500, small:50, big:500}`. The old `min`/`amount` pair is gone, and the loader deletes those keys and pulls `who` back to unipcs if the any-trader test mode (`*`) was left on.
- `amountFor(usd)` picks the tier. fomo opens IMMEDIATELY on the tape's size, because that is the fast number and it has matched the chain to the dollar on every verified row; then `verifyBuy` returns in 0.3-0.5s and if the chain size lands in the other tier the amount is re-filled. No time is lost either way, and the final number in the box is always the chain's.
- There is no "too small to follow" case any more: every proved buy gets a ticket, only the size changes. Banner reads "big ticket" or "small ticket", both green, and both end in "press Buy".
- Bar controls are now: tail checkbox, trader, **split**, **small**, **big**.

## v1.4.1, three console errors Ben caught in the extension DevTools
- **`Cannot read properties of null (reading 'usd')` in `banner()`.** A JS object literal evaluates EVERY branch before one is indexed, so `Math.round(v.usd)` in the `real`/`small` entries ran even when the state was `checking` or `fake` and `v` was null. Fixed with `v = v || {}` and defaulted reads. Reusable rule: never put a property read inside a `{...}[state]` lookup table unless the object is guaranteed present on every path.
- **`AudioContext was not allowed to start`.** A tail fires with no user gesture, and Chrome refuses to start a context that was never unlocked. Now ONE shared `AudioContext`, resumed on the first `pointerdown` or `keydown` on the page; `alarm()` returns silently if it is still suspended. The banner always shows regardless.
- **`Extension context invalidated`.** Reloading the extension orphans the content script already on the page and every `chrome.*` call then throws. All of them now go through `send()` / `store()`, which set a `DEAD` flag, stop the 20s keepalive, and toast "trenchbuy was reloaded, reload this page to arm it again". This will fire on every extension reload, and it is not a bug in the code, it is the reason the page reload is always needed too.

## v1.5.0, THE DEPLOYER FLAG next to the lightning bolt, 5 Sep 2026
[stated] Ben: "How long does it take you to check the deployer? If you can check that in real time, then you could add a green or red flag next to the electricity sign so that I know if I should tail him or not."
- **Answer on speed: 0.8s to 3.5s normally, up to 19.6s when Blockscout is busy, and one lookup in six failed under load.** Too slow to block a click, fine behind a hover. So the dot is painted on `mouseenter` (the row already prefetches fomo there) and cached per token forever, and the ⚡ never waits for it.
- New file **`deployer.js`**, loaded before `trenches.js`. Exposes `window.TB_DEP.gradeOf(ca)`.
- The dot, from the 127,711-launch study in [[pullback-comeback]]: **green** deployer >=3% of its finished launches went 10x · **blue** brand new deployer, under 5 finished launches (4.93%, fine, better than a mediocre one) · **amber** 0.5-3% · **red** <=0.5%, has never made a winner (0.59% 10x, 68% straight to zero). Chain base rate is 2.75%. Tooltip carries the deployer address, its launch count and its exact rate.
- **Key on `contractFactory`, not `contractCreator`.** Blockscout returns both; the factory is the launchpad contract and is what Dune's `creation_traces."from"` reports, so it is what groups a pad's thousands of tokens. Fall back to the creator for a hand-deployed token.
- **The scorecard is served, not bundled, so it cannot go stale:** `http://159.223.88.168/dep_table.json` (11KB, 199 deployers), fetched once and cached 6 hours in `chrome.storage`, with the stale copy used if the fetch fails. Rebuilt nightly on the droplet by `/opt/launchwatch/deptab.py`, which now also copies it to `/opt/launchwatch/pub/`. Served by `lwserve.service` (a 12-line python `SimpleHTTPRequestHandler` on port 80, CORS open, one directory, read-only). ufw already allowed 80.
- **Never cache a failed lookup.** The first version stored `""` on failure, which would have left a token grey forever; it now retries once after 1.2s and caches only a real answer, so hovering again retries.
- Manifest 1.5.0 adds host permissions for `https://robinhoodchain.blockscout.com/*` and `http://159.223.88.168/*`.
- **Patching trap that bit twice here:** the string patcher's "already applied" guard tested a line (`"verify.js",`) that was always present, so it silently skipped adding `deployer.js` and reported success. **Edit `manifest.json` by loading the JSON and mutating the object, never by string matching**, and make any skip-guard test something unique to the NEW content.
- Verified end to end against live tokens: PHOOD green (139 launches, 19.4%), WATCH amber (51,123 launches, 2.7%), AI amber (1,916, 2.1%), CNPY blue (new deployer), PONS amber. **Note AI reads amber: the pad that made the chain's biggest coin is below average per launch, which is the point of the flag.**
- Still needs Ben's two clicks: the extension reload arrow in chrome://extensions, then a page reload.

## v1.6.0, CLICK TO SELECT, and the lookup failure was self-inflicted, 5 Sep 2026
[stated] Ben, with a screenshot of every dot grey and "deployer lookup failed (Blockscout busy)": "let's not do hover. Let's do it so that when I click on a line, it then selects that line... and then you start the lookup. Something needs to be fixed here with the lookup anyway."
- **ROOT CAUSE, and it was mine.** `decorate()` called `paintDot()` on every row, so loading the tape fired ~150 Blockscout requests inside one second and every one 429'd. Hover then fired another per row as the mouse moved down the list. Blockscout was never the problem. **Proved by re-testing one at a time with a 6s gap: PHOOD 3.5s, COCO 2.6s, PONS 1.8s, zero failures, all correct.** COCO had failed under the stampede and resolves fine alone.
- **RULE, general: never fire a per-row network call from a row-decorating function on a live tape.** 150 rows on load plus a prepend every second is a self-DDoS. Make it on-demand, and put a queue in front of it anyway.
- **Now: nothing looks anything up on its own.** No fire on decorate, no fire on hover. Clicking a row selects it (grey `tr.tb-sel` background plus a blue inset bar) and THAT starts the one lookup. Clicking the same row again deselects. The dot pulses grey while it waits.
- A queue in `deployer.js` caps it at **2 concurrent lookups, 250ms apart**, so even a burst of clicks cannot stampede again.
- **Second Blockscout route added as a fallback:** `/api/v2/addresses/{ca}` returns `creator_address_hash` and answers when `getcontractcreation` is busy; it returned the same factory address for factory-made tokens in testing. Three attempts, alternating routes, backing off 0.9s then 1.8s.
- Answers cached in a `dotKnown` Map per page and in `chrome.storage` across sessions, so a re-click or a repeat token is instant and free.

## Related judgement worth repeating to him once, not twice
[[unipcs-worldview]] records unipcs saying plainly: *"i'm not sure it is a good idea to be copytrading me on fomo... my fomo wallet is a degen wallet... i'll buy and sell as i please, with or without a thesis or disclosure."* And he has no exit rule at all, by his own admission. Say it once when a tail is built on him; do not repeat it every session.

## Why the last click stays his
Claude does not execute trades or transfers, and does not take custody of or handle a private key or a trading API key. Building a macro whose whole purpose is to press Buy is the same thing as executing the trade. The honest maximum is: remove every second of friction BEFORE the buy, and leave the irreversible click to Ben. He was told this in one line, without a lecture.

## v1.7.0, the verifier was WRONG and is now rebuilt. 6 Sep 2026. READ THIS BEFORE TOUCHING verify.js
[stated] Ben, with three screenshots: fomo shows unipcs's PAIRCAT as "Received from external wallet" while the tape flagged only 2 of his 3 PAIRCAT rows. "a lot of fake buys are being categorized as real buys. Find out why you mischaracterize these. And then fix it." He was right. v1 passed a plant.

**The chain facts that overturn everything v1 assumed, measured on 95 transactions across two wallets:**
- **fomo is CUSTODIAL.** The trader's cash never leaves his on-chain wallet. His USDG is held at `0x4cd00e387622c35bddb9b4c962c136462338bc31` and paid out of fomo's funding wallet `0xf70da97812cb96acdf810712aa562db8dfa3dbef`. So **"money left his wallet" is FALSE on every genuine buy** and must never be used as a test.
- **He does not sign his own buys either.** His own actions (sells, unwraps) go through ERC-4337 EntryPoint `0x4337084d9e255ff0702461cf8895ce9e3b5ff108`, signed by rotating `0x4337...` bundler keys. His BUYS carry no UserOperation of his at all. So **`tx.from === wallet` is FALSE on every genuine buy** and must never be used as a test either. Both of these were the obvious fixes and both are wrong.
- **A plant has a real cash leg.** A stranger sends his OWN native ether to relay `0xb92fe925dc43a0ecde6c8b1a2709c170ec4fff4f`, the relay swaps it through the v4 PoolManager, then forwards the token to the famous trader. Real money moved through a real pool. It just was not the trader's money. **That is exactly what v1's "is there a cash leg anywhere in this tx" test rewarded.**

**The two tests that actually separate them, both address-light and both verified:**
- **A. `tx.value` must be 0.** Every genuine fill is settled in tokens from fomo's funder with zero native value attached. Every plant attaches 0.004 to 1.0 ether. This single line kills all three PAIRCAT plants including `0xc86e7acbe87606b39f6e87239168c8e791639160060e9587d98cba5aab10082d`, the one v1 called REAL at $13.97 off a stray WETH leg.
- **B. it must be a real fill**: `tx.to` is a known fomo router (`0xccc88a9d1b4ed6b0eaba998850414b24f1c315be`) OR the receipt contains a log from the v4 PoolManager `0x8366a39cc670b4001a1121b8f6a443a643e40951`. Bulk airdrop batches through multicall3 `0xca11bde05977b3631167028862be2a173976ca11` have neither, and they **bundle a USDG transfer alongside the gift**, which is the second way v1 was fooled.
- Keep BOTH. The router test alone matched all 95 cases but is one redeploy from breaking; the swap test alone misses bonding-curve fills (3 of Ben's real buys have no v4 swap because the token had not graduated).
- Also fixed: a USDG or WETH row could price itself off its own delivery leg, and a pool quoted in a tokenized stock (SPY, GLD, NVDA) was called an airdrop. Those now return `ok:true, unpriced:true` and the caller falls back to the tape's size instead of dropping a big buy to the small ticket.

**Ground truth used, keep these as the regression suite (12/12 passing, 319-558ms on Ben's machine):**
| case | tx | expect |
|---|---|---|
| Ben real buy | 0x50d05791408ea40d283b0e224dee859f8715c7c50bc6bbba5f23717549de4ad6 | REAL $167.15 |
| Ben bonding-curve buy, no v4 swap | 0x6f8f81476727c18a6220b5e08722d3173c0f8c6debc35335aa69a67e0396e5a2 | REAL $18.88 |
| Ben PAIRCAT buy | 0x556daa5caff8259432a1e4d5df6c9b2bf92910683459545dd693f6c6c79eed5e | REAL $97.56 |
| Ben gift | 0x4f4f7dcf18e9390d874eff8e6ac0dbe364ecc90f4f2e0208adaef56119b7264b | FAKE |
| unipcs STONK, his ONE real buy | 0x6407d65442a86eed6418477440a025bfde47df2a2f448d7a940258fb93eb7ebf | REAL $98.43 |
| unipcs PAIRCAT plant 1 | 0x41132dd4a37488759691f4eb46640500ff4c4e5d87f5f042835114725e172f08 | FAKE |
| unipcs PAIRCAT plant 2, v1's false positive | 0xc86e7acbe87606b39f6e87239168c8e791639160060e9587d98cba5aab10082d | FAKE |
| unipcs PAIRCAT plant 3 | 0xcb050b5af00168ef5c98a1b22f2c9725e6ecd1c79ab3b5d5e8763fc8d474ad39 | FAKE |
| unipcs WOLF plant | 0x097c625fcd1dc491a7dfd1ba61974afe44389697e9916f663647b84c6570322a | FAKE |
| unipcs GLD airdrop batch | 0x6469081307c3f6fd0f5ab2051f6b8a3a3ae68fd238829b82e4673ac7e6746328 | FAKE |
| unipcs NVDA airdrop batch | 0x7d501070fbeb9dd0622574190addb8ccf98d0c967eeeb012db098751b1b2ab6c | FAKE |
| unipcs USDG airdrop, self-price trap | 0x9866ebdacf9f743c4a02d4c15463fde7b5d9cb14c36cf6c27928b41bccafb34c | FAKE |

**The scale of the problem, which is the real headline for Ben:** of unipcs's 62 token deliveries in the last ~3 hours, **61 are plants or airdrops and 1 is a real buy.** Ben's own wallet in the same period: 20 real buys, 13 gifts. So a tape filtered to unipcs is roughly 98% noise, and both the site's flag and v1 were passing a large share of it.

**The earlier "LIVE TEST OF THE VERIFIER" table in this file is not trustworthy.** It says v1 "agreed with the tape every time", but v1 and the tape were reading the same wrong signal, so agreement proved nothing. Treat the unipcs ROBO $199.87 and BEE $22.96 rows there as unverified, not as confirmed real buys.

**Reusable rule, general, this cost a full session twice now:** when a verifier and the thing it is checking agree, that is not validation. Validation is finding a case where they must disagree. Here it meant pulling a wallet whose real buys are known independently (Ben's own, cross-checked by which tokens he later sold) and confirming the rule keeps those while killing the plants.

Files changed on his Mac: `verify.js` rewritten (v1 kept as `verify.v1.bak.js`), `trenches.js` tailFire and banner handle `unpriced`, `manifest.json` -> 1.7.0. Both `node --check` clean. **Still needs his two clicks: the reload arrow in chrome://extensions, then a page reload.**
