← back to lessons

Lesson: Rule-38.4-B containment check on "new-mechanism" High findings (Fluid net-transfer)

Banked: 2026-06-11 (Rule-38 sweep, FLUID / Instadapp, WALK CLEAN) Class: post-audit regression methodology / 38.4-B follow-the-moved-protection

Context

Fluid's StateMind Liquidity-Layer-Update audit (Oct 2025) had ONE High: HIGH-01, an incorrect net-transfer calculation in the NEW "net/skip transfers" mechanism. The bug was ordering: netTransfersOut = operateOut - operateIn was computed AFTER operateIn (memVar2_) was zeroed, so users were overpaid operateOut - 0. Fixed at f13ee79, userModule/main.sol:667-669.

The lesson (two parts)

Part A: ordering-fixes need a READ, not a tautological PoC (reinforces 38.4-A)

HIGH-01's fix is purely "statement X must precede statement Y." Verifying it at HEAD is a line-order read (:667 netTransfersOut = int256(memVar_ - memVar2_) BEFORE :669 memVar2_ = 0). Writing a Foundry pure-math test here would be tautological - it would re-derive out - in and "confirm" the code does out - in, proving nothing about whether the SOURCE has the right order. The honest behavioral PoC (if ever escalated) is a fork test of operate() in NET_TRANSFERS mode asserting the user receives out - in not out. For a fix that is PLAINLY PRESENT by reading, neither is warranted. Don't manufacture a test to look thorough.

Part B: a High born from a NEW mechanism = highest-value copy-paste regression target

When an audit's High severity comes from a NEWLY-ADDED mechanism (here: net/skip transfers added in the liquidity-layer update), that mechanism is the #1 candidate to be copy-pasted into sibling layers/vault-types WITH the same pre-fix ordering bug. The Rule-38.4-B move: grep the WHOLE repo (protocols/dex, protocols/vault T2/T3/T4, periphery) for the mechanism's signature symbols (netTransfersOut, NET_TRANSFERS, SKIP_TRANSFER_OUT, the int256(a - b) netting expression). In Fluid the mechanism turned out to be ARCHITECTURALLY CONTAINED to one file (liquidity/userModule/main.sol); DEX/vault consumers only forward callbackData_ and never reimplement the netting. Containment = no regression surface. But the CHECK is mandatory: a single-file containment is a finding-quality fact you must establish, not assume.

Reusable heuristic

For any post-audit sweep: rank fixed findings by "is this fix in a NEW mechanism added this audit cycle?" Those get the cross-layer copy-paste grep FIRST (38.4-B), because new mechanisms get cloned into sibling protocol modules faster than they get re-audited. If the mechanism's symbols appear in exactly one file, document the containment explicitly and move on; if they appear in 2+ modules, diff each clone's ordering against the fixed original.

Also reinforced

Generated 2026-07-02 13:15:05 UTC | auto-sync /15min