Skip to content

Commit c3bb19d

Browse files
committed
Drop forall quantifiers from RealizableBadDebtLiquidate repaid branch; keep concrete instances (NIA blowup fix per #1083)
1 parent 925bef9 commit c3bb19d

1 file changed

Lines changed: 11 additions & 12 deletions

File tree

certora/specs/RealizableBadDebtLiquidate.spec

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -214,18 +214,17 @@ rule liquidateRealizesBadDebtRepaidInput(env e, Midnight.Market market, uint256
214214
mathint maxLif = maxLifGhost(market.collateralParams[collateralIndex].lltv, market.collateralParams[collateralIndex].liquidationCursor);
215215
require maxLif >= to_mathint(WAD()), "maxLif at least 1x (market-creation invariant)";
216216

217-
// The near-linear consequences of the MulDiv lemmas are assumed over the loose ghost: the double
218-
// sub-additivity bounds the getter-sum drop g(c_k) - g(c_k - seizedAssets) by g(seizedAssets), and
219-
// the seize-value bound closes g(seizedAssets) <= repaidUnits, so the getter-sum drops by at most
220-
// the repaid debt drop. The nonlinear reasoning is proven once, over concrete mulDiv, in MulDiv.spec
221-
// (mulDivUpDoubleSubAdditive, mulDivSeizeValueBounded, mulDivMonotoneA, mulDivZero).
222-
require forall mathint a1. forall mathint a2. forall mathint b. forall mathint d. axiomUpMonotoneA(a1, a2, b, d), "monotone in first arg (mulDivMonotoneA)";
223-
require forall mathint b. forall mathint d. axiomUpZero(b, d), "zero collateral values to zero (mulDivZero)";
224-
require forall mathint a. forall mathint s. forall mathint p. forall mathint L. axiomUpDoubleSubAdditive(a, s, p, L), "getter-form double sub-additivity (mulDivUpDoubleSubAdditive)";
225-
require forall mathint r. forall mathint l. forall mathint p. forall mathint sc. forall mathint w. axiomSeizeValue(r, l, p, sc, w), "seize-value bound (mulDivSeizeValueBounded)";
226-
227-
// Ground instances of the derived-seize chain (seizedAssets = src/Midnight.sol:692) so the axioms
228-
// above close without quantifier search on the loop-internal seized term.
217+
// The near-linear consequences of the MulDiv lemmas are assumed over the loose ghost, but only as
218+
// concrete (non-quantified) ground-term instances -- no `forall` axioms. The general quantified
219+
// forms over unbounded mathint were the NIA blowup that timed the rule out; instantiating them once,
220+
// by hand, on the exact terms the loop produces keeps the reasoning near-linear (see #1083). The
221+
// double sub-additivity instance bounds the getter-sum drop g(c_k) - g(c_k - seizedAssets) by
222+
// g(seizedAssets), and the seize-value instance closes g(seizedAssets) <= repaidUnits, so the
223+
// getter-sum drops by at most the repaid debt drop. The nonlinear reasoning is proven once, over
224+
// concrete mulDiv, in MulDiv.spec (mulDivUpDoubleSubAdditive, mulDivSeizeValueBounded).
225+
226+
// Ground instances of the derived-seize chain (seizedAssets = src/Midnight.sol:692) so the facts
227+
// close without quantifier search on the loop-internal seized term.
229228
mathint price = summaryPrice(market.collateralParams[collateralIndex].oracle);
230229
mathint seizedDerived = ghostMulDivDown(ghostMulDivDown(repaidUnits, maxLif, WAD()), ORACLE_PRICE_SCALE(), price);
231230
mathint gSeized = ghostMulDivUp(ghostMulDivUp(seizedDerived, price, ORACLE_PRICE_SCALE()), WAD(), maxLif);

0 commit comments

Comments
 (0)