Rugs

How the night's three rugs and the earlier two could have been refused before the buy, what is live now, and the ceiling sweep.

Lane report · REPORT-rugs.md · updated 06/09/2026 07:46:31

Worker: analysis-rugs. Brief: analysis-2026-09-06/BRIEF-rugs.md. Written 2026-09-06 07:46 Beirut. All times UTC unless marked +03.

TLDR

  1. The deployer deny list Thomas asked for would not have worked. ZEP, PEZZED and PEZ were deployed by three different fresh EOAs (0x7d1bcd…, 0x62443b…, 0x30a3a6…), each a direct contract-creation, each with 7 to 8 lifetime transactions. Banning ZEP's deployer at 03:25 +03 would have stopped nothing at 04:23 or 05:06.
  2. The signalling wallet was the common thread, and we already had its rap sheet. data/watchtower/smartmoney.json carried frankdegods: entries 39, rugs 6 (15.4%) with lastTs 2026-09-06T00:00:22Z, twenty-five minutes before the ZEP signal. research/smartmoney/FOLLOW-LIST.json graded it verdict: "watch". Nothing in executor/follower.mjs filterSignal() reads either field. That is the single cheapest fix on the table: zero RPC calls, one config key.
  3. Four independent pre-buy tells each catch all three of the night's rugs with zero false positives across 36 controls on the debrief tape: pool quote asset is WETH not native ETH; liq/mcap >= 0.85 at signal time at any age; pre-entry sells/buys under 0.30; token bytecode is a hand-written 8.7 KB ERC20 with owner + maxTx instead of the 3248 / 181 / 44 byte launchpad shapes. Scorecard in finding 3.
  4. These were honeypots, not only LP pulls. At 01:35 on PEZZED and 02:13 on PEZ the follower fired a real clip_target at about +60% and the sell reverted TransferHelper: TRANSFER_FROM_FAILED, once explicitly "Blocked: cannot sell" (data/executor/follower.log). The LP drain came after. No exit rule can beat a contract that refuses to sell, so the money is won or lost at the pre-buy gate.
  5. The existing rugRatio guard already worked, it was just scoped too narrowly. It refused PEZZEL (0.93 at 10 min) and PENZ (0.94 at 9 min) that same night. ZEP (0.895 at 12 min), PEZZED (0.862 at 14 min) and PEZ (0.873 at 16 min) slipped through only because underAgeMin: 10 switches the guard off past ten minutes.
  6. The in-position layer cannot save a hard pull, it can only stop the lying. ZEP's pool went dead about 7 minutes after our fill and we marked it at +18% off dexscreener for 2 h 20 m. A PoolManager liquidity watch buys truth and a fast write-off, not money.
  7. Sample honesty: five rugs total (ZEP, PEZZED, PEZ, SEPE, CYBERDOG), three of them one family from one wallet in three hours. Every "zero false positives" below is against 36 controls on one tape. These are strong candidates, not laws.

1. Deployer genealogy

Method: Blockscout api/v2 and api are both Cloudflare-challenged from this box right now (HTTP 403, verified twice on both endpoints at 07:36 and 07:38 +03), so the address-history route in the brief was unavailable. Instead each token's first Transfer from the zero address was located with eth_getLogs on the public RPC and the minting transaction's from and to read back. Note for anyone reusing this: the Transfer topic on Robinhood Chain is 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, not the canonical …b68c….

token outcome mint block deployer EOA mint tx to deployer nonce now deployer bal now
ZEP rug 55540398 0x7d1bcd19f1b9900a0ba21f8aba069982dfcc5ddd null (raw creation) 7 0.00040 ETH
PEZZED rug 55573589 0x62443ba303206ccbb1a0cefdd9315c08e46f3913 null (raw creation) 7 0.00041 ETH
PEZ rug 55598049 0x30a3a65bb0e022530aad7fe3e874f8bf4743c2e3 null (raw creation) 8 0.00003 ETH
SEPE rug 54746143 0xeae350215fb186ddf26d280bb713b34c2a348ec9 0xefd94948… (factory) 30 0.00001 ETH
CYBERDOG rug 54363123 0xa8189779f819b34cf75153cce2d400ff7c0c45a5 0xdb3d02bf… (factory) 41 0.00001 ETH
LIQLORACLE +551% 55563380 0xabe3de2c52bd3ebe03aaa0a641872adc4a38b78a 0x22e99278… (factory) 20 0.128 ETH
hoodrat +65% 55376942 0xe2f5cae53f2e23651d8ff0ae434ea21b386c3624 0xb2a748f6… (factory) 4 0.408 ETH
BUSINESS +17% 55433560 0x2857bbe641c37fa9f5ad9cfde029fd04b92a9371 0x22e99278… (factory) 28 0.00305 ETH

Source: analysis-2026-09-06/data/rugs/mints-out.txt, deployer-nonces.txt.

Reads:

Rug rate over the whole tracked cohort, from the same file (analysis-2026-09-06/data/rugs/smartmoney-rugs.txt, wallets with 5+ entries):

handle entries rugs rate what it gave us on this tape
loganlim_x 5 2 0.400 nothing followed
seralberttrades 11 3 0.273 AJC -63%, PETOI -71%, Uranus -22%
Rowdy 25 6 0.240 nothing followed
fr3ak 12 2 0.167 hoodrat +65%, MADETEST -54%, MUPPETS -49%, Culio -98%
frankdegods 39 6 0.154 ZEP, PEZZED, PEZ (-$150), RF +194% (Wide set)
iruletrenches 10 0 0.000 BODKIN +196%
NotARandomUser 9 0 0.000 DOOKIE -58%
picadura 7 0 0.000 LIQLORACLE +551% paper, +$128.86 live

A maxWalletRugRate gate at 0.15 refuses frankdegods, seralberttrades, fr3ak, Rowdy, loganlim_x, Binkieee, elliotrades and about fifteen more. On this tape that costs hoodrat (+65%) and RF (+194%, Wide set, not live money) and saves the three rugs plus AJC, PETOI, Uranus, MADETEST, MUPPETS, Culio. On live Gold v2 dollars it is clearly positive; on paper Wide it is not.


2. Pre-buy tells, scored

Every tell below was computed from what was on disk at or before our entry timestamp: data/watchtower/feed.jsonl fields at signal time, and debriefs/<call>/swaps.jsonl truncated at metrics.json entryTs. 41 debriefed calls, 5 of them rugs. Full table: analysis-2026-09-06/data/rugs/tell-scorecard.txt.

tell fires on rugs caught false positives
pre-entry sells/buys < 0.30, at least 30 pre-entry swaps 3 3/5 0
pool quote asset is WETH (0x0bd7d308f8…) not native ETH 3 3/5 0
liq/mcap >= 0.85 at signal, any age 3 3/5 0
liq/mcap >= 0.80 at signal, any age 3 3/5 0
bytecode has owner() + maxTxAmount() selectors 3 3/4 scanned 0
bytecode has owner() alone 4 3/4 scanned 1 (Viagra)

The three that all four tells catch are ZEP, PEZZED and PEZ. None of the four catches SEPE or CYBERDOG, which were 181-byte launchpad clones on native-ETH pools with ordinary two-sided flow. SEPE has its own tell and it is already shipped (liq/mcap 1.599 at 3 minutes).

2a. Pre-entry sell flow is the sharpest number on the tape

token pre-entry swaps buys sells sells/buys
PEZ 74 70 4 0.057
PEZZED 100 91 9 0.099
ZEP 129 117 12 0.103
lowest control: MILADY 885 505 380 0.752
next: BBM 507 289 218 0.754
next: ELFIE 3906 2225 1681 0.756
median of 36 controls ~0.95

The gap is 7x, not marginal. Thomas's note ("163 buys / 4 sells in h1 on PEZ") generalises: on a real launch roughly as many wallets sell as buy in the first minutes; on this family almost nobody sold, because almost nobody could. A threshold anywhere between 0.25 and 0.60 separates them cleanly on this tape. 0.30 with a 30-swap minimum is the conservative pick.

Second-order signal in the same numbers: the rugs are thin. 74 to 129 pre-entry swaps against 900 to 14,000 on the controls. Absolute swap count alone is not clean enough to use (Launch had 23, TERROR 8, SNOO 75, all honest), but combined with the sell ratio it is the same fingerprint.

2b. Liquidity to market cap, freed from the ten-minute window

The guard exists (executor/follower.json filters.rugRatio: { maxLiqToMcap: 0.8, underAgeMin: 10 }) and it worked. From data/watchtower/feed.jsonl:

token age at signal liq/mcap verdict that night
PENZ 9 min 0.941 refused, "liquidity is 0.94x the market cap on a 9m old pool"
PEZZEL 10 min 0.929 refused, "liquidity is 0.93x the market cap on a 10m old pool"
ZEP 12 min 0.895 bought, guard off past 10 min
PEZ 16 min 0.873 bought, guard off past 10 min
PEZZED 14 min 0.862 bought, guard off past 10 min
LIQLORACLE (+551%) 7 min 0.754 bought, correct
BUSINESS (+17%) 6 min 0.793 bought, correct
AJC 20 min 0.331 bought
hoodrat (+65%) 4 min 0.169 bought
MADETEST 7.5 min 0.166 bought

The whole family sits in a band, 0.86 to 0.94, and the best control on the tape sits at 0.793. Raising underAgeMin from 10 to 60 (i.e. applying the ratio across the follower's entire 2 to 60 minute age window) and holding maxLiqToMcap at 0.80 refuses all five family tokens and nothing else in the feed rows I checked. The nearest control, BUSINESS at 0.793, survives by 0.007, which is uncomfortably tight, so 0.85 is the safer number and still catches all five.

2c. Quote asset and contract shape

Every token on the debrief tape resolves to one of three bytecode shapes (analysis-2026-09-06/data/rugs/bytecode-tells.txt):

shape bytes count what it is rugs
launchpad token A 3248 26 standard clone, only burn() exposed 0
launchpad token B 44 to 283 11 minimal proxy SEPE, CYBERDOG
hand-written ERC20 8722 to 8777 3 owner, renounceOwnership, maxTxAmount, OZ 4.x revert strings, PEZ embeds the string ipez.family ZEP, PEZZED, PEZ
one-off 7003 1 Viagra, owner + burn, honest 0

And the quote asset: 16 of the 41 pools quote in native ETH, 22 in assorted quote tokens (USDG, PONS, SLV, ETH-wrappers and others), and exactly three quote in WETH 0x0bd7d308f8e1639fab988df18a8011f41eacad73: ZEP, PEZZED, PEZ. The WETH quote is also why the sell path had no route at all on the night, since the v4 sell leg assumed native-ETH pools until the 05:29 UNWRAP_WETH work. Two problems with one root.

Honest caveat on both: these three tokens came from one operator on one night. "WETH-quoted" and "8.7 KB owner contract" may be that operator's habits rather than a rug law. They are cheap enough to run as soft signals (log and alert) before they become hard refusals.

2d. Tells I could not test


3. What the follower actually did

From data/executor/follower.log and data/executor/follower-fills.jsonl.

ZEP PEZZED PEZ
signal 00:25:46 01:23:08 02:06:27
live buy 00:25:57 01:23:21 02:06:44
first failed exit 04:55 +03 = 01:55, time_stop 01:35, clip_target reverted TRANSFER_FROM_FAILED 02:13, clip_target reverted TRANSFER_FROM_FAILED
first "no aggregator route to mark" 00:33 01:38 02:24
paper book liquidity_pulled 00:34:17 01:38 02:25
write-off 02:54:32 02:54:33 02:54:37
dead lot carried 2 h 20 m 1 h 16 m 0 h 30 m
failed exit attempts logged 248 344 (+27 requotes) 166 (+87 requotes)

Four things fall out.

  1. The clip_target reverts are the story. On PEZZED at 01:35 and PEZ at 02:13 the ladder did exactly the right thing, fired a 50% clip at about +60%, and the token refused: TransferHelper: TRANSFER_FROM_FAILED, and once at 01:37 the unambiguous "Blocked: cannot sell". Sells worked earlier (12 sells in ZEP's pre-entry tape, 9 in PEZZED's), so this is a delayed honeypot: the owner flips a flag once enough buyers are in. That also means a pre-buy sell simulation would have passed at signal time and would not have saved these three. Worth building anyway for the static-honeypot case, but do not sell it as the fix for this family.
  2. ZEP's 90-minute time stop was never late. The open question in memory/2026-09-06.md ("why 04:55 and not 01:55") is a timezone artifact: the buy was 00:25:57 UTC = 03:25 +03, and the stop fired at 01:55 UTC = 04:55 +03, exactly 90 minutes later. No ladder bug. Closing that question.
  3. The marking was the real damage. From 00:33 the follower logged ZEP: no aggregator route to mark …, marking off the dexscreener mid $0.000001094 until one comes back and kept the lot at +18% for 2 h 20 m. The stop loss could never trigger because the mark never went down. The 05:29 v4PoolDrained fix addresses exactly this and would have cut ZEP's dead hold from 140 minutes to about 1 minute.
  4. A liquidity-drop watch would have told the truth, not saved the money. The quote reserve on all three pools never fell in the swap tape: ZEP qRes ends at 26.647, which is also its maximum; PEZZED ends at its maximum 34.603; PEZ at 41.499 (analysis-2026-09-06/data/rugs/preentry-tells.txt). An LP burn is not a swap, so it is invisible to the swap feed by construction, and by the time v4PoolLiquidityById reads zero there is nothing to sell into. A "liquidity below 50% of entry" watch is worth building for the gradual drain case and for honest marking, but on this family it arrives after the door is shut. Only the pre-buy gate saves money here.

Recommendations

Ship now (config only, reversible)

  1. filters.rugRatio.underAgeMin: 10 -> 60 and maxLiqToMcap: 0.8 -> 0.85 in executor/follower.json (mirror in watchtower/rules-v2.json Gold v2, the two must move together per fixes-2026-09-05/FIELDS.md). Refuses ZEP, PEZZED, PEZ, PEZZEL, PENZ, SEPE. Refuses nothing else in the feed rows checked. Cost: zero RPC, zero latency, the field is already on every feed row. This is the highest value single line in the report.
  2. Extend filters.handlesDeny beyond frankdegods with the wallets whose prior rug rate is at or above 0.15 and that have signalled us: seralberttrades, fr3ak, Rowdy, loganlim_x, Binkieee. On this tape that gives up hoodrat (+$43.23 realised across two clips and a trail) and blocks AJC (-$26.40), PETOI, Uranus, MADETEST, MUPPETS and Culio. Net positive on live dollars, but it is a static list and it will go stale, so treat it as a bridge to item 4 below.
  3. Leave burnedWalletHours: 24 alone. It is correct and it was shipped at 05:29. Note only that it is a post-loss rule: it cannot fire until one lot has already been written off, and on the night it would have fired only after ZEP's write-off at 02:54, by which point PEZZED and PEZ were already bought. It is a floor, not a fix.

Build (code, with the test that proves it)

  1. walletRugRate filter in executor/follower.mjs. New check inside filterSignal() (executor/follower.mjs:203), placed next to the existing handlesDeny block at line 253. Reads the wallet row out of data/watchtower/smartmoney.json (already on disk, already refreshed by the watchtower, no new feed), computes rugs / entries, refuses when entries >= cfg.filters.minWalletEntriesForRugRate (default 8) and the rate is at or above cfg.filters.maxWalletRugRate (default 0.15). Refusal string: wallet <handle> has rugged 6 of 39 tracked entries (15%), over the 15% ceiling. Test: executor/test-follower.mjs, new group asserting (a) frankdegods at 6/39 is refused, (b) picadura at 0/7 passes, (c) a wallet with 3 entries and 1 rug passes because it is under the entries floor, (d) a missing smartmoney row passes rather than blocking the book. This is the check that would have refused all three lots at 00:25, 01:23 and 02:06 with no on-chain call and no added latency.
  2. sellFlowSkip filter, same function. Refuse when the pre-entry tape has at least 30 swaps and fewer than 0.30 sells per buy. The counts are not on the feed row today; the collector that writes data/watchtower/feed.jsonl already walks the pool's swaps to compute runH1Pct, so add preBuys and preSells there and read them in filterSignal(). Test: executor/test-follower.mjs fixture rows for PEZ (70/4, refused), ZEP (117/12, refused), MILADY (505/380, passes), Launch (12/11 on 23 swaps, passes because under the swap floor).
  3. Record the swap sender. Add the sender/origin address to each row of debriefs/*/swaps.jsonl and to whatever the collector persists. Without it, deployer-share-of-buys, unique-buyer counts and one-funder clusters, three of the tells the brief asked for, are permanently uncomputable. This is the single biggest data gap in the rug work.
  4. Pre-buy quote-asset and bytecode probe, log-only first. In executor/routes.mjs, v4PoolKey() (line 259) already resolves the pool's counter currency before every buy, so flagging "counter is WETH, not native" is free. Add one eth_getCode on the token (about 40 ms, one Alchemy call) and flag owner()+maxTxAmount() selectors and code length over 8000 bytes. Ship these as alerts, not refusals, for a week, then score them. n=3 does not earn a hard gate. Test: executor/test-univ4.mjs, and note the group-2 CYBERDOG fixture is stale (delisted) and needs replacing regardless.
  5. Liquidity-drop watch in the mark loop. executor/follower.mjs mark step 3 already calls v4PoolDrained when the simulate fails. Extend it to a ratio: record entryLiquidity from routes.mjs v4PoolLiquidityById(poolId) at fill time, and on every mark cycle exit at market when live liquidity is under 50% of it. Test: executor/test-follower.mjs with a stubbed v4PoolLiquidityById returning entry, 0.6x (hold), 0.4x (exit), 0 (write-off). Be honest about what it buys: on ZEP, PEZZED and PEZ it buys a truthful mark and a 1-minute write-off instead of a 2 h 20 m fiction. It does not buy dollars back.
  6. Automatic deny-list feeding. On every liquidity_pulled close, append the signalling wallet and the token's deployer EOA (resolvable with the same mint-log lookup used here, two RPC calls) to a data/executor/rug-wallets.json file that filterSignal() reads. Deployer entries will rarely fire twice, per finding 1, but they cost nothing and they are the only way a genuine repeat deployer ever gets caught.

Needs Thomas

  1. An indexer with address history. Blockscout is Cloudflare-blocked from this box on both /api and /api/v2, and the public RPC serves no archive state. Without one of a Blockscout API key, an Alchemy tier with getAssetTransfers, or another Robinhood Chain indexer, we cannot answer "how many tokens has this EOA launched before" or "who funded this burner", which is the literal wording of the brief. This is also the execution lane's problem, so decide it once.
  2. Accept the cost of the wallet gate. A 0.15 rug-rate ceiling refuses roughly a quarter of the tracked cohort, including fr3ak, which produced hoodrat. Confirm you want that trade before item 4 goes live rather than log-only.

Open questions

Sources

Ceiling tuning sweep · data/tuning/SWEEP.md · updated 06/09/2026 10:40:55

Brief: analysis-2026-09-06/BRIEF-tuning.md. Script: sweep.mjs (rerunnable, node stdlib only, imports filterSignal / rugRatioSkip / liqToMcap / walletRugRateSkip from executor/follower.mjs). Full grid: sweep.json (1044 rug-gate points + 6 age points). Disk-only replay, no RPC.

Tape: data/watchtower/feed.jsonl, 1422 rows / 330 tokens, 2026-09-04T22:17Z to 2026-09-06T07:31Z.

0. Headline

# Finding
1 No setting in the grid keeps every rug out. PEZ re-signals at 02:16:54Z at age 26 min with liqToMcap 0.681, from wallets with no rug history. 0 of 1044 grid points refuse it.
2 The rug-ratio gate does all the work the wallet gate was meant to do. At underAgeMin >= 20 and maxLiqToMcap in {0.80, 0.82, 0.85} it refuses a row of all 6 rug tokens and loses zero runners.
3 The shipped maxWalletRugRate 0.15 / minWalletEntries 8 adds zero rug refusals on top of that and costs 8 of the 14 runners in the pool. minWalletEntries is the wrong number, not the rate.
4 maxLiqToMcap has a wide dead zone. Every value in [0.80, 0.85] gives the identical result. The only clean separation on the tape is runner ceiling 0.793 (BUSINESS) to rug floor 0.862 (PEZZED).
5 The "runner" label is a peak proxy, not money. The 8 runners the shipped gate blocks sum to -50.18 Gold v2 paper and +16.83 live. Losing them is close to free.

1. Method and universe

Pool. "Rows Gold v2 would otherwise have taken" is built by running the live filterSignal with the three gates this sweep moves (maxAgeMin, rugRatio, maxWalletRugRate) switched off, and every gate it does not move left on: band in {under 250k, 250k to 1M}, minAgeMin 2, liquidity 25k-400k, maxMcapUsd with the 2h / 3M fresh exemption, minBuyUsd 100 (measured receipts only), maxOtherCohortWallets 1, maxRunH1Pct 500. entry.cooldownMinPerToken 120 is applied in time order so a token cannot be counted eight times. handlesDeny is emptied for the replay, because the static frankdegods entry is exactly the thing the wallet rule is meant to replace. Two Gold v2 gates are not reconstructible from disk and are not applied: entry.maxChasePct (needs the live exec quote at signal time) and universe.maxSignalAgeSec (a liveness check, satisfied by construction when the row was written).

Set Rows Tokens rug runner flat unknown
Whole feed 1422 330 12 34 56 228
Pool (age ceiling 60) 60 41 6 14 8 13
Pool (no age ceiling, for the age sweep) 671 153 - - - -

Rug tokens in the pool: SEPE, ZEP, PEZZEL, PEZZED, PEZ, PENZ. Runner tokens: AJC, BODKIN, BUSINESS, CLANKSEN, Culio, ETHOSIS, LIQLORACLE, MADETEST, MUPPETS, PETOI, PasDePanique, RF, ROBBING, hoodrat.

No-outcome rows. 13 of 41 pool tokens (17 of 60 pool rows) have no book, no debrief and no fill, so no label. They are counted in every "rows refused" column and excluded from every rate. On the whole feed the figure is 228 of 330 tokens, which is why every rate below is quoted against the pool, not the feed.

Money. Credited once per token, on its first refused row. paperG2 is the Gold v2 book close (pnlUsd summed over closes); paperAny falls back to the widest v2 book for tokens that predate the Gold v2 set (created 2026-09-05T07:42Z), so it mixes sets and is the weaker column; live sums follower-fills.jsonl sell and writeoff pnlUsd. Sign convention throughout: negative = refusing that row saved money, positive = refusing forwent money.

2. The decisive rows

Every rug and every near-line runner in the pool, with the two numbers the gates read:

Label Symbol ts ageMin liqToMcap peak% handle paperG2 live
rug SEPE 09-05 02:01Z 3 1.599 3.1 6 handles - -50.00
rug ZEP 09-06 00:25Z 12 0.895 18.6 frankdegods -50.00 -50.00
rug PEZZEL 09-06 00:46Z 10 0.929 81.7 frankdegods - -
rug PEZZED 09-06 01:23Z 14 0.862 70.0 frankdegods -11.07 -50.00
rug PEZ 09-06 02:06Z 16 0.873 144.2 frankdegods -8.64 -50.00
rug PEZ (2nd) 09-06 02:16Z 26 0.681 144.2 AvgJoesCrypto, RugDalio - -
rug PENZ 09-06 02:39Z 9 0.941 322.5 frankdegods - -
runner BUSINESS 09-05 6 0.793 77.0 lilbro +8.61 -
runner LIQLORACLE 09-05 7 0.754 2296.4 picadura +275.67 +128.86

Reading the table: the rug-ratio gate has a clean window of 0.793 to 0.862 and an age window whose binding rug is PEZ at 16 min. Everything else in the grid is noise around those two numbers.

The PEZ hole. At 02:16:54Z the LP had topped the pool up, so PEZ came back at liqToMcap 0.681, ten minutes after the 02:06 signal, from @AvgJoesCrypto (7 entries, 1 rug, 0.143) and @RugDalio (no rug row in smartmoney.json at all, so no rate to test). 0.681 is under every maxLiqToMcap in the grid and both wallets are under every maxWalletRugRate. In the replay that row is always taken, so takenLabels.rug is 1 at all 1044 grid points. Live this did not happen, because the 02:06 buy set the per-token cooldown; in the replay the 02:06 row is refused, which re-opens 02:16. That is the honest shape of the risk: the ceiling gates buy a first-signal veto, not immunity, and a rug that reloads its pool walks back in through the front door.

3. Pareto front

Settings that refuse a row of all 6 rug tokens, ordered by runners lost then Gold v2 paper forgone. 772 of the 1044 grid points refuse all 6. To keep every number exact, the table is pinned at underAgeMin 60, the shipped value (20, 30 and 45 give the same runner and money columns; only the unknown-token counts move by one). At 60, 157 of the 174 points refuse all 6 and collapse to 35 outcome classes; the front and the notable classes below it are:

Class ratio wrate@min (all equivalent) Runners lost Names flat unk rows refused tokens taken paperG2 paperAny live
1 0.80, 0.82, 0.85 off, 0.18@15, 0.20@15, 0.25@15, 0.30@8, 0.30@10, 0.30@15 0 - 0 4 16 32 -69.71 -15.25 -200.00
2 0.80, 0.82, 0.85 0.30@5 0 - 0 5 17 32 -69.71 -15.25 -200.00
3 0.80, 0.82, 0.85 0.10@15, 0.12@15, 0.15@15 1 RF 1 6 20 28 -69.71 +49.36 -200.00
4 0.90 0.10@15, 0.12@15, 0.15@15 1 RF 1 5 19 29 -69.71 +49.36 -200.00
5 0.78 off, 0.18@15, 0.20@15, 0.25@15, 0.30@8+ 1 BUSINESS 0 4 17 31 -61.10 +2.77 -200.00
7 0.80, 0.82, 0.85 0.18@10, 0.20@10, 0.25@10 2 AJC, PETOI 1 4 19 30 -101.01 -106.23 -226.40
8 0.78 0.10@15, 0.12@15, 0.15@15 2 BUSINESS, RF 1 6 21 27 -61.10 +67.38 -200.00
9 0.75 off, 0.18@15, 0.20@15, 0.25@15, 0.30@8+ 2 BUSINESS, LIQLORACLE 0 4 19 30 +214.57 +278.44 -71.14
11 0.80, 0.82, 0.85 0.18@5, 0.20@5, 0.25@5 3 AJC, PETOI, PasDePanique 1 6 22 30 -101.01 -134.45 -226.40
12 0.80, 0.82, 0.85 0.18@8, 0.20@8, 0.25@8 3 AJC, PETOI, PasDePanique 1 5 21 30 -101.01 -134.45 -226.40
13 0.78 0.18@10, 0.20@10, 0.25@10 3 AJC, BUSINESS, PETOI 1 4 20 29 -92.40 -88.21 -226.40
17 0.75 0.18@10, 0.20@10, 0.25@10 4 AJC, BUSINESS, LIQLORACLE, PETOI 1 4 22 28 +183.27 +187.46 -97.54
20 0.80, 0.82, 0.85 0.10@10, 0.12@10, 0.15@10 7 AJC, Culio, MADETEST, MUPPETS, PETOI, RF, hoodrat 2 6 27 23 -119.89 -27.15 -183.17
23 0.80, 0.82, 0.85 0.10@8, 0.12@8, 0.15@8 (the shipped config) 8 AJC, Culio, MADETEST, MUPPETS, PETOI, PasDePanique, RF, hoodrat 2 7 30 22 -119.89 -55.37 -183.17
33 0.75 0.10@5, 0.12@5 10 + BUSINESS, LIQLORACLE 2 8 35 20 +164.39 +238.32 -54.31

Class 1 is the tip: it is the only class that refuses every rug token without touching a single runner. Class 7 is the money-best point on live and on Gold v2 paper. The shipped config sits at class 23, eight runners deep into the front, buying nothing over class 1 in rug coverage and taking only 22 of the pool's 41 tokens.

Reference points side by side:

Config rugs refused runners lost rows refused tokens taken paperG2 live
Baseline before today (10 / 0.80 / no wallet gate) 3 of 6 0 12 35 0.00 -50.00
Shipped this morning (60 / 0.85 / 0.15@8) 6 of 6 8 30 22 -119.89 -183.17
Ratio only (60 / 0.82 / off) 6 of 6 0 16 32 -69.71 -200.00
Conservative (60 / 0.82 / 0.15@15) 6 of 6 1 (RF) 20 28 -69.71 -200.00
Recommended (60 / 0.82 / 0.18@10) 6 of 6 2 (AJC, PETOI) 19 30 -101.01 -226.40

Every row of this table still takes PEZ once, on its 02:16Z re-signal. See section 2.

4. Recommendation

filters.rugRatio.underAgeMin           60      (keep as shipped)
filters.rugRatio.maxLiqToMcap          0.82    (from 0.85)
filters.maxWalletRugRate               0.18    (from 0.15)
filters.minWalletEntriesForRugRate     10      (from 8)
filters.maxAgeMin                      60      (keep)

The age half of the rug-ratio gate is the lever that actually catches rugs and it is free: underAgeMin 10 catches 3 of 6, 15 catches 5 of 6, and 20 catches all 6, after which 30, 45 and 60 are byte-identical because no runner in the pool has a liqToMcap above 0.793 at any age. Keeping the shipped 60 buys 44 minutes of margin over PEZ at 16 min for nothing, so keep it. The ratio half is a dead zone: 0.80, 0.82 and 0.85 produce exactly the same refusals, the same runners and the same dollars, so the choice is pure margin geometry, and 0.82 is the only value that centres the one clean separation the tape gives us. Nearest miss below the line is BUSINESS at 0.793 (peak 77%, +8.61 Gold v2 paper), 3.3% under 0.82; nearest miss above is PEZZED at 0.862 (-50.00 live), 5.1% over. Shipped 0.85 leaves PEZZED only 1.4% of headroom, and 0.80 leaves BUSINESS only 0.9%; with 6 rugs and 14 runners neither tail is estimated well enough to justify sitting on either edge. Going to 0.78 starts costing BUSINESS, and 0.75 costs LIQLORACLE, the tape's single best name at 0.754 (+275.67 paper, +128.86 live), which is a $128 mistake to avoid a $50 one. The wallet gate is the one place the shipped numbers are wrong: at minWalletEntries 8 a 0.15 rate is 1.2 rugs, which is indistinguishable from a clean wallet, and it costs 8 of the 14 runners for zero additional rug refusals. Moving it to 0.18 at 10 entries blocks exactly one wallet with pool rows (@seralberttrades, 3 of 3 pool tokens lost money) and hands back @fr3ak, whose pool contained hoodrat, the day's only live winner besides LIQLORACLE. Note that handlesDeny: ["frankdegods"] stays in the live config and is doing the frankdegods work regardless; at 0.18 his 0.154 rate no longer trips the dynamic rule, but all six of his rug signals are already refused by the ratio gate at 0.82/60.

If the priority is belt-and-braces over money, take 0.15@15 instead (class 2): it keeps the dynamic frankdegods block alive without the static deny list, costs only RF, and matches the money of the ratio-only setting exactly. It fails on hoodrat's cohort only because 15 entries is a high bar for a 40-wallet follow list.

5. Sensitivity, one threshold at a time

underAgeMin (ratio 0.80, wallet gate off). The whole rug story is here.

underAgeMin rugs refused rug names runners lost paperG2 live
10 3 PENZ, PEZZEL, SEPE 0 0.00 -50.00
15 5 + PEZZED, ZEP 0 -61.07 -150.00
20 6 + PEZ 0 -69.71 -200.00
30 6 same 0 -69.71 -200.00
45 6 same 0 -69.71 -200.00
60 6 same 0 -69.71 -200.00

maxLiqToMcap (under 60, wallet gate off). Flat from 0.80 to 0.85, falls off a cliff at both ends.

maxLiqToMcap rugs refused runners lost names paperG2 live
0.75 6 2 BUSINESS, LIQLORACLE +214.57 -71.14
0.78 6 1 BUSINESS -61.10 -200.00
0.80 6 0 - -69.71 -200.00
0.82 6 0 - -69.71 -200.00
0.85 6 0 - -69.71 -200.00
0.90 3 0 - 0.00 -50.00

At 0.90 the gate loses ZEP (0.895), PEZ (0.873) and PEZZED (0.862) and only holds SEPE, PEZZEL, PENZ.

maxWalletRugRate and minWalletEntries (under 20, ratio 0.80; the wallet-gate column is that gate's own attribution, on top of the ratio gate's constant 6 rugs / 0 runners).

wrate wmin extra rows refused extra rugs runners lost paperG2 of those rows live of those rows
off - 0 0 0 0.00 0.00
0.10 5 16 0 8 -50.18 +16.83
0.10 15 4 0 1 (RF) 0.00 0.00
0.12 8 14 0 8 -50.18 +16.83
0.15 8 (shipped) 14 0 8 -50.18 +16.83
0.15 10 11 0 7 -50.18 +16.83
0.15 15 4 0 1 (RF) 0.00 0.00
0.18 10 (rec) 3 0 2 -31.30 -26.40
0.18 15 0 0 0 0.00 0.00
0.20 10 3 0 2 -31.30 -26.40
0.25 10 3 0 2 -31.30 -26.40
0.30 8+ 0 0 0 0.00 0.00

The gate never adds a rug refusal once underAgeMin >= 20, because the ratio gate fires first on every rug row. minWalletEntries moves the answer far more than the rate does: 0.15 costs 8 runners at 8 entries, 7 at 10 and 1 at 15, with the rate held fixed.

maxAgeMin, one-dimensional, current Gold v2 filters otherwise (under 10, ratio 0.80, wallet gate off), against the no-age-ceiling pool of 671 rows / 153 tokens. Columns are that gate's own attribution.

maxAgeMin rows refused rugs runners lost flat unk paperG2 paperAny live
15 628 CHROME, PEZ 20 37 70 -103.58 +1409.49 -116.91
30 614 CHROME 18 33 67 -37.38 +1574.40 -15.03
45 609 CHROME 17 32 67 -12.22 +1601.87 +9.25
60 (live) 608 CHROME 17 31 67 -12.22 +1625.84 +9.25
120 602 CHROME 17 29 67 -12.22 +1774.20 +20.83
180 594 CHROME 15 27 67 -20.83 +1935.64 +20.83

The age ceiling is flat on Gold v2 between 45 and 120. Tightening 60 to 15 would have refused 20 extra rows worth -91.36 paper and -126.16 live, so on this tape it would have saved money, but it does so by refusing three more peak-60 names (AJC, CLANKSEN, PETOI) whose realised pnl was negative anyway. That is the positions lane's problem, not the entry gate's: do not move maxAgeMin on this evidence. The paperAny column is large only because it mixes non-Gold books over 123 tokens and should not be read as Gold v2 money.

6. The wallet gate at the recommended threshold

Every wallet blocked at maxWalletRugRate 0.18, minWalletEntriesForRugRate 10, with what it gave the pool. Rates are from data/watchtower/smartmoney.json as of 2026-09-06T07:33Z.

Handle entries rugs rate pool rows tokens it gave us
seralberttrades 11 3 0.273 3 MUMU (flat, peak 0, paperAny -23.97); PETOI (runner, peak 95.7%, paperAny -35.71); AJC (runner, peak 64.7%, paperG2 -31.30, live -26.40)
Binkieee 17 4 0.235 0 nothing in the pool
Rowdy 26 6 0.231 0 nothing in the pool
facap 10 2 0.200 0 nothing in the pool
FartmanSacks 10 2 0.200 0 nothing in the pool

@seralberttrades is the only blocked wallet that touched the pool, and all three of its tokens lost money: the "2 runners lost" line in the Pareto table is +26.40 live and +31.30 paper in hand.

Wallets that clear 0.18@10 but would be blocked by the shipped 0.15@8, with what blocking them costs:

Handle entries rugs rate pool rows what blocking it costs
fr3ak 12 2 0.167 7 hoodrat (peak 238.6%, live +43.23, paperG2 +32.74); MUPPETS (peak 412.6%, paperAny +59.91, paperG2 -24.41); Culio (peak 129%, paperAny -49.20); MADETEST (peak 85.1%, paperG2 -27.21); PasDePanique (peak 63.1%, paperAny -28.22); DOOKIE (flat, paperG2 -29.16); TRUMP2028 (unknown)
frankdegods 39 6 0.154 10 RF (peak 740.3%, paperAny +96.95); PENZ (rug); plus 5 rug rows the ratio gate already refuses. Statically denied in follower.json regardless
ericzhong 8 2 0.250 2 PasDePanique (peak 63.1%, paperAny -28.22); TRUMP2028 (unknown). Blocked at 8 entries, cleared at 10
Quanterty 6 1 0.167 2 BODKIN (peak 670.2%, paperG2 +97.89); SEPE (rug). Under 8 entries, so never blocked in the shipped config either
AvgJoesCrypto 7 1 0.143 3 LIQLORACLE (peak 2296.4%, paperG2 +275.67, live +128.86); SEPE and PEZ (rugs). Clears every rate in the grid

@AvgJoesCrypto is the case that should make anyone nervous about tightening this gate further: the wallet that handed us the tape's best name at +128.86 live also handed us two of the six rugs, at a 0.143 rate that no setting in the grid catches.

7. Caveats

# Caveat
1 n is tiny. 6 rugs and 14 runners in a 41-token pool, over 33 hours. Every threshold here is fitted to single observations: the ratio floor is one token (PEZZED, 0.862), the ratio ceiling is one token (BUSINESS, 0.793), the age binding is one token (PEZ, 16 min). Treat the recommendation as "do not sit on an edge", not as a calibrated number.
2 One-night family. 5 of the 6 rugs (ZEP, PEZZEL, PEZZED, PEZ, PENZ) are the same launcher on the same night, all with liqToMcap between 0.862 and 0.941 at ages 9-16 min. They are one event, not five. SEPE is the only independent rug in the pool, and its 1.599 ratio is refused by every setting including the old baseline. Effectively the whole rug-side signal is n = 1 launcher + 1 token.
3 Leakage. Wallet rug counts come from the rolling data/watchtower/smartmoney.json, which is a snapshot at 07:33Z, after the night. For the three night rugs the picture is better than feared: frankdegods' row carries lastTs 2026-09-06T00:00:22Z with entries 39 / rugs 6, i.e. the 0.154 rate was already on disk 25 minutes before the ZEP signal, and 0.154 clears 0.15, so the shipped gate genuinely would have fired live on ZEP, PEZZED and PEZ. @fr3ak (lastTs 09-05T21:24Z) and @seralberttrades (lastTs 09-05T23:09Z) are likewise pre-night. That is a fortunate coincidence of three wallets, not a general property: exact as-of-signal counts for older rows are not reconstructible from disk, so any wallet whose lastTs falls inside the window it is being graded on is leaking.
4 frankdegods sits 0.004 above the shipped line. 6/39 = 0.1538. One fewer counted rug puts him at 0.128, under 0.15, and the dynamic gate goes silent. A rate gate resting on a 0.004 margin is a deny list with extra steps.
5 The runner label is a peak proxy. peakPct >= 60 says the price went there, not that the book captured it. 8 of the 14 pool runners closed negative on Gold v2 paper. Every "runners lost" count in this document should be read next to its money columns.
6 13 of 41 pool tokens have no outcome data at all (17 of 60 rows). They are counted in the "rows refused" columns and excluded from every rate. Any of them could be a rug or a runner.
7 The replay releases cooldowns the live system held. Refusing a signal frees the per-token cooldown, so a refused token can re-signal and be taken later in the replay when it could not have been live. This is exactly how the PEZ hole in section 2 opens, and it means the refusal counts here are, if anything, optimistic about coverage.
8 maxChasePct and maxSignalAgeSec are not applied. Both need state that is not on disk. Some pool rows would have been refused live for chase or staleness, which shrinks the true pool below 60 rows.

Built 06/09/2026 22:00:01 Beirut. Source files under projects/crypto-2026-09/analysis-2026-09-06/.