Slither triage
Why every Slither finding in contracts/src is left as it is. Read before silencing a new one, and add
it here when you do. CI runs Slither with fail-on: medium; make lint does the same.
Triaged 15 Sep 2026, Slither 0.11.4: 44 findings, no High. The 14 Mediums are disabled at their lines.
| Finding | Where | Verdict |
|---|---|---|
| incorrect-equality | BondingCurve.graduate, FeeVault.distribute | Intended: exact zero checks, one of them the "migrator took everything" assertion |
| reentrancy-no-eth | PoolMigrator.collectFees | False positive: collectFees and both flushes share one nonReentrant; the only callee is our vault |
| uninitialized-local | LaunchFactory.launch none | Intended: the zero CreatorFees is "no creator fee" |
| unused-return ×10 | settle, initialize, getSlot0, modifyLiquidity, unlock, sync, launchOf | Intended: each return is either already known or deliberately not needed |
| missing-zero-check ×3 (Low) | payout asset, token observer, sellForEth.to | Zero is meaningful for the first two; the third is checked in _checkTrade |
| calls-loop ×5 (Low) | BasketWrapper.preview* | Bounded at ten assets; a paused constituent reverting a preview is correct |
| reentrancy-benign/events ×10 (Low) | curve, factory, migrator, vault, token | Same reasoning as the forge-lint exclusion: guarded paths or contracts we deployed in the same call |
timestamp ×2, low-level-calls, naming, unused __gap, OZ event | — | Deadlines, ETH payout, and the upgrade-safety gap convention |