Session — stage 3, graduation — closed 15 Sep 2026
Graduation must actually happen inline for a normal wallet. Every stage 3 line was ✔ bar the permissioned pool; checking the first one against a real gas estimate found it does not hold.
What we found — 15 Sep 2026
- A crossing buy sent at its gas estimate defers graduation. Local anvil,
make dev-deploy:cast estimateof a crossing buy = 192,308; sent at that limit it succeeded,lockedtrue,graduatedfalse.graduate()alone estimates 452,747; the floor is 500,000. - Why: below the floor the curve locks and returns success, and estimation looks for the least gas
that succeeds. RHUB hid it with an interface that doubled the gas (
TradePanel.tsx). Doubling would not reach the floor here. - The permissioned-pool line was never needed for anything we pair against.
Decided (D23)
- A crossing buy short of the floor reverts. Deferral stays for a migrator that really fails.
- Proved by a fuzz over gas limits: never success + crossed + not graduated.
- Permissioned-pool graduation: out of v1, into Future updates.
Build plan
- Done. Curve: a failed graduation is believed only with ≥ 2M gas; below, the buy reverts.
Gas sweeps (real
PoolManager, a dearer mock migrator, the live singleton) all revert-or-graduate; both sweeps failed on the old code at 250k. - Done. On anvil the same crossing buy now estimates 566,419 and, sent at exactly that,
graduates (was 192,308 and deferred).
make dev-smokesends the crossing buy at the node's estimate from now on; its hard-coded 4M limit was what hid the bug. - Nothing to build. The fix lives in the curve, so every caller inherits it. A gas sweep through the router still passed with the router capping the curve's gas to 700k — it caught nothing the curve's own sweep does not, so it was deleted.
Tried and rejected
- Revert under a 500k floor before the
try. Holds for today's migrator, but one costing more than the floor passes the check, runs out inside thetry, and is deferred again. - Telling out-of-gas apart in the
catchby gas left (< 1/63). A migrator that runs out two calls deep hands gas back as each frame unwinds; failed at 760k. Nothing in acatchcan tell. - So the floor moved into the
catchand rose to 2M, above any graduation: a crossing buy that graduates needs 660k locally and 670k on the live singleton. A hooked migrator must be added toGraduationGas.t.solbefore it ships.
Not this session
Pool fees (O17), hooks, the interface, anti-snipe, security, dividends (O18).
Next
Closed. STATUS.md updated; the next thread is the developer's call.