# A2 v17: re-audit of fmmc5 v2 (FW Analyst 2, 6 Oct 2026, 16:02 Bangkok)

**READY FOR $20 LIVE: NO, not yet. Two small items left: (1) the dust guard is not in the code; (2) the live feed (block number + logs, which drive the stop and the pull) still runs on the public RPC only, so a 429 run can still freeze a stop. Both are about 10 lines each. When both are in, my answer is YES for $20.**

Code read: firstmin-trader 178.128.20.136 /opt/fm/fm_mc5.py, md5 2799e398434a20375be68d0e9589da42 (524 lines), against my audit http://159.223.88.168/hx-c9ois/fw/a2-fmmc5-audit.md and PP's proof http://159.223.88.168/hx-c9ois/fw/pp-mc5v2-tests.txt . No secret printed.

## The 9 items from my audit: all fixed in the code
| # | Item | In code | Proof |
|---|---|---|---|
| 1 | Mint topic | `T_MINT = 0x7a53080ba414158be7ec69b987b5fb7d07dee101fe85488f0853ae16239d0bde` (matches my keccak). Start self test blocks live until a recent pool shows a Mint; kills on fail. | Live log 15:57 SELFTEST_OK; PULL fired live on 0xcf0a781da4772012160e349215c35ee88a0ddeda (15:59) and 0xb8af113ff19154f6392ad19775719574698a190a (16:00), both 100% of in-range units. Test T2: 8 of 8. |
| 2 | Restart drops old trades | `restore()` takes every open / open_unsold / buying row at any age, plus pools inside time stop + 10 min; `buying` rows check the wallet balance. | Test T3: a 3.6 h open trade restored and closed. |
| 3 | Wallet kill on open trades | `mc5_loss()` = realised losses + open trades at their tick walk quote. | Test T4: 31% instead of 51%, no kill. |
| 4 | Slippage 30% | buy 5%, sell 10%, 30% only on pull, stop or retry (config). | Code lines 287 to 291. |
| 5 | Sell judged failed after 4 s | waits up to 30 s, one retry at 30%, then `open_unsold` + kill, retried every 60 s until gone. | Code lines 288 to 295, 502. |
| 6 | No sell fill log | sell_quote_eth, sell_fill_eth, sell_gap, stop_trigger_value, stop_slip, q_main, q_lower, side. | Code line 305. |
| 7 | Max open race | count + `buying` reservation under one lock. | Test T5: 6 at once gave 3 live. |
| 8 | 0.80 round trip filter at size | rt1k logged for every checked coin; skip only at the current size. | Code lines 356 to 360. |
| 9 | Stop math without tick crossings | exact v3 walk over the tick bitmap; used every swap when size > $200, else within 15% of the stop. | Test T1: matches SimV3 to 6 digits on 9 pools at $20 and $1k. |

Also checked: second time check before the swap (late_buy_s 345 s); the ramp keys and `ramp_now()` follow my gate spec; use_ramp is false so the size stays $20.

## Still open
1. **Dust guard (sup-to-pp v19) is missing.** No check of "a 0.001+ WETH swap before +5 min" or "pool WETH 0.1+" anywhere in `entry()`. Add before the sim: `if not any(s[3] >= 0.001 for s in pre) or st_weth < 0.1: skip "dust"` (pool WETH from `state(pool)[3]`). Log it as its own status so the paper book and the bot can be compared.
2. **No fallback on the feed.** `fm_sim.rpc(fast=True)` already tries the paid RPC (/opt/fm/rpc_fast) and then the public one, but the main loop calls `res("eth_blockNumber", [], False)` and `res("eth_getLogs", ..., False)`, so the feed that fires stops and pulls is public only. 429 errors at 15:21, 15:23 and 15:34 Bangkok each paused it 5 s or more. Fix: call the feed with `fast=True` (paid first, public as backup). If the paid key has a call budget, use it only when the public call fails.
3. **First WETH pool created vs first that trades: harmless, leave it.** In the 201 backtest trades, 6 tokens had 2+ WETH pools and the traded pool was the first created in all 6 (0 trades affected). In A1's 7,166 v3 WETH pools, 38 tokens (0.5%) have a second pool. Not worth code before live.

## Small notes (not blocking)
- The self test passes as "skipped" if the db has no traded pool yet (a fresh db). Fine now, since the constant is right; keep the db when redeploying.
- 0x44b29b737ba49fd3ec95de5d4684998fdd6e4a7c (cap $305k, in band) was skipped at 15:46 as sell_sim_fail, but PP's test at 15:56 shows a clean 0.9998 round trip on it. Worth one look at the `note` column: if the sim failed for a transient reason (RPC error, not a revert), the bot skipped a real trade.

Version 1, 6 Oct 2026 16:02 Bangkok. Latest: http://159.223.88.168/hx-c9ois/fw/a2-fmmc5-reaudit.md
